org.eclipse.jubula.rc.javafx.tester.adapter.TreeOperationContext.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jubula.rc.javafx.tester.adapter.TreeOperationContext.java

Source

/*******************************************************************************
 * Copyright (c) 2013 BREDEX GmbH.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BREDEX GmbH - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.jubula.rc.javafx.tester.adapter;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;

import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.Validate;
import org.eclipse.jubula.rc.common.driver.ClickOptions;
import org.eclipse.jubula.rc.common.driver.IEventThreadQueuer;
import org.eclipse.jubula.rc.common.driver.IRobot;
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
import org.eclipse.jubula.rc.common.implclasses.tree.AbstractTreeOperationContext;
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
import org.eclipse.jubula.rc.common.util.SelectionUtil;
import org.eclipse.jubula.rc.javafx.driver.EventThreadQueuerJavaFXImpl;
import org.eclipse.jubula.rc.javafx.listener.ComponentHandler;
import org.eclipse.jubula.rc.javafx.util.Rounding;

/**
 * This context holds the tree and supports access to the Robot. It also
 * implements some general operations on trees.
 *
 * @author BREDEX GmbH
 * @created 19.11.2013
 */
public class TreeOperationContext extends AbstractTreeOperationContext {

    /** The AUT Server logger. */
    private static AutServerLogger log = new AutServerLogger(TreeOperationContext.class);

    /**
     * Creates a new instance. The JTree must have a tree model.
     *
     * @param queuer
     *            The queuer
     * @param robot
     *            The Robot
     * @param tree
     *            The tree
     */
    public TreeOperationContext(IEventThreadQueuer queuer, IRobot robot, TreeView<?> tree) {
        super(queuer, robot, tree);
        Validate.notNull(tree.getRoot());
    }

    /**
     * {@inheritDoc}
     *
     * @param row
     *            Not used!
     */
    @Override
    protected String convertValueToText(final Object node, final int row) throws StepExecutionException {
        String result = EventThreadQueuerJavaFXImpl.invokeAndWait("convertValueToText", new Callable<String>() { //$NON-NLS-1$

            @Override
            public String call() throws Exception {
                TreeItem<?> item = (TreeItem<?>) node;
                if (item != null) {
                    Object val = item.getValue();
                    if (val != null) {
                        return val.toString();
                    }
                }
                return null;
            }
        });
        return result;
    }

    @Override
    public Collection<String> getNodeTextList(Object node) {
        List<String> res = new ArrayList<String>();
        int rowNotUsed = 0;
        String valText = convertValueToText(node, rowNotUsed);
        if (valText != null) {
            res.add(valText);
        }
        String rendText = getRenderedText(node);
        if (rendText != null) {
            res.add(rendText);
        }
        return res;
    }

    @Override
    public String getRenderedText(final Object node) throws StepExecutionException {
        String result = EventThreadQueuerJavaFXImpl.invokeAndWait("getRenderedText", new Callable<String>() { //$NON-NLS-1$

            @Override
            public String call() throws Exception {
                List<? extends TreeCell> tCells = ComponentHandler.getAssignableFrom(TreeCell.class);
                for (TreeCell<?> cell : tCells) {
                    TreeItem<?> item = cell.getTreeItem();
                    if (item != null && item.equals(node)) {
                        return cell.getText();
                    }
                }
                return null;
            }
        });

        return result;
    }

    @Override
    public boolean isVisible(final Object node) {
        boolean result = EventThreadQueuerJavaFXImpl.invokeAndWait("isVisible", //$NON-NLS-1$
                new Callable<Boolean>() {

                    @Override
                    public Boolean call() throws Exception {
                        TreeItem<?> item = (TreeItem<?>) node;
                        return item.isExpanded() && ((TreeView<?>) getTree()).isVisible();
                    }
                });

        return result;
    }

    @Override
    public Rectangle getVisibleRowBounds(final Rectangle rowBounds) {
        Rectangle result = EventThreadQueuerJavaFXImpl.invokeAndWait("getVisibleRowBounds", //$NON-NLS-1$
                new Callable<Rectangle>() {

                    @Override
                    public Rectangle call() throws Exception {
                        TreeView<?> tree = ((TreeView<?>) getTree());
                        // Update the layout coordinates otherwise
                        // we would get old position values
                        tree.layout();
                        Rectangle visibleTreeBounds = new Rectangle(0, 0, Rounding.round(tree.getWidth()),
                                Rounding.round(tree.getHeight()));
                        return rowBounds.intersection(visibleTreeBounds);
                    }
                });
        return result;

    }

    @Override
    public boolean isExpanded(final Object node) {
        boolean result = EventThreadQueuerJavaFXImpl.invokeAndWait("isExpanded", new Callable<Boolean>() { //$NON-NLS-1$

            @Override
            public Boolean call() throws Exception {
                TreeItem<?> item = (TreeItem<?>) node;
                return item.isExpanded();
            }
        });

        return result;
    }

