Getting TreeItem of SWT Tree via path (Java)

Last edited on

Overview

While recording or when picking (and copying the object names) in an SWT tree Squish will generate object names hierarchies that represent the TreeItem structure and store them in "TEST_SUITE_DIR/shared/names.*.

However having a large number of such TreeItem hierarchies in the object map can be hard to maintain.

The approach shown below does not use Squish object names for retrieving TreeItems, but instead it iterates over the TreeItem objects of an SWT tree by accessing the SWT Tree object API directly from the test script, by using the SWT Tree’s getItem() method.

The main idea of this is that often it is desirable to look up TreeItems via a “path” of TreeItems, specified as text, for example:

["item 0", "item 0 0", "item 0 0 2"]
Example TreeItem path (JavaScript)

JavaScript

function main()
{
    startApplication("my_aut_with_swt_tree");

    tree = waitForObject({'isvisible':'true', 'type':'org.eclipse.swt.widgets.Tree'});

    item = getSWTTreeItem(tree, ["item 0", ["item 0 0", 2], "item 0 0 2"], true);

    // Just to show it off, click on the tree item
    // with coordinates relative to the tree:
    itemBounds = item.getBounds();
    mouseClick(tree, itemBounds.x + 5, itemBounds.y + 5, 0, Button.Button3);
    snooze(3);
}

/**
 * Get item in an SWT tree.
 *
 * path is a list of TreeItem texts, denoting the path of
 * the desired item. For example:
 *
 *     Node1
 *         Sub-Node1
 *     Node2
 *
 *     path = ["Node1", "Sub-Node1"]
 *
 * In addition each element of path can also be an array
 * of [TreeItem_text, occurrence], where occurrence
 * specifies which TreeItem to use in case of duplicates
 * under the same parent TreeItem. For example:
 *
 *     Node0
 *         Sub-Node1
 *         Sub-Node1
 *
 *     path = ["Node0", ["Sub-Node1", 2]] 
 */
function getSWTTreeItem(treeOrItem, path, verbose)
{
    if (verbose == null) {
        verbose = false;
    }
    return getSWTTreeItemImpl(treeOrItem, path, path, verbose);
}

function getSWTTreeItemImpl(treeOrItem, path, subPath, verbose)
{
    var n = treeOrItem.getItemCount();
    var occurrence = null;
    for (var i = 0; i < n; i++) {
        item = treeOrItem.getItem(i);
        itemText = item.getText();

        if (occurrence == null) {
            pathElement = subPath[0];
            if (!(pathElement instanceof Array)) {
                pathElement = [pathElement, 1];
            }
            occurrence = pathElement[1];
            pathElement = pathElement[0];
        }
        if (itemText == pathElement) {
            if (occurrence > 1) {
                if (verbose) {
                    test.log("Ignoring: " + itemText + ", occurrence: " + occurrence);
                }
                occurrence--;
                continue;
            }

            occurrence = null;
            if (verbose) {
                test.log("Found " + itemText);
            }

            if (subPath.length == 1) {
                if (verbose) {
                    test.log("Reached end of path");
                }
                return item;
            } else {
                return getSWTTreeItemImpl(item, path, subPath.slice(1), verbose);
            }
        }
    }
    if (verbose) {
        test.log("Error: Path element not found: " + subPath[0] + " (Complete path: " + path.toString() + ")");
    }
    return null;
}
test.js

Python

def main():
    startApplication("my_aut_with_swt_tree")

    tree = waitForObject({'isvisible':'true', 'type':'org.eclipse.swt.widgets.Tree'})

    item = get_swt_tree_item(tree, ["item 0", ("item 0 0", 2), "item 0 0 2"], verbose=True)

    # Just to show it off, click on the tree item
    # with coordinates relative to the tree:
    item_bounds = item.getBounds()
    mouseClick(tree, item_bounds.x + 5, item_bounds.y + 5, 0, Button.Button3)
    snooze(3)

def get_swt_tree_item(tree_or_item, path, sub_path=None, verbose=False):
    """Get item in an SWT tree.
    path is a list of TreeItem texts, denoting the path of
    the desired item. For example:

        Node1
            Sub-Node1
        Node2

        path = ["Node1", "Sub-Node1"]

    In addition each element of path can also be a tuple
    of (TreeItem_text, occurrence), where occurrence
    specifies which TreeItem to use in case of duplicates
    under the same parent TreeItem. For example:

        Node0
            Sub-Node1
            Sub-Node1

        path = ["Node0", ("Sub-Node1", 2)]"""

    if sub_path is None:
        sub_path = path
    n = tree_or_item.getItemCount()
    occurrence = None
    for i in range(n):
        item = tree_or_item.getItem(i)
        item_text = item.getText()

        if occurrence is None:
            path_element = sub_path[0]
            if not isinstance(path_element, tuple):
                path_element = (path_element, 1)
            occurrence = path_element[1]
            path_element = path_element[0]
        if item_text == path_element:
            if occurrence > 1:
                if verbose:
                    test.log("Ignoring: " + item_text + ", occurrence: " + str(occurrence))
                occurrence -= 1
                continue

            occurrence = None
            if verbose:
                test.log("Found " + item_text)

            if len(sub_path) == 1:
                if verbose:
                    test.log("Reached end of path")
                return item
            else:
                return get_swt_tree_item(item, path, sub_path[1:], verbose)

    if verbose:
        test.log("Error: Path element not found: " + str(sub_path[0]) + " (Complete path: " + str(path) + ")")
    return None
test.py