1. /*
  2. * @(#)MenuComponent.java 1.44 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt;
  8. import java.awt.peer.MenuComponentPeer;
  9. import java.awt.event.ActionEvent;
  10. import java.io.IOException;
  11. import java.io.ObjectInputStream;
  12. import sun.awt.AppContext;
  13. import sun.awt.SunToolkit;
  14. /**
  15. * The abstract class <code>MenuComponent</code> is the superclass
  16. * of all menu-related components. In this respect, the class
  17. * <code>MenuComponent</code> is analogous to the abstract superclass
  18. * <code>Component</code> for AWT components.
  19. * <p>
  20. * Menu components receive and process AWT events, just as components do,
  21. * through the method <code>processEvent</code>.
  22. *
  23. * @version 1.44, 11/29/01
  24. * @author Arthur van Hoff
  25. * @since JDK1.0
  26. */
  27. public abstract class MenuComponent implements java.io.Serializable {
  28. static {
  29. /* ensure that the necessary native libraries are loaded */
  30. Toolkit.loadLibraries();
  31. initIDs();
  32. }
  33. transient MenuComponentPeer peer;
  34. transient MenuContainer parent;
  35. /**
  36. * The AppContext of the MenuComponent. This is set in the constructor
  37. * and never changes.
  38. */
  39. transient AppContext appContext;
  40. /**
  41. * The Menu Components Font.
  42. * This value can be null at which point a default will be used.
  43. *
  44. * @serial
  45. * @see setFont()
  46. * @see getFont()
  47. */
  48. Font font;
  49. /**
  50. * The Menu Components name.
  51. * @serial
  52. * @see getName()
  53. * @see setName()
  54. */
  55. private String name;
  56. /**
  57. * A variable to indicate whether a name is explicitly set.
  58. * If it is true the name will be set explicitly.
  59. * @serial
  60. * @see setName()
  61. */
  62. private boolean nameExplicitlySet = false;
  63. /**
  64. * @serial
  65. * @see dispatchEvent()
  66. */
  67. boolean newEventsOnly = false;
  68. /*
  69. * Internal constants for serialization
  70. */
  71. final static String actionListenerK = Component.actionListenerK;
  72. final static String itemListenerK = Component.itemListenerK;
  73. /*
  74. * JDK 1.1 serialVersionUID
  75. */
  76. private static final long serialVersionUID = -4536902356223894379L;
  77. /**
  78. * Constructor for MenuComponent.
  79. */
  80. public MenuComponent() {
  81. appContext = AppContext.getAppContext();
  82. SunToolkit.insertTargetMapping(this, appContext);
  83. }
  84. /**
  85. * Construct a name for this MenuComponent. Called by getName() when
  86. * the name is null.
  87. */
  88. String constructComponentName() {
  89. return null; // For strict compliance with prior JDKs, a MenuComponent
  90. // that doesn't set its name should return null from
  91. // getName()
  92. }
  93. /**
  94. * Gets the name of the menu component.
  95. * @return the name of the menu component.
  96. * @see java.awt.MenuComponent#setName(java.lang.String)
  97. * @since JDK1.1
  98. */
  99. public String getName() {
  100. if (name == null && !nameExplicitlySet) {
  101. synchronized(this) {
  102. if (name == null && !nameExplicitlySet)
  103. name = constructComponentName();
  104. }
  105. }
  106. return name;
  107. }
  108. /**
  109. * Sets the name of the component to the specified string.
  110. * @param name the name of the menu component.
  111. * @see java.awt.MenuComponent#getName
  112. * @since JDK1.1
  113. */
  114. public void setName(String name) {
  115. synchronized(this) {
  116. this.name = name;
  117. nameExplicitlySet = true;
  118. }
  119. }
  120. /**
  121. * Returns the parent container for this menu component.
  122. * @return the menu component containing this menu component,
  123. * or <code>null</code> if this menu component
  124. * is the outermost component, the menu bar itself.
  125. */
  126. public MenuContainer getParent() {
  127. return getParent_NoClientCode();
  128. }
  129. // NOTE: This method may be called by privileged threads.
  130. // This functionality is implemented in a package-private method
  131. // to insure that it cannot be overridden by client subclasses.
  132. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  133. final MenuContainer getParent_NoClientCode() {
  134. return parent;
  135. }
  136. /**
  137. * @deprecated As of JDK version 1.1,
  138. * programs should not directly manipulate peers.
  139. */
  140. public MenuComponentPeer getPeer() {
  141. return peer;
  142. }
  143. /**
  144. * Gets the font used for this menu component.
  145. * @return the font used in this menu component, if there is one;
  146. * <code>null</code> otherwise.
  147. * @see java.awt.MenuComponent#setFont
  148. */
  149. public Font getFont() {
  150. Font font = this.font;
  151. if (font != null) {
  152. return font;
  153. }
  154. MenuContainer parent = this.parent;
  155. if (parent != null) {
  156. return parent.getFont();
  157. }
  158. return null;
  159. }
  160. // NOTE: This method may be called by privileged threads.
  161. // This functionality is implemented in a package-private method
  162. // to insure that it cannot be overridden by client subclasses.
  163. // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  164. final Font getFont_NoClientCode() {
  165. Font font = this.font;
  166. if (font != null) {
  167. return font;
  168. }
  169. // The MenuContainer interface does not have getFont_NoClientCode()
  170. // and it cannot, because it must be package-private. Because of
  171. // this, we must manually cast classes that implement
  172. // MenuContainer.
  173. Object parent = this.parent;
  174. if (parent != null) {
  175. if (parent instanceof Component) {
  176. font = ((Component)parent).getFont_NoClientCode();
  177. } else if (parent instanceof MenuComponent) {
  178. font = ((MenuComponent)parent).getFont_NoClientCode();
  179. }
  180. }
  181. return font;
  182. } // getFont_NoClientCode()
  183. /**
  184. * Sets the font to be used for this menu component to the specified
  185. * font. This font is also used by all subcomponents of this menu
  186. * component, unless those subcomponents specify a different font.
  187. * @param f the font to be set.
  188. * @see java.awt.MenuComponent#getFont
  189. */
  190. public void setFont(Font f) {
  191. font = f;
  192. }
  193. /**
  194. * Removes the menu component's peer. The peer allows us to modify the
  195. * appearance of the menu component without changing the functionality of
  196. * the menu component.
  197. */
  198. public void removeNotify() {
  199. synchronized (getTreeLock()) {
  200. MenuComponentPeer p = (MenuComponentPeer)this.peer;
  201. if (p != null) {
  202. Toolkit.getEventQueue().removeSourceEvents(this);
  203. this.peer = null;
  204. p.dispose();
  205. }
  206. }
  207. }
  208. /**
  209. * Posts the specified event to the menu.
  210. * This method is part of the Java 1.0 event system
  211. * and it is maintained only for backwards compatibility.
  212. * Its use is discouraged, and it may not be supported
  213. * in the future.
  214. * @param evt the event which is to take place
  215. * @deprecated As of JDK version 1.1,
  216. * replaced by <code>dispatchEvent(AWTEvent)</code>.
  217. */
  218. public boolean postEvent(Event evt) {
  219. MenuContainer parent = this.parent;
  220. if (parent != null) {
  221. parent.postEvent(evt);
  222. }
  223. return false;
  224. }
  225. /*
  226. * Delivers an event to this component or one of its sub components.
  227. * @param e the event
  228. */
  229. public final void dispatchEvent(AWTEvent e) {
  230. dispatchEventImpl(e);
  231. }
  232. void dispatchEventImpl(AWTEvent e) {
  233. Toolkit.getDefaultToolkit().notifyAWTEventListeners(e);
  234. if (newEventsOnly ||
  235. (parent != null && parent instanceof MenuComponent &&
  236. ((MenuComponent)parent).newEventsOnly)) {
  237. if (eventEnabled(e)) {
  238. processEvent(e);
  239. } else if (e instanceof ActionEvent && parent != null) {
  240. ((MenuComponent)parent).dispatchEvent(new ActionEvent(parent,
  241. e.getID(),
  242. ((ActionEvent)e).getActionCommand()));
  243. }
  244. } else { // backward compatibility
  245. Event olde = e.convertToOld();
  246. if (olde != null) {
  247. postEvent(olde);
  248. }
  249. }
  250. }
  251. // REMIND: remove when filtering is done at lower level
  252. boolean eventEnabled(AWTEvent e) {
  253. return false;
  254. }
  255. /**
  256. * Processes events occurring on this menu component.
  257. *
  258. * @param e the event
  259. * @since JDK1.1
  260. */
  261. protected void processEvent(AWTEvent e) {
  262. }
  263. /**
  264. * Returns the parameter string representing the state of this
  265. * menu component. This string is useful for debugging.
  266. * @return the parameter string of this menu component.
  267. */
  268. protected String paramString() {
  269. String thisName = getName();
  270. return (thisName != null? thisName : "");
  271. }
  272. /**
  273. * Returns a representation of this menu component as a string.
  274. * @return a string representation of this menu component.
  275. */
  276. public String toString() {
  277. return getClass().getName() + "[" + paramString() + "]";
  278. }
  279. /**
  280. * Gets this component's locking object (the object that owns the thread
  281. * sychronization monitor) for AWT component-tree and layout
  282. * operations.
  283. * @return This component's locking object.
  284. */
  285. protected final Object getTreeLock() {
  286. return Component.LOCK;
  287. }
  288. private void readObject(ObjectInputStream s)
  289. throws ClassNotFoundException, IOException
  290. {
  291. s.defaultReadObject();
  292. appContext = AppContext.getAppContext();
  293. SunToolkit.insertTargetMapping(this, appContext);
  294. }
  295. /**
  296. * Initialize JNI field and method IDs
  297. */
  298. private static native void initIDs();
  299. }