Example usage for org.eclipse.jface.viewers TreeViewer getControl

List of usage examples for org.eclipse.jface.viewers TreeViewer getControl

Introduction

In this page you can find the example usage for org.eclipse.jface.viewers TreeViewer getControl.

Prototype

@Override
    public Control getControl() 

Source Link

Usage

From source file:org.eclipse.ptp.remotetools.environment.ui.views.RemoteToolsEnvironmentView.java

License:Open Source License

private boolean showConfirm(String message, TreeViewer viewer) {
    return MessageDialog.openConfirm(viewer.getControl().getShell(), Messages.RemoteToolsEnvironmentView_42,
            message);/*www.  j  a v a  2  s.c o  m*/
}

From source file:org.eclipse.rap.themeeditor.editor.CSSContentOutlinePage.java

License:Open Source License

private void update() {
    TreeViewer viewer = getTreeViewer();
    if (viewer != null) {
        Control control = viewer.getControl();
        if (control != null && !control.isDisposed()) {
            control.setRedraw(false);//from  ww w  . ja  v  a 2  s. c  o m
            viewer.setInput(input);
            viewer.expandAll();
            control.setRedraw(true);
        }
    }
}

From source file:org.eclipse.rcptt.ctx.filesystem.ui.FilesystemContextEditor.java

License:Open Source License

private void createTree(FormToolkit toolkit, Composite client) {
    final Tree tree = new Tree(client, SWT.BORDER | SWT.MULTI);
    GridDataFactory.fillDefaults().grab(true, true).span(1, 1).hint(100, 50).applyTo(tree);

    viewer = new TreeViewer(tree);
    viewer.setLabelProvider(new FilesystemContextLabelProvider());
    viewer.setContentProvider(new FilesystemContextContentProvider());
    viewer.setInput(getContextElement());
    viewer.addSelectionChangedListener(new ISelectionChangedListener() {
        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
            Object[] res = sel.toArray();
            FSResource[] resources = new FSResource[res.length];
            for (int i = 0; i < res.length; i++)
                resources[i] = (FSResource) res[i];
            setSelection(resources);/*from   w w w .j av a 2 s .c  o m*/
        }
    });
    viewer.addDoubleClickListener(new IDoubleClickListener() {

        /**
         * Opens file or expands/collapses folder.
         */
        public void doubleClick(DoubleClickEvent event) {
            if (openFileAction.isEnabled()) {
                openFileAction.run();
            } else {
                TreeViewer viewer = (TreeViewer) event.getViewer();
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                Object selectedNode = selection.getFirstElement();
                viewer.setExpandedState(selectedNode, !viewer.getExpandedState(selectedNode));
            }
        }
    });

    // Setups renaming
    TreeViewerEditor.create(viewer, new DefaultTreeViewerEditStrategy(viewer), ColumnViewerEditor.DEFAULT);
    viewer.setCellEditors(new CellEditor[] { new TextCellEditor(tree) });
    viewer.setCellModifier(new ICellModifier() {
        public void modify(Object element, String property, Object value) {
            TreeItem item = (TreeItem) element;
            FSResource res = (FSResource) item.getData();
            EObject parent = res.eContainer();
            Set<String> allNames = getAllNames(parent);
            allNames.remove(res.getName());

            String newValue = (String) value;
            if (allNames.contains(newValue)) {
                return;
            }

            if (newValue != null && !newValue.isEmpty() && !newValue.equals(res.getName())) {
                res.setName(newValue);
            }
        }

        public Object getValue(Object element, String property) {
            return ((FSResource) element).getName();
        }

        public boolean canModify(Object element, String property) {
            return true;
        }
    });
    viewer.setColumnProperties(new String[] { "" });

    viewer.getControl().addKeyListener(new KeyListener() {

        public void keyReleased(KeyEvent e) {
        }

        public void keyPressed(KeyEvent e) {
            if ((SWT.DEL == e.character) && (0 == e.stateMask)) {
                if (removeAction.isEnabled()) {
                    removeAction.run();
                    e.doit = false;
                }
            }
        }
    });

    UIContentAdapter adapter = new UIContentAdapter() {
        @Override
        protected void changed(Notification notification) {
            if (viewer.getControl().isDisposed()) {
                return;
            }
            viewer.refresh();
        }
    };
    getContextElement().eAdapters().add(adapter);
}

From source file:org.eclipse.rcptt.ui.report.internal.TestCaseComposite.java

License:Open Source License

public void createControl(Composite parent) {
    super.createControl(parent);

    control = new Composite(parent, SWT.NONE);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(control);
    GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(false).applyTo(control);

    TreeViewer viewer = new TreeViewer(control,
            SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
    Tree tree = viewer.getTree();/*from   w  ww . ja v a  2  s . c  om*/
    tree.setHeaderVisible(true);
    GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, 100).applyTo(viewer.getControl());
    TreeColumn testcaseColumn = new TreeColumn(tree, SWT.NONE);
    testcaseColumn.setText("Test case");
    testcaseColumn.setWidth(200);

    TreeColumn statusColumn = new TreeColumn(tree, SWT.NONE);
    statusColumn.setText("Status");
    statusColumn.setWidth(80);

    TreeColumn timeColumn = new TreeColumn(tree, SWT.NONE);
    timeColumn.setText("Time");
    timeColumn.setWidth(80);

    viewer.setLabelProvider(new ReportEntryLabelProvider());
    viewer.setContentProvider(new ReportEntryContentProvider());
    viewer.setInput(report);

    viewer.addSelectionChangedListener(new ISelectionChangedListener() {
        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            List<Node> nodes = new ArrayList<Node>();
            Iterator<?> i = selection.iterator();
            while (i.hasNext()) {
                addNodes(nodes, (Node) i.next());
            }
            doNodesSelection(nodes);
        }

        private void addNodes(List<Node> nodes, Node next) {
            if (!nodes.contains(next)) {
                nodes.add(next);
            }
        }
    });

    viewer.addDoubleClickListener(new IDoubleClickListener() {
        @Override
        public void doubleClick(DoubleClickEvent event) {
            IStructuredSelection thisSelection = (IStructuredSelection) event.getSelection();
            Object selectedNode = thisSelection.getFirstElement();
            if (selectedNode == null || !(selectedNode instanceof Node)) {
                return;
            }

            Node node = (Node) selectedNode;
            Q7Info info = (Q7Info) node.getProperties().get(IQ7ReportConstants.ROOT);
            if (info == null) {
                return;
            }
            String id = info.getId();
            IQ7NamedElement element = Q7SearchCore.findById(id);
            if (element == null) {
                return;
            }

            try {
                IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(),
                        (IFile) element.getResource());
            } catch (PartInitException e) {
                // Do nothing
            }
        }
    });

}

From source file:org.eclipse.rcptt.ui.resources.viewers.WorkspaceContextEditor.java

License:Open Source License

