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-2006 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: package org.netbeans.jellytools;
042:
043: import java.awt.Component;
044: import java.awt.Point;
045: import java.awt.Rectangle;
046: import javax.swing.JPopupMenu;
047: import javax.swing.JScrollPane;
048: import javax.swing.JTable;
049: import javax.swing.JTree;
050: import javax.swing.tree.TreePath;
051:
052: import org.netbeans.jemmy.ComponentChooser;
053: import org.netbeans.jemmy.ComponentSearcher;
054: import org.netbeans.jemmy.EventTool;
055: import org.netbeans.jemmy.Timeout;
056: import org.netbeans.jemmy.drivers.DriverManager;
057: import org.netbeans.jemmy.drivers.MouseDriver;
058: import org.netbeans.jemmy.drivers.SupportiveDriver;
059: import org.netbeans.jemmy.operators.ComponentOperator;
060: import org.netbeans.jemmy.operators.ContainerOperator;
061: import org.netbeans.jemmy.operators.JPopupMenuOperator;
062: import org.netbeans.jemmy.operators.JScrollPaneOperator;
063: import org.netbeans.jemmy.operators.JTableOperator;
064: import org.netbeans.jemmy.operators.JTreeOperator;
065: import org.netbeans.jemmy.util.EmptyVisualizer;
066: import org.openide.explorer.view.Visualizer;
067:
068: /**
069: * Handle IDE's org.openide.explorer.view.TreeTable component
070: * which is used instead of JTree in Options dialog, ...
071: */
072: public class TreeTableOperator extends JTableOperator {
073:
074: private JTreeOperator _tree;
075:
076: /** Creates new instance.
077: * @param view JTable representing requested TreeTable
078: */
079: public TreeTableOperator(JTable view) {
080: super (view);
081: }
082:
083: /** Creates new instance for the first TreeTable in container.
084: * @param contOper container where to find TreeTable
085: */
086: public TreeTableOperator(ContainerOperator contOper) {
087: this (contOper, 0);
088: }
089:
090: /** Creates new instance for the first TreeTable in container.
091: * @param contOper container where to find TreeTable
092: * @param index int index
093: */
094: public TreeTableOperator(ContainerOperator contOper, int index) {
095: this ((JTable) waitComponent(contOper, new TreeTableFinder(
096: ComponentSearcher.getTrueChooser("Any TreeTable")),
097: index));
098: copyEnvironment(contOper);
099: }
100:
101: /** Returns operator for a tree which is showed as a part of
102: * the table.
103: * @return JTreeOperator instance
104: */
105: public JTreeOperator tree() {
106: if (_tree == null) {
107: // Need to wait until TreeTable is populated. Otherwise it can throw
108: // NPE from getValueAt(0, 0).
109: waitState(new ComponentChooser() {
110: public boolean checkComponent(Component comp) {
111: return getColumnCount() > 0 && getRowCount() > 0;
112: }
113:
114: public String getDescription() {
115: return "TreeTable contains any rows.";
116: }
117: });
118: // cell renderer component for first column is JTree
119: Object value = getValueAt(0, 0);
120: JTree jTree = (JTree) getCellRenderer(0, 0)
121: .getTableCellRendererComponent(
122: (JTable) this .getSource(), value, false,
123: false, 0, 0);
124: // Need to set EmptyVisualizer because found JTree doesn't have any parent Container
125: // and calling makeComponentVisible() throws NPE
126: // _tree = new JTreeOperator(jTree);
127: _tree = new RenderedTreeOperator(this , jTree);
128: _tree.setVisualizer(new EmptyVisualizer());
129: }
130: // Everytime make parent container visible because tree has EmptyVisualizer
131: // and it is need for example for popup menu operations on JTree
132: makeComponentVisible();
133: return _tree;
134: }
135:
136: /** Selects node in this TreeTable.
137: * @param path path to node (e.g. "System|Settings")
138: * @return row number of selected node
139: */
140: public int selectNode(String path) {
141: TreePath treePath = tree().findPath(path, "|");
142: if (!tree().isPathSelected(treePath)) {
143: tree().selectPath(treePath);
144: }
145: int result = tree().getRowForPath(treePath);
146: scrollToCell(result, 0);
147: new EventTool().waitNoEvent(500);
148: return result;
149: }
150:
151: /** Registers RenderedMouseDriver to be used by RenderedTreeOperator. */
152: static {
153: DriverManager.setDriver(DriverManager.MOUSE_DRIVER_ID,
154: new RenderedMouseDriver(), RenderedTreeOperator.class);
155: }
156:
157: /** Finder to search for "org.openide.explorer.view.TreeTable". */
158: static class TreeTableFinder implements ComponentChooser {
159: ComponentChooser subFinder;
160:
161: public TreeTableFinder(ComponentChooser sf) {
162: subFinder = sf;
163: }
164:
165: public boolean checkComponent(Component comp) {
166: Class cls = comp.getClass();
167: do {
168: if (cls.getName().equals(
169: "org.openide.explorer.view.TreeTable")) {
170: return (subFinder.checkComponent(comp));
171: }
172: } while ((cls = cls.getSuperclass()) != null);
173: return (false);
174: }
175:
176: public String getDescription() {
177: return (subFinder.getDescription());
178: }
179: }
180:
181: /** MouseDriver used to process events not on JTree but on TreeTable
182: * component which is used to handle events in real.
183: */
184: public static class RenderedMouseDriver extends SupportiveDriver
185: implements MouseDriver {
186:
187: /** Creates new instance of RenderedMouseDriver. */
188: public RenderedMouseDriver() {
189: super (new Class[] { RenderedTreeOperator.class });
190: }
191:
192: /** Presses mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
193: * @param oper operator which delegates events on an real operator
194: * @param x x position of mouse operation
195: * @param y y position of mouse operation
196: * @param mouseButton mouse button identification
197: * @param modifiers modifiers pressed during mouse click
198: */
199: public void pressMouse(ComponentOperator oper, int x, int y,
200: int mouseButton, int modifiers) {
201: checkSupported(oper);
202: ComponentOperator realOper = ((RenderedTreeOperator) oper)
203: .getRealOperator();
204: DriverManager.getMouseDriver(realOper).pressMouse(realOper,
205: x, y, mouseButton, modifiers);
206: }
207:
208: /** Releases mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
209: * @param oper operator which delegates events on an real operator
210: * @param x x position of mouse operation
211: * @param y y position of mouse operation
212: * @param mouseButton mouse button identification
213: * @param modifiers modifiers pressed during mouse click
214: */
215: public void releaseMouse(ComponentOperator oper, int x, int y,
216: int mouseButton, int modifiers) {
217: checkSupported(oper);
218: ComponentOperator realOper = ((RenderedTreeOperator) oper)
219: .getRealOperator();
220: DriverManager.getMouseDriver(realOper).releaseMouse(
221: realOper, x, y, mouseButton, modifiers);
222: }
223:
224: /** Clicks mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
225: * @param oper operator which delegates events on an real operator
226: * @param x x position of mouse operation
227: * @param y y position of mouse operation
228: * @param clickCount how many times to be clicked
229: * @param mouseButton mouse button identification
230: * @param modifiers modifiers pressed during mouse click
231: * @param mouseClick timeout of mouse click
232: */
233: public void clickMouse(ComponentOperator oper, int x, int y,
234: int clickCount, int mouseButton, int modifiers,
235: Timeout mouseClick) {
236: checkSupported(oper);
237: ComponentOperator realOper = ((RenderedTreeOperator) oper)
238: .getRealOperator();
239: DriverManager.getMouseDriver(realOper).clickMouse(realOper,
240: x, y, clickCount, mouseButton, modifiers,
241: mouseClick);
242: }
243:
244: /** Moves mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
245: * @param oper operator which delegates events on an real operator
246: * @param x x position of mouse operation
247: * @param y y position of mouse operation
248: */
249: public void moveMouse(ComponentOperator oper, int x, int y) {
250: checkSupported(oper);
251: ComponentOperator realOper = ((RenderedTreeOperator) oper)
252: .getRealOperator();
253: DriverManager.getMouseDriver(realOper).moveMouse(realOper,
254: x, y);
255: }
256:
257: /** Drags mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
258: * @param oper operator which delegates events on an real operator
259: * @param x x position of mouse operation
260: * @param y y position of mouse operation
261: * @param mouseButton mouse button identification
262: * @param modifiers modifiers pressed during mouse click
263: */
264: public void dragMouse(ComponentOperator oper, int x, int y,
265: int mouseButton, int modifiers) {
266: checkSupported(oper);
267: ComponentOperator realOper = ((RenderedTreeOperator) oper)
268: .getRealOperator();
269: DriverManager.getMouseDriver(realOper).dragMouse(realOper,
270: x, y, mouseButton, modifiers);
271: }
272:
273: /** Provides drag and drop operation on operator given by
274: * {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
275: * @param oper operator which delegates events on an real operator
276: * @param start_x x position where to drag
277: * @param start_y y position where to drag
278: * @param end_x x position where to drop
279: * @param end_y y position where to drop
280: * @param mouseButton mouse button identification
281: * @param modifiers modifiers pressed during mouse click
282: * @param before timeout before drag
283: * @param after timeout after drop
284: */
285: public void dragNDrop(ComponentOperator oper, int start_x,
286: int start_y, int end_x, int end_y, int mouseButton,
287: int modifiers, Timeout before, Timeout after) {
288: checkSupported(oper);
289: ComponentOperator realOper = ((RenderedTreeOperator) oper)
290: .getRealOperator();
291: DriverManager.getMouseDriver(realOper).dragNDrop(realOper,
292: start_x, start_y, end_x, end_y, mouseButton,
293: modifiers, before, after);
294: }
295:
296: /** Enters mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
297: * @param oper operator which delegates events on an real operator
298: */
299: public void enterMouse(ComponentOperator oper) {
300: checkSupported(oper);
301: ComponentOperator realOper = ((RenderedTreeOperator) oper)
302: .getRealOperator();
303: DriverManager.getMouseDriver(realOper).enterMouse(realOper);
304: }
305:
306: /** Exits mouse on operator given by {@link TreeTableOperator.RenderedTreeOperator#getRealOperator getRealOperator()} method.
307: * @param oper operator which delegates events on an real operator
308: */
309: public void exitMouse(ComponentOperator oper) {
310: checkSupported(oper);
311: ComponentOperator realOper = ((RenderedTreeOperator) oper)
312: .getRealOperator();
313: DriverManager.getMouseDriver(realOper).exitMouse(realOper);
314: }
315: }
316:
317: /** Operator used to process events not on JTree but on TreeTable
318: * component which is used to handle events in real.
319: */
320: public static class RenderedTreeOperator extends JTreeOperator {
321: TreeTableOperator oper;
322:
323: /** Creates new instance of RenderedTreeOperator.
324: * @param oper TreeTable operator to handle events
325: * @param tree JTree representing nodes
326: */
327: public RenderedTreeOperator(TreeTableOperator oper, JTree tree) {
328: super (tree);
329: this .oper = oper;
330: }
331:
332: /** Returns TreeTableOperator instance which is used to handle events.
333: * @return TreeTableOperator instance
334: */
335: public ComponentOperator getRealOperator() {
336: return (oper);
337: }
338:
339: /** Calls popup menu on specified tree paths.
340: * @param paths an array of TreePath instances
341: * @param mouseButton mouse button identification
342: * @return JPopupMenu instance opened by this method
343: */
344: public JPopupMenu callPopupOnPaths(TreePath[] paths,
345: int mouseButton) {
346: oper.makeComponentVisible();
347: for (int i = 0; i < paths.length; i++) {
348: if (paths[i].getParentPath() != null) {
349: expandPath(paths[i].getParentPath());
350: }
351: }
352: selectPaths(paths);
353: scrollToPath(paths[paths.length - 1]);
354: Point point = getPointToClick(paths[paths.length - 1]);
355: return (JPopupMenuOperator
356: .callPopup(oper.getSource(), (int) point.getX(),
357: (int) point.getY(), mouseButton));
358: }
359:
360: /**
361: * Scrolls to a path if the tree is on a JScrollPane component.
362: * @param path TreePath where to scroll
363: */
364: public void scrollToPath(TreePath path) {
365: makeComponentVisible();
366: //try to find JScrollPane under.
367: JScrollPane scroll = (JScrollPane) getContainer(new JScrollPaneOperator.JScrollPaneFinder(
368: ComponentSearcher.getTrueChooser("JScrollPane")));
369: if (scroll == null) {
370: return;
371: }
372: JScrollPaneOperator scroller = new JScrollPaneOperator(
373: scroll);
374: scroller.copyEnvironment(this );
375: scroller.setVisualizer(new EmptyVisualizer());
376: Rectangle rect = getPathBounds(path);
377: if (rect != null) {
378: scroller.scrollToComponentRectangle(getRealOperator()
379: .getSource(), (int) rect.getX(), (int) rect
380: .getY(), (int) rect.getWidth(), (int) rect
381: .getHeight());
382: } else {
383: throw (new NoSuchPathException(path));
384: }
385: }
386:
387: /** Expands path and waits until all children are ready. This method
388: * is used in JTreeOperator.findPathPrimitive, so we need it override here.
389: * @param treePath tree path to be expanded
390: */
391: public void expandPath(final TreePath treePath) {
392: super .expandPath(treePath);
393: Visualizer.findNode(treePath.getLastPathComponent())
394: .getChildren().getNodes(true);
395: }
396: }
397:
398: /** Performs verification by accessing all sub-components */
399: public void verify() {
400: tree();
401: }
402:
403: }
|