com.siteview.mde.internal.ui.editor.schema.ElementSection.java Source code

Java tutorial

Introduction

Here is the source code for com.siteview.mde.internal.ui.editor.schema.ElementSection.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 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.siteview.mde.internal.ui.editor.schema;

import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import com.siteview.mde.core.IModelChangedEvent;
import com.siteview.mde.internal.core.ICoreConstants;
import com.siteview.mde.internal.core.ischema.*;
import com.siteview.mde.internal.core.schema.*;
import com.siteview.mde.internal.ui.MDEPlugin;
import com.siteview.mde.internal.ui.MDEUIMessages;
import com.siteview.mde.internal.ui.editor.*;
import com.siteview.mde.internal.ui.editor.actions.CollapseAction;
import com.siteview.mde.internal.ui.elements.DefaultContentProvider;
import com.siteview.mde.internal.ui.parts.TreePart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

public class ElementSection extends TreeSection {
    private TreeViewer fTreeViewer;
    private Schema fSchema;
    private NewElementAction fNewElementAction = new NewElementAction();
    private NewAttributeAction fNewAttributeAction = new NewAttributeAction();
    private Clipboard fClipboard;
    private SchemaRearranger fRearranger;
    private CollapseAction fCollapseAction;

    class ContentProvider extends DefaultContentProvider implements ITreeContentProvider {
        public Object[] getElements(Object object) {
            if (object instanceof Schema) {
                Schema schema = (Schema) object;
                return schema.getElements();
            }
            return new Object[0];
        }

        public Object[] getChildren(Object parent) {
            Object[] children = new Object[0];
            if (parent instanceof ISchemaElement) {
                Object[] types = new Object[0];
                Object[] attributes = ((ISchemaElement) parent).getAttributes();
                ISchemaType type = ((ISchemaElement) parent).getType();
                if (type instanceof ISchemaComplexType) {
                    Object compositor = ((ISchemaComplexType) type).getCompositor();
                    if (compositor != null)
                        types = new Object[] { compositor };
                }
                children = new Object[types.length + attributes.length];
                System.arraycopy(types, 0, children, 0, types.length);
                System.arraycopy(attributes, 0, children, types.length, attributes.length);
            } else if (parent instanceof ISchemaCompositor) {
                children = ((ISchemaCompositor) parent).getChildren();
            }
            return children;
        }

        public Object getParent(Object child) {
            if (child instanceof ISchemaObject)
                return ((ISchemaObject) child).getParent();
            return null;
        }

        public boolean hasChildren(Object parent) {
            if (parent instanceof ISchemaAttribute || parent instanceof ISchemaObjectReference)
                return false;
            return getChildren(parent).length > 0;
        }
    }

    public ElementSection(MDEFormPage page, Composite parent) {
        super(page, parent, Section.DESCRIPTION,
                new String[] { MDEUIMessages.SchemaEditor_ElementSection_newElement,
                        MDEUIMessages.SchemaEditor_ElementSection_newAttribute,
                        MDEUIMessages.SchemaEditor_ElementSection_newChoice,
                        MDEUIMessages.SchemaEditor_ElementSection_newSequence,
                        MDEUIMessages.SchemaEditor_ElementSection_remove });
        getSection().setText(MDEUIMessages.SchemaEditor_ElementSection_title);
        getSection().setDescription(MDEUIMessages.SchemaEditor_ElementSection_desc);
    }

    public void createClient(Section section, FormToolkit toolkit) {
        Composite container = createClientContainer(section, 2, toolkit);
        createTree(container, toolkit);
        toolkit.paintBordersFor(container);
        section.setClient(container);
        initialize();
        createSectionToolbar(section, toolkit);
    }