private Tree createTree(Composite parent, FormToolkit toolkit) {
    Tree tree = new Tree(parent, SWT.BORDER | SWT.MULTI);
    GridDataFactory.fillDefaults().grab(true, true).hint(100, 50).applyTo(tree);

    viewer = new TreeViewer(tree);
    TreeViewerEditor.create(viewer, new DefaultTreeViewerEditStrategy(viewer), ColumnViewerEditor.DEFAULT);
    viewer.setCellEditors(new CellEditor[] { new TextCellEditor(tree) });
    viewer.setCellModifier(new ICellModifier() {
        public void modify(Object element, String property, Object value) {
            TreeItem item = (TreeItem) element;
            WSResource res = (WSResource) item.getData();
            WSContainer parent = (WSContainer) res.eContainer();
            Set<String> allNames = getAllNames(parent);
            allNames.remove(res.getName());

            String newValue = (String) value;
            if (allNames.contains(newValue)) {
                return;
            }/*from   w  w w . j av a2s. com*/
            if (newValue != null && !newValue.equals(res.getName())) {
                try {
                    IPersistenceModel model = getElement().getPersistenceModel();

                    if (res instanceof WSFile) {
                        String oldName = ImportUtils.getName((WSFile) res);
                        res.setName(newValue);
                        String newName = ImportUtils.getName((WSFile) res);
                        model.rename(oldName, newName);
                    } else if (res instanceof WSContainer) {
                        // Rename all stored files.
                        List<String> oldNames = new ArrayList<String>();
                        List<WSFile> allFiles = findChildFiles((WSContainer) res);
                        for (WSFile wsFile : allFiles) {
                            oldNames.add(ImportUtils.getName(wsFile));
                        }
                        res.setName(newValue);
                        for (int i = 0; i < oldNames.size(); i++) {
                            String oldName = oldNames.get(i);
                            WSFile file = allFiles.get(i);
                            String newName = ImportUtils.getName(file);
                            model.rename(oldName, newName);
                        }
                    }
                    // viewer.update(res, null);
                } catch (Exception e) {
                    Q7UIPlugin.log(e);
                }
            }
        }

        public Object getValue(Object element, String property) {
            return ((WSResource) element).getName();
        }

        public boolean canModify(Object element, String property) {
            return true;
        }
    });
    viewer.setColumnProperties(new String[] { "o" });
    viewer.setContentProvider(new WorkspaceContentProvider());
    ILabelDecorator decorator = PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator();
    viewer.setLabelProvider(
            new DecoratingStyledCellLabelProvider(new WorkspaceLabelProvider(), decorator, null));
    viewer.setInput(getContextElement());
    viewer.addSelectionChangedListener(new ISelectionChangedListener() {

        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
            Object[] res = sel.toArray();
            WSResource[] resources = new WSResource[res.length];
            for (int i = 0; i < res.length; i++)
                resources[i] = (WSResource) res[i];
            setSelection(resources);
        }
    });
    viewer.addDoubleClickListener(new IDoubleClickListener() {

        /**
         * Opens file or expands/collapses folder.
         */
        public void doubleClick(DoubleClickEvent event) {
            if (openFileAction.isEnabled()) {
                openFileAction.run();
            } else {
                TreeViewer viewer = (TreeViewer) event.getViewer();
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                Object selectedNode = selection.getFirstElement();
                viewer.setExpandedState(selectedNode, !viewer.getExpandedState(selectedNode));
            }
        }
    });
    viewer.getControl().addKeyListener(new KeyListener() {

        public void keyReleased(KeyEvent e) {
        }

        public void keyPressed(KeyEvent e) {
            if ((SWT.DEL == e.character) && (0 == e.stateMask)) {
                if (removeAction.isEnabled()) {
                    removeAction.run();
                    e.doit = false;
                }
            }
        }
    });

    adapter = new UIContentAdapter() {

        protected void changed(Notification notification) {
            if (viewer.getControl().isDisposed()) {
                return;
            }
            viewer.refresh();
        }
    };
    getContextElement().eAdapters().add(adapter);

    toolkit.adapt(tree);

    return tree;
}

From source file:org.eclipse.rcptt.ui.tags.SelectTagDialog.java

License:Open Source License

@Override
protected Control createDialogArea(final Composite parent) {
    final Composite panel = (Composite) super.createDialogArea(parent);

    final SearchControl searchControl = new SearchControl(panel);
    searchControl.setInitialText(Messages.SelectTagDialog_InitialTagName);
    GridDataFactory.fillDefaults().grab(true, false).applyTo(searchControl);
    final TreeViewer tagsViewer = new TreeViewer(panel, SWT.BORDER | SWT.MULTI);
    tagsViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    searchControl.setSearchResultControl(tagsViewer.getControl());
    searchControl.getFilterControl().addModifyListener(new ModifyListener() {
        public void modifyText(ModifyEvent e) {
            String value = searchControl.getFilterString();
            if (!searchControl.getInitialText().equals(value)) {
                tagName = value;/* ww  w . ja v  a 2 s  .  c  om*/
            } else {
                tagName = null;
            }
            tagsViewer.refresh();
            validate();
        }
    });

    tagsViewer.setFilters(new ViewerFilter[] { new TreeViewerWildcardFilter(tagsViewer) {
        protected boolean isIgnoredElement(Object parentElement, Object element) {
            return false;
        }

        @Override
        protected String getFilterText() {
            String value = searchControl.getFilterString();
            if (!searchControl.getInitialText().equals(value)) {
                return value;
            }
            return ""; //$NON-NLS-1$
        }

        @Override
        protected String getElementText(Object parentElement, Object element) {
            return ((Tag) element).getValue();
        }

    } });

    final ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider(
            new IObservableFactory() {

                public IObservable createObservable(final Object target) {
                    if (target instanceof IObservable) {
                        return (IObservable) target;
                    } else if (target instanceof Tag) {
                        final Tag tag = (Tag) target;
                        ObservableList list = new WritableList();
                        synchronized (tag) {
                            EList<Tag> tags = tag.getTags();
                            for (Tag childTag : tags) {
                                synchronized (childTag) {
                                    if (childTag.getTags().size() > 0
                                            || !disabledTags.contains(childTag.getPath())) {
                                        list.add(childTag);
                                    }
                                }
                            }
                        }
                        return list;
                    } else {
                        return null;
                    }
                }
            }, null);

    tagsViewer.setContentProvider(contentProvider);

    allTags = new WritableList();
    TagsRegistry tagRegistry = Q7UIPlugin.getDefault().getTags();
    synchronized (tagRegistry) {
        EList<Tag> tags = tagRegistry.getTags();
        for (Tag childTag : tags) {
            synchronized (childTag) {
                if (childTag.getTags().size() > 0 || !disabledTags.contains(childTag.getPath())) {
                    allTags.add(childTag);
                }
            }
        }
    }
    tagsViewer.setInput(allTags);
    tagsViewer.setLabelProvider(new DelegatingStyledCellLabelProvider(new TagLabels()));
    tagsViewer.addSelectionChangedListener(new ISelectionChangedListener() {

        public void selectionChanged(final SelectionChangedEvent event) {
            final IStructuredSelection iss = (IStructuredSelection) event.getSelection();
            result.clear();

            boolean changed = false;
            for (final Object o : iss.toList()) {
                final Tag tag = (Tag) o;
                if (!disabledTags.contains(tag.getPath())) {
                    result.add(tag);
                } else {
                    changed = true;
                }
            }

            if (changed) {
                tagsViewer.setSelection(new StructuredSelection(result));
            }
            validate();
        }
    });
    tagsViewer.addDoubleClickListener(new IDoubleClickListener() {

        public void doubleClick(final DoubleClickEvent event) {
            setReturnCode(OK);
            result.clear();
            result.add((Tag) ((IStructuredSelection) event.getSelection()).getFirstElement());
            close();
        }
    });
    validate();

    PlatformUI.getWorkbench().getHelpSystem().setHelp(panel, IQ7HelpContextIds.TAGS);
    return panel;
}

From source file:org.eclipse.reddeer.gef.spy.view.GEFSpyView.java

License:Open Source License

/**
 * Refreshes a given tree viewer with all edit parts (or figures) if a GEF editor is available. Otherwise, it throws
 * a warning about that.//from   w  ww  . java 2s.  c o  m
 * 
 * @param treeViewer
 *            Tree viewer
 */
protected void refresh(TreeViewer treeViewer) {
    EditPart editPart = null;

    try {
        IEditorPart editorPart = EditorPartLookup.getInstance().getEditor();
        editPart = ViewerLookup.getInstance().findGraphicalViewer(editorPart).getContents();
    } catch (Exception ex) {
        treeViewer.setInput(new TreeNode[] {});
        MessageDialog.openWarning(treeViewer.getControl().getShell(), "GEF View",
                "No GEF editor was detected.");
        return;
    }

    treeViewer.setInput(createTree(editPart));
    treeViewer.refresh();
}

From source file:org.eclipse.reddeer.jface.test.viewer.PrepareTreeWithStyledItems.java

License:Open Source License

