Java tutorial
/******************************************************************************* * Copyright (c) 2011, 2012 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: * Sascha Becher <s.becher@qualitype.de> - bug 360894 *******************************************************************************/ package org.eclipse.pde.internal.ui.editor.actions; import java.util.Iterator; import org.eclipse.jface.action.Action; import org.eclipse.jface.viewers.*; import org.eclipse.pde.core.plugin.IPluginParent; import org.eclipse.pde.internal.core.text.plugin.PluginExtensionNode; import org.eclipse.pde.internal.core.text.plugin.PluginParentNode; import org.eclipse.pde.internal.ui.PDEPluginImages; import org.eclipse.pde.internal.ui.PDEUIMessages; import org.eclipse.pde.internal.ui.editor.plugin.FormFilteredTree; import org.eclipse.pde.internal.ui.search.ExtensionsPatternFilter; import org.eclipse.swt.widgets.TreeItem; /** * Expands and collapses selected tree nodes in the extension elements tree viewer upon their expand state. */ public class ToggleExpandStateAction extends Action { public static int NEEDS_EXPAND = 1; public static int NEEDS_COLLAPSE = 2; protected TreeViewer fExtensionTree; protected FormFilteredTree fFilteredTree; public ToggleExpandStateAction(FormFilteredTree filteredTree, TreeViewer treeViewer) { setImageDescriptor(PDEPluginImages.DESC_TOGGLE_EXPAND_STATE); setDisabledImageDescriptor(PDEPluginImages.DESC_TOGGLE_EXPAND_STATE_DISABLED); setText(PDEUIMessages.ExtensionsPage_toggleExpandState); fExtensionTree = treeViewer; fFilteredTree = filteredTree; } public void run() { StructuredSelection selection = (StructuredSelection) fExtensionTree.getSelection(); if (fExtensionTree.getTree().getSelectionCount() > 0) { TreeItem[] items = fExtensionTree.getTree().getSelection(); try { fFilteredTree.setRedraw(false); int state = getStateChangeRequired(items); toggleExpandState(state, selection); } finally { fFilteredTree.setRedraw(true); fExtensionTree.refresh(); } } } public void toggleExpandState(int state, StructuredSelection selection) { TreeItem[] items = fExtensionTree.getTree().getSelection(); if (state == NEEDS_EXPAND) { // expand sub tree traverseChildrenAndSetExpanded(items); // load non-expanded children fExtensionTree.refresh(); expandChildrenElements(selection.toArray(), true); fExtensionTree.setSelection(selection, false); } else { // collapse sub tree for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { fExtensionTree.setExpandedState(iterator.next(), false); } } } public int getStateChangeRequired(TreeItem[] selection) { return (traverseStateChangeRequired(selection)) ? NEEDS_EXPAND : NEEDS_COLLAPSE; } /** * @param items items to be traversed * @return <code>true</code> if at least one of the tree items could be expanded but is not. Otherwise <code>false</code> is returned. */ protected boolean traverseStateChangeRequired(TreeItem[] items) { if (items != null) { for (int i = 0; i < items.length; i++) { TreeItem treeItem = items[i]; TreeItem[] children = treeItem.getItems(); if (children.length > 0) { if (treeItem.getExpanded()) { if (traverseStateChangeRequired(children)) { return true; } } else { return true; } } } } return false; } /** * Expands subtrees of given items. Items of type <code>PluginExtensionNode</code> that have multiple children to expand * will only be expanded to the that level. Further expanding is required to reveal the whole subtree. This is for reasons of * convenience. * * @param items tree items to be expand with their children */ private void traverseChildrenAndSetExpanded(TreeItem[] items) { for (int i = 0; i < items.length; i++) { TreeItem treeItem = items[i]; TreeItem[] children = treeItem.getItems(); int extensionsChildCount = getExtensionsChildCount((IPluginParent) treeItem.getData()); boolean furtherExpanding = !(extensionsChildCount > 1 && (!treeItem.getExpanded())); treeItem.setExpanded(furtherExpanding); if (furtherExpanding) { traverseChildrenAndSetExpanded(children); } } } private int getExtensionsChildCount(IPluginParent leafData) { int extensionsChildCount = 0; if (leafData != null && leafData instanceof PluginExtensionNode) { if (!fFilteredTree.isFiltered()) { return leafData.getChildCount(); } ExtensionsPatternFilter filter = (ExtensionsPatternFilter) fFilteredTree.getPatternFilter(); for (int j = 0; j < leafData.getChildCount(); j++) { if (filter.containsElement(leafData.getChildren()[j])) { extensionsChildCount++; } } } return extensionsChildCount; } /** * @param children list of elements to be expand with their children */ private void expandChildrenElements(Object[] children, boolean fullExpand) { for (int i = 0; i < children.length; i++) { Object child = children[i]; if (child instanceof PluginParentNode) { PluginParentNode node = (PluginParentNode) child; if (node.getChildCount() > 0 && fullExpand) { boolean furtherExpanding = !(node instanceof PluginExtensionNode && !fExtensionTree.getExpandedState(node)); expandChildrenElements(node.getChildren(), furtherExpanding); } else { fExtensionTree.expandToLevel(node, 0); } } } } /** * Determines whether the selected leafs are expandable * * @param selection selection to test each item with * @return whether the selection can be expanded */ public static boolean isExpandable(IStructuredSelection selection) { boolean isExpandable = false; if (selection != null) { if (!selection.isEmpty()) { for (Iterator<?> iterator = selection.iterator(); iterator.hasNext();) { Object element = iterator.next(); if (element instanceof PluginParentNode) { PluginParentNode node = (PluginParentNode) element; if (node.getChildCount() > 0) { isExpandable = true; break; } } } } } return isExpandable; } }