    /**
     * @param section
     * @param toolkit
     */
    private void createSectionToolbar(Section section, FormToolkit toolkit) {

        ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
        ToolBar toolbar = toolBarManager.createControl(section);
        final Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
        toolbar.setCursor(handCursor);
        // Cursor needs to be explicitly disposed
        toolbar.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if ((handCursor != null) && (handCursor.isDisposed() == false)) {
                    handCursor.dispose();
                }
            }
        });
        // Add collapse action to the tool bar
        fCollapseAction = new CollapseAction(fTreeViewer, MDEUIMessages.ExtensionsPage_collapseAll);
        toolBarManager.add(fCollapseAction);

        toolBarManager.update(true);

        section.setTextClient(toolbar);
    }

    private void createTree(Composite container, FormToolkit toolkit) {
        TreePart treePart = getTreePart();
        createViewerPartControl(container, SWT.MULTI, 2, toolkit);
        fTreeViewer = treePart.getTreeViewer();
        fTreeViewer.setContentProvider(new ContentProvider());
        fTreeViewer.setLabelProvider(MDEPlugin.getDefault().getLabelProvider());
        MDEPlugin.getDefault().getLabelProvider().connect(this);
        initDragAndDrop();
    }

    protected void initDragAndDrop() {
        fClipboard = new Clipboard(fTreeViewer.getControl().getDisplay());
        int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
        Transfer[] transfers = new Transfer[] { ModelDataTransfer.getInstance(), TextTransfer.getInstance() };
        ElementSectionDragAdapter dragAdapter = new ElementSectionDragAdapter(fTreeViewer);
        fTreeViewer.addDragSupport(ops, transfers, dragAdapter);
        fTreeViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers,
                new ElementSectionDropAdapter(dragAdapter, this));
    }

    protected TreeViewer getTreeViewer() {
        return fTreeViewer;
    }

    public void refresh() {
        fTreeViewer.refresh();
        super.refresh();

        if (fTreeViewer.getSelection().isEmpty() && fSchema.getElementCount() > 0) {
            fTreeViewer.setSelection(new StructuredSelection(fSchema.getElements()[0]));
        }
    }

    protected void buttonSelected(int index) {
        switch (index) {
        case 0:
            handleNewElement();
            break;
        case 1:
            handleNewAttribute();
            break;
        case 2:
            addCompositor(ISchemaCompositor.CHOICE);
            break;
        case 3:
            addCompositor(ISchemaCompositor.SEQUENCE);
            break;
        case 4:
            final ISelection selection = fTreeViewer.getSelection();
            handleDelete((IStructuredSelection) selection);
            break;
        }
    }

    private void addCompositor(int kind) {
        Object selection = ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement();
        ISchemaElement sourceElement = null;
        Object current = selection;
        while (current instanceof ISchemaCompositor)
            current = ((ISchemaCompositor) current).getParent();
        if (current instanceof ISchemaElement)
            sourceElement = (ISchemaElement) current;
        if (sourceElement != null)
            new NewCompositorAction(sourceElement, selection, kind).run();
    }

    public void dispose() {
        if (fClipboard != null) {
            fClipboard.dispose();
            fClipboard = null;
        }
        MDEPlugin.getDefault().getLabelProvider().disconnect(this);
        super.dispose();
    }

    public boolean doGlobalAction(String actionId) {
        boolean cut = actionId.equals(ActionFactory.CUT.getId());
        if (cut || actionId.equals(ActionFactory.DELETE.getId())) {
            // Get the current selection
            IStructuredSelection sel = (IStructuredSelection) fTreeViewer.getSelection();
            // Get the first selected object
            Object selectedObject = sel.getFirstElement();
            // Ensure we have a selection
            if (selectedObject == null) {
                return true;
            }
            handleDelete(sel);
            // if cutting delete here and let the editor transfer
            // the selection to the clipboard
            return !cut;
        }
        if (actionId.equals(ActionFactory.PASTE.getId())) {
            doPaste();
            return true;
        }
        return false;
    }

    public boolean setFormInput(Object object) {
        if (object instanceof ISchemaElement || object instanceof ISchemaAttribute
                || object instanceof ISchemaCompositor) {
            fTreeViewer.setSelection(new StructuredSelection(object), true);

            ISelection selection = fTreeViewer.getSelection();
            if (selection != null && !selection.isEmpty())
                return true;
            if (object instanceof ISchemaElement) {
                ISchemaElement found = fSchema.findElement(((ISchemaElement) object).getName());
                if (found != null)
                    fTreeViewer.setSelection(new StructuredSelection(found), true);
                return found != null;
            }
        }
        return false;
    }

    protected void fillContextMenu(IMenuManager manager) {
        final ISelection selection = fTreeViewer.getSelection();
        final Object object = ((IStructuredSelection) selection).getFirstElement();

        MenuManager submenu = new MenuManager(MDEUIMessages.Menus_new_label);
        if (object == null) {
            fNewElementAction.setSchema(fSchema);
            fNewElementAction.setEnabled(fSchema.isEditable());
            submenu.add(fNewElementAction);
        }
        if (object != null) {
            ISchemaElement element = null;
            if (object instanceof SchemaElement)
                element = (SchemaElement) object;
            else if (object instanceof SchemaAttribute)
                element = (SchemaElement) ((SchemaAttribute) object).getParent();

            if (element != null && !(element instanceof ISchemaRootElement)
                    && !(element instanceof ISchemaObjectReference)) {
                fNewAttributeAction.setElement((SchemaElement) element);
                fNewAttributeAction.setEnabled(fSchema.isEditable());
                submenu.add(fNewAttributeAction);
            }
        }
        if (object instanceof SchemaElement || object instanceof SchemaCompositor) {
            ISchemaElement sourceElement = null;
            ISchemaObject schemaObject = (ISchemaObject) object;
            while (schemaObject != null) {
                if (schemaObject instanceof ISchemaElement) {
                    sourceElement = (ISchemaElement) schemaObject;
                    break;
                }
                schemaObject = schemaObject.getParent();
            }
            if (sourceElement != null) {
                if (object instanceof SchemaCompositor || sourceElement.getType() instanceof ISchemaSimpleType
                        || ((ISchemaComplexType) sourceElement.getType()).getCompositor() == null) {
                    if (submenu.getItems().length > 0)
                        submenu.add(new Separator());
                    submenu.add(new NewCompositorAction(sourceElement, object, ISchemaCompositor.CHOICE));
                    submenu.add(new NewCompositorAction(sourceElement, object, ISchemaCompositor.SEQUENCE));
                }
                if (object instanceof SchemaCompositor) {
                    boolean seperatorAdded = false;
                    ISchemaElement[] elements = sourceElement.getSchema().getResolvedElements();
                    Arrays.sort(elements);
                    for (int i = 0; i < elements.length; i++) {
                        if (!(elements[i] instanceof SchemaRootElement)) {
                            if (!seperatorAdded) {
                                submenu.add(new Separator());
                                seperatorAdded = true;
                            }
                            submenu.add(new NewReferenceAction(sourceElement, object, elements[i]));
                        }
                    }
                }
            }
        }
        manager.add(submenu);
        if (object != null) {
            if (!(object instanceof ISchemaRootElement)) {
                if (manager.getItems().length > 0)
                    manager.add(new Separator());
                if (!(object instanceof ISchemaAttribute
                        && ((ISchemaAttribute) object).getParent() instanceof ISchemaRootElement)) {
                    Action deleteAction = new Action() {
                        public void run() {
                            handleDelete((IStructuredSelection) selection);
                        }
                    };
                    deleteAction.setText(MDEUIMessages.Actions_delete_label);
                    deleteAction.setEnabled(fSchema.isEditable());
                    manager.add(deleteAction);
                }
            }
        }
        getPage().getMDEEditor().getContributor().contextMenuAboutToShow(manager);
        manager.add(new Separator());
    }

    private void handleDelete(IStructuredSelection selection) {
        IStructuredSelection nextSelection = null;
        Object selectionSource = null;
        for (Iterator iter = selection.iterator(); iter.hasNext();) {
            Object thisObject = iter.next();
            // Do the delete and generate a new selection in one of the following cases:
            //   1. No selection has been generated
            //   2. This object is higher up in the hierarchy than the previous
            //      object used to generate the selection
            //   3. The object selected for deletion is currently set as the next selection
            IStructuredSelection result = handleDelete(thisObject,
                    nextSelection == null || schemaObjectHigherThan(thisObject, selectionSource)
                            || nextSelection.getFirstElement().equals(thisObject));
            if (result != null) {
                nextSelection = result;
                selectionSource = thisObject;
            }
        }
        if (nextSelection != null)
            getTreeViewer().setSelection(nextSelection);
    }

    private IStructuredSelection handleDelete(Object object, boolean generateSelection) {
        IStructuredSelection newSelection = null;
        if (!isEditable()) {
            Display.getCurrent().beep();
        } else if (object instanceof ISchemaRootElement) {
            // Semantic rule: The root "extension" element of a schema
            // cannot be removed

            // Produce audible beep
            Display.getCurrent().beep();
        } else if (object instanceof SchemaElementReference) {
            newSelection = handleReferenceDelete((SchemaElementReference) object, generateSelection);
        } else if (object instanceof ISchemaElement) {
            newSelection = handleElementDelete((ISchemaElement) object, generateSelection);
        } else if (object instanceof ISchemaAttribute) {
            ISchemaAttribute att = (ISchemaAttribute) object;
            if (!(att.getParent() instanceof ISchemaRootElement)) {
                newSelection = handleAttributeDelete(att, generateSelection);
            } else {
                // Semantic rule: Attributes of the root "extension" element
                // of a schema cannot be removed

                // Produce audible beep
                Display.getCurrent().beep();
            }
        } else if (object instanceof ISchemaCompositor) {
            newSelection = handleCompositorDelete((ISchemaCompositor) object, generateSelection);
        }
        return newSelection;
    }

    private IStructuredSelection handleReferenceDelete(SchemaElementReference ref, boolean generateSelection) {
        IStructuredSelection newSelection = null;
        if (generateSelection) {
            SchemaCompositor parent = (SchemaCompositor) ref.getParent();
            ISchemaObject[] children = parent.getChildren();
            int index = getNewSelectionIndex(getArrayIndex(children, ref), children.length);
            if (index == -1)
                newSelection = new StructuredSelection(parent);
            else
                newSelection = new StructuredSelection(children[index]);
        }
        fRearranger.deleteReference(ref);
        return newSelection;
    }

    private IStructuredSelection handleElementDelete(ISchemaElement element, boolean generateSelection) {
        IStructuredSelection newSelection = null;
        if (generateSelection) {
            ISchema parent = element.getSchema();
            ISchemaElement[] children = parent.getElements();
            int index = getNewSelectionIndex(getArrayIndex(children, element), children.length);
            if (index != -1)
                newSelection = new StructuredSelection(children[index]);
        }
        fRearranger.deleteElement(element);
        return newSelection;
    }

    private IStructuredSelection handleAttributeDelete(ISchemaAttribute att, boolean generateSelection) {
        IStructuredSelection newSelection = null;
        if (generateSelection) {
            ISchemaElement parent = (ISchemaElement) att.getParent();
            ISchemaAttribute[] children = parent.getAttributes();
            int index = getNewSelectionIndex(getArrayIndex(children, att), children.length);
            if (index == -1) {
                ISchemaType type = parent.getType();
                if (type instanceof ISchemaComplexType) {
                    ISchemaCompositor comp = ((ISchemaComplexType) type).getCompositor();
                    if (comp != null)
                        newSelection = new StructuredSelection(comp);
                    else
                        newSelection = new StructuredSelection(parent);
                }
            } else
                newSelection = new StructuredSelection(children[index]);
        }
        fRearranger.deleteAttribute(att);
        return newSelection;
    }

    private IStructuredSelection handleCompositorDelete(ISchemaCompositor comp, boolean generateSelection) {
        IStructuredSelection newSelection = null;
        if (generateSelection) {
            ISchemaObject parent = comp.getParent();
            if (parent instanceof ISchemaElement) {
                ISchemaElement element = (ISchemaElement) parent;
                ISchemaAttribute[] attributes = element.getAttributes();
                if (attributes.length > 0)
                    newSelection = new StructuredSelection(attributes[0]);
                else
                    newSelection = new StructuredSelection(element);
            } else {
                ISchemaCompositor parentComp = (ISchemaCompositor) parent;
                ISchemaObject[] children = parentComp.getChildren();
                int index = getNewSelectionIndex(getArrayIndex(children, comp), children.length);
                if (index == -1)
                    newSelection = new StructuredSelection(parent);
                else
                    newSelection = new StructuredSelection(children[index]);
            }
        }
        fRearranger.deleteCompositor(comp);
        return newSelection;
    }

    // returns true if object a is a SchemaObject higher in the hierarchy than object b
    // returns false if b is higher or they are equal
    private boolean schemaObjectHigherThan(Object a, Object b) {
        if (!(b instanceof ISchemaObject))
            return true;
        if (!(a instanceof ISchemaObject))
            return false;
        return (computeNestLevel((ISchemaObject) a) < computeNestLevel((ISchemaObject) b));
    }

    // determines how deeply nested an ISchemaObject is
    // returns 0 if this is an element, 1 if it's a direct child, etc.
    private int computeNestLevel(ISchemaObject o) {
        int result = 0;
        while ((o instanceof SchemaElementReference) || !(o instanceof ISchemaElement)) {
            o = o.getParent();
            result++;
        }
        return result;
    }

    private void handleNewAttribute() {
        Object object = ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement();
        if (object != null) {
            SchemaElement element = null;
            if (object instanceof SchemaElement)
                element = (SchemaElement) object;
            else if (object instanceof SchemaAttribute)
                element = (SchemaElement) ((SchemaAttribute) object).getParent();

            if (element != null && !(element instanceof ISchemaRootElement)) {
                fNewAttributeAction.setElement(element);
                fNewAttributeAction.run();
            }
        }
    }

    private void handleNewElement() {
        fNewElementAction.setSchema(fSchema);
        fNewElementAction.run();
    }

    public void initialize() {
        this.fSchema = (Schema) getPage().getModel();
        fRearranger = new SchemaRearranger(fSchema);
        fTreeViewer.setInput(fSchema);
        boolean isEditable = fSchema.isEditable();
        getTreePart().setButtonEnabled(0, isEditable);
        getTreePart().setButtonEnabled(1, false);
        getTreePart().setButtonEnabled(2, isEditable);
        getTreePart().setButtonEnabled(3, isEditable);
        getTreePart().setButtonEnabled(4, isEditable);
    }

    public void handleModelChanged(IModelChangedEvent e) {
        if (e.getChangedProperty() != null && e.getChangedProperty().equals(ISchemaObject.P_DESCRIPTION))
            return;
        if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
            handleModelEventWorldChanged(e);
            return;
        }
        Object[] objects = e.getChangedObjects();
        for (int i = 0; i < objects.length; i++) {
            Object obj = objects[0];
            if (obj instanceof SchemaElementReference) {
                fTreeViewer.refresh(((SchemaElementReference) obj).getCompositor());
                if (e.getChangeType() == IModelChangedEvent.INSERT)
                    fTreeViewer.setSelection(new StructuredSelection(obj), true);
            } else if (obj instanceof ISchemaElement || obj instanceof ISchemaAttribute) {
                if (e.getChangeType() == IModelChangedEvent.CHANGE) {
                    String changeProp = e.getChangedProperty();
                    if (changeProp != null && (changeProp.equals(ISchemaObject.P_NAME)
                            || changeProp.equals(SchemaAttribute.P_KIND)))
                        fTreeViewer.update(obj, null);
                    Object typeCheck = e.getNewValue();
                    if (typeCheck instanceof ISchemaComplexType && changeProp.equals(SchemaElement.P_TYPE)
                            && obj instanceof ISchemaElement) {
                        fTreeViewer.refresh(typeCheck);
                        fTreeViewer.setSelection(new StructuredSelection(typeCheck), true);
                    } else {
                        fTreeViewer.refresh(obj);
                    }
                } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
                    ISchemaObject sobj = (ISchemaObject) obj;
                    ISchemaObject parent = sobj.getParent();
                    fTreeViewer.refresh(parent);
                    fTreeViewer.setSelection(new StructuredSelection(obj), true);
                } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
                    fTreeViewer.remove(obj);
                    // the new selection is handled by the handleDelete method for cuts and deletes,
                    // for moves it is handled by the subsequent insert
                }
            } else if (obj instanceof ISchemaCompositor || obj instanceof ISchemaObjectReference) {
                final ISchemaObject sobj = (ISchemaObject) obj;
                ISchemaObject parent = sobj.getParent();
                if (e.getChangeType() == IModelChangedEvent.CHANGE) {
                    fTreeViewer.refresh(sobj);
                } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
                    fTreeViewer.add(parent, sobj);
                    fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
                        public void run() {
                            fTreeViewer.setSelection(new StructuredSelection(sobj), true);
                        }
                    });
                } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
                    fTreeViewer.remove(sobj);
                    // the new selection is handled by the handleDelete method for cuts and deletes,
                    // for moves it is handled by the subsequent insert
                }
            } else if (obj instanceof ISchemaComplexType) {
                // first compositor added/removed
                ISchemaCompositor comp = ((ISchemaComplexType) obj).getCompositor();
                fTreeViewer.refresh(comp);
                if (comp != null)
                    fTreeViewer.refresh(comp.getParent());

                if (e.getChangeType() == IModelChangedEvent.INSERT
                        || e.getChangeType() == IModelChangedEvent.CHANGE) {
                    ISchemaComplexType type = (ISchemaComplexType) obj;
                    final ISchemaCompositor compositor = type.getCompositor();
                    if (compositor != null) {
                        fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
                            public void run() {
                                fTreeViewer.setSelection(new StructuredSelection(compositor), true);
                            }
                        });
                    }
                }
            } else if (obj instanceof ISchema) {
                if (!ISchemaObject.P_NAME.equals(e.getChangedProperty()))
                    fTreeViewer.refresh();
            }
        }
    }

    /**
     * @param event
     */
    private void handleModelEventWorldChanged(IModelChangedEvent event) {
        // Note:  Cannot use event.  There are no changed objects within it
        // This method acts like a refresh
        initialize();
        // TODO: MP: REVERT: LOW: Update initialize with this once Bug #171897 is fixed
        ISchemaElement root = fSchema.getSchema().findElement(ICoreConstants.EXTENSION_NAME);
        // Ensure the root element is present
        if (root == null) {
            return;
        }
        // Select the root extension element
        fTreeViewer.setSelection(new StructuredSelection(root), true);
        // Collapse tree to the first level
        fTreeViewer.expandToLevel(1);
    }

    protected void selectionChanged(IStructuredSelection selection) {
        //      getPage().getManagedForm().fireSelectionChanged(this, selection);
        getPage().getMDEEditor().setSelection(selection);
        updateButtons();
    }

    /* (non-Javadoc)
     * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#setFocus()
     */
    public void setFocus() {
        if (fTreeViewer != null) {
            fTreeViewer.getTree().setFocus();
            getPage().getMDEEditor().setSelection(fTreeViewer.getSelection());
        }
    }

    private void updateButtons() {
        if (!fSchema.isEditable())
            return;
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        ISchemaObject sobject = (ISchemaObject) selection.getFirstElement();

        boolean canAddAttribute = false;
        if (sobject instanceof ISchemaElement) {
            if (!(sobject instanceof ISchemaRootElement) && !(sobject instanceof ISchemaObjectReference))
                canAddAttribute = true;
        } else if (sobject instanceof ISchemaAttribute) {
            ISchemaElement element = (ISchemaElement) (sobject.getParent());
            if (!(element instanceof ISchemaRootElement))
                canAddAttribute = true;
        }
        getTreePart().setButtonEnabled(1, canAddAttribute);

        boolean canAddCompositor = false;
        if (sobject instanceof ISchemaCompositor || (sobject instanceof ISchemaElement
                && !(sobject instanceof SchemaElementReference)
                && (((ISchemaElement) sobject).getType() instanceof ISchemaSimpleType
                        || ((ISchemaComplexType) ((ISchemaElement) sobject).getType()).getCompositor() == null)))
            canAddCompositor = true;
        getTreePart().setButtonEnabled(2, canAddCompositor);
        getTreePart().setButtonEnabled(3, canAddCompositor);

        boolean canRemove = false;
        for (Iterator iter = selection.iterator(); iter.hasNext();) {
            sobject = (ISchemaObject) iter.next();
            if (sobject != null && !(sobject instanceof ISchemaRootElement) && !(sobject instanceof ISchemaAttribute
                    && sobject.getParent() instanceof ISchemaRootElement)) {
                canRemove = true;
                break;
            }
        }
        getTreePart().setButtonEnabled(4, canRemove);
    }

    private ISchemaObject getSibling(Object target, Object object) {
        if (target instanceof ISchemaElement && object instanceof ISchemaElement)
            return (ISchemaElement) target;
        if (target instanceof ISchemaAttribute && object instanceof ISchemaAttribute)
            return (ISchemaAttribute) target;
        if (target instanceof SchemaElementReference && object instanceof ISchemaElement)
            return (SchemaElementReference) target;
        return null;
    }

    private ISchemaObject getRealTarget(Object target, Object object) {
        if (object instanceof ISchemaElement || object instanceof ISchemaObjectReference) {
            if (target instanceof SchemaElementReference)
                return ((SchemaElementReference) target).getCompositor();
            if (target instanceof ISchemaCompositor)
                return (ISchemaCompositor) target;
            if (object instanceof ISchemaElement)
                return fSchema;
        }
        if (object instanceof ISchemaAttribute) {
            if (target instanceof ISchemaAttribute) {
                // add it to the parent of the selected attribute
                return ((ISchemaAttribute) target).getParent();
            }
            if (target instanceof ISchemaElement)
                return (ISchemaElement) target;
        }
        if (object instanceof ISchemaCompositor) {
            if (target instanceof SchemaElementReference)
                return ((SchemaElementReference) target).getCompositor();
            if (target instanceof ISchemaElement)
                return (ISchemaElement) target;
            if (target instanceof ISchemaCompositor)
                return (ISchemaCompositor) target;
        }
        return null;
    }

    protected boolean canPaste(Object target, Object[] objects) {
        for (int i = 0; i < objects.length; i++) {
            Object obj = objects[i];
            if (obj instanceof ISchemaAttribute && target instanceof ISchemaAttribute) {
                continue;
            } else if (obj instanceof ISchemaObjectReference && target instanceof ISchemaCompositor) {
                continue;
            } else if (target instanceof ISchemaElement && !(target instanceof ISchemaObjectReference)
                    && !(obj instanceof ISchemaRootElement)) {
                continue;
            }
            return false;
        }
        return true;
    }

    protected void handleDoubleClick(IStructuredSelection selection) {
        super.handleDoubleClick(selection);
        Object object = selection.getFirstElement();
        if (object instanceof SchemaElementReference) {
            ISchemaElement element = ((SchemaElementReference) object).getReferencedElement();
            if (element == null) {
                String name = ((SchemaElementReference) object).getName();
                MessageDialog.openWarning(getPage().getSite().getShell(),
                        MDEUIMessages.ElementSection_missingRefElement,
                        NLS.bind(MDEUIMessages.SchemaIncludesSection_missingWarningMessage, name));
                return;
            }
            ISchema schema = element.getSchema();
            if (schema.equals(fSchema))
                fireSelection(new StructuredSelection(element));
            else {
                ISchemaInclude[] includes = fSchema.getIncludes();
                for (int i = 0; i < includes.length; i++) {
                    if (includes[i].getIncludedSchema().equals(schema)) {
                        String location = includes[i].getLocation();
                        SchemaEditor.openToElement(new Path(location), element);
                        break;
                    }
                }
            }
        }
    }

    protected void fireSelection(ISelection selection) {
        if (selection == null)
            selection = fTreeViewer.getSelection();
        fTreeViewer.setSelection(selection);
    }

    protected void doPaste(Object target, Object[] objects) {
        handleOp(target, objects, DND.DROP_COPY);
    }

    public void handleOp(Object currentTarget, Object[] objects, int currentOperation) {
        for (int i = 0; i < objects.length; i++) {
            if (!(objects[i] instanceof ISchemaObject))
                continue;
            ISchemaObject object = (ISchemaObject) objects[i];
            ISchemaObject realTarget = getRealTarget(currentTarget, object);
            ISchemaObject sibling = getSibling(currentTarget, object);
            if (realTarget == null)
                continue;
            switch (currentOperation) {
            case DND.DROP_COPY:
                doPaste(realTarget, sibling, object);
                break;
            case DND.DROP_MOVE:
                doMove(realTarget, sibling, object);
                break;
            case DND.DROP_LINK:
                doLink(realTarget, sibling, object);
                break;
            }
        }
    }

    private void doLink(ISchemaObject realTarget, ISchemaObject sibling, ISchemaObject object) {
        if (realTarget instanceof ISchemaCompositor && object instanceof ISchemaElement) {
            fRearranger.linkReference((ISchemaCompositor) realTarget, (ISchemaElement) object, sibling);
        }
    }

    private void doMove(ISchemaObject realTarget, ISchemaObject sibling, ISchemaObject object) {
        if (object instanceof ISchemaCompositor) {
            fRearranger.moveCompositor(realTarget, (ISchemaCompositor) object);
        } else if (object instanceof SchemaElementReference) {
            fRearranger.moveReference((SchemaElementReference) object, (ISchemaCompositor) realTarget, sibling);
        } else if (object instanceof ISchemaElement) {
            fRearranger.moveElement(realTarget, (ISchemaElement) object, sibling);
        } else if (object instanceof ISchemaAttribute) {
            fRearranger.moveAttribute((ISchemaElement) realTarget, (ISchemaAttribute) object,
                    sibling != null ? (ISchemaAttribute) sibling : null);
        }
    }

    private void doPaste(ISchemaObject realTarget, ISchemaObject sibling, ISchemaObject object) {
        if (object instanceof ISchemaCompositor) {
            fRearranger.pasteCompositor(realTarget, (ISchemaCompositor) object, sibling);
        } else if (object instanceof SchemaElementReference) {
            fRearranger.pasteReference(realTarget, (SchemaElementReference) object, sibling);
        } else if (object instanceof ISchemaElement) {
            fRearranger.pasteElement((ISchemaElement) object, sibling);
        } else if (object instanceof ISchemaAttribute) {
            fRearranger.pasteAttribute((ISchemaElement) realTarget, (ISchemaAttribute) object, sibling);
        }
    }
}