private Composite createPartControl(Composite parent) {
    Composite composite = new Composite(parent, SWT.NONE);

    composite.setLayout(new GridLayout(1, true));

    Label label = new Label(composite, SWT.NONE);
    label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
    label.setText("Tree with decorators");

    final TreeViewer treeViewer = new TreeViewer(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);

    StyledTreeItemLabelProvider labelProvider = new StyledTreeItemLabelProvider();
    TreeItemProvider treeItemProvider = new TreeItemProvider();

    treeViewer.getControl().setSize(400, 400);
    treeViewer.setLabelProvider(labelProvider);
    treeViewer.setContentProvider(treeItemProvider);

    GridData data = new GridData(GridData.CENTER, GridData.FILL, true, true);
    treeViewer.getControl().setLayoutData(data);
    treeViewer.setInput(new Object());

    composite.pack();/*from w ww . j  av  a  2  s.co m*/

    return composite;
}

From source file:org.eclipse.sapphire.ui.form.editors.masterdetails.MasterDetailsEditorPage.java

License:Open Source License

private FilteredTree createContentOutline(final Composite parent, final MasterDetailsContentOutline outline,
        final boolean addBorders) {
    final int treeStyle = (addBorders ? SWT.BORDER : SWT.NONE) | SWT.MULTI;

    final ContentOutlineFilteredTree filteredTree = new ContentOutlineFilteredTree(parent, treeStyle, outline);
    final TreeViewer treeViewer = filteredTree.getViewer();
    final Tree tree = treeViewer.getTree();

    final ITreeContentProvider contentProvider = new ITreeContentProvider() {
        private final Listener listener = new Listener() {
            @Override/*  w  w w.  j  a v  a2 s  . c  o m*/
            public void handle(final org.eclipse.sapphire.Event event) {
                if (event instanceof PartEvent) {
                    final SapphirePart part = ((PartEvent) event).part();

                    if (part instanceof MasterDetailsContentNode) {
                        final MasterDetailsContentNode node = (MasterDetailsContentNode) part;

                        if (event instanceof PartVisibilityEvent) {
                            final MasterDetailsContentNode parent = node.getParentNode();

                            if (parent == outline.getRoot()) {
                                treeViewer.refresh();
                            } else {
                                treeViewer.refresh(parent);
                            }
                        } else {
                            if (node.visible()) {
                                if (event instanceof LabelChangedEvent || event instanceof ImageChangedEvent) {
                                    Display.getCurrent().asyncExec(new TreeViewerUpdateJob(treeViewer, node));
                                } else if (event instanceof NodeListEvent) {
                                    treeViewer.refresh(node);
                                }
                            }
                        }
                    }
                }
            }
        };

        private void attach(final List<MasterDetailsContentNode> nodes) {
            for (MasterDetailsContentNode node : nodes) {
                node.attach(this.listener);
            }
        }

        private void detach(final List<MasterDetailsContentNode> nodes) {
            for (MasterDetailsContentNode node : nodes) {
                node.detach(this.listener);
                detach(node.nodes());
            }
        }

        public Object[] getElements(final Object inputElement) {
            final MasterDetailsContentNodeList nodes = outline.getRoot().nodes();
            attach(nodes);
            return nodes.visible().toArray();
        }

        public Object[] getChildren(final Object parentElement) {
            final MasterDetailsContentNodeList nodes = ((MasterDetailsContentNode) parentElement).nodes();
            attach(nodes);
            return nodes.visible().toArray();
        }

        public Object getParent(final Object element) {
            return ((MasterDetailsContentNode) element).getParentNode();
        }

        public boolean hasChildren(final Object parentElement) {
            final MasterDetailsContentNodeList nodes = ((MasterDetailsContentNode) parentElement).nodes();
            attach(nodes);
            return !nodes.visible().isEmpty();
        }

        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
        }

        public void dispose() {
            detach(outline.getRoot().nodes());
        }
    };

    final LabelProvider labelProvider = new LabelProvider() {
        private final Map<ImageDescriptor, Image> images = new HashMap<ImageDescriptor, Image>();

        @Override
        public String getText(final Object element) {
            return ((MasterDetailsContentNode) element).getLabel();
        }

        @Override
        public Image getImage(final Object element) {
            return getImage((MasterDetailsContentNode) element);
        }

        private Image getImage(final MasterDetailsContentNode node) {
            final ImageDescriptor imageDescriptor = node.getImage();
            Image image = this.images.get(imageDescriptor);

            if (image == null) {
                image = imageDescriptor.createImage();
                this.images.put(imageDescriptor, image);
            }

            return image;
        }

        @Override
        public void dispose() {
            for (Image image : this.images.values()) {
                image.dispose();
            }
        }
    };

    new SapphireToolTip(tree) {
        protected Object getToolTipArea(final Event event) {
            return treeViewer.getCell(new Point(event.x, event.y));
        }

        protected boolean shouldCreateToolTip(Event event) {
            if (!super.shouldCreateToolTip(event)) {
                return false;
            }

            setShift(new Point(0, 20));
            tree.setToolTipText("");

            boolean res = false;

            final MasterDetailsContentNode node = getNode(event);

            if (node != null) {
                res = !node.validation().ok();
            }

            return res;
        }

        private MasterDetailsContentNode getNode(final Event event) {
            final TreeItem item = tree.getItem(new Point(event.x, event.y));

            if (item == null) {
                return null;
            } else {
                return (MasterDetailsContentNode) item.getData();
            }
        }

        protected void afterHideToolTip(Event event) {
            super.afterHideToolTip(event);
            // Clear the restored value else this could be a source of a leak
            if (event != null && event.widget != treeViewer.getControl()) {
                treeViewer.getControl().setFocus();
            }
        }

        @Override
        protected void createContent(final Event event, final Composite parent) {
            final MasterDetailsContentNode node = getNode(event);

            parent.setLayout(glayout(1));

            SapphireFormText text = new SapphireFormText(parent, SWT.NO_FOCUS);
            text.setLayoutData(gdfill());

            final org.eclipse.sapphire.modeling.Status validation = node.validation();
            final List<org.eclipse.sapphire.modeling.Status> items = gather(validation);

            final StringBuffer buffer = new StringBuffer();
            buffer.append("<form>");

            final int count = items.size();
            int i = 0;

            for (org.eclipse.sapphire.modeling.Status item : items) {
                final String imageKey = (item.severity() == org.eclipse.sapphire.modeling.Status.Severity.ERROR
                        ? "error"
                        : "warning");
                buffer.append("<li style=\"image\" value=\"" + imageKey + "\">" + escapeForXml(item.message())
                        + "</li>");

                i++;

                if (count > 10 && i == 9) {
                    break;
                }
            }

            if (count > 10) {
                final String msg = NLS.bind(Resources.problemsOverflowMessage, numberToString(count - 9));
                final String imageKey = (validation
                        .severity() == org.eclipse.sapphire.modeling.Status.Severity.ERROR ? "error"
                                : "warning");
                buffer.append("<br/><li style=\"image\" value=\"" + imageKey + "\">" + msg + "</li>");
            }

            buffer.append("</form>");

            text.setText(buffer.toString(), true, false);
            text.setImage("error", ImageData.createFromClassLoader(SwtResourceCache.class, "Error.png"));
            text.setImage("warning", ImageData.createFromClassLoader(SwtResourceCache.class, "Warning.png"));
        }

        private String numberToString(final int number) {
            switch (number) {
            case 2:
                return Resources.two;
            case 3:
                return Resources.three;
            case 4:
                return Resources.four;
            case 5:
                return Resources.five;
            case 6:
                return Resources.six;
            case 7:
                return Resources.seven;
            case 8:
                return Resources.eight;
            case 9:
                return Resources.nine;
            default:
                return String.valueOf(number);
            }
        }

        private List<org.eclipse.sapphire.modeling.Status> gather(
                final org.eclipse.sapphire.modeling.Status status) {
            final List<org.eclipse.sapphire.modeling.Status> items = new ArrayList<org.eclipse.sapphire.modeling.Status>();
            gather(status, items);
            return items;
        }

        private void gather(final org.eclipse.sapphire.modeling.Status status,
                final List<org.eclipse.sapphire.modeling.Status> items) {
            if (status.children().isEmpty()) {
                items.add(status);
            } else {
                for (org.eclipse.sapphire.modeling.Status child : status.children()) {
                    gather(child, items);
                }
            }
        }
    };

    treeViewer.setContentProvider(contentProvider);
    treeViewer.setLabelProvider(labelProvider);
    treeViewer.setInput(new Object());

    final MutableReference<Boolean> ignoreSelectionChange = new MutableReference<Boolean>(false);
    final MutableReference<Boolean> ignoreExpandedStateChange = new MutableReference<Boolean>(false);

    final Listener contentTreeListener = new Listener() {
        @Override
        public void handle(final org.eclipse.sapphire.Event event) {
            if (event instanceof MasterDetailsContentOutline.SelectionChangedEvent) {
                if (ignoreSelectionChange.get() == true) {
                    return;
                }

                final MasterDetailsContentOutline.SelectionChangedEvent evt = (MasterDetailsContentOutline.SelectionChangedEvent) event;
                final List<MasterDetailsContentNode> selection = evt.selection();

                final IStructuredSelection sel;

                if (selection.isEmpty()) {
                    sel = StructuredSelection.EMPTY;
                } else {
                    sel = new StructuredSelection(selection);
                }

                if (!treeViewer.getSelection().equals(sel)) {
                    for (MasterDetailsContentNode node : selection) {
                        treeViewer.reveal(node);
                    }

                    treeViewer.setSelection(sel);
                }
            } else if (event instanceof MasterDetailsContentOutline.NodeExpandedStateChangedEvent) {
                if (ignoreExpandedStateChange.get() == true) {
                    return;
                }

                final MasterDetailsContentOutline.NodeExpandedStateChangedEvent evt = (MasterDetailsContentOutline.NodeExpandedStateChangedEvent) event;
                final MasterDetailsContentNode node = evt.node();

                final boolean expandedState = node.isExpanded();

                if (treeViewer.getExpandedState(node) != expandedState) {
                    treeViewer.setExpandedState(node, expandedState);
                }
            } else if (event instanceof MasterDetailsContentOutline.FilterChangedEvent) {
                final MasterDetailsContentOutline.FilterChangedEvent evt = (MasterDetailsContentOutline.FilterChangedEvent) event;
                filteredTree.changeFilterText(evt.filter());
            }
        }
    };

    outline.attach(contentTreeListener);

    treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
        public void selectionChanged(final SelectionChangedEvent event) {
            ignoreSelectionChange.set(true);

            try {
                final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                final List<MasterDetailsContentNode> nodes = new ArrayList<MasterDetailsContentNode>();

                for (Iterator<?> itr = selection.iterator(); itr.hasNext();) {
                    nodes.add((MasterDetailsContentNode) itr.next());
                }

                outline.setSelectedNodes(nodes);
            } finally {
                ignoreSelectionChange.set(false);
            }
        }
    });

    treeViewer.addTreeListener(new ITreeViewerListener() {
        public void treeExpanded(final TreeExpansionEvent event) {
            ignoreExpandedStateChange.set(true);

            try {
                final MasterDetailsContentNode node = (MasterDetailsContentNode) event.getElement();
                node.setExpanded(true);
            } finally {
                ignoreExpandedStateChange.set(false);
            }
        }

        public void treeCollapsed(final TreeExpansionEvent event) {
            ignoreExpandedStateChange.set(true);

            try {
                final MasterDetailsContentNode node = (MasterDetailsContentNode) event.getElement();
                node.setExpanded(false);
            } finally {
                ignoreExpandedStateChange.set(false);
            }
        }
    });

    final ContentOutlineActionSupport actionSupport = new ContentOutlineActionSupport(outline, tree);

    treeViewer.setExpandedElements(outline.getExpandedNodes().toArray());
    contentTreeListener
            .handle(new MasterDetailsContentOutline.SelectionChangedEvent(outline.getSelectedNodes()));

    filteredTree.changeFilterText(outline.getFilterText());

    final ModelElementsTransfer transfer = new ModelElementsTransfer(
            getModelElement().type().getModelElementClass().getClassLoader());
    final Transfer[] transfers = new Transfer[] { transfer };

    final DragSource dragSource = new DragSource(tree, DND.DROP_MOVE);
    dragSource.setTransfer(transfers);

    final List<Element> dragElements = new ArrayList<Element>();

    dragSource.addDragListener(new DragSourceListener() {
        public void dragStart(final DragSourceEvent event) {
            final TreeItem[] selection = tree.getSelection();
            final String filter = outline().getFilterText();

            if ((filter == null || filter.length() == 0) && draggable(selection)) {
                event.doit = true;

                for (TreeItem item : selection) {
                    final MasterDetailsContentNode node = (MasterDetailsContentNode) item.getData();
                    dragElements.add(node.getModelElement());
                }
            } else {
                event.doit = false;
            }
        }

        protected boolean draggable(final TreeItem[] selection) {
            if (selection.length > 0) {
                for (TreeItem item : selection) {
                    final MasterDetailsContentNode node = (MasterDetailsContentNode) item.getData();

                    if (!draggable(node)) {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }

        protected boolean draggable(final MasterDetailsContentNode node) {
            final Element element = node.getModelElement();

            if (element.parent().definition() instanceof ListProperty && node.controls(element)) {
                return true;
            }

            return false;
        }

        public void dragSetData(final DragSourceEvent event) {
            event.data = dragElements;
        }

        public void dragFinished(final DragSourceEvent event) {
            if (event.detail == DND.DROP_MOVE) {
                // When drop target is the same editor as drag source, the drop handler takes care of removing
                // elements from their original location. The following block of code accounts for the case when 
                // dropping into another editor.

                boolean droppedIntoAnotherEditor = false;

                for (Element dragElement : dragElements) {
                    if (!dragElement.disposed()) {
                        droppedIntoAnotherEditor = true;
                        break;
                    }
                }

                if (droppedIntoAnotherEditor) {
                    final TreeItem[] selection = tree.getSelection();
                    final List<MasterDetailsContentNode> dragNodes = new ArrayList<MasterDetailsContentNode>();

                    for (TreeItem item : selection) {
                        dragNodes.add((MasterDetailsContentNode) item.getData());
                    }

                    final MasterDetailsContentNode parentNode = dragNodes.get(0).getParentNode();

                    MasterDetailsContentNode selectionPostDelete = findSelectionPostDelete(
                            parentNode.nodes().visible(), dragNodes);

                    if (selectionPostDelete == null) {
                        selectionPostDelete = parentNode;
                    }

                    try {
                        outline.listeners().suspend(MasterDetailsContentOutline.SelectionChangedEvent.class);

                        for (Element dragElement : dragElements) {
                            final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();
                            dragElementContainer.remove(dragElement);
                        }
                    } catch (Exception e) {
                        // Log this exception unless the cause is EditFailedException. These exception
                        // are the result of the user declining a particular action that is necessary
                        // before the edit can happen (such as making a file writable).

                        final EditFailedException editFailedException = EditFailedException.findAsCause(e);

                        if (editFailedException == null) {
                            SapphireUiFrameworkPlugin.log(e);
                        }
                    } finally {
                        outline.listeners().resume(MasterDetailsContentOutline.SelectionChangedEvent.class);
                    }

                    parentNode.getContentTree().setSelectedNode(selectionPostDelete);
                }
            }

            dragElements.clear();
        }
    });

    final DropTarget target = new DropTarget(tree, DND.DROP_MOVE);
    target.setTransfer(transfers);

    target.addDropListener(new DropTargetAdapter() {
        public void dragOver(final DropTargetEvent event) {
            if (event.item != null) {
                final TreeItem dragOverItem = (TreeItem) event.item;
                final MasterDetailsContentNode dragOverNode = (MasterDetailsContentNode) dragOverItem.getData();
                final MasterDetailsContentNode parentNode = dragOverNode.getParentNode();
                final List<MasterDetailsContentNode> siblingNodes = parentNode.nodes().visible();

                final Point pt = dragOverItem.getDisplay().map(null, tree, event.x, event.y);
                final Rectangle bounds = dragOverItem.getBounds();

                MasterDetailsContentNode precedingNode = null;
                MasterDetailsContentNode trailingNode = null;

                if (pt.y < bounds.y + bounds.height / 2) {
                    precedingNode = findPrecedingItem(siblingNodes, dragOverNode);
                    trailingNode = dragOverNode;

                    event.feedback = DND.FEEDBACK_INSERT_BEFORE;
                } else {
                    precedingNode = dragOverNode;
                    trailingNode = findTrailingItem(siblingNodes, dragOverNode);

                    event.feedback = DND.FEEDBACK_INSERT_AFTER;
                }

                boolean ok = false;

                if (precedingNode != null) {
                    final Element precedingElement = precedingNode.getModelElement();

                    if (precedingElement.parent().definition() instanceof ListProperty
                            && precedingNode.controls(precedingElement)) {
                        ok = true;
                    }
                }

                if (!ok && trailingNode != null) {
                    final Element trailingElement = trailingNode.getModelElement();

                    if (trailingElement.parent().definition() instanceof ListProperty
                            && trailingNode.controls(trailingElement)) {
                        ok = true;
                    }
                }

                if (!ok) {
                    event.feedback = DND.FEEDBACK_NONE;
                }
            }

            event.feedback |= DND.FEEDBACK_SCROLL;
        }

        @SuppressWarnings("unchecked")

        public void drop(final DropTargetEvent event) {
            if (event.data == null || event.item == null) {
                event.detail = DND.DROP_NONE;
                return;
            }

            // Determine where something was dropped.

            final List<Element> droppedElements = (List<Element>) event.data;
            final TreeItem dropTargetItem = (TreeItem) event.item;
            final MasterDetailsContentNode dropTargetNode = (MasterDetailsContentNode) dropTargetItem.getData();
            final MasterDetailsContentNode parentNode = dropTargetNode.getParentNode();
            final List<MasterDetailsContentNode> siblingNodes = parentNode.nodes().visible();

            final Point pt = tree.getDisplay().map(null, tree, event.x, event.y);
            final Rectangle bounds = dropTargetItem.getBounds();

            MasterDetailsContentNode precedingNode = null;
            MasterDetailsContentNode trailingNode = null;

            if (pt.y < bounds.y + bounds.height / 2) {
                precedingNode = findPrecedingItem(siblingNodes, dropTargetNode);
                trailingNode = dropTargetNode;
            } else {
                precedingNode = dropTargetNode;
                trailingNode = findTrailingItem(siblingNodes, dropTargetNode);
            }

            // Determine whether the drop was valid from model standpoint and figure out
            // where in the model the dropped elements are to be inserted.

            ElementList<?> list = null;
            int position = -1;

            if (precedingNode != null) {
                final Element precedingElement = precedingNode.getModelElement();

                if (precedingElement.parent().definition() instanceof ListProperty
                        && !precedingElement.parent().definition().isReadOnly()
                        && precedingNode.controls(precedingElement)) {
                    list = (ElementList<?>) precedingElement.parent();

                    final Set<ElementType> possibleListElementTypes = list.definition()
                            .service(PossibleTypesService.class).types();

                    for (Element droppedElement : droppedElements) {
                        if (!possibleListElementTypes.contains(droppedElement.type())) {
                            list = null;
                            break;
                        }
                    }

                    if (list != null) {
                        position = list.indexOf(precedingElement) + 1;
                    }
                }
            }

            if (list == null && trailingNode != null) {
                final Element trailingElement = trailingNode.getModelElement();

                if (trailingElement.parent().definition() instanceof ListProperty
                        && !trailingElement.parent().definition().isReadOnly()
                        && trailingNode.controls(trailingElement)) {
                    list = (ElementList<?>) trailingElement.parent();

                    final Set<ElementType> possibleListElementTypes = list.definition()
                            .service(PossibleTypesService.class).types();

                    for (Element droppedElement : droppedElements) {
                        if (!possibleListElementTypes.contains(droppedElement.type())) {
                            list = null;
                            break;
                        }
                    }

                    if (list != null) {
                        position = list.indexOf(trailingElement);
                    }
                }
            }

            if (list == null) {
                for (PropertyDef dropTargetChildProperty : dropTargetNode.getChildNodeFactoryProperties()) {
                    if (dropTargetChildProperty instanceof ListProperty
                            && !dropTargetChildProperty.isReadOnly()) {
                        final ListProperty dropTargetChildListProperty = (ListProperty) dropTargetChildProperty;

                        boolean compatible = true;

                        final Set<ElementType> possibleListElementTypes = dropTargetChildListProperty
                                .service(PossibleTypesService.class).types();

                        for (Element droppedElement : droppedElements) {
                            if (!possibleListElementTypes.contains(droppedElement.type())) {
                                compatible = false;
                                break;
                            }
                        }

                        if (compatible) {
                            list = dropTargetNode.getLocalModelElement().property(dropTargetChildListProperty);
                            position = list.size();
                        }
                    }
                }
            }

            if (list == null) {
                event.detail = DND.DROP_NONE;
                return;
            }

            // Perform the removal and insertion into the new location.

            try {
                outline.listeners().suspend(MasterDetailsContentOutline.SelectionChangedEvent.class);

                for (Element dragElement : dragElements) {
                    final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();

                    if (dragElementContainer == list && dragElementContainer.indexOf(dragElement) < position) {
                        position--;
                    }

                    dragElementContainer.remove(dragElement);
                }

                final List<MasterDetailsContentNode> newSelection = new ArrayList<MasterDetailsContentNode>();

                for (Element droppedElement : droppedElements) {
                    final Element insertedElement = list.insert(droppedElement.type(), position);
                    insertedElement.copy(droppedElement);

                    newSelection.add(parentNode.findNode(insertedElement));

                    position++;
                }

                parentNode.getContentTree().setSelectedNodes(newSelection);
            } catch (Exception e) {
                // Log this exception unless the cause is EditFailedException. These exception
                // are the result of the user declining a particular action that is necessary
                // before the edit can happen (such as making a file writable).

                final EditFailedException editFailedException = EditFailedException.findAsCause(e);

                if (editFailedException == null) {
                    SapphireUiFrameworkPlugin.log(e);
                }

                event.detail = DND.DROP_NONE;
            } finally {
                outline.listeners().resume(MasterDetailsContentOutline.SelectionChangedEvent.class);
            }
        }
    });

    tree.addDisposeListener(new DisposeListener() {
        public void widgetDisposed(final DisposeEvent event) {
            outline.detach(contentTreeListener);
            actionSupport.dispose();
        }
    });

    return filteredTree;
}

From source file:org.eclipse.sapphire.ui.forms.swt.MasterDetailsEditorPage.java

License:Open Source License

private FilteredTree createContentOutline(final Composite parent, final MasterDetailsContentOutline outline,
        final boolean addBorders) {
    final int treeStyle = (addBorders ? SWT.BORDER : SWT.NONE) | SWT.MULTI;

    final ContentOutlineFilteredTree filteredTree = new ContentOutlineFilteredTree(parent, treeStyle, outline);
    final TreeViewer treeViewer = filteredTree.getViewer();
    final Tree tree = treeViewer.getTree();

    final ITreeContentProvider contentProvider = new ITreeContentProvider() {
        private final Listener listener = new Listener() {
            @Override/* w ww . j ava2  s  . c  o m*/
            public void handle(final org.eclipse.sapphire.Event event) {
                if (event instanceof PartEvent) {
                    final SapphirePart part = ((PartEvent) event).part();

                    if (part instanceof MasterDetailsContentNodePart) {
                        final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) part;

                        if (event instanceof PartVisibilityEvent) {
                            final MasterDetailsContentNodePart parent = node.getParentNode();

                            if (parent == outline.getRoot()) {
                                treeViewer.refresh();
                            } else {
                                treeViewer.refresh(parent);
                            }
                        } else {
                            if (node.visible()) {
                                if (event instanceof LabelChangedEvent || event instanceof ImageChangedEvent
                                        || event instanceof DecorationEvent) {
                                    Display.getCurrent().asyncExec(new TreeViewerUpdateJob(treeViewer, node));
                                } else if (event instanceof NodeListEvent) {
                                    treeViewer.refresh(node);
                                }
                            }
                        }
                    }
                }
            }
        };

        private void attach(final List<MasterDetailsContentNodePart> nodes) {
            for (MasterDetailsContentNodePart node : nodes) {
                node.attach(this.listener);
            }
        }

        private void detach(final List<MasterDetailsContentNodePart> nodes) {
            for (MasterDetailsContentNodePart node : nodes) {
                node.detach(this.listener);
                detach(node.nodes());
            }
        }

        public Object[] getElements(final Object inputElement) {
            final MasterDetailsContentNodeList nodes = outline.getRoot().nodes();
            attach(nodes);
            return nodes.visible().toArray();
        }

        public Object[] getChildren(final Object parentElement) {
            final MasterDetailsContentNodeList nodes = ((MasterDetailsContentNodePart) parentElement).nodes();
            attach(nodes);
            return nodes.visible().toArray();
        }

        public Object getParent(final Object element) {
            return ((MasterDetailsContentNodePart) element).getParentNode();
        }

        public boolean hasChildren(final Object parentElement) {
            final MasterDetailsContentNodeList nodes = ((MasterDetailsContentNodePart) parentElement).nodes();
            attach(nodes);
            return !nodes.visible().isEmpty();
        }

        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
        }

        public void dispose() {
            detach(outline.getRoot().nodes());
        }
    };

    final StyledCellLabelProvider labelProvider = new StyledCellLabelProvider() {
        private final Map<ImageDescriptor, Image> images = new HashMap<ImageDescriptor, Image>();
        private final Map<org.eclipse.sapphire.Color, Color> colors = new HashMap<org.eclipse.sapphire.Color, Color>();

        public void update(final ViewerCell cell) {
            final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) cell.getElement();

            final StyledString styledString = new StyledString(node.getLabel());

            for (final TextDecoration decoration : node.decorations()) {
                String text = decoration.text();

                if (text != null) {
                    text = text.trim();

                    if (text.length() > 0) {
                        final Color color = color(decoration.color());

                        styledString.append(" " + text, new Styler() {
                            @Override
                            public void applyStyles(final TextStyle style) {
                                style.foreground = color;
                            }
                        });
                    }
                }
            }

            cell.setText(styledString.toString());
            cell.setStyleRanges(styledString.getStyleRanges());
            cell.setImage(image(node.getImage()));

            super.update(cell);
        }

        private Color color(final org.eclipse.sapphire.Color c) {
            Color color = this.colors.get(c);

            if (color == null) {
                color = new Color(tree.getDisplay(), c.red(), c.green(), c.blue());
                this.colors.put(c, color);
            }

            return color;
        }

        private Image image(final ImageDescriptor imageDescriptor) {
            Image image = this.images.get(imageDescriptor);

            if (image == null) {
                image = imageDescriptor.createImage();
                this.images.put(imageDescriptor, image);
            }

            return image;
        }

        @Override
        public void dispose() {
            for (final Image image : this.images.values()) {
                image.dispose();
            }
        }
    };

    new SapphireToolTip(tree) {
        protected Object getToolTipArea(final Event event) {
            return treeViewer.getCell(new Point(event.x, event.y));
        }

        protected boolean shouldCreateToolTip(Event event) {
            if (!super.shouldCreateToolTip(event)) {
                return false;
            }

            setShift(new Point(0, 20));
            tree.setToolTipText("");

            boolean res = false;

            final MasterDetailsContentNodePart node = getNode(event);

            if (node != null) {
                res = !node.validation().ok();
            }

            return res;
        }

        private MasterDetailsContentNodePart getNode(final Event event) {
            final TreeItem item = tree.getItem(new Point(event.x, event.y));

            if (item == null) {
                return null;
            } else {
                return (MasterDetailsContentNodePart) item.getData();
            }
        }

        protected void afterHideToolTip(Event event) {
            super.afterHideToolTip(event);
            // Clear the restored value else this could be a source of a leak
            if (event != null && event.widget != treeViewer.getControl()) {
                treeViewer.getControl().setFocus();
            }
        }

        @Override
        protected void createContent(final Event event, final Composite parent) {
            final MasterDetailsContentNodePart node = getNode(event);

            parent.setLayout(glayout(1));

            SapphireFormText text = new SapphireFormText(parent, SWT.NO_FOCUS);
            text.setLayoutData(gdfill());

            final org.eclipse.sapphire.modeling.Status validation = node.validation();
            final List<org.eclipse.sapphire.modeling.Status> items = gather(validation);

            final StringBuffer buffer = new StringBuffer();
            buffer.append("<form>");

            final int count = items.size();
            int i = 0;

            for (org.eclipse.sapphire.modeling.Status item : items) {
                final String imageKey = (item.severity() == org.eclipse.sapphire.modeling.Status.Severity.ERROR
                        ? "error"
                        : "warning");
                buffer.append("<li style=\"image\" value=\"" + imageKey + "\">" + escapeForXml(item.message())
                        + "</li>");

                i++;

                if (count > 10 && i == 9) {
                    break;
                }
            }

            if (count > 10) {
                final String msg = problemsOverflowMessage.format(numberToString(count - 9));
                final String imageKey = (validation
                        .severity() == org.eclipse.sapphire.modeling.Status.Severity.ERROR ? "error"
                                : "warning");
                buffer.append("<br/><li style=\"image\" value=\"" + imageKey + "\">" + msg + "</li>");
            }

            buffer.append("</form>");

            text.setText(buffer.toString(), true, false);
            text.setImage("error",
                    ImageData.readFromClassLoader(SwtResourceCache.class, "Error.png").required());
            text.setImage("warning",
                    ImageData.readFromClassLoader(SwtResourceCache.class, "Warning.png").required());
        }

        private String numberToString(final int number) {
            switch (number) {
            case 2:
                return two.text();
            case 3:
                return three.text();
            case 4:
                return four.text();
            case 5:
                return five.text();
            case 6:
                return six.text();
            case 7:
                return seven.text();
            case 8:
                return eight.text();
            case 9:
                return nine.text();
            default:
                return String.valueOf(number);
            }
        }

        private List<org.eclipse.sapphire.modeling.Status> gather(
                final org.eclipse.sapphire.modeling.Status status) {
            final List<org.eclipse.sapphire.modeling.Status> items = new ArrayList<org.eclipse.sapphire.modeling.Status>();
            gather(status, items);
            return items;
        }

        private void gather(final org.eclipse.sapphire.modeling.Status status,
                final List<org.eclipse.sapphire.modeling.Status> items) {
            if (status.children().isEmpty()) {
                items.add(status);
            } else {
                for (org.eclipse.sapphire.modeling.Status child : status.children()) {
                    gather(child, items);
                }
            }
        }
    };

    treeViewer.setContentProvider(contentProvider);
    treeViewer.setLabelProvider(labelProvider);
    treeViewer.setInput(new Object());

    final MutableReference<Boolean> ignoreSelectionChange = new MutableReference<Boolean>(false);
    final MutableReference<Boolean> ignoreExpandedStateChange = new MutableReference<Boolean>(false);

    final Listener contentTreeListener = new Listener() {
        @Override
        public void handle(final org.eclipse.sapphire.Event event) {
            if (event instanceof MasterDetailsContentOutline.SelectionChangedEvent) {
                if (ignoreSelectionChange.get() == true) {
                    return;
                }

                final MasterDetailsContentOutline.SelectionChangedEvent evt = (MasterDetailsContentOutline.SelectionChangedEvent) event;
                final List<MasterDetailsContentNodePart> selection = evt.selection();

                final IStructuredSelection sel;

                if (selection.isEmpty()) {
                    sel = StructuredSelection.EMPTY;
                } else {
                    sel = new StructuredSelection(selection);
                }

                if (!treeViewer.getSelection().equals(sel)) {
                    for (MasterDetailsContentNodePart node : selection) {
                        treeViewer.reveal(node);
                    }

                    treeViewer.setSelection(sel);
                }
            } else if (event instanceof MasterDetailsContentOutline.NodeExpandedStateChangedEvent) {
                if (ignoreExpandedStateChange.get() == true) {
                    return;
                }

                final MasterDetailsContentOutline.NodeExpandedStateChangedEvent evt = (MasterDetailsContentOutline.NodeExpandedStateChangedEvent) event;
                final MasterDetailsContentNodePart node = evt.node();

                final boolean expandedState = node.isExpanded();

                if (treeViewer.getExpandedState(node) != expandedState) {
                    treeViewer.setExpandedState(node, expandedState);
                }
            } else if (event instanceof MasterDetailsContentOutline.FilterChangedEvent) {
                final MasterDetailsContentOutline.FilterChangedEvent evt = (MasterDetailsContentOutline.FilterChangedEvent) event;
                filteredTree.changeFilterText(evt.filter());
            }
        }
    };

    outline.attach(contentTreeListener);

    treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
        public void selectionChanged(final SelectionChangedEvent event) {
            ignoreSelectionChange.set(true);

            try {
                final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                final List<MasterDetailsContentNodePart> nodes = new ArrayList<MasterDetailsContentNodePart>();

                for (Iterator<?> itr = selection.iterator(); itr.hasNext();) {
                    nodes.add((MasterDetailsContentNodePart) itr.next());
                }

                outline.setSelectedNodes(nodes);
            } finally {
                ignoreSelectionChange.set(false);
            }
        }
    });

    treeViewer.addDoubleClickListener(new IDoubleClickListener() {
        public void doubleClick(DoubleClickEvent event) {
            IStructuredSelection thisSelection = (IStructuredSelection) event.getSelection();
            if (thisSelection.size() == 1) {
                MasterDetailsContentNodePart selectedNode = (MasterDetailsContentNodePart) thisSelection
                        .getFirstElement();
                selectedNode.setExpanded(!selectedNode.isExpanded());
            }
        }
    });

    treeViewer.addTreeListener(new ITreeViewerListener() {
        public void treeExpanded(final TreeExpansionEvent event) {
            ignoreExpandedStateChange.set(true);

            try {
                final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) event.getElement();
                node.setExpanded(true);
            } finally {
                ignoreExpandedStateChange.set(false);
            }
        }

        public void treeCollapsed(final TreeExpansionEvent event) {
            ignoreExpandedStateChange.set(true);

            try {
                final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) event.getElement();
                node.setExpanded(false);
            } finally {
                ignoreExpandedStateChange.set(false);
            }
        }
    });

    final ContentOutlineActionSupport actionSupport = new ContentOutlineActionSupport(outline, tree);

    treeViewer.setExpandedElements(outline.getExpandedNodes().toArray());
    contentTreeListener
            .handle(new MasterDetailsContentOutline.SelectionChangedEvent(outline.getSelectedNodes()));

    filteredTree.changeFilterText(outline.getFilterText());

    final ElementsTransfer transfer = new ElementsTransfer(
            getModelElement().type().getModelElementClass().getClassLoader());
    final Transfer[] transfers = new Transfer[] { transfer };

    final DragSource dragSource = new DragSource(tree, DND.DROP_COPY | DND.DROP_MOVE);
    dragSource.setTransfer(transfers);

    final List<Element> dragElements = new ArrayList<Element>();

    dragSource.addDragListener(new DragSourceListener() {
        public void dragStart(final DragSourceEvent event) {
            final TreeItem[] selection = tree.getSelection();
            final String filter = outline().getFilterText();

            if ((filter == null || filter.length() == 0) && draggable(selection)) {
                event.doit = true;

                for (TreeItem item : selection) {
                    final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) item.getData();
                    dragElements.add(node.getModelElement());
                }
            } else {
                event.doit = false;
            }
        }

        protected boolean draggable(final TreeItem[] selection) {
            if (selection.length > 0) {
                for (TreeItem item : selection) {
                    final MasterDetailsContentNodePart node = (MasterDetailsContentNodePart) item.getData();

                    if (!draggable(node)) {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }

        protected boolean draggable(final MasterDetailsContentNodePart node) {
            final Element element = node.getModelElement();

            if (element.parent() instanceof ElementList && node.controls(element)) {
                return true;
            }

            return false;
        }

        public void dragSetData(final DragSourceEvent event) {
            event.data = dragElements;
        }

        public void dragFinished(final DragSourceEvent event) {
            if (event.detail == DND.DROP_MOVE) {
                // When drop target is the same editor as drag source, the drop handler takes care of removing
                // elements from their original location. The following block of code accounts for the case when 
                // dropping into another editor.

                boolean droppedIntoAnotherEditor = false;

                for (Element dragElement : dragElements) {
                    if (!dragElement.disposed()) {
                        droppedIntoAnotherEditor = true;
                        break;
                    }
                }

                if (droppedIntoAnotherEditor) {
                    final TreeItem[] selection = tree.getSelection();
                    final List<MasterDetailsContentNodePart> dragNodes = new ArrayList<MasterDetailsContentNodePart>();

                    for (TreeItem item : selection) {
                        dragNodes.add((MasterDetailsContentNodePart) item.getData());
                    }

                    final MasterDetailsContentNodePart parentNode = dragNodes.get(0).getParentNode();

                    MasterDetailsContentNodePart selectionPostDelete = findSelectionPostDelete(
                            parentNode.nodes().visible(), dragNodes);

                    if (selectionPostDelete == null) {
                        selectionPostDelete = parentNode;
                    }

                    final Disposable suspension = outline.listeners().queue()
                            .suspend(SelectionChangedEventFilter.INSTANCE);

                    try {
                        for (Element dragElement : dragElements) {
                            final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();
                            dragElementContainer.remove(dragElement);
                        }
                    } catch (Exception e) {
                        // Log this exception unless the cause is EditFailedException. These exception
                        // are the result of the user declining a particular action that is necessary
                        // before the edit can happen (such as making a file writable).

                        final EditFailedException editFailedException = EditFailedException.findAsCause(e);

                        if (editFailedException == null) {
                            Sapphire.service(LoggingService.class).log(e);
                        }
                    } finally {
                        suspension.dispose();
                        outline.listeners().queue().process();
                    }

                    parentNode.getContentTree().setSelectedNode(selectionPostDelete);
                }
            }

            dragElements.clear();
        }
    });

    final DropTarget target = new DropTarget(tree, DND.DROP_COPY | DND.DROP_MOVE);
    target.setTransfer(transfers);

    target.addDropListener(new DropTargetAdapter() {
        public void dragOver(final DropTargetEvent event) {
            if (event.item != null) {
                final TreeItem dragOverItem = (TreeItem) event.item;
                final MasterDetailsContentNodePart dragOverNode = (MasterDetailsContentNodePart) dragOverItem
                        .getData();
                final MasterDetailsContentNodePart parentNode = dragOverNode.getParentNode();
                final List<MasterDetailsContentNodePart> siblingNodes = parentNode.nodes().visible();

                final Point pt = dragOverItem.getDisplay().map(null, tree, event.x, event.y);
                final Rectangle bounds = dragOverItem.getBounds();

                boolean dragOverNodeAcceptedDrop = false;

                if (pt.y > bounds.y + bounds.height / 3
                        && pt.y < bounds.y + bounds.height - bounds.height / 3) {
                    for (final PropertyDef dragOverTargetChildProperty : dragOverNode
                            .getChildNodeFactoryProperties()) {
                        if (dragOverTargetChildProperty instanceof ListProperty
                                && !dragOverTargetChildProperty.isReadOnly()) {
                            dragOverNodeAcceptedDrop = true;
                            event.feedback = DND.FEEDBACK_SELECT;

                            break;
                        }
                    }
                }

                if (!dragOverNodeAcceptedDrop) {
                    MasterDetailsContentNodePart precedingNode = null;
                    MasterDetailsContentNodePart trailingNode = null;

                    if (pt.y < bounds.y + bounds.height / 2) {
                        precedingNode = findPrecedingItem(siblingNodes, dragOverNode);
                        trailingNode = dragOverNode;

                        event.feedback = DND.FEEDBACK_INSERT_BEFORE;
                    } else {
                        precedingNode = dragOverNode;
                        trailingNode = findTrailingItem(siblingNodes, dragOverNode);

                        event.feedback = DND.FEEDBACK_INSERT_AFTER;
                    }

                    boolean ok = false;

                    if (precedingNode != null) {
                        final Element precedingElement = precedingNode.getModelElement();

                        if (precedingElement.parent() instanceof ElementList
                                && precedingNode.controls(precedingElement)) {
                            ok = true;
                        }
                    }

                    if (!ok && trailingNode != null) {
                        final Element trailingElement = trailingNode.getModelElement();

                        if (trailingElement.parent() instanceof ElementList
                                && trailingNode.controls(trailingElement)) {
                            ok = true;
                        }
                    }

                    if (!ok) {
                        event.feedback = DND.FEEDBACK_NONE;
                    }
                }
            }

            event.feedback |= DND.FEEDBACK_SCROLL;
        }

        @SuppressWarnings("unchecked")

        public void drop(final DropTargetEvent event) {
            if (event.data == null || event.item == null) {
                event.detail = DND.DROP_NONE;
                return;
            }

            // Determine where something was dropped.

            final List<ElementData> droppedElements = (List<ElementData>) event.data;
            final TreeItem dropTargetItem = (TreeItem) event.item;
            final MasterDetailsContentNodePart dropTargetNode = (MasterDetailsContentNodePart) dropTargetItem
                    .getData();
            final MasterDetailsContentNodePart parentNode = dropTargetNode.getParentNode();
            final List<MasterDetailsContentNodePart> siblingNodes = parentNode.nodes().visible();

            final Point pt = tree.getDisplay().map(null, tree, event.x, event.y);
            final Rectangle bounds = dropTargetItem.getBounds();

            MasterDetailsContentNodePart precedingNode = null;
            MasterDetailsContentNodePart trailingNode = null;

            boolean dropTargetNodeAcceptedDrop = false;

            if (pt.y > bounds.y + bounds.height / 3 && pt.y < bounds.y + bounds.height - bounds.height / 3) {
                for (final PropertyDef dropTargetChildProperty : dropTargetNode
                        .getChildNodeFactoryProperties()) {
                    if (dropTargetChildProperty instanceof ListProperty
                            && !dropTargetChildProperty.isReadOnly()) {
                        dropTargetNodeAcceptedDrop = true;
                        break;
                    }
                }
            }

            if (!dropTargetNodeAcceptedDrop) {
                if (pt.y < bounds.y + bounds.height / 2) {
                    precedingNode = findPrecedingItem(siblingNodes, dropTargetNode);
                    trailingNode = dropTargetNode;
                } else {
                    precedingNode = dropTargetNode;
                    trailingNode = findTrailingItem(siblingNodes, dropTargetNode);
                }
            }

            // Determine whether the drop was valid from model standpoint and figure out
            // where in the model the dropped elements are to be inserted.

            ElementList<?> list = null;
            int position = -1;

            if (precedingNode != null) {
                final Element precedingElement = precedingNode.getModelElement();

                if (precedingElement.parent() instanceof ElementList
                        && !precedingElement.parent().definition().isReadOnly()
                        && precedingNode.controls(precedingElement)) {
                    list = (ElementList<?>) precedingElement.parent();

                    final Set<ElementType> possibleListElementTypes = list.definition()
                            .service(PossibleTypesService.class).types();

                    for (final ElementData droppedElement : droppedElements) {
                        if (!possibleListElementTypes.contains(droppedElement.type())) {
                            list = null;
                            break;
                        }
                    }

                    if (list != null) {
                        position = list.indexOf(precedingElement) + 1;
                    }
                }
            }

            if (list == null && trailingNode != null) {
                final Element trailingElement = trailingNode.getModelElement();

                if (trailingElement.parent() instanceof ElementList
                        && !trailingElement.parent().definition().isReadOnly()
                        && trailingNode.controls(trailingElement)) {
                    list = (ElementList<?>) trailingElement.parent();

                    final Set<ElementType> possibleListElementTypes = list.definition()
                            .service(PossibleTypesService.class).types();

                    for (final ElementData droppedElement : droppedElements) {
                        if (!possibleListElementTypes.contains(droppedElement.type())) {
                            list = null;
                            break;
                        }
                    }

                    if (list != null) {
                        position = list.indexOf(trailingElement);
                    }
                }
            }

            if (list == null) {
                for (PropertyDef dropTargetChildProperty : dropTargetNode.getChildNodeFactoryProperties()) {
                    if (dropTargetChildProperty instanceof ListProperty
                            && !dropTargetChildProperty.isReadOnly()) {
                        final ListProperty dropTargetChildListProperty = (ListProperty) dropTargetChildProperty;

                        boolean compatible = true;

                        final Set<ElementType> possibleListElementTypes = dropTargetChildListProperty
                                .service(PossibleTypesService.class).types();

                        for (final ElementData droppedElement : droppedElements) {
                            if (!possibleListElementTypes.contains(droppedElement.type())) {
                                compatible = false;
                                break;
                            }
                        }

                        if (compatible) {
                            list = dropTargetNode.getLocalModelElement().property(dropTargetChildListProperty);
                            position = list.size();
                        }
                    }
                }
            }

            if (list == null) {
                event.detail = DND.DROP_NONE;
                return;
            }

            // Prevent a drop within a drag element.

            for (Property p = list; p != null; p = p.element().parent()) {
                for (final Element dragElement : dragElements) {
                    if (p.element() == dragElement) {
                        event.detail = DND.DROP_NONE;
                        return;
                    }
                }
            }

            // Perform the removal and insertion into the new location.

            final Disposable suspension = outline.listeners().queue()
                    .suspend(SelectionChangedEventFilter.INSTANCE);

            try {
                if (event.detail == DND.DROP_MOVE) {
                    for (Element dragElement : dragElements) {
                        final ElementList<?> dragElementContainer = (ElementList<?>) dragElement.parent();

                        if (dragElementContainer == list
                                && dragElementContainer.indexOf(dragElement) < position) {
                            position--;
                        }

                        dragElementContainer.remove(dragElement);
                    }
                }

                final List<MasterDetailsContentNodePart> newSelection = new ArrayList<MasterDetailsContentNodePart>();

                for (final ElementData droppedElement : droppedElements) {
                    final Element insertedElement = list.insert(droppedElement.type(), position);
                    insertedElement.copy(droppedElement);

                    newSelection.add(parentNode.findNode(insertedElement));

                    position++;
                }

                parentNode.getContentTree().setSelectedNodes(newSelection);
            } catch (Exception e) {
                // Log this exception unless the cause is EditFailedException. These exception
                // are the result of the user declining a particular action that is necessary
                // before the edit can happen (such as making a file writable).

                final EditFailedException editFailedException = EditFailedException.findAsCause(e);

                if (editFailedException == null) {
                    Sapphire.service(LoggingService.class).log(e);
                }

                event.detail = DND.DROP_NONE;
            } finally {
                suspension.dispose();
                outline.listeners().queue().process();
            }
        }
    });

    tree.addDisposeListener(new DisposeListener() {
        public void widgetDisposed(final DisposeEvent event) {
            outline.detach(contentTreeListener);
            actionSupport.dispose();
        }
    });

    return filteredTree;
}