]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramLayersPage.java
Configurable connection crossing styles
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / DiagramLayersPage.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.ui.diagramEditor;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Set;
18
19 import org.eclipse.jface.layout.GridDataFactory;
20 import org.eclipse.jface.layout.GridLayoutFactory;
21 import org.eclipse.jface.viewers.CellLabelProvider;
22 import org.eclipse.jface.viewers.CheckStateChangedEvent;
23 import org.eclipse.jface.viewers.CheckboxTreeViewer;
24 import org.eclipse.jface.viewers.ICheckStateListener;
25 import org.eclipse.jface.viewers.ICheckStateProvider;
26 import org.eclipse.jface.viewers.ISelection;
27 import org.eclipse.jface.viewers.ISelectionChangedListener;
28 import org.eclipse.jface.viewers.ITreeContentProvider;
29 import org.eclipse.jface.viewers.SelectionChangedEvent;
30 import org.eclipse.jface.viewers.TreeViewer;
31 import org.eclipse.jface.viewers.Viewer;
32 import org.eclipse.jface.viewers.ViewerCell;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.custom.TreeEditor;
35 import org.eclipse.swt.events.KeyAdapter;
36 import org.eclipse.swt.events.KeyEvent;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.graphics.Color;
40 import org.eclipse.swt.graphics.GC;
41 import org.eclipse.swt.graphics.Point;
42 import org.eclipse.swt.graphics.Rectangle;
43 import org.eclipse.swt.widgets.Button;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Control;
46 import org.eclipse.swt.widgets.Event;
47 import org.eclipse.swt.widgets.Listener;
48 import org.eclipse.swt.widgets.Text;
49 import org.eclipse.swt.widgets.Tree;
50 import org.eclipse.swt.widgets.TreeColumn;
51 import org.eclipse.swt.widgets.TreeItem;
52 import org.eclipse.ui.part.Page;
53 import org.simantics.diagram.layer.ILayersViewPage;
54 import org.simantics.g2d.canvas.ICanvasContext;
55 import org.simantics.g2d.diagram.DiagramHints;
56 import org.simantics.g2d.diagram.IDiagram;
57 import org.simantics.g2d.diagram.participant.Selection;
58 import org.simantics.g2d.element.ElementClass;
59 import org.simantics.g2d.element.IElement;
60 import org.simantics.g2d.element.handler.ElementLayers;
61 import org.simantics.g2d.layers.IEditableLayer;
62 import org.simantics.g2d.layers.ILayer;
63 import org.simantics.g2d.layers.ILayers;
64 import org.simantics.g2d.layers.ILayersEditor;
65 import org.simantics.g2d.layers.SimpleLayer;
66 import org.simantics.g2d.layers.ILayersEditor.ILayersEditorListener;
67 import org.simantics.utils.datastructures.Arrays;
68 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
69 import org.simantics.utils.datastructures.hints.IHintListener;
70 import org.simantics.utils.datastructures.hints.IHintObservable;
71 import org.simantics.utils.datastructures.hints.IHintContext.Key;
72 import org.simantics.utils.ui.ISelectionUtils;
73
74 public class DiagramLayersPage extends Page implements ILayersViewPage {
75
76     private static final String TEXT_APPLY_FOCUS_SETTINGS = Messages.DiagramLayersPage_FocusActive;
77     private static final String TOOLTIP_APPLY_FOCUS_SETTINGS = Messages.DiagramLayersPage_FocusActiveTT;
78     private static final String TEXT_IGNORE_FOCUS_SETTINGS = Messages.DiagramLayersPage_FocusAll;
79     private static final String TOOLTIP_IGNORE_FOCUS_SETTINGS = Messages.DiagramLayersPage_FocusAllTT;
80
81     private static final String TEXT_APPLY_VISIBILITY_SETTINGS = Messages.DiagramLayersPage_ShowActive;
82     private static final String TOOLTIP_APPLY_VISIBILITY_SETTINGS = Messages.DiagramLayersPage_ShowActiveTT;
83     private static final String TEXT_IGNORE_VISIBILITY_SETTINGS = Messages.DiagramLayersPage_ShowAll;
84     private static final String TOOLTIP_IGNORE_VISIBILITY_SETTINGS = Messages.DiagramLayersPage_ShowAllTT;
85
86     final private ICanvasContext context;
87     final private IDiagram diagram;
88     private CheckboxTreeViewer viewer;
89     private Composite composite;
90     private TreeEditor editor;
91
92     private Collection<IElement> elements = Collections.emptySet();
93
94     enum Attribute {
95         Visible,
96         Focusable
97     }
98
99     enum Tristate {
100         True,
101         False,
102         Both;
103
104         static Tristate to(Boolean b) {
105             return b == null ? null : b ? True : False;
106         }
107         boolean toBoolean() {
108             switch (this) {
109                 case Both:
110                     throw new IllegalStateException("cannot convert Tristate Both to boolean"); //$NON-NLS-1$
111                 case False:
112                     return false;
113                 case True:
114                     return true;
115                 default:
116                     return false;
117             }
118         }
119         Tristate toggle() {
120             switch (this) {
121                 case Both:
122                 case False:
123                     return True;
124                 case True:
125                     return False;
126                 default:
127                     return False;
128             }
129         }
130         Tristate merge(Tristate state) {
131             if (state == null)
132                 return this;
133             switch (this) {
134                 case Both:
135                     return Both;
136                 case False:
137                     switch (state) {
138                         case False:
139                             return False;
140                         case Both:
141                         case True:
142                             return Both;
143                     }
144                 case True:
145                     switch (state) {
146                         case True:
147                             return True;
148                         case False:
149                         case Both:
150                             return Both;
151                     }
152             }
153             return this;
154         }
155     }
156
157     Boolean getAttribute(IElement e, ILayer layer, Attribute attribute) {
158         ElementClass ec = e.getElementClass();
159         for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {
160             switch (attribute) {
161                 case Visible:
162                     return Boolean.valueOf(el.isVisible(e, layer));
163                 case Focusable:
164                     return Boolean.valueOf(el.isFocusable(e, layer));
165             }
166         }
167         return null;
168     }
169
170     boolean setAttribute(IElement e, ILayer layer, Attribute attribute, boolean value) {
171         ElementClass ec = e.getElementClass();
172         for (ElementLayers el : ec.getItemsByClass(ElementLayers.class)) {
173             switch (attribute) {
174                 case Visible:
175                     return el.setVisibility(e, layer, value);
176                 case Focusable:
177                     return el.setFocusability(e, layer, value);
178             }
179         }
180         return false;
181     }
182
183     Tristate getJointAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute) {
184         Tristate state = null;
185         for (IElement e : elements) {
186             Boolean attr = getAttribute(e, layer, attribute);
187             if (attr == null)
188                 continue;
189
190             if (state == null) {
191                 state = Tristate.to(attr);
192             } else {
193                 state = state.merge(Tristate.to(attr));
194             }
195         }
196         return state;
197     }
198
199     int setAttribute(Collection<IElement> elements, ILayer layer, Attribute attribute, boolean value) {
200         int result = 0;
201         for (IElement e : elements) {
202             if (setAttribute(e, layer, attribute, value))
203                 ++result;
204         }
205         return result;
206     }
207
208
209     final private IHintListener selectionListener = new HintListenerAdapter() {
210
211         @Override
212         public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
213             Collection<IElement> es = Collections.emptySet();
214             if (newValue instanceof Collection<?>) {
215                 Collection<?> coll = (Collection<?>)newValue;
216                 es = new ArrayList<IElement>(coll.size());
217                 for (Object o : coll) {
218                     if (!(o instanceof IElement))
219                         return;
220                     es.add((IElement) o);
221                 }
222                 if (es.isEmpty())
223                     es = Collections.emptySet();
224             }
225             elements = es;
226             redraw();
227         }
228
229         private void redraw() {
230             viewer.getControl().getDisplay().asyncExec(new Runnable() {
231                 @Override
232                 public void run() {
233                     if (viewer.getControl().isDisposed())
234                         return;
235                     viewer.getControl().redraw();
236                 }
237             });
238         }
239     };
240
241     public DiagramLayersPage(IDiagram diagram, ICanvasContext context) {
242
243         assert(diagram != null);
244
245         this.diagram = diagram;
246         this.context = context;
247
248         context.getDefaultHintContext().addKeyHintListener(Selection.SELECTION0, selectionListener);
249     }
250
251     @Override
252     public void dispose() {
253
254         context.getDefaultHintContext().removeKeyHintListener(Selection.SELECTION0, selectionListener);
255
256         super.dispose();
257
258     }
259
260     @Override
261     public void createControl(Composite parent) {
262
263         final ILayersEditor layers = diagram.getHint(DiagramHints.KEY_LAYERS_EDITOR);
264         layers.addListener(new ILayersEditorListener() {
265
266             @Override
267             public void layerRemoved(ILayer layer) {
268                 scheduleRefresh();
269             }
270
271             @Override
272             public void layerAdded(ILayer layer) {
273                 scheduleRefresh();
274             }
275
276             @Override
277             public void layerActivated(ILayer layer) {
278                 scheduleRefresh();
279             }
280
281             @Override
282             public void layerDeactivated(ILayer layer) {
283                 scheduleRefresh();
284             }
285
286             @Override
287             public void ignoreFocusChanged(boolean value) {
288             }
289
290             @Override
291             public void ignoreVisibilityChanged(boolean value) {
292             }
293
294             void scheduleRefresh() {
295                 viewer.getControl().getDisplay().asyncExec(new Runnable() {
296                     @Override
297                     public void run() {
298                         viewer.refresh();
299                     }
300                 });
301             }
302         });
303
304         composite = new Composite(parent, SWT.NONE);
305         GridLayoutFactory.fillDefaults().numColumns(4).applyTo(composite);
306
307         Button addButton = new Button(composite, SWT.NONE);
308         addButton.setText(Messages.DiagramLayersPage_New);
309         addButton.setToolTipText(Messages.DiagramLayersPage_NewTT);
310         addButton.addSelectionListener(new SelectionListener() {
311
312             String findFreshName(ILayers layers, String proposal) {
313                 Set<ILayer> all = layers.getLayers();
314                 String name = proposal;
315                 int i = 1;
316                 while (true) {
317                     boolean match = false;
318                     for (ILayer layer : all) {
319                         if (name.equals(layer.getName())) {
320                             match = true;
321                             break;
322                         }
323                     }
324                     if (!match)
325                         return name;
326                     ++i;
327                     name = proposal + " " + i; //$NON-NLS-1$
328                 }
329             }
330
331             @Override
332             public void widgetSelected(SelectionEvent e) {
333                 String name = findFreshName(layers, Messages.DiagramLayersPage_NewRole);
334                 SimpleLayer layer = new SimpleLayer(name);
335                 layers.addLayer(layer);
336                 layers.activate(layer);
337             }
338
339             @Override
340             public void widgetDefaultSelected(SelectionEvent e) {
341                 widgetSelected(e);
342             }
343
344         });
345
346         final Button removeButton = new Button(composite, SWT.NONE);
347         removeButton.setText(Messages.DiagramLayersPage_Remove);
348         removeButton.setToolTipText(Messages.DiagramLayersPage_RemoveTT);
349         removeButton.addSelectionListener(new SelectionListener() {
350             @Override
351             public void widgetSelected(SelectionEvent e) {
352                 TreeItem[] items = viewer.getTree().getSelection();
353                 if (items.length == 0)
354                     return;
355
356                 TreeItem[] all = viewer.getTree().getItems();
357                 int firstIndex = Arrays.indexOf(all, items[0]);
358                 for (TreeItem item : items) {
359                     int index = Arrays.indexOf(all, item);
360                     all[index] = null;
361                     ILayer layer = (ILayer)item.getData();
362                     layers.removeLayer(layer);
363                 }
364                 int selectIndex = firstIndex - 1;
365                 if (firstIndex == 0) {
366                     for (int i = firstIndex; i < all.length; ++i)
367                         if (all[i] != null) {
368                             selectIndex = i;
369                             break;
370                         }
371                 }
372                 if (selectIndex >= 0) {
373                     viewer.getTree().select(all[selectIndex]);
374                 }
375             }
376
377             @Override
378             public void widgetDefaultSelected(SelectionEvent e) {
379                 widgetSelected(e);
380             }
381         });
382
383         String ignoreVisibilityText = TEXT_IGNORE_VISIBILITY_SETTINGS;
384         String ignoreVisibilityTooltip = TOOLTIP_IGNORE_VISIBILITY_SETTINGS;
385         boolean ignoreVisibility = layers.getIgnoreVisibilitySettings();
386         if (ignoreVisibility) {
387             ignoreVisibilityText = TEXT_APPLY_VISIBILITY_SETTINGS;
388             ignoreVisibilityTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;
389         }
390
391         final Button ignoreVisibilityButton = new Button(composite, SWT.NONE);
392         ignoreVisibilityButton.setText(ignoreVisibilityText);
393         ignoreVisibilityButton.setToolTipText(ignoreVisibilityTooltip);
394         ignoreVisibilityButton.addSelectionListener(new SelectionListener() {
395
396             @Override
397             public void widgetSelected(SelectionEvent e) {
398                 String ignoreText = TEXT_IGNORE_VISIBILITY_SETTINGS;
399                 String ignoreTooltip= TOOLTIP_IGNORE_VISIBILITY_SETTINGS;
400                 boolean ignore = layers.getIgnoreVisibilitySettings();
401                 if(!ignore) {
402                     ignoreText = TEXT_APPLY_VISIBILITY_SETTINGS;
403                     ignoreTooltip = TOOLTIP_APPLY_VISIBILITY_SETTINGS;
404                     layers.setIgnoreVisibilitySettings(true);
405                 } else {
406                     layers.setIgnoreVisibilitySettings(false);
407                 }
408                 ignoreVisibilityButton.setText(ignoreText);
409                 ignoreVisibilityButton.setToolTipText(ignoreTooltip);
410                 composite.layout();
411                 context.getThreadAccess().asyncExec(new Runnable() {
412
413                     @Override
414                     public void run() {
415                         if(context.isDisposed()) return;
416                         context.getContentContext().setDirty();
417                     }
418
419                 });
420             }
421
422             @Override
423             public void widgetDefaultSelected(SelectionEvent e) {
424                 widgetSelected(e);
425             }
426
427         });
428
429         String ignoreFocusText = TEXT_IGNORE_FOCUS_SETTINGS;
430         String ignoreFocusTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;
431         boolean ignoreFocus = layers.getIgnoreFocusSettings();
432         if(ignoreFocus) {
433             ignoreFocusText = TEXT_APPLY_FOCUS_SETTINGS;
434             ignoreFocusTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;
435         }
436
437         final Button ignoreFocusButton = new Button(composite, SWT.NONE);
438         ignoreFocusButton.setText(ignoreFocusText);
439         ignoreFocusButton.setToolTipText(ignoreFocusTooltip);
440         ignoreFocusButton.addSelectionListener(new SelectionListener() {
441
442             @Override
443             public void widgetSelected(SelectionEvent e) {
444                 String ignoreText = TEXT_IGNORE_FOCUS_SETTINGS;
445                 String ignoreTooltip = TOOLTIP_IGNORE_FOCUS_SETTINGS;
446                 boolean ignore = layers.getIgnoreFocusSettings();
447                 if(!ignore) {
448                     ignoreText = TEXT_APPLY_FOCUS_SETTINGS;
449                     ignoreTooltip = TOOLTIP_APPLY_FOCUS_SETTINGS;
450                     layers.setIgnoreFocusSettings(true);
451                 } else {
452                     layers.setIgnoreFocusSettings(false);
453                 }
454                 ignoreFocusButton.setText(ignoreText);
455                 ignoreFocusButton.setToolTipText(ignoreTooltip);
456                 composite.layout();
457                 context.getThreadAccess().asyncExec(new Runnable() {
458
459                     @Override
460                     public void run() {
461                         if(context.isDisposed()) return;
462                         context.getContentContext().setDirty();
463                     }
464
465                 });
466             }
467
468             @Override
469             public void widgetDefaultSelected(SelectionEvent e) {
470                 widgetSelected(e);
471             }
472
473         });
474
475         viewer = new CheckboxTreeViewer(composite, SWT.BORDER | SWT.FULL_SELECTION );
476
477         GridDataFactory.fillDefaults().grab(true, true).span(4, 1).applyTo(viewer.getControl());
478         viewer.getControl().setToolTipText(Messages.DiagramLayersPage_SelectTT);
479         viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
480         viewer.getTree().setHeaderVisible(true);
481         editor = new TreeEditor(viewer.getTree());
482
483         final TreeColumn column1 = new TreeColumn(viewer.getTree(), SWT.LEFT);
484         column1.setText(Messages.DiagramLayersPage_Role);
485         column1.setWidth(100);
486         final TreeColumn column2 = new TreeColumn(viewer.getTree(), SWT.LEFT);
487         column2.setText(Messages.DiagramLayersPage_Show);
488         column2.setWidth(50);
489         final TreeColumn column3 = new TreeColumn(viewer.getTree(), SWT.LEFT);
490         column3.setText(Messages.DiagramLayersPage_Focus);
491         column3.setWidth(50);
492         viewer.getTree().addListener(SWT.Resize, new Listener() {
493             @Override
494             public void handleEvent(Event event) {
495                 Tree tree = viewer.getTree();
496                 Point size = tree.getSize();
497                 int w = Math.max(size.x - 100 - tree.getBorderWidth() * 2, 30);
498                 column1.setWidth(w);
499             }
500         });
501
502         viewer.getTree().addListener(SWT.PaintItem, new Listener() {
503             public void handleEvent(Event event) {
504                 if ((event.index == 1 || event.index == 2) && !elements.isEmpty()) {
505                     ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);
506
507                     TreeItem item = (TreeItem)event.item;
508                     int index = viewer.getTree().indexOf(item);
509
510                     int width = 0;
511                     if (event.index == 1)
512                         width = (column2.getWidth() - 1);
513                     if (event.index == 2)
514                         width = (column3.getWidth() - 1);
515
516                     Attribute attribute = Attribute.Visible;
517                     if (event.index == 2)
518                         attribute = Attribute.Focusable;
519                     Tristate state = getJointAttribute(elements, lz[index], attribute);
520
521                     Color color = null;
522                     switch (state) {
523                         case False:
524                             color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_RED);
525                             break;
526                         case True:
527                             color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GREEN);
528                             break;
529                         case Both:
530                             color = viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_GRAY);
531                             break;
532                     }
533
534                     GC gc = event.gc;
535                     Color foreground = gc.getForeground();
536                     Color background = gc.getBackground();
537                     gc.setBackground(color);
538                     gc.setForeground(viewer.getTree().getDisplay().getSystemColor(SWT.COLOR_BLACK));
539                     gc.fillRectangle(event.x, event.y, width-1, event.height-1);
540                     Rectangle rect2 = new Rectangle(event.x, event.y, width-1, event.height-1);
541                     gc.drawRectangle(rect2);
542                     gc.setForeground(background);
543                     gc.setBackground(foreground);
544                 }
545             }
546         });
547         viewer.getTree().addKeyListener(new KeyAdapter() {
548             @Override
549             public void keyPressed(KeyEvent event) {
550                 if (event.keyCode == SWT.F2) {
551                     // FIXME: Eclipse currently eats F2 presses. This should be
552                     // implemented as a command handler or find some way to
553                     // force these listeners to have priority...
554                     System.out.println("startediting"); //$NON-NLS-1$
555
556                     TreeItem[] items = viewer.getTree().getSelection();
557                     if(items.length != 1)
558                         return;
559
560                     TreeItem item = items[0];
561
562                     ILayer layer = ISelectionUtils.filterSingleSelection(viewer.getSelection(), ILayer.class);
563                     if (layer == null)
564                         return;
565
566                     startEditing(layer, item);
567                 }
568             }
569         });
570         viewer.getTree().addListener(SWT.MouseDown, new Listener() {
571             public void handleEvent(Event event) {
572                 if (viewer.getControl().isDisposed())
573                     return;
574
575                 Point pt = new Point(event.x, event.y);
576                 TreeItem item = viewer.getTree().getItem(pt);
577                 if (item == null)
578                     return;
579
580                 int index = viewer.getTree().indexOf(item);
581                 ILayer[] lz = layers.getLayers().toArray(new ILayer[0]);
582                 ILayer layer = lz[index];
583
584                 Rectangle rect = item.getBounds(0);
585                 if (event.count == 2 && rect.contains(pt)) {
586                     startEditing(layer, item);
587                     return;
588                 }
589
590                 // Cannot adjust visibility/focusability if no elements are selected.
591                 if (elements.isEmpty())
592                     return;
593
594                 rect = item.getBounds(1);
595                 if (rect.contains(pt)) {
596                     Tristate state = getJointAttribute(elements, layer, Attribute.Visible);
597                     if (setAttribute(elements, layer, Attribute.Visible, state.toggle().toBoolean()) > 0) {
598                         refresh();
599                     }
600                     return;
601                 }
602
603                 Rectangle rect2 = item.getBounds(2);
604                 if (rect2.contains(pt)) {
605                     Tristate state = getJointAttribute(elements, layer, Attribute.Focusable);
606                     if (setAttribute(elements, layer, Attribute.Focusable, state.toggle().toBoolean()) > 0) {
607                         refresh();
608                     }
609                     return;
610                 }
611             }
612
613             private void refresh() {
614                 viewer.getControl().redraw();
615                 context.getThreadAccess().asyncExec(new Runnable() {
616                     @Override
617                     public void run() {
618                         if (context.isDisposed())
619                             return;
620                         context.getContentContext().setDirty();
621                     }
622                 });
623             }
624         });
625
626         viewer.addCheckStateListener(new ICheckStateListener(){
627             @Override
628             public void checkStateChanged(CheckStateChangedEvent event) {
629                 ILayer layer = (ILayer)event.getElement();
630                 if(event.getChecked()) layers.activate(layer);
631                 else layers.deactivate(layer);
632                 viewer.setSubtreeChecked(event.getElement(), event.getChecked());
633                 context.getThreadAccess().asyncExec(new Runnable() {
634
635                     @Override
636                     public void run() {
637                         if(context.isDisposed()) return;
638                         context.getContentContext().setDirty();
639                     }
640
641                 });
642             }
643         });
644
645         viewer.addSelectionChangedListener(new ISelectionChangedListener() {
646             @Override
647             public void selectionChanged(SelectionChangedEvent event) {
648                 ISelection s = event.getSelection();
649                 if (s.isEmpty()) {
650                     removeButton.setEnabled(false);
651                 } else {
652                     removeButton.setEnabled(true);
653                 }
654             }
655         });
656
657         viewer.setContentProvider(new ITreeContentProvider(){
658             @Override
659             public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
660             }
661             @Override
662             public void dispose() {
663             }
664             @Override
665             public Object[] getElements(Object inputElement) {
666                 return layers.getLayers().toArray();
667             }
668             @Override
669             public boolean hasChildren(Object element) {
670                 return false;
671             }
672             @Override
673             public Object getParent(Object element) {
674                 return null;
675             }
676             @Override
677             public Object[] getChildren(Object parentElement) {
678                 return new Object[0];
679             }
680         });
681         viewer.setLabelProvider(new CellLabelProvider() {
682             @Override
683             public void update(ViewerCell cell) {
684                 if(cell.getColumnIndex() == 0) {
685                     ILayer layer  = (ILayer)cell.getElement();
686                     cell.setText(layer.getName());
687                 } else {
688                     cell.setText(""); //$NON-NLS-1$
689                 }
690             }
691         });
692         viewer.setCheckStateProvider(new ICheckStateProvider() {
693             @Override
694             public boolean isChecked(Object element) {
695                 ILayer layer  = (ILayer)element;
696                 final boolean isActive = layers.isActive(layer);
697                 return isActive;
698             }
699             @Override
700             public boolean isGrayed(Object element) {
701                 return false;
702             }
703         });
704
705         viewer.setInput(this);
706
707         for(ILayer layer : layers.getVisibleLayers()) {
708             viewer.setSubtreeChecked(layer, true);
709         }
710     }
711
712     @Override
713     public Control getControl() {
714         return composite;
715     }
716
717     @Override
718     public void setFocus() {
719     }
720
721     @Override
722     public void addSelectionChangedListener(ISelectionChangedListener listener) {
723     }
724
725     @Override
726     public ISelection getSelection() {
727         return null;
728     }
729
730     @Override
731     public void removeSelectionChangedListener(ISelectionChangedListener listener) {
732     }
733
734     @Override
735     public void setSelection(ISelection selection) {
736     }
737
738     private boolean startEditing(final ILayer layer, final TreeItem item/*, final int columnIndex*/) {
739
740         //        Column column = columns[columnIndex];
741
742         String initialText = layer.getName();
743
744         final Composite composite = new Composite(viewer.getTree(), SWT.NONE);
745         final Text text = new Text(composite, SWT.BORDER);
746         final int insetX = 0;
747         final int insetY = 0;
748         composite.addListener(SWT.Resize, new Listener() {
749             public void handleEvent(Event e) {
750                 Rectangle rect = composite.getClientArea();
751                 text.setBounds(rect.x + insetX, rect.y + insetY, rect.width - insetX * 2, rect.height
752                         - insetY * 2);
753             }
754         });
755         Listener textListener = new Listener() {
756             public void handleEvent(final Event e) {
757                 //String error;
758                 String newText;
759                 switch (e.type) {
760                     case SWT.FocusOut:
761                         if(layer instanceof IEditableLayer) {
762                             IEditableLayer l = (IEditableLayer)layer;
763                             l.setName(text.getText());
764                             System.out.println("renamed layer to " + text.getText()); //$NON-NLS-1$
765                             viewer.refresh();
766                         }
767
768                         //                                      // Item may be disposed if the tree gets reset after a previous editing.
769                         //                                      if (!item.isDisposed()) {
770                         //                                              item.setText(columnIndex, text.getText());
771                         //                                              queueSelectionRefresh(context);
772                         //                                      }
773                         //                              } else {
774                         //                                      //                                System.out.println("validation error: " + error);
775                         //                              }
776                         composite.dispose();
777                         break;
778                     case SWT.Modify:
779                         //                              newText = text.getText();
780                         //                              error = modifier.isValid(newText);
781                         //                              if (error != null) {
782                         //                                      text.setBackground(invalidModificationColor);
783                         //                                      //                                System.out.println("validation error: " + error);
784                         //                              } else {
785                         //                                      text.setBackground(null);
786                         //                              }
787                         break;
788                     case SWT.Verify:
789                         newText = text.getText();
790                         String leftText = newText.substring(0, e.start);
791                         String rightText = newText.substring(e.end, newText.length());
792                         GC gc = new GC(text);
793                         Point size = gc.textExtent(leftText + e.text + rightText);
794                         gc.dispose();
795                         size = text.computeSize(size.x, SWT.DEFAULT);
796                         editor.horizontalAlignment = SWT.LEFT;
797                         Rectangle itemRect = item.getBounds(0),
798                         rect = viewer.getTree().getClientArea();
799                         editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;
800                         int left = itemRect.x,
801                         right = rect.x + rect.width;
802                         editor.minimumWidth = Math.min(editor.minimumWidth, right - left);
803                         editor.minimumHeight = size.y + insetY * 2;
804                         editor.layout();
805                         break;
806                     case SWT.Traverse:
807                         switch (e.detail) {
808                             case SWT.TRAVERSE_RETURN:
809                                 if(layer instanceof IEditableLayer) {
810                                     IEditableLayer l = (IEditableLayer)layer;
811                                     l.setName(text.getText());
812                                     //System.out.println("renamed layer to " + text.getText());
813                                     viewer.refresh();
814                                 }
815                                 //                                      error = modifier.isValid(text.getText());
816                                 //                                      if (error == null) {
817                                 //                                              modifier.modify(text.getText());
818                                 //                                              if (!item.isDisposed()) {
819                                 //                                                      item.setText(columnIndex, text.getText());
820                                 //                                                      queueSelectionRefresh(context);
821                                 //                                              }
822                                 //                                      }
823                                 // FALL THROUGH
824                             case SWT.TRAVERSE_ESCAPE:
825                                 composite.dispose();
826                                 e.doit = false;
827                                 break;
828                             default:
829                                 //System.out.println("unhandled traversal: " + e.detail);
830                                 break;
831                         }
832                         break;
833                 }
834             }
835         };
836         text.addListener(SWT.FocusOut, textListener);
837         text.addListener(SWT.Traverse, textListener);
838         text.addListener(SWT.Verify, textListener);
839         text.addListener(SWT.Modify, textListener);
840         editor.setEditor(composite, item, 0);
841         text.setText(initialText);
842         text.selectAll();
843         text.setFocus();
844         //        lastItem[0] = item;
845         return true;
846     }
847
848 }