    @Override
    public void scrollNodeToVisible(final Object node) {
        EventThreadQueuerJavaFXImpl.invokeAndWait("scrollNodeToVisible", //$NON-NLS-1$
                new Callable<Void>() {

                    @Override
                    public Void call() throws Exception {
                        int index = ((TreeView<?>) getTree()).getRow((TreeItem) node);
                        ((TreeView<?>) getTree()).scrollTo(index);
                        // Update the layout coordinates otherwise
                        // we would get old position values
                        ((TreeView<?>) getTree()).layout();
                        return null;
                    }
                });
    }

    @Override
    public void clickNode(Object node, ClickOptions clickOps) {
        scrollNodeToVisible(node);
        Rectangle rowBounds = getNodeBounds(node);
        Rectangle visibleRowBounds = getVisibleRowBounds(rowBounds);
        getRobot().click(getTree(), visibleRowBounds, clickOps);
    }

    @Override
    public void expandNode(final Object node) {
        scrollNodeToVisible(node);
        Object result = EventThreadQueuerJavaFXImpl.invokeAndWait("expandNode", //$NON-NLS-1$
                new Callable<Object>() {

                    @Override
                    public Object call() throws Exception {
                        List<? extends TreeCell> tCells = ComponentHandler.getAssignableFrom(TreeCell.class);
                        for (TreeCell<?> cell : tCells) {
                            TreeItem<?> item = cell.getTreeItem();
                            if (item != null && item.equals(node) && !item.isExpanded()) {
                                TreeView<?> tree = ((TreeView<?>) getTree());
                                // Update the layout coordinates otherwise
                                // we would get old position values
                                tree.layout();
                                return cell.getDisclosureNode();
                            }
                        }
                        return null;
                    }
                });
        if (result != null) {
            getRobot().click(result, null, ClickOptions.create().setClickCount(1).setMouseButton(1));
        }
        EventThreadQueuerJavaFXImpl.invokeAndWait("expandNodeCheckIfExpanded", //$NON-NLS-1$
                new Callable<Void>() {

                    @Override
                    public Void call() throws Exception {
                        TreeItem<?> item = (TreeItem<?>) node;
                        if (!((TreeView<?>) getTree()).isDisabled() && !item.isExpanded()) {
                            log.warn("Expand node fallback used for: " //$NON-NLS-1$
                                    + item.getValue());

                            item.setExpanded(true);
                        }
                        return null;
                    }
                });
    }

    @Override
    public void collapseNode(final Object node) {
        scrollNodeToVisible(node);
        Object result = EventThreadQueuerJavaFXImpl.invokeAndWait("collapseNode", new Callable<Object>() { //$NON-NLS-1$

            @Override
            public Object call() throws Exception {
                List<? extends TreeCell> tCells = ComponentHandler.getAssignableFrom(TreeCell.class);
                for (TreeCell<?> cell : tCells) {
                    TreeItem<?> item = cell.getTreeItem();
                    if (item != null && item.equals(node) && item.isExpanded()) {
                        TreeView<?> tree = ((TreeView<?>) getTree());
                        // Update the layout coordinates otherwise
                        // we would get old position values
                        tree.layout();
                        return cell.getDisclosureNode();
                    }
                }
                return null;
            }
        });
        if (result != null) {
            getRobot().click(result, null, ClickOptions.create().setClickCount(1).setMouseButton(1));
        }
        EventThreadQueuerJavaFXImpl.invokeAndWait("collapseNodeCheckIfCollapsed", new Callable<Void>() { //$NON-NLS-1$

            @Override
            public Void call() throws Exception {
                TreeItem<?> item = (TreeItem<?>) node;
                if (!((TreeView<?>) getTree()).isDisabled() && item.isExpanded()) {
                    log.warn("Collapse node fallback used for: " //$NON-NLS-1$
                            + item.getValue());

                    item.setExpanded(false);
                }
                return null;
            }
        });
    }

    @Override
    public Object getSelectedNode() {
        Object result = EventThreadQueuerJavaFXImpl.invokeAndWait("getSelectedNode", new Callable<Object>() { //$NON-NLS-1$

            @Override
            public Object call() throws Exception {

                return ((TreeView<?>) getTree()).getSelectionModel().getSelectedItem();
            }
        });
        if (result != null) {
            SelectionUtil.validateSelection(new Object[] { result });
        } else {
            SelectionUtil.validateSelection(new Object[] {});
        }
        return result;
    }

