org.netbeans.jellytools.OutlineOperator Maven / Gradle / Ivy
/*
* 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.Point;
import javax.swing.tree.TreePath;
import org.netbeans.jellytools.nodes.OutlineNode;
import org.netbeans.jemmy.*;
import org.netbeans.jemmy.operators.ContainerOperator;
import org.netbeans.jemmy.operators.JTableOperator;
import org.netbeans.swing.outline.Outline;
import org.netbeans.swing.outline.OutlineModel;
/**
* An operator to handle org.netbeans.swing.outline.Outline component used e.g.
* in debugger views.
*
*
* Warning: Do not use yet unless really neccessary!! Incomplete, under
* development and most probably still buggy!
*
* @author Vojtech Sigler
*/
public class OutlineOperator extends JTableOperator {
public OutlineOperator(ContainerOperator cont) {
this(cont, 0);
}
public OutlineOperator(ContainerOperator cont, int index) {
super((Outline) cont.waitSubComponent(
new OutlineFinder(ComponentSearcher.getTrueChooser("Any Outline")),
index));
copyEnvironment(cont);
}
public OutlineOperator(Outline outline) {
super(outline);
}
/**
* Gets the Outline component the operator is working with.
*
* @return Outline component
*/
public Outline getOutline() {
return (Outline) getSource();
}
/**
* Gets the current index of the tree column (column of the table which
* contains the tree) in the table.
*
* @return index of the tree column or -1 if is not found (error)
*/
public int getTreeColumnIndex() {
int lnNumColumns = this.getColumnCount();
for (int i = 0; i < lnNumColumns; i++) {
if (convertColumnIndexToModel(i) == 0) {
return i;
}
}
return -1;
}
/**
* Tries to find a child of the irParentPath which matches isName. The index
* parameter is used if we want indexth node of the same name (otherwise use
* 0). If it is not found a TimeoutExpiredException is thrown.
*
* @param irParentPath parent path in which to search
* @param isName name of the node to be found
* @param inIndex index of the node among its siblings (in case there are
* more of the same name)
* @return found path
*/
public TreePath findNextPathElement(final TreePath irParentPath, final String isName, final int inIndex) {
if (!isExpanded(irParentPath)) {
expandPath(irParentPath);
}
TreePath lrTreePath;
Timeouts lrTimes = getTimeouts().cloneThis();
//behavior should be similar to JTreeOperator, so we can use its timeout values
lrTimes.setTimeout("Waiter.WaitingTime", getTimeouts().getTimeout("JTreeOperator.WaitNextNodeTimeout"));
try {
Waiter lrWaiter = new Waiter(new NodeWaiter(irParentPath, isName, inIndex));
lrWaiter.setTimeouts(lrTimes);
lrTreePath = (TreePath) lrWaiter.waitAction(null);
} catch (InterruptedException e) {
throw new JemmyException("Interrupted.", e);
}
return lrTreePath;
}
/**
* Tries to find a child of the irParentPath which matches isName. If it is
* not found a TimeoutExpiredException is thrown.
*
* @param irParentPath
* @param isName
* @return found path
*/
public TreePath findNextPathElement(TreePath irParentPath, String isName) {
return findNextPathElement(irParentPath, isName, 0);
}
/**
* Gets the first root node (child of the root element) of the specified
* name.
*
* @param isName
* @return
*/
public OutlineNode getRootNode(String isName) {
return getRootNode(isName, 0);
}
/**
* Gets a root node (child of the root element) of the specified name. The
* index parameter is used if we want indexth node of the same name
* (otherwise use 0).
*
* @param isName
* @param inIndex
* @return
*/
public OutlineNode getRootNode(String isName, int inIndex) {
TreePath lrParentPath = new TreePath(getOutline().getOutlineModel().getRoot());
return new OutlineNode(this, findNextPathElement(lrParentPath, isName, inIndex));
}
/**
*
* Tries to find a subpath (descendant) of a parent path in the tree.
*
* @param irParentPath parent path to start the search in
* @param isPath node name or a list of nodes separated by "|"
* @return found path
*/
public TreePath findPath(TreePath irParentPath, String isPath) {
int lnDelimIndex = isPath.indexOf("|");
if (lnDelimIndex > -1) {
TreePath lrFoundPath = findNextPathElement(irParentPath, isPath.substring(0, lnDelimIndex));
return findPath(lrFoundPath, isPath.substring(lnDelimIndex + 1));
}
return findNextPathElement(irParentPath, isPath);
}
/**
*
* Tries to find a the defined path beginning from the root node.
*
* @param isPath node name or a list of nodes separated by "|"
* @return found path
*/
public TreePath findPath(String isPath) {
TreePath lrParentPath = new TreePath(getOutline().getOutlineModel().getRoot());
return findPath(lrParentPath, isPath);
}
/**
* Waits until the given TreePath is expanded.
*
* @param irTP TreePath in question
*/
public void waitExpanded(final TreePath irTP) {
if (irTP != null) {
waitState(new ComponentChooser() {
@Override
public boolean checkComponent(Component comp) {
return (isExpanded(irTP));
}
@Override
public String getDescription() {
return ("Has \"" + irTP.toString() + "\" path expanded");
}
});
} else {
throw (new JemmyException("No such path: null"));
}
}
/**
* Returns modifier based on root being hidden or not. When the root is
* hidden, all y coordinates need to be decreased by 1.
*
* @return 0 or -1
*/
protected int getVisibleRootModifier() {
return getOutline().isRootVisible() ? 0 : -1;
}
/**
* Gets the location of a given TreePath in the Outline table (x for columns
* and y for rows) or (-1,-1) in case it was not found.
*
* @param irTreePath TreePath in question
* @return Location for the given path or Point(-1,-1) if it was not found.
*/
public Point getLocationForPath(TreePath irTreePath) {
int lnX = getTreeColumnIndex();
int lnY = getRowForPath(irTreePath);
return (lnY == -1) ? new Point(-1, -1) : new Point(lnX, lnY);
}
/**
* Gets the row in the Outline table for a given TreePath or -1 if the
* TreePath is invalid.
*
* @param irTreePath TreePath in question
* @return Row of the path or -1 if it is invalid.
*/
public int getRowForPath(TreePath irTreePath) {
if (irTreePath.getParentPath() == null) {
return getVisibleRootModifier();
}
if (!isExpanded(irTreePath.getParentPath())) {
expandPath(irTreePath.getParentPath());
}
int lnRow = -1;
while (irTreePath.getParentPath() != null) {
lnRow += 1 + getPrecedingSiblingsRowSpan(irTreePath);
irTreePath = irTreePath.getParentPath();
}
return lnRow;
}
/**
* Gets the rowspan of siblings which are above irTreePath in the tree. Only
* expanded paths are taken into account.
*
* @param irTreePath
* @return
*/
protected int getPrecedingSiblingsRowSpan(TreePath irTreePath) {
OutlineModel lrModel = getOutline().getOutlineModel();
if (irTreePath.getParentPath() == null) {
return 0 + getVisibleRootModifier();
}
Object lrLast = irTreePath.getLastPathComponent();
TreePath lrParent = irTreePath.getParentPath();
int lnRowSpan = 0;
int lnIndex = lrModel.getIndexOfChild(lrParent.getLastPathComponent(), lrLast);
for (int i = lnIndex - 1; i >= 0; i--) {
Object lrSibling = lrModel.getChild(lrParent.getLastPathComponent(), i);
lnRowSpan += getRowSpanOfLastElement(lrParent.pathByAddingChild(lrSibling));
}
return lnRowSpan;
}
/**
* Gets the total rowspan of the last element of irTreePath.
*
* @param irTreePath
* @return
*/
protected int getRowSpanOfLastElement(TreePath irTreePath) {
OutlineModel lrModel = getOutline().getOutlineModel();
if (!isExpanded(irTreePath)) {
return 1;
}
Object lrLast = irTreePath.getLastPathComponent();
int lnRowspan = 1; //1 for the current node
int lnChildCount = lrModel.getChildCount(lrLast);
for (int i = 0; i < lnChildCount; i++) {
Object lnChild = lrModel.getChild(lrLast, i);
TreePath lrTempPath = irTreePath.pathByAddingChild(lnChild);
lnRowspan += getRowSpanOfLastElement(lrTempPath);
}
return lnRowspan;
}
public void selectPath(TreePath irPath) {
Point lrLocation = getLocationForPath(irPath);
if (!lrLocation.equals(new Point(-1, -1))) {
this.selectCell(lrLocation.y, lrLocation.x);
}
}
public void scrollToPath(TreePath irPath) {
Point lrLocation = getLocationForPath(irPath);
if (!lrLocation.equals(new Point(-1, -1))) {
this.scrollToCell(lrLocation.y, lrLocation.x);
}
}
//Mappings
/**
* Expands target path.
*
* @param irTP
*/
public void expandPath(final TreePath irTP) {
runMapping(new MapVoidAction("expandPath") {
@Override
public void map() {
getOutline().expandPath(irTP);
}
});
}
/**
* Returns true if target path is expanded.
*
* @param irTP
* @return
*/
public boolean isExpanded(final TreePath irTP) {
return ((Boolean) runMapping(new MapAction("isExpanded") {
@Override
public Object map() {
return (getOutline().isExpanded(irTP));
}
}));
}
//Nested classes
private static class OutlineFinder implements ComponentChooser {
private ComponentChooser subFinder;
public OutlineFinder(ComponentChooser finder) {
subFinder = finder;
}
@Override
public boolean checkComponent(Component comp) {
Class cls = comp.getClass();
do {
if (cls.getName().equals("org.netbeans.swing.outline.Outline")) {
return (subFinder.checkComponent(comp));
}
} while ((cls = cls.getSuperclass()) != null);
return (false);
}
@Override
public String getDescription() {
return subFinder.getDescription();
}
}
/**
* Waits for indexth node with string name to appear.
*/
private class NodeWaiter implements Waitable {
private TreePath parentPath;
private int[] rowsToSearch = null;
private String name;
private int index;
public NodeWaiter(TreePath irParentPath, String isName, int inIndex) {
parentPath = irParentPath;
name = isName;
index = inIndex;
}
/**
* Returns the array of rows we will search in. The array is cached and
* will regenerate when the child count of parentPath changes.
*
* @return array of row numbers
*/
private int[] getRowsToSearch() {
int lnRowSpan = getOutline().getOutlineModel().getChildCount(parentPath.getLastPathComponent());
if ((rowsToSearch == null) || (rowsToSearch.length != lnRowSpan)) {
int lnStartRow = getRowForPath(parentPath) + 1;
int lnPrecedingSiblingRowSpan = 0;
rowsToSearch = new int[lnRowSpan];
for (int i = 0; i < lnRowSpan; i++) {
rowsToSearch[i] = lnStartRow + lnPrecedingSiblingRowSpan;
Object lrSibling = getOutline().getOutlineModel().getChild(parentPath.getLastPathComponent(), i);
TreePath lrSiblingPath = parentPath.pathByAddingChild(lrSibling);
lnPrecedingSiblingRowSpan += getRowSpanOfLastElement(lrSiblingPath);
}
}
return rowsToSearch;
}
@Override
public Object actionProduced(Object anObject) {
TreePath lrPath;
Point lrFindPoint = findCell(name, getRowsToSearch(), new int[]{getTreeColumnIndex()}, index);
//no cell found
if (lrFindPoint.equals(new Point(-1, -1))) {
return null;
}
//y is row, x is not important since we're asking for a row in the tree
lrPath = getOutline().getLayoutCache().getPathForRow(lrFindPoint.y);
//path for the specified row not found or it is not visible
if (lrPath == null) {
return null;
}
//found a cell that is a not a direct child of the parent path
if (lrPath.getPathCount() != parentPath.getPathCount() + 1) {
return null;
}
return lrPath;
}
@Override
public String getDescription() {
return ("Tree node cell with name '" + name + "' present.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy