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: package org.netbeans.modules.visualweb.gravy;
043:
044: import java.awt.Component;
045: import java.awt.Container;
046: import java.io.PrintStream;
047: import java.util.ArrayList;
048:
049: import javax.swing.*;
050: import javax.swing.event.ChangeListener;
051: import javax.swing.event.ChangeEvent;
052:
053: import org.netbeans.jemmy.ComponentChooser;
054: import org.netbeans.jemmy.JemmyProperties;
055: import org.netbeans.jemmy.JemmyException;
056: import org.netbeans.jemmy.Waitable;
057: import org.netbeans.jemmy.Waiter;
058:
059: import org.netbeans.jemmy.operators.ContainerOperator;
060: import org.netbeans.jemmy.operators.ComponentOperator;
061: import org.netbeans.jemmy.operators.DialogOperator;
062: import org.netbeans.jemmy.operators.JButtonOperator;
063: import org.netbeans.jemmy.operators.JComponentOperator.JComponentByTipFinder;
064: import org.netbeans.jemmy.operators.JFrameOperator;
065: import org.netbeans.jemmy.operators.JPopupMenuOperator;
066: import org.openide.awt.Toolbar;
067:
068: import org.openide.awt.StatusDisplayer;
069:
070: /**
071: *
072: * @author shura
073: */
074: public class MainWindowOperator extends JFrameOperator {
075:
076: JButtonOperator deployButton;
077:
078: /** Creates a new instance of MainWindowOperator */
079: public MainWindowOperator() {
080: super ((JFrame) RaveWindowOperator.getDefaultRave().getSource());
081: copyEnvironment(RaveWindowOperator.getDefaultRave());
082: }
083:
084: /** Pushes Save All Button in Main Toolbar
085: */
086: public void saveAll() {
087: new JButtonOperator(this , new JComponentByTipFinder("Save All"))
088: .push();
089: }
090:
091: /** Pushes Deploy button from Main Toolbar and waits some timeout
092: */
093: public DeploymentDialogOperator deploy() {
094: btDeploy().push();
095: DeploymentDialogOperator dlg = null;
096: long oldWaitTime = Util.getMainWindow().getTimeouts()
097: .getTimeout("DialogWaiter.WaitDialogTimeout");
098: try {
099: Util.getMainWindow().getTimeouts().setTimeout(
100: "DialogWaiter.WaitDialogTimeout", 100000);
101: dlg = new DeploymentDialogOperator();
102: } catch (Exception e) {
103: e.printStackTrace();
104: Util.getMainWindow().getTimeouts().setTimeout(
105: "DialogWaiter.WaitDialogTimeout", oldWaitTime);
106: }
107: return (dlg);
108: }
109:
110: /** Deploy project and waits until deployment completed */
111: public void deployProject() {
112: DeploymentDialogOperator dlg = deploy();
113: dlg.setAutoHide(false);
114: dlg.waitCompleted();
115: Util.wait(1000);
116: dlg.close();
117: }
118:
119: /** Pushes deploy button from Main Toolbar
120: */
121: public JButtonOperator btDeploy() {
122: if (deployButton == null) {
123: deployButton = new JButtonOperator(
124: this ,
125: new JComponentByTipFinder(
126: Bundle
127: .getStringTrimmed(
128: "org.netbeans.modules.project.ui.actions.Bundle",
129: "LBL_RunMainProjectAction_Name")));
130: deployButton.getTimeouts().setTimeout(
131: "ComponentOperator.WaitStateTimeout", 60000);
132: }
133: return (deployButton);
134: }
135:
136: private static StatusTextTracer statusTextTracer = null;
137:
138: /** Returns text from status bar.
139: * @return currently displayed text
140: */
141: public String getStatusText() {
142: return org.openide.awt.StatusDisplayer.getDefault()
143: .getStatusText();
144: }
145:
146: /** Sets given text to main window's status bar.
147: * @param newStatusText string to be displayed in status bar
148: */
149: public void setStatusText(String newStatusText) {
150: org.openide.awt.StatusDisplayer.getDefault().setStatusText(
151: newStatusText);
152: }
153:
154: /** Returns singleton instance of StatusTextTracer.
155: * @return singleton instance of StatusTextTracer
156: */
157: public synchronized StatusTextTracer getStatusTextTracer() {
158: if (statusTextTracer == null) {
159: statusTextTracer = new StatusTextTracer();
160: }
161: return statusTextTracer;
162: }
163:
164: /** Waits until given text appears in the main window status bar.
165: * If you want to trace status messages during an operation is proceed,
166: * use {@link StatusTextTracer}.
167: * @param text a text to wait for
168: */
169: public void waitStatusText(final String text) {
170: getStatusTextTracer().start();
171: try {
172: // not wait in case status text was already printed out
173: if (!getComparator().equals(getStatusText(), text)) {
174: getStatusTextTracer().waitText(text);
175: }
176: } finally {
177: getStatusTextTracer().stop();
178: }
179: }
180:
181: /** Class to trace messages printed to status bar of the Main Window.
182: * <p>
183: * Usage:<br>
184: * <pre>
185: * MainWindowOperator.StatusTextTracer stt = MainWindowOperator.getDefault().getStatusTextTracer();
186: * // start tracing
187: * stt.start();
188: * // compile action will produce at least two messages: "Compiling ...",
189: * // "Finished ..."
190: * new CompileAction().performAPI();
191: *
192: * // waits for "Compiling" status text
193: * stt.waitText("Compiling");
194: * // waits for "Finished" status text
195: * stt.waitText("Finished");
196: *
197: * // order is not significant => following works as well
198: * stt.waitText("Finished");
199: * stt.waitText("Compiling");
200: *
201: * // to be order significant, set removedCompared parameter to true
202: * stt.waitText("Compiling", true);
203: * stt.waitText("Finished", true);
204: *
205: * // history was removed by above methods => need to produce a new messages
206: * new CompileAction().performAPI();
207: *
208: * // order is significant if removedCompared parameter is true =>
209: * // => following fails because Finished is shown as second
210: * stt.waitText("Finished", true);
211: * stt.waitText("Compiling", true);
212: *
213: * // stop tracing
214: * stt.stop();
215: * </pre>
216: */
217: public class StatusTextTracer implements ChangeListener {
218: /** List of all messages */
219: private ArrayList statusTextHistory;
220:
221: /** Creates new instance. */
222: public StatusTextTracer() {
223: this .statusTextHistory = new ArrayList();
224: }
225:
226: /** Starts to register all status messages into history array.
227: * Exactly, it adds the listener to org.openide.awt.StatusDisplayer.
228: * It clears possible previously filled history array before.
229: */
230: public void start() {
231: stop();
232: clear();
233: StatusDisplayer.getDefault().addChangeListener(this );
234: }
235:
236: /** Stops registering of status messages. Exactly, it removes the
237: * listener from org.openide.awt.StatusDisplayer.
238: */
239: public void stop() {
240: StatusDisplayer.getDefault().removeChangeListener(this );
241: }
242:
243: /** Called when status text was changed. It adds status text to history
244: * array.
245: * @param evt change event - not used
246: */
247: public void stateChanged(ChangeEvent evt) {
248: synchronized (this ) {
249: statusTextHistory.add(StatusDisplayer.getDefault()
250: .getStatusText());
251: // print message to jemmy output stream
252: JemmyProperties.getCurrentOutput().printTrace(
253: "Status text changed to: \""
254: + StatusDisplayer.getDefault()
255: .getStatusText() + "\"");
256: }
257: }
258:
259: /** Clears status text history array. */
260: public void clear() {
261: synchronized (this ) {
262: statusTextHistory.clear();
263: }
264: }
265:
266: /** Checks whether given text equals to any of messages in the history
267: * array. Comparator of this MainWindowOperator instance is used.
268: * If <tt>removeCompared</tt> parameter is set to <tt>true</tt>,
269: * messages already compared are removed from history array. Otherwise
270: * messages are not removed until {@link #clear} or {@link #start} are
271: * called.
272: * @param text a text to be compared
273: * @param removeCompared whether to remove already compared messages from
274: * history array
275: * @return true if text matches any of messages in the history array;
276: * false otherwise
277: */
278: public boolean contains(String text, boolean removeCompared) {
279: StringComparator comparator = getComparator();
280: synchronized (this ) {
281: if (removeCompared) {
282: while (!statusTextHistory.isEmpty()) {
283: String status = (String) statusTextHistory
284: .remove(0);
285: if (comparator.equals(status, text)) {
286: return true;
287: }
288: }
289: } else {
290: for (int i = 0; i < statusTextHistory.size(); i++) {
291: if (comparator
292: .equals((String) statusTextHistory
293: .get(i), text)) {
294: return true;
295: }
296: }
297: }
298: return false;
299: }
300: }
301:
302: /** Waits for text to be shown in the Main Window status bar not
303: * removing any message from history.
304: * Comparator of this MainWindowOperator instance is used.
305: * It throws TimeoutExpiredException if timeout expires.
306: * @param text a text to wait for
307: */
308: public void waitText(final String text) {
309: waitText(text, false);
310: }
311:
312: /** Waits for text to be shown in the Main Window status bar.
313: * Comparator of this MainWindowOperator instance is used.
314: * If <tt>removeCompared</tt> parameter is set to <tt>true</tt>,
315: * messages already compared are removed from history array. It satisfies
316: * that order of messages is significant when this method is called
317: * more than once.
318: * If <tt>removeCompared</tt> parameter is set to <tt>false</tt>,
319: * messages are not removed until {@link #clear} or {@link #start} are
320: * called and its order is not taken into account.
321: * @param text a text to wait for
322: * @param removeCompared whether to remove already compared messages from
323: * history array
324: */
325: public void waitText(final String text,
326: final boolean removeCompared) {
327: try {
328: new Waiter(new Waitable() {
329: public Object actionProduced(Object anObject) {
330: return contains(text, removeCompared) ? Boolean.TRUE
331: : null;
332: }
333:
334: public String getDescription() {
335: return ("Wait status text equals to " + text);
336: }
337: }).waitAction(null);
338: } catch (InterruptedException e) {
339: throw new JemmyException("Interrupted.", e);
340: }
341: }
342:
343: /** Calls {@link #stop} at the end of life cycle of this class. */
344: public void finalize() {
345: stop();
346: }
347:
348: /** Returns list of elements collected from the moment method
349: * {@link #start} was called. Remember, if <tt>removeCompared</tt>
350: * parameter is set to <tt>true</tt> in some of methods,
351: * messages already compared are removed from history array.
352: * @return ArrayList of elements representing status text messages
353: */
354: public ArrayList getStatusTextHistory() {
355: return statusTextHistory;
356: }
357:
358: /** Prints list of elements collected from the moment method
359: * {@link #start} was called. Remember, if <tt>removeCompared</tt>
360: * parameter is set to <tt>true</tt> in some of methods,
361: * messages already compared are removed from history array.
362: * @param outputPrintStream stream to print output in
363: */
364: public void printStatusTextHistory(PrintStream outputPrintStream) {
365: for (int i = 0; i < statusTextHistory.size(); i++) {
366: outputPrintStream.println(statusTextHistory.get(i)
367: .toString());
368: }
369: }
370: }
371:
372: /***************** methods for toolbars manipulation *******************/
373:
374: /** Returns ContainerOperator representing index-th floating toolbar in
375: * IDE main window. Toolbars are NOT indexed from left to right.
376: * @param index index of toolbar to find
377: * @return ContainerOperator instance representing a toolbar
378: */
379: public ContainerOperator getToolbar(int index) {
380: ComponentChooser chooser = new ToolbarChooser();
381: return new ContainerOperator((Container) waitComponent(
382: (Container) getSource(), chooser, index));
383: }
384:
385: /** Returns ContainerOperator representing floating toolbar with given name.
386: * @param toolbarName toolbar's display name. It is shown in its tooltip.
387: * @return ContainerOperator instance representing a toolbar
388: */
389: public ContainerOperator getToolbar(String toolbarName) {
390: ComponentChooser chooser = new ToolbarChooser(toolbarName,
391: getComparator());
392: return new ContainerOperator((Container) waitComponent(
393: (Container) getSource(), chooser));
394: }
395:
396: /** Returns number of toolbars currently shown in IDE.
397: * @return number of toolbars
398: */
399: public int getToolbarCount() {
400: ToolbarChooser chooser = new ToolbarChooser(
401: "Non sense name - @#$%^&*", //NOI18N
402: getComparator());
403: findComponent((Container) getSource(), chooser);
404: return chooser.getCount();
405: }
406:
407: /** Returns display name of toolbar with given index. Toolbars are NOT
408: * indexed from left to right.
409: * @param index index of toolbar
410: * @return display name of toolbar
411: */
412: public String getToolbarName(int index) {
413: return ((Toolbar) getToolbar(index).getSource())
414: .getDisplayName();
415: }
416:
417: /** Return JButtonOperator representing a toolbar button found by given
418: * tooltip within given toolbar operator.
419: * @param toolbarOper ContainerOperator of a toolbar.
420: * Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
421: * to obtain an operator.
422: * @param buttonTooltip tooltip of toolbar button
423: * @return JButtonOperator instance of found toolbar button
424: */
425: public JButtonOperator getToolbarButton(
426: ContainerOperator toolbarOper, String buttonTooltip) {
427: ToolbarButtonChooser chooser = new ToolbarButtonChooser(
428: buttonTooltip, getComparator());
429: return new JButtonOperator(JButtonOperator.waitJButton(
430: (Container) toolbarOper.getSource(), chooser));
431: }
432:
433: /** Return JButtonOperator representing index-th toolbar button within given
434: * toolbar operator.
435: * @param toolbarOper ContainerOperator of a toolbar.
436: * Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
437: * to obtain an operator.
438: * @param index index of toolbar button to find
439: * @return JButtonOperator instance of found toolbar button
440: */
441: public JButtonOperator getToolbarButton(
442: ContainerOperator toolbarOper, int index) {
443: return new JButtonOperator(toolbarOper, index);
444: }
445:
446: /** Pushes popup menu on toolbars. It doesn't matter on which toolbar it is
447: * invoked, everytime it is the same. That's why popup menu is invoked on
448: * the right side of toolbar with index 0.
449: * @param popupPath path to menu item (e.g. "Edit")
450: */
451: public void pushToolbarPopupMenu(String popupPath) {
452: ContainerOperator contOper = getToolbar(0);
453: contOper.clickForPopup(contOper.getWidth() - 1, contOper
454: .getHeight() / 2);
455: new JPopupMenuOperator().pushMenu(popupPath, "|");
456: }
457:
458: /** Pushes popup menu on toolbars - no block further execution.
459: * It doesn't matter on which toolbar it is
460: * invoked, everytime it is the same. That's why popup menu is invoked on
461: * the right side of toolbar with index 0.
462: * @param popupPath path to menu item (e.g. "Save Configuration...")
463: */
464: public void pushToolbarPopupMenuNoBlock(String popupPath) {
465: ContainerOperator contOper = getToolbar(0);
466: contOper.clickForPopup(contOper.getWidth() - 1, contOper
467: .getHeight() / 2);
468: new JPopupMenuOperator().pushMenuNoBlock(popupPath, "|");
469: }
470:
471: /** Drags a toolbar to a new position determined by [x, y] relatively.
472: * @param toolbarOper ContainerOperator of a toolbar.
473: * Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
474: * to obtain an operator.
475: * @param x relative move along x direction
476: * @param y relative move along y direction
477: */
478: public void dragNDropToolbar(ContainerOperator toolbarOper, int x,
479: int y) {
480: ComponentChooser chooser = new ComponentChooser() {
481: public boolean checkComponent(Component comp) {
482: if (comp instanceof JPanel) {
483: String className = comp.getClass().getName();
484: return className
485: .equals("org.openide.awt.Toolbar$ToolbarBump")
486: ||
487: // used in Windows L&F
488: className
489: .equals("org.openide.awt.Toolbar$ToolbarGrip");
490: }
491: return false;
492: }
493:
494: public String getDescription() {
495: return "org.openide.awt.Toolbar$ToolbarBump or org.openide.awt.Toolbar$ToolbarGrip";
496: }
497: };
498: Component comp = findComponent((Container) toolbarOper
499: .getSource(), chooser);
500: new ComponentOperator(comp).dragNDrop(comp.getWidth() / 2, comp
501: .getHeight() / 2, x, y);
502: }
503:
504: /** Chooser which can be used to find a org.openide.awt.Toolbar component or
505: * count a number of such components in given container.
506: */
507: private static class ToolbarChooser implements ComponentChooser {
508: private String toolbarName;
509: private StringComparator comparator;
510: private int count = 0;
511:
512: /** Use this to find org.openide.awt.Toolbar component with given name. */
513: public ToolbarChooser(String toolbarName,
514: StringComparator comparator) {
515: this .toolbarName = toolbarName;
516: this .comparator = comparator;
517: }
518:
519: /** Use this to count org.openide.awt.Toolbar components in given container. */
520: public ToolbarChooser() {
521: this .comparator = null;
522: }
523:
524: public boolean checkComponent(Component comp) {
525: if (comp instanceof org.openide.awt.Toolbar) {
526: count++;
527: if (comparator != null) {
528: return comparator.equals(((Toolbar) comp)
529: .getDisplayName(), toolbarName);
530: } else {
531: return true;
532: }
533: }
534: return false;
535: }
536:
537: public String getDescription() {
538: return "org.openide.awt.Toolbar";
539: }
540:
541: public int getCount() {
542: return count;
543: }
544: }
545:
546: /** Chooser which can be used to find a component with given tooltip,
547: * for example a toolbar button.
548: */
549: private static class ToolbarButtonChooser implements
550: ComponentChooser {
551: private String buttonTooltip;
552: private StringComparator comparator;
553:
554: public ToolbarButtonChooser(String buttonTooltip,
555: StringComparator comparator) {
556: this .buttonTooltip = buttonTooltip;
557: this .comparator = comparator;
558: }
559:
560: public boolean checkComponent(Component comp) {
561: return comparator.equals(((JComponent) comp)
562: .getToolTipText(), buttonTooltip);
563: }
564:
565: public String getDescription() {
566: return "Toolbar button with tooltip \"" + buttonTooltip
567: + "\".";
568: }
569: }
570:
571: }
|