]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramLayersPage.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / DiagramLayersPage.java
index ba7ed78366357d88f0c85b5c32305b80b147257d..1632f32caa5c0d6e58d2d9ff15992ea2a7ab01bb 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.modeling.ui.diagramEditor;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Set;\r
-\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.viewers.CellLabelProvider;\r
-import org.eclipse.jface.viewers.CheckStateChangedEvent;\r
-import org.eclipse.jface.viewers.CheckboxTreeViewer;\r
-import org.eclipse.jface.viewers.ICheckStateListener;\r
-import org.eclipse.jface.viewers.ICheckStateProvider;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.ISelectionChangedListener;\r
-import org.eclipse.jface.viewers.ITreeContentProvider;\r
-import org.eclipse.jface.viewers.SelectionChangedEvent;\r
-import org.eclipse.jface.viewers.TreeViewer;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerCell;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.custom.TreeEditor;\r
-import org.eclipse.swt.events.KeyAdapter;\r
-import org.eclipse.swt.events.KeyEvent;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.events.SelectionListener;\r
-import org.eclipse.swt.graphics.Color;\r
-import org.eclipse.swt.graphics.GC;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.graphics.Rectangle;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Listener;\r
-import org.eclipse.swt.widgets.Text;\r
-import org.eclipse.swt.widgets.Tree;\r
-import org.eclipse.swt.widgets.TreeColumn;\r
-import org.eclipse.swt.widgets.TreeItem;\r
-import org.eclipse.ui.part.Page;\r
-import org.simantics.diagram.layer.ILayersViewPage;\r
-import org.simantics.g2d.canvas.ICanvasContext;\r
-import org.simantics.g2d.diagram.DiagramHints;\r
-import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.g2d.diagram.participant.Selection;\r
-import org.simantics.g2d.element.ElementClass;\r
-import org.simantics.g2d.element.IElement;\r
-import org.simantics.g2d.element.handler.ElementLayers;\r
-import org.simantics.g2d.layers.IEditableLayer;\r
-import org.simantics.g2d.layers.ILayer;\r
-import org.simantics.g2d.layers.ILayers;\r
-import org.simantics.g2d.layers.ILayersEditor;\r
-import org.simantics.g2d.layers.SimpleLayer;\r
-import org.simantics.g2d.layers.ILayersEditor.ILayersEditorListener;\r
-import org.simantics.utils.datastructures.Arrays;\r
-import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
-import org.simantics.utils.datastructures.hints.IHintListener;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.ui.ISelectionUtils;\r
-\r
-public class DiagramLayersPage extends Page implements ILayersViewPage {\r
-\r
-    private static final String TEXT_APPLY_FOCUS_SETTINGS = "Focus Active";\r
-    private static final String TOOLTIP_APPLY_FOCUS_SETTINGS = "Only Focus Diagram Elements For Active Roles";\r
-    private static final String TEXT_IGNORE_FOCUS_SETTINGS = "Focus All";\r
-    private static final String TOOLTIP_IGNORE_FOCUS_SETTINGS = "Focus All Diagram Elements Regardless Of Active Roles";\r
-\r
-    private static final String TEXT_APPLY_VISIBILITY_SETTINGS = "Show Active";\r
-    private static final String TOOLTIP_APPLY_VISIBILITY_SETTINGS = "Only Show Diagram Elements For Active Roles";\r
-    private static final String TEXT_IGNORE_VISIBILITY_SETTINGS = "Show All";\r
-    private static final String TOOLTIP_IGNORE_VISIBILITY_SETTINGS = "Show All Diagram Elements Regardless Of Active Roles";\r
-\r
-    final private ICanvasContext context;\r
-    final private IDiagram diagram;\r
-    private CheckboxTreeViewer viewer;\r
-    private Composite composite;\r
-    private TreeEditor editor;\r
-\r
-    private Collection<IElement> elements = Collections.emptySet();\r
-\r
-    enum Attribute {\r
-        Visible,\r
-        Focusable\r
-    }\r
-\r
-    enum Tristate {\r
-        True,\r
-        False,\r
-        Both;\r
-\r
-        static Tristate to(Boolean b) {\r
-            return b == null ? null : b ? True : False;\r
-        }\r
-        boolean toBoolean() {\r
-            switch (this) {\r
-                case Both:\r
-                    throw new IllegalStateException("cannot convert Tristate Both to boolean");\r
-                case False:\r
-                    return false;\r
-                case True:\r
-                    return true;\r
-                default:\r
-                    return false;\r
-            }\r
-        }\r
-        Tristate toggle() {\r
-            switch (this) {\r
-                case Both:\r
-                case False:\r
-                    return True;\r
-                case True:\r
-                    return False;\r
-                default:\r
-                    return False;\r
-            }\r
-        }\r
-        Tristate merge(Tristate state) {\r
-            if (state == null)\r
-                return this;\r
-            switch (this) {\r
-                case Both:\r
-                    return Both;\r
-                case False:\r
-                    switch (state) {\r
-                        case False:\r
-                            return False;\r
-                        case Both:\r
-                        case True:\r
-                            return Both;\r
-                    }\r
-                case True:\r
-                    switch (state) {\r
-                        case True:\r
-                            return True;\r
-                        case False:\r
-                        case Both:\r
-                            return Both;\r
-                    }\r
-            }\r
-            return this;\r
-        }\r
-    }\r
-\r
-    Boolean getAttribute(IElement e, ILayer layer, Attribute attribute) {\r
-        ElementClass ec = e.getElementClass();\r
-        for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {\r
-            switch (attribute) {\r
-                case Visible:\r
-                    return Boolean.valueOf(el.isVisible(e, layer));\r
-                case Focusable:\r
-                    return Boolean.valueOf(el.isFocusable(e, layer));\r
-            }\r
-        }\r
-        return null;\r
-    }\r
-\r
-    boolean setAttribute(IElement e, ILayer layer, Attribute attribute, boolean value) {\r
-        ElementClass ec = e.getElementClass();\r
-        for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {\r
-            switch (attribute) {\r
-                case Visible:\r
-                    return el.setVisibility(e, layer, value);\r
-                case Focusable:\r
-                    return el.setFocusability(e, layer, value);\r
-            }\r
-        }\r
-        return false;\r
-    }\r
-\r
-    Tristate getJointAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute) {\r
-        Tristate state = null;\r
-        for (IElement e : elements) {\r
-            Boolean attr = getAttribute(e, layer, attribute);\r
-            if (attr == null)\r
-                continue;\r
-\r
-            if (state == null) {\r
-                state = Tristate.to(attr);\r
-            } else {\r
-                state = state.merge(Tristate.to(attr));\r
-            }\r
-        }\r
-        return state;\r
-    }\r
-\r
-    int setAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute, boolean value) {\r
-        int result = 0;\r
-        for (IElement e : elements) {\r
-            if (setAttribute(e, layer, attribute, value))\r
-                ++result;\r
-        }\r
-        return result;\r
-    }\r
-\r
-\r
-    final private IHintListener selectionListener = new HintListenerAdapter() {\r
-\r
-        @Override\r
-        public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
-            Collection<IElement> es = Collections.emptySet();\r
-            if (newValue instanceof Collection<?>) {\r
-                Collection<?> coll = (Collection<?>)newValue;\r
-                es = new ArrayList<IElement>(coll.size());\r
-                for (Object o : coll) {\r
-                    if (!(o instanceof IElement))\r
-                        return;\r
-                    es.add((IElement) o);\r
-                }\r
-                if (es.isEmpty())\r
-                    es = Collections.emptySet();\r
-            }\r
-            elements = es;\r
-            redraw();\r
-        }\r
-\r
-        private void redraw() {\r
-            viewer.getControl().getDisplay().asyncExec(new Runnable() {\r
-                @Override\r
-                public void run() {\r
-                    if (viewer.getControl().isDisposed())\r
-                        return;\r
-                    viewer.getControl().redraw();\r
-                }\r
-            });\r
-        }\r
-    };\r
-\r
-    public DiagramLayersPage(IDiagram diagram, ICanvasContext context) {\r
-\r
-        assert(diagram != null);\r
-\r
-        this.diagram = diagram;\r
-        this.context = context;\r
-\r
-        context.getDefaultHintContext().addKeyHintListener(Selection.SELECTION0, selectionListener);\r
-    }\r
-\r
-    @Override\r
-    public void dispose() {\r
-\r
-        context.getDefaultHintContext().removeKeyHintListener(Selection.SELECTION0, selectionListener);\r
-\r
-        super.dispose();\r
-\r
-    }\r
-\r
-    @Override\r
-    public void createControl(Composite parent) {\r
-\r
-        final ILayersEditor layers = diagram.getHint(DiagramHints.KEY_LAYERS_EDITOR);\r
-        layers.addListener(new ILayersEditorListener() {\r
-\r
-            @Override\r
-            public void layerRemoved(ILayer layer) {\r
-                scheduleRefresh();\r
-            }\r
-\r
-            @Override\r
-            public void layerAdded(ILayer layer) {\r
-                scheduleRefresh();\r
-            }\r
-\r
-            @Override\r
-            public void layerActivated(ILayer layer) {\r
-                scheduleRefresh();\r
-            }\r
-\r
-            @Override\r
-            public void layerDeactivated(ILayer layer) {\r
-                scheduleRefresh();\r
-            }\r
-\r
-            @Override\r
-            public void ignoreFocusChanged(boolean value) {\r
-            }\r
-\r
-            @Override\r
-            public void ignoreVisibilityChanged(boolean value) {\r
-            }\r
-\r
-            void scheduleRefresh() {\r
-                viewer.getControl().getDisplay().asyncExec(new Runnable() {\r
-                    @Override\r
-                    public void run() {\r
-                        viewer.refresh();\r
-                    }\r
-                });\r
-            }\r
-        });\r
-\r
-        composite = new Composite(parent, SWT.NONE);\r
-        GridLayoutFactory.fillDefaults().numColumns(4).applyTo(composite);\r
-\r
-        Button addButton = new Button(composite, SWT.NONE);\r
-        addButton.setText("New");\r
-        addButton.setToolTipText("Create New Diagram Role");\r
-        addButton.addSelectionListener(new SelectionListener() {\r
-\r
-            String findFreshName(ILayers layers, String proposal) {\r
-                Set<ILayer> all = layers.getLayers();\r
-                String name = proposal;\r
-                int i = 1;\r
-                while (true) {\r
-                    boolean match = false;\r
-                    for (ILayer layer : all) {\r
-                        if (name.equals(layer.getName())) {\r
-                            match = true;\r
-                            break;\r
-                        }\r
-                    }\r
-                    if (!match)\r
-                        return name;\r
-                    ++i;\r
-                    name = proposal + " " + i;\r
-                }\r
-            }\r
-\r
-            @Override\r
-            public void widgetSelected(SelectionEvent e) {\r
-                String name = findFreshName(layers, "New Role");\r
-                SimpleLayer layer = new SimpleLayer(name);\r
-                layers.addLayer(layer);\r
-                layers.activate(layer);\r
-            }\r
-\r
-            @Override\r
-            public void widgetDefaultSelected(SelectionEvent e) {\r
-                widgetSelected(e);\r
-            }\r
-\r
-        });\r
-\r
-        final Button removeButton = new Button(composite, SWT.NONE);\r
-        removeButton.setText("Remove");\r
-        removeButton.setToolTipText("Remove Selected Diagram Role");\r
-        removeButton.addSelectionListener(new SelectionListener() {\r
-            @Override\r
-            public void widgetSelected(SelectionEvent e) {\r
-                TreeItem[] items = viewer.getTree().getSelection();\r
-                if (items.length == 0)\r
-                    return;\r
-\r
-                TreeItem[] all = viewer.getTree().getItems();\r
-                int firstIndex = Arrays.indexOf(all, items[0]);\r
-                for (TreeItem item : items) {\r
-                    int index = Arrays.indexOf(all, item);\r
-                    all[index] = null;\r
-                    ILayer layer = (ILayer)item.getData();\r
-                    layers.removeLayer(layer);\r
-                }\r
-                int selectIndex = firstIndex - 1;\r
-                if (firstIndex == 0) {\r
-                    for (int i = firstIndex; i < all.length; ++i)\r
-                        if (all[i] != null) {\r
-                            selectIndex = i;\r
-                            break;\r
-                        }\r
-                }\r
-                if (selectIndex >= 0) {\r
-                    viewer.getTree().select(all[selectIndex]);\r
-                }\r
-            }\r
-\r
-            @Override\r
-            public void widgetDefaultSelected(SelectionEvent e) {\r
-                widgetSelected(e);\r
-            }\r
-        });\r
-\r
-        String ignoreVisibilityText = TEXT_IGNORE_VISIBILITY_SETTINGS;\r
-        String ignoreVisibilityTooltip = TOOLTIP_IGNORE_VISIBILITY_SETTINGS;\r
-        boolean ignoreVisibility = layers.getIgnoreVisibilitySettings();\r
-        if (ignoreVisibility) {\r
-            ignoreVisibilityText = TEXT_APPLY_VISIBILITY_SETTINGS;\r
-            ignoreVisibilityTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;\r
-        }\r
-\r
-        final Button ignoreVisibilityButton = new Button(composite, SWT.NONE);\r
-        ignoreVisibilityButton.setText(ignoreVisibilityText);\r
-        ignoreVisibilityButton.setToolTipText(ignoreVisibilityTooltip);\r
-        ignoreVisibilityButton.addSelectionListener(new SelectionListener() {\r
-\r
-            @Override\r
-            public void widgetSelected(SelectionEvent e) {\r
-                String ignoreText = TEXT_IGNORE_VISIBILITY_SETTINGS;\r
-                String ignoreTooltip= TOOLTIP_IGNORE_VISIBILITY_SETTINGS;\r
-                boolean ignore = layers.getIgnoreVisibilitySettings();\r
-                if(!ignore) {\r
-                    ignoreText = TEXT_APPLY_VISIBILITY_SETTINGS;\r
-                    ignoreTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;\r
-                    layers.setIgnoreVisibilitySettings(true);\r
-                } else {\r
-                    layers.setIgnoreVisibilitySettings(false);\r
-                }\r
-                ignoreVisibilityButton.setText(ignoreText);\r
-                ignoreVisibilityButton.setToolTipText(ignoreTooltip);\r
-                composite.layout();\r
-                context.getThreadAccess().asyncExec(new Runnable() {\r
-\r
-                    @Override\r
-                    public void run() {\r
-                        if(context.isDisposed()) return;\r
-                        context.getContentContext().setDirty();\r
-                    }\r
-\r
-                });\r
-            }\r
-\r
-            @Override\r
-            public void widgetDefaultSelected(SelectionEvent e) {\r
-                widgetSelected(e);\r
-            }\r
-\r
-        });\r
-\r
-        String ignoreFocusText = TEXT_IGNORE_FOCUS_SETTINGS;\r
-        String ignoreFocusTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;\r
-        boolean ignoreFocus = layers.getIgnoreFocusSettings();\r
-        if(ignoreFocus) {\r
-            ignoreFocusText = TEXT_APPLY_FOCUS_SETTINGS;\r
-            ignoreFocusTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;\r
-        }\r
-\r
-        final Button ignoreFocusButton = new Button(composite, SWT.NONE);\r
-        ignoreFocusButton.setText(ignoreFocusText);\r
-        ignoreFocusButton.setToolTipText(ignoreFocusTooltip);\r
-        ignoreFocusButton.addSelectionListener(new SelectionListener() {\r
-\r
-            @Override\r
-            public void widgetSelected(SelectionEvent e) {\r
-                String ignoreText = TEXT_IGNORE_FOCUS_SETTINGS;\r
-                String ignoreTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;\r
-                boolean ignore = layers.getIgnoreFocusSettings();\r
-                if(!ignore) {\r
-                    ignoreText = TEXT_APPLY_FOCUS_SETTINGS;\r
-                    ignoreTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;\r
-                    layers.setIgnoreFocusSettings(true);\r
-                } else {\r
-                    layers.setIgnoreFocusSettings(false);\r
-                }\r
-                ignoreFocusButton.setText(ignoreText);\r
-                ignoreFocusButton.setToolTipText(ignoreTooltip);\r
-                composite.layout();\r
-                context.getThreadAccess().asyncExec(new Runnable() {\r
-\r
-                    @Override\r
-                    public void run() {\r
-                        if(context.isDisposed()) return;\r
-                        context.getContentContext().setDirty();\r
-                    }\r
-\r
-                });\r
-            }\r
-\r
-            @Override\r
-            public void widgetDefaultSelected(SelectionEvent e) {\r
-                widgetSelected(e);\r
-            }\r
-\r
-        });\r
-\r
-        viewer = new CheckboxTreeViewer(composite, SWT.BORDER | SWT.FULL_SELECTION );\r
-\r
-        GridDataFactory.fillDefaults().grab(true, true).span(4, 1).applyTo(viewer.getControl());\r
-        viewer.getControl().setToolTipText("Selects the diagram to include in the exported document.");\r
-        viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);\r
-        viewer.getTree().setHeaderVisible(true);\r
-        editor = new TreeEditor(viewer.getTree());\r
-\r
-        final TreeColumn column1 = new TreeColumn(viewer.getTree(), SWT.LEFT);\r
-        column1.setText("Role");\r
-        column1.setWidth(100);\r
-        final TreeColumn column2 = new TreeColumn(viewer.getTree(), SWT.LEFT);\r
-        column2.setText("Show");\r
-        column2.setWidth(50);\r
-        final TreeColumn column3 = new TreeColumn(viewer.getTree(), SWT.LEFT);\r
-        column3.setText("Focus");\r
-        column3.setWidth(50);\r
-        viewer.getTree().addListener(SWT.Resize, new Listener() {\r
-            @Override\r
-            public void handleEvent(Event event) {\r
-                Tree tree = viewer.getTree();\r
-                Point size = tree.getSize();\r
-                int w = Math.max(size.x - 100 - tree.getBorderWidth() * 2, 30);\r
-                column1.setWidth(w);\r
-            }\r
-        });\r
-\r
-        viewer.getTree().addListener(SWT.PaintItem, new Listener() {\r
-            public void handleEvent(Event event) {\r
-                if ((event.index == 1 || event.index == 2) && !elements.isEmpty()) {\r
-                    ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);\r
-\r
-                    TreeItem item = (TreeItem)event.item;\r
-                    int index = viewer.getTree().indexOf(item);\r
-\r
-                    int width = 0;\r
-                    if (event.index == 1)\r
-                        width = (column2.getWidth() - 1);\r
-                    if (event.index == 2)\r
-                        width = (column3.getWidth() - 1);\r
-\r
-                    Attribute attribute = Attribute.Visible;\r
-                    if (event.index == 2)\r
-                        attribute = Attribute.Focusable;\r
-                    Tristate state = getJointAttribute(elements, lz[index], attribute);\r
-\r
-                    Color color = null;\r
-                    switch (state) {\r
-                        case False:\r
-                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_RED);\r
-                            break;\r
-                        case True:\r
-                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GREEN);\r
-                            break;\r
-                        case Both:\r
-                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GRAY);\r
-                            break;\r
-                    }\r
-\r
-                    GC gc = event.gc;\r
-                    Color foreground = gc.getForeground();\r
-                    Color background = gc.getBackground();\r
-                    gc.setBackground(color);\r
-                    gc.setForeground(viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_BLACK));\r
-                    gc.fillRectangle(event.x, event.y, width-1, event.height-1);\r
-                    Rectangle rect2 = new Rectangle(event.x, event.y, width-1, event.height-1);\r
-                    gc.drawRectangle(rect2);\r
-                    gc.setForeground(background);\r
-                    gc.setBackground(foreground);\r
-                }\r
-            }\r
-        });\r
-        viewer.getTree().addKeyListener(new KeyAdapter() {\r
-            @Override\r
-            public void keyPressed(KeyEvent event) {\r
-                if (event.keyCode == SWT.F2) {\r
-                    // FIXME: Eclipse currently eats F2 presses. This should be\r
-                    // implemented as a command handler or find some way to\r
-                    // force these listeners to have priority...\r
-                    System.out.println("startediting");\r
-\r
-                    TreeItem[] items = viewer.getTree().getSelection();\r
-                    if(items.length != 1)\r
-                        return;\r
-\r
-                    TreeItem item = items[0];\r
-\r
-                    ILayer layer = ISelectionUtils.filterSingleSelection(viewer.getSelection(), ILayer.class);\r
-                    if (layer == null)\r
-                        return;\r
-\r
-                    startEditing(layer, item);\r
-                }\r
-            }\r
-        });\r
-        viewer.getTree().addListener(SWT.MouseDown, new Listener() {\r
-            public void handleEvent(Event event) {\r
-                if (viewer.getControl().isDisposed())\r
-                    return;\r
-\r
-                Point pt = new Point(event.x, event.y);\r
-                TreeItem item = viewer.getTree().getItem(pt);\r
-                if (item == null)\r
-                    return;\r
-\r
-                int index = viewer.getTree().indexOf(item);\r
-                ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);\r
-                ILayer layer = lz[index];\r
-\r
-                Rectangle rect = item.getBounds(0);\r
-                if (event.count == 2 && rect.contains(pt)) {\r
-                    startEditing(layer, item);\r
-                    return;\r
-                }\r
-\r
-                // Cannot adjust visibility/focusability if no elements are selected.\r
-                if (elements.isEmpty())\r
-                    return;\r
-\r
-                rect = item.getBounds(1);\r
-                if (rect.contains(pt)) {\r
-                    Tristate state = getJointAttribute(elements, layer, Attribute.Visible);\r
-                    if (setAttribute(elements, layer, Attribute.Visible, state.toggle().toBoolean()) > 0) {\r
-                        refresh();\r
-                    }\r
-                    return;\r
-                }\r
-\r
-                Rectangle rect2 = item.getBounds(2);\r
-                if (rect2.contains(pt)) {\r
-                    Tristate state = getJointAttribute(elements, layer, Attribute.Focusable);\r
-                    if (setAttribute(elements, layer, Attribute.Focusable, state.toggle().toBoolean()) > 0) {\r
-                        refresh();\r
-                    }\r
-                    return;\r
-                }\r
-            }\r
-\r
-            private void refresh() {\r
-                viewer.getControl().redraw();\r
-                context.getThreadAccess().asyncExec(new Runnable() {\r
-                    @Override\r
-                    public void run() {\r
-                        if (context.isDisposed())\r
-                            return;\r
-                        context.getContentContext().setDirty();\r
-                    }\r
-                });\r
-            }\r
-        });\r
-\r
-        viewer.addCheckStateListener(new ICheckStateListener(){\r
-            @Override\r
-            public void checkStateChanged(CheckStateChangedEvent event) {\r
-                ILayer layer = (ILayer)event.getElement();\r
-                if(event.getChecked()) layers.activate(layer);\r
-                else layers.deactivate(layer);\r
-                viewer.setSubtreeChecked(event.getElement(), event.getChecked());\r
-                context.getThreadAccess().asyncExec(new Runnable() {\r
-\r
-                    @Override\r
-                    public void run() {\r
-                        if(context.isDisposed()) return;\r
-                        context.getContentContext().setDirty();\r
-                    }\r
-\r
-                });\r
-            }\r
-        });\r
-\r
-        viewer.addSelectionChangedListener(new ISelectionChangedListener() {\r
-            @Override\r
-            public void selectionChanged(SelectionChangedEvent event) {\r
-                ISelection s = event.getSelection();\r
-                if (s.isEmpty()) {\r
-                    removeButton.setEnabled(false);\r
-                } else {\r
-                    removeButton.setEnabled(true);\r
-                }\r
-            }\r
-        });\r
-\r
-        viewer.setContentProvider(new ITreeContentProvider(){\r
-            @Override\r
-            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
-            }\r
-            @Override\r
-            public void dispose() {\r
-            }\r
-            @Override\r
-            public Object[] getElements(Object inputElement) {\r
-                return layers.getLayers().toArray();\r
-            }\r
-            @Override\r
-            public boolean hasChildren(Object element) {\r
-                return false;\r
-            }\r
-            @Override\r
-            public Object getParent(Object element) {\r
-                return null;\r
-            }\r
-            @Override\r
-            public Object[] getChildren(Object parentElement) {\r
-                return new Object[0];\r
-            }\r
-        });\r
-        viewer.setLabelProvider(new CellLabelProvider() {\r
-            @Override\r
-            public void update(ViewerCell cell) {\r
-                if(cell.getColumnIndex() == 0) {\r
-                    ILayer layer  = (ILayer)cell.getElement();\r
-                    cell.setText(layer.getName());\r
-                } else {\r
-                    cell.setText("");\r
-                }\r
-            }\r
-        });\r
-        viewer.setCheckStateProvider(new ICheckStateProvider() {\r
-            @Override\r
-            public boolean isChecked(Object element) {\r
-                ILayer layer  = (ILayer)element;\r
-                final boolean isActive = layers.isActive(layer);\r
-                return isActive;\r
-            }\r
-            @Override\r
-            public boolean isGrayed(Object element) {\r
-                return false;\r
-            }\r
-        });\r
-\r
-        viewer.setInput(this);\r
-\r
-        for(ILayer layer : layers.getVisibleLayers()) {\r
-            viewer.setSubtreeChecked(layer, true);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public Control getControl() {\r
-        return composite;\r
-    }\r
-\r
-    @Override\r
-    public void setFocus() {\r
-    }\r
-\r
-    @Override\r
-    public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
-    }\r
-\r
-    @Override\r
-    public ISelection getSelection() {\r
-        return null;\r
-    }\r
-\r
-    @Override\r
-    public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
-    }\r
-\r
-    @Override\r
-    public void setSelection(ISelection selection) {\r
-    }\r
-\r
-    private boolean startEditing(final ILayer layer, final TreeItem item/*, final int columnIndex*/) {\r
-\r
-        //        Column column = columns[columnIndex];\r
-\r
-        String initialText = layer.getName();\r
-\r
-        final Composite composite = new Composite(viewer.getTree(), SWT.NONE);\r
-        final Text text = new Text(composite, SWT.BORDER);\r
-        final int insetX = 0;\r
-        final int insetY = 0;\r
-        composite.addListener(SWT.Resize, new Listener() {\r
-            public void handleEvent(Event e) {\r
-                Rectangle rect = composite.getClientArea();\r
-                text.setBounds(rect.x + insetX, rect.y + insetY, rect.width - insetX * 2, rect.height\r
-                        - insetY * 2);\r
-            }\r
-        });\r
-        Listener textListener = new Listener() {\r
-            public void handleEvent(final Event e) {\r
-                //String error;\r
-                String newText;\r
-                switch (e.type) {\r
-                    case SWT.FocusOut:\r
-                        if(layer instanceof IEditableLayer) {\r
-                            IEditableLayer l = (IEditableLayer)layer;\r
-                            l.setName(text.getText());\r
-                            System.out.println("renamed layer to " + text.getText());\r
-                            viewer.refresh();\r
-                        }\r
-\r
-                        //                                     // Item may be disposed if the tree gets reset after a previous editing.\r
-                        //                                     if (!item.isDisposed()) {\r
-                        //                                             item.setText(columnIndex, text.getText());\r
-                        //                                             queueSelectionRefresh(context);\r
-                        //                                     }\r
-                        //                             } else {\r
-                        //                                     //                                System.out.println("validation error: " + error);\r
-                        //                             }\r
-                        composite.dispose();\r
-                        break;\r
-                    case SWT.Modify:\r
-                        //                             newText = text.getText();\r
-                        //                             error = modifier.isValid(newText);\r
-                        //                             if (error != null) {\r
-                        //                                     text.setBackground(invalidModificationColor);\r
-                        //                                     //                                System.out.println("validation error: " + error);\r
-                        //                             } else {\r
-                        //                                     text.setBackground(null);\r
-                        //                             }\r
-                        break;\r
-                    case SWT.Verify:\r
-                        newText = text.getText();\r
-                        String leftText = newText.substring(0, e.start);\r
-                        String rightText = newText.substring(e.end, newText.length());\r
-                        GC gc = new GC(text);\r
-                        Point size = gc.textExtent(leftText + e.text + rightText);\r
-                        gc.dispose();\r
-                        size = text.computeSize(size.x, SWT.DEFAULT);\r
-                        editor.horizontalAlignment = SWT.LEFT;\r
-                        Rectangle itemRect = item.getBounds(0),\r
-                        rect = viewer.getTree().getClientArea();\r
-                        editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;\r
-                        int left = itemRect.x,\r
-                        right = rect.x + rect.width;\r
-                        editor.minimumWidth = Math.min(editor.minimumWidth, right - left);\r
-                        editor.minimumHeight = size.y + insetY * 2;\r
-                        editor.layout();\r
-                        break;\r
-                    case SWT.Traverse:\r
-                        switch (e.detail) {\r
-                            case SWT.TRAVERSE_RETURN:\r
-                                if(layer instanceof IEditableLayer) {\r
-                                    IEditableLayer l = (IEditableLayer)layer;\r
-                                    l.setName(text.getText());\r
-                                    //System.out.println("renamed layer to " + text.getText());\r
-                                    viewer.refresh();\r
-                                }\r
-                                //                                     error = modifier.isValid(text.getText());\r
-                                //                                     if (error == null) {\r
-                                //                                             modifier.modify(text.getText());\r
-                                //                                             if (!item.isDisposed()) {\r
-                                //                                                     item.setText(columnIndex, text.getText());\r
-                                //                                                     queueSelectionRefresh(context);\r
-                                //                                             }\r
-                                //                                     }\r
-                                // FALL THROUGH\r
-                            case SWT.TRAVERSE_ESCAPE:\r
-                                composite.dispose();\r
-                                e.doit = false;\r
-                                break;\r
-                            default:\r
-                                //System.out.println("unhandled traversal: " + e.detail);\r
-                                break;\r
-                        }\r
-                        break;\r
-                }\r
-            }\r
-        };\r
-        text.addListener(SWT.FocusOut, textListener);\r
-        text.addListener(SWT.Traverse, textListener);\r
-        text.addListener(SWT.Verify, textListener);\r
-        text.addListener(SWT.Modify, textListener);\r
-        editor.setEditor(composite, item, 0);\r
-        text.setText(initialText);\r
-        text.selectAll();\r
-        text.setFocus();\r
-        //        lastItem[0] = item;\r
-        return true;\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * 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:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.modeling.ui.diagramEditor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.CellLabelProvider;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ICheckStateProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TreeEditor;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.part.Page;
+import org.simantics.diagram.layer.ILayersViewPage;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.diagram.DiagramHints;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.participant.Selection;
+import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.handler.ElementLayers;
+import org.simantics.g2d.layers.IEditableLayer;
+import org.simantics.g2d.layers.ILayer;
+import org.simantics.g2d.layers.ILayers;
+import org.simantics.g2d.layers.ILayersEditor;
+import org.simantics.g2d.layers.SimpleLayer;
+import org.simantics.g2d.layers.ILayersEditor.ILayersEditorListener;
+import org.simantics.utils.datastructures.Arrays;
+import org.simantics.utils.datastructures.hints.HintListenerAdapter;
+import org.simantics.utils.datastructures.hints.IHintListener;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.ui.ISelectionUtils;
+
+public class DiagramLayersPage extends Page implements ILayersViewPage {
+
+    private static final String TEXT_APPLY_FOCUS_SETTINGS = "Focus Active";
+    private static final String TOOLTIP_APPLY_FOCUS_SETTINGS = "Only Focus Diagram Elements For Active Roles";
+    private static final String TEXT_IGNORE_FOCUS_SETTINGS = "Focus All";
+    private static final String TOOLTIP_IGNORE_FOCUS_SETTINGS = "Focus All Diagram Elements Regardless Of Active Roles";
+
+    private static final String TEXT_APPLY_VISIBILITY_SETTINGS = "Show Active";
+    private static final String TOOLTIP_APPLY_VISIBILITY_SETTINGS = "Only Show Diagram Elements For Active Roles";
+    private static final String TEXT_IGNORE_VISIBILITY_SETTINGS = "Show All";
+    private static final String TOOLTIP_IGNORE_VISIBILITY_SETTINGS = "Show All Diagram Elements Regardless Of Active Roles";
+
+    final private ICanvasContext context;
+    final private IDiagram diagram;
+    private CheckboxTreeViewer viewer;
+    private Composite composite;
+    private TreeEditor editor;
+
+    private Collection<IElement> elements = Collections.emptySet();
+
+    enum Attribute {
+        Visible,
+        Focusable
+    }
+
+    enum Tristate {
+        True,
+        False,
+        Both;
+
+        static Tristate to(Boolean b) {
+            return b == null ? null : b ? True : False;
+        }
+        boolean toBoolean() {
+            switch (this) {
+                case Both:
+                    throw new IllegalStateException("cannot convert Tristate Both to boolean");
+                case False:
+                    return false;
+                case True:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        Tristate toggle() {
+            switch (this) {
+                case Both:
+                case False:
+                    return True;
+                case True:
+                    return False;
+                default:
+                    return False;
+            }
+        }
+        Tristate merge(Tristate state) {
+            if (state == null)
+                return this;
+            switch (this) {
+                case Both:
+                    return Both;
+                case False:
+                    switch (state) {
+                        case False:
+                            return False;
+                        case Both:
+                        case True:
+                            return Both;
+                    }
+                case True:
+                    switch (state) {
+                        case True:
+                            return True;
+                        case False:
+                        case Both:
+                            return Both;
+                    }
+            }
+            return this;
+        }
+    }
+
+    Boolean getAttribute(IElement e, ILayer layer, Attribute attribute) {
+        ElementClass ec = e.getElementClass();
+        for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {
+            switch (attribute) {
+                case Visible:
+                    return Boolean.valueOf(el.isVisible(e, layer));
+                case Focusable:
+                    return Boolean.valueOf(el.isFocusable(e, layer));
+            }
+        }
+        return null;
+    }
+
+    boolean setAttribute(IElement e, ILayer layer, Attribute attribute, boolean value) {
+        ElementClass ec = e.getElementClass();
+        for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {
+            switch (attribute) {
+                case Visible:
+                    return el.setVisibility(e, layer, value);
+                case Focusable:
+                    return el.setFocusability(e, layer, value);
+            }
+        }
+        return false;
+    }
+
+    Tristate getJointAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute) {
+        Tristate state = null;
+        for (IElement e : elements) {
+            Boolean attr = getAttribute(e, layer, attribute);
+            if (attr == null)
+                continue;
+
+            if (state == null) {
+                state = Tristate.to(attr);
+            } else {
+                state = state.merge(Tristate.to(attr));
+            }
+        }
+        return state;
+    }
+
+    int setAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute, boolean value) {
+        int result = 0;
+        for (IElement e : elements) {
+            if (setAttribute(e, layer, attribute, value))
+                ++result;
+        }
+        return result;
+    }
+
+
+    final private IHintListener selectionListener = new HintListenerAdapter() {
+
+        @Override
+        public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+            Collection<IElement> es = Collections.emptySet();
+            if (newValue instanceof Collection<?>) {
+                Collection<?> coll = (Collection<?>)newValue;
+                es = new ArrayList<IElement>(coll.size());
+                for (Object o : coll) {
+                    if (!(o instanceof IElement))
+                        return;
+                    es.add((IElement) o);
+                }
+                if (es.isEmpty())
+                    es = Collections.emptySet();
+            }
+            elements = es;
+            redraw();
+        }
+
+        private void redraw() {
+            viewer.getControl().getDisplay().asyncExec(new Runnable() {
+                @Override
+                public void run() {
+                    if (viewer.getControl().isDisposed())
+                        return;
+                    viewer.getControl().redraw();
+                }
+            });
+        }
+    };
+
+    public DiagramLayersPage(IDiagram diagram, ICanvasContext context) {
+
+        assert(diagram != null);
+
+        this.diagram = diagram;
+        this.context = context;
+
+        context.getDefaultHintContext().addKeyHintListener(Selection.SELECTION0, selectionListener);
+    }
+
+    @Override
+    public void dispose() {
+
+        context.getDefaultHintContext().removeKeyHintListener(Selection.SELECTION0, selectionListener);
+
+        super.dispose();
+
+    }
+
+    @Override
+    public void createControl(Composite parent) {
+
+        final ILayersEditor layers = diagram.getHint(DiagramHints.KEY_LAYERS_EDITOR);
+        layers.addListener(new ILayersEditorListener() {
+
+            @Override
+            public void layerRemoved(ILayer layer) {
+                scheduleRefresh();
+            }
+
+            @Override
+            public void layerAdded(ILayer layer) {
+                scheduleRefresh();
+            }
+
+            @Override
+            public void layerActivated(ILayer layer) {
+                scheduleRefresh();
+            }
+
+            @Override
+            public void layerDeactivated(ILayer layer) {
+                scheduleRefresh();
+            }
+
+            @Override
+            public void ignoreFocusChanged(boolean value) {
+            }
+
+            @Override
+            public void ignoreVisibilityChanged(boolean value) {
+            }
+
+            void scheduleRefresh() {
+                viewer.getControl().getDisplay().asyncExec(new Runnable() {
+                    @Override
+                    public void run() {
+                        viewer.refresh();
+                    }
+                });
+            }
+        });
+
+        composite = new Composite(parent, SWT.NONE);
+        GridLayoutFactory.fillDefaults().numColumns(4).applyTo(composite);
+
+        Button addButton = new Button(composite, SWT.NONE);
+        addButton.setText("New");
+        addButton.setToolTipText("Create New Diagram Role");
+        addButton.addSelectionListener(new SelectionListener() {
+
+            String findFreshName(ILayers layers, String proposal) {
+                Set<ILayer> all = layers.getLayers();
+                String name = proposal;
+                int i = 1;
+                while (true) {
+                    boolean match = false;
+                    for (ILayer layer : all) {
+                        if (name.equals(layer.getName())) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match)
+                        return name;
+                    ++i;
+                    name = proposal + " " + i;
+                }
+            }
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                String name = findFreshName(layers, "New Role");
+                SimpleLayer layer = new SimpleLayer(name);
+                layers.addLayer(layer);
+                layers.activate(layer);
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                widgetSelected(e);
+            }
+
+        });
+
+        final Button removeButton = new Button(composite, SWT.NONE);
+        removeButton.setText("Remove");
+        removeButton.setToolTipText("Remove Selected Diagram Role");
+        removeButton.addSelectionListener(new SelectionListener() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                TreeItem[] items = viewer.getTree().getSelection();
+                if (items.length == 0)
+                    return;
+
+                TreeItem[] all = viewer.getTree().getItems();
+                int firstIndex = Arrays.indexOf(all, items[0]);
+                for (TreeItem item : items) {
+                    int index = Arrays.indexOf(all, item);
+                    all[index] = null;
+                    ILayer layer = (ILayer)item.getData();
+                    layers.removeLayer(layer);
+                }
+                int selectIndex = firstIndex - 1;
+                if (firstIndex == 0) {
+                    for (int i = firstIndex; i < all.length; ++i)
+                        if (all[i] != null) {
+                            selectIndex = i;
+                            break;
+                        }
+                }
+                if (selectIndex >= 0) {
+                    viewer.getTree().select(all[selectIndex]);
+                }
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                widgetSelected(e);
+            }
+        });
+
+        String ignoreVisibilityText = TEXT_IGNORE_VISIBILITY_SETTINGS;
+        String ignoreVisibilityTooltip = TOOLTIP_IGNORE_VISIBILITY_SETTINGS;
+        boolean ignoreVisibility = layers.getIgnoreVisibilitySettings();
+        if (ignoreVisibility) {
+            ignoreVisibilityText = TEXT_APPLY_VISIBILITY_SETTINGS;
+            ignoreVisibilityTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;
+        }
+
+        final Button ignoreVisibilityButton = new Button(composite, SWT.NONE);
+        ignoreVisibilityButton.setText(ignoreVisibilityText);
+        ignoreVisibilityButton.setToolTipText(ignoreVisibilityTooltip);
+        ignoreVisibilityButton.addSelectionListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                String ignoreText = TEXT_IGNORE_VISIBILITY_SETTINGS;
+                String ignoreTooltip= TOOLTIP_IGNORE_VISIBILITY_SETTINGS;
+                boolean ignore = layers.getIgnoreVisibilitySettings();
+                if(!ignore) {
+                    ignoreText = TEXT_APPLY_VISIBILITY_SETTINGS;
+                    ignoreTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;
+                    layers.setIgnoreVisibilitySettings(true);
+                } else {
+                    layers.setIgnoreVisibilitySettings(false);
+                }
+                ignoreVisibilityButton.setText(ignoreText);
+                ignoreVisibilityButton.setToolTipText(ignoreTooltip);
+                composite.layout();
+                context.getThreadAccess().asyncExec(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        if(context.isDisposed()) return;
+                        context.getContentContext().setDirty();
+                    }
+
+                });
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                widgetSelected(e);
+            }
+
+        });
+
+        String ignoreFocusText = TEXT_IGNORE_FOCUS_SETTINGS;
+        String ignoreFocusTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;
+        boolean ignoreFocus = layers.getIgnoreFocusSettings();
+        if(ignoreFocus) {
+            ignoreFocusText = TEXT_APPLY_FOCUS_SETTINGS;
+            ignoreFocusTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;
+        }
+
+        final Button ignoreFocusButton = new Button(composite, SWT.NONE);
+        ignoreFocusButton.setText(ignoreFocusText);
+        ignoreFocusButton.setToolTipText(ignoreFocusTooltip);
+        ignoreFocusButton.addSelectionListener(new SelectionListener() {
+
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                String ignoreText = TEXT_IGNORE_FOCUS_SETTINGS;
+                String ignoreTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;
+                boolean ignore = layers.getIgnoreFocusSettings();
+                if(!ignore) {
+                    ignoreText = TEXT_APPLY_FOCUS_SETTINGS;
+                    ignoreTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;
+                    layers.setIgnoreFocusSettings(true);
+                } else {
+                    layers.setIgnoreFocusSettings(false);
+                }
+                ignoreFocusButton.setText(ignoreText);
+                ignoreFocusButton.setToolTipText(ignoreTooltip);
+                composite.layout();
+                context.getThreadAccess().asyncExec(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        if(context.isDisposed()) return;
+                        context.getContentContext().setDirty();
+                    }
+
+                });
+            }
+
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                widgetSelected(e);
+            }
+
+        });
+
+        viewer = new CheckboxTreeViewer(composite, SWT.BORDER | SWT.FULL_SELECTION );
+
+        GridDataFactory.fillDefaults().grab(true, true).span(4, 1).applyTo(viewer.getControl());
+        viewer.getControl().setToolTipText("Selects the diagram to include in the exported document.");
+        viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
+        viewer.getTree().setHeaderVisible(true);
+        editor = new TreeEditor(viewer.getTree());
+
+        final TreeColumn column1 = new TreeColumn(viewer.getTree(), SWT.LEFT);
+        column1.setText("Role");
+        column1.setWidth(100);
+        final TreeColumn column2 = new TreeColumn(viewer.getTree(), SWT.LEFT);
+        column2.setText("Show");
+        column2.setWidth(50);
+        final TreeColumn column3 = new TreeColumn(viewer.getTree(), SWT.LEFT);
+        column3.setText("Focus");
+        column3.setWidth(50);
+        viewer.getTree().addListener(SWT.Resize, new Listener() {
+            @Override
+            public void handleEvent(Event event) {
+                Tree tree = viewer.getTree();
+                Point size = tree.getSize();
+                int w = Math.max(size.x - 100 - tree.getBorderWidth() * 2, 30);
+                column1.setWidth(w);
+            }
+        });
+
+        viewer.getTree().addListener(SWT.PaintItem, new Listener() {
+            public void handleEvent(Event event) {
+                if ((event.index == 1 || event.index == 2) && !elements.isEmpty()) {
+                    ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);
+
+                    TreeItem item = (TreeItem)event.item;
+                    int index = viewer.getTree().indexOf(item);
+
+                    int width = 0;
+                    if (event.index == 1)
+                        width = (column2.getWidth() - 1);
+                    if (event.index == 2)
+                        width = (column3.getWidth() - 1);
+
+                    Attribute attribute = Attribute.Visible;
+                    if (event.index == 2)
+                        attribute = Attribute.Focusable;
+                    Tristate state = getJointAttribute(elements, lz[index], attribute);
+
+                    Color color = null;
+                    switch (state) {
+                        case False:
+                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_RED);
+                            break;
+                        case True:
+                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GREEN);
+                            break;
+                        case Both:
+                            color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GRAY);
+                            break;
+                    }
+
+                    GC gc = event.gc;
+                    Color foreground = gc.getForeground();
+                    Color background = gc.getBackground();
+                    gc.setBackground(color);
+                    gc.setForeground(viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_BLACK));
+                    gc.fillRectangle(event.x, event.y, width-1, event.height-1);
+                    Rectangle rect2 = new Rectangle(event.x, event.y, width-1, event.height-1);
+                    gc.drawRectangle(rect2);
+                    gc.setForeground(background);
+                    gc.setBackground(foreground);
+                }
+            }
+        });
+        viewer.getTree().addKeyListener(new KeyAdapter() {
+            @Override
+            public void keyPressed(KeyEvent event) {
+                if (event.keyCode == SWT.F2) {
+                    // FIXME: Eclipse currently eats F2 presses. This should be
+                    // implemented as a command handler or find some way to
+                    // force these listeners to have priority...
+                    System.out.println("startediting");
+
+                    TreeItem[] items = viewer.getTree().getSelection();
+                    if(items.length != 1)
+                        return;
+
+                    TreeItem item = items[0];
+
+                    ILayer layer = ISelectionUtils.filterSingleSelection(viewer.getSelection(), ILayer.class);
+                    if (layer == null)
+                        return;
+
+                    startEditing(layer, item);
+                }
+            }
+        });
+        viewer.getTree().addListener(SWT.MouseDown, new Listener() {
+            public void handleEvent(Event event) {
+                if (viewer.getControl().isDisposed())
+                    return;
+
+                Point pt = new Point(event.x, event.y);
+                TreeItem item = viewer.getTree().getItem(pt);
+                if (item == null)
+                    return;
+
+                int index = viewer.getTree().indexOf(item);
+                ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);
+                ILayer layer = lz[index];
+
+                Rectangle rect = item.getBounds(0);
+                if (event.count == 2 && rect.contains(pt)) {
+                    startEditing(layer, item);
+                    return;
+                }
+
+                // Cannot adjust visibility/focusability if no elements are selected.
+                if (elements.isEmpty())
+                    return;
+
+                rect = item.getBounds(1);
+                if (rect.contains(pt)) {
+                    Tristate state = getJointAttribute(elements, layer, Attribute.Visible);
+                    if (setAttribute(elements, layer, Attribute.Visible, state.toggle().toBoolean()) > 0) {
+                        refresh();
+                    }
+                    return;
+                }
+
+                Rectangle rect2 = item.getBounds(2);
+                if (rect2.contains(pt)) {
+                    Tristate state = getJointAttribute(elements, layer, Attribute.Focusable);
+                    if (setAttribute(elements, layer, Attribute.Focusable, state.toggle().toBoolean()) > 0) {
+                        refresh();
+                    }
+                    return;
+                }
+            }
+
+            private void refresh() {
+                viewer.getControl().redraw();
+                context.getThreadAccess().asyncExec(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (context.isDisposed())
+                            return;
+                        context.getContentContext().setDirty();
+                    }
+                });
+            }
+        });
+
+        viewer.addCheckStateListener(new ICheckStateListener(){
+            @Override
+            public void checkStateChanged(CheckStateChangedEvent event) {
+                ILayer layer = (ILayer)event.getElement();
+                if(event.getChecked()) layers.activate(layer);
+                else layers.deactivate(layer);
+                viewer.setSubtreeChecked(event.getElement(), event.getChecked());
+                context.getThreadAccess().asyncExec(new Runnable() {
+
+                    @Override
+                    public void run() {
+                        if(context.isDisposed()) return;
+                        context.getContentContext().setDirty();
+                    }
+
+                });
+            }
+        });
+
+        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+            @Override
+            public void selectionChanged(SelectionChangedEvent event) {
+                ISelection s = event.getSelection();
+                if (s.isEmpty()) {
+                    removeButton.setEnabled(false);
+                } else {
+                    removeButton.setEnabled(true);
+                }
+            }
+        });
+
+        viewer.setContentProvider(new ITreeContentProvider(){
+            @Override
+            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+            }
+            @Override
+            public void dispose() {
+            }
+            @Override
+            public Object[] getElements(Object inputElement) {
+                return layers.getLayers().toArray();
+            }
+            @Override
+            public boolean hasChildren(Object element) {
+                return false;
+            }
+            @Override
+            public Object getParent(Object element) {
+                return null;
+            }
+            @Override
+            public Object[] getChildren(Object parentElement) {
+                return new Object[0];
+            }
+        });
+        viewer.setLabelProvider(new CellLabelProvider() {
+            @Override
+            public void update(ViewerCell cell) {
+                if(cell.getColumnIndex() == 0) {
+                    ILayer layer  = (ILayer)cell.getElement();
+                    cell.setText(layer.getName());
+                } else {
+                    cell.setText("");
+                }
+            }
+        });
+        viewer.setCheckStateProvider(new ICheckStateProvider() {
+            @Override
+            public boolean isChecked(Object element) {
+                ILayer layer  = (ILayer)element;
+                final boolean isActive = layers.isActive(layer);
+                return isActive;
+            }
+            @Override
+            public boolean isGrayed(Object element) {
+                return false;
+            }
+        });
+
+        viewer.setInput(this);
+
+        for(ILayer layer : layers.getVisibleLayers()) {
+            viewer.setSubtreeChecked(layer, true);
+        }
+    }
+
+    @Override
+    public Control getControl() {
+        return composite;
+    }
+
+    @Override
+    public void setFocus() {
+    }
+
+    @Override
+    public void addSelectionChangedListener(ISelectionChangedListener listener) {
+    }
+
+    @Override
+    public ISelection getSelection() {
+        return null;
+    }
+
+    @Override
+    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+    }
+
+    @Override
+    public void setSelection(ISelection selection) {
+    }
+
+    private boolean startEditing(final ILayer layer, final TreeItem item/*, final int columnIndex*/) {
+
+        //        Column column = columns[columnIndex];
+
+        String initialText = layer.getName();
+
+        final Composite composite = new Composite(viewer.getTree(), SWT.NONE);
+        final Text text = new Text(composite, SWT.BORDER);
+        final int insetX = 0;
+        final int insetY = 0;
+        composite.addListener(SWT.Resize, new Listener() {
+            public void handleEvent(Event e) {
+                Rectangle rect = composite.getClientArea();
+                text.setBounds(rect.x + insetX, rect.y + insetY, rect.width - insetX * 2, rect.height
+                        - insetY * 2);
+            }
+        });
+        Listener textListener = new Listener() {
+            public void handleEvent(final Event e) {
+                //String error;
+                String newText;
+                switch (e.type) {
+                    case SWT.FocusOut:
+                        if(layer instanceof IEditableLayer) {
+                            IEditableLayer l = (IEditableLayer)layer;
+                            l.setName(text.getText());
+                            System.out.println("renamed layer to " + text.getText());
+                            viewer.refresh();
+                        }
+
+                        //                                     // Item may be disposed if the tree gets reset after a previous editing.
+                        //                                     if (!item.isDisposed()) {
+                        //                                             item.setText(columnIndex, text.getText());
+                        //                                             queueSelectionRefresh(context);
+                        //                                     }
+                        //                             } else {
+                        //                                     //                                System.out.println("validation error: " + error);
+                        //                             }
+                        composite.dispose();
+                        break;
+                    case SWT.Modify:
+                        //                             newText = text.getText();
+                        //                             error = modifier.isValid(newText);
+                        //                             if (error != null) {
+                        //                                     text.setBackground(invalidModificationColor);
+                        //                                     //                                System.out.println("validation error: " + error);
+                        //                             } else {
+                        //                                     text.setBackground(null);
+                        //                             }
+                        break;
+                    case SWT.Verify:
+                        newText = text.getText();
+                        String leftText = newText.substring(0, e.start);
+                        String rightText = newText.substring(e.end, newText.length());
+                        GC gc = new GC(text);
+                        Point size = gc.textExtent(leftText + e.text + rightText);
+                        gc.dispose();
+                        size = text.computeSize(size.x, SWT.DEFAULT);
+                        editor.horizontalAlignment = SWT.LEFT;
+                        Rectangle itemRect = item.getBounds(0),
+                        rect = viewer.getTree().getClientArea();
+                        editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;
+                        int left = itemRect.x,
+                        right = rect.x + rect.width;
+                        editor.minimumWidth = Math.min(editor.minimumWidth, right - left);
+                        editor.minimumHeight = size.y + insetY * 2;
+                        editor.layout();
+                        break;
+                    case SWT.Traverse:
+                        switch (e.detail) {
+                            case SWT.TRAVERSE_RETURN:
+                                if(layer instanceof IEditableLayer) {
+                                    IEditableLayer l = (IEditableLayer)layer;
+                                    l.setName(text.getText());
+                                    //System.out.println("renamed layer to " + text.getText());
+                                    viewer.refresh();
+                                }
+                                //                                     error = modifier.isValid(text.getText());
+                                //                                     if (error == null) {
+                                //                                             modifier.modify(text.getText());
+                                //                                             if (!item.isDisposed()) {
+                                //                                                     item.setText(columnIndex, text.getText());
+                                //                                                     queueSelectionRefresh(context);
+                                //                                             }
+                                //                                     }
+                                // FALL THROUGH
+                            case SWT.TRAVERSE_ESCAPE:
+                                composite.dispose();
+                                e.doit = false;
+                                break;
+                            default:
+                                //System.out.println("unhandled traversal: " + e.detail);
+                                break;
+                        }
+                        break;
+                }
+            }
+        };
+        text.addListener(SWT.FocusOut, textListener);
+        text.addListener(SWT.Traverse, textListener);
+        text.addListener(SWT.Verify, textListener);
+        text.addListener(SWT.Modify, textListener);
+        editor.setEditor(composite, item, 0);
+        text.setText(initialText);
+        text.selectAll();
+        text.setFocus();
+        //        lastItem[0] = item;
+        return true;
+    }
+
+}