FileDocCategorySizeDatePackage
UiContentOutlinePage.javaAPI DocAndroid 1.5 API23296Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.editors.layout

UiContentOutlinePage

public class UiContentOutlinePage extends org.eclipse.gef.ui.parts.ContentOutlinePage
Implementation of the {@link ContentOutlinePage} to display {@link UiElementNode}.

Fields Summary
private AbstractGraphicalLayoutEditor
mEditor
private org.eclipse.jface.action.Action
mAddAction
private org.eclipse.jface.action.Action
mDeleteAction
private org.eclipse.jface.action.Action
mUpAction
private org.eclipse.jface.action.Action
mDownAction
private UiOutlineActions
mUiActions
Constructors Summary
public UiContentOutlinePage(AbstractGraphicalLayoutEditor editor, org.eclipse.gef.EditPartViewer viewer)


          
        super(viewer);
        mEditor = editor;
        IconFactory factory = IconFactory.getInstance();
        
        mAddAction = new Action("Add...") {
            @Override
            public void run() {
                List<UiElementNode> nodes = getModelSelections();
                UiElementNode node = nodes != null && nodes.size() > 0 ? nodes.get(0) : null;
                
                mUiActions.doAdd(node, viewer.getControl().getShell());
            }
        };
        mAddAction.setToolTipText("Adds a new element.");
        mAddAction.setImageDescriptor(factory.getImageDescriptor("add")); //$NON-NLS-1$

        mDeleteAction = new Action("Remove...") {
            @Override
            public void run() {
                List<UiElementNode> nodes = getModelSelections();
                
                mUiActions.doRemove(nodes, viewer.getControl().getShell());
            }
        };
        mDeleteAction.setToolTipText("Removes an existing selected element.");
        mDeleteAction.setImageDescriptor(factory.getImageDescriptor("delete")); //$NON-NLS-1$

        mUpAction = new Action("Up") {
            @Override
            public void run() {
                List<UiElementNode> nodes = getModelSelections();
                
                mUiActions.doUp(nodes);
            }
        };
        mUpAction.setToolTipText("Moves the selected element up");
        mUpAction.setImageDescriptor(factory.getImageDescriptor("up")); //$NON-NLS-1$

        mDownAction = new Action("Down") {
            @Override
            public void run() {
                List<UiElementNode> nodes = getModelSelections();
                
                mUiActions.doDown(nodes);
            }
        };
        mDownAction.setToolTipText("Moves the selected element down");
        mDownAction.setImageDescriptor(factory.getImageDescriptor("down")); //$NON-NLS-1$

        // all actions disabled by default.
        mAddAction.setEnabled(false);
        mDeleteAction.setEnabled(false);
        mUpAction.setEnabled(false);
        mDownAction.setEnabled(false);

        addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                ISelection selection = event.getSelection();
                
                // the selection is never empty. The least it'll contain is the
                // UiDocumentTreeEditPart object.
                if (selection instanceof StructuredSelection) {
                    StructuredSelection structSel = (StructuredSelection)selection;

                    if (structSel.size() == 1 &&
                            structSel.getFirstElement() instanceof UiDocumentTreeEditPart) {
                        mDeleteAction.setEnabled(false);
                        mUpAction.setEnabled(false);
                        mDownAction.setEnabled(false);
                    } else {
                        mDeleteAction.setEnabled(true);
                        mUpAction.setEnabled(true);
                        mDownAction.setEnabled(true);
                    }

                    // the "add" button is always enabled, in order to be able to set the
                    // initial root node
                    mAddAction.setEnabled(true);
                }
            }
        });
    
Methods Summary
voidbreakConnectionWithEditor()

        // unhook outline viewer
        mEditor.getSelectionSynchronizer().removeViewer(getViewer());
    
public voidcreateControl(org.eclipse.swt.widgets.Composite parent)

        // create outline viewer page
        getViewer().createControl(parent);

        // configure outline viewer
        getViewer().setEditPartFactory(new UiElementTreeEditPartFactory());

        setupOutline();
        setupContextMenu();
        setupTooltip();
        setupDoubleClick();
    
public voiddispose()

        breakConnectionWithEditor();

        // dispose
        super.dispose();
    
