diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java | 946 |
1 files changed, 0 insertions, 946 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java deleted file mode 100644 index d11b8a4c6..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java +++ /dev/null @@ -1,946 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.editors.ui.tree; - -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper; -import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper.ManifestSectionPart; -import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; -import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; -import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener; -import com.android.ide.eclipse.adt.internal.sdk.Sdk.TargetChangeListener; - -import org.eclipse.core.resources.IProject; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IMenuListener; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.ITreeSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.jface.viewers.ViewerFilter; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.ui.forms.DetailsPart; -import org.eclipse.ui.forms.IDetailsPage; -import org.eclipse.ui.forms.IDetailsPageProvider; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.MasterDetailsBlock; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; - -/** - * {@link UiTreeBlock} is a {@link MasterDetailsBlock} which displays a tree view for - * a specific set of {@link UiElementNode}. - * <p/> - * For a given UI element node, the tree view displays all first-level children that - * match a given type (given by an {@link ElementDescriptor}. All children from these - * nodes are also displayed. - * <p/> - * In the middle next to the tree are some controls to add or delete tree nodes. - * On the left is a details part that displays all the visible UI attributes for a given - * selected UI element node. - */ -public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml { - - /** Height hint for the tree view. Helps the grid layout resize properly on smaller screens. */ - private static final int TREE_HEIGHT_HINT = 50; - - /** Container editor */ - AndroidXmlEditor mEditor; - /** The root {@link UiElementNode} which contains all the elements that are to be - * manipulated by this tree view. In general this is the manifest UI node. */ - private UiElementNode mUiRootNode; - /** The descriptor of the elements to be displayed as root in this tree view. All elements - * of the same type in the root will be displayed. Can be null or empty to mean everything - * can be displayed. */ - private ElementDescriptor[] mDescriptorFilters; - /** The title for the master-detail part (displayed on the top "tab" on top of the tree) */ - private String mTitle; - /** The description for the master-detail part (displayed on top of the tree view) */ - private String mDescription; - /** The master-detail part, composed of a main tree and an auxiliary detail part */ - private ManifestSectionPart mMasterPart; - /** The tree viewer in the master-detail part */ - private TreeViewer mTreeViewer; - /** The "add" button for the tree view */ - private Button mAddButton; - /** The "remove" button for the tree view */ - private Button mRemoveButton; - /** The "up" button for the tree view */ - private Button mUpButton; - /** The "down" button for the tree view */ - private Button mDownButton; - /** The Managed Form used to create the master part */ - private IManagedForm mManagedForm; - /** Reference to the details part of the tree master block. */ - private DetailsPart mDetailsPart; - /** Reference to the clipboard for copy-paste */ - private Clipboard mClipboard; - /** Listener to refresh the tree viewer when the parent's node has been updated */ - private IUiUpdateListener mUiRefreshListener; - /** Listener to enable/disable the UI based on the application node's presence */ - private IUiUpdateListener mUiEnableListener; - /** An adapter/wrapper to use the add/remove/up/down tree edit actions. */ - private UiTreeActions mUiTreeActions; - /** - * True if the root node can be created on-demand (i.e. as needed as - * soon as children exist). False if an external entity controls the existence of the - * root node. In practise, this is false for the manifest application page (the actual - * "application" node is managed by the ApplicationToggle part) whereas it is true - * for all other tree pages. - */ - private final boolean mAutoCreateRoot; - - - /** - * Creates a new {@link MasterDetailsBlock} that will display all UI nodes matching the - * given filter in the given root node. - * - * @param editor The parent manifest editor. - * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are - * to be manipulated by this tree view. In general this is the manifest UI node or the - * application UI node. This cannot be null. - * @param autoCreateRoot True if the root node can be created on-demand (i.e. as needed as - * soon as children exist). False if an external entity controls the existence of the - * root node. In practise, this is false for the manifest application page (the actual - * "application" node is managed by the ApplicationToggle part) whereas it is true - * for all other tree pages. - * @param descriptorFilters A list of descriptors of the elements to be displayed as root in - * this tree view. Use null or an empty list to accept any kind of node. - * @param title Title for the section - * @param description Description for the section - */ - public UiTreeBlock(AndroidXmlEditor editor, - UiElementNode uiRootNode, - boolean autoCreateRoot, - ElementDescriptor[] descriptorFilters, - String title, - String description) { - mEditor = editor; - mUiRootNode = uiRootNode; - mAutoCreateRoot = autoCreateRoot; - mDescriptorFilters = descriptorFilters; - mTitle = title; - mDescription = description; - } - - /** @returns The container editor */ - AndroidXmlEditor getEditor() { - return mEditor; - } - - /** @returns The reference to the clipboard for copy-paste */ - Clipboard getClipboard() { - return mClipboard; - } - - /** @returns The master-detail part, composed of a main tree and an auxiliary detail part */ - ManifestSectionPart getMasterPart() { - return mMasterPart; - } - - /** - * Returns the {@link UiElementNode} for the current model. - * <p/> - * This is used by the content provider attached to {@link #mTreeViewer} since - * the uiRootNode changes after each call to - * {@link #changeRootAndDescriptors(UiElementNode, ElementDescriptor[], boolean)}. - */ - public UiElementNode getRootNode() { - return mUiRootNode; - } - - @Override - protected void createMasterPart(final IManagedForm managedForm, Composite parent) { - FormToolkit toolkit = managedForm.getToolkit(); - - mManagedForm = managedForm; - mMasterPart = new ManifestSectionPart(parent, toolkit); - Section section = mMasterPart.getSection(); - section.setText(mTitle); - section.setDescription(mDescription); - section.setLayout(new GridLayout()); - section.setLayoutData(new GridData(GridData.FILL_BOTH)); - - Composite grid = SectionHelper.createGridLayout(section, toolkit, 2); - - Tree tree = createTreeViewer(toolkit, grid, managedForm); - createButtons(toolkit, grid); - createTreeContextMenu(tree); - createSectionActions(section, toolkit); - } - - private void createSectionActions(Section section, FormToolkit toolkit) { - ToolBarManager manager = new ToolBarManager(SWT.FLAT); - manager.removeAll(); - - ToolBar toolbar = manager.createControl(section); - section.setTextClient(toolbar); - - ElementDescriptor[] descs = mDescriptorFilters; - if (descs == null && mUiRootNode != null) { - descs = mUiRootNode.getDescriptor().getChildren(); - } - - if (descs != null && descs.length > 1) { - for (ElementDescriptor desc : descs) { - manager.add(new DescriptorFilterAction(desc)); - } - } - - manager.add(new TreeSortAction()); - - manager.update(true /*force*/); - } - - /** - * Creates the tree and its viewer - * @return The tree control - */ - private Tree createTreeViewer(FormToolkit toolkit, Composite grid, - final IManagedForm managedForm) { - // Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here. - // However the class must be adapted to create an adapted toolkit tree. - final Tree tree = toolkit.createTree(grid, SWT.MULTI); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.widthHint = AndroidXmlEditor.TEXT_WIDTH_HINT; - gd.heightHint = TREE_HEIGHT_HINT; - tree.setLayoutData(gd); - - mTreeViewer = new TreeViewer(tree); - mTreeViewer.setContentProvider(new UiModelTreeContentProvider(mUiRootNode, mDescriptorFilters)); - mTreeViewer.setLabelProvider(new UiModelTreeLabelProvider()); - mTreeViewer.setInput("unused"); //$NON-NLS-1$ - - // Create a listener that reacts to selections on the tree viewer. - // When a selection is made, ask the managed form to propagate an event to - // all parts in the managed form. - // This is picked up by UiElementDetail.selectionChanged(). - mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - managedForm.fireSelectionChanged(mMasterPart, event.getSelection()); - adjustTreeButtons(event.getSelection()); - } - }); - - // Create three listeners: - // - One to refresh the tree viewer when the parent's node has been updated - // - One to refresh the tree viewer when the framework resources have changed - // - One to enable/disable the UI based on the application node's presence. - mUiRefreshListener = new IUiUpdateListener() { - @Override - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - mTreeViewer.refresh(); - } - }; - - mUiEnableListener = new IUiUpdateListener() { - @Override - public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) { - // The UiElementNode for the application XML node always exists, even - // if there is no corresponding XML node in the XML file. - // - // Normally, we enable the UI here if the XML node is not null. - // - // However if mAutoCreateRoot is true, the root node will be created on-demand - // so the tree/block is always enabled. - boolean exists = mAutoCreateRoot || (ui_node.getXmlNode() != null); - if (mMasterPart != null) { - Section section = mMasterPart.getSection(); - if (section.getEnabled() != exists) { - section.setEnabled(exists); - for (Control c : section.getChildren()) { - c.setEnabled(exists); - } - } - } - } - }; - - /** Listener to update the root node if the target of the file is changed because of a - * SDK location change or a project target change */ - final ITargetChangeListener targetListener = new TargetChangeListener() { - @Override - public IProject getProject() { - if (mEditor != null) { - return mEditor.getProject(); - } - - return null; - } - - @Override - public void reload() { - // If a details part has been created, we need to "refresh" it too. - if (mDetailsPart != null) { - // The details part does not directly expose access to its internal - // page book. Instead it is possible to resize the page book to 0 and then - // back to its original value, which has the side effect of removing all - // existing cached pages. - int limit = mDetailsPart.getPageLimit(); - mDetailsPart.setPageLimit(0); - mDetailsPart.setPageLimit(limit); - } - // Refresh the tree, preserving the selection if possible. - mTreeViewer.refresh(); - } - }; - - // Setup the listeners - changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */); - - // Listen on resource framework changes to refresh the tree - AdtPlugin.getDefault().addTargetListener(targetListener); - - // Remove listeners when the tree widget gets disposed. - tree.addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - if (mUiRootNode != null) { - UiElementNode node = mUiRootNode.getUiParent() != null ? - mUiRootNode.getUiParent() : - mUiRootNode; - - if (node != null) { - node.removeUpdateListener(mUiRefreshListener); - } - mUiRootNode.removeUpdateListener(mUiEnableListener); - } - - AdtPlugin.getDefault().removeTargetListener(targetListener); - if (mClipboard != null) { - mClipboard.dispose(); - mClipboard = null; - } - } - }); - - // Get a new clipboard reference. It is disposed when the tree is disposed. - mClipboard = new Clipboard(tree.getDisplay()); - - return tree; - } - - /** - * Changes the UI root node and the descriptor filters of the tree. - * <p/> - * This removes the listeners attached to the old root node and reattaches them to the - * new one. - * - * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are - * to be manipulated by this tree view. In general this is the manifest UI node or the - * application UI node. This cannot be null. - * @param descriptorFilters A list of descriptors of the elements to be displayed as root in - * this tree view. Use null or an empty list to accept any kind of node. - * @param forceRefresh If tree, forces the tree to refresh - */ - public void changeRootAndDescriptors(UiElementNode uiRootNode, - ElementDescriptor[] descriptorFilters, boolean forceRefresh) { - UiElementNode node; - - // Remove previous listeners if any - if (mUiRootNode != null) { - node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode; - node.removeUpdateListener(mUiRefreshListener); - mUiRootNode.removeUpdateListener(mUiEnableListener); - } - - mUiRootNode = uiRootNode; - mDescriptorFilters = descriptorFilters; - - mTreeViewer.setContentProvider( - new UiModelTreeContentProvider(mUiRootNode, mDescriptorFilters)); - - // Listen on structural changes on the root node of the tree - // If the node has a parent, listen on the parent instead. - if (mUiRootNode != null) { - node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode; - - if (node != null) { - node.addUpdateListener(mUiRefreshListener); - } - - // Use the root node to listen to its presence. - mUiRootNode.addUpdateListener(mUiEnableListener); - - // Initialize the enabled/disabled state - mUiEnableListener.uiElementNodeUpdated(mUiRootNode, null /* state, not used */); - } - - if (forceRefresh) { - mTreeViewer.refresh(); - } - - createSectionActions(mMasterPart.getSection(), mManagedForm.getToolkit()); - } - - /** - * Creates the buttons next to the tree. - */ - private void createButtons(FormToolkit toolkit, Composite grid) { - - mUiTreeActions = new UiTreeActions(); - - Composite button_grid = SectionHelper.createGridLayout(grid, toolkit, 1); - button_grid.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); - mAddButton = toolkit.createButton(button_grid, "Add...", SWT.PUSH); - SectionHelper.addControlTooltip(mAddButton, "Adds a new element."); - mAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | - GridData.VERTICAL_ALIGN_BEGINNING)); - - mAddButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeAdd(); - } - }); - - mRemoveButton = toolkit.createButton(button_grid, "Remove...", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Removes an existing selected element."); - mRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mRemoveButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeRemove(); - } - }); - - mUpButton = toolkit.createButton(button_grid, "Up", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element up."); - mUpButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mUpButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeUp(); - } - }); - - mDownButton = toolkit.createButton(button_grid, "Down", SWT.PUSH); - SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element down."); - mDownButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mDownButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - super.widgetSelected(e); - doTreeDown(); - } - }); - - adjustTreeButtons(TreeSelection.EMPTY); - } - - private void createTreeContextMenu(Tree tree) { - MenuManager menuManager = new MenuManager(); - menuManager.setRemoveAllWhenShown(true); - menuManager.addMenuListener(new IMenuListener() { - /** - * The menu is about to be shown. The menu manager has already been - * requested to remove any existing menu item. This method gets the - * tree selection and if it is of the appropriate type it re-creates - * the necessary actions. - */ - @Override - public void menuAboutToShow(IMenuManager manager) { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - doCreateMenuAction(manager, selected); - return; - } - doCreateMenuAction(manager, null /* ui_node */); - } - }); - Menu contextMenu = menuManager.createContextMenu(tree); - tree.setMenu(contextMenu); - } - - /** - * Adds the menu actions to the context menu when the given UI node is selected in - * the tree view. - * - * @param manager The context menu manager - * @param selected The UI nodes selected in the tree. Can be null, in which case the root - * is to be modified. - */ - private void doCreateMenuAction(IMenuManager manager, ArrayList<UiElementNode> selected) { - if (selected != null) { - boolean hasXml = false; - for (UiElementNode uiNode : selected) { - if (uiNode.getXmlNode() != null) { - hasXml = true; - break; - } - } - - if (hasXml) { - manager.add(new CopyCutAction(getEditor(), getClipboard(), - null, selected, true /* cut */)); - manager.add(new CopyCutAction(getEditor(), getClipboard(), - null, selected, false /* cut */)); - - // Can't paste with more than one element selected (the selection is the target) - if (selected.size() <= 1) { - // Paste is not valid if it would add a second element on a terminal element - // which parent is a document -- an XML document can only have one child. This - // means paste is valid if the current UI node can have children or if the - // parent is not a document. - UiElementNode ui_root = selected.get(0).getUiRoot(); - if (ui_root.getDescriptor().hasChildren() || - !(ui_root.getUiParent() instanceof UiDocumentNode)) { - manager.add(new PasteAction(getEditor(), getClipboard(), selected.get(0))); - } - } - manager.add(new Separator()); - } - } - - // Append "add" and "remove" actions. They do the same thing as the add/remove - // buttons on the side. - IconFactory factory = IconFactory.getInstance(); - - // "Add" makes sense only if there's 0 or 1 item selected since the - // one selected item becomes the target. - if (selected == null || selected.size() <= 1) { - manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-1$ - @Override - public void run() { - super.run(); - doTreeAdd(); - } - }); - } - - if (selected != null) { - if (selected != null) { - manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-1$ - @Override - public void run() { - super.run(); - doTreeRemove(); - } - }); - } - manager.add(new Separator()); - - manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-1$ - @Override - public void run() { - super.run(); - doTreeUp(); - } - }); - manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-1$ - @Override - public void run() { - super.run(); - doTreeDown(); - } - }); - } - } - - - /** - * This is called by the tree when a selection is made. - * It enables/disables the buttons associated with the tree depending on the current - * selection. - * - * @param selection The current tree selection (same as mTreeViewer.getSelection()) - */ - private void adjustTreeButtons(ISelection selection) { - mRemoveButton.setEnabled(!selection.isEmpty() && selection instanceof ITreeSelection); - mUpButton.setEnabled(canDoTreeUp(selection)); - mDownButton.setEnabled(canDoTreeDown(selection)); - } - - /** - * An adapter/wrapper to use the add/remove/up/down tree edit actions. - */ - private class UiTreeActions extends UiActions { - @Override - protected UiElementNode getRootNode() { - return mUiRootNode; - } - - @Override - protected void selectUiNode(UiElementNode uiNodeToSelect) { - // Select the new item - if (uiNodeToSelect != null) { - LinkedList<UiElementNode> segments = new LinkedList<UiElementNode>(); - for (UiElementNode ui_node = uiNodeToSelect; ui_node != mUiRootNode; - ui_node = ui_node.getUiParent()) { - segments.add(0, ui_node); - } - if (segments.size() > 0) { - mTreeViewer.setSelection(new TreeSelection(new TreePath(segments.toArray()))); - } else { - mTreeViewer.setSelection(null); - } - } - } - - @Override - public void commitPendingXmlChanges() { - commitManagedForm(); - } - } - - /** - * Filters an ITreeSelection to only keep the {@link UiElementNode}s (in case there's - * something else in there). - * - * @return A new list of {@link UiElementNode} with at least one item or null. - */ - private ArrayList<UiElementNode> filterSelection(ITreeSelection selection) { - ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>(); - - for (Iterator<Object> it = selection.iterator(); it.hasNext(); ) { - Object selectedObj = it.next(); - - if (selectedObj instanceof UiElementNode) { - selected.add((UiElementNode) selectedObj); - } - } - - return selected.size() > 0 ? selected : null; - } - - /** - * Called when the "Add..." button next to the tree view is selected. - * - * Displays a selection dialog that lets the user select which kind of node - * to create, depending on the current selection. - */ - private void doTreeAdd() { - UiElementNode ui_node = mUiRootNode; - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ITreeSelection tree_selection = (ITreeSelection) selection; - Object first = tree_selection.getFirstElement(); - if (first != null && first instanceof UiElementNode) { - ui_node = (UiElementNode) first; - } - } - - mUiTreeActions.doAdd( - ui_node, - mDescriptorFilters, - mTreeViewer.getControl().getShell(), - (ILabelProvider) mTreeViewer.getLabelProvider()); - } - - /** - * Called when the "Remove" button is selected. - * - * If the tree has a selection, remove it. - * This simply deletes the XML node attached to the UI node: when the XML model fires the - * update event, the tree will get refreshed. - */ - protected void doTreeRemove() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - mUiTreeActions.doRemove(selected, mTreeViewer.getControl().getShell()); - } - } - - /** - * Called when the "Up" button is selected. - * <p/> - * If the tree has a selection, move it up, either in the child list or as the last child - * of the previous parent. - */ - protected void doTreeUp() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - mUiTreeActions.doUp(selected, mDescriptorFilters); - } - } - - /** - * Checks whether the "up" action can be done on the current selection. - * - * @param selection The current tree selection. - * @return True if all the selected nodes can be moved up. - */ - protected boolean canDoTreeUp(ISelection selection) { - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - return mUiTreeActions.canDoUp(selected, mDescriptorFilters); - } - - return false; - } - - /** - * Called when the "Down" button is selected. - * - * If the tree has a selection, move it down, either in the same child list or as the - * first child of the next parent. - */ - protected void doTreeDown() { - ISelection selection = mTreeViewer.getSelection(); - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - mUiTreeActions.doDown(selected, mDescriptorFilters); - } - } - - /** - * Checks whether the "down" action can be done on the current selection. - * - * @param selection The current tree selection. - * @return True if all the selected nodes can be moved down. - */ - protected boolean canDoTreeDown(ISelection selection) { - if (!selection.isEmpty() && selection instanceof ITreeSelection) { - ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection); - return mUiTreeActions.canDoDown(selected, mDescriptorFilters); - } - - return false; - } - - /** - * Commits the current managed form (the one associated with our master part). - * As a side effect, this will commit the current UiElementDetails page. - */ - void commitManagedForm() { - if (mManagedForm != null) { - mManagedForm.commit(false /* onSave */); - } - } - - /* Implements ICommitXml for CopyCutAction */ - @Override - public void commitPendingXmlChanges() { - commitManagedForm(); - } - - @Override - protected void createToolBarActions(IManagedForm managedForm) { - // Pass. Not used, toolbar actions are defined by createSectionActions(). - } - - @Override - protected void registerPages(DetailsPart inDetailsPart) { - // Keep a reference on the details part (the super class doesn't provide a getter - // for it.) - mDetailsPart = inDetailsPart; - - // The page selection mechanism does not use pages registered by association with - // a node class. Instead it uses a custom details page provider that provides a - // new UiElementDetail instance for each node instance. A limit of 5 pages is - // then set (the value is arbitrary but should be reasonable) for the internal - // page book. - inDetailsPart.setPageLimit(5); - - final UiTreeBlock tree = this; - - inDetailsPart.setPageProvider(new IDetailsPageProvider() { - @Override - public IDetailsPage getPage(Object key) { - if (key instanceof UiElementNode) { - return new UiElementDetail(tree); - } - return null; - } - - @Override - public Object getPageKey(Object object) { - return object; // use node object as key - } - }); - } - - /** - * An alphabetic sort action for the tree viewer. - */ - private class TreeSortAction extends Action { - - private ViewerComparator mComparator; - - public TreeSortAction() { - super("Sorts elements alphabetically.", AS_CHECK_BOX); - setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$ - - if (mTreeViewer != null) { - boolean is_sorted = mTreeViewer.getComparator() != null; - setChecked(is_sorted); - } - } - - /** - * Called when the button is selected. Toggles the tree viewer comparator. - */ - @Override - public void run() { - if (mTreeViewer == null) { - notifyResult(false /*success*/); - return; - } - - ViewerComparator comp = mTreeViewer.getComparator(); - if (comp != null) { - // Tree is currently sorted. - // Save currently comparator and remove it - mComparator = comp; - mTreeViewer.setComparator(null); - } else { - // Tree is not currently sorted. - // Reuse or add a new comparator. - if (mComparator == null) { - mComparator = new ViewerComparator(); - } - mTreeViewer.setComparator(mComparator); - } - - notifyResult(true /*success*/); - } - } - - /** - * A filter on descriptor for the tree viewer. - * <p/> - * The tree viewer will contain many of these actions and only one can be enabled at a - * given time. When no action is selected, everything is displayed. - * <p/> - * Since "radio"-like actions do not allow for unselecting all of them, we manually - * handle the exclusive radio button-like property: when an action is selected, it manually - * removes all other actions as needed. - */ - private class DescriptorFilterAction extends Action { - - private final ElementDescriptor mDescriptor; - private ViewerFilter mFilter; - - public DescriptorFilterAction(ElementDescriptor descriptor) { - super(String.format("Displays only %1$s elements.", descriptor.getUiName()), - AS_CHECK_BOX); - - mDescriptor = descriptor; - setImageDescriptor(descriptor.getImageDescriptor()); - } - - /** - * Called when the button is selected. - * <p/> - * Find any existing {@link DescriptorFilter}s and remove them. Install ours. - */ - @Override - public void run() { - super.run(); - - if (isChecked()) { - if (mFilter == null) { - // create filter when required - mFilter = new DescriptorFilter(this); - } - - // we add our filter first, otherwise the UI might show the full list - mTreeViewer.addFilter(mFilter); - - // Then remove the any other filters except ours. There should be at most - // one other filter, since that's how the actions are made to look like - // exclusive radio buttons. - for (ViewerFilter filter : mTreeViewer.getFilters()) { - if (filter instanceof DescriptorFilter && filter != mFilter) { - DescriptorFilterAction action = ((DescriptorFilter) filter).getAction(); - action.setChecked(false); - mTreeViewer.removeFilter(filter); - } - } - } else if (mFilter != null){ - mTreeViewer.removeFilter(mFilter); - } - } - - /** - * Filters the tree viewer for the given descriptor. - * <p/> - * The filter is linked to the action so that an action can iterate through the list - * of filters and un-select the actions. - */ - private class DescriptorFilter extends ViewerFilter { - - private final DescriptorFilterAction mAction; - - public DescriptorFilter(DescriptorFilterAction action) { - mAction = action; - } - - public DescriptorFilterAction getAction() { - return mAction; - } - - /** - * Returns true if an element should be displayed, that if the element or - * any of its parent matches the requested descriptor. - */ - @Override - public boolean select(Viewer viewer, Object parentElement, Object element) { - while (element instanceof UiElementNode) { - UiElementNode uiNode = (UiElementNode)element; - if (uiNode.getDescriptor() == mDescriptor) { - return true; - } - element = uiNode.getUiParent(); - } - return false; - } - } - } - -} |