    @Override
    public Object[] getSelectedNodes() {
        Object[] result = EventThreadQueuerJavaFXImpl.invokeAndWait("getSelectedNode", new Callable<Object[]>() { //$NON-NLS-1$

            @Override
            public Object[] call() throws Exception {

                return ((TreeView<?>) getTree()).getSelectionModel().getSelectedItems().toArray();
            }
        });
        SelectionUtil.validateSelection(result);
        return result;
    }

    @Override
    public Object[] getRootNodes() {
        Object[] result = EventThreadQueuerJavaFXImpl.invokeAndWait("getRootNodes", new Callable<Object[]>() { //$NON-NLS-1$

            @Override
            public Object[] call() throws Exception {
                TreeView<?> tree = (TreeView<?>) getTree();

                // If the root is visible, just return that.
                if (tree.showRootProperty().getValue()) {
                    return new Object[] { tree.getRoot() };
                }

                // If the root is not visible, return all direct
                // children of the
                // non-visible root.
                return getChildren(tree.getRoot());
            }
        });
        return result;
    }

    @Override
    public Object getParent(final Object child) {
        Object result = EventThreadQueuerJavaFXImpl.invokeAndWait("getParent", //$NON-NLS-1$
                new Callable<Object>() {

                    @Override
                    public Object call() throws Exception {

                        return ((TreeItem<?>) child).getParent();
                    }
                });

        return result;
    }

    @Override
    public Object getChild(final Object parent, final int index) {
        Object result = EventThreadQueuerJavaFXImpl.invokeAndWait("getChild", //$NON-NLS-1$
                new Callable<Object>() {

                    @Override
                    public Object call() throws Exception {

                        return ((TreeItem<?>) parent).getChildren().get(index);
                    }
                });

        return result;
    }

    @Override
    public int getNumberOfChildren(final Object parent) {
        Integer result = EventThreadQueuerJavaFXImpl.invokeAndWait("getNumberOfChildren", new Callable<Integer>() { //$NON-NLS-1$

            @Override
            public Integer call() throws Exception {

                return ((TreeItem<?>) parent).getChildren().size();
            }
        });

        return result;
    }

    @Override
    public boolean isLeaf(final Object node) {
        boolean result = EventThreadQueuerJavaFXImpl.invokeAndWait("isLeaf", //$NON-NLS-1$
                new Callable<Boolean>() {

                    @Override
                    public Boolean call() throws Exception {
                        TreeItem<?> item = (TreeItem<?>) node;
                        return item.isLeaf();
                    }
                });

        return result;
    }

    @Override
    public Object[] getChildren(final Object parent) {
        Object[] result = EventThreadQueuerJavaFXImpl.invokeAndWait("getSelectedNode", new Callable<Object[]>() { //$NON-NLS-1$

            @Override
            public Object[] call() throws Exception {

                return ((TreeItem<?>) parent).getChildren().toArray();
            }
        });

        return result;
    }

    @Override
    public Rectangle getNodeBounds(final Object node) {
        Rectangle result = EventThreadQueuerJavaFXImpl.invokeAndWait("getNodeBounds", new Callable<Rectangle>() { //$NON-NLS-1$
            @Override
            public Rectangle call() throws Exception {
                List<? extends TreeCell> tCells = ComponentHandler.getAssignableFrom(TreeCell.class);
                for (TreeCell<?> cell : tCells) {
                    TreeItem<?> item = cell.getTreeItem();
                    TreeView<?> tree = (TreeView<?>) getTree();
                    if ((item != null && item.equals(node))) {
                        // Update the layout coordinates otherwise
                        // we would get old position values
                        tree.layout();

                        Point2D posTree = tree.localToScreen(0, 0);
                        Point2D posCell = cell.localToScreen(0, 0);
                        Bounds b = cell.getBoundsInParent();
                        Rectangle cBounds = new Rectangle(
                                Math.abs(Rounding.round((posCell.getX() - posTree.getX()))),
                                Math.abs(Rounding.round((posCell.getY() - posTree.getY()))),
                                Rounding.round(b.getWidth()), Rounding.round(b.getHeight()));
                        return cBounds;
                    }
                }
                return null;
            }
        });
        return result;
    }

    @Override
    public int getIndexOfChild(final Object parent, final Object child) {
        Integer result = EventThreadQueuerJavaFXImpl.invokeAndWait("getIndexOfChild", new Callable<Integer>() { //$NON-NLS-1$

            @Override
            public Integer call() throws Exception {
                if (parent == null) {
                    Object[] rootNodes = getRootNodes();
                    for (int i = 0; i < rootNodes.length; i++) {
                        if (ObjectUtils.equals(rootNodes[i], child)) {
                            return i;
                        }
                    }

                    return -1;
                }
                List<?> children = ((TreeItem<?>) parent).getChildren();
                if (children.contains(child)) {
                    return children.indexOf(child);
                }
                return -1;
            }
        });
        return result;
    }

}