You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Window.java 48KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.ui;
  5. import java.io.Serializable;
  6. import java.lang.reflect.Method;
  7. import java.net.MalformedURLException;
  8. import java.net.URL;
  9. import java.util.Collections;
  10. import java.util.Iterator;
  11. import java.util.LinkedHashSet;
  12. import java.util.LinkedList;
  13. import java.util.Map;
  14. import java.util.Set;
  15. import com.vaadin.Application;
  16. import com.vaadin.terminal.DownloadStream;
  17. import com.vaadin.terminal.PaintException;
  18. import com.vaadin.terminal.PaintTarget;
  19. import com.vaadin.terminal.ParameterHandler;
  20. import com.vaadin.terminal.Resource;
  21. import com.vaadin.terminal.Sizeable;
  22. import com.vaadin.terminal.Terminal;
  23. import com.vaadin.terminal.URIHandler;
  24. import com.vaadin.terminal.gwt.client.ui.VView;
  25. /**
  26. * Application window component.
  27. *
  28. * @author IT Mill Ltd.
  29. * @version
  30. * @VERSION@
  31. * @since 3.0
  32. */
  33. @SuppressWarnings("serial")
  34. @ClientWidget(VView.class)
  35. public class Window extends Panel implements URIHandler, ParameterHandler {
  36. /**
  37. * Window with no border.
  38. */
  39. public static final int BORDER_NONE = 0;
  40. /**
  41. * Window with only minimal border.
  42. */
  43. public static final int BORDER_MINIMAL = 1;
  44. /**
  45. * Window with default borders.
  46. */
  47. public static final int BORDER_DEFAULT = 2;
  48. /**
  49. * The terminal this window is attached to.
  50. */
  51. private Terminal terminal = null;
  52. /**
  53. * The application this window is attached to.
  54. */
  55. private Application application = null;
  56. /**
  57. * List of URI handlers for this window.
  58. */
  59. private LinkedList<URIHandler> uriHandlerList = null;
  60. /**
  61. * List of parameter handlers for this window.
  62. */
  63. private LinkedList<ParameterHandler> parameterHandlerList = null;
  64. /** Set of subwindows */
  65. private final LinkedHashSet<Window> subwindows = new LinkedHashSet<Window>();
  66. /**
  67. * Explicitly specified theme of this window. If null, application theme is
  68. * used.
  69. */
  70. private String theme = null;
  71. /**
  72. * Resources to be opened automatically on next repaint.
  73. */
  74. private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
  75. /**
  76. * The name of the window.
  77. */
  78. private String name = null;
  79. /**
  80. * Window border mode.
  81. */
  82. private int border = BORDER_DEFAULT;
  83. /**
  84. * Distance of Window top border in pixels from top border of the containing
  85. * (main window) or -1 if unspecified.
  86. */
  87. private int positionY = -1;
  88. /**
  89. * Distance of Window left border in pixels from left border of the
  90. * containing (main window) or -1 if unspecified .
  91. */
  92. private int positionX = -1;
  93. private LinkedList<Notification> notifications;
  94. private boolean modal = false;
  95. private boolean resizable = true;
  96. private boolean centerRequested = false;
  97. private Focusable pendingFocus;
  98. /* ********************************************************************* */
  99. /**
  100. * Creates a new empty unnamed window with default layout.
  101. *
  102. * <p>
  103. * To show the window in application, it must be added to application with
  104. * <code>Application.addWindow</code> method.
  105. * </p>
  106. *
  107. * <p>
  108. * The windows are scrollable by default.
  109. * </p>
  110. *
  111. * @param caption
  112. * the Title of the window.
  113. */
  114. public Window() {
  115. this("", null);
  116. }
  117. /**
  118. * Creates a new empty window with default layout.
  119. *
  120. * <p>
  121. * To show the window in application, it must be added to application with
  122. * <code>Application.addWindow</code> method.
  123. * </p>
  124. *
  125. * <p>
  126. * The windows are scrollable by default.
  127. * </p>
  128. *
  129. * @param caption
  130. * the Title of the window.
  131. */
  132. public Window(String caption) {
  133. this(caption, null);
  134. }
  135. /**
  136. * Creates a new window.
  137. *
  138. * <p>
  139. * To show the window in application, it must be added to application with
  140. * <code>Application.addWindow</code> method.
  141. * </p>
  142. *
  143. * <p>
  144. * The windows are scrollable by default.
  145. * </p>
  146. *
  147. * @param caption
  148. * the Title of the window.
  149. * @param layout
  150. * the Layout of the window.
  151. */
  152. public Window(String caption, ComponentContainer content) {
  153. super(caption, content);
  154. setScrollable(true);
  155. setSizeUndefined();
  156. }
  157. /**
  158. * Gets the terminal type.
  159. *
  160. * @return the Value of property terminal.
  161. */
  162. public Terminal getTerminal() {
  163. return terminal;
  164. }
  165. /* ********************************************************************* */
  166. /**
  167. * Gets the window of the component. Returns the window where this component
  168. * belongs to. If the component does not yet belong to a window the returns
  169. * null.
  170. *
  171. * @return the parent window of the component.
  172. */
  173. @Override
  174. public final Window getWindow() {
  175. return this;
  176. }
  177. /**
  178. * Gets the application instance of the component. Returns the application
  179. * where this component belongs to. If the component does not yet belong to
  180. * a application the returns null.
  181. *
  182. * @return the parent application of the component.
  183. */
  184. @Override
  185. public final Application getApplication() {
  186. if (getParent() == null) {
  187. return application;
  188. }
  189. return ((Window) getParent()).getApplication();
  190. }
  191. /**
  192. * Getter for property parent.
  193. *
  194. * <p>
  195. * Parent is the visual parent of a component. Each component can belong to
  196. * only one ComponentContainer at time.
  197. * </p>
  198. *
  199. * <p>
  200. * For windows attached directly to the application, parent is
  201. * <code>null</code>. For windows inside other windows, parent is the window
  202. * containing this window.
  203. * </p>
  204. *
  205. * @return the Value of property parent.
  206. */
  207. @Override
  208. public final Component getParent() {
  209. return super.getParent();
  210. }
  211. /**
  212. * Setter for property parent.
  213. *
  214. * <p>
  215. * Parent is the visual parent of a component. This is mostly called by
  216. * containers add method and should not be called directly
  217. * </p>
  218. *
  219. * @param parent
  220. * the New value of property parent.
  221. */
  222. @Override
  223. public void setParent(Component parent) {
  224. super.setParent(parent);
  225. }
  226. /**
  227. * Gets the component UIDL tag.
  228. *
  229. * @return the Component UIDL tag as string.
  230. */
  231. @Override
  232. public String getTag() {
  233. return "window";
  234. }
  235. /* ********************************************************************* */
  236. /**
  237. * Adds the new URI handler to this window. For sub-windows, URI handlers
  238. * are attached to root level window.
  239. *
  240. * @param handler
  241. * the URI handler to add.
  242. */
  243. public void addURIHandler(URIHandler handler) {
  244. if (getParent() != null) {
  245. // this is subwindow, attach to main level instead
  246. // TODO hold internal list also and remove on detach
  247. Window mainWindow = (Window) getParent();
  248. mainWindow.addURIHandler(handler);
  249. } else {
  250. if (uriHandlerList == null) {
  251. uriHandlerList = new LinkedList<URIHandler>();
  252. }
  253. synchronized (uriHandlerList) {
  254. if (!uriHandlerList.contains(handler)) {
  255. uriHandlerList.addLast(handler);
  256. }
  257. }
  258. }
  259. }
  260. /**
  261. * Removes the given URI handler from this window.
  262. *
  263. * @param handler
  264. * the URI handler to remove.
  265. */
  266. public void removeURIHandler(URIHandler handler) {
  267. if (getParent() != null) {
  268. // this is subwindow
  269. Window mainWindow = (Window) getParent();
  270. mainWindow.removeURIHandler(handler);
  271. } else {
  272. if (handler == null || uriHandlerList == null) {
  273. return;
  274. }
  275. synchronized (uriHandlerList) {
  276. uriHandlerList.remove(handler);
  277. if (uriHandlerList.isEmpty()) {
  278. uriHandlerList = null;
  279. }
  280. }
  281. }
  282. }
  283. /**
  284. * Handles uri recursively. Windows uri handler passes uri to all
  285. * {@link URIHandler}s added to it.
  286. * <p>
  287. * Note, that instead of overriding this method developer should consider
  288. * using {@link Window#addURIHandler(URIHandler)} to add uri handler to
  289. * Window.
  290. *
  291. * @param context
  292. * @param relativeUri
  293. */
  294. public DownloadStream handleURI(URL context, String relativeUri) {
  295. DownloadStream result = null;
  296. if (uriHandlerList != null) {
  297. Object[] handlers;
  298. synchronized (uriHandlerList) {
  299. handlers = uriHandlerList.toArray();
  300. }
  301. for (int i = 0; i < handlers.length; i++) {
  302. final DownloadStream ds = ((URIHandler) handlers[i]).handleURI(
  303. context, relativeUri);
  304. if (ds != null) {
  305. if (result != null) {
  306. throw new RuntimeException("handleURI for " + context
  307. + " uri: '" + relativeUri
  308. + "' returns ambigious result.");
  309. }
  310. result = ds;
  311. }
  312. }
  313. }
  314. return result;
  315. }
  316. /* ********************************************************************* */
  317. /**
  318. * Adds the new parameter handler to this window. For sub windows, parameter
  319. * handlers are attached to parent windows.
  320. *
  321. * @param handler
  322. * the parameter handler to add.
  323. */
  324. public void addParameterHandler(ParameterHandler handler) {
  325. if (getParent() != null) {
  326. // this is subwindow
  327. // TODO hold internal list also and remove on detach
  328. Window mainWindow = (Window) getParent();
  329. mainWindow.addParameterHandler(handler);
  330. } else {
  331. if (parameterHandlerList == null) {
  332. parameterHandlerList = new LinkedList<ParameterHandler>();
  333. }
  334. synchronized (parameterHandlerList) {
  335. if (!parameterHandlerList.contains(handler)) {
  336. parameterHandlerList.addLast(handler);
  337. }
  338. }
  339. }
  340. }
  341. /**
  342. * Removes the given URI handler from this window.
  343. *
  344. * @param handler
  345. * the parameter handler to remove.
  346. */
  347. public void removeParameterHandler(ParameterHandler handler) {
  348. if (getParent() != null) {
  349. // this is subwindow
  350. Window mainWindow = (Window) getParent();
  351. mainWindow.addParameterHandler(handler);
  352. } else {
  353. if (handler == null || parameterHandlerList == null) {
  354. return;
  355. }
  356. synchronized (parameterHandlerList) {
  357. parameterHandlerList.remove(handler);
  358. if (parameterHandlerList.isEmpty()) {
  359. parameterHandlerList = null;
  360. }
  361. }
  362. }
  363. }
  364. /* Documented by the interface */
  365. public void handleParameters(Map parameters) {
  366. if (parameterHandlerList != null) {
  367. Object[] handlers;
  368. synchronized (parameterHandlerList) {
  369. handlers = parameterHandlerList.toArray();
  370. }
  371. for (int i = 0; i < handlers.length; i++) {
  372. ((ParameterHandler) handlers[i]).handleParameters(parameters);
  373. }
  374. }
  375. }
  376. /* ********************************************************************* */
  377. /**
  378. * Gets the theme for this window.
  379. *
  380. * <p>
  381. * Subwindows do not support themes and thus return theme used by the parent
  382. * </p>
  383. *
  384. * @return the Name of the theme used in window. If the theme for this
  385. * individual window is not explicitly set, the application theme is
  386. * used instead. If application is not assigned the
  387. * terminal.getDefaultTheme is used. If terminal is not set, null is
  388. * returned
  389. */
  390. public String getTheme() {
  391. if (getParent() != null) {
  392. return ((Window) getParent()).getTheme();
  393. }
  394. if (theme != null) {
  395. return theme;
  396. }
  397. if ((application != null) && (application.getTheme() != null)) {
  398. return application.getTheme();
  399. }
  400. if (terminal != null) {
  401. return terminal.getDefaultTheme();
  402. }
  403. return null;
  404. }
  405. /**
  406. * Sets the theme for this window.
  407. *
  408. * Setting theme for subwindows is not supported.
  409. *
  410. * In Toolkit 5 terminal will reload its host page on theme changes.
  411. *
  412. * @param theme
  413. * the New theme for this window. Null implies the default theme.
  414. */
  415. public void setTheme(String theme) {
  416. if (getParent() != null) {
  417. throw new UnsupportedOperationException(
  418. "Setting theme for sub-windows is not supported.");
  419. }
  420. this.theme = theme;
  421. requestRepaint();
  422. }
  423. /**
  424. * Paints the content of this component.
  425. *
  426. * @param event
  427. * the Paint Event.
  428. * @throws PaintException
  429. * if the paint operation failed.
  430. */
  431. @Override
  432. public synchronized void paintContent(PaintTarget target)
  433. throws PaintException {
  434. // Sets the window name
  435. final String name = getName();
  436. target.addAttribute("name", name == null ? "" : name);
  437. // Sets the window theme
  438. final String theme = getTheme();
  439. target.addAttribute("theme", theme == null ? "" : theme);
  440. if (modal) {
  441. target.addAttribute("modal", true);
  442. }
  443. if (resizable) {
  444. target.addAttribute("resizable", true);
  445. }
  446. if (centerRequested) {
  447. target.addAttribute("center", true);
  448. centerRequested = false;
  449. }
  450. // Marks the main window
  451. if (getApplication() != null
  452. && this == getApplication().getMainWindow()) {
  453. target.addAttribute("main", true);
  454. }
  455. if (getContent() != null) {
  456. if (getContent().getHeightUnits() == Sizeable.UNITS_PERCENTAGE) {
  457. target.addAttribute("layoutRelativeHeight", true);
  458. }
  459. if (getContent().getWidthUnits() == Sizeable.UNITS_PERCENTAGE) {
  460. target.addAttribute("layoutRelativeWidth", true);
  461. }
  462. }
  463. // Open requested resource
  464. synchronized (openList) {
  465. if (!openList.isEmpty()) {
  466. for (final Iterator<OpenResource> i = openList.iterator(); i
  467. .hasNext();) {
  468. (i.next()).paintContent(target);
  469. }
  470. openList.clear();
  471. }
  472. }
  473. // Contents of the window panel is painted
  474. super.paintContent(target);
  475. // Window position
  476. target.addVariable(this, "positionx", getPositionX());
  477. target.addVariable(this, "positiony", getPositionY());
  478. // Window closing
  479. target.addVariable(this, "close", false);
  480. if (getParent() == null) {
  481. // Paint subwindows
  482. for (final Iterator<Window> i = subwindows.iterator(); i.hasNext();) {
  483. final Window w = i.next();
  484. w.paint(target);
  485. }
  486. } else {
  487. // mark subwindows
  488. target.addAttribute("sub", true);
  489. }
  490. // Paint notifications
  491. if (notifications != null) {
  492. target.startTag("notifications");
  493. for (final Iterator<Notification> it = notifications.iterator(); it
  494. .hasNext();) {
  495. final Notification n = it.next();
  496. target.startTag("notification");
  497. if (n.getCaption() != null) {
  498. target.addAttribute("caption", n.getCaption());
  499. }
  500. if (n.getMessage() != null) {
  501. target.addAttribute("message", n.getMessage());
  502. }
  503. if (n.getIcon() != null) {
  504. target.addAttribute("icon", n.getIcon());
  505. }
  506. target.addAttribute("position", n.getPosition());
  507. target.addAttribute("delay", n.getDelayMsec());
  508. if (n.getStyleName() != null) {
  509. target.addAttribute("style", n.getStyleName());
  510. }
  511. target.endTag("notification");
  512. }
  513. target.endTag("notifications");
  514. notifications = null;
  515. }
  516. if (pendingFocus != null) {
  517. // ensure focused component is still attached to this main window
  518. if (pendingFocus.getWindow() == this
  519. || (pendingFocus.getWindow() != null && pendingFocus
  520. .getWindow().getParent() == this)) {
  521. target.paintReference(pendingFocus, "focused");
  522. }
  523. pendingFocus = null;
  524. }
  525. }
  526. /* ********************************************************************* */
  527. /**
  528. * Opens the given resource in this window.
  529. *
  530. * @param resource
  531. */
  532. public void open(Resource resource) {
  533. synchronized (openList) {
  534. if (!openList.contains(resource)) {
  535. openList.add(new OpenResource(resource, null, -1, -1,
  536. BORDER_DEFAULT));
  537. }
  538. }
  539. requestRepaint();
  540. }
  541. /* ********************************************************************* */
  542. /**
  543. * Opens the given resource in named terminal window. Empty or
  544. * <code>null</code> window name results the resource to be opened in this
  545. * window.
  546. *
  547. * @param resource
  548. * the resource.
  549. * @param windowName
  550. * the name of the window.
  551. */
  552. public void open(Resource resource, String windowName) {
  553. synchronized (openList) {
  554. if (!openList.contains(resource)) {
  555. openList.add(new OpenResource(resource, windowName, -1, -1,
  556. BORDER_DEFAULT));
  557. }
  558. }
  559. requestRepaint();
  560. }
  561. /* ********************************************************************* */
  562. /**
  563. * Opens the given resource in named terminal window with given size and
  564. * border properties. Empty or <code>null</code> window name results the
  565. * resource to be opened in this window.
  566. *
  567. * @param resource
  568. * @param windowName
  569. * @param width
  570. * @param height
  571. * @param border
  572. */
  573. public void open(Resource resource, String windowName, int width,
  574. int height, int border) {
  575. synchronized (openList) {
  576. if (!openList.contains(resource)) {
  577. openList.add(new OpenResource(resource, windowName, width,
  578. height, border));
  579. }
  580. }
  581. requestRepaint();
  582. }
  583. /* ********************************************************************* */
  584. /**
  585. * Returns the full url of the window, this returns window specific url even
  586. * for the main window.
  587. *
  588. * @return the URL of the window.
  589. */
  590. public URL getURL() {
  591. if (application == null) {
  592. return null;
  593. }
  594. try {
  595. return new URL(application.getURL(), getName() + "/");
  596. } catch (final MalformedURLException e) {
  597. throw new RuntimeException(
  598. "Internal problem getting window URL, please report");
  599. }
  600. }
  601. /**
  602. * Gets the unique name of the window that indentifies it on the terminal.
  603. *
  604. * <p>
  605. * Name identifies the URL used to access application-level windows, but is
  606. * not used for windows inside other windows. all application-level windows
  607. * can be accessed by their names in url
  608. * <code>http://host:port/foo/bar/</code> where
  609. * <code>http://host:port/foo/</code> is the application url as returned by
  610. * getURL() and <code>bar</code> is the name of the window. Also note that
  611. * not all windows should be added to application - one can also add windows
  612. * inside other windows - these windows show as smaller windows inside those
  613. * windows.
  614. * </p>
  615. *
  616. * @return the Name of the Window.
  617. */
  618. public String getName() {
  619. return name;
  620. }
  621. /**
  622. * Returns the border.
  623. *
  624. * @return the border.
  625. */
  626. public int getBorder() {
  627. return border;
  628. }
  629. /**
  630. * Sets the border.
  631. *
  632. * @param border
  633. * the border to set.
  634. */
  635. public void setBorder(int border) {
  636. this.border = border;
  637. }
  638. /**
  639. * Sets the application this window is connected to.
  640. *
  641. * <p>
  642. * This method should not be invoked directly. Instead the
  643. * {@link com.vaadin.Application#addWindow(Window)} method should be used to
  644. * add the window to an application and
  645. * {@link com.vaadin.Application#removeWindow(Window)} method for removing
  646. * the window from the applicion. These methods call this method implicitly.
  647. * </p>
  648. *
  649. * <p>
  650. * The method invokes {@link Component#attach()} and
  651. * {@link Component#detach()} methods when necessary.
  652. * <p>
  653. *
  654. * @param application
  655. * the application to set.
  656. */
  657. public void setApplication(Application application) {
  658. // If the application is not changed, dont do nothing
  659. if (application == this.application) {
  660. return;
  661. }
  662. // Sends detach event if the window is connected to application
  663. if (this.application != null) {
  664. detach();
  665. }
  666. // Connects to new parent
  667. this.application = application;
  668. // Sends the attach event if connected to a window
  669. if (application != null) {
  670. attach();
  671. }
  672. }
  673. /**
  674. * Sets the name.
  675. * <p>
  676. * The name of the window must be unique inside the application.
  677. * </p>
  678. *
  679. * <p>
  680. * If the name is null, the the window is given name automatically when it
  681. * is added to an application.
  682. * </p>
  683. *
  684. * @param name
  685. * the name to set.
  686. */
  687. public void setName(String name) {
  688. // The name can not be changed in application
  689. if (getApplication() != null) {
  690. throw new IllegalStateException(
  691. "Window name can not be changed while "
  692. + "the window is in application");
  693. }
  694. this.name = name;
  695. }
  696. /**
  697. * Sets the terminal type. The terminal type is set by the the terminal
  698. * adapter and may change from time to time.
  699. *
  700. * @param type
  701. * the terminal type to set.
  702. */
  703. public void setTerminal(Terminal type) {
  704. terminal = type;
  705. }
  706. /**
  707. * Private data structure for storing opening window properties.
  708. */
  709. private class OpenResource implements Serializable {
  710. private final Resource resource;
  711. private final String name;
  712. private final int width;
  713. private final int height;
  714. private final int border;
  715. /**
  716. * Creates a new open resource.
  717. *
  718. * @param resource
  719. * @param name
  720. * @param width
  721. * @param height
  722. * @param border
  723. */
  724. private OpenResource(Resource resource, String name, int width,
  725. int height, int border) {
  726. this.resource = resource;
  727. this.name = name;
  728. this.width = width;
  729. this.height = height;
  730. this.border = border;
  731. }
  732. /**
  733. * Paints the open-tag inside the window.
  734. *
  735. * @param target
  736. * the Paint Event.
  737. * @throws PaintException
  738. * if the Paint Operation fails.
  739. */
  740. private void paintContent(PaintTarget target) throws PaintException {
  741. target.startTag("open");
  742. target.addAttribute("src", resource);
  743. if (name != null && name.length() > 0) {
  744. target.addAttribute("name", name);
  745. }
  746. if (width >= 0) {
  747. target.addAttribute("width", width);
  748. }
  749. if (height >= 0) {
  750. target.addAttribute("height", height);
  751. }
  752. switch (border) {
  753. case Window.BORDER_MINIMAL:
  754. target.addAttribute("border", "minimal");
  755. break;
  756. case Window.BORDER_NONE:
  757. target.addAttribute("border", "none");
  758. break;
  759. }
  760. target.endTag("open");
  761. }
  762. }
  763. /**
  764. * Called when one or more variables handled by the implementing class are
  765. * changed.
  766. *
  767. * @see com.vaadin.terminal.VariableOwner#changeVariables(java.lang.Object,
  768. * java.util.Map)
  769. */
  770. @Override
  771. public void changeVariables(Object source, Map variables) {
  772. boolean sizeHasChanged = false;
  773. // size is handled in super class, but resize events only in windows ->
  774. // so detect if size change occurs before super.changeVariables()
  775. if (variables.containsKey("height")
  776. && (getHeightUnits() != UNITS_PIXELS || (Integer) variables
  777. .get("height") != getHeight())) {
  778. sizeHasChanged = true;
  779. }
  780. if (variables.containsKey("width")
  781. && (getWidthUnits() != UNITS_PIXELS || (Integer) variables
  782. .get("width") != getWidth())) {
  783. sizeHasChanged = true;
  784. }
  785. super.changeVariables(source, variables);
  786. // Positioning
  787. final Integer positionx = (Integer) variables.get("positionx");
  788. if (positionx != null) {
  789. final int x = positionx.intValue();
  790. setPositionX(x < 0 ? -1 : x);
  791. }
  792. final Integer positiony = (Integer) variables.get("positiony");
  793. if (positiony != null) {
  794. final int y = positiony.intValue();
  795. setPositionY(y < 0 ? -1 : y);
  796. }
  797. if (!isReadOnly()) {
  798. // Closing
  799. final Boolean close = (Boolean) variables.get("close");
  800. if (close != null && close.booleanValue()) {
  801. close();
  802. }
  803. }
  804. // fire event if size has really changed
  805. if (sizeHasChanged) {
  806. fireResize();
  807. }
  808. }
  809. /**
  810. * Method that handles window closing (from UI).
  811. *
  812. * <p>
  813. * By default, sub-windows are removed from their respective parent windows
  814. * and thus visually closed on browser-side. Browser-level windows also
  815. * closed on the client-side, but they are not implicitly removed from the
  816. * application.
  817. * </p>
  818. *
  819. * <p>
  820. * If one wants change the default behavior, register a window close
  821. * listenter and do something else. For example, you could re-open the
  822. * browser-level window with mainWindow.open(), re-add the removed
  823. * sub-window back to its parent or remove browser-level window
  824. * automatically from the application.
  825. * </p>
  826. */
  827. protected void close() {
  828. Window parent = (Window) getParent();
  829. if (parent == null) {
  830. fireClose();
  831. } else {
  832. // subwindow is removed from parent
  833. parent.removeWindow(this);
  834. fireClose();
  835. }
  836. }
  837. /**
  838. * Gets the distance of Window left border in pixels from left border of the
  839. * containing (main window).
  840. *
  841. * @return the Distance of Window left border in pixels from left border of
  842. * the containing (main window). or -1 if unspecified.
  843. * @since 4.0.0
  844. */
  845. public int getPositionX() {
  846. return positionX;
  847. }
  848. /**
  849. * Sets the distance of Window left border in pixels from left border of the
  850. * containing (main window).
  851. *
  852. * @param positionX
  853. * the Distance of Window left border in pixels from left border
  854. * of the containing (main window). or -1 if unspecified.
  855. * @since 4.0.0
  856. */
  857. public void setPositionX(int positionX) {
  858. this.positionX = positionX;
  859. centerRequested = false;
  860. requestRepaint();
  861. }
  862. /**
  863. * Gets the distance of Window top border in pixels from top border of the
  864. * containing (main window).
  865. *
  866. * @return Distance of Window top border in pixels from top border of the
  867. * containing (main window). or -1 if unspecified .
  868. *
  869. * @since 4.0.0
  870. */
  871. public int getPositionY() {
  872. return positionY;
  873. }
  874. /**
  875. * Sets the distance of Window top border in pixels from top border of the
  876. * containing (main window).
  877. *
  878. * @param positionY
  879. * the Distance of Window top border in pixels from top border of
  880. * the containing (main window). or -1 if unspecified
  881. *
  882. * @since 4.0.0
  883. */
  884. public void setPositionY(int positionY) {
  885. this.positionY = positionY;
  886. centerRequested = false;
  887. requestRepaint();
  888. }
  889. private static final Method WINDOW_CLOSE_METHOD;
  890. static {
  891. try {
  892. WINDOW_CLOSE_METHOD = CloseListener.class.getDeclaredMethod(
  893. "windowClose", new Class[] { CloseEvent.class });
  894. } catch (final java.lang.NoSuchMethodException e) {
  895. // This should never happen
  896. throw new java.lang.RuntimeException(
  897. "Internal error, window close method not found");
  898. }
  899. }
  900. public class CloseEvent extends Component.Event {
  901. /**
  902. *
  903. * @param source
  904. */
  905. public CloseEvent(Component source) {
  906. super(source);
  907. }
  908. /**
  909. * Gets the Window.
  910. *
  911. * @return the window.
  912. */
  913. public Window getWindow() {
  914. return (Window) getSource();
  915. }
  916. }
  917. public interface CloseListener extends Serializable {
  918. public void windowClose(CloseEvent e);
  919. }
  920. /**
  921. * Adds the listener.
  922. *
  923. * @param listener
  924. * the listener to add.
  925. */
  926. public void addListener(CloseListener listener) {
  927. addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD);
  928. }
  929. /**
  930. * Removes the listener.
  931. *
  932. * @param listener
  933. * the listener to remove.
  934. */
  935. public void removeListener(CloseListener listener) {
  936. addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD);
  937. }
  938. protected void fireClose() {
  939. fireEvent(new Window.CloseEvent(this));
  940. }
  941. /**
  942. * Method for the resize event.
  943. */
  944. private static final Method WINDOW_RESIZE_METHOD;
  945. static {
  946. try {
  947. WINDOW_RESIZE_METHOD = ResizeListener.class.getDeclaredMethod(
  948. "windowResized", new Class[] { ResizeEvent.class });
  949. } catch (final java.lang.NoSuchMethodException e) {
  950. // This should never happen
  951. throw new java.lang.RuntimeException(
  952. "Internal error, window resized method not found");
  953. }
  954. }
  955. /**
  956. * Resize events are fired whenever the client-side fires a resize-event
  957. * (e.g. the browser window is resized). The frequency may vary across
  958. * browsers.
  959. */
  960. public class ResizeEvent extends Component.Event {
  961. /**
  962. *
  963. * @param source
  964. */
  965. public ResizeEvent(Component source) {
  966. super(source);
  967. }
  968. /**
  969. * Get the window form which this event originated
  970. *
  971. * @return the window
  972. */
  973. public Window getWindow() {
  974. return (Window) getSource();
  975. }
  976. }
  977. /**
  978. * Listener for window resize events.
  979. *
  980. * @see com.vaadin.ui.Window.ResizeEvent
  981. */
  982. public interface ResizeListener extends Serializable {
  983. public void windowResized(ResizeEvent e);
  984. }
  985. /**
  986. * Add a resize listener.
  987. *
  988. * @param listener
  989. */
  990. public void addListener(ResizeListener listener) {
  991. addListener(ResizeEvent.class, listener, WINDOW_RESIZE_METHOD);
  992. }
  993. /**
  994. * Remove a resize listener.
  995. *
  996. * @param listener
  997. */
  998. public void removeListener(ResizeListener listener) {
  999. removeListener(ResizeEvent.class, this);
  1000. }
  1001. /**
  1002. * Fire the resize event.
  1003. */
  1004. protected void fireResize() {
  1005. fireEvent(new ResizeEvent(this));
  1006. }
  1007. private void attachWindow(Window w) {
  1008. subwindows.add(w);
  1009. w.setParent(this);
  1010. requestRepaint();
  1011. }
  1012. /**
  1013. * Adds a window inside another window.
  1014. *
  1015. * <p>
  1016. * Adding windows inside another window creates "subwindows". These windows
  1017. * should not be added to application directly and are not accessible
  1018. * directly with any url. Addding windows implicitly sets their parents.
  1019. * </p>
  1020. *
  1021. * <p>
  1022. * Only one level of subwindows are supported. Thus you can add windows
  1023. * inside such windows whose parent is <code>null</code>.
  1024. * </p>
  1025. *
  1026. * @param window
  1027. * @throws IllegalArgumentException
  1028. * if a window is added inside non-application level window.
  1029. * @throws NullPointerException
  1030. * if the given <code>Window</code> is <code>null</code>.
  1031. */
  1032. public void addWindow(Window window) throws IllegalArgumentException,
  1033. NullPointerException {
  1034. if (window == null) {
  1035. throw new NullPointerException("Argument must not be null");
  1036. }
  1037. if (window.getApplication() != null) {
  1038. throw new IllegalArgumentException(
  1039. "Window was already added to application"
  1040. + " - it can not be added to another window also.");
  1041. } else if (getParent() != null) {
  1042. throw new IllegalArgumentException(
  1043. "You can only add windows inside application-level windows.");
  1044. } else if (window.subwindows.size() > 0) {
  1045. throw new IllegalArgumentException(
  1046. "Only one level of subwindows are supported.");
  1047. }
  1048. attachWindow(window);
  1049. }
  1050. /**
  1051. * Remove the given subwindow from this window.
  1052. *
  1053. * @param window
  1054. * Window to be removed.
  1055. */
  1056. public void removeWindow(Window window) {
  1057. subwindows.remove(window);
  1058. window.setParent(null);
  1059. requestRepaint();
  1060. }
  1061. /**
  1062. * Get the set of all child windows.
  1063. *
  1064. * @return Set of child windows.
  1065. */
  1066. public Set<Window> getChildWindows() {
  1067. return Collections.unmodifiableSet(subwindows);
  1068. }
  1069. /**
  1070. * Sets sub-window modal, so that widgets behind it cannot be accessed.
  1071. * <b>Note:</b> affects sub-windows only.
  1072. *
  1073. * @param modality
  1074. * true if modality is to be turned on
  1075. */
  1076. public void setModal(boolean modality) {
  1077. modal = modality;
  1078. center();
  1079. requestRepaint();
  1080. }
  1081. /**
  1082. * @return true if this window is modal.
  1083. */
  1084. public boolean isModal() {
  1085. return modal;
  1086. }
  1087. /**
  1088. * Sets sub-window resizable. <b>Note:</b> affects sub-windows only.
  1089. *
  1090. * @param resizable
  1091. * true if resizability is to be turned on
  1092. */
  1093. public void setResizable(boolean resizeability) {
  1094. resizable = resizeability;
  1095. requestRepaint();
  1096. }
  1097. /**
  1098. *
  1099. * @return true if window is resizable by the end-user, otherwise false.
  1100. */
  1101. public boolean isResizable() {
  1102. return resizable;
  1103. }
  1104. /**
  1105. * Request to center this window on the screen. <b>Note:</b> affects
  1106. * sub-windows only.
  1107. */
  1108. public void center() {
  1109. centerRequested = true;
  1110. requestRepaint();
  1111. }
  1112. /**
  1113. * Shows a notification message on the middle of the window. The message
  1114. * automatically disappears ("humanized message").
  1115. *
  1116. * @see #showNotification(com.vaadin.ui.Window.Notification)
  1117. * @see Notification
  1118. *
  1119. * @param caption
  1120. * The message
  1121. */
  1122. public void showNotification(String caption) {
  1123. addNotification(new Notification(caption));
  1124. }
  1125. /**
  1126. * Shows a notification message the window. The position and behavior of the
  1127. * message depends on the type, which is one of the basic types defined in
  1128. * {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE.
  1129. *
  1130. * @see #showNotification(com.vaadin.ui.Window.Notification)
  1131. * @see Notification
  1132. *
  1133. * @param caption
  1134. * The message
  1135. * @param type
  1136. * The message type
  1137. */
  1138. public void showNotification(String caption, int type) {
  1139. addNotification(new Notification(caption, type));
  1140. }
  1141. /**
  1142. * Shows a notification consisting of a bigger caption and a smaller
  1143. * description on the middle of the window. The message automatically
  1144. * disappears ("humanized message").
  1145. *
  1146. * @see #showNotification(com.vaadin.ui.Window.Notification)
  1147. * @see Notification
  1148. *
  1149. * @param caption
  1150. * The caption of the message
  1151. * @param description
  1152. * The message description
  1153. *
  1154. */
  1155. public void showNotification(String caption, String description) {
  1156. addNotification(new Notification(caption, description));
  1157. }
  1158. /**
  1159. * Shows a notification consisting of a bigger caption and a smaller
  1160. * description. The position and behavior of the message depends on the
  1161. * type, which is one of the basic types defined in {@link Notification},
  1162. * for instance Notification.TYPE_WARNING_MESSAGE.
  1163. *
  1164. * @see #showNotification(com.vaadin.ui.Window.Notification)
  1165. * @see Notification
  1166. *
  1167. * @param caption
  1168. * The caption of the message
  1169. * @param description
  1170. * The message description
  1171. * @param type
  1172. * The message type
  1173. */
  1174. public void showNotification(String caption, String description, int type) {
  1175. addNotification(new Notification(caption, description, type));
  1176. }
  1177. /**
  1178. * Shows a notification message.
  1179. *
  1180. * @see Notification
  1181. * @see #showNotification(String)
  1182. * @see #showNotification(String, int)
  1183. * @see #showNotification(String, String)
  1184. * @see #showNotification(String, String, int)
  1185. *
  1186. * @param notification
  1187. * The notification message to show
  1188. */
  1189. public void showNotification(Notification notification) {
  1190. addNotification(notification);
  1191. }
  1192. private void addNotification(Notification notification) {
  1193. if (notifications == null) {
  1194. notifications = new LinkedList<Notification>();
  1195. }
  1196. notifications.add(notification);
  1197. requestRepaint();
  1198. }
  1199. /**
  1200. * This method is used by Component.Focusable objects to request focus to
  1201. * themselves. Focus renders must be handled at window level (instead of
  1202. * Component.Focusable) due we want the last focused component to be focused
  1203. * in client too. Not the one that is rendered last (the case we'd get if
  1204. * implemented in Focusable only).
  1205. *
  1206. * To focus component from Vaadin application, use Focusable.focus(). See
  1207. * {@link Focusable}.
  1208. *
  1209. * @param focusable
  1210. * to be focused on next paint
  1211. */
  1212. void setFocusedComponent(Focusable focusable) {
  1213. if (getParent() != null) {
  1214. // focus is handled by main windows
  1215. ((Window) getParent()).setFocusedComponent(focusable);
  1216. } else {
  1217. pendingFocus = focusable;
  1218. requestRepaint();
  1219. }
  1220. }
  1221. /**
  1222. * A notification message, used to display temporary messages to the user -
  1223. * for example "Document saved", or "Save failed".
  1224. * <p>
  1225. * The notification message can consist of several parts: caption,
  1226. * description and icon. It is usually used with only caption - one should
  1227. * be wary of filling the notification with too much information.
  1228. * </p>
  1229. * <p>
  1230. * The notification message tries to be as unobtrusive as possible, while
  1231. * still drawing needed attention. There are several basic types of messages
  1232. * that can be used in different situations:
  1233. * <ul>
  1234. * <li>TYPE_HUMANIZED_MESSAGE fades away quickly as soon as the user uses
  1235. * the mouse or types something. It can be used to show fairly unimportant
  1236. * messages, such as feedback that an operation succeeded ("Document Saved")
  1237. * - the kind of messages the user ignores once the application is familiar.
  1238. * </li>
  1239. * <li>TYPE_WARNING_MESSAGE is shown for a short while after the user uses
  1240. * the mouse or types something. It's default style is also more noticeable
  1241. * than the humanized message. It can be used for messages that do not
  1242. * contain a lot of important information, but should be noticed by the
  1243. * user. Despite the name, it does not have to be a warning, but can be used
  1244. * instead of the humanized message whenever you want to make the message a
  1245. * little more noticeable.</li>
  1246. * <li>TYPE_ERROR_MESSAGE requires to user to click it before disappearing,
  1247. * and can be used for critical messages.</li>
  1248. * <li>TYPE_TRAY_NOTIFICATION is shown for a while in the lower left corner
  1249. * of the window, and can be used for "convenience notifications" that do
  1250. * not have to be noticed immediately, and should not interfere with the
  1251. * current task - for instance to show "You have a new message in your
  1252. * inbox" while the user is working in some other area of the application.</li>
  1253. * </ul>
  1254. * </p>
  1255. * <p>
  1256. * In addition to the basic pre-configured types, a Notification can also be
  1257. * configured to show up in a custom position, for a specified time (or
  1258. * until clicked), and with a custom stylename. An icon can also be added.
  1259. * </p>
  1260. *
  1261. */
  1262. public static class Notification implements Serializable {
  1263. public static final int TYPE_HUMANIZED_MESSAGE = 1;
  1264. public static final int TYPE_WARNING_MESSAGE = 2;
  1265. public static final int TYPE_ERROR_MESSAGE = 3;
  1266. public static final int TYPE_TRAY_NOTIFICATION = 4;
  1267. public static final int POSITION_CENTERED = 1;
  1268. public static final int POSITION_CENTERED_TOP = 2;
  1269. public static final int POSITION_CENTERED_BOTTOM = 3;
  1270. public static final int POSITION_TOP_LEFT = 4;
  1271. public static final int POSITION_TOP_RIGHT = 5;
  1272. public static final int POSITION_BOTTOM_LEFT = 6;
  1273. public static final int POSITION_BOTTOM_RIGHT = 7;
  1274. public static final int DELAY_FOREVER = -1;
  1275. public static final int DELAY_NONE = 0;
  1276. private String caption;
  1277. private String description;
  1278. private Resource icon;
  1279. private int position = POSITION_CENTERED;
  1280. private int delayMsec = 0;
  1281. private String styleName;
  1282. /**
  1283. * Creates a "humanized" notification message.
  1284. *
  1285. * @param caption
  1286. * The message to show
  1287. */
  1288. public Notification(String caption) {
  1289. this(caption, null, TYPE_HUMANIZED_MESSAGE);
  1290. }
  1291. /**
  1292. * Creates a notification message of the specified type.
  1293. *
  1294. * @param caption
  1295. * The message to show
  1296. * @param type
  1297. * The type of message
  1298. */
  1299. public Notification(String caption, int type) {
  1300. this(caption, null, type);
  1301. }
  1302. /**
  1303. * Creates a "humanized" notification message with a bigger caption and
  1304. * smaller description.
  1305. *
  1306. * @param caption
  1307. * The message caption
  1308. * @param description
  1309. * The message description
  1310. */
  1311. public Notification(String caption, String description) {
  1312. this(caption, description, TYPE_HUMANIZED_MESSAGE);
  1313. }
  1314. /**
  1315. * Creates a notification message of the specified type, with a bigger
  1316. * caption and smaller description.
  1317. *
  1318. * @param caption
  1319. * The message caption
  1320. * @param description
  1321. * The message description
  1322. * @param type
  1323. * The type of message
  1324. */
  1325. public Notification(String caption, String description, int type) {
  1326. this.caption = caption;
  1327. this.description = description;
  1328. setType(type);
  1329. }
  1330. private void setType(int type) {
  1331. switch (type) {
  1332. case TYPE_WARNING_MESSAGE:
  1333. delayMsec = 1500;
  1334. styleName = "warning";
  1335. break;
  1336. case TYPE_ERROR_MESSAGE:
  1337. delayMsec = -1;
  1338. styleName = "error";
  1339. break;
  1340. case TYPE_TRAY_NOTIFICATION:
  1341. delayMsec = 3000;
  1342. position = POSITION_BOTTOM_RIGHT;
  1343. styleName = "tray";
  1344. case TYPE_HUMANIZED_MESSAGE:
  1345. default:
  1346. break;
  1347. }
  1348. }
  1349. /**
  1350. * Gets the caption part of the notification message.
  1351. *
  1352. * @return The message caption
  1353. */
  1354. public String getCaption() {
  1355. return caption;
  1356. }
  1357. /**
  1358. * Sets the caption part of the notification message
  1359. *
  1360. * @param caption
  1361. * The message caption
  1362. */
  1363. public void setCaption(String caption) {
  1364. this.caption = caption;
  1365. }
  1366. /**
  1367. * @deprecated Use {@link #getDescription()} instead.
  1368. * @return
  1369. */
  1370. @Deprecated
  1371. public String getMessage() {
  1372. return description;
  1373. }
  1374. /**
  1375. * @deprecated Use {@link #setDescription(String)} instead.
  1376. * @param description
  1377. */
  1378. @Deprecated
  1379. public void setMessage(String description) {
  1380. this.description = description;
  1381. }
  1382. /**
  1383. * Gets the description part of the notification message.
  1384. *
  1385. * @return The message description.
  1386. */
  1387. public String getDescription() {
  1388. return description;
  1389. }
  1390. /**
  1391. * Sets the description part of the notification message.
  1392. *
  1393. * @param description
  1394. */
  1395. public void setDescription(String description) {
  1396. this.description = description;
  1397. }
  1398. /**
  1399. * Gets the position of the notification message.
  1400. *
  1401. * @return The position
  1402. */
  1403. public int getPosition() {
  1404. return position;
  1405. }
  1406. /**
  1407. * Sets the position of the notification message.
  1408. *
  1409. * @param position
  1410. * The desired notification position
  1411. */
  1412. public void setPosition(int position) {
  1413. this.position = position;
  1414. }
  1415. /**
  1416. * Gets the icon part of the notification message.
  1417. *
  1418. * @return The message icon
  1419. */
  1420. public Resource getIcon() {
  1421. return icon;
  1422. }
  1423. /**
  1424. * Sets the icon part of the notification message.
  1425. *
  1426. * @param icon
  1427. * The desired message icon
  1428. */
  1429. public void setIcon(Resource icon) {
  1430. this.icon = icon;
  1431. }
  1432. /**
  1433. * Gets the delay before the notification disappears.
  1434. *
  1435. * @return the delay in msec, -1 indicates the message has to be
  1436. * clicked.
  1437. */
  1438. public int getDelayMsec() {
  1439. return delayMsec;
  1440. }
  1441. /**
  1442. * Sets the delay before the notification disappears.
  1443. *
  1444. * @param delayMsec
  1445. * the desired delay in msec, -1 to require the user to click
  1446. * the message
  1447. */
  1448. public void setDelayMsec(int delayMsec) {
  1449. this.delayMsec = delayMsec;
  1450. }
  1451. /**
  1452. * Sets the style name for the notification message.
  1453. *
  1454. * @param styleName
  1455. * The desired style name.
  1456. */
  1457. public void setStyleName(String styleName) {
  1458. this.styleName = styleName;
  1459. }
  1460. /**
  1461. * Gets the style name for the notification message.
  1462. *
  1463. * @return
  1464. */
  1465. public String getStyleName() {
  1466. return styleName;
  1467. }
  1468. }
  1469. }