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.

AbstractComponent.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /* *************************************************************************
  2. IT Mill Toolkit
  3. Development of Browser User Intarfaces Made Easy
  4. Copyright (C) 2000-2006 IT Mill Ltd
  5. *************************************************************************
  6. This product is distributed under commercial license that can be found
  7. from the product package on license/license.txt. Use of this product might
  8. require purchasing a commercial license from IT Mill Ltd. For guidelines
  9. on usage, see license/licensing-guidelines.html
  10. *************************************************************************
  11. For more information, contact:
  12. IT Mill Ltd phone: +358 2 4802 7180
  13. Ruukinkatu 2-4 fax: +358 2 4802 7181
  14. 20540, Turku email: info@itmill.com
  15. Finland company www: www.itmill.com
  16. Primary source for information and releases: www.itmill.com
  17. ********************************************************************** */
  18. package com.itmill.toolkit.ui;
  19. import com.itmill.toolkit.Application;
  20. import com.itmill.toolkit.event.EventRouter;
  21. import com.itmill.toolkit.event.MethodEventSource;
  22. import com.itmill.toolkit.terminal.*;
  23. import java.util.Collection;
  24. import java.util.LinkedList;
  25. import java.util.Locale;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import java.util.HashSet;
  29. import java.lang.reflect.Method;
  30. /** An abstract class that defines default implementation for the
  31. * {@link Component} interface. Basic UI components that are not derived
  32. * from an external component can inherit this class to easily qualify as a
  33. * IT Mill Toolkit component. Most components in the toolkit do
  34. * just that.
  35. *
  36. * @author IT Mill Ltd.
  37. * @version @VERSION@
  38. * @since 3.0
  39. */
  40. public abstract class AbstractComponent
  41. implements Component, MethodEventSource {
  42. /* Private members ************************************************* */
  43. /** Look-and-feel style of the component. */
  44. private String style;
  45. /** Caption text. */
  46. private String caption;
  47. /** Application specific data object. */
  48. private Object applicationData;
  49. /** Icon to be shown together with caption. */
  50. private Resource icon;
  51. /** Is the component enable (its normal usage is allowed). */
  52. private boolean enabled = true;
  53. /** Is the component visible (it is rendered). */
  54. private boolean visible = true;
  55. /** Is the component read-only ? */
  56. private boolean readOnly = false;
  57. /** Description of the usage (XML). */
  58. private String description = null;
  59. /** The container this component resides in. */
  60. private Component parent = null;
  61. /** The EventRouter used for the event model. */
  62. private EventRouter eventRouter = null;
  63. /** The internal error message of the component. */
  64. private ErrorMessage componentError = null;
  65. /** List of event variable change event handling dependencies */
  66. private Set dependencies = null;
  67. /** Immediate mode: if true, all variable changes are required to be sent
  68. * from the terminal immediately
  69. */
  70. private boolean immediate = false;
  71. /** Locale of this component. */
  72. private Locale locale;
  73. /** List of repaint request listeners or null if not listened at all */
  74. private LinkedList repaintRequestListeners = null;
  75. /** Are all the repaint listeners notified about recent changes ? */
  76. private boolean repaintRequestListenersNotified = false;
  77. /* Constructor ***************************************************** */
  78. /** Constructs a new Component */
  79. public AbstractComponent() {
  80. }
  81. /* Get/Set component properties ************************************ */
  82. /** Gets the UIDL tag corresponding to the component.
  83. *
  84. * @return component's UIDL tag as <code>String</code>
  85. */
  86. public abstract String getTag();
  87. /* Gets the component's style.
  88. * Don't add a JavaDoc comment here, we use the default documentation
  89. * from implemented interface.
  90. */
  91. public String getStyle() {
  92. return this.style;
  93. }
  94. /* Sets the component's style.
  95. * Don't add a JavaDoc comment here, we use the default documentation
  96. * from implemented interface.
  97. */
  98. public void setStyle(String style) {
  99. this.style = style;
  100. requestRepaint();
  101. }
  102. /* Get's the component's caption.
  103. * Don't add a JavaDoc comment here, we use the default documentation
  104. * from implemented interface.
  105. */
  106. public String getCaption() {
  107. return this.caption;
  108. }
  109. /** Sets the component's caption <code>String</code>. Caption is the
  110. * visible name of the component. This method will trigger a
  111. * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
  112. *
  113. * @param caption new caption <code>String</code> for the component
  114. */
  115. public void setCaption(String caption) {
  116. this.caption = caption;
  117. requestRepaint();
  118. }
  119. /* Don't add a JavaDoc comment here, we use the default documentation
  120. * from implemented interface.
  121. */
  122. public Locale getLocale() {
  123. if (this.locale != null)
  124. return this.locale;
  125. if (this.parent != null)
  126. return parent.getLocale();
  127. Application app = this.getApplication();
  128. if (app != null)
  129. return app.getLocale();
  130. return null;
  131. }
  132. /** Sets the locale of this component.
  133. * @param locale The locale to become this component's locale.
  134. */
  135. public void setLocale(Locale locale) {
  136. this.locale = locale;
  137. }
  138. /* Gets the component's icon resource.
  139. * Don't add a JavaDoc comment here, we use the default documentation
  140. * from implemented interface.
  141. */
  142. public Resource getIcon() {
  143. return this.icon;
  144. }
  145. /** Sets the component's icon. This method will trigger a
  146. * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
  147. *
  148. * @param icon the icon to be shown with the component's caption
  149. */
  150. public void setIcon(Resource icon) {
  151. this.icon = icon;
  152. requestRepaint();
  153. }
  154. /* Tests if the component is enabled or not.
  155. * Don't add a JavaDoc comment here, we use the default documentation
  156. * from implemented interface.
  157. */
  158. public boolean isEnabled() {
  159. return this.enabled && isVisible();
  160. }
  161. /* Enables or disables the component.
  162. * Don't add a JavaDoc comment here, we use the default documentation
  163. * from implemented interface.
  164. */
  165. public void setEnabled(boolean enabled) {
  166. if (this.enabled != enabled) {
  167. this.enabled = enabled;
  168. requestRepaint();
  169. }
  170. }
  171. /* Tests if the component is in the immediate mode.
  172. * Don't add a JavaDoc comment here, we use the default documentation
  173. * from implemented interface.
  174. */
  175. public boolean isImmediate() {
  176. return immediate;
  177. }
  178. /** Sets the component's immediate mode to the specified status. This
  179. * method will trigger a
  180. * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
  181. *
  182. * @param immediate boolean value specifying if the component should
  183. * be in the immediate mode after the call.
  184. * @see Component#isImmediate()
  185. */
  186. public void setImmediate(boolean immediate) {
  187. this.immediate = immediate;
  188. requestRepaint();
  189. }
  190. /* Tests if the component is visible.
  191. * Don't add a JavaDoc comment here, we use the default documentation
  192. * from implemented interface.
  193. */
  194. public boolean isVisible() {
  195. return this.visible;
  196. }
  197. /* Sets the components visibility.
  198. * Don't add a JavaDoc comment here, we use the default documentation
  199. * from implemented interface.
  200. */
  201. public void setVisible(boolean visible) {
  202. if (this.visible != visible) {
  203. this.visible = visible;
  204. // Instead of requesting repaint normally we
  205. // fire the event directly to assure that the
  206. // event goes through event in the component might
  207. // now be invisible
  208. fireRequestRepaintEvent(null);
  209. }
  210. }
  211. /** <p>Gets the component's description. The description can be used to
  212. * briefly describe the state of the component to the user. The
  213. * description string may contain certain XML tags:</p>
  214. *
  215. * <p><table border=1>
  216. * <tr><td width=120><b>Tag</b></td>
  217. * <td width=120><b>Description</b></td>
  218. * <td width=120><b>Example</b></td>
  219. * </tr>
  220. * <tr><td>&lt;b></td>
  221. * <td>bold</td>
  222. * <td><b>bold text</b></td>
  223. * </tr>
  224. * <tr><td>&lt;i></td>
  225. * <td>italic</td>
  226. * <td><i>italic text</i></td>
  227. * </tr>
  228. * <tr><td>&lt;u></td>
  229. * <td>underlined</td>
  230. * <td><u>underlined text</u></td>
  231. * </tr>
  232. * <tr><td>&lt;br></td>
  233. * <td>linebreak</td>
  234. * <td>N/A</td>
  235. * </tr>
  236. * <tr><td>&lt;ul><br>&lt;li>item1<br>&lt;li>item1<br>&lt;/ul></td>
  237. * <td>item list</td>
  238. * <td><ul><li>item1 <li>item2</ul></td>
  239. * </tr>
  240. * </table></p>
  241. *
  242. * <p>These tags may be nested.</p>
  243. *
  244. * @return component's description <code>String</code>
  245. */
  246. public String getDescription() {
  247. return this.description;
  248. }
  249. /** Sets the component's description. See {@link #getDescription()} for
  250. * more information on what the description is. This method will trigger
  251. * a {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
  252. *
  253. * @param description new description string for the component
  254. */
  255. public void setDescription(String description) {
  256. this.description = description;
  257. requestRepaint();
  258. }
  259. /* Gets the component's parent component.
  260. * Don't add a JavaDoc comment here, we use the default documentation
  261. * from implemented interface.
  262. */
  263. public Component getParent() {
  264. return this.parent;
  265. }
  266. /* Set the parent component.
  267. * Don't add a JavaDoc comment here, we use the default documentation
  268. * from implemented interface.
  269. */
  270. public void setParent(Component parent) {
  271. // If the parent is not changed, dont do nothing
  272. if (parent == this.parent)
  273. return;
  274. // Send detach event if the component have been connected to a window
  275. if (getApplication() != null) {
  276. detach();
  277. this.parent = null;
  278. }
  279. // Connect to new parent
  280. this.parent = parent;
  281. // Send attach event if connected to a window
  282. if (getApplication() != null)
  283. attach();
  284. }
  285. /** Get the error message for this component.
  286. *
  287. * @return ErrorMessage containing the description of the error state
  288. * of the component or null, if the component contains no errors. Extending
  289. * classes should override this method if they support other error message
  290. * types such as validation errors or buffering errors. The returned error
  291. * message contains information about all the errors.
  292. */
  293. public ErrorMessage getErrorMessage() {
  294. return this.componentError;
  295. }
  296. /** Gets the component's error message.
  297. * @link Terminal.ErrorMessage#ErrorMessage(String, int)
  298. *
  299. * @return component's error message
  300. */
  301. public ErrorMessage getComponentError() {
  302. return this.componentError;
  303. }
  304. /** Sets the component's error message. The message may contain certain
  305. * XML tags, for more information see
  306. * @link Component.ErrorMessage#ErrorMessage(String, int)
  307. *
  308. * @param errorMessage new <code>ErrorMessage</code> of the component
  309. */
  310. public void setComponentError(ErrorMessage componentError) {
  311. this.componentError = componentError;
  312. fireComponentErrorEvent();
  313. requestRepaint();
  314. }
  315. /* Tests if the component is in read-only mode.
  316. * Don't add a JavaDoc comment here, we use the default documentation
  317. * from implemented interface.
  318. */
  319. public boolean isReadOnly() {
  320. return readOnly;
  321. }
  322. /* Set the component's read-only mode.
  323. * Don't add a JavaDoc comment here, we use the default documentation
  324. * from implemented interface.
  325. */
  326. public void setReadOnly(boolean readOnly) {
  327. this.readOnly = readOnly;
  328. requestRepaint();
  329. }
  330. /* Get the parent window of the component.
  331. * Don't add a JavaDoc comment here, we use the default documentation
  332. * from implemented interface.
  333. */
  334. public Window getWindow() {
  335. if (parent == null)
  336. return null;
  337. else
  338. return parent.getWindow();
  339. }
  340. /* Notify the component that it's attached to a window.
  341. * Don't add a JavaDoc comment here, we use the default documentation
  342. * from implemented interface.
  343. */
  344. public void attach() {
  345. }
  346. /* Detach the component from application.
  347. * Don't add a JavaDoc comment here, we use the default documentation
  348. * from implemented interface.
  349. */
  350. public void detach() {
  351. }
  352. /* Get the parent application of the component.
  353. * Don't add a JavaDoc comment here, we use the default documentation
  354. * from implemented interface.
  355. */
  356. public Application getApplication() {
  357. if (parent == null)
  358. return null;
  359. else
  360. return parent.getApplication();
  361. }
  362. /* Component painting ********************************************** */
  363. /* Documented in super interface */
  364. public void requestRepaintRequests() {
  365. repaintRequestListenersNotified = false;
  366. }
  367. /* Paints the component into a UIDL stream.
  368. * Don't add a JavaDoc comment here, we use the default documentation
  369. * from implemented interface.
  370. */
  371. public final void paint(PaintTarget target) throws PaintException {
  372. if (!target.startTag(this, this.getTag())) {
  373. if (getStyle() != null && getStyle().length() > 0)
  374. target.addAttribute("style", getStyle());
  375. if (isReadOnly())
  376. target.addAttribute("readonly", true);
  377. if (!isVisible())
  378. target.addAttribute("invisible", true);
  379. if (isImmediate())
  380. target.addAttribute("immediate", true);
  381. if (!isEnabled())
  382. target.addAttribute("disabled", true);
  383. if (getCaption() != null)
  384. target.addAttribute("caption", getCaption());
  385. if (getIcon() != null)
  386. target.addAttribute("icon", getIcon());
  387. // Only paint content of visible components.
  388. if (isVisible()) {
  389. paintContent(target);
  390. String desc = getDescription();
  391. if (desc != null && description.length() > 0) {
  392. target.startTag("description");
  393. target.addUIDL(getDescription());
  394. target.endTag("description");
  395. }
  396. ErrorMessage error = getErrorMessage();
  397. if (error != null)
  398. error.paint(target);
  399. }
  400. }
  401. target.endTag(this.getTag());
  402. repaintRequestListenersNotified = false;
  403. }
  404. /** Paints any needed component-specific things to the given UIDL
  405. * stream. The more general {@link #paint(PaintTarget)} method handles
  406. * all general attributes common to all components, and it calls this
  407. * method to paint any component-specific attributes to the UIDL stream.
  408. *
  409. * @param target target UIDL stream where the component should paint
  410. * itself to
  411. * @throws PaintException if the operation failed
  412. */
  413. public void paintContent(PaintTarget target) throws PaintException {
  414. }
  415. /* Documentation copied from interface */
  416. public void requestRepaint() {
  417. // The effect of the repaint request is identical to case where a
  418. // child requests repaint
  419. childRequestedRepaint(null);
  420. }
  421. /* Documentation copied from interface */
  422. public void childRequestedRepaint(Collection alreadyNotified) {
  423. // Invisible components do not need repaints
  424. if (!isVisible())
  425. return;
  426. fireRequestRepaintEvent(alreadyNotified);
  427. }
  428. /** Fire repaint request event */
  429. private void fireRequestRepaintEvent(Collection alreadyNotified) {
  430. // Notify listeners only once
  431. if (!repaintRequestListenersNotified) {
  432. // Notify the listeners
  433. if (repaintRequestListeners != null
  434. && !repaintRequestListeners.isEmpty()) {
  435. Object[] listeners = repaintRequestListeners.toArray();
  436. RepaintRequestEvent event = new RepaintRequestEvent(this);
  437. for (int i = 0; i < listeners.length; i++) {
  438. if (alreadyNotified == null)
  439. alreadyNotified = new LinkedList();
  440. if (!alreadyNotified.contains(listeners[i])) {
  441. (
  442. (
  443. RepaintRequestListener) listeners[i])
  444. .repaintRequested(
  445. event);
  446. alreadyNotified.add(listeners[i]);
  447. repaintRequestListenersNotified = true;
  448. }
  449. }
  450. }
  451. // Notify the parent
  452. Component parent = getParent();
  453. if (parent != null)
  454. parent.childRequestedRepaint(alreadyNotified);
  455. }
  456. }
  457. /* Documentation copied from interface */
  458. public void addListener(RepaintRequestListener listener) {
  459. if (repaintRequestListeners == null)
  460. repaintRequestListeners = new LinkedList();
  461. if (!repaintRequestListeners.contains(listener)) {
  462. repaintRequestListeners.add(listener);
  463. }
  464. }
  465. /* Documentation copied from interface */
  466. public void removeListener(RepaintRequestListener listener) {
  467. if (repaintRequestListeners != null) {
  468. repaintRequestListeners.remove(listener);
  469. if (repaintRequestListeners.isEmpty())
  470. repaintRequestListeners = null;
  471. }
  472. }
  473. /* Component variable changes ************************************** */
  474. /* Invoked when the value of a variable has changed.
  475. * Don't add a JavaDoc comment here, we use the default documentation
  476. * from implemented interface.
  477. */
  478. public void changeVariables(Object source, Map variables) {
  479. }
  480. /* Adds a variable-change dependency to this component.
  481. * Don't add a JavaDoc comment here, we use the default documentation
  482. * from implemented interface.
  483. */
  484. public void dependsOn(VariableOwner depended) {
  485. // Assure that the list exists
  486. if (dependencies == null)
  487. dependencies = new HashSet();
  488. // Add to the list of dependencies
  489. if (depended != null)
  490. dependencies.add(depended);
  491. }
  492. /* Removes a dependency from the component.
  493. * Don't add a JavaDoc comment here, we use the default documentation
  494. * from implemented interface.
  495. */
  496. public void removeDirectDependency(VariableOwner depended) {
  497. // Remove the listener if necessary
  498. if (dependencies != null && depended != null)
  499. dependencies.remove(depended);
  500. }
  501. /* Gets the set of depended components.
  502. * Don't add a JavaDoc comment here, we use the default documentation
  503. * from implemented interface.
  504. */
  505. public Set getDirectDependencies() {
  506. return dependencies;
  507. }
  508. /* General event framework *************************************** */
  509. private static final Method COMPONENT_EVENT_METHOD;
  510. static {
  511. try {
  512. COMPONENT_EVENT_METHOD =
  513. Component.Listener.class.getDeclaredMethod(
  514. "componentEvent",
  515. new Class[] { Component.Event.class });
  516. } catch (java.lang.NoSuchMethodException e) {
  517. // This should never happen
  518. e.printStackTrace();
  519. throw new java.lang.RuntimeException();
  520. }
  521. }
  522. /** <p>Registers a new listener with the specified activation method to
  523. * listen events generated by this component. If the activation method
  524. * does not have any arguments the event object will not be passed to it
  525. * when it's called.</p>
  526. *
  527. * <p>For more information on the inheritable event mechanism
  528. * see the
  529. * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}.</p>
  530. *
  531. * @param eventType type of the listened event. Events of this type or
  532. * its subclasses activate the listener.
  533. * @param object the object instance who owns the activation method
  534. * @param method the activation method
  535. * @throws java.lang.IllegalArgumentException unless <code>method</code>
  536. * has exactly one match in <code>object</code>
  537. */
  538. public void addListener(Class eventType, Object object, Method method) {
  539. if (eventRouter == null)
  540. eventRouter = new EventRouter();
  541. eventRouter.addListener(eventType, object, method);
  542. }
  543. /** <p>Registers a new listener with the specified activation method to
  544. * listen events generated by this component. If the activation method
  545. * does not have any arguments the event object will not be passed to it
  546. * when it's called.</p>
  547. *
  548. * <p>This version of <code>addListener</code> gets the name of the
  549. * activation method as a parameter. The actual method is reflected from
  550. * <code>object</code>, and unless exactly one match is found,
  551. * <code>java.lang.IllegalArgumentException</code> is thrown.</p>
  552. *
  553. * <p>For more information on the inheritable event mechanism
  554. * see the
  555. * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}.</p>
  556. *
  557. * @param eventType type of the listened event. Events of this type or
  558. * its subclasses activate the listener.
  559. * @param object the object instance who owns the activation method
  560. * @param methodName the name of the activation method
  561. * @throws java.lang.IllegalArgumentException unless <code>method</code>
  562. * has exactly one match in <code>object</code>
  563. */
  564. public void addListener(
  565. Class eventType,
  566. Object object,
  567. String methodName) {
  568. if (eventRouter == null)
  569. eventRouter = new EventRouter();
  570. eventRouter.addListener(eventType, object, methodName);
  571. }
  572. /** Removes all registered listeners matching the given parameters.
  573. * Since this method receives the event type and the listener object as
  574. * parameters, it will unregister all <code>object</code>'s methods that
  575. * are registered to listen to events of type <code>eventType</code>
  576. * generated by this component.
  577. *
  578. * <p>For more information on the inheritable event mechanism
  579. * see the
  580. * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}.</p>
  581. *
  582. * @param eventType exact event type the <code>object</code> listens to
  583. * @param target target object that has registered to listen to events
  584. * of type <code>eventType</code> with one or more methods
  585. */
  586. public void removeListener(Class eventType, Object target) {
  587. if (eventRouter != null)
  588. eventRouter.removeListener(eventType, target);
  589. }
  590. /** Removes one registered listener method. The given method owned by
  591. * the given object will no longer be called when the specified events
  592. * are generated by this component.
  593. *
  594. * <p>For more information on the inheritable event mechanism
  595. * see the
  596. * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}.</p>
  597. *
  598. * @param eventType exact event type the <code>object</code> listens to
  599. * @param target target object that has registered to listen to events
  600. * of type <code>eventType</code> with one or more methods
  601. * @param method the method owned by <code>target</code> that's
  602. * registered to listen to events of type <code>eventType</code>
  603. */
  604. public void removeListener(Class eventType, Object target, Method method) {
  605. if (eventRouter != null)
  606. eventRouter.removeListener(eventType, target, method);
  607. }
  608. /** <p>Removes one registered listener method. The given method owned by
  609. * the given object will no longer be called when the specified events
  610. * are generated by this component.</p>
  611. *
  612. * <p>This version of <code>removeListener</code> gets the name of the
  613. * activation method as a parameter. The actual method is reflected from
  614. * <code>target</code>, and unless exactly one match is found,
  615. * <code>java.lang.IllegalArgumentException</code> is thrown.</p>
  616. *
  617. * <p>For more information on the inheritable event mechanism
  618. * see the
  619. * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}.</p>
  620. *
  621. * @param eventType exact event type the <code>object</code> listens to
  622. * @param target target object that has registered to listen to events
  623. * of type <code>eventType</code> with one or more methods
  624. * @param methodName name of the method owned by <code>target</code>
  625. * that's registered to listen to events of type <code>eventType</code>
  626. */
  627. public void removeListener(
  628. Class eventType,
  629. Object target,
  630. String methodName) {
  631. if (eventRouter != null)
  632. eventRouter.removeListener(eventType, target, methodName);
  633. }
  634. /** Send event to all listeners
  635. * @param event Event to be sent to all listeners
  636. */
  637. protected void fireEvent(Component.Event event) {
  638. if (eventRouter != null)
  639. eventRouter.fireEvent(event);
  640. }
  641. /* Component event framework *************************************** */
  642. /* Registers a new listener to listen events generated by this
  643. * component.
  644. * Don't add a JavaDoc comment here, we use the default documentation
  645. * from implemented interface.
  646. */
  647. public void addListener(Component.Listener listener) {
  648. if (eventRouter == null)
  649. eventRouter = new EventRouter();
  650. eventRouter.addListener(
  651. Component.Event.class,
  652. listener,
  653. COMPONENT_EVENT_METHOD);
  654. }
  655. /* Removes a previously registered listener from this component.
  656. * Don't add a JavaDoc comment here, we use the default documentation
  657. * from implemented interface.
  658. */
  659. public void removeListener(Component.Listener listener) {
  660. if (eventRouter != null) {
  661. eventRouter.removeListener(
  662. Component.Event.class,
  663. listener,
  664. COMPONENT_EVENT_METHOD);
  665. }
  666. }
  667. /** Emits a component event. It is transmitted to all registered
  668. * listeners interested in such events.
  669. */
  670. protected void fireComponentEvent() {
  671. fireEvent(new Component.Event(this));
  672. }
  673. /** Emits a component error event. It is transmitted to all registered
  674. * listeners interested in such events.
  675. */
  676. protected void fireComponentErrorEvent() {
  677. fireEvent(new Component.ErrorEvent(this.getComponentError(),this));
  678. }
  679. /** Sets application specific data object.
  680. *
  681. * @param data Application specific data.
  682. * @since 3.1
  683. */
  684. public void setData(Object data) {
  685. this.applicationData = data;
  686. }
  687. /** Gets application specific data.
  688. *
  689. * @return Application specific data set with setData function.
  690. * @since 3.1
  691. */
  692. public Object getData() {
  693. return this.applicationData;
  694. }
  695. }