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