1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.plugin.views.outline;
13
14 import java.util.ArrayList;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18
19 import org.eclipse.core.runtime.IAdaptable;
20 import org.eclipse.jface.action.IStatusLineManager;
21 import org.eclipse.jface.viewers.ISelection;
22 import org.eclipse.jface.viewers.ISelectionChangedListener;
23 import org.eclipse.jface.viewers.ISelectionProvider;
24 import org.eclipse.jface.viewers.IStructuredSelection;
25 import org.eclipse.jface.viewers.SelectionChangedEvent;
26 import org.eclipse.jface.viewers.StructuredSelection;
27 import org.eclipse.jface.viewers.TreeViewer;
28 import org.eclipse.swt.SWT;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Control;
31 import org.eclipse.ui.part.Page;
32 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
33 import org.eclipse.ui.views.properties.IPropertySource;
34 import org.w3c.dom.Node;
35
36 import sk.baka.ikslibs.interval.DOMIntervalSet;
37 import sk.baka.ikslibs.levelmapper.NodeListID;
38 import sk.uniba.euromath.document.IGeneralListener;
39 import sk.uniba.euromath.document.XMLAccess;
40 import sk.uniba.euromath.editor.EditorSite;
41 import sk.uniba.euromath.editor.selections.DOMSelectionChangedEvent;
42 import sk.uniba.euromath.editor.selections.IDOMSelectionChangedListener;
43 import sk.uniba.euromath.editor.selections.IDOMSelectionProvider;
44 import sk.uniba.euromath.plugin.views.outline.actions.XMLOutlineActionContributor;
45 import sk.uniba.euromath.plugin.views.outline.items.OutlineItem;
46
47
48
49
50 public class XMLOutlinePage extends Page implements IContentOutlinePage,
51 IDOMSelectionChangedListener, ISelectionChangedListener, IAdaptable,
52 IDOMSelectionProvider {
53 /***
54 * Jface tree viewer to display xml document in DOM tree style.
55 */
56 private TreeViewer viewer;
57
58 private XMLAccessContentProvider contentProvider;
59
60 /***
61 * Label provider for outline items.
62 */
63 private OutlineItemsLabelProvider labelProvider;
64
65 private Set<ISelectionChangedListener> selectionListeners = new HashSet<ISelectionChangedListener>();
66
67 private Set<IDOMSelectionChangedListener> domSelectionListeners = new HashSet<IDOMSelectionChangedListener>();
68
69 private XMLAccess xmlAccess = null;
70
71 private final EditorSite editorSite;
72
73 private final IGeneralListener xmlAccessChangeHandler;
74
75 private StatusLineUpdateManager statusLineManager;
76
77 private boolean showingTransformed;
78
79 /***
80 * Outline action contributor.
81 */
82 protected XMLOutlineActionContributor actionContributor;
83
84 public XMLOutlinePage(EditorSite site) {
85 super();
86 this.editorSite = site;
87 this.xmlAccessChangeHandler = new IGeneralListener() {
88 public void documentWasTransformed(XMLAccess xmlAccess) {
89 handleDocumentTransformation(xmlAccess);
90 }
91 };
92 setXmlAccess(site.getXMLAccess());
93 getXMLAccess().getListeners().addGeneralListener(
94 getXmlAccessChangeHandler());
95 setShowingTransformed(false);
96 }
97
98 @Override
99 public void createControl(Composite parent) {
100 setViewer(createTreeViewer(parent));
101 setActionContributor(new XMLOutlineActionContributor(getSite()
102 .getWorkbenchWindow().getActivePage().getActivePart(), this));
103 prepareStatusLineManager(getSite().getActionBars()
104 .getStatusLineManager());
105 refreshViewerData(getRoot());
106 getViewer().addSelectionChangedListener(this);
107
108 getEditorSite().addSelectionChangedListener(
109 (IDOMSelectionChangedListener) this);
110 selectionChanged(new DOMSelectionChangedEvent(getEditorSite(),
111 getEditorSite().getDOMSelection()));
112 }
113
114 /***
115 * Returns a XML node which will be the root of the outline tree.
116 */
117 protected Node getRoot() {
118 Node result = null;
119 if (this.xmlAccess != null) {
120 if (isShowingTransformed()) {
121 getLabelProvider().setWithInvertedImages(false);
122
123 result = getXMLAccess().getDocument().getDocumentElement();
124 } else {
125 getLabelProvider().setWithInvertedImages(true);
126 result = this.xmlAccess.getDocument().getDocumentElement();
127 }
128 }
129 return result;
130 }
131
132 protected void prepareStatusLineManager(IStatusLineManager manager) {
133 setStatusLineManager(new StatusLineUpdateManager(manager,
134 getXMLAccess()));
135 this.statusLineManager.setImageRegistry(getLabelProvider()
136 .getImageRegistry());
137 this.statusLineManager.connect(this);
138 }
139
140 protected TreeViewer createTreeViewer(Composite parent) {
141 TreeViewer result = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL
142 | SWT.V_SCROLL);
143 setContentProvider(new XMLAccessContentProvider());
144 result.setContentProvider(getContentProvider());
145 setLabelProvider(new OutlineItemsLabelProvider(getEditorSite()));
146 result.setLabelProvider(getLabelProvider());
147 return result;
148 }
149
150
151
152
153
154
155 public Object getAdapter(Class adapter) {
156 if (adapter == IPropertySource.class) {
157 if (getViewer().getSelection() != null) {
158 if (getViewer().getSelection() instanceof IStructuredSelection) {
159 IStructuredSelection sSel = (IStructuredSelection) getViewer()
160 .getSelection();
161 if (!sSel.isEmpty() && (sSel.size() == 1)) {
162 Object e0 = sSel.getFirstElement();
163 if (e0 instanceof IPropertySource) {
164 return e0;
165 } else if (e0 instanceof OutlineItem) {
166 return ((OutlineItem) e0).getPropertySource();
167 }
168 }
169 }
170 }
171 return null;
172 }
173
174 if (adapter.equals(IDOMSelectionProvider.class)) {
175 return this;
176 }
177
178 if (adapter.equals(IDOMSelectionProvider.class)) {
179 return this;
180 }
181
182 if (adapter.equals(XMLAccess.class)) {
183 return getXMLAccess();
184 }
185
186 return null;
187 }
188
189
190
191
192
193
194 @Override
195 public Control getControl() {
196 return getViewer().getControl();
197 }
198
199 public void handleDocumentTransformation(XMLAccess newData) {
200 setXmlAccess(newData);
201
202 Object[] expanded = getViewer().getExpandedElements();
203
204 IStructuredSelection oldSelection = (IStructuredSelection) getViewer()
205 .getSelection();
206
207 refreshViewerData(getRoot());
208
209 List<OutlineItem> newItems = new ArrayList<OutlineItem>();
210 for (int i = 0; i < expanded.length; i++) {
211 newItems.add(getContentProvider().getItem(
212 ((OutlineItem) expanded[i]).getModel()));
213 }
214 getViewer().setExpandedElements(newItems.toArray());
215
216 List selItems = oldSelection.toList();
217 newItems = new ArrayList<OutlineItem>();
218 for (int i = 0; i < selItems.size(); i++) {
219 newItems.add(getContentProvider().getItem(
220 ((OutlineItem) selItems.get(i)).getModel()));
221 }
222 StructuredSelection viewerSel = new StructuredSelection(newItems);
223 getViewer().setSelection(viewerSel);
224
225 if (!viewerSel.isEmpty()) {
226 getViewer().reveal(viewerSel.getFirstElement());
227 }
228 }
229
230 public void refreshViewerData(Node topNode) {
231 getViewer().setInput(topNode);
232 getViewer().refresh(true);
233 }
234
235 public void refresh() {
236 handleDocumentTransformation(getXMLAccess());
237 }
238
239
240
241
242
243
244 @Override
245 public void setFocus() {
246 getViewer().getControl().setFocus();
247 }
248
249 /***
250 * @return Selection in that is stored, what is selected in whole document
251 */
252 public DOMIntervalSet getDOMSelection() {
253 return getEditorSite().getDOMSelection();
254 }
255
256 /***
257 *
258 */
259 public void addSelectionChangedListener(
260 IDOMSelectionChangedListener listener) {
261 this.domSelectionListeners.add(listener);
262 }
263
264 /***
265 *
266 */
267 public void removeSelectionChangedListener(
268 ISelectionChangedListener listener) {
269 this.domSelectionListeners.remove(listener);
270 }
271
272 /***
273 * Routs information about this new IXMLSelection to SelectionListeners and
274 * to TreeViewer
275 *
276 * @param selection
277 * IXMLSelection to set
278 */
279 public void setSelection(DOMIntervalSet selection) {
280 fireSelectionChangeEvent(selection);
281 }
282
283 /***
284 * This should be called from TreeViewer or from EditorSite Selection in the
285 * Event can be IStructureSelection or IXMLSelection depending on even
286 * source.
287 *
288 * @param event
289 * Event that contains Selection
290 */
291 public void selectionChanged(DOMSelectionChangedEvent event) {
292
293 if (event.getSource() == getViewer()) {
294
295
296
297
298 } else {
299
300
301 IStructuredSelection sSel = convertIXMLSelectionToIStructureSelection(event
302 .getDOMSelection());
303 getViewer().setSelection(sSel);
304 if (!sSel.isEmpty()) {
305 getViewer().reveal(sSel.getFirstElement());
306 }
307
308 fireSelectionChangeEvent(event.getDOMSelection());
309 }
310
311
312
313
314
315
316 this.statusLineManager.show(getDOMSelection());
317 }
318
319 /***
320 * XMLOutlinePage starts selection listening. It adds itself to
321 * XMLOutlinePage's listeners listeners. And add itself to TreeViewer's
322 * selectionListeners It is a "two way listening" Call in pair with
323 * stopSelectionListening().
324 */
325 private void startSelectionListening() {
326 for (ISelectionChangedListener listener : this.selectionListeners)
327 if (listener instanceof ISelectionProvider)
328 ((ISelectionProvider) listener)
329 .removeSelectionChangedListener(this);
330 for (IDOMSelectionChangedListener listener : this.domSelectionListeners)
331 if (listener instanceof IDOMSelectionProvider)
332 ((IDOMSelectionProvider) listener)
333 .removeSelectionChangedListener(this);
334 getViewer().addSelectionChangedListener(this);
335 }
336
337 /***
338 * XMLOutlinePage does not realy stops selection listening because
339 * setSelection and selectionChange are public methods, but it removes
340 * itself from XMLOutlinePage's listeners listeners. And removes itself from
341 * TreeViewer's selectionListeners This prevents from loops.
342 */
343 private void stopSelectionListening() {
344 for (ISelectionChangedListener listener : this.selectionListeners)
345 if (listener instanceof ISelectionProvider)
346 ((ISelectionProvider) listener)
347 .removeSelectionChangedListener(this);
348 for (IDOMSelectionChangedListener listener : this.domSelectionListeners)
349 if (listener instanceof IDOMSelectionProvider)
350 ((IDOMSelectionProvider) listener)
351 .removeSelectionChangedListener(this);
352
353 getViewer().removeSelectionChangedListener(this);
354 }
355
356 /***
357 * @param xmlSelection
358 * IXMLSelection to be routed to selectionListeners
359 */
360 protected void fireSelectionChangeEvent(DOMIntervalSet xmlSelection) {
361 if (this.domSelectionListeners.isEmpty())
362 return;
363 stopSelectionListening();
364
365 DOMSelectionChangedEvent event = new DOMSelectionChangedEvent(this,
366 xmlSelection);
367 for (IDOMSelectionChangedListener listener : this.domSelectionListeners) {
368 listener.selectionChanged(event);
369 }
370
371 startSelectionListening();
372 }
373
374 /***
375 * Makes IDs from IStructureSelection and IDs from IXMLSelection. Then the
376 * are 3 cases
377 * <ul>
378 * <li> id from IStructureSelection is in IDs from IXMLSelection - no
379 * change, so do nothing</li>
380 * <li> id from IStructureSelection is NOT in IDs from IXMLSelection - new
381 * Node was selected in Outline, so add to IXMLSelection whole DOMInterval
382 * of this Node</li>
383 * <li> id from IXMLSelection is NOT in IDs from IStructureSelection - Node
384 * was deselected, so remove DOMInterval of this NOde </li>
385 * </ul>
386 *
387 * @param sSel
388 * IStructureSelection from TreeViewer
389 * @param xmlSelection
390 * curent IXMLSelection, that will be updated
391 *
392 * @return
393 */
394 protected DOMIntervalSet synchronizeViewerSelection(
395 IStructuredSelection sSel, DOMIntervalSet xmlSelection) {
396
397 return null;
398 }
399
400 protected IStructuredSelection convertIXMLSelectionToIStructureSelection(
401 DOMIntervalSet xmlSelection) {
402 List<OutlineItem> n = new ArrayList<OutlineItem>();
403
404 Set<String> ids = xmlSelection.getContentIds(getXMLAccess().getIdManager());
405 for (String id : ids) {
406 NodeListID nlID = this.xmlAccess.getIdManager().getNodeNull(id);
407 if (nlID != null) {
408 for (int j = 0; j < nlID.getLength(); j++) {
409 OutlineItem p = this.contentProvider.getItem(nlID.item(j));
410 if (p != null) {
411 n.add(p);
412 }
413 }
414 }
415 }
416
417 return new StructuredSelection(n);
418 }
419
420 public void setShowTransformed(boolean showTrn) {
421 if (showTrn != this.showingTransformed) {
422 this.showingTransformed = showTrn;
423 refreshViewerData(getRoot());
424 }
425 }
426
427 /***
428 * @return Returns the viewer.
429 */
430 public TreeViewer getViewer() {
431 return this.viewer;
432 }
433
434 /***
435 * @param viewer
436 * The viewer to set.
437 */
438 public void setViewer(TreeViewer viewer) {
439 this.viewer = viewer;
440 }
441
442 /***
443 * @return Returns the actionContributor.
444 */
445 public XMLOutlineActionContributor getActionContributor() {
446 return this.actionContributor;
447 }
448
449 /***
450 * @param actionContributor
451 * The actionContributor to set.
452 */
453 public void setActionContributor(
454 XMLOutlineActionContributor actionContributor) {
455 this.actionContributor = actionContributor;
456 }
457
458 /***
459 * @return Returns the contentProvider.
460 */
461 public XMLAccessContentProvider getContentProvider() {
462 return this.contentProvider;
463 }
464
465 /***
466 * @param contentProvider
467 * The contentProvider to set.
468 */
469 public void setContentProvider(XMLAccessContentProvider contentProvider) {
470 this.contentProvider = contentProvider;
471 }
472
473 /***
474 * @return Returns the xmlAccess.
475 */
476 public XMLAccess getXMLAccess() {
477 return this.xmlAccess;
478 }
479
480 /***
481 * @param xmlAccess
482 * The xmlAccess to set.
483 */
484 private void setXmlAccess(XMLAccess xmlAccess) {
485 this.xmlAccess = xmlAccess;
486 }
487
488 /***
489 * @return Returns the editorSite.
490 */
491 private EditorSite getEditorSite() {
492 return this.editorSite;
493 }
494
495 /***
496 * @return Returns the labelProvider.
497 */
498 protected OutlineItemsLabelProvider getLabelProvider() {
499 return this.labelProvider;
500 }
501
502 /***
503 * @param labelProvider
504 * The labelProvider to set.
505 */
506 protected void setLabelProvider(OutlineItemsLabelProvider labelProvider) {
507 this.labelProvider = labelProvider;
508 }
509
510 /***
511 * @return Returns the showingTransformed.
512 */
513 protected boolean isShowingTransformed() {
514 return this.showingTransformed;
515 }
516
517 /***
518 * @param showingTransformed
519 * The showingTransformed to set.
520 */
521 protected void setShowingTransformed(boolean showingTransformed) {
522 this.showingTransformed = showingTransformed;
523 }
524
525 /***
526 * @return Returns the xmlAccessChangeHandler.
527 */
528 protected IGeneralListener getXmlAccessChangeHandler() {
529 return this.xmlAccessChangeHandler;
530 }
531
532 /***
533 * @param statusLineManager
534 * The statusLineManager to set.
535 */
536 protected void setStatusLineManager(
537 StatusLineUpdateManager statusLineManager) {
538 this.statusLineManager = statusLineManager;
539 }
540
541 public void addSelectionChangedListener(ISelectionChangedListener listener) {
542
543
544 }
545
546 public ISelection getSelection() {
547
548 return null;
549 }
550
551 public void setSelection(ISelection selection) {
552
553
554 }
555
556 public void selectionChanged(SelectionChangedEvent event) {
557
558
559 }
560
561 public void removeSelectionChangedListener(IDOMSelectionChangedListener listener) {
562
563
564 }
565
566
567 }