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