private voiddoCreateMenuAction(org.eclipse.jface.action.IMenuManager manager, java.util.List selected)
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 node selected in the tree. Can be null, in which case the root is to be modified.

        
        if (selected != null) {
            boolean hasXml = false;
            for (UiElementNode uiNode : selected) {
                if (uiNode.getXmlNode() != null) {
                    hasXml = true;
                    break;
                }
            }

            if (hasXml) {
                manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
                        null, selected, true /* cut */));
                manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.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(mEditor.getLayoutEditor(),
                                mEditor.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.
        //
        // "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(mAddAction);
        }

        if (selected != null) {
            manager.add(mDeleteAction);
            manager.add(new Separator());
            
            manager.add(mUpAction);
            manager.add(mDownAction);
        }

        if (selected != null && selected.size() == 1) {
            manager.add(new Separator());
            
            Action propertiesAction = new Action("Properties") {
                @Override
                public void run() {
                    EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
                            true /* activate */);
                }
            };
            propertiesAction.setToolTipText("Displays properties of the selected element.");
            manager.add(propertiesAction);
        }
    
private com.android.ide.eclipse.editors.layout.parts.UiElementTreeEditPartfindPartForModel(com.android.ide.eclipse.editors.layout.parts.UiElementTreeEditPart rootPart, com.android.ide.eclipse.editors.uimodel.UiElementNode uiNode)
Utility method that tries to find an edit part that matches a given model UI node.

param
rootPart The root of the viewer edit parts
param
uiNode The UI node model to find
return
The part that matches the model or null if it's not in the sub tree.

        if (rootPart.getModel() == uiNode) {
            return rootPart;
        }
        
        for (Object part : rootPart.getChildren()) {
            if (part instanceof UiElementTreeEditPart) {
                UiElementTreeEditPart found = findPartForModel(
                        (UiElementTreeEditPart) part, uiNode);
                if (found != null) {
                    return found;
                }
            }
        }

        return null;
    
public org.eclipse.swt.widgets.ControlgetControl()

        return getViewer().getControl();
    
private java.util.ListgetModelSelections()
Returns the currently selected model element, which is either an {@link UiViewTreeEditPart} or an {@link UiLayoutTreeEditPart}.

Returns null if there is no selection or if the implicit root is "selected" (which actually represents the lack of a real element selection.)


        List<UiElementTreeEditPart> parts = getViewerSelections();

        if (parts != null) {
            ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
            
            for (UiElementTreeEditPart part : parts) {
                if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
                    selected.add((UiElementNode) part.getModel());
                }
            }
            
            return selected.size() > 0 ? selected : null;
        }
        
        return null;
    
private java.util.ListgetViewerSelections()
Returns the currently selected element, if any, in the viewer. This returns the viewer's elements (i.e. an {@link UiElementTreeEditPart}) and not the underlying model node.

When there is no actual selection, this might still return the root node, which is of type {@link UiDocumentTreeEditPart}.

        ISelection selection = getSelection();
        if (selection instanceof StructuredSelection) {
            StructuredSelection structuredSelection = (StructuredSelection)selection;
            
            if (structuredSelection.size() > 0) {
                ArrayList<UiElementTreeEditPart> selected = new ArrayList<UiElementTreeEditPart>();
                
                for (Iterator it = structuredSelection.iterator(); it.hasNext(); ) {
                    Object selectedObj = it.next();
                
                    if (selectedObj instanceof UiElementTreeEditPart) {
                        selected.add((UiElementTreeEditPart) selectedObj);
                    }
                }
                
                return selected.size() > 0 ? selected : null;
            }
        }
        
        return null;
    
public voidreloadModel()
Updates the outline view with the model of the {@link GraphicalLayoutEditor}.

This attemps to preserve the selection, if any.

        // Attemps to preserve the UiNode selection, if any
        List<UiElementNode> uiNodes = null;
        try {
            // get current selection using the model rather than the edit part as
            // reloading the content may change the actual edit part.
            uiNodes = getModelSelections();

            // perform the update
            getViewer().setContents(mEditor.getModel());

        } finally {
            // restore selection
            if (uiNodes != null) {
                setModelSelection(uiNodes.get(0));
            }
        }
    
public voidsetActionBars(org.eclipse.ui.IActionBars actionBars)

        IToolBarManager toolBarManager = actionBars.getToolBarManager();
        toolBarManager.add(mAddAction);
        toolBarManager.add(mDeleteAction);
        toolBarManager.add(new Separator());
        toolBarManager.add(mUpAction);
        toolBarManager.add(mDownAction);
        
        IMenuManager menuManager = actionBars.getMenuManager();
        menuManager.add(mAddAction);
        menuManager.add(mDeleteAction);
        menuManager.add(new Separator());
        menuManager.add(mUpAction);
        menuManager.add(mDownAction);
    
private voidsetModelSelection(com.android.ide.eclipse.editors.uimodel.UiElementNode uiNodeToSelect)
Selects the corresponding model element in the tree viewer.

        if (uiNodeToSelect != null) {
            
            // find an edit part that has the requested model element
            UiElementTreeEditPart part = findPartForModel(
                    (UiElementTreeEditPart) getViewer().getContents(),
                    uiNodeToSelect);
            
            // if we found a part, select it and reveal it
            if (part != null) {
                setViewerSelection(part);
                getViewer().reveal(part);
            }
        }
    
voidsetNewEditor(GraphicalLayoutEditor editor)

        mEditor = editor;
        setupOutline();
    
private voidsetViewerSelection(com.android.ide.eclipse.editors.layout.parts.UiElementTreeEditPart selectedPart)
Selects the corresponding edit part in the tree viewer.

        if (selectedPart != null && !(selectedPart instanceof UiDocumentTreeEditPart)) {
            LinkedList<UiElementTreeEditPart> segments = new LinkedList<UiElementTreeEditPart>();
            for (UiElementTreeEditPart part = selectedPart;
                    !(part instanceof UiDocumentTreeEditPart);
                    part = (UiElementTreeEditPart) part.getParent()) {
                segments.add(0, part);
            }
            setSelection(new TreeSelection(new TreePath(segments.toArray())));
        }
    
private voidsetupContextMenu()

        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.
             */
           public void menuAboutToShow(IMenuManager manager) {
               List<UiElementNode> selected = getModelSelections();
               
               if (selected != null) {
                   doCreateMenuAction(manager, selected);
                   return;
               }
               doCreateMenuAction(manager, null /* ui_node */);
            } 
        });
        Control control = getControl();
        Menu contextMenu = menuManager.createContextMenu(control);
        control.setMenu(contextMenu);
    
private voidsetupDoubleClick()
Sets up double-click action on the tree.

By default, double-click (a.k.a. "default selection") on a valid list item will show the property view.

        final Tree tree = (Tree) getControl();

        tree.addListener(SWT.DefaultSelection, new Listener() {
            public void handleEvent(Event event) {
                EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
                        true /* activate */);
            }
        });
    
private voidsetupOutline()

        getViewer().setEditDomain(mEditor.getEditDomain());

        // hook outline viewer
        mEditor.getSelectionSynchronizer().addViewer(getViewer());

        // initialize outline viewer with model
        getViewer().setContents(mEditor.getModel());
    
private voidsetupTooltip()
Sets up a custom tooltip when hovering over tree items.

The tooltip will display the element's javadoc, if any, or the item's getText otherwise.

        final Tree tree = (Tree) getControl();
        
        /*
         * Reference: 
         * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
         */
        
        final Listener listener = new Listener() {
            Shell tip = null;
            Label label  = null;
            
            public void handleEvent(Event event) {
                switch(event.type) {
                case SWT.Dispose:
                case SWT.KeyDown:
                case SWT.MouseExit:
                case SWT.MouseDown:
                case SWT.MouseMove:
                    if (tip != null) {
                        tip.dispose();
                        tip = null;
                        label = null;
                    }
                    break;
                case SWT.MouseHover:
                    if (tip != null) {
                        tip.dispose();
                        tip = null;
                        label = null;
                    }

                    String tooltip = null;
                    
                    TreeItem item = tree.getItem(new Point(event.x, event.y));
                    if (item != null) {
                        Object data = item.getData();
                        if (data instanceof UiElementTreeEditPart) {
                            Object model = ((UiElementTreeEditPart) data).getModel();
                            if (model instanceof UiElementNode) {
                                tooltip = ((UiElementNode) model).getDescriptor().getTooltip();
                            }
                        }

                        if (tooltip == null) {
                            tooltip = item.getText();
                        } else {
                            tooltip = item.getText() + ":\r" + tooltip;
                        }
                    }
                    
                    
                    if (tooltip != null) {
                        Shell shell = tree.getShell();
                        Display display = tree.getDisplay();
                        
                        tip = new Shell(shell, SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
                        tip.setBackground(display .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
                        FillLayout layout = new FillLayout();
                        layout.marginWidth = 2;
                        tip.setLayout(layout);
                        label = new Label(tip, SWT.NONE);
                        label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
                        label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
                        label.setData("_TABLEITEM", item);
                        label.setText(tooltip);
                        label.addListener(SWT.MouseExit, this);
                        label.addListener(SWT.MouseDown, this);
                        Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
                        Rectangle rect = item.getBounds(0);
                        Point pt = tree.toDisplay(rect.x, rect.y);
                        tip.setBounds(pt.x, pt.y, size.x, size.y);
                        tip.setVisible(true);
                    }
                }
            }
        };
        
        tree.addListener(SWT.Dispose, listener);
        tree.addListener(SWT.KeyDown, listener);
        tree.addListener(SWT.MouseMove, listener);
        tree.addListener(SWT.MouseHover, listener);