View Javadoc

1   /*
2    * Created on Jul 24, 2005.
3    * Copyright 1999-2006 Faculty of Mathematics, Physics and Informatics, Comenius University, Bratislava.
4    * This file is protected by the Mozilla Public License
5    * version 1.1 (the "License"); you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    * 
8    *      http://euromath2.sourceforge.net/license.html
9    * 
10   * Unless required by applicable law or agreed to in writing, software 
11   * distributed under the License is distributed on an "AS IS" BASIS, 
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package sk.uniba.euromath.editor;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.EnumMap;
21  import java.util.EnumSet;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Queue;
28  import java.util.Set;
29  
30  import org.apache.commons.io.FilenameUtils;
31  import org.eclipse.core.runtime.IAdaptable;
32  import org.eclipse.core.runtime.IProgressMonitor;
33  import org.eclipse.core.runtime.IStatus;
34  import org.eclipse.draw2d.ColorConstants;
35  import org.eclipse.draw2d.geometry.Dimension;
36  import org.eclipse.draw2d.geometry.Point;
37  import org.eclipse.jface.dialogs.MessageDialog;
38  import org.eclipse.jface.viewers.ISelection;
39  import org.eclipse.jface.viewers.ISelectionChangedListener;
40  import org.eclipse.jface.viewers.ISelectionProvider;
41  import org.eclipse.jface.window.Window;
42  import org.eclipse.swt.SWT;
43  import org.eclipse.swt.graphics.Rectangle;
44  import org.eclipse.swt.layout.FillLayout;
45  import org.eclipse.swt.widgets.Composite;
46  import org.eclipse.ui.IEditorInput;
47  import org.eclipse.ui.IEditorSite;
48  import org.eclipse.ui.PartInitException;
49  import org.eclipse.ui.part.EditorPart;
50  import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
51  
52  import sk.baka.ikslibs.ResultEnum;
53  import sk.baka.ikslibs.interval.DOMIntervalSet;
54  import sk.baka.xml.gene.CoordinatorInputKey;
55  import sk.baka.xml.gene.ExportException;
56  import sk.baka.xml.gene.exportgraph.TransformGraph;
57  import sk.uniba.euromath.EuroMath;
58  import sk.uniba.euromath.document.DocumentView;
59  import sk.uniba.euromath.document.XMLAccess;
60  import sk.uniba.euromath.editor.actions.MultiViewActionContributor;
61  import sk.uniba.euromath.editor.dialogs.Dialogs;
62  import sk.uniba.euromath.editor.dialogs.IWidgetFactory;
63  import sk.uniba.euromath.editor.dialogs.WidgetWrapperDialog;
64  import sk.uniba.euromath.editor.lang.Messages;
65  import sk.uniba.euromath.editor.selections.DOMSelectionChangedEvent;
66  import sk.uniba.euromath.editor.selections.IDOMSelectionChangedListener;
67  import sk.uniba.euromath.editor.selections.IDOMSelectionProvider;
68  import sk.uniba.euromath.editor.widgets.FileBrowserEnum;
69  import sk.uniba.euromath.editor.widgets.FileRequirementsEnum;
70  import sk.uniba.euromath.editor.widgets.FileSelector;
71  import sk.uniba.euromath.editor.widgets.GraphSelectorWidget;
72  import sk.uniba.euromath.editor.widgets.IUserInputWidget;
73  import sk.uniba.euromath.editor.widgets.MessageLevelEnum;
74  import sk.uniba.euromath.editor.widgets.MultiWidget;
75  import sk.uniba.euromath.editor.xmlEditor.XMLEditor;
76  import sk.uniba.euromath.editor.xmlEditor.policies.FigureSelectionPolicy;
77  import sk.uniba.euromath.gene.IEditorDataReceiver;
78  import sk.uniba.euromath.gene.GeneDataProvider.RendererSite;
79  import sk.uniba.euromath.gene.gui.widgets.EncodingWidget;
80  import sk.uniba.euromath.gene.gui.widgets.XMLSerializerPropertiesWidget;
81  import sk.uniba.euromath.plugin.views.outline.XMLOutlinePage;
82  import sk.uniba.euromath.tools.StringTools;
83  
84  /***
85   * TODO STUDVA recoment
86   * <h6>Is a View, is a true compound editor, composites of IEditors.</h6>
87   * <p>
88   * This class houses instances of IEditors: chooses from available, creates
89   * and/or destroys instances of IEditors when required and creates and positions
90   * Composites for them.
91   * </p>
92   * <p>
93   * Is is also ISelectionProvider and owns XMLSelection. Other
94   * IXMLSelectionProviders refernces this XMLSelection, modifies it and send
95   * changes back to EditorSite through methods setSelection(...) or
96   * selectionChanged(...)<br>
97   * </p>
98   * <p>
99   * Is also responsible for loading, transforming, saving. Main functionality is
100  * driven by GENE.
101  * </p>
102  * <p>
103  * Acts as view in MultiViewXMLEditor.
104  * </p>
105  * 
106  * @author Tomáš Studva, Martin Vysny, Martin Kollar
107  * @see sk.uniba.euromath.editor.IEditor
108  */
109 public final class EditorSite extends EditorPart implements
110         IDOMSelectionProvider, IDOMSelectionChangedListener,
111         ISelectionProvider, IEditorDataReceiver, IFocusListener {
112 
113     /***
114      * Auxiliary class for structure purpose only. Ties together IEditor info
115      * and stores IEditor hierarchy.
116      * 
117      * @author Tomáš Studva 23.1.2006
118      */
119     private class EditorContext {
120         /***
121          * Editor.
122          */
123         public IEditor editor;
124 
125         /***
126          * Used renderer site by editor.
127          */
128         public RendererSite rendererSite;
129 
130         /***
131          * Associated input.
132          */
133         public CoordinatorInputKey key;
134 
135         /***
136          * GENE id - renderer id.
137          */
138         public String id;
139 
140         /***
141          * Parent editor context reference.
142          */
143         public EditorContext parentEditorContext;
144 
145         /***
146          * Contructor.
147          * 
148          * @param editor -
149          *            IEditor
150          * @param rendererSite -
151          *            used renderer site by editor
152          * @param key
153          *            Associated input
154          * @param id -
155          *            GENE id - renderer id
156          * @param parentEditorContext -
157          *            parent editor context reference
158          */
159         public EditorContext(IEditor editor, RendererSite rendererSite,
160                 CoordinatorInputKey key, String id,
161                 EditorContext parentEditorContext) {
162             super();
163             this.editor = editor;
164             this.rendererSite = rendererSite;
165             this.key = key;
166             this.parentEditorContext = parentEditorContext;
167             this.id = id;
168         }
169     }
170 
171     /***
172      * Contributor instance.
173      */
174     private MultiViewActionContributor actionContributor;
175 
176     /***
177      * Topmost composite.
178      */
179     private Composite rootComposite;
180 
181     /***
182      * Active editor.
183      */
184     private IEditor activeEditor;
185 
186     /***
187      * Root editor, works with rootComposite.
188      */
189     private IEditor rootEditor;
190 
191     /***
192      * Editor containing this as view.
193      */
194     private final MultiViewXMLEditor parentMultiEditor;
195 
196     private DOMIntervalSet xmlSelection;
197 
198     /***
199      * Selection listeners of this editor site. Editor site selectionis
200      * synchronized with selection provider from this list.
201      */
202     private final List<IDOMSelectionChangedListener> selectionListeners = new ArrayList<IDOMSelectionChangedListener>();
203 
204     /***
205      * IFocusListeners listening to focus changes between IEditors.
206      */
207     private final List<IFocusListener> focusListeners = new ArrayList<IFocusListener>();
208 
209     /***
210      * Outline page for this EditorSite - view.
211      */
212     private XMLOutlinePage outlinePage;
213 
214     /***
215      * Holds only those ids of nodes from xml data document, that are
216      * visualized(displayed) by at least one IEditor.
217      */
218     private final Set<String> visualizedIds;
219 
220     /***
221      * Holds source of last selectionChangeEvent.
222      */
223     // private Object selectionChangeEventSource;
224     /***
225      * For every key map holds associated(created, used) IEditor.
226      */
227     private final Map<CoordinatorInputKey, IEditor> keyEditorMap = new HashMap<CoordinatorInputKey, IEditor>();
228 
229     /***
230      * For every key map holds renderer related context(site).
231      */
232     private Map<CoordinatorInputKey, RendererSite> keyRendererSiteMap;
233 
234     /***
235      * For every key map holds editor related context. Context also contains
236      * key, so whole tree hierarchy is navigable.
237      */
238     private Map<CoordinatorInputKey, EditorContext> editorContexts = new HashMap<CoordinatorInputKey, EditorContext>();
239 
240     /***
241      * Constructor.
242      * 
243      * @param parentMultiEditor
244      *            host for this EditorSite.
245      */
246     public EditorSite(MultiViewXMLEditor parentMultiEditor) {
247         this.parentMultiEditor = parentMultiEditor;
248         // this.selectionProviders = new ArrayList<IXMLSelectionProvider>();
249         // this.globalSelection = new HashMap<IEditor, IXMLSelection>();
250         this.xmlSelection = new DOMIntervalSet();
251         this.visualizedIds = new HashSet<String>();
252     }
253 
254     /***
255      * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
256      */
257     @Override
258     public void doSave(IProgressMonitor monitor) {
259         try {
260             getParentMultiEditor().getResourceManipulator().save(null);
261         } catch (Exception ex) {
262             EuroMath.log(IStatus.ERROR, 0, "Error storing document", ex); //$NON-NLS-1$
263             MessageDialog
264                     .openError(getEditorSite().getShell(),
265                             Messages.getString("ERROR"), //$NON-NLS-1$
266                             Messages.getString("ERROR_STORING_DOCUMENT") + ex.getLocalizedMessage()); //$NON-NLS-1$
267         }
268     }
269 
270     /***
271      * @see org.eclipse.ui.ISaveablePart#doSaveAs()
272      */
273     @Override
274     public void doSaveAs() {
275         final IWidgetFactory<MultiWidget> wfactory = new IWidgetFactory<MultiWidget>() {
276             /*
277              * (non-Javadoc)
278              * 
279              * @see sk.uniba.euromath.editor.dialogs.IWidgetFactory#create(org.eclipse.swt.widgets.Composite)
280              */
281             public MultiWidget create(Composite parent) {
282                 final List<IUserInputWidget> widgets = new ArrayList<IUserInputWidget>(
283                         3);
284                 // create the file selector.
285                 final String docName = parentMultiEditor.getXMLAccess().getFileName();
286                 int extSeparator = docName.lastIndexOf('.');
287                 if (extSeparator < 0)
288                     extSeparator = docName.length();
289                 final String documentExtension = FilenameUtils.getExtension(docName);
290                 final Map<FileRequirementsEnum, MessageLevelEnum> flags = new EnumMap<FileRequirementsEnum, MessageLevelEnum>(
291                         FileRequirementsEnum.class);
292                 flags.put(FileRequirementsEnum.MUST_BE_CREATABLE_FILE,
293                         MessageLevelEnum.ERROR);
294                 flags.put(FileRequirementsEnum.MUST_BE_FILE,
295                         MessageLevelEnum.ERROR);
296                 flags.put(FileRequirementsEnum.OBJECT_MUST_NOT_EXIST,
297                         MessageLevelEnum.WARNING);
298                 flags.put(FileRequirementsEnum.PATH_MUST_EXIST,
299                         MessageLevelEnum.ERROR);
300                 final FileSelector fs = new FileSelector(parent, documentExtension, MessageLevelEnum.WARNING,
301                         flags, FileBrowserEnum.SAVE_FILE);
302                 fs.setFileName(getXMLAccess().getDocumentURL().toString());
303                 widgets.add(fs);
304                 // create the encoding selector
305                 final EncodingWidget eq = new EncodingWidget(parent);
306                 if (getXMLAccess().getEncoding() != null)
307                     eq.select(getXMLAccess().getEncoding());
308                 widgets.add(eq);
309                 // create the output formatting query
310                 final XMLSerializerPropertiesWidget deq = new XMLSerializerPropertiesWidget(
311                         parent);
312                 widgets.add(deq);
313                 return new MultiWidget(parent, widgets);
314             }
315         };
316         final WidgetWrapperDialog<MultiWidget> dlg = new WidgetWrapperDialog<MultiWidget>(
317                 getEditorSite().getShell(), Messages.getString("SAVE_AS"), //$NON-NLS-1$
318                 Messages.getString("SAVE_FILE_AS", //$NON-NLS-1$
319                         getXMLAccess().getFileName()), wfactory);
320         if (dlg.open() != Window.OK)
321             return;
322         // retrieve data from the dialog.
323         final String fname = ((FileSelector) dlg.getWidget().getWidgets()
324                 .get(0)).getFileName();
325         final String encoding = ((EncodingWidget) dlg.getWidget().getWidgets()
326                 .get(1)).getSelected();
327         final XMLSerializerPropertiesWidget deq = (XMLSerializerPropertiesWidget) dlg
328                 .getWidget().getWidgets().get(2);
329         // save the file
330         try {
331             getParentMultiEditor().getResourceManipulator().save(fname,
332                     encoding, deq);
333         } catch (Exception ex) {
334             EuroMath.log(IStatus.ERROR, 0, "Error storing document", ex); //$NON-NLS-1$
335             MessageDialog
336                     .openError(getEditorSite().getShell(),
337                             Messages.getString("ERROR"), //$NON-NLS-1$
338                             Messages.getString("ERROR_STORING_DOCUMENT") + ex.getLocalizedMessage()); //$NON-NLS-1$
339         }
340     }
341 
342     /***
343      * 
344      * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
345      *      org.eclipse.ui.IEditorInput)
346      */
347     @Override
348     public void init(IEditorSite site, IEditorInput input)
349             throws PartInitException {
350         setSite(site);
351         setInput(input);
352     }
353 
354     /***
355      * 
356      * @see org.eclipse.ui.ISaveablePart#isDirty()
357      */
358     @Override
359     public boolean isDirty() {
360         return !getXMLAccess().getUndoManager().isSavePoint();
361     }
362 
363     /***
364      * 
365      * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
366      */
367     @Override
368     public boolean isSaveAsAllowed() {
369         return true;
370     }
371 
372     /***
373      * Creates and initalizes IEditor for coordinator with "parent
374      * parentEditor". Actually IEditors don't have parents. Also creates
375      * Composite.
376      * 
377      * @param coordinator
378      *            CoordinatorInputKey for which to create editor
379      * @param id
380      *            of root node for newly created editr, it is also same id as
381      *            have associated renderer
382      * @param parentEditor
383      *            editor with Composite which host Composite for this new editor
384      * @return new IEditor instance
385      * 
386      * @throws EditorException
387      *             is thrown in all bad cases: no suitable editor found, editor
388      *             creation failure, editor init failure
389      */
390     private IEditor buildEditor(CoordinatorInputKey coordinator, String id,
391             IEditor parentEditor) throws EditorException {
392 
393         String nameSpace = coordinator.targetNamespace;
394         EnumSet<ResultEnum> resultTypes = EnumSet
395                 .of(coordinator.info.resultType);
396 
397         // get suitable editors
398         List<EditorInfo> editorInfo = EditInstanceProvider.getInstance()
399                 .getEditorsForNamespace(nameSpace, resultTypes);
400         try {
401             IRenderer parentRenderer = parentEditor.getRenderer();
402             RendererSite rendererSite = this.keyRendererSiteMap
403                     .get(coordinator);
404             // create composite on parents composite
405             parentEditor.getClientComposite().setLayout(
406                     new PreferredByControlLayout());
407             Composite c = new Composite(parentEditor.getClientComposite(),
408                     SWT.NO_RADIO_GROUP);
409             c.setBackground(ColorConstants.green);
410             c.setLayout(new FillLayout());
411             Point p = parentRenderer.getPlacement(id);
412             Dimension dim = rendererSite.renderer.getCanvasSize();
413             c.setLayoutData(new Rectangle(p.x, p.y, dim.width + 2
414                     * FigureSelectionPolicy.SELECION_BORDER_WIDTH, dim.height
415                     + 2 * FigureSelectionPolicy.SELECION_BORDER_WIDTH));
416             // create IEditor
417             IEditor editor = createBestEditor(editorInfo);
418             // init IEditor
419             editor.init(rendererSite.getSource().getSource(),
420                     rendererSite.renderer, c, getXMLAccess(), this);
421             return editor;
422         } catch (ExportException e) {
423             throw new EditorException("Some IEditor fails to create.", e); //$NON-NLS-1$
424         } catch (EditorException e) {
425             throw new EditorException("Some IEditor fails to initialize.", e); //$NON-NLS-1$
426         }
427     }
428 
429     /***
430      * Creates and initalizes root IEditor. Also creates Composite.
431      * 
432      * @param coordinator
433      *            Coordinator for this root editor
434      * @return root Editor
435      * 
436      * @throws EditorException
437      *             is thrown in all bad cases: no suitable editor found, editor
438      *             creation failure, editor init failure
439      */
440     private IEditor buildRootEditor(CoordinatorInputKey coordinator)
441             throws EditorException {
442         String nameSpace = coordinator.targetNamespace;
443         EnumSet<ResultEnum> resultTypes = EnumSet.of(coordinator
444                 .getResultType());
445         // get suitable editors
446         List<EditorInfo> editorInfo = EditInstanceProvider.getInstance()
447                 .getEditorsForNamespace(nameSpace, resultTypes);
448 
449         try {
450             getRootComposite().setLayout(new FillLayout());
451             // create rootEditor
452             IEditor result = createBestEditor(editorInfo);
453             RendererSite rootRendererSite = this.keyRendererSiteMap
454                     .get(coordinator);
455             // init rootEditor
456             // rootComposite.setLayout(null);
457             result.init(rootRendererSite.getSource().getSource(),
458                     rootRendererSite.renderer, getRootComposite(),
459                     getXMLAccess(), this);
460             return result;
461         } catch (ExportException e) {
462             throw new EditorException("Root IEditor fails to create.", e); //$NON-NLS-1$
463         }
464 
465     }
466 
467     /***
468      * Creates best editor. Created is IEditor implementing most of interfaces
469      * providing editing capability, such as {@link IXMLSelectionProvider},
470      * providing Selections.
471      * 
472      * @param editorInfo
473      * @return new instance
474      * @throws EditorException
475      * @throws ExportException
476      */
477     private IEditor createBestEditor(List<EditorInfo> editorInfo)
478             throws ExportException {
479         // TODO Studva make it work as in coment or better
480         if ((editorInfo == null) || editorInfo.isEmpty()) {
481             return new XMLEditor();
482         }
483         return editorInfo.get(0).newEditor();
484     }
485 
486     /* (non-Javadoc)
487      * @see sk.uniba.euromath.gene.IEditorDataReceiver#initReceiver()
488      */
489     public void initReceiver() {
490     	// nothing needs to be initialized.
491     }
492 
493     /***
494      * @see IEditorDataReceiver#dataChanged(java.util.Map,
495      *      CoordinatorInputKey, java.util.Map,
496      *      java.util.Map, java.util.Set, java.util.Set)
497      */
498     public void dataChanged(
499             Map<CoordinatorInputKey, RendererSite> rendererKeys,
500             CoordinatorInputKey rootKey,
501             Map<CoordinatorInputKey, Set<CoordinatorInputKey>> nametreeHierarchy,
502             Map<String, CoordinatorInputKey> geneIdMapping,
503             Set<CoordinatorInputKey> newKeys,
504             Set<CoordinatorInputKey> deletedKeys) throws EditorException {
505 
506         this.editorContexts.clear();
507 
508         // compute inverse map of geneIdMapping map.
509         final HashMap<CoordinatorInputKey, String> keyIdMapping = new HashMap<CoordinatorInputKey, String>(
510                 geneIdMapping.size());
511         for (final String id : geneIdMapping.keySet()) {
512             keyIdMapping.put(geneIdMapping.get(id), id);
513         }
514 
515         this.keyRendererSiteMap = rendererKeys;
516         // delete old bad editors, for which now doesn't exists Key
517         for (CoordinatorInputKey deletedKey : deletedKeys) {
518             if (this.keyEditorMap.containsKey(deletedKey)) {
519                 // destroy editor - remove from map, dispose, remove form
520                 // selectionProviders
521                 IEditor editor = this.keyEditorMap.get(deletedKey);
522                 // getSelectionProviders().remove(editor);
523                 if (editor instanceof IDOMSelectionProvider)
524                     removeSelectionChangedListener(editor);
525                 // getGlobalSelection().remove(editor);
526 
527                 // remove this as focus listener
528                 editor.addFocusListener(this);
529                 // remove this as selection listener, if root editor provide
530                 // selections
531                 if (editor instanceof IDOMSelectionProvider) {
532                     ((IDOMSelectionProvider) editor)
533                             .removeSelectionChangedListener(this);
534                 }
535                 editor.dispose();
536                 this.keyEditorMap.remove(deletedKey);
537             }
538         }
539 
540         // if needed build root editor
541         if (newKeys.contains(rootKey)) {
542             setRootEditor(buildRootEditor(rootKey));
543             this.keyEditorMap.put(rootKey, getRootEditor());
544             // fill context
545             this.editorContexts.put(rootKey, new EditorContext(getRootEditor(),
546                     this.keyRendererSiteMap.get(rootKey), rootKey, keyIdMapping
547                             .get(rootKey), null));
548             // add this as focus listener to handle focus events
549             getRootEditor().addFocusListener(this);
550             // add this as selection listener, if root editor provide
551             // selections
552             if (getRootEditor() instanceof IDOMSelectionProvider) {
553                 ((IDOMSelectionProvider) getRootEditor())
554                         .addSelectionChangedListener(this);
555                 addSelectionChangedListener(getRootEditor());
556 
557                 // getSelectionProviders().add(
558                 // (IXMLSelectionProvider) getRootEditor());
559 
560                 // getGlobalSelection().put(
561                 // getRootEditor(),
562                 // ((IXMLSelectionProvider) getRootEditor())
563                 // .getSelection());
564             }
565         } else {
566             // reinit of root editor
567             getRootEditor().reinit(
568                     rendererKeys.get(rootKey).getSource().getSource(),
569                     rendererKeys.get(rootKey).getSource());
570             // update context
571             this.editorContexts.put(rootKey, new EditorContext(getRootEditor(),
572                     this.keyRendererSiteMap.get(rootKey), rootKey, keyIdMapping
573                             .get(rootKey), null));
574 
575         }
576 
577         // build editors from root to lists
578         IEditor parentEditor;
579         IEditor newEditor;
580         CoordinatorInputKey parentKey;
581 
582         // contains keys for build editors, which don't have build children
583         Queue<CoordinatorInputKey> parentKeys = new LinkedList<CoordinatorInputKey>();
584         parentKeys.add(rootKey);
585 
586         while (!parentKeys.isEmpty()) {
587             // choose one from list
588             parentKey = parentKeys.poll();
589             parentEditor = this.keyEditorMap.get(parentKey);
590             // build its children
591             for (CoordinatorInputKey sonKey : nametreeHierarchy.get(parentKey)) {
592                 if (newKeys.contains(sonKey)) {
593                     final String sonKeyId = keyIdMapping.get(sonKey);
594                     assert sonKeyId != null;
595                     newEditor = buildEditor(sonKey, sonKeyId, parentEditor);
596                     this.keyEditorMap.put(sonKey, newEditor);
597                     // fill context
598                     this.editorContexts.put(sonKey, new EditorContext(
599                             newEditor, this.keyRendererSiteMap.get(sonKey),
600                             sonKey, keyIdMapping.get(sonKey),
601                             this.editorContexts.get(parentKey)));
602                     // add freshly build editor to parent keys
603                     parentKeys.add(sonKey);
604                     // add this as focus listener to handle focus events
605                     newEditor.addFocusListener(this);
606                     // add this as selection listener, if new editor provide
607                     // selections
608                     if (newEditor instanceof IDOMSelectionProvider) {
609                         ((IDOMSelectionProvider) newEditor)
610                                 .addSelectionChangedListener(this);
611                         addSelectionChangedListener(newEditor);
612 
613                         // getSelectionProviders().add(
614                         // (IXMLSelectionProvider) newEditor);
615 
616                         // getGlobalSelection().put(
617                         // newEditor,
618                         // ((IXMLSelectionProvider) newEditor)
619                         // .getSelection());
620                     }
621                 } else {
622                     // reinit
623                     this.keyEditorMap.get(sonKey).reinit(
624                             rendererKeys.get(sonKey).getSource().getSource(),
625                             rendererKeys.get(sonKey).getSource());
626                     // fill context
627                     this.editorContexts.put(sonKey, new EditorContext(
628                             this.keyEditorMap.get(sonKey),
629                             this.keyRendererSiteMap.get(sonKey), sonKey,
630                             keyIdMapping.get(sonKey), this.editorContexts
631                                     .get(parentKey)));
632                 }
633             }
634 
635         }
636         layout();
637         computeVisualizedIds();
638         fireSelectionChangeEvent();
639     }
640 
641     @Override
642     public void createPartControl(Composite parent) {
643         createOutlinePage();
644         hookOutlinePage(getOutlinePage());
645         this.rootComposite = parent;
646 
647         // init the document presentation
648         try {
649             final DocumentView view = new DocumentView(getParentMultiEditor()
650                     .getXMLAccess(), null, this);
651             final WidgetWrapperDialog<GraphSelectorWidget> dlg = Dialogs
652                     .createGraphSelector(this.getEditorSite().getShell(),
653                             GraphSelectorWidget.getEditableChoices(view
654                                     .getEditGraph()), view.getEditGraph());
655             if (dlg.open() != Window.OK) {
656                 // user pressed cancel, abort the document opening process.
657                 return;
658             }
659             final TransformGraph graph = dlg.getWidget().getTransformationInfo(
660                     view.getCoordinatorInfo());
661             view.initialize(graph);
662             // tu uz by mal tvoj EditorSite automaticky dostavat tucne data
663             // od GENE, instancovat editory atd atd.
664 
665             getParentMultiEditor().getXMLAccess().openView(view);
666         } catch (Exception ex) {
667             EuroMath.log(IStatus.ERROR, 0, "Error opening document view", ex); //$NON-NLS-1$
668             MessageDialog.openError(getEditorSite().getShell(), Messages
669                     .getString("ERROR"), //$NON-NLS-1$
670                     Messages.getString("ERROR_INITIALIZING_EDITOR") //$NON-NLS-1$
671                             + ex.getLocalizedMessage());
672         }
673     }
674 
675     /***
676      * Responsible for registring EditorSite as lisener in XMLOutlinePage.
677      * 
678      * @param page
679      *            XMLOutlinePage
680      */
681     private void hookOutlinePage(XMLOutlinePage page) {
682         // add EditorSite as XMLOutlinePage listener
683         page.addSelectionChangedListener(this);
684         // getSelectionProviders().add(page);
685     }
686 
687     /***
688      * Creates outline page.
689      */
690     private void createOutlinePage() {
691         this.outlinePage = new XMLOutlinePage(this);
692     }
693 
694     /***
695      * Returns outline page instance.
696      * 
697      * @return outline page instance
698      */
699     public XMLOutlinePage getOutlinePage() {
700         return this.outlinePage;
701     }
702 
703     /***
704      * Sets focus to activete this EditorSite. As active editor is choosed last
705      * active or root editor.
706      */
707     @Override
708     public void setFocus() {
709         if (getActiveEditor() != null)
710             getActiveEditor().setFocus();
711         if (getRootEditor() != null)
712             setActiveEditor(getRootEditor());
713     }
714 
715     /***
716      * Sets editor as IEditor with focus.
717      * 
718      * @param editor
719      *            to set as active = with focus
720      */
721     private void setActiveEditor(IEditor editor) {
722         this.activeEditor = editor;
723         editor.setFocus();
724     }
725 
726     /***
727      * Returns active editor.
728      * 
729      * @return IEditor with focus
730      */
731     public IEditor getActiveEditor() {
732         return this.activeEditor;
733     }
734 
735     /***
736      * Returns root editor.
737      * 
738      * @return root IEditor
739      */
740     public IEditor getRootEditor() {
741         return this.rootEditor;
742     }
743 
744     /***
745      * Returns multi editor containing this EditorSite instance as child view.
746      * 
747      * @return parent multi editor
748      */
749     public MultiViewXMLEditor getParentMultiEditor() {
750         return this.parentMultiEditor;
751     }
752 
753     /***
754      * Returns document instance.
755      * 
756      * @return xmlaccess instance
757      */
758     public XMLAccess getXMLAccess() {
759         return getParentMultiEditor().getXMLAccess();
760     }
761 
762     public void addSelectionChangedListener(IDOMSelectionChangedListener listener) {
763         if (!this.selectionListeners.contains(listener)) {
764             this.selectionListeners.add(listener);
765         }
766     }
767     /***
768      * @param listener
769      */
770     public void removeSelectionChangedListener(
771             IDOMSelectionChangedListener listener) {
772         this.selectionListeners.remove(listener);
773 
774     }
775 
776     /***
777      * @return return current XMLSelection
778      */
779     public DOMIntervalSet getDOMSelection() {
780         return xmlSelection;
781     }
782 
783     /***
784      * Routes this new IXMLSelection to all listeners
785      * 
786      * @param selection
787      *            DOM selection to set
788      */
789     public void setSelection(DOMIntervalSet selection) {
790         setSelection(selection, true);
791     }
792 
793     /***
794      * Fires SelectionEvent to all listeners, if toAll is <code>true</code>.
795      * Otherwise fires SelectionEvent only to active editor, if it provides
796      * selections (is IXMLSelectionProvider)
797      * 
798      * @param selection
799      *            IXMLSelection
800      * @param toAll
801      *            <code>true</code> means route in all IEditors, that provides
802      *            selections <code>false</code> route only in active editor,
803      *            if it provides selections
804      */
805     public void setSelection(DOMIntervalSet selection, Boolean toAll) {
806         this.xmlSelection = selection;
807 
808         if (toAll)
809             fireSelectionChangeEvent();
810         else {
811             if ((getActiveEditor() != null)
812                     && (getActiveEditor() instanceof IDOMSelectionProvider)) {
813 
814                 // stop listening to ActiveEditor
815                 ((IDOMSelectionProvider) getActiveEditor())
816                         .removeSelectionChangedListener(this);
817 
818                 getActiveEditor().selectionChanged(
819                         new DOMSelectionChangedEvent(this, getDOMSelection()));
820 
821                 // start listening to ActiveEditor
822                 ((IDOMSelectionProvider) getActiveEditor())
823                         .addSelectionChangedListener(this);
824             }
825         }
826 
827     }
828 
829     /***
830      * FireSelectionChangeEvent containing current selection to listeners
831      */
832     private void fireSelectionChangeEvent() {
833         stopSelectionListening();
834 
835         for (IDOMSelectionChangedListener listener : this.selectionListeners)
836             listener.selectionChanged(new DOMSelectionChangedEvent(this,
837                     getDOMSelection()));
838 
839         startSelectionListening();
840     }
841 
842     /***
843      * EditorSite starts selection listening. It adds itself to EditorSites's
844      * listeners listeners. It is a "two way listening" Call in pair with
845      * stopSelectionListening().
846      */
847     private void startSelectionListening() {
848         for (IDOMSelectionChangedListener listener : this.selectionListeners)
849             if (listener instanceof IDOMSelectionProvider)
850                 ((IDOMSelectionProvider) listener)
851                         .addSelectionChangedListener(this);
852     }
853 
854     /***
855      * EditorSite does not realy stops selection listening because setSelection
856      * and selectionChange are public methods, but it EditorSite removes itself
857      * from EditorSite's listeners listeners. This prevents from loops.
858      */
859     private void stopSelectionListening() {
860         for (IDOMSelectionChangedListener listener : this.selectionListeners)
861             if (listener instanceof IDOMSelectionProvider)
862                 ((IDOMSelectionProvider) listener)
863                         .removeSelectionChangedListener(this);
864     }
865 
866     /***
867      * Source of event can be
868      * <ul>
869      * <li>IEditor</li>
870      * <li>ContentOutline</li>
871      * <li>something else for future </li>
872      * </ul>
873      * All this sources should be IXMLSelectionProviders, but more imporatant is
874      * that their IXMLSelection have to be "synchronized" with other
875      * IXMLSelectionProviders
876      * 
877      * @param event
878      *            SelectionChangedEvent <b>If event.getSelection() is not
879      *            instance of XMLSelection, does nothing.<b>
880      */
881     public void selectionChanged(DOMSelectionChangedEvent event) {
882         // FIXME clone
883         this.xmlSelection = event.getDOMSelection();
884         fireSelectionChangeEvent();
885     }
886 
887     /***
888      * @return selection providers IEditors or XMLOutline
889      */
890     /*
891      * public List<IXMLSelectionProvider> getSelectionProviders() { return
892      * this.selectionProviders; }
893      * 
894      * 
895      * public HashMap<IEditor, IXMLSelection> getGlobalSelection() { return
896      * this.globalSelection; }
897      * 
898      * public Object getSelectionChangeEventSource() { return
899      * this.selectionChangeEventSource; }
900      * 
901      * public void setSelectionChangeEventSource(Object
902      * selectionChangeEventSource) { this.selectionChangeEventSource =
903      * selectionChangeEventSource; }
904      */
905 
906     /***
907      * TODO STUDVA nejasne co to ma robit a ci to je spravne implementovane
908      * 
909      * @param actionContributor
910      */
911     public void setActionContributor(
912             MultiViewActionContributor actionContributor) {
913         if (getActionContributor() == null) {
914             this.actionContributor = actionContributor;
915             for (IEditor editor : getAllIEditors()) {
916                 editor.getActionContributor().init(
917                         this.actionContributor.getActionRegistry());
918             }
919         }
920     }
921 
922     /***
923      * Returns the adapter for the specified class.
924      */
925     @Override
926     public Object getAdapter(Class adapter) {
927         if (adapter.equals(IContentOutlinePage.class))
928             return getOutlinePage();
929 
930         if (adapter.equals(IDOMSelectionProvider.class))
931             return this;
932 
933         if (adapter.equals(IDOMSelectionProvider.class))
934             return this;
935 
936         if (adapter.equals(XMLAccess.class))
937             return getXMLAccess();
938 
939         if (adapter.equals(IEditor.class))
940             return getActiveEditor();
941 
942         if (getActiveEditor() instanceof IAdaptable)
943             return ((IAdaptable) getActiveEditor()).getAdapter(adapter);
944 
945         return null;
946     }
947 
948     /***
949      * Test if IEditor is root editor. If root editor doesn't exists, every time
950      * returns true.
951      * 
952      * @param editor
953      *            to test
954      * @return <code>true</code> if editor is a rootEditor
955      */
956     public boolean isRootEditor(IEditor editor) {
957         return (getRootEditor() == editor) || (getRootEditor() == null);
958     }
959 
960     /***
961      * Lays out editors composites.
962      */
963     private void layout() {
964         // paints all editors and updates positions of editors composites
965         for (EditorContext editorContext : this.editorContexts.values()) {
966             // paint editor
967             // get renderer, parent renderer and id
968             if (editorContext.editor != getRootEditor()) {
969                 IRenderer parentRenderer = editorContext.parentEditorContext.rendererSite.renderer;
970                 Point location = parentRenderer.getPlacement(editorContext.id);
971                 try {
972                     Dimension dim = editorContext.rendererSite.renderer
973                             .getCanvasSize();
974 
975                     editorContext.editor.getHostingComposite().setLayoutData(
976                             new Rectangle(location.x, location.y, dim.width,
977                                     dim.height));
978                 } catch (EditorException e) {
979                     EuroMath.log(IStatus.ERROR, 0,
980                             "Renderer dimension retreiving error.", e); //$NON-NLS-1$
981                 }
982             }
983         }
984         getRootComposite().layout(true, true);
985     }
986 
987     /***
988      * @return Returns the actionContributor.
989      */
990     public MultiViewActionContributor getActionContributor() {
991         return this.actionContributor;
992     }
993 
994     /***
995      * Adds listener as focus listener. Listener is added if is not yet
996      * listening.
997      * 
998      * @param listener
999      *            to add
1000      */
1001     public void addFocusListener(IFocusListener listener) {
1002         if (!getFocusListeners().contains(listener))
1003             getFocusListeners().add(listener);
1004     }
1005 
1006     /***
1007      * Removes listener. If not listener is not listening, nothing is done.
1008      * 
1009      * @param listener
1010      *            to remove
1011      */
1012     public void removeFocusListener(IFocusListener listener) {
1013         getFocusListeners().remove(listener);
1014     }
1015 
1016     /***
1017      * @return Returns the focusListeners.
1018      */
1019     private List<IFocusListener> getFocusListeners() {
1020         return this.focusListeners;
1021     }
1022 
1023     /***
1024      * @param rootEditor
1025      *            The rootEditor to set.
1026      */
1027     private void setRootEditor(IEditor rootEditor) {
1028         this.rootEditor = rootEditor;
1029     }
1030 
1031     /***
1032      * IEditor has gained focus. Send message to focus listeners.
1033      */
1034     public void focusGained(IEditor editor) {
1035         for (IFocusListener listener : getFocusListeners()) {
1036             listener.focusGained(editor);
1037         }
1038     }
1039 
1040     /***
1041      * IEditor has lost focus. Send message to focus listeners.
1042      */
1043     public void focusLost(IEditor editor) {
1044         for (IFocusListener listener : getFocusListeners()) {
1045             listener.focusLost(editor);
1046         }
1047     }
1048 
1049     /***
1050      * Returns all IEditors in this site.
1051      * 
1052      * @return collection of all IEditors in this site
1053      */
1054     public Collection<IEditor> getAllIEditors() {
1055         return this.keyEditorMap.values();
1056     }
1057 
1058     /***
1059      * Computes or recomputes visualized ids.
1060      * 
1061      * @see #getVisualizedIds()
1062      */
1063     private void computeVisualizedIds() {
1064         this.visualizedIds.clear();
1065         for (IEditor editor : getAllIEditors())
1066             this.visualizedIds.addAll(editor.getVisualizedIds());
1067     }
1068 
1069     /***
1070      * Returns ids of nodes which are graphically rendered(represented) by at
1071      * least one IEditor. Id's are without :N.
1072      * 
1073      * @return list of ids which are visualized by at least one IEditor
1074      */
1075     public Set<String> getVisualizedIds() {
1076         return this.visualizedIds;
1077     }
1078 
1079     /***
1080      * @return Returns the rootComposite.
1081      */
1082     public Composite getRootComposite() {
1083         return this.rootComposite;
1084     }
1085 
1086     public void addSelectionChangedListener(ISelectionChangedListener listener) {
1087         // TODO Auto-generated method stub
1088         
1089     }
1090 
1091     public ISelection getSelection() {
1092         // TODO Auto-generated method stub
1093         return null;
1094     }
1095 
1096     public void removeSelectionChangedListener(ISelectionChangedListener listener) {
1097         // TODO Auto-generated method stub
1098         
1099     }
1100 
1101     public void setSelection(ISelection selection) {
1102         // TODO Auto-generated method stub
1103         
1104     }
1105 }