001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * DiagramElementAction.java
044: *
045: * Created on February 10, 2005, 2:13 PM
046: *
047: * This Class is derived from jelly DiagramElementAction.java
048: */
049:
050: package org.netbeans.test.umllib.actions;
051:
052: import java.awt.event.InputEvent;
053: import java.awt.event.KeyEvent;
054: import org.netbeans.jellytools.JellyVersion;
055: import org.netbeans.jellytools.MainWindowOperator;
056: import org.netbeans.jellytools.actions.Action.Shortcut;
057: import org.netbeans.jemmy.EventTool;
058: import org.netbeans.jemmy.JemmyException;
059: import org.netbeans.jemmy.JemmyProperties;
060: import org.netbeans.jemmy.Timeout;
061: import org.netbeans.jemmy.Timeouts;
062: import org.netbeans.jemmy.drivers.input.KeyRobotDriver;
063: import org.netbeans.jemmy.drivers.input.MouseRobotDriver;
064: import org.netbeans.jemmy.operators.JPopupMenuOperator;
065: import org.netbeans.jemmy.operators.Operator;
066: import org.netbeans.jemmy.operators.Operator.DefaultStringComparator;
067: import org.netbeans.jemmy.operators.Operator.StringComparator;
068: import org.netbeans.test.umllib.actions.Actionable;
069:
070: /**
071: * This is basic class for all diagram actions. Derived from
072: * corresponding jelly <CODE>Action</CODE> class
073: * @author Alexei Mokeev
074: */
075: public class DiagramElementAction {
076: /** through menu action performing mode */
077: public static final int MENU_MODE = 0;
078: /** through popup menu action performing mode */
079: public static final int POPUP_MODE = 1;
080: /** through API action performing mode */
081: public static final int API_MODE = 2;
082: /** through shortcut action performing mode */
083: public static final int SHORTCUT_MODE = 3;
084:
085: /** sleep time between elements selection and action execution */
086: protected static final long SELECTION_WAIT_TIME = 300;
087: /** sleep time after action execution */
088: protected static final long AFTER_ACTION_WAIT_TIME = 0;
089: /** sleep time between sequence of shortcuts */
090: protected static final long WAIT_AFTER_SHORTCUT_TIMEOUT = 0;
091:
092: private static final int sequence[][] = {
093: { MENU_MODE, POPUP_MODE, SHORTCUT_MODE, API_MODE },
094: { POPUP_MODE, MENU_MODE, SHORTCUT_MODE, API_MODE },
095: { API_MODE, POPUP_MODE, MENU_MODE, SHORTCUT_MODE },
096: { SHORTCUT_MODE, POPUP_MODE, MENU_MODE, API_MODE } };
097:
098: /** menu path of current action or null when MENU_MODE is not supported */
099: protected String menuPath;
100: /** popup menu path of current action or null when POPUP_MODE is not supported */
101: protected String popupPath;
102: /** SystemDiagramElementAction class of current action or null when API_MODE is not supported */
103: protected Class systemActionClass;
104: /** array of shortcuts of current action or null when SHORTCUT_MODE is not supported */
105: protected Shortcut[] shortcuts;
106:
107: /** Comparator used as default for all DiagramElementAction instances. It is set in static clause. */
108: private static StringComparator defaultComparator;
109: /** Comparator used for this action instance. */
110: private StringComparator comparator;
111:
112: /** creates new DiagramElementAction instance without API_MODE and SHORTCUT_MODE support
113: * @param menuPath action path in main menu (use null value if menu mode is not supported)
114: * @param popupPath action path in popup menu (use null value if popup mode shell is not supported) */
115: public DiagramElementAction(String menuPath, String popupPath) {
116: this (menuPath, popupPath, null, (Shortcut[]) null);
117: }
118:
119: /** creates new DiagramElementAction instance without SHORTCUT_MODE support
120: * @param menuPath action path in main menu (use null value if menu mode is not supported)
121: * @param popupPath action path in popup menu (use null value if popup mode is not supported)
122: * @param systemActionClass String class name of SystemDiagramElementAction (use null value if API mode is not supported) */
123: public DiagramElementAction(String menuPath, String popupPath,
124: String systemActionClass) {
125: this (menuPath, popupPath, systemActionClass, (Shortcut[]) null);
126: }
127:
128: /** creates new DiagramElementAction instance without API_MODE support
129: * @param shortcuts array of Shortcut instances (use null value if shorcut mode is not supported)
130: * @param menuPath action path in main menu (use null value if menu mode is not supported)
131: * @param popupPath action path in popup menu (use null value if popup mode shell is not supported) */
132: public DiagramElementAction(String menuPath, String popupPath,
133: Shortcut[] shortcuts) {
134: this (menuPath, popupPath, null, shortcuts);
135: }
136:
137: /** creates new DiagramElementAction instance without API_MODE support
138: * @param shortcut Shortcut (use null value if menu mode is not supported)
139: * @param menuPath action path in main menu (use null value if menu mode is not supported)
140: * @param popupPath action path in popup menu (use null value if popup mode shell is not supported) */
141: public DiagramElementAction(String menuPath, String popupPath,
142: Shortcut shortcut) {
143: this (menuPath, popupPath, null, new Shortcut[] { shortcut });
144: }
145:
146: /** creates new DiagramElementAction instance
147: * @param shortcuts array of Shortcut instances (use null value if shortcut mode is not supported)
148: * @param menuPath action path in main menu (use null value if menu mode is not supported)
149: * @param popupPath action path in popup menu (use null value if popup mode is not supported)
150: * @param systemActionClass String class name of SystemDiagramElementAction (use null value if API mode is not supported) */
151: public DiagramElementAction(String menuPath, String popupPath,
152: String systemActionClass, Shortcut[] shortcuts) {
153: this .menuPath = menuPath;
154: this .popupPath = popupPath;
155: if (systemActionClass == null) {
156: this .systemActionClass = null;
157: } else
158: try {
159: this .systemActionClass = Class
160: .forName(systemActionClass);
161: } catch (ClassNotFoundException e) {
162: this .systemActionClass = null;
163: }
164: this .shortcuts = shortcuts;
165: }
166:
167: /** creates new DiagramElementAction instance
168: * @param shortcut Shortcut String (use null value if menu mode is not supported)
169: * @param menuPath action path in main menu (use null value if menu mode is not supported)
170: * @param popupPath action path in popup menu (use null value if popup mode is not supported)
171: * @param systemActionClass String class name of SystemDiagramElementAction (use null value if API mode is not supported) */
172: public DiagramElementAction(String menuPath, String popupPath,
173: String systemActionClass, Shortcut shortcut) {
174: this (menuPath, popupPath, systemActionClass,
175: new Shortcut[] { shortcut });
176: }
177:
178: static {
179: // Checks if you run on correct jemmy version. Writes message to jemmy log if not.
180: JellyVersion.checkJemmyVersion();
181:
182: if (JemmyProperties
183: .getCurrentProperty("DiagramElementAction.DefaultMode") == null)
184: JemmyProperties.setCurrentProperty(
185: "DiagramElementAction.DefaultMode", new Integer(
186: POPUP_MODE));
187: Timeouts.initDefault(
188: "DiagramElementAction.WaitAfterShortcutTimeout",
189: WAIT_AFTER_SHORTCUT_TIMEOUT);
190: // Set case sensitive comparator as default because of
191: // very often clash between Cut and Execute menu items.
192: // Substring criterion is set according to default string comparator
193: boolean compareExactly = !Operator.getDefaultStringComparator()
194: .equals("abc", "a"); // NOI18N
195: defaultComparator = new DefaultStringComparator(compareExactly,
196: true);
197: }
198:
199: private void perform(int mode) {
200: switch (mode) {
201: // case POPUP_MODE: performPopup(); break;
202: case MENU_MODE:
203: performMenu();
204: break;
205: // case API_MODE: performAPI(); break;
206: // case SHORTCUT_MODE: performShortcut(); break;
207: default:
208: throw new IllegalArgumentException(
209: "Wrong DiagramElementAction.MODE");
210: }
211: }
212:
213: /** Creates a new instance of DiagramElementAction */
214: public DiagramElementAction() {
215: }
216:
217: /** performs action through main menu
218: * @throws UnsupportedOperationException when action does not support menu mode */
219: public void performMenu() {
220: if (menuPath == null) {
221: throw new UnsupportedOperationException(getClass()
222: .toString()
223: + " does not define menu path");
224: }
225: // Need to wait here to be more reliable.
226: // TBD - It can be removed after issue 23663 is solved.
227: new EventTool().waitNoEvent(500);
228: MainWindowOperator.getDefault().menuBar().pushMenu(menuPath,
229: "|", getComparator());
230: try {
231: Thread.sleep(AFTER_ACTION_WAIT_TIME);
232: } catch (Exception e) {
233: throw new JemmyException("Sleeping interrupted", e);
234: }
235: }
236:
237: public void performMenu(Actionable element) {
238: performMenu(new Actionable[] { element });
239: }
240:
241: /** performs action through main menu
242: * @param elements elements to be action performed on
243: * @throws UnsupportedOperationException when action does not support shortcut mode */
244: public void performMenu(Actionable[] elements) {
245: if (menuPath == null) {
246: throw new UnsupportedOperationException(getClass()
247: .toString()
248: + " does not define menu path");
249: }
250: //Need to check that all of them are from the same diagram
251: elements[0].select();
252:
253: for (int i = 1; i < elements.length; i++) {
254: elements[i].addToSelection();
255: try {
256: Thread.sleep(SELECTION_WAIT_TIME);
257: } catch (Exception e) {
258: throw new JemmyException("Sleeping interrupted", e);
259: }
260: }
261:
262: new EventTool().waitNoEvent(500);
263: performMenu();
264: }
265:
266: /** performs action through popup menu
267: * @param element node to be action performed on
268: * @throws UnsupportedOperationException when action does not support popup mode */
269: public void performPopup(Actionable element) {
270: performPopup(new Actionable[] { element });
271: }
272:
273: /** performs action through popup menu
274: * @param elements elements to be action performed on
275: * @throws UnsupportedOperationException when action does not support popup mode */
276: public void performPopup(Actionable[] elements) {
277: if (popupPath == null) {
278: throw new UnsupportedOperationException(getClass()
279: .toString()
280: + " does not define popup path");
281: }
282: //Need to check that all of them are from the same diagram
283: elements[0].select();
284:
285: for (int i = 1; i < elements.length; i++) {
286: elements[i].addToSelection();
287: try {
288: Thread.sleep(SELECTION_WAIT_TIME);
289: } catch (Exception e) {
290: throw new JemmyException("Sleeping interrupted", e);
291: }
292: }
293:
294: new EventTool().waitNoEvent(500);
295:
296: JPopupMenuOperator popup = elements[0].getPopup();
297: popup.pushMenu(popupPath, "|", getComparator());
298: try {
299: Thread.sleep(AFTER_ACTION_WAIT_TIME);
300: } catch (Exception e) {
301: throw new JemmyException("Sleeping interrupted", e);
302: }
303:
304: }
305:
306: /** performs action through popup menu
307: * @param element node to be action performed on
308: * @throws UnsupportedOperationException when action does not support popup mode */
309: public void performPopupNoBlock(Actionable element) {
310: performPopupNoBlock(new Actionable[] { element });
311: }
312:
313: /** performs action through popup menu
314: * @param elements elements to be action performed on
315: * @throws UnsupportedOperationException when action does not support popup mode */
316: public void performPopupNoBlock(Actionable[] elements) {
317: if (popupPath == null) {
318: throw new UnsupportedOperationException(getClass()
319: .toString()
320: + " does not define popup path");
321: }
322: //Need to check that all of them are from the same diagram
323: elements[0].select();
324:
325: for (int i = 1; i < elements.length; i++) {
326: elements[i].addToSelection();
327: try {
328: Thread.sleep(SELECTION_WAIT_TIME);
329: } catch (Exception e) {
330: throw new JemmyException("Sleeping interrupted", e);
331: }
332: }
333:
334: new EventTool().waitNoEvent(500);
335:
336: JPopupMenuOperator popup = elements[0].getPopup();
337: popup.pushMenuNoBlock(popupPath, "|", getComparator());
338: try {
339: Thread.sleep(AFTER_ACTION_WAIT_TIME);
340: } catch (Exception e) {
341: throw new JemmyException("Sleeping interrupted", e);
342: }
343:
344: }
345:
346: /** performs action through shortcut
347: * @throws UnsupportedOperationException if no shortcut is defined */
348: public void performShortcut() {
349: if (shortcuts == null) {
350: throw new UnsupportedOperationException(getClass()
351: .toString()
352: + " does not define shortcut");
353: }
354: for (int i = 0; i < shortcuts.length; i++) {
355: new KeyRobotDriver(new Timeout("autoDelay", 100))
356: .pushKey(
357: null,
358: shortcuts[i].getKeyCode(),
359: shortcuts[i].getKeyModifiers(),
360: JemmyProperties
361: .getCurrentTimeouts()
362: .create(
363: "ComponentOperator.PushKeyTimeout"));
364: JemmyProperties.getProperties().getTimeouts().sleep(
365: "DiagramElementAction.WaitAfterShortcutTimeout");
366: }
367: try {
368: Thread.sleep(AFTER_ACTION_WAIT_TIME);
369: } catch (Exception e) {
370: throw new JemmyException("Sleeping interrupted", e);
371: }
372: }
373:
374: /** performs action through shortcut
375: * @param element node to be action performed on
376: * @throws UnsupportedOperationException when action does not support shortcut mode */
377: public void performShortcut(Actionable element) {
378: performShortcut(new Actionable[] { element });
379: }
380:
381: /** performs action through shortcut
382: * @param elements elements to be action performed on
383: * @throws UnsupportedOperationException when action does not support shortcut mode */
384: public void performShortcut(Actionable[] elements) {
385: if (shortcuts == null) {
386: throw new UnsupportedOperationException(getClass()
387: .toString()
388: + " does not define shortcut");
389: }
390: //Need to check that all of them are from the same diagram
391: elements[0].select();
392:
393: for (int i = 1; i < elements.length; i++) {
394: elements[i].addToSelection();
395: try {
396: Thread.sleep(SELECTION_WAIT_TIME);
397: } catch (Exception e) {
398: throw new JemmyException("Sleeping interrupted", e);
399: }
400: }
401:
402: new EventTool().waitNoEvent(500);
403: performShortcut();
404: }
405:
406: /** Sets comparator fot this action. Comparator is used for all actions
407: * after this method is called.
408: * @param comparator new comparator to be set (e.g.
409: * new Operator.DefaultStringComparator(true, true);
410: * to search string item exactly and case sensitive)
411: */
412: public void setComparator(StringComparator comparator) {
413: this .comparator = comparator;
414: }
415:
416: /** Gets comparator set for this action instance.
417: * @return comparator set for this action instance.
418: */
419: public StringComparator getComparator() {
420: if (comparator == null) {
421: comparator = defaultComparator;
422: }
423: return comparator;
424: }
425: }
|