1. /*
  2. * @(#)BasicMenuUI.java 1.121 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 javax.swing.plaf.basic;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import javax.swing.*;
  12. import javax.swing.event.*;
  13. import javax.swing.plaf.*;
  14. import javax.swing.border.*;
  15. /**
  16. * A default L&F implementation of MenuUI. This implementation
  17. * is a "combined" view/controller.
  18. *
  19. * @version 1.121 11/29/01
  20. * @author Georges Saab
  21. * @author David Karlton
  22. * @author Arnaud Weber
  23. */
  24. public class BasicMenuUI extends BasicMenuItemUI
  25. {
  26. protected ChangeListener changeListener;
  27. protected PropertyChangeListener propertyChangeListener;
  28. protected MenuListener menuListener;
  29. private int lastMnemonic = 0;
  30. public static ComponentUI createUI(JComponent x) {
  31. return new BasicMenuUI();
  32. }
  33. protected void installDefaults() {
  34. super.installDefaults();
  35. ((JMenu)menuItem).setDelay(200);
  36. }
  37. protected String getPropertyPrefix() {
  38. return "Menu";
  39. }
  40. protected void installListeners() {
  41. super.installListeners();
  42. changeListener = createChangeListener(menuItem);
  43. propertyChangeListener = createPropertyChangeListener(menuItem);
  44. menuListener = createMenuListener(menuItem);
  45. menuItem.addChangeListener(changeListener);
  46. menuItem.addPropertyChangeListener(propertyChangeListener);
  47. ((JMenu)menuItem).addMenuListener(menuListener);
  48. }
  49. protected void installKeyboardActions() {
  50. if(menuItem.getModel().getMnemonic() != lastMnemonic) {
  51. menuItem.unregisterKeyboardAction(
  52. KeyStroke.getKeyStroke(lastMnemonic,
  53. ActionEvent.ALT_MASK,
  54. false));
  55. lastMnemonic = menuItem.getModel().getMnemonic();
  56. menuItem.registerKeyboardAction(
  57. new PostAction((JMenu)menuItem, true),
  58. KeyStroke.getKeyStroke(lastMnemonic,
  59. ActionEvent.ALT_MASK,
  60. false),
  61. JComponent.WHEN_IN_FOCUSED_WINDOW);
  62. }
  63. }
  64. protected void uninstallKeyboardActions() {
  65. menuItem.unregisterKeyboardAction(
  66. KeyStroke.getKeyStroke(lastMnemonic,
  67. ActionEvent.ALT_MASK,
  68. false));
  69. lastMnemonic = 0;
  70. }
  71. protected MouseInputListener createMouseInputListener(JComponent c) {
  72. return new MouseInputHandler();
  73. }
  74. protected MenuListener createMenuListener(JComponent c) {
  75. return new MenuHandler();
  76. }
  77. protected ChangeListener createChangeListener(JComponent c) {
  78. return new ChangeHandler((JMenu)c, this);
  79. }
  80. protected PropertyChangeListener createPropertyChangeListener(JComponent c) {
  81. return new PropertyChangeHandler();
  82. }
  83. protected void uninstallDefaults() {
  84. menuItem.setArmed(false);
  85. menuItem.setSelected(false);
  86. menuItem.resetKeyboardActions();
  87. super.uninstallDefaults();
  88. }
  89. protected void uninstallListeners() {
  90. super.uninstallListeners();
  91. menuItem.removeChangeListener(changeListener);
  92. menuItem.removePropertyChangeListener(propertyChangeListener);
  93. ((JMenu)menuItem).removeMenuListener(menuListener);
  94. changeListener = null;
  95. propertyChangeListener = null;
  96. menuListener = null;
  97. }
  98. protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) {
  99. return new MenuDragMouseHandler();
  100. }
  101. protected MenuKeyListener createMenuKeyListener(JComponent c) {
  102. return new MenuKeyHandler();
  103. }
  104. public Dimension getMaximumSize(JComponent c) {
  105. if (((JMenu)menuItem).isTopLevelMenu() == true) {
  106. Dimension d = c.getPreferredSize();
  107. return new Dimension(d.width, Short.MAX_VALUE);
  108. }
  109. return null;
  110. }
  111. protected void setupPostTimer(JMenu menu) {
  112. Timer timer = new Timer(menu.getDelay(),new PostAction(menu,false));
  113. timer.setRepeats(false);
  114. timer.start();
  115. }
  116. private static class PostAction implements ActionListener {
  117. JMenu menu;
  118. boolean force=false;
  119. PostAction(JMenu menu,boolean shouldForce) {
  120. this.menu = menu;
  121. this.force = shouldForce;
  122. }
  123. public void actionPerformed(ActionEvent e) {
  124. MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager();
  125. if(force) {
  126. Container cnt = menu.getParent();
  127. if(cnt != null && cnt instanceof JMenuBar) {
  128. MenuElement me[];
  129. MenuElement subElements[];
  130. subElements = menu.getPopupMenu().getSubElements();
  131. if(subElements.length > 0) {
  132. me = new MenuElement[4];
  133. me[0] = (MenuElement) cnt;
  134. me[1] = (MenuElement) menu;
  135. me[2] = (MenuElement) menu.getPopupMenu();
  136. me[3] = subElements[0];
  137. defaultManager.setSelectedPath(me);
  138. } else {
  139. me = new MenuElement[2];
  140. me[0] = (MenuElement)cnt;
  141. me[1] = menu;
  142. defaultManager.setSelectedPath(me);
  143. }
  144. }
  145. } else {
  146. MenuElement path[] = defaultManager.getSelectedPath();
  147. if(path.length > 0 && path[path.length-1] == menu) {
  148. MenuElement newPath[] = new MenuElement[path.length+1];
  149. System.arraycopy(path,0,newPath,0,path.length);
  150. newPath[path.length] = menu.getPopupMenu();
  151. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  152. }
  153. }
  154. }
  155. public boolean isEnabled() {
  156. return menu.getModel().isEnabled();
  157. }
  158. }
  159. private class PropertyChangeHandler implements PropertyChangeListener {
  160. public void propertyChange(PropertyChangeEvent e) {
  161. String prop = e.getPropertyName();
  162. if(prop.equals(AbstractButton.MNEMONIC_CHANGED_PROPERTY)) {
  163. installKeyboardActions();
  164. }
  165. }
  166. }
  167. private class MouseInputHandler implements MouseInputListener {
  168. public void mouseClicked(MouseEvent e) {}
  169. public void mousePressed(MouseEvent e) {
  170. JMenu menu = (JMenu)menuItem;
  171. if (!menu.isEnabled())
  172. return;
  173. MenuSelectionManager manager =
  174. MenuSelectionManager.defaultManager();
  175. if(menu.isTopLevelMenu()) {
  176. if(menu.isSelected()) {
  177. manager.clearSelectedPath();
  178. } else {
  179. Container cnt = menu.getParent();
  180. if(cnt != null && cnt instanceof JMenuBar) {
  181. MenuElement me[] = new MenuElement[2];
  182. me[0]=(MenuElement)cnt;
  183. me[1]=menu;
  184. manager.setSelectedPath(me);
  185. }
  186. }
  187. }
  188. MenuElement selectedPath[] = manager.getSelectedPath();
  189. if(!(selectedPath.length > 0 &&
  190. selectedPath[selectedPath.length-1] ==
  191. menu.getPopupMenu())) {
  192. if(menu.isTopLevelMenu() ||
  193. menu.getDelay() == 0) {
  194. MenuElement newPath[] = new MenuElement[selectedPath.length+1];
  195. System.arraycopy(selectedPath,0,newPath,0,selectedPath.length);
  196. newPath[selectedPath.length] = menu.getPopupMenu();
  197. manager.setSelectedPath(newPath);
  198. } else {
  199. setupPostTimer(menu);
  200. }
  201. }
  202. }
  203. public void mouseReleased(MouseEvent e) {
  204. JMenu menu = (JMenu)menuItem;
  205. if (!menu.isEnabled())
  206. return;
  207. MenuSelectionManager manager =
  208. MenuSelectionManager.defaultManager();
  209. manager.processMouseEvent(e);
  210. if (!e.isConsumed())
  211. manager.clearSelectedPath();
  212. }
  213. public void mouseEntered(MouseEvent e) {
  214. JMenu menu = (JMenu)menuItem;
  215. if (!menu.isEnabled())
  216. return;
  217. MenuSelectionManager manager =
  218. MenuSelectionManager.defaultManager();
  219. MenuElement selectedPath[] = manager.getSelectedPath();
  220. if (!menu.isTopLevelMenu()) {
  221. if(!(selectedPath.length > 0 &&
  222. selectedPath[selectedPath.length-1] ==
  223. menu.getPopupMenu())) {
  224. if(menu.getDelay() == 0) {
  225. MenuElement newPath[] = new MenuElement[selectedPath.length+2];
  226. System.arraycopy(selectedPath,0,newPath,0,selectedPath.length);
  227. newPath[selectedPath.length] = menuItem;
  228. newPath[selectedPath.length+1] = menu.getPopupMenu();
  229. manager.setSelectedPath(newPath);
  230. } else {
  231. manager.setSelectedPath(getPath());
  232. setupPostTimer(menu);
  233. }
  234. }
  235. } else {
  236. if(selectedPath.length > 0 &&
  237. selectedPath[0] == menu.getParent()) {
  238. MenuElement newPath[] = new MenuElement[3];
  239. // A top level menu's parent is by definition
  240. // a JMenuBar
  241. newPath[0] = (MenuElement)menu.getParent();
  242. newPath[1] = menu;
  243. newPath[2] = menu.getPopupMenu();
  244. manager.setSelectedPath(newPath);
  245. }
  246. }
  247. }
  248. public void mouseExited(MouseEvent e) {
  249. }
  250. public void mouseDragged(MouseEvent e) {
  251. JMenu menu = (JMenu)menuItem;
  252. if (!menu.isEnabled())
  253. return;
  254. MenuSelectionManager.defaultManager().processMouseEvent(e);
  255. }
  256. public void mouseMoved(MouseEvent e) {
  257. }
  258. }
  259. private static class MenuHandler implements MenuListener {
  260. public void menuSelected(MenuEvent e) {}
  261. public void menuDeselected(MenuEvent e) {}
  262. public void menuCanceled(MenuEvent e) {
  263. JMenu m = (JMenu)e.getSource();
  264. MenuSelectionManager manager = MenuSelectionManager.defaultManager();
  265. if(manager.isComponentPartOfCurrentMenu(m))
  266. MenuSelectionManager.defaultManager().clearSelectedPath();
  267. }
  268. }
  269. public class ChangeHandler implements ChangeListener {
  270. public JMenu menu;
  271. public BasicMenuUI ui;
  272. public boolean isSelected = false;
  273. public Component wasFocused;
  274. public ChangeHandler(JMenu m, BasicMenuUI ui) {
  275. menu = m;
  276. this.ui = ui;
  277. validateKeyboardActions(menu.isSelected());
  278. }
  279. public void stateChanged(ChangeEvent e) {
  280. validateKeyboardActions(menu.isSelected());
  281. }
  282. private Component findFocusedComponent(Component c) {
  283. Container parent;
  284. for(parent = c.getParent() ; parent != null ; parent = parent.getParent()) {
  285. if(parent instanceof java.awt.Window)
  286. return ((java.awt.Window)parent).getFocusOwner();
  287. }
  288. return null;
  289. }
  290. private void validateKeyboardActions(boolean sel) {
  291. if(sel != isSelected) {
  292. isSelected = sel;
  293. if(isSelected) {
  294. boolean isRequestFocusEnabled = menu.isRequestFocusEnabled();
  295. wasFocused = findFocusedComponent(menu);
  296. if(!isRequestFocusEnabled)
  297. menu.setRequestFocusEnabled(true);
  298. menu.requestFocus();
  299. if(!isRequestFocusEnabled)
  300. menu.setRequestFocusEnabled(false);
  301. menu.registerKeyboardAction(new CancelAction(),
  302. KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0,false),
  303. JComponent.WHEN_IN_FOCUSED_WINDOW);
  304. menu.registerKeyboardAction(new SelectNextItemAction(),
  305. KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0,false),
  306. JComponent.WHEN_IN_FOCUSED_WINDOW);
  307. menu.registerKeyboardAction(new SelectNextItemAction(),
  308. KeyStroke.getKeyStroke("KP_DOWN"),
  309. JComponent.WHEN_IN_FOCUSED_WINDOW);
  310. menu.registerKeyboardAction(new SelectPreviousItemAction(),
  311. KeyStroke.getKeyStroke(KeyEvent.VK_UP,0,false),
  312. JComponent.WHEN_IN_FOCUSED_WINDOW);
  313. menu.registerKeyboardAction(new SelectPreviousItemAction(),
  314. KeyStroke.getKeyStroke("KP_UP"),
  315. JComponent.WHEN_IN_FOCUSED_WINDOW);
  316. menu.registerKeyboardAction(new SelectParentItemAction(),
  317. KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0,false),
  318. JComponent.WHEN_IN_FOCUSED_WINDOW);
  319. menu.registerKeyboardAction(new SelectParentItemAction(),
  320. KeyStroke.getKeyStroke("KP_LEFT"),
  321. JComponent.WHEN_IN_FOCUSED_WINDOW);
  322. menu.registerKeyboardAction(new SelectChildItemAction(),
  323. KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0,false),
  324. JComponent.WHEN_IN_FOCUSED_WINDOW);
  325. menu.registerKeyboardAction(new SelectChildItemAction(),
  326. KeyStroke.getKeyStroke("KP_RIGHT"),
  327. JComponent.WHEN_IN_FOCUSED_WINDOW);
  328. menu.registerKeyboardAction(new ReturnAction(),
  329. KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0,false),
  330. JComponent.WHEN_IN_FOCUSED_WINDOW);
  331. menu.registerKeyboardAction(new ReturnAction(),
  332. KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0,false),
  333. JComponent.WHEN_IN_FOCUSED_WINDOW);
  334. } else {
  335. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0,false));
  336. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0,false));
  337. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke("KP_DOWN"));
  338. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0,false));
  339. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke("KP_UP"));
  340. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0,false));
  341. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke("KP_LEFT"));
  342. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0,false));
  343. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke("KP_RIGHT"));
  344. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0,false));
  345. menu.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0,false));
  346. if(wasFocused != null) {
  347. if(wasFocused instanceof JComponent) {
  348. JComponent jc = (JComponent) wasFocused;
  349. boolean isRFEnabled = jc.isRequestFocusEnabled();
  350. if(!isRFEnabled)
  351. jc.setRequestFocusEnabled(true);
  352. wasFocused.requestFocus();
  353. if(!isRFEnabled)
  354. jc.setRequestFocusEnabled(false);
  355. } else
  356. wasFocused.requestFocus();
  357. wasFocused = null;
  358. }
  359. }
  360. }
  361. }
  362. private class CancelAction implements ActionListener {
  363. public void actionPerformed(ActionEvent e) {
  364. JMenu menu = (JMenu)menuItem;
  365. if (!menu.isEnabled())
  366. return;
  367. MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath();
  368. if(path.length > 4) { /* PENDING(arnaud) Change this to 2 when a mouse grabber is available for MenuBar */
  369. MenuElement newPath[] = new MenuElement[path.length - 2];
  370. System.arraycopy(path,0,newPath,0,path.length-2);
  371. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  372. } else
  373. MenuSelectionManager.defaultManager().clearSelectedPath();
  374. }
  375. }
  376. private class ReturnAction implements ActionListener {
  377. public void actionPerformed(ActionEvent e) {
  378. JMenu menu = (JMenu)menuItem;
  379. if (!menu.isEnabled())
  380. return;
  381. MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath();
  382. MenuElement lastElement;
  383. if(path.length > 0) {
  384. lastElement = path[path.length-1];
  385. if(lastElement instanceof JMenu) {
  386. MenuElement newPath[] = new MenuElement[path.length+1];
  387. System.arraycopy(path,0,newPath,0,path.length);
  388. newPath[path.length] = ((JMenu)lastElement).getPopupMenu();
  389. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  390. } else if(lastElement instanceof JMenuItem) {
  391. MenuSelectionManager.defaultManager().clearSelectedPath();
  392. ((JMenuItem)lastElement).doClick(0);
  393. ((JMenuItem)lastElement).setArmed(false);
  394. }
  395. }
  396. }
  397. }
  398. private MenuElement nextEnabledChild(MenuElement e[],int fromIndex) {
  399. int i,c;
  400. for(i=fromIndex,c=e.length ; i < c ; i++) {
  401. if (e[i]!=null) {
  402. Component comp = e[i].getComponent();
  403. if(comp != null && comp.isEnabled())
  404. return e[i];
  405. }
  406. }
  407. return null;
  408. }
  409. private MenuElement previousEnabledChild(MenuElement e[],int fromIndex) {
  410. int i;
  411. for(i=fromIndex ; i >= 0 ; i--) {
  412. if (e[i]!=null) {
  413. Component comp = e[i].getComponent();
  414. if(comp != null && comp.isEnabled())
  415. return e[i];
  416. }
  417. }
  418. return null;
  419. }
  420. private class SelectNextItemAction implements ActionListener {
  421. public void actionPerformed(ActionEvent e) {
  422. JMenu menu = (JMenu)menuItem;
  423. if (!menu.isEnabled())
  424. return;
  425. MenuElement currentSelection[] = MenuSelectionManager.defaultManager().getSelectedPath();
  426. if(currentSelection.length > 1) {
  427. MenuElement parent = currentSelection[currentSelection.length-2];
  428. if(parent.getComponent() instanceof JMenu) {
  429. MenuElement childs[];
  430. parent = currentSelection[currentSelection.length-1];
  431. childs = parent.getSubElements();
  432. if(childs.length > 0) {
  433. MenuElement newPath[] = new MenuElement[currentSelection.length+1];
  434. System.arraycopy(currentSelection,0,
  435. newPath,0,currentSelection.length);
  436. newPath[currentSelection.length] = nextEnabledChild(childs,0);
  437. if(newPath[currentSelection.length] != null)
  438. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  439. }
  440. } else {
  441. MenuElement childs[] = parent.getSubElements();
  442. MenuElement nextChild;
  443. int i,c;
  444. for(i=0,c=childs.length;i<c;i++) {
  445. if(childs[i] == currentSelection[currentSelection.length-1]) {
  446. nextChild = nextEnabledChild(childs,i+1);
  447. if(nextChild == null)
  448. nextChild = nextEnabledChild(childs,0);
  449. if(nextChild != null) {
  450. currentSelection[currentSelection.length-1] = nextChild;
  451. MenuSelectionManager.defaultManager().setSelectedPath(currentSelection);
  452. }
  453. break;
  454. }
  455. }
  456. }
  457. }
  458. }
  459. }
  460. private class SelectPreviousItemAction implements ActionListener {
  461. public void actionPerformed(ActionEvent e) {
  462. JMenu menu = (JMenu)menuItem;
  463. if (!menu.isEnabled())
  464. return;
  465. MenuElement currentSelection[] = MenuSelectionManager.defaultManager().getSelectedPath();
  466. if(currentSelection.length > 1) {
  467. MenuElement parent = currentSelection[currentSelection.length-2];
  468. if(parent.getComponent() instanceof JMenu) {
  469. MenuElement childs[];
  470. parent = currentSelection[currentSelection.length-1];
  471. childs = parent.getSubElements();
  472. if(childs.length > 0) {
  473. MenuElement newPath[] = new MenuElement[currentSelection.length+1];
  474. System.arraycopy(currentSelection,0,
  475. newPath,0,currentSelection.length);
  476. newPath[currentSelection.length] = previousEnabledChild(childs,childs.length-1);
  477. if(newPath[currentSelection.length] != null)
  478. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  479. }
  480. } else {
  481. MenuElement childs[] = parent.getSubElements();
  482. MenuElement nextChild;
  483. int i,c;
  484. for(i=0,c=childs.length;i<c;i++) {
  485. if(childs[i] == currentSelection[currentSelection.length-1]) {
  486. nextChild = previousEnabledChild(childs,i-1);
  487. if(nextChild == null)
  488. nextChild = previousEnabledChild(childs,childs.length-1);
  489. if(nextChild != null) {
  490. currentSelection[currentSelection.length-1] = nextChild;
  491. MenuSelectionManager.defaultManager().setSelectedPath(currentSelection);
  492. }
  493. break;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. }
  500. private class SelectParentItemAction implements ActionListener {
  501. public void actionPerformed(ActionEvent e) {
  502. JMenu menu = (JMenu)menuItem;
  503. if (!menu.isEnabled())
  504. return;
  505. MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath();
  506. if(path.length > 3 && path[path.length-3].getComponent() instanceof JMenu &&
  507. !((JMenu)path[path.length-3].getComponent()).isTopLevelMenu()) {
  508. MenuElement newPath[] = new MenuElement[path.length-2];
  509. System.arraycopy(path,0,newPath,0,path.length-2);
  510. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  511. } else if(path.length > 0 && path[0].getComponent() instanceof JMenuBar) {
  512. MenuElement nextMenu=null,popup=null,firstItem=null;
  513. MenuElement tmp[];
  514. int i,c;
  515. if(path.length > 1) {
  516. MenuElement previousElement;
  517. tmp = path[0].getSubElements();
  518. for(i=0,c=tmp.length;i<c;i++) {
  519. if(tmp[i] == path[1]) {
  520. nextMenu = previousEnabledChild(tmp,i-1);
  521. if(nextMenu == null)
  522. nextMenu = previousEnabledChild(tmp,tmp.length-1);
  523. }
  524. }
  525. }
  526. if(nextMenu != null) {
  527. MenuElement newSelection[];
  528. popup = ((JMenu)nextMenu).getPopupMenu();
  529. if(((JMenu)nextMenu).isTopLevelMenu())
  530. firstItem = null;
  531. else {
  532. tmp = popup.getSubElements();
  533. if(tmp.length > 0)
  534. firstItem = nextEnabledChild(tmp,0);
  535. }
  536. if(firstItem != null) {
  537. newSelection = new MenuElement[4];
  538. newSelection[0] = path[0];
  539. newSelection[1] = nextMenu;
  540. newSelection[2] = popup;
  541. newSelection[3] = firstItem;
  542. } else {
  543. newSelection = new MenuElement[3];
  544. newSelection[0] = path[0];
  545. newSelection[1] = nextMenu;
  546. newSelection[2] = popup;
  547. }
  548. MenuSelectionManager.defaultManager().setSelectedPath(newSelection);
  549. }
  550. }
  551. }
  552. }
  553. private class SelectChildItemAction implements ActionListener {
  554. public void actionPerformed(ActionEvent e) {
  555. JMenu menu = (JMenu)menuItem;
  556. if (!menu.isEnabled())
  557. return;
  558. MenuElement path[] = MenuSelectionManager.defaultManager().getSelectedPath();
  559. if(path.length > 0 && path[path.length-1].getComponent().isEnabled() &&
  560. path[path.length-1].getComponent() instanceof JMenu &&
  561. !((JMenu)path[path.length-1].getComponent()).isTopLevelMenu()) {
  562. MenuElement newPath[] = new MenuElement[path.length+2];
  563. MenuElement subElements[];
  564. System.arraycopy(path,0,newPath,0,path.length);
  565. newPath[path.length] = ((JMenu)path[path.length-1].getComponent()).getPopupMenu();
  566. subElements = newPath[path.length].getSubElements();
  567. if(subElements.length > 0) {
  568. newPath[path.length+1] = nextEnabledChild(subElements,0);
  569. MenuSelectionManager.defaultManager().setSelectedPath(newPath);
  570. }
  571. } else if(path.length > 0 && path[0].getComponent() instanceof JMenuBar) {
  572. MenuElement nextMenu=null,popup=null,firstItem=null;
  573. MenuElement tmp[];
  574. int i,c;
  575. if(path.length > 1) {
  576. tmp = path[0].getSubElements();
  577. for(i=0,c=tmp.length;i<c;i++) {
  578. if(tmp[i] == path[1]) {
  579. nextMenu = nextEnabledChild(tmp,i+1);
  580. if(nextMenu == null)
  581. nextMenu = nextEnabledChild(tmp,0);
  582. }
  583. }
  584. }
  585. if(nextMenu != null) {
  586. MenuElement newSelection[];
  587. popup = ((JMenu)nextMenu).getPopupMenu();
  588. if(((JMenu)nextMenu).isTopLevelMenu())
  589. firstItem = null;
  590. else {
  591. tmp = popup.getSubElements();
  592. if(tmp.length > 0)
  593. firstItem = nextEnabledChild(tmp,0);
  594. }
  595. if(firstItem != null) {
  596. newSelection = new MenuElement[4];
  597. newSelection[0] = path[0];
  598. newSelection[1] = nextMenu;
  599. newSelection[2] = popup;
  600. newSelection[3] = firstItem;
  601. } else {
  602. newSelection = new MenuElement[3];
  603. newSelection[0] = path[0];
  604. newSelection[1] = nextMenu;
  605. newSelection[2] = popup;
  606. }
  607. MenuSelectionManager.defaultManager().setSelectedPath(newSelection);
  608. }
  609. }
  610. }
  611. }
  612. }
  613. private class MenuDragMouseHandler implements MenuDragMouseListener {
  614. public void menuDragMouseEntered(MenuDragMouseEvent e) {}
  615. public void menuDragMouseDragged(MenuDragMouseEvent e) {
  616. if (menuItem.isEnabled() == false)
  617. return;
  618. MenuSelectionManager manager = e.getMenuSelectionManager();
  619. MenuElement path[] = e.getPath();
  620. Point p = e.getPoint();
  621. if(p.x >= 0 && p.x < menuItem.getWidth() &&
  622. p.y >= 0 && p.y < menuItem.getHeight()) {
  623. JMenu menu = (JMenu)menuItem;
  624. MenuElement selectedPath[] = manager.getSelectedPath();
  625. if(!(selectedPath.length > 0 &&
  626. selectedPath[selectedPath.length-1] ==
  627. menu.getPopupMenu())) {
  628. if(menu.isTopLevelMenu() ||
  629. menu.getDelay() == 0 ||
  630. e.getID() == MouseEvent.MOUSE_DRAGGED) {
  631. MenuElement newPath[] = new MenuElement[path.length+1];
  632. System.arraycopy(path,0,newPath,0,path.length);
  633. newPath[path.length] = menu.getPopupMenu();
  634. manager.setSelectedPath(newPath);
  635. } else {
  636. manager.setSelectedPath(path);
  637. setupPostTimer(menu);
  638. }
  639. }
  640. } else if(e.getID() == MouseEvent.MOUSE_RELEASED) {
  641. Component comp = manager.componentForPoint(e.getComponent(), e.getPoint());
  642. if (comp == null)
  643. manager.clearSelectedPath();
  644. }
  645. }
  646. public void menuDragMouseExited(MenuDragMouseEvent e) {}
  647. public void menuDragMouseReleased(MenuDragMouseEvent e) {}
  648. }
  649. private class MenuKeyHandler implements MenuKeyListener {
  650. public void menuKeyTyped(MenuKeyEvent e) { }
  651. public void menuKeyPressed(MenuKeyEvent e) {}
  652. public void menuKeyReleased(MenuKeyEvent e) {}
  653. private int lower(int ascii) {
  654. if(ascii >= 'A' && ascii <= 'Z')
  655. return ascii + 'a' - 'A';
  656. else
  657. return ascii;
  658. }
  659. }
  660. }