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