1 /* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.netbeans.jemmy.drivers.menus; 26 27 import java.awt.event.KeyEvent; 28 29 import javax.swing.JMenu; 30 import javax.swing.JMenuBar; 31 import javax.swing.JMenuItem; 32 import javax.swing.MenuElement; 33 34 import org.netbeans.jemmy.JemmyException; 35 import org.netbeans.jemmy.Timeout; 36 import org.netbeans.jemmy.TimeoutExpiredException; 37 import org.netbeans.jemmy.drivers.DescriptablePathChooser; 38 import org.netbeans.jemmy.drivers.MenuDriver; 39 import org.netbeans.jemmy.drivers.PathChooser; 40 import org.netbeans.jemmy.drivers.input.RobotDriver; 41 import org.netbeans.jemmy.operators.ComponentOperator; 42 import org.netbeans.jemmy.operators.Operator; 43 44 /** 45 * 46 * @author shura 47 */ 48 public class AppleMenuDriver extends RobotDriver implements MenuDriver { 49 50 /** 51 * Creates a new instance of AppleMenuDriver 52 */ AppleMenuDriver()53 public AppleMenuDriver() { 54 super(new Timeout("apple.system.menu.delay", 100), 55 new String[]{"org.netbeans.jemmy.operators.JMenuBarOperator"}); 56 } 57 58 @Override pushMenu(ComponentOperator oper, PathChooser chooser)59 public Object pushMenu(ComponentOperator oper, PathChooser chooser) { 60 Timeout maxTime = oper.getTimeouts().create("ComponentOperator.WaitComponentTimeout"); 61 JMenuBar bar = (JMenuBar) (oper.getSource()); 62 activateMenu(bar); 63 MenuElement menuObject; 64 maxTime.start(); 65 while (!chooser.checkPathComponent(0, (menuObject = getSelectedElement(bar)))) { 66 pressKey(KeyEvent.VK_RIGHT, 0); 67 releaseKey(KeyEvent.VK_RIGHT, 0); 68 if (maxTime.expired()) { 69 throw (new TimeoutExpiredException("AppleMenuDriver: can not find an appropriate menu!")); 70 } 71 } 72 for (int depth = 1; depth < chooser.getDepth(); depth++) { 73 // TODO - wait for menu item 74 int elementIndex = getDesiredElementIndex(menuObject, chooser, depth); 75 if (elementIndex == -1) { 76 throw (new JemmyException("Unable to find menu (menuitem): " + ((DescriptablePathChooser) chooser).getDescription())); 77 } 78 for (int i = ((depth == 1) ? 0 : 1); i <= elementIndex; i++) { 79 pressKey(KeyEvent.VK_DOWN, 0); 80 releaseKey(KeyEvent.VK_DOWN, 0); 81 } 82 if (depth == chooser.getDepth() - 1) { 83 pressKey(KeyEvent.VK_ENTER, 0); 84 releaseKey(KeyEvent.VK_ENTER, 0); 85 return null; 86 } else { 87 pressKey(KeyEvent.VK_RIGHT, 0); 88 releaseKey(KeyEvent.VK_RIGHT, 0); 89 menuObject = menuObject.getSubElements()[0].getSubElements()[elementIndex]; 90 } 91 } 92 return menuObject; 93 } 94 activateMenu(JMenuBar bar)95 private void activateMenu(JMenuBar bar) { 96 if (getSelectedElement(bar) == null) { 97 tryToActivate(); 98 if (getSelectedElement(bar) == null) { 99 tryToActivate(); 100 } 101 } 102 } 103 tryToActivate()104 private void tryToActivate() { 105 moveMouse(0, 0); 106 pressMouse(Operator.getDefaultMouseButton(), 0); 107 releaseMouse(Operator.getDefaultMouseButton(), 0); 108 pressKey(KeyEvent.VK_RIGHT, 0); 109 releaseKey(KeyEvent.VK_RIGHT, 0); 110 pressKey(KeyEvent.VK_RIGHT, 0); 111 releaseKey(KeyEvent.VK_RIGHT, 0); 112 } 113 getSelectedElement(MenuElement bar)114 private static MenuElement getSelectedElement(MenuElement bar) { 115 MenuElement[] subElements = bar.getSubElements(); 116 for (MenuElement subElement : subElements) { 117 if (subElement instanceof JMenu 118 && ((JMenu) subElement).isSelected()) { 119 return subElement; 120 } else if (subElement instanceof JMenuItem 121 && ((JMenuItem) subElement).isSelected()) { 122 return subElement; 123 } 124 } 125 return null; 126 } 127 getDesiredElementIndex(MenuElement bar, PathChooser chooser, int depth)128 private static int getDesiredElementIndex(MenuElement bar, PathChooser chooser, int depth) { 129 MenuElement[] subElements = bar.getSubElements()[0].getSubElements(); 130 int realIndex = 0; 131 for (MenuElement subElement : subElements) { 132 // do not count invisible and disabled menu items 133 if (subElement instanceof JMenuItem && ((JMenuItem) subElement).isVisible() && ((JMenuItem) subElement).isEnabled()) { 134 if (chooser.checkPathComponent(depth, subElement)) { 135 return realIndex; 136 } 137 realIndex++; 138 } 139 } 140 return -1; 141 } 142 } 143