com.binge.workforce.widgets.internal.DrillDownAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.binge.workforce.widgets.internal.DrillDownAdapter.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.binge.workforce.widgets.internal;

import java.util.Arrays;
import java.util.List;
import org.eclipse.e4.demo.simpleide.dialogs.internal.Messages;
import org.eclipse.e4.demo.simpleide.services.IImageService;
import org.eclipse.e4.demo.simpleide.services.IImageService.IImagePool;
import org.eclipse.e4.demo.simpleide.sharedimages.SharedImageKeys;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;

/**
 * Implements a simple web style navigation metaphor for a <code>TreeViewer</code>.  
 * Home, back, and "drill into" functions are supported for the viewer,
 * <p>
 * To use the <code>DrillDownAdapter</code> ..
 * </p>
 * <ul>
 * <li>Create an instance of <code>TreeViewer</code>. </li>
 * <li>Create a <code>DrillDownAdapter</code> for the viewer. </li>
 * <li>Create a container for your viewer with a toolbar or a popup menu.
 *      Add actions for "goBack", "goHome", and "goInto" to either one by calling
 *      </code>addNavigationActions</code> with the popup menu or toolbar.</li>
 * </ol>
 * <p>
 * If the input for the underlying viewer is changed by something other than the 
 * adapter the <code>reset</code> method should be called.  This will clear
 * the drill stack and update the navigation buttons to reflect the new 
 * state of the underlying viewer.
 * </p>
 * </p>
 */
public class DrillDownAdapter implements ISelectionChangedListener {
    private TreeViewer fChildTree;

    private DrillStack fDrillStack;

    private Action homeAction;

    private Action backAction;

    private Action forwardAction;

    /**
     * Allocates a new DrillDownTreePart.
     *
     * @param tree the target tree for refocusing
     */
    public DrillDownAdapter(TreeViewer tree, IImageService imageService) {
        pool = imageService.getControlPool(tree.getControl());
        fDrillStack = new DrillStack();
        fChildTree = tree;
    }

    /**
     * Adds actions for "go back", "go home", and "go into" to a menu manager.
     *
     * @param manager is the target manager to update
     */
    public void addNavigationActions(IMenuManager manager) {
        createActions();
        manager.add(homeAction);
        manager.add(backAction);
        manager.add(forwardAction);
        updateNavigationButtons();
    }

    /**
     * Adds actions for "go back", "go home", and "go into" to a tool bar manager.
     *
     * @param toolBar is the target manager to update
     */
    public void addNavigationActions(IToolBarManager toolBar) {
        createActions();
        toolBar.add(homeAction);
        toolBar.add(backAction);
        toolBar.add(forwardAction);
        updateNavigationButtons();
    }

    /**
     * Returns whether expansion is possible for the current selection.  This
     * will only be true if it has children.
     *
     * @param element the object to test for expansion
     * @return <code>true</code> if expansion is possible; otherwise 
     *      return <code>false</code
     */
    public boolean canExpand(Object element) {
        return fChildTree.isExpandable(element);
    }

    /**
     * Returns whether "go back" is possible for child tree.  This is only possible 
     * if the client has performed one or more drilling operations.
     *
     * @return <code>true</code> if "go back" is possible; <code>false</code> otherwise
     */
    public boolean canGoBack() {
        return fDrillStack.canGoBack();
    }

    /**
     * Returns whether "go home" is possible for child tree.  This is only possible 
     * if the client has performed one or more drilling operations.
     *
     * @return <code>true</code> if "go home" is possible; <code>false</code> otherwise
     */
    public boolean canGoHome() {
        return fDrillStack.canGoHome();
    }

    /**
     * Returns whether "go into" is possible for child tree.  This is only possible 
     * if the current selection in the client has one item and it has children.
     *
     * @return <code>true</code> if "go into" is possible; <code>false</code> otherwise
     */
    public boolean canGoInto() {
        IStructuredSelection oSelection = (IStructuredSelection) fChildTree.getSelection();
        if (oSelection == null || oSelection.size() != 1) {
            return false;
        }
        Object anElement = oSelection.getFirstElement();
        return canExpand(anElement);
    }

    /**
     * Create the actions for navigation.
     *
     */
    private void createActions() {
        // Only do this once.
        if (homeAction != null) {
            return;
        }

        // Home.   
        homeAction = new Action(Messages.GoHome_text) {
            public void run() {
                goHome();
            }
        };
        homeAction.setToolTipText(Messages.GoHome_toolTip);
        homeAction.setImageDescriptor(
                ImageDescriptor.createFromImage(pool.getImageUnchecked(SharedImageKeys.IMG_TOOL_HOME_NAV)));

        // Back.
        backAction = new Action(Messages.GoBack_text) {
            public void run() {
                goBack();
            }
        };
        backAction.setToolTipText(Messages.GoBack_toolTip);
        backAction.setImageDescriptor(
                ImageDescriptor.createFromImage(pool.getImageUnchecked(SharedImageKeys.IMG_TOOL_BACK)));
        backAction.setDisabledImageDescriptor(
                ImageDescriptor.createFromImage(pool.getImageUnchecked(SharedImageKeys.IMG_TOOL_BACK_DISABLED)));

        // Forward.
        forwardAction = new Action(Messages.GoInto_text) {
            public void run() {
                goInto();
            }
        };
        forwardAction.setToolTipText(Messages.GoInto_toolTip);
        forwardAction.setImageDescriptor(
                ImageDescriptor.createFromImage(pool.getImageUnchecked(SharedImageKeys.IMG_TOOL_FORWARD)));
        forwardAction.setDisabledImageDescriptor(
                ImageDescriptor.createFromImage(pool.getImageUnchecked(SharedImageKeys.IMG_TOOL_FORWARD_DISABLED)));

        // Update the buttons when a selection change occurs.
        fChildTree.addSelectionChangedListener(this);
        updateNavigationButtons();
    }

    /**
     * Expands the given items in the tree.  The list of items passed should be
     * derived by calling <code>getExpanded</code>.
     *
     * @param items is a list of items within the tree which should be expanded
     */
    private void expand(List items) {
        fChildTree.setExpandedElements(items.toArray());
    }

    /**
     * Returns a list of elements corresponding to expanded nodes in 
     * child tree.
     *
     * @return a list of expandd elements
     */
    private List getExpanded() {
        return Arrays.asList(fChildTree.getExpandedElements());
    }

    /**
     * Reverts the input for the tree back to the state when <code>goInto</code>
     * was last called.
     * <p>
     * A frame is removed from the drill stack.  Then that frame is used to reset the
     * input and expansion state for the child tree.
     * </p>
     */
    public void goBack() {
        Object currentInput = fChildTree.getInput();
        DrillFrame oFrame = fDrillStack.goBack();
        Object input = oFrame.getElement();
        fChildTree.setInput(input);
        expand(oFrame.getExpansion());
        // if there was a selection, it should have been preserved,
        // but if not, select the element that was drilled into
        if (fChildTree.getSelection().isEmpty()) {
            fChildTree.setSelection(new StructuredSelection(currentInput), true);
        }
        updateNavigationButtons();
    }

    /**
     * Reverts the input for the tree back to the state when the adapter was
     * created.
     * <p>
     * All of the frames are removed from the drill stack.  Then the oldest frame is 
     * used to reset the input and expansion state for the child tree.
     * </p>
     */
    public void goHome() {
        Object currentInput = fChildTree.getInput();
        DrillFrame oFrame = fDrillStack.goHome();
        Object input = oFrame.getElement();
        fChildTree.setInput(input);
        expand(oFrame.getExpansion());
        // if there was a selection, it should have been preserved,
        // but if not, select the element that was last drilled into
        if (fChildTree.getSelection().isEmpty()) {
            fChildTree.setSelection(new StructuredSelection(currentInput), true);
        }
        updateNavigationButtons();
    }

    /**
     * Sets the input for the tree to the current selection.
     * <p>
     * The current input and expansion state are saved in a frame and added to the 
     * drill stack.  Then the input for the tree is changed to be the current selection.  
     * The expansion state for the tree is maintained during the operation.
     * </p><p>
     * On return the client may revert back to the previous state by invoking 
     * <code>goBack</code> or <code>goHome</code>.
     * </p>
     */
    public void goInto() {
        IStructuredSelection sel = (IStructuredSelection) fChildTree.getSelection();
        Object element = sel.getFirstElement();
        goInto(element);
    }

    /**
     * Sets the input for the tree to a particular item in the tree.
     * <p>
     * The current input and expansion state are saved in a frame and added to the 
     * drill stack.  Then the input for the tree is changed to be <code>newInput</code>.  
     * The expansion state for the tree is maintained during the operation.
     * </p><p>
     * On return the client may revert back to the previous state by invoking 
     * <code>goBack</code> or <code>goHome</code>.
     * </p>
     *
     * @param newInput the new input element
     */
    public void goInto(Object newInput) {
        // If we can drill ..
        if (canExpand(newInput)) {
            // Save the old state.
            Object oldInput = fChildTree.getInput();
            List expandedList = getExpanded();
            fDrillStack.add(new DrillFrame(oldInput, "null", expandedList));//$NON-NLS-1$

            // Install the new state.
            fChildTree.setInput(newInput);
            expand(expandedList);
            updateNavigationButtons();
        }
    }

    /**
     * Resets the drill down adapter. 
     * <p>
     * This method is typically called when the input for the underlying view
     * is reset by something other than the adapter.
     * On return the drill stack has been cleared and the navigation buttons
     * reflect the new state of the underlying viewer.
     * </p>
     */
    public void reset() {
        fDrillStack.reset();
        updateNavigationButtons();
    }

    /**
     * Updates the navigation buttons when a selection change occurs
     * in the tree.
     */
    public void selectionChanged(SelectionChangedEvent event) {
        updateNavigationButtons();
    }

    /**
     * Updates the enabled state for each navigation button.  
     */
    protected void updateNavigationButtons() {
        if (homeAction != null) {
            homeAction.setEnabled(canGoHome());
            backAction.setEnabled(canGoBack());
            forwardAction.setEnabled(canGoInto());
        }
    }
}