/*******************************************************************************
* Copyright (c) 2012 Arapiki Solutions Inc.
* 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:
* "Peter Smith <psmith@arapiki.com>" - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.eclipse.utils;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
/**
* A VisibilityTreeViewer is the same as a TreeViewer, but has special features for
* hiding certain elements. A non-visible element can either be removed completely from the
* Tree (i.e. filtered out), or can be greyed-out (still visible, but obviously not selected).
*
* @author "Peter Smith <psmith@arapiki.com>"
*/
public class VisibilityTreeViewer extends TreeViewer {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/**
* The externally-registered IVisibilityProvider used by this VisibilityTreeViewer
* to indicate whether specific elements should be visible in the Tree control, or
* not.
*/
private IVisibilityProvider visibilityProvider = null;
/** The TreeViewer filters to use to reveal all paths */
private ViewerFilter revealViewerFilters[];
/** The TreeViewer filters to use to hide invisible paths */
private ViewerFilter hiddenViewerFilters[];
/**
* If true, show hidden elements as being greyed-out. If false, don't
* show them at all.
*/
boolean greyVisibilityMode = true;
/*=====================================================================================*
* CONSTRUCTORS
*=====================================================================================*/
/**
* Create a new VisibilityTreeViewer class.
* @param tree The Tree widget that this TreeViewer will wrap.
*/
public VisibilityTreeViewer(Tree tree) {
super(tree);
/*
* Filter for revealing invisible elements so that they can be shown greyed out
* (actually, this disables all filters).
*/
revealViewerFilters = new ViewerFilter[0];
/* Filter for hiding non-visible elements so they won't be seen at all. */
hiddenViewerFilters = new ViewerFilter[1];
hiddenViewerFilters[0] = new ViewerFilter() {
public boolean select(Viewer viewer, Object parentElement, Object element) {
return visibilityProvider.isVisible(element);
}
};
/* disabled greyed-out mode */
setGreyVisibilityMode(false);
}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/**
* For a given TreeViewer element, set its visibility state. A visible element will appear,
* as normal, but a non-visible element will either be greyed out, or not render at all.
*
* @param element The element to be made visible or non-visible.
* @param state True to make it visible, else false.
*/
public void setVisibility(Object element, boolean state)
{
/*
* First, ensure that there's an underlying model, otherwise everything
* should be considered to be selected.
*/
if (visibilityProvider == null) {
return;
}
/* Set visibility of this element in the underlying model. */
visibilityProvider.setVisibility(element, state);
/* refresh the whole TreeViewer so that things appear/disappear/re-colour */
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
refresh();
}
});
}
/*-------------------------------------------------------------------------------------*/
/**
* Set this viewer's visibility provider class. This provider informs the TreeViewer
* which elements in the Tree are to be visible (or non-greyed-out) versus being
* invisible (or greyed-out).
*
* @param visibilityProvider An external provider class (implementing IVisibilityProvider).
*/
public void setVisibilityProvider(IVisibilityProvider visibilityProvider)
{
this.visibilityProvider = visibilityProvider;
}
/*-------------------------------------------------------------------------------------*/
/**
* Specify whether this TreeViewer should render non-visible elements using
* grey font, or whether they should not be rendered at all.
* @param greyVisibility True if non-visible element should be greyed out,
* or false if they should not be shown at all.
*/
public void setGreyVisibilityMode(boolean greyVisibility) {
if (greyVisibility) {
/* disable the TreeViewer filter, so we'll see the non-visible element */
setFilters(revealViewerFilters);
} else {
setFilters(hiddenViewerFilters);
}
this.greyVisibilityMode = greyVisibility;
}
/*-------------------------------------------------------------------------------------*/
/**
* Determine whether this TreeViewer will show non-visible elements using a grey font,
* as opposed to not rendering them at all.
* @return True if non-visible element are being greyed-out, else false.
*/
public boolean getGreyVisibilityMode() {
return greyVisibilityMode;
}
/*=====================================================================================*
* PROTECTED METHODS
*=====================================================================================*/
/*
* Overrides the parent class's doUpdateItem(). We use the visibility provider object
* (if it exists) to colour the widget appropriately.
*/
protected void doUpdateItem(Widget widget, Object element, boolean fullMap)
{
/* invoke the super class to do most of the work */
super.doUpdateItem(widget, element, fullMap);
/*
* now, if there's a filter registered, ask it whether this element
* should be highlighted
*/
if ((visibilityProvider != null) && (widget instanceof TreeItem)) {
setWidgetHighlight((TreeItem)widget,
visibilityProvider.isVisible(element));
}
}
/*=====================================================================================*
* PRIVATE METHODS
*=====================================================================================*/
/**
* Internal method for setting the colour of a widget (to black or grey), depending
* on whether the corresponding tree element is visible or not.
* @param item The Widget to be coloured.
* @param state True to highlight the widget with black, else false to grey it out.
*/
private void setWidgetHighlight(TreeItem item, boolean state) {
if (state) {
item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
} else {
item.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
}
}
/*-------------------------------------------------------------------------------------*/
}