org.netbeans.jellytools.MainWindowOperator Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.jellytools;
import java.awt.Component;
import java.awt.Container;
import java.awt.GraphicsEnvironment;
import java.io.PrintStream;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.awt.Toolbar;
import org.openide.awt.StatusDisplayer;
import org.openide.windows.WindowManager;
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.JemmyException;
import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.QueueTool;
import org.netbeans.jemmy.Waitable;
import org.netbeans.jemmy.Waiter;
import org.netbeans.jemmy.operators.ComponentOperator;
import org.netbeans.jemmy.operators.ContainerOperator;
import org.netbeans.jemmy.operators.JButtonOperator;
import org.netbeans.jemmy.operators.JFrameOperator;
import org.netbeans.jemmy.operators.JMenuBarOperator;
import org.netbeans.jemmy.operators.JPopupMenuOperator;
/**
* Handle NetBeans main window. It manipulates with toolbars and
* you can get text from status bar. To invoke menu items use
* {@link org.netbeans.jellytools.actions actions}.
*
* It is singleton, so to get instance use static method getDefault()
.
*
* Usage:
*
* MainWindowOperator mainWindow = MainWindowOperator.getDefault();
* mainWindow.waitStatusText("Finished");
* System.out.println("STATUS="+mainWindow.getStatusText());
* // push "Open" toolbar button in "System" toolbar
* mainWindow.getToolbarButton(mainWindow.getToolbar("System"), "Open").push();
* Thread.sleep(2000);
* new NbDialogOperator("Open").close();
* // invoke "Compile" menu item under "Build" menu
* new CompileAction().performMenu();
* // invoke About menu item under "Help" menu
* new ActionNoBlock("Help|About", null).perform();
* Thread.sleep(2000);
* new NbDialogOperator("About").close();
*
*
* @author [email protected]
*/
public class MainWindowOperator extends JFrameOperator {
/** Singleton instance of MainWindowOperator. */
//private static MainWindowOperator defaultMainWindowOperator;
/** JMenuBarOperator instance. */
private JMenuBarOperator _menuBar;
/** Instance of StatusTextTracer for this MainWindowOperator instance */
private static StatusTextTracer statusTextTracer = null;
/** Creates new instance of MainWindowOperator. It gets instance of main window
* Frame.
*
* Note: costructor made public, so this class is not neccessarily used as singleton.
*/
public MainWindowOperator() {
// run in dispatch thread
super((JFrame)new QueueTool().invokeSmoothly(new QueueTool.QueueAction("getMainWindow") { // NOI18N
public Object launch() {
return WindowManager.getDefault().getMainWindow(); //NOI18N
}
})
);
}
//TODO: If making this non-singleton proves to really fix the C/V tests, mark this as deprecated.
/** Returns instance of MainWindowOperator. It is singleton, so this method
* is only way how to obtain instance. If instance not exists, it creates one.
* @return instance of MainWindowOperator
*/
public static synchronized MainWindowOperator getDefault() {
/*
* This is done, because having this class as singleton kept a static reference
* to MainWindow and sometimes kept a reference to a document which would have been
* otherwise GDed. This behavior sometimes caused commit validation tests
* to fail.
*
if(defaultMainWindowOperator == null) {
defaultMainWindowOperator = new MainWindowOperator();
}
*/
return new MainWindowOperator();
}
/** Returns operator of main menu bar.
* @return JMenuBarOperator instance of main menu
*/
public JMenuBarOperator menuBar() {
if(_menuBar == null) {
_menuBar = new JMenuBarOperator(this);
}
return _menuBar;
}
/** Returns text from status bar.
* @return currently displayed text
*/
public String getStatusText() {
return org.openide.awt.StatusDisplayer.getDefault().getStatusText();
}
/** Sets given text to main window's status bar.
* @param newStatusText string to be displayed in status bar
*/
public void setStatusText(String newStatusText) {
org.openide.awt.StatusDisplayer.getDefault().setStatusText(newStatusText);
}
/** Returns singleton instance of StatusTextTracer.
* @return singleton instance of StatusTextTracer
*/
public synchronized StatusTextTracer getStatusTextTracer() {
if(statusTextTracer == null) {
statusTextTracer = new StatusTextTracer();
}
return statusTextTracer;
}
/** Waits until given text appears in the main window status bar.
* If you want to trace status messages during an operation is proceed,
* use {@link StatusTextTracer}.
* @param text a text to wait for
*/
public void waitStatusText(final String text) {
getStatusTextTracer().start();
try {
// not wait in case status text was already printed out
if(!getComparator().equals(getStatusText(), text)) {
getStatusTextTracer().waitText(text);
}
} finally {
getStatusTextTracer().stop();
}
}
/***************** methods for toolbars manipulation *******************/
/** Returns ContainerOperator representing index-th floating toolbar in
* IDE main window. Toolbars are NOT indexed from left to right.
* @param index index of toolbar to find
* @return ContainerOperator instance representing a toolbar
*/
public ContainerOperator getToolbar(int index) {
ComponentChooser chooser = new ToolbarChooser();
return new ContainerOperator((Container)waitComponent((Container)getSource(),
chooser, index));
}
/** Returns ContainerOperator representing floating toolbar with given name.
* @param toolbarName toolbar's display name. It is shown in its tooltip.
* @return ContainerOperator instance representing a toolbar
*/
public ContainerOperator getToolbar(String toolbarName) {
ComponentChooser chooser = new ToolbarChooser(toolbarName, getComparator());
return new ContainerOperator((Container)waitComponent((Container)getSource(), chooser));
}
/** Returns number of toolbars currently shown in IDE.
* @return number of toolbars
*/
public int getToolbarCount() {
ToolbarChooser chooser = new ToolbarChooser("Non sense name - @#$%^&*", //NOI18N
getComparator());
findComponent((Container)getSource(), chooser);
return chooser.getCount();
}
/** Returns display name of toolbar with given index. Toolbars are NOT
* indexed from left to right.
* @param index index of toolbar
* @return display name of toolbar
*/
public String getToolbarName(int index) {
return ((Toolbar)getToolbar(index).getSource()).getDisplayName();
}
/** Return JButtonOperator representing a toolbar button found by given
* tooltip within given toolbar operator.
* @param toolbarOper ContainerOperator of a toolbar.
* Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
* to obtain an operator.
* @param buttonTooltip tooltip of toolbar button
* @return JButtonOperator instance of found toolbar button
*/
public JButtonOperator getToolbarButton(ContainerOperator toolbarOper, String buttonTooltip) {
ToolbarButtonChooser chooser = new ToolbarButtonChooser(buttonTooltip, getComparator());
return new JButtonOperator(JButtonOperator.waitJButton(
(Container)toolbarOper.getSource(), chooser));
}
/** Return JButtonOperator representing index-th toolbar button within given
* toolbar operator.
* @param toolbarOper ContainerOperator of a toolbar.
* Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
* to obtain an operator.
* @param index index of toolbar button to find
* @return JButtonOperator instance of found toolbar button
*/
public JButtonOperator getToolbarButton(ContainerOperator toolbarOper, int index) {
return new JButtonOperator(toolbarOper, index);
}
/** Pushes popup menu on toolbars. It doesn't matter on which toolbar it is
* invoked, everytime it is the same. That's why popup menu is invoked on
* the right side of toolbar with index 0.
* @param popupPath path to menu item (e.g. "Edit")
*/
public void pushToolbarPopupMenu(String popupPath) {
ContainerOperator contOper = getToolbar(0);
contOper.clickForPopup(contOper.getWidth()-1, contOper.getHeight()/2);
new JPopupMenuOperator().pushMenu(popupPath, "|");
}
/** Pushes popup menu on toolbars - no block further execution.
* It doesn't matter on which toolbar it is
* invoked, everytime it is the same. That's why popup menu is invoked on
* the right side of toolbar with index 0.
* @param popupPath path to menu item (e.g. "Save Configuration...")
*/
public void pushToolbarPopupMenuNoBlock(String popupPath) {
ContainerOperator contOper = getToolbar(0);
contOper.clickForPopup(contOper.getWidth()-1, contOper.getHeight()/2);
new JPopupMenuOperator().pushMenuNoBlock(popupPath, "|");
}
/** Drags a toolbar to a new position determined by [x, y] relatively.
* @param toolbarOper ContainerOperator of a toolbar.
* Use {@link #getToolbar(String)} or {@link #getToolbar(int)}
* to obtain an operator.
* @param x relative move along x direction
* @param y relative move along y direction
*/
public void dragNDropToolbar(ContainerOperator toolbarOper, int x, int y) {
// find toolbar drag and drop area
Component comp = toolbarOper.findSubComponent(new ComponentChooser() {
@Override
public boolean checkComponent(Component comp) {
return comp instanceof JPanel;
}
@Override
public String getDescription() {
return "Toolbar dragger";
}
});
new ComponentOperator(comp).dragNDrop(comp.getWidth() / 2, comp.getHeight() / 2, comp.getWidth() / 2 + x, comp.getHeight() / 2 + y);
}
/** Chooser which can be used to find a org.openide.awt.Toolbar component or
* count a number of such components in given container.
*/
private static class ToolbarChooser implements ComponentChooser {
private String toolbarName;
private StringComparator comparator;
private int count = 0;
/** Use this to find org.openide.awt.Toolbar component with given name. */
public ToolbarChooser(String toolbarName, StringComparator comparator) {
this.toolbarName = toolbarName;
this.comparator = comparator;
}
/** Use this to count org.openide.awt.Toolbar components in given container. */
public ToolbarChooser() {
this.comparator = null;
}
public boolean checkComponent(Component comp) {
if(comp instanceof org.openide.awt.Toolbar) {
count++;
if(comparator != null) {
return comparator.equals(((Toolbar)comp).getDisplayName(), toolbarName);
} else {
return true;
}
}
return false;
}
public String getDescription() {
return "org.openide.awt.Toolbar";
}
public int getCount() {
return count;
}
}
/** Chooser which can be used to find a component with given tooltip,
* for example a toolbar button.
*/
private static class ToolbarButtonChooser implements ComponentChooser {
private String buttonTooltip;
private StringComparator comparator;
public ToolbarButtonChooser(String buttonTooltip, StringComparator comparator) {
this.buttonTooltip = buttonTooltip;
this.comparator = comparator;
}
public boolean checkComponent(Component comp) {
return comparator.equals(((JComponent)comp).getToolTipText(), buttonTooltip);
}
public String getDescription() {
return "Toolbar button with tooltip \""+buttonTooltip+"\".";
}
}
/** Performs verification by accessing all sub-components */
public void verify() {
menuBar();
}
/**
* Maximize main window accounting native window manager task bars.
*/
@Override
public void maximize() {
setBounds(GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds());
}
/** Class to trace messages printed to status bar of the Main Window.
*
* Usage:
*
* MainWindowOperator.StatusTextTracer stt = MainWindowOperator.getDefault().getStatusTextTracer();
* // start tracing
* stt.start();
* // compile action will produce at least two messages: "Compiling ...",
* // "Finished ..."
* new CompileAction().performAPI();
*
* // waits for "Compiling" status text
* stt.waitText("Compiling");
* // waits for "Finished" status text
* stt.waitText("Finished");
*
* // order is not significant => following works as well
* stt.waitText("Finished");
* stt.waitText("Compiling");
*
* // to be order significant, set removedCompared parameter to true
* stt.waitText("Compiling", true);
* stt.waitText("Finished", true);
*
* // history was removed by above methods => need to produce a new messages
* new CompileAction().performAPI();
*
* // order is significant if removedCompared parameter is true =>
* // => following fails because Finished is shown as second
* stt.waitText("Finished", true);
* stt.waitText("Compiling", true);
*
* // stop tracing
* stt.stop();
*
*/
public class StatusTextTracer implements ChangeListener {
/** List of all messages */
private ArrayList statusTextHistory;
/** Creates new instance. */
public StatusTextTracer() {
this.statusTextHistory = new ArrayList();
}
/** Starts to register all status messages into history array.
* Exactly, it adds the listener to org.openide.awt.StatusDisplayer.
* It clears possible previously filled history array before.
*/
public void start() {
stop();
clear();
StatusDisplayer.getDefault().addChangeListener(this);
}
/** Stops registering of status messages. Exactly, it removes the
* listener from org.openide.awt.StatusDisplayer.
*/
public void stop() {
StatusDisplayer.getDefault().removeChangeListener(this);
}
/** Called when status text was changed. It adds status text to history
* array.
* @param evt change event - not used
*/
public void stateChanged(ChangeEvent evt) {
synchronized (this) {
statusTextHistory.add(StatusDisplayer.getDefault().getStatusText());
// print message to jemmy output stream
JemmyProperties.getCurrentOutput().printTrace("Status text changed to: \""+
StatusDisplayer.getDefault().getStatusText()+"\"");
}
}
/** Clears status text history array. */
public void clear() {
synchronized (this) {
statusTextHistory.clear();
}
}
/** Checks whether given text equals to any of messages in the history
* array. Comparator of this MainWindowOperator instance is used.
* If removeCompared parameter is set to true,
* messages already compared are removed from history array. Otherwise
* messages are not removed until {@link #clear} or {@link #start} are
* called.
* @param text a text to be compared
* @param removeCompared whether to remove already compared messages from
* history array
* @return true if text matches any of messages in the history array;
* false otherwise
*/
public boolean contains(String text, boolean removeCompared) {
StringComparator comparator = getComparator();
synchronized (this) {
if(removeCompared) {
while(!statusTextHistory.isEmpty()) {
String status = statusTextHistory.remove(0);
if(comparator.equals(status, text)) {
return true;
}
}
} else {
for (int i = 0; i < statusTextHistory.size(); i ++) {
if(comparator.equals(statusTextHistory.get(i), text)) {
return true;
}
}
}
return false;
}
}
/** Waits for text to be shown in the Main Window status bar not
* removing any message from history.
* Comparator of this MainWindowOperator instance is used.
* It throws TimeoutExpiredException if timeout expires.
* @param text a text to wait for
*/
public void waitText(final String text) {
waitText(text, false);
}
/** Waits for text to be shown in the Main Window status bar.
* Comparator of this MainWindowOperator instance is used.
* If removeCompared parameter is set to true,
* messages already compared are removed from history array. It satisfies
* that order of messages is significant when this method is called
* more than once.
* If removeCompared parameter is set to false,
* messages are not removed until {@link #clear} or {@link #start} are
* called and its order is not taken into account.
* @param text a text to wait for
* @param removeCompared whether to remove already compared messages from
* history array
*/
public void waitText(final String text, final boolean removeCompared) {
try {
new Waiter(new Waitable() {
public Object actionProduced(Object anObject) {
return contains(text, removeCompared) ? Boolean.TRUE : null;
}
public String getDescription() {
return("Wait status text equals to "+text);
}
}).waitAction(null);
} catch (InterruptedException e) {
throw new JemmyException("Interrupted.", e);
}
}
/** Calls {@link #stop} at the end of life cycle of this class. */
@Override
protected void finalize() {
stop();
}
/** Returns list of elements collected from the moment method
* {@link #start} was called. Remember, if removeCompared
* parameter is set to true in some of methods,
* messages already compared are removed from history array.
* @return ArrayList of elements representing status text messages
*/
public ArrayList getStatusTextHistory() {
return statusTextHistory;
}
/** Prints list of elements collected from the moment method
* {@link #start} was called. Remember, if removeCompared
* parameter is set to true in some of methods,
* messages already compared are removed from history array.
* @param outputPrintStream stream to print output in
*/
public void printStatusTextHistory(PrintStream outputPrintStream) {
for (int i = 0; i < statusTextHistory.size(); i ++) {
outputPrintStream.println(statusTextHistory.get(i));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy