Mercurial > projects > dwt-addons
annotate dwtx/jface/viewers/StructuredViewer.d @ 90:7ffeace6c47f
Update 3.4M7 to 3.4
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 06 Jul 2008 23:30:07 +0200 |
parents | 46a6e0e6ccd4 |
children | 04b47443bb01 |
rev | line source |
---|---|
10 | 1 /******************************************************************************* |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
10 | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Tom Schindl - bug 151205 | |
11 * Port to the D programming language: | |
12 * Frank Benoit <benoit@tionex.de> | |
13 *******************************************************************************/ | |
14 module dwtx.jface.viewers.StructuredViewer; | |
15 | |
16 import dwtx.jface.viewers.IBaseLabelProvider; | |
17 import dwtx.jface.viewers.IPostSelectionProvider; | |
18 import dwtx.jface.viewers.ContentViewer; | |
19 import dwtx.jface.viewers.CustomHashtable; | |
20 import dwtx.jface.viewers.IElementComparer; | |
21 import dwtx.jface.viewers.ViewerComparator; | |
22 import dwtx.jface.viewers.ViewerFilter; | |
23 import dwtx.jface.viewers.IDoubleClickListener; | |
24 import dwtx.jface.viewers.IOpenListener; | |
25 import dwtx.jface.viewers.ISelectionChangedListener; | |
26 import dwtx.jface.viewers.OpenEvent; | |
27 import dwtx.jface.viewers.SelectionChangedEvent; | |
28 import dwtx.jface.viewers.ISelection; | |
29 import dwtx.jface.viewers.DoubleClickEvent; | |
30 import dwtx.jface.viewers.ViewerSorter; | |
31 import dwtx.jface.viewers.IContentProvider; | |
32 import dwtx.jface.viewers.IColorProvider; | |
33 import dwtx.jface.viewers.IFontProvider; | |
34 import dwtx.jface.viewers.LabelProviderChangedEvent; | |
35 import dwtx.jface.viewers.ViewerLabel; | |
36 import dwtx.jface.viewers.TreePath; | |
37 import dwtx.jface.viewers.ITreePathLabelProvider; | |
38 import dwtx.jface.viewers.IViewerLabelProvider; | |
39 import dwtx.jface.viewers.ILabelProvider; | |
40 import dwtx.jface.viewers.IStructuredContentProvider; | |
41 import dwtx.jface.viewers.StructuredSelection; | |
42 import dwtx.jface.viewers.IStructuredSelection; | |
43 | |
44 import tango.util.collection.ArraySeq; | |
45 import tango.util.collection.model.Seq; | |
46 import tango.util.collection.model.SeqView; | |
47 | |
48 import dwt.custom.TableTreeItem; | |
49 import dwt.dnd.DragSource; | |
50 import dwt.dnd.DragSourceListener; | |
51 import dwt.dnd.DropTarget; | |
52 import dwt.dnd.DropTargetListener; | |
53 import dwt.dnd.Transfer; | |
54 import dwt.events.DisposeEvent; | |
55 import dwt.events.SelectionAdapter; | |
56 import dwt.events.SelectionEvent; | |
57 import dwt.events.SelectionListener; | |
58 import dwt.graphics.Color; | |
59 import dwt.graphics.Font; | |
60 import dwt.widgets.Control; | |
61 import dwt.widgets.Item; | |
62 import dwt.widgets.TableItem; | |
63 import dwt.widgets.TreeItem; | |
64 import dwt.widgets.Widget; | |
65 import dwtx.core.runtime.Assert; | |
66 import dwtx.core.runtime.ListenerList; | |
67 import dwtx.jface.util.IOpenEventListener; | |
68 import dwtx.jface.util.OpenStrategy; | |
69 import dwtx.jface.util.SafeRunnable; | |
70 | |
71 import dwt.dwthelper.utils; | |
72 import dwt.dwthelper.Runnable; | |
73 | |
74 /** | |
75 * Abstract base implementation for structure-oriented viewers (trees, lists, | |
76 * tables). Supports custom sorting, filtering, and rendering. | |
77 * <p> | |
78 * Any number of viewer filters can be added to this viewer (using | |
79 * <code>addFilter</code>). When the viewer receives an update, it asks each | |
80 * of its filters if it is out of date, and refilters elements as required. | |
81 * </p> | |
82 * | |
83 * @see ViewerFilter | |
84 * @see ViewerComparator | |
85 */ | |
86 public abstract class StructuredViewer : ContentViewer, IPostSelectionProvider { | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
87 alias ContentViewer.opEquals opEquals; |
10 | 88 alias ContentViewer.setSelection setSelection; |
89 /** | |
90 * A map from the viewer's model elements to DWT widgets. (key type: | |
91 * <code>Object</code>, value type: <code>Widget</code>, or <code>Widget[]</code>). | |
92 * <code>null</code> means that the element map is disabled. | |
93 */ | |
94 private CustomHashtable elementMap; | |
95 | |
96 /** | |
97 * The comparer to use for comparing elements, or <code>null</code> to use | |
98 * the default <code>equals</code> and <code>hashCode</code> methods on | |
99 * the element itself. | |
100 */ | |
101 private IElementComparer comparer; | |
102 | |
103 /** | |
104 * This viewer's comparator used for sorting. <code>null</code> means there is no comparator. | |
105 */ | |
106 private ViewerComparator sorter; | |
107 | |
108 /** | |
109 * This viewer's filters (element type: <code>ViewerFilter</code>). | |
110 * <code>null</code> means there are no filters. | |
111 */ | |
112 private Seq!(ViewerFilter) filters; | |
113 | |
114 /** | |
115 * Indicates whether a selection change is in progress on this viewer. | |
116 * | |
117 * @see #setSelection(ISelection, bool) | |
118 */ | |
119 private bool inChange; | |
120 | |
121 /** | |
122 * Used while a selection change is in progress on this viewer to indicates | |
123 * whether the selection should be restored. | |
124 * | |
125 * @see #setSelection(ISelection, bool) | |
126 */ | |
127 private bool restoreSelection; | |
128 | |
129 /** | |
130 * List of double-click state listeners (element type: | |
131 * <code>IDoubleClickListener</code>). | |
132 * | |
133 * @see #fireDoubleClick | |
134 */ | |
135 private ListenerList doubleClickListeners; | |
136 | |
137 /** | |
138 * List of open listeners (element type: | |
139 * <code>ISelectionActivateListener</code>). | |
140 * | |
141 * @see #fireOpen | |
142 */ | |
143 private ListenerList openListeners; | |
144 | |
145 /** | |
146 * List of post selection listeners (element type: | |
147 * <code>ISelectionActivateListener</code>). | |
148 * | |
149 * @see #firePostSelectionChanged | |
150 */ | |
151 private ListenerList postSelectionChangedListeners; | |
152 | |
153 /** | |
154 * The colorAndFontCollector is an object used by viewers that | |
155 * support the IColorProvider, the IFontProvider and/or the | |
156 * IViewerLabelProvider for color and font updates. | |
157 * Initialize it to have no color or font providing | |
158 * initially. | |
159 * @since 3.1 | |
160 */ | |
161 private ColorAndFontCollector colorAndFontCollector; | |
162 | |
163 /** | |
164 * Empty array of widgets. | |
165 */ | |
166 private static Widget[] NO_WIDGETS = null; | |
167 | |
168 /** | |
169 * The ColorAndFontCollector is a helper class for viewers | |
170 * that have color and font support ad optionally decorators. | |
171 * @see IColorDecorator | |
172 * @see IFontDecorator | |
173 * @see IColorProvider | |
174 * @see IFontProvider | |
175 * @see IDecoration | |
176 */ | |
177 protected class ColorAndFontCollectorWithProviders : ColorAndFontCollector{ | |
178 | |
179 IColorProvider colorProvider; | |
180 | |
181 IFontProvider fontProvider; | |
182 | |
183 /** | |
184 * Create a new instance of the receiver using the supplied | |
185 * label provider. If it is an IColorProvider or IFontProvider | |
186 * set these values up. | |
187 * @param provider IBaseLabelProvider | |
188 * @see IColorProvider | |
189 * @see IFontProvider | |
190 */ | |
191 public this(IBaseLabelProvider provider) { | |
192 super(); | |
193 if ( auto cp = cast(IColorProvider) provider ) { | |
194 colorProvider = cp; | |
195 } | |
196 if ( auto fp = cast(IFontProvider) provider ) { | |
197 fontProvider = fp; | |
198 } | |
199 } | |
200 | |
201 | |
202 /* (non-Javadoc) | |
203 * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#setFontsAndColors(java.lang.Object) | |
204 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
205 public override void setFontsAndColors(Object element){ |
10 | 206 |
207 if(fontProvider !is null){ | |
208 if(font is null) { | |
209 font = fontProvider.getFont(element); | |
210 } | |
211 } | |
212 | |
213 if(colorProvider is null) { | |
214 return; | |
215 } | |
216 //Set the colors if they are not set yet | |
217 if(background is null) { | |
218 background = colorProvider.getBackground(element); | |
219 } | |
220 | |
221 if(foreground is null) { | |
222 foreground = colorProvider.getForeground(element); | |
223 } | |
224 } | |
225 | |
226 /** | |
227 * Apply the fonts and colors to the control if | |
228 * required. | |
229 * @param control | |
230 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
231 public override void applyFontsAndColors(TableItem control) { |
10 | 232 |
233 if(colorProvider is null){ | |
234 if(usedDecorators){ | |
235 //If there is no provider only apply set values | |
236 if(background !is null) { | |
237 control.setBackground(background); | |
238 } | |
239 | |
240 if(foreground !is null) { | |
241 control.setForeground(foreground); | |
242 } | |
243 } | |
244 } | |
245 else{ | |
246 //Always set the value if there is a provider | |
247 control.setBackground(background); | |
248 control.setForeground(foreground); | |
249 } | |
250 | |
251 if(fontProvider is null){ | |
252 if(usedDecorators && font !is null) { | |
253 control.setFont(font); | |
254 } | |
255 } else { | |
256 control.setFont(font); | |
257 } | |
258 | |
259 clear(); | |
260 } | |
261 | |
262 | |
263 | |
264 /* (non-Javadoc) | |
265 * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(dwt.widgets.TreeItem) | |
266 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
267 public override void applyFontsAndColors(TreeItem control) { |
10 | 268 |
269 if(colorProvider is null){ | |
270 if(usedDecorators){ | |
271 //If there is no provider only apply set values | |
272 if(background !is null) { | |
273 control.setBackground(background); | |
274 } | |
275 | |
276 if(foreground !is null) { | |
277 control.setForeground(foreground); | |
278 } | |
279 } | |
280 } | |
281 else{ | |
282 //Always set the value if there is a provider | |
283 control.setBackground(background); | |
284 control.setForeground(foreground); | |
285 } | |
286 | |
287 if(fontProvider is null){ | |
288 if(usedDecorators && font !is null) { | |
289 control.setFont(font); | |
290 } | |
291 } else { | |
292 control.setFont(font); | |
293 } | |
294 | |
295 clear(); | |
296 } | |
297 | |
298 | |
299 /* (non-Javadoc) | |
300 * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(dwt.custom.TableTreeItem) | |
301 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
302 public override void applyFontsAndColors(TableTreeItem control) { |
10 | 303 |
304 if(colorProvider is null){ | |
305 if(usedDecorators){ | |
306 //If there is no provider only apply set values | |
307 if(background !is null) { | |
308 control.setBackground(background); | |
309 } | |
310 | |
311 if(foreground !is null) { | |
312 control.setForeground(foreground); | |
313 } | |
314 } | |
315 } | |
316 else{ | |
317 //Always set the value if there is a provider | |
318 control.setBackground(background); | |
319 control.setForeground(foreground); | |
320 } | |
321 | |
322 if(fontProvider is null){ | |
323 if(usedDecorators && font !is null) { | |
324 control.setFont(font); | |
325 } | |
326 } else { | |
327 control.setFont(font); | |
328 } | |
329 | |
330 clear(); | |
331 } | |
332 | |
333 | |
334 } | |
335 | |
336 /** | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
337 * The ColorAndFontCollector collects fonts and colors without a |
10 | 338 * a color or font provider. |
339 * | |
340 */ | |
341 protected class ColorAndFontCollector { | |
342 | |
343 Color foreground = null; | |
344 | |
345 Color background = null; | |
346 | |
347 Font font = null; | |
348 | |
349 bool usedDecorators = false; | |
350 | |
351 /** | |
352 * Create a new instance of the receiver with | |
353 * no color and font provider. | |
354 */ | |
355 public this(){ | |
356 } | |
357 | |
358 | |
359 /** | |
360 * Clear all of the results. | |
361 */ | |
362 public void clear() { | |
363 foreground = null; | |
364 background = null; | |
365 font = null; | |
366 usedDecorators = false; | |
367 } | |
368 | |
369 | |
370 /** | |
371 * Set the initial fonts and colors for the element from the | |
372 * content providers. | |
373 * @param element Object | |
374 */ | |
375 public void setFontsAndColors(Object element){ | |
376 //Do nothing if there are no providers | |
377 } | |
378 | |
379 /** | |
380 * Set that decorators were applied. | |
381 */ | |
382 public void setUsedDecorators() { | |
383 this.usedDecorators = true; | |
384 } | |
385 | |
386 /** | |
387 * Apply the fonts and colors to the control if | |
388 * required. | |
389 * @param control | |
390 */ | |
391 public void applyFontsAndColors(TableItem control) { | |
392 | |
393 if(usedDecorators){ | |
394 //If there is no provider only apply set values | |
395 if(background !is null) { | |
396 control.setBackground(background); | |
397 } | |
398 | |
399 if(foreground !is null) { | |
400 control.setForeground(foreground); | |
401 } | |
402 | |
403 if(font !is null) { | |
404 control.setFont(font); | |
405 } | |
406 } | |
407 clear(); | |
408 } | |
409 | |
410 /** | |
411 * Apply the fonts and colors to the control if | |
412 * required. | |
413 * @param control | |
414 */ | |
415 public void applyFontsAndColors(TreeItem control) { | |
416 if(usedDecorators){ | |
417 //If there is no provider only apply set values | |
418 if(background !is null) { | |
419 control.setBackground(background); | |
420 } | |
421 | |
422 if(foreground !is null) { | |
423 control.setForeground(foreground); | |
424 } | |
425 | |
426 if(font !is null) { | |
427 control.setFont(font); | |
428 } | |
429 } | |
430 clear(); | |
431 } | |
432 | |
433 /** | |
434 * Apply the fonts and colors to the control if | |
435 * required. | |
436 * @param control | |
437 */ | |
438 public void applyFontsAndColors(TableTreeItem control) { | |
439 if(usedDecorators){ | |
440 //If there is no provider only apply set values | |
441 if(background !is null) { | |
442 control.setBackground(background); | |
443 } | |
444 | |
445 if(foreground !is null) { | |
446 control.setForeground(foreground); | |
447 } | |
448 | |
449 if(font !is null) { | |
450 control.setFont(font); | |
451 } | |
452 } | |
453 clear(); | |
454 } | |
455 | |
456 /** | |
457 * Set the background color. | |
458 * @param background | |
459 */ | |
460 public void setBackground(Color background) { | |
461 this.background = background; | |
462 } | |
463 /** | |
464 * Set the font. | |
465 * @param font | |
466 */ | |
467 public void setFont(Font font) { | |
468 this.font = font; | |
469 } | |
470 /** | |
471 * Set the foreground color. | |
472 * @param foreground | |
473 */ | |
474 public void setForeground(Color foreground) { | |
475 this.foreground = foreground; | |
476 } | |
477 | |
478 | |
479 } | |
480 | |
481 /** | |
482 * The safe runnable used to update an item. | |
483 */ | |
484 class UpdateItemSafeRunnable : SafeRunnable { | |
485 private Widget widget; | |
486 | |
487 private Object element; | |
488 | |
489 private bool fullMap; | |
490 | |
491 this(Widget widget, Object element, bool fullMap) { | |
492 this.widget = widget; | |
493 this.element = element; | |
494 this.fullMap = fullMap; | |
495 } | |
496 | |
497 public void run() { | |
498 doUpdateItem(widget, element, fullMap); | |
499 } | |
500 } | |
501 | |
502 /** | |
503 * Creates a structured element viewer. The viewer has no input, no content | |
504 * provider, a default label provider, no sorter, and no filters. | |
505 */ | |
506 protected this() { | |
507 doubleClickListeners = new ListenerList(); | |
508 openListeners = new ListenerList(); | |
509 postSelectionChangedListeners = new ListenerList(); | |
510 colorAndFontCollector = new ColorAndFontCollector(); | |
511 // do nothing | |
512 } | |
513 | |
514 /** | |
515 * Adds a listener for double-clicks in this viewer. Has no effect if an | |
516 * identical listener is already registered. | |
517 * | |
518 * @param listener | |
519 * a double-click listener | |
520 */ | |
521 public void addDoubleClickListener(IDoubleClickListener listener) { | |
522 doubleClickListeners.add(cast(Object)listener); | |
523 } | |
524 | |
525 /** | |
526 * Adds a listener for selection-open in this viewer. Has no effect if an | |
527 * identical listener is already registered. | |
528 * | |
529 * @param listener | |
530 * a double-click listener | |
531 */ | |
532 public void addOpenListener(IOpenListener listener) { | |
533 openListeners.add(cast(Object)listener); | |
534 } | |
535 | |
536 /* | |
537 * (non-Javadoc) Method declared on IPostSelectionProvider. | |
538 */ | |
539 public void addPostSelectionChangedListener(ISelectionChangedListener listener) { | |
540 postSelectionChangedListeners.add(cast(Object)listener); | |
541 } | |
542 | |
543 /** | |
544 * Adds support for dragging items out of this viewer via a user | |
545 * drag-and-drop operation. | |
546 * | |
547 * @param operations | |
548 * a bitwise OR of the supported drag and drop operation types ( | |
549 * <code>DROP_COPY</code>,<code>DROP_LINK</code>, and | |
550 * <code>DROP_MOVE</code>) | |
551 * @param transferTypes | |
552 * the transfer types that are supported by the drag operation | |
553 * @param listener | |
554 * the callback that will be invoked to set the drag data and to | |
555 * cleanup after the drag and drop operation finishes | |
556 * @see dwt.dnd.DND | |
557 */ | |
558 public void addDragSupport(int operations, Transfer[] transferTypes, DragSourceListener listener) { | |
559 | |
560 Control myControl = getControl(); | |
561 final DragSource dragSource = new DragSource(myControl, operations); | |
562 dragSource.setTransfer(transferTypes); | |
563 dragSource.addDragListener(listener); | |
564 } | |
565 | |
566 /** | |
567 * Adds support for dropping items into this viewer via a user drag-and-drop | |
568 * operation. | |
569 * | |
570 * @param operations | |
571 * a bitwise OR of the supported drag and drop operation types ( | |
572 * <code>DROP_COPY</code>,<code>DROP_LINK</code>, and | |
573 * <code>DROP_MOVE</code>) | |
574 * @param transferTypes | |
575 * the transfer types that are supported by the drop operation | |
576 * @param listener | |
577 * the callback that will be invoked after the drag and drop | |
578 * operation finishes | |
579 * @see dwt.dnd.DND | |
580 */ | |
581 public void addDropSupport(int operations, Transfer[] transferTypes, | |
582 DropTargetListener listener) { | |
583 Control control = getControl(); | |
584 DropTarget dropTarget = new DropTarget(control, operations); | |
585 dropTarget.setTransfer(transferTypes); | |
586 dropTarget.addDropListener(listener); | |
587 } | |
588 | |
589 /** | |
590 * Adds the given filter to this viewer, and triggers refiltering and | |
591 * resorting of the elements. If you want to add more than one filter | |
592 * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}. | |
593 * | |
594 * @param filter | |
595 * a viewer filter | |
596 * @see StructuredViewer#setFilters(ViewerFilter[]) | |
597 */ | |
598 public void addFilter(ViewerFilter filter) { | |
599 if (filters is null) { | |
600 filters = new ArraySeq!(ViewerFilter); | |
601 } | |
602 filters.append(filter); | |
603 refresh(); | |
604 } | |
605 | |
606 /** | |
607 * Asserts that the given array of elements is itself non- <code>null</code> | |
608 * and contains no <code>null</code> elements. | |
609 * | |
610 * @param elements | |
611 * the array to check | |
612 */ | |
613 protected void assertElementsNotNull(Object[] elements) { | |
614 // Assert.isNotNull(elements); | |
615 for (int i = 0, n = elements.length; i < n; ++i) { | |
616 Assert.isNotNull(elements[i]); | |
617 } | |
618 } | |
619 | |
620 /** | |
621 * Associates the given element with the given widget. Sets the given item's | |
622 * data to be the element, and maps the element to the item in the element | |
623 * map (if enabled). | |
624 * | |
625 * @param element | |
626 * the element | |
627 * @param item | |
628 * the widget | |
629 */ | |
630 protected void associate(Object element, Item item) { | |
631 Object data = item.getData(); | |
632 if (data !is element) { | |
633 if (data !is null) { | |
634 disassociate(item); | |
635 } | |
636 item.setData(element); | |
637 } | |
638 // Always map the element, even if data is element, | |
639 // since unmapAllElements() can leave the map inconsistent | |
640 // See bug 2741 for details. | |
641 mapElement(element, item); | |
642 } | |
643 | |
644 /** | |
645 * Disassociates the given DWT item from its corresponding element. Sets the | |
646 * item's data to <code>null</code> and removes the element from the | |
647 * element map (if enabled). | |
648 * | |
649 * @param item | |
650 * the widget | |
651 */ | |
652 protected void disassociate(Item item) { | |
653 Object element = item.getData(); | |
654 Assert.isNotNull(element); | |
655 //Clear the map before we clear the data | |
656 unmapElement(element, item); | |
657 item.setData(null); | |
658 } | |
659 | |
660 /** | |
661 * Returns the widget in this viewer's control which represents the given | |
662 * element if it is the viewer's input. | |
663 * <p> | |
664 * This method is internal to the framework; subclassers should not call | |
665 * this method. | |
666 * </p> | |
667 * | |
668 * @param element | |
669 * @return the corresponding widget, or <code>null</code> if none | |
670 */ | |
671 protected abstract Widget doFindInputItem(Object element); | |
672 | |
673 /** | |
674 * Returns the widget in this viewer's control which represent the given | |
675 * element. This method searches all the children of the input element. | |
676 * <p> | |
677 * This method is internal to the framework; subclassers should not call | |
678 * this method. | |
679 * </p> | |
680 * | |
681 * @param element | |
682 * @return the corresponding widget, or <code>null</code> if none | |
683 */ | |
684 protected abstract Widget doFindItem(Object element); | |
685 | |
686 /** | |
687 * Copies the attributes of the given element into the given DWT item. The | |
688 * element map is updated according to the value of <code>fullMap</code>. | |
689 * If <code>fullMap</code> is <code>true</code> then the current mapping | |
690 * from element to widgets is removed and the new mapping is added. If | |
691 * full map is <code>false</code> then only the new map gets installed. | |
692 * Installing only the new map is necessary in cases where only the order of | |
693 * elements changes but not the set of elements. | |
694 * <p> | |
695 * This method is internal to the framework; subclassers should not call | |
696 * this method. | |
697 * </p> | |
698 * | |
699 * @param item | |
700 * @param element element | |
701 * @param fullMap | |
702 * <code>true</code> if mappings are added and removed, and | |
703 * <code>false</code> if only the new map gets installed | |
704 */ | |
705 protected abstract void doUpdateItem(Widget item, Object element, bool fullMap); | |
706 | |
707 /** | |
708 * Compares two elements for equality. Uses the element comparer if one has | |
709 * been set, otherwise uses the default <code>equals</code> method on the | |
710 * elements themselves. | |
711 * | |
712 * @param elementA | |
713 * the first element | |
714 * @param elementB | |
715 * the second element | |
716 * @return whether elementA is equal to elementB | |
717 */ | |
718 protected int opEquals(Object elementA, Object elementB) { | |
719 if (comparer is null) { | |
720 return elementA is null ? elementB is null : elementA.opEquals(elementB); | |
721 } else { | |
722 return elementA is null ? elementB is null : comparer.opEquals(elementA, elementB); | |
723 } | |
724 } | |
725 | |
726 /** | |
727 * Returns the result of running the given elements through the filters. | |
728 * | |
729 * @param elements | |
730 * the elements to filter | |
731 * @return only the elements which all filters accept | |
732 */ | |
733 protected Object[] filter(Object[] elements) { | |
734 if (filters !is null) { | |
735 ArraySeq!(Object) filtered = new ArraySeq!(Object); | |
736 filtered.capacity(elements.length); | |
737 Object root = getRoot(); | |
738 for (int i = 0; i < elements.length; i++) { | |
739 bool add = true; | |
740 for (int j = 0; j < filters.size(); j++) { | |
741 add = (cast(ViewerFilter) filters.get(j)).select(this, root, elements[i]); | |
742 if (!add) { | |
743 break; | |
744 } | |
745 } | |
746 if (add) { | |
747 filtered.append(elements[i]); | |
748 } | |
749 } | |
750 return filtered.toArray(); | |
751 } | |
752 return elements; | |
753 } | |
754 | |
755 /** | |
756 * Finds the widget which represents the given element. | |
757 * <p> | |
758 * The default implementation of this method tries first to find the widget | |
759 * for the given element assuming that it is the viewer's input; this is | |
760 * done by calling <code>doFindInputItem</code>. If it is not found | |
761 * there, it is looked up in the internal element map provided that this | |
762 * feature has been enabled. If the element map is disabled, the widget is | |
763 * found via <code>doFindInputItem</code>. | |
764 * </p> | |
765 * | |
766 * @param element | |
767 * the element | |
768 * @return the corresponding widget, or <code>null</code> if none | |
769 */ | |
770 protected final Widget findItem(Object element) { | |
771 Widget[] result = findItems(element); | |
772 return result.length is 0 ? null : result[0]; | |
773 } | |
774 | |
775 /** | |
776 * Finds the widgets which represent the given element. The returned array | |
777 * must not be changed by clients; it might change upon calling other | |
778 * methods on this viewer. | |
779 * <p> | |
780 * This method was introduced to support multiple equal elements in a viewer | |
781 * (@see {@link AbstractTreeViewer}). Multiple equal elements are only | |
782 * supported if the element map is enabled by calling | |
783 * {@link #setUseHashlookup(bool)} and passing <code>true</code>. | |
784 * </p> | |
785 * <p> | |
786 * The default implementation of this method tries first to find the widget | |
787 * for the given element assuming that it is the viewer's input; this is | |
788 * done by calling <code>doFindInputItem</code>. If it is not found | |
789 * there, the widgets are looked up in the internal element map provided | |
790 * that this feature has been enabled. If the element map is disabled, the | |
791 * widget is found via <code>doFindInputItem</code>. | |
792 * </p> | |
793 * | |
794 * @param element | |
795 * the element | |
796 * @return the corresponding widgets | |
797 * | |
798 * @since 3.2 | |
799 */ | |
800 protected final Widget[] findItems(Object element) { | |
801 Widget result = doFindInputItem(element); | |
802 if (result !is null) { | |
803 return [ result ]; | |
804 } | |
805 // if we have an element map use it, otherwise search for the item. | |
806 if (usingElementMap()) { | |
807 Object widgetOrWidgets = elementMap.get(element); | |
808 if (widgetOrWidgets is null) { | |
809 return NO_WIDGETS; | |
810 } else if ( auto w = cast(Widget) widgetOrWidgets ) { | |
811 return [w]; | |
812 } else { | |
813 return (cast(ArrayWrapperT!(Widget))widgetOrWidgets).array; | |
814 } | |
815 } | |
816 result = doFindItem(element); | |
817 return result is null ? NO_WIDGETS : [ result ]; | |
818 } | |
819 | |
820 /** | |
821 * Notifies any double-click listeners that a double-click has been | |
822 * received. Only listeners registered at the time this method is called are | |
823 * notified. | |
824 * | |
825 * @param event | |
826 * a double-click event | |
827 * | |
828 * @see IDoubleClickListener#doubleClick | |
829 */ | |
830 protected void fireDoubleClick(DoubleClickEvent event) { | |
831 Object[] listeners = doubleClickListeners.getListeners(); | |
832 for (int i = 0; i < listeners.length; ++i) { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
833 SafeRunnable.run(new class(cast(IDoubleClickListener) listeners[i], event) SafeRunnable { |
10 | 834 IDoubleClickListener l; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
835 DoubleClickEvent event_; |
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
836 this(IDoubleClickListener a,DoubleClickEvent b){ |
39 | 837 l = a; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
838 event_=b; |
10 | 839 } |
840 public void run() { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
841 l.doubleClick(event_); |
10 | 842 } |
843 }); | |
844 } | |
845 } | |
846 package void fireDoubleClick_package(DoubleClickEvent event) { | |
847 fireDoubleClick(event); | |
848 } | |
849 | |
850 /** | |
851 * Notifies any open event listeners that a open event has been received. | |
852 * Only listeners registered at the time this method is called are notified. | |
853 * | |
854 * @param event | |
855 * a double-click event | |
856 * | |
857 * @see IOpenListener#open(OpenEvent) | |
858 */ | |
859 protected void fireOpen(OpenEvent event) { | |
860 Object[] listeners = openListeners.getListeners(); | |
861 for (int i = 0; i < listeners.length; ++i) { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
862 SafeRunnable.run(new class(cast(IOpenListener) listeners[i],event) SafeRunnable { |
10 | 863 IOpenListener l; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
864 OpenEvent event_; |
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
865 this(IOpenListener a, OpenEvent b){ |
39 | 866 l = a; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
867 event_=b; |
10 | 868 } |
869 public void run() { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
870 l.open(event_); |
10 | 871 } |
872 }); | |
873 } | |
874 } | |
875 package void fireOpen_package(OpenEvent event) { | |
876 fireOpen(event); | |
877 } | |
878 | |
879 /** | |
880 * Notifies any post selection listeners that a post selection event has | |
881 * been received. Only listeners registered at the time this method is | |
882 * called are notified. | |
883 * | |
884 * @param event | |
885 * a selection changed event | |
886 * | |
887 * @see #addPostSelectionChangedListener(ISelectionChangedListener) | |
888 */ | |
889 protected void firePostSelectionChanged(SelectionChangedEvent event) { | |
890 Object[] listeners = postSelectionChangedListeners.getListeners(); | |
891 for (int i = 0; i < listeners.length; ++i) { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
892 SafeRunnable.run(new class(cast(ISelectionChangedListener) listeners[i],event) SafeRunnable { |
10 | 893 ISelectionChangedListener l; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
894 SelectionChangedEvent event_; |
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
895 this(ISelectionChangedListener a,SelectionChangedEvent b){ |
39 | 896 l = a; |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
897 event_=b; |
10 | 898 } |
899 public void run() { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
900 l.selectionChanged(event_); |
10 | 901 } |
902 }); | |
903 } | |
904 } | |
905 | |
906 /** | |
907 * Returns the comparer to use for comparing elements, or | |
908 * <code>null</code> if none has been set. If specified, | |
909 * the viewer uses this to compare and hash elements rather | |
910 * than the elements' own equals and hashCode methods. | |
911 * | |
912 * @return the comparer to use for comparing elements or | |
913 * <code>null</code> | |
914 */ | |
915 public IElementComparer getComparer() { | |
916 return comparer; | |
917 } | |
918 | |
919 /** | |
920 * Returns the filtered array of children of the given element. The | |
921 * resulting array must not be modified, as it may come directly from the | |
922 * model's internal state. | |
923 * | |
924 * @param parent | |
925 * the parent element | |
926 * @return a filtered array of child elements | |
927 */ | |
928 protected Object[] getFilteredChildren(Object parent) { | |
929 Object[] result = getRawChildren(parent); | |
930 if (filters !is null) { | |
931 foreach (f;filters) { | |
932 result = f.filter(this, parent, result); | |
933 } | |
934 } | |
935 return result; | |
936 } | |
937 | |
938 /** | |
939 * Returns this viewer's filters. | |
940 * | |
941 * @return an array of viewer filters | |
942 * @see StructuredViewer#setFilters(ViewerFilter[]) | |
943 */ | |
944 public ViewerFilter[] getFilters() { | |
945 if (filters is null) { | |
946 return new ViewerFilter[0]; | |
947 } | |
948 return filters.toArray(); | |
949 } | |
950 | |
951 /** | |
952 * Returns the item at the given display-relative coordinates, or | |
953 * <code>null</code> if there is no item at that location or | |
954 * the underlying DWT-Control is not made up of {@link Item} | |
955 * (e.g {@link ListViewer}) | |
956 * <p> | |
957 * The default implementation of this method returns <code>null</code>. | |
958 * </p> | |
959 * | |
960 * @param x | |
961 * horizontal coordinate | |
962 * @param y | |
963 * vertical coordinate | |
964 * @return the item, or <code>null</code> if there is no item at the given | |
965 * coordinates | |
966 * @deprecated This method is deprecated in 3.3 in favor of {@link ColumnViewer#getItemAt(dwt.graphics.Point)}. | |
967 * Viewers who are not subclasses of {@link ColumnViewer} should consider using a | |
968 * widget relative implementation like {@link ColumnViewer#getItemAt(dwt.graphics.Point)}. | |
969 * | |
970 */ | |
971 protected Item getItem(int x, int y) { | |
972 return null; | |
973 } | |
974 | |
975 /** | |
976 * Returns the children of the given parent without sorting and filtering | |
977 * them. The resulting array must not be modified, as it may come directly | |
978 * from the model's internal state. | |
979 * <p> | |
980 * Returns an empty array if the given parent is <code>null</code>. | |
981 * </p> | |
982 * | |
983 * @param parent | |
984 * the parent element | |
985 * @return the child elements | |
986 */ | |
987 protected Object[] getRawChildren(Object parent) { | |
988 Object[] result = null; | |
989 if (parent !is null) { | |
990 IStructuredContentProvider cp = cast(IStructuredContentProvider) getContentProvider(); | |
991 if (cp !is null) { | |
992 result = cp.getElements(parent); | |
993 assertElementsNotNull(result); | |
994 } | |
995 } | |
996 return (result !is null) ? result : null; | |
997 } | |
998 | |
999 /** | |
1000 * Returns the root element. | |
1001 * <p> | |
1002 * The default implementation of this framework method forwards to | |
1003 * <code>getInput</code>. Override if the root element is different from | |
1004 * the viewer's input element. | |
1005 * </p> | |
1006 * | |
1007 * @return the root element, or <code>null</code> if none | |
1008 */ | |
1009 protected Object getRoot() { | |
1010 return getInput(); | |
1011 } | |
1012 | |
1013 /** | |
1014 * The <code>StructuredViewer</code> implementation of this method returns | |
1015 * the result as an <code>IStructuredSelection</code>. | |
1016 * <p> | |
1017 * Subclasses do not typically override this method, but implement | |
1018 * <code>getSelectionFromWidget(List)</code> instead. | |
1019 * <p> | |
1020 * @return ISelection | |
1021 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1022 public override ISelection getSelection() { |
10 | 1023 Control control = getControl(); |
1024 if (control is null || control.isDisposed()) { | |
1025 return StructuredSelection.EMPTY; | |
1026 } | |
1027 auto list = getSelectionFromWidget(); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1028 return new StructuredSelection(list, comparer); |
10 | 1029 } |
1030 | |
1031 /** | |
1032 * Retrieves the selection, as a <code>List</code>, from the underlying | |
1033 * widget. | |
1034 * | |
1035 * @return the list of selected elements | |
1036 */ | |
1037 protected abstract SeqView!(Object) getSelectionFromWidget(); | |
1038 package SeqView!(Object) getSelectionFromWidget_package(){ | |
1039 return getSelectionFromWidget(); | |
1040 } | |
1041 | |
1042 /** | |
1043 * Returns the sorted and filtered set of children of the given element. The | |
1044 * resulting array must not be modified, as it may come directly from the | |
1045 * model's internal state. | |
1046 * | |
1047 * @param parent | |
1048 * the parent element | |
1049 * @return a sorted and filtered array of child elements | |
1050 */ | |
1051 protected Object[] getSortedChildren(Object parent) { | |
1052 Object[] result = getFilteredChildren(parent); | |
1053 if (sorter !is null) { | |
1054 // be sure we're not modifying the original array from the model | |
1055 result = result.dup; | |
1056 sorter.sort(this, result); | |
1057 } | |
1058 return result; | |
1059 } | |
1060 | |
1061 /** | |
1062 * Returns this viewer's sorter, or <code>null</code> if it does not have | |
1063 * one. If this viewer has a comparator that was set via | |
1064 * <code>setComparator(ViewerComparator)</code> then this method will return | |
1065 * <code>null</code> if the comparator is not an instance of ViewerSorter. | |
1066 * <p> | |
1067 * It is recommended to use <code>getComparator()</code> instead. | |
1068 * </p> | |
1069 * | |
1070 * @return a viewer sorter, or <code>null</code> if none or if the comparator is | |
1071 * not an instance of ViewerSorter | |
1072 */ | |
1073 public ViewerSorter getSorter() { | |
1074 if ( auto vs = cast(ViewerSorter)sorter ) | |
1075 return vs; | |
1076 return null; | |
1077 } | |
1078 | |
1079 /** | |
1080 * Return this viewer's comparator used to sort elements. | |
1081 * This method should be used instead of <code>getSorter()</code>. | |
1082 * | |
1083 * @return a viewer comparator, or <code>null</code> if none | |
1084 * | |
1085 * @since 3.2 | |
1086 */ | |
1087 public ViewerComparator getComparator(){ | |
1088 return sorter; | |
1089 } | |
1090 | |
1091 /** | |
1092 * Handles a double-click select event from the widget. | |
1093 * <p> | |
1094 * This method is internal to the framework; subclassers should not call | |
1095 * this method. | |
1096 * </p> | |
1097 * | |
1098 * @param event | |
1099 * the DWT selection event | |
1100 */ | |
1101 protected void handleDoubleSelect(SelectionEvent event) { | |
1102 // This method is reimplemented in AbstractTreeViewer to fix bug 108102. | |
1103 | |
1104 // handle case where an earlier selection listener disposed the control. | |
1105 Control control = getControl(); | |
1106 if (control !is null && !control.isDisposed()) { | |
1107 // If the double-clicked element can be obtained from the event, use it | |
1108 // otherwise get it from the control. Some controls like List do | |
1109 // not have the notion of item. | |
1110 // For details, see bug 90161 [Navigator] DefaultSelecting folders shouldn't always expand first one | |
1111 ISelection selection; | |
1112 if (event.item !is null && event.item.getData() !is null) { | |
1113 selection = new StructuredSelection(event.item.getData()); | |
1114 } | |
1115 else { | |
1116 selection = getSelection(); | |
1117 updateSelection(selection); | |
1118 } | |
1119 fireDoubleClick(new DoubleClickEvent(this, selection)); | |
1120 } | |
1121 } | |
1122 | |
1123 /** | |
1124 * Handles an open event from the OpenStrategy. | |
1125 * <p> | |
1126 * This method is internal to the framework; subclassers should not call | |
1127 * this method. | |
1128 * </p> | |
1129 * | |
1130 * @param event | |
1131 * the DWT selection event | |
1132 */ | |
1133 protected void handleOpen(SelectionEvent event) { | |
1134 Control control = getControl(); | |
1135 if (control !is null && !control.isDisposed()) { | |
1136 ISelection selection = getSelection(); | |
1137 fireOpen(new OpenEvent(this, selection)); | |
1138 } | |
1139 } | |
1140 | |
1141 /** | |
1142 * Handles an invalid selection. | |
1143 * <p> | |
1144 * This framework method is called if a model change picked up by a viewer | |
1145 * results in an invalid selection. For instance if an element contained in | |
1146 * the selection has been removed from the viewer, the viewer is free to | |
1147 * either remove the element from the selection or to pick another element | |
1148 * as its new selection. The default implementation of this method calls | |
1149 * <code>updateSelection</code>. Subclasses may override it to implement | |
1150 * a different strategy for picking a new selection when the old selection | |
1151 * becomes invalid. | |
1152 * </p> | |
1153 * | |
1154 * @param invalidSelection | |
1155 * the selection before the viewer was updated | |
1156 * @param newSelection | |
1157 * the selection after the update, or <code>null</code> if none | |
1158 */ | |
1159 protected void handleInvalidSelection(ISelection invalidSelection, ISelection newSelection) { | |
1160 updateSelection(newSelection); | |
1161 SelectionChangedEvent event = new SelectionChangedEvent(this, newSelection); | |
1162 firePostSelectionChanged(event); | |
1163 } | |
1164 | |
1165 /** | |
1166 * The <code>StructuredViewer</code> implementation of this | |
1167 * <code>ContentViewer</code> method calls <code>update</code> if the | |
1168 * event specifies that the label of a given element has changed, otherwise | |
1169 * it calls super. Subclasses may reimplement or extend. | |
1170 * </p> | |
1171 * @param event the event that generated this update | |
1172 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1173 protected override void handleLabelProviderChanged(LabelProviderChangedEvent event) { |
10 | 1174 Object[] elements = event.getElements(); |
1175 if (elements !is null) { | |
1176 update(elements, null); | |
1177 } else { | |
1178 super.handleLabelProviderChanged(event); | |
1179 } | |
1180 } | |
1181 package void handleLabelProviderChanged_package(LabelProviderChangedEvent event) { | |
1182 handleLabelProviderChanged(event); | |
1183 } | |
1184 | |
1185 /** | |
1186 * Handles a select event from the widget. | |
1187 * <p> | |
1188 * This method is internal to the framework; subclassers should not call | |
1189 * this method. | |
1190 * </p> | |
1191 * | |
1192 * @param event | |
1193 * the DWT selection event | |
1194 */ | |
1195 protected void handleSelect(SelectionEvent event) { | |
1196 // handle case where an earlier selection listener disposed the control. | |
1197 Control control = getControl(); | |
1198 if (control !is null && !control.isDisposed()) { | |
1199 updateSelection(getSelection()); | |
1200 } | |
1201 } | |
1202 | |
1203 /** | |
1204 * Handles a post select event from the widget. | |
1205 * <p> | |
1206 * This method is internal to the framework; subclassers should not call | |
1207 * this method. | |
1208 * </p> | |
1209 * | |
1210 * @param e the DWT selection event | |
1211 */ | |
1212 protected void handlePostSelect(SelectionEvent e) { | |
1213 SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); | |
1214 firePostSelectionChanged(event); | |
1215 } | |
1216 | |
1217 /* | |
1218 * (non-Javadoc) Method declared on Viewer. | |
1219 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1220 protected override void hookControl(Control control) { |
10 | 1221 super.hookControl(control); |
1222 OpenStrategy handler = new OpenStrategy(control); | |
1223 handler.addSelectionListener(new class SelectionListener { | |
1224 public void widgetSelected(SelectionEvent e) { | |
1225 // On Windows, selection events may happen during a refresh. | |
1226 // Ignore these events if we are currently in preservingSelection(). | |
1227 // See bug 184441. | |
1228 if (!inChange) { | |
1229 handleSelect(e); | |
1230 } | |
1231 } | |
1232 | |
1233 public void widgetDefaultSelected(SelectionEvent e) { | |
1234 handleDoubleSelect(e); | |
1235 } | |
1236 }); | |
1237 handler.addPostSelectionListener(new class SelectionAdapter { | |
1238 public void widgetSelected(SelectionEvent e) { | |
1239 handlePostSelect(e); | |
1240 } | |
1241 }); | |
1242 handler.addOpenListener(new class IOpenEventListener { | |
1243 public void handleOpen(SelectionEvent e) { | |
1244 this.outer.handleOpen(e); | |
1245 } | |
1246 }); | |
1247 } | |
1248 | |
1249 /** | |
1250 * Returns whether this viewer has any filters. | |
1251 * @return bool | |
1252 */ | |
1253 protected bool hasFilters() { | |
1254 return filters !is null && filters.size() > 0; | |
1255 } | |
1256 | |
1257 /** | |
1258 * Refreshes this viewer starting at the given element. | |
1259 * | |
1260 * @param element | |
1261 * the element | |
1262 */ | |
1263 protected abstract void internalRefresh(Object element); | |
1264 | |
1265 /** | |
1266 * Refreshes this viewer starting at the given element. Labels are updated | |
1267 * as described in <code>refresh(bool updateLabels)</code>. | |
1268 * <p> | |
1269 * The default implementation simply calls | |
1270 * <code>internalRefresh(element)</code>, ignoring | |
1271 * <code>updateLabels</code>. | |
1272 * <p> | |
1273 * If this method is overridden to do the actual refresh, then | |
1274 * <code>internalRefresh(Object element)</code> should simply call | |
1275 * <code>internalRefresh(element, true)</code>. | |
1276 * | |
1277 * @param element | |
1278 * the element | |
1279 * @param updateLabels | |
1280 * <code>true</code> to update labels for existing elements, | |
1281 * <code>false</code> to only update labels as needed, assuming | |
1282 * that labels for existing elements are unchanged. | |
1283 * | |
1284 * @since 2.0 | |
1285 */ | |
1286 protected void internalRefresh(Object element, bool updateLabels) { | |
1287 internalRefresh(element); | |
1288 } | |
1289 | |
1290 /** | |
1291 * Adds the element item pair to the element map. | |
1292 * <p> | |
1293 * This method is internal to the framework; subclassers should not call | |
1294 * this method. | |
1295 * </p> | |
1296 * | |
1297 * @param element | |
1298 * the element | |
1299 * @param item | |
1300 * the corresponding widget | |
1301 */ | |
1302 protected void mapElement(Object element, Widget item) { | |
1303 if (elementMap !is null) { | |
1304 Object widgetOrWidgets = elementMap.get(element); | |
1305 if (widgetOrWidgets is null) { | |
1306 elementMap.put(element, item); | |
1307 } else if ( auto w = cast(Widget)widgetOrWidgets ) { | |
1308 if (widgetOrWidgets !is item) { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1309 elementMap.put(element, new ArrayWrapperT!(Widget)( [ w, item ] )); |
10 | 1310 } |
1311 } else { | |
1312 Widget[] widgets = (cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; | |
1313 int indexOfItem = -1; | |
1314 foreach( idx, w; widgets ){ | |
1315 if( w == item ){ | |
1316 indexOfItem = idx; | |
1317 break; | |
1318 } | |
1319 } | |
1320 if (indexOfItem is -1) { | |
1321 int length_ = widgets.length; | |
1322 System.arraycopy(widgets, 0, | |
1323 widgets = new Widget[length_ + 1], 0, length_); | |
1324 widgets[length_] = item; | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1325 elementMap.put(element, new ArrayWrapperT!(Widget)(widgets)); |
10 | 1326 } |
1327 } | |
1328 } | |
1329 } | |
1330 | |
1331 /** | |
1332 * Determines whether a change to the given property of the given element | |
1333 * would require refiltering and/or resorting. | |
1334 * <p> | |
1335 * This method is internal to the framework; subclassers should not call | |
1336 * this method. | |
1337 * </p> | |
1338 * | |
1339 * @param element | |
1340 * the element | |
1341 * @param property | |
1342 * the property | |
1343 * @return <code>true</code> if refiltering is required, and | |
1344 * <code>false</code> otherwise | |
1345 */ | |
1346 protected bool needsRefilter(Object element, String property) { | |
1347 if (sorter !is null && sorter.isSorterProperty(element, property)) { | |
1348 return true; | |
1349 } | |
1350 | |
1351 if (filters !is null) { | |
1352 foreach( filter; filters ){ | |
1353 if (filter.isFilterProperty(element, property)) { | |
1354 return true; | |
1355 } | |
1356 } | |
1357 } | |
1358 return false; | |
1359 } | |
1360 | |
1361 /** | |
1362 * Returns a new hashtable using the given capacity and this viewer's element comparer. | |
1363 * | |
1364 * @param capacity the initial capacity of the hashtable | |
1365 * @return a new hashtable | |
1366 * | |
1367 * @since 3.0 | |
1368 */ | |
1369 CustomHashtable newHashtable(int capacity) { | |
1370 return new CustomHashtable(capacity, getComparer()); | |
1371 } | |
1372 | |
1373 /** | |
1374 * Attempts to preserves the current selection across a run of the given | |
1375 * code. | |
1376 * <p> | |
1377 * The default implementation of this method: | |
1378 * <ul> | |
1379 * <li>discovers the old selection (via <code>getSelection</code>)</li> | |
1380 * <li>runs the given runnable</li> | |
1381 * <li>attempts to restore the old selection (using | |
1382 * <code>setSelectionToWidget</code></li> | |
1383 * <li>rediscovers the resulting selection (via <code>getSelection</code>) | |
1384 * </li> | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1385 * <li>calls <code>handleInvalidSelection</code> if the resulting selection is different from the old selection</li> |
10 | 1386 * </ul> |
1387 * </p> | |
1388 * | |
1389 * @param updateCode | |
1390 * the code to run | |
1391 */ | |
1392 protected void preservingSelection(Runnable updateCode) { | |
1393 preservingSelection(updateCode, false); | |
1394 } | |
1395 | |
1396 /** | |
1397 * Attempts to preserves the current selection across a run of the given | |
1398 * code, with a best effort to avoid scrolling if <code>reveal</code> is false, | |
1399 * or to reveal the selection if <code>reveal</code> is true. | |
1400 * <p> | |
1401 * The default implementation of this method: | |
1402 * <ul> | |
1403 * <li>discovers the old selection (via <code>getSelection</code>)</li> | |
1404 * <li>runs the given runnable</li> | |
1405 * <li>attempts to restore the old selection (using | |
1406 * <code>setSelectionToWidget</code></li> | |
1407 * <li>rediscovers the resulting selection (via <code>getSelection</code>) | |
1408 * </li> | |
1409 * <li>calls <code>handleInvalidSelection</code> if the selection did not | |
1410 * take</li> | |
1411 * </ul> | |
1412 * </p> | |
1413 * | |
1414 * @param updateCode | |
1415 * the code to run | |
1416 * @param reveal | |
1417 * <code>true</code> if the selection should be made visible, | |
1418 * <code>false</code> if scrolling should be avoided | |
1419 * @since 3.3 | |
1420 */ | |
1421 void preservingSelection(Runnable updateCode, bool reveal) { | |
1422 | |
1423 ISelection oldSelection = null; | |
1424 try { | |
1425 // preserve selection | |
1426 oldSelection = getSelection(); | |
1427 inChange = restoreSelection = true; | |
1428 | |
1429 // perform the update | |
1430 updateCode.run(); | |
1431 | |
1432 } finally { | |
1433 inChange = false; | |
1434 | |
1435 // restore selection | |
1436 if (restoreSelection) { | |
1437 setSelectionToWidget(oldSelection, reveal); | |
1438 } | |
1439 | |
1440 // send out notification if old and new differ | |
1441 ISelection newSelection = getSelection(); | |
1442 if (!(cast(Object)newSelection).opEquals(cast(Object)oldSelection)) { | |
1443 handleInvalidSelection(oldSelection, newSelection); | |
1444 } | |
1445 } | |
1446 } | |
1447 | |
1448 /* | |
1449 * Non-Javadoc. Method declared on Viewer. | |
1450 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1451 public override void refresh() { |
10 | 1452 refresh(getRoot()); |
1453 } | |
1454 | |
1455 /** | |
1456 * Refreshes this viewer with information freshly obtained from this | |
1457 * viewer's model. If <code>updateLabels</code> is <code>true</code> | |
1458 * then labels for otherwise unaffected elements are updated as well. | |
1459 * Otherwise, it assumes labels for existing elements are unchanged, and | |
1460 * labels are only obtained as needed (for example, for new elements). | |
1461 * <p> | |
1462 * Calling <code>refresh(true)</code> has the same effect as | |
1463 * <code>refresh()</code>. | |
1464 * <p> | |
1465 * Note that the implementation may still obtain labels for existing | |
1466 * elements even if <code>updateLabels</code> is false. The intent is | |
1467 * simply to allow optimization where possible. | |
1468 * | |
1469 * @param updateLabels | |
1470 * <code>true</code> to update labels for existing elements, | |
1471 * <code>false</code> to only update labels as needed, assuming | |
1472 * that labels for existing elements are unchanged. | |
1473 * | |
1474 * @since 2.0 | |
1475 */ | |
1476 public void refresh(bool updateLabels) { | |
1477 refresh(getRoot(), updateLabels); | |
1478 } | |
1479 | |
1480 /** | |
1481 * Refreshes this viewer starting with the given element. | |
1482 * <p> | |
1483 * Unlike the <code>update</code> methods, this handles structural changes | |
1484 * to the given element (e.g. addition or removal of children). If only the | |
1485 * given element needs updating, it is more efficient to use the | |
1486 * <code>update</code> methods. | |
1487 * </p> | |
1488 * | |
1489 * @param element | |
1490 * the element | |
1491 */ | |
1492 public void refresh(Object element) { | |
39 | 1493 preservingSelection(new class(element) Runnable { |
10 | 1494 Object element_; |
39 | 1495 this(Object a){ |
1496 element_ = a; | |
10 | 1497 } |
1498 public void run() { | |
1499 internalRefresh(element_); | |
1500 } | |
1501 }); | |
1502 } | |
1503 | |
1504 /** | |
1505 * Refreshes this viewer starting with the given element. Labels are updated | |
1506 * as described in <code>refresh(bool updateLabels)</code>. | |
1507 * <p> | |
1508 * Unlike the <code>update</code> methods, this handles structural changes | |
1509 * to the given element (e.g. addition or removal of children). If only the | |
1510 * given element needs updating, it is more efficient to use the | |
1511 * <code>update</code> methods. | |
1512 * </p> | |
1513 * | |
1514 * @param element | |
1515 * the element | |
1516 * @param updateLabels | |
1517 * <code>true</code> to update labels for existing elements, | |
1518 * <code>false</code> to only update labels as needed, assuming | |
1519 * that labels for existing elements are unchanged. | |
1520 * | |
1521 * @since 2.0 | |
1522 */ | |
1523 public void refresh(Object element, bool updateLabels) { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1524 preservingSelection(new class(element, updateLabels) Runnable { |
10 | 1525 Object element_; |
1526 bool updateLabels_; | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1527 this(Object a, bool b){ |
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1528 element_ = a; |
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1529 updateLabels_ = b; |
10 | 1530 } |
1531 public void run() { | |
1532 internalRefresh(element_, updateLabels_); | |
1533 } | |
1534 }); | |
1535 } | |
1536 | |
1537 /** | |
1538 * | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1539 * Refreshes the given item with the given element. Calls |
10 | 1540 * <code>doUpdateItem(..., false)</code>. |
1541 * <p> | |
1542 * This method is internal to the framework; subclassers should not call | |
1543 * this method. | |
1544 * </p> | |
1545 * @param widget | |
1546 * the widget | |
1547 * @param element | |
1548 * the element | |
1549 */ | |
1550 protected final void refreshItem(Widget widget, Object element) { | |
1551 SafeRunnable.run(new UpdateItemSafeRunnable(widget, element, true)); | |
1552 } | |
1553 | |
1554 /** | |
1555 * Removes the given open listener from this viewer. Has no affect if an | |
1556 * identical listener is not registered. | |
1557 * | |
1558 * @param listener | |
1559 * a double-click listener | |
1560 */ | |
1561 public void removeOpenListener(IOpenListener listener) { | |
1562 openListeners.remove(cast(Object)listener); | |
1563 } | |
1564 | |
1565 /* | |
1566 * (non-Javadoc) Method declared on IPostSelectionProvider. | |
1567 */ | |
1568 public void removePostSelectionChangedListener(ISelectionChangedListener listener) { | |
1569 postSelectionChangedListeners.remove(cast(Object)listener); | |
1570 } | |
1571 | |
1572 /** | |
1573 * Removes the given double-click listener from this viewer. Has no affect | |
1574 * if an identical listener is not registered. | |
1575 * | |
1576 * @param listener | |
1577 * a double-click listener | |
1578 */ | |
1579 public void removeDoubleClickListener(IDoubleClickListener listener) { | |
1580 doubleClickListeners.remove(cast(Object)listener); | |
1581 } | |
1582 | |
1583 /** | |
1584 * Removes the given filter from this viewer, and triggers refiltering and | |
1585 * resorting of the elements if required. Has no effect if the identical | |
1586 * filter is not registered. If you want to remove more than one filter | |
1587 * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}. | |
1588 * | |
1589 * @param filter | |
1590 * a viewer filter | |
1591 * @see StructuredViewer#setFilters(ViewerFilter[]) | |
1592 */ | |
1593 public void removeFilter(ViewerFilter filter) { | |
1594 Assert.isNotNull(filter); | |
1595 if (filters !is null) { | |
1596 // Note: can't use List.remove(Object). Use identity comparison | |
1597 // instead. | |
1598 int delIdx = 0; | |
1599 foreach( o; filters ){ | |
1600 if (o is filter) { | |
1601 filters.removeAt(delIdx); | |
1602 refresh(); | |
1603 if (filters.size() is 0) { | |
1604 filters = null; | |
1605 } | |
1606 return; | |
1607 } | |
1608 delIdx++; | |
1609 } | |
1610 } | |
1611 } | |
1612 | |
1613 /** | |
1614 * Sets the filters, replacing any previous filters, and triggers | |
1615 * refiltering and resorting of the elements. | |
1616 * | |
1617 * @param filters | |
1618 * an array of viewer filters | |
1619 * @since 3.3 | |
1620 */ | |
1621 public void setFilters(ViewerFilter[] filters) { | |
1622 if (filters.length is 0) { | |
1623 resetFilters(); | |
1624 } else { | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1625 auto tmp = new ArraySeq!(ViewerFilter); |
10 | 1626 foreach( f; filters ){ |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1627 tmp.append(f); |
10 | 1628 } |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1629 this.filters = tmp; |
10 | 1630 refresh(); |
1631 } | |
1632 } | |
1633 | |
1634 /** | |
1635 * Discards this viewer's filters and triggers refiltering and resorting of | |
1636 * the elements. | |
1637 */ | |
1638 public void resetFilters() { | |
1639 if (filters !is null) { | |
1640 filters = null; | |
1641 refresh(); | |
1642 } | |
1643 } | |
1644 | |
1645 /** | |
1646 * Ensures that the given element is visible, scrolling the viewer if | |
1647 * necessary. The selection is unchanged. | |
1648 * | |
1649 * @param element | |
1650 * the element to reveal | |
1651 */ | |
1652 public abstract void reveal(Object element); | |
1653 | |
1654 /* | |
1655 * (non-Javadoc) | |
1656 * @see dwtx.jface.viewers.ContentViewer#setContentProvider(dwtx.jface.viewers.IContentProvider) | |
1657 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1658 public override void setContentProvider(IContentProvider provider) { |
10 | 1659 assertContentProviderType(provider); |
1660 super.setContentProvider(provider); | |
1661 } | |
1662 | |
1663 /** | |
1664 * Assert that the content provider is of one of the | |
1665 * supported types. | |
1666 * @param provider | |
1667 */ | |
1668 protected void assertContentProviderType(IContentProvider provider) { | |
1669 Assert.isTrue( null !is cast(IStructuredContentProvider)provider ); | |
1670 } | |
1671 | |
1672 /* | |
1673 * (non-Javadoc) | |
1674 * @see dwtx.jface.viewers.Viewer#setInput(java.lang.Object) | |
1675 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1676 public override final void setInput(Object input) { |
10 | 1677 |
1678 try { | |
1679 // fInChange= true; | |
1680 | |
1681 unmapAllElements(); | |
1682 | |
1683 super.setInput(input); | |
1684 | |
1685 } finally { | |
1686 // fInChange= false; | |
1687 } | |
1688 } | |
1689 | |
1690 /* | |
1691 * (non-Javadoc) | |
1692 * @see dwtx.jface.viewers.Viewer#setSelection(dwtx.jface.viewers.ISelection, bool) | |
1693 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1694 public override void setSelection(ISelection selection, bool reveal) { |
10 | 1695 /** |
1696 * <p> | |
1697 * If the new selection differs from the current selection the hook | |
1698 * <code>updateSelection</code> is called. | |
1699 * </p> | |
1700 * <p> | |
1701 * If <code>setSelection</code> is called from within | |
1702 * <code>preserveSelection</code>, the call to | |
1703 * <code>updateSelection</code> is delayed until the end of | |
1704 * <code>preserveSelection</code>. | |
1705 * </p> | |
1706 * <p> | |
1707 * Subclasses do not typically override this method, but implement | |
1708 * <code>setSelectionToWidget</code> instead. | |
1709 * </p> | |
1710 */ | |
1711 Control control = getControl(); | |
1712 if (control is null || control.isDisposed()) { | |
1713 return; | |
1714 } | |
1715 if (!inChange) { | |
1716 setSelectionToWidget(selection, reveal); | |
1717 ISelection sel = getSelection(); | |
1718 updateSelection(sel); | |
1719 firePostSelectionChanged(new SelectionChangedEvent(this, sel)); | |
1720 } else { | |
1721 restoreSelection = false; | |
1722 setSelectionToWidget(selection, reveal); | |
1723 } | |
1724 } | |
1725 | |
1726 /** | |
1727 * Parlays the given list of selected elements into selections on this | |
1728 * viewer's control. | |
1729 * <p> | |
1730 * Subclasses should override to set their selection based on the given list | |
1731 * of elements. | |
1732 * </p> | |
1733 * | |
1734 * @param l | |
1735 * list of selected elements (element type: <code>Object</code>) | |
1736 * or <code>null</code> if the selection is to be cleared | |
1737 * @param reveal | |
1738 * <code>true</code> if the selection is to be made visible, | |
1739 * and <code>false</code> otherwise | |
1740 */ | |
1741 protected abstract void setSelectionToWidget(SeqView!(Object) l, bool reveal); | |
1742 | |
1743 /** | |
1744 * Converts the selection to a <code>List</code> and calls | |
1745 * <code>setSelectionToWidget(List, bool)</code>. The selection is | |
1746 * expected to be an <code>IStructuredSelection</code> of elements. If | |
1747 * not, the selection is cleared. | |
1748 * <p> | |
1749 * Subclasses do not typically override this method, but implement | |
1750 * <code>setSelectionToWidget(List, bool)</code> instead. | |
1751 * | |
1752 * @param selection | |
1753 * an IStructuredSelection of elements | |
1754 * @param reveal | |
1755 * <code>true</code> to reveal the first element in the | |
1756 * selection, or <code>false</code> otherwise | |
1757 */ | |
1758 protected void setSelectionToWidget(ISelection selection, bool reveal) { | |
1759 if ( auto ss = cast(IStructuredSelection) selection ) { | |
1760 setSelectionToWidget(ss.toList(), reveal); | |
1761 } else { | |
1762 setSelectionToWidget(cast(SeqView!(Object)) null, reveal); | |
1763 } | |
1764 } | |
1765 | |
1766 /** | |
1767 * Sets this viewer's sorter and triggers refiltering and resorting of this | |
1768 * viewer's element. Passing <code>null</code> turns sorting off. | |
1769 * <p> | |
1770 * It is recommended to use <code>setComparator()</code> instead. | |
1771 * </p> | |
1772 * | |
1773 * @param sorter | |
1774 * a viewer sorter, or <code>null</code> if none | |
1775 */ | |
1776 public void setSorter(ViewerSorter sorter) { | |
1777 if (this.sorter !is sorter) { | |
1778 this.sorter = sorter; | |
1779 refresh(); | |
1780 } | |
1781 } | |
1782 | |
1783 /** | |
1784 * Sets this viewer's comparator to be used for sorting elements, and triggers refiltering and | |
1785 * resorting of this viewer's element. <code>null</code> turns sorting off. | |
1786 * To get the viewer's comparator, call <code>getComparator()</code>. | |
1787 * <p> | |
1788 * IMPORTANT: This method was introduced in 3.2. If a reference to this viewer object | |
1789 * is passed to clients who call <code>getSorter()<code>, null may be returned from | |
1790 * from that method even though the viewer is sorting its elements using the | |
1791 * viewer's comparator. | |
1792 * </p> | |
1793 * | |
1794 * @param comparator a viewer comparator, or <code>null</code> if none | |
1795 * | |
1796 * @since 3.2 | |
1797 */ | |
1798 public void setComparator(ViewerComparator comparator){ | |
1799 if (this.sorter !is comparator){ | |
1800 this.sorter = comparator; | |
1801 refresh(); | |
1802 } | |
1803 } | |
1804 | |
1805 /** | |
1806 * Configures whether this structured viewer uses an internal hash table to | |
1807 * speeds up the mapping between elements and DWT items. This must be called | |
1808 * before the viewer is given an input (via <code>setInput</code>). | |
1809 * | |
1810 * @param enable | |
1811 * <code>true</code> to enable hash lookup, and | |
1812 * <code>false</code> to disable it | |
1813 */ | |
1814 public void setUseHashlookup(bool enable) { | |
1815 Assert.isTrue(getInput() is null, | |
1816 "Can only enable the hash look up before input has been set");//$NON-NLS-1$ | |
1817 if (enable) { | |
1818 elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY); | |
1819 } else { | |
1820 elementMap = null; | |
1821 } | |
1822 } | |
1823 | |
1824 /** | |
1825 * Sets the comparer to use for comparing elements, or <code>null</code> | |
1826 * to use the default <code>equals</code> and <code>hashCode</code> | |
1827 * methods on the elements themselves. | |
1828 * | |
1829 * @param comparer | |
1830 * the comparer to use for comparing elements or | |
1831 * <code>null</code> | |
1832 */ | |
1833 public void setComparer(IElementComparer comparer) { | |
1834 this.comparer = comparer; | |
1835 if (elementMap !is null) { | |
1836 elementMap = new CustomHashtable(elementMap, comparer); | |
1837 } | |
1838 } | |
1839 | |
1840 /** | |
1841 * Hook for testing. | |
1842 * @param element | |
1843 * @return Widget | |
1844 */ | |
1845 public Widget testFindItem(Object element) { | |
1846 return findItem(element); | |
1847 } | |
1848 | |
1849 /** | |
1850 * Hook for testing. | |
1851 * @param element | |
1852 * @return Widget[] | |
1853 * @since 3.2 | |
1854 */ | |
1855 public Widget[] testFindItems(Object element) { | |
1856 return findItems(element); | |
1857 } | |
1858 | |
1859 /** | |
1860 * Removes all elements from the map. | |
1861 * <p> | |
1862 * This method is internal to the framework; subclassers should not call | |
1863 * this method. | |
1864 * </p> | |
1865 */ | |
1866 protected void unmapAllElements() { | |
1867 if (elementMap !is null) { | |
1868 elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY); | |
1869 } | |
1870 } | |
1871 | |
1872 /** | |
1873 * Removes the given element from the internal element to widget map. Does | |
1874 * nothing if mapping is disabled. If mapping is enabled, the given element | |
1875 * must be present. | |
1876 * <p> | |
1877 * This method is internal to the framework; subclassers should not call | |
1878 * this method. | |
1879 * </p> | |
1880 * | |
1881 * @param element | |
1882 * the element | |
1883 */ | |
1884 protected void unmapElement(Object element) { | |
1885 if (elementMap !is null) { | |
1886 elementMap.remove(element); | |
1887 } | |
1888 } | |
1889 | |
1890 /** | |
1891 * Removes the given association from the internal element to widget map. | |
1892 * Does nothing if mapping is disabled, or if the given element does not map | |
1893 * to the given item. | |
1894 * <p> | |
1895 * This method is internal to the framework; subclassers should not call | |
1896 * this method. | |
1897 * </p> | |
1898 * | |
1899 * @param element | |
1900 * the element | |
1901 * @param item the item to unmap | |
1902 * @since 2.0 | |
1903 */ | |
1904 protected void unmapElement(Object element, Widget item) { | |
1905 // double-check that the element actually maps to the given item before | |
1906 // unmapping it | |
1907 if (elementMap !is null) { | |
1908 Object widgetOrWidgets = elementMap.get(element); | |
1909 if (widgetOrWidgets is null) { | |
1910 // item was not mapped, return | |
1911 return; | |
1912 } else if ( auto w = cast(Widget) widgetOrWidgets ) { | |
1913 if (item is widgetOrWidgets) { | |
1914 elementMap.remove(element); | |
1915 } | |
1916 } else { | |
1917 Widget[] widgets = ( cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; | |
1918 int indexOfItem = -1; | |
1919 foreach( idx, w; widgets ){ | |
1920 if( w == item ){ | |
1921 indexOfItem = idx; | |
1922 break; | |
1923 } | |
1924 } | |
1925 if (indexOfItem is -1) { | |
1926 return; | |
1927 } | |
1928 int length = widgets.length; | |
1929 if (indexOfItem is 0) { | |
1930 if(length is 1) { | |
1931 elementMap.remove(element); | |
1932 } else { | |
1933 Widget[] updatedWidgets = new Widget[length - 1]; | |
1934 System.arraycopy(widgets, 1, updatedWidgets, 0, length -1 ); | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1935 elementMap.put(element, new ArrayWrapperT!(Widget)( updatedWidgets)); |
10 | 1936 } |
1937 } else { | |
1938 Widget[] updatedWidgets = new Widget[length - 1]; | |
1939 System.arraycopy(widgets, 0, updatedWidgets, 0, indexOfItem); | |
1940 System.arraycopy(widgets, indexOfItem + 1, updatedWidgets, indexOfItem, length - indexOfItem - 1); | |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
43
diff
changeset
|
1941 elementMap.put(element, new ArrayWrapperT!(Widget)(updatedWidgets)); |
10 | 1942 } |
1943 } | |
1944 } | |
1945 } | |
1946 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1947 // flag to indicate that a full refresh took place. See bug 102440. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1948 private bool refreshOccurred; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1949 |
10 | 1950 /** |
1951 * Updates the given elements' presentation when one or more of their | |
1952 * properties change. Only the given elements are updated. | |
1953 * <p> | |
1954 * This does not handle structural changes (e.g. addition or removal of | |
1955 * elements), and does not update any other related elements (e.g. child | |
1956 * elements). To handle structural changes, use the <code>refresh</code> | |
1957 * methods instead. | |
1958 * </p> | |
1959 * <p> | |
1960 * This should be called when an element has changed in the model, in order | |
1961 * to have the viewer accurately reflect the model. This method only affects | |
1962 * the viewer, not the model. | |
1963 * </p> | |
1964 * <p> | |
1965 * Specifying which properties are affected may allow the viewer to optimize | |
1966 * the update. For example, if the label provider is not affected by changes | |
1967 * to any of these properties, an update may not actually be required. | |
1968 * Specifying <code>properties</code> as <code>null</code> forces a full | |
1969 * update of the given elements. | |
1970 * </p> | |
1971 * <p> | |
1972 * If the viewer has a sorter which is affected by a change to one of the | |
1973 * properties, the elements' positions are updated to maintain the sort | |
1974 * order. Note that resorting does not happen if <code>properties</code> | |
1975 * is <code>null</code>. | |
1976 * </p> | |
1977 * <p> | |
1978 * If the viewer has a filter which is affected by a change to one of the | |
1979 * properties, elements may appear or disappear if the change affects | |
1980 * whether or not they are filtered out. | |
1981 * </p> | |
1982 * | |
1983 * @param elements | |
1984 * the elements | |
1985 * @param properties | |
1986 * the properties that have changed, or <code>null</code> to | |
1987 * indicate unknown | |
1988 */ | |
1989 public void update(Object[] elements, String[] properties) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1990 bool previousValue = refreshOccurred; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1991 refreshOccurred = false; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1992 try { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1993 for (int i = 0; i < elements.length; ++i) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1994 update(elements[i], properties); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1995 if (refreshOccurred) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1996 return; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1997 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1998 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1999 } finally { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2000 refreshOccurred = previousValue; |
10 | 2001 } |
2002 } | |
2003 | |
2004 /** | |
2005 * Updates the given element's presentation when one or more of its | |
2006 * properties changes. Only the given element is updated. | |
2007 * <p> | |
2008 * This does not handle structural changes (e.g. addition or removal of | |
2009 * elements), and does not update any other related elements (e.g. child | |
2010 * elements). To handle structural changes, use the <code>refresh</code> | |
2011 * methods instead. | |
2012 * </p> | |
2013 * <p> | |
2014 * This should be called when an element has changed in the model, in order | |
2015 * to have the viewer accurately reflect the model. This method only affects | |
2016 * the viewer, not the model. | |
2017 * </p> | |
2018 * <p> | |
2019 * Specifying which properties are affected may allow the viewer to optimize | |
2020 * the update. For example, if the label provider is not affected by changes | |
2021 * to any of these properties, an update may not actually be required. | |
2022 * Specifying <code>properties</code> as <code>null</code> forces a full | |
2023 * update of the element. | |
2024 * </p> | |
2025 * <p> | |
2026 * If the viewer has a sorter which is affected by a change to one of the | |
2027 * properties, the element's position is updated to maintain the sort order. | |
2028 * Note that resorting does not happen if <code>properties</code> is | |
2029 * <code>null</code>. | |
2030 * </p> | |
2031 * <p> | |
2032 * If the viewer has a filter which is affected by a change to one of the | |
2033 * properties, the element may appear or disappear if the change affects | |
2034 * whether or not the element is filtered out. | |
2035 * </p> | |
2036 * | |
2037 * @param element | |
2038 * the element | |
2039 * @param properties | |
2040 * the properties that have changed, or <code>null</code> to | |
2041 * indicate unknown | |
2042 */ | |
2043 public void update(Object element, String[] properties) { | |
2044 Assert.isNotNull(element); | |
2045 Widget[] items = findItems(element); | |
2046 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2047 bool mayExitEarly = !refreshOccurred; |
10 | 2048 for (int i = 0; i < items.length; i++) { |
2049 internalUpdate(items[i], element, properties); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2050 if (mayExitEarly && refreshOccurred) { |
90 | 2051 // detected a change from refreshOccurred is false to refreshOccurred is true |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2052 return; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2053 } |
10 | 2054 } |
2055 } | |
2056 | |
2057 /** | |
2058 * Updates the given element's presentation when one or more of its | |
2059 * properties changes. Only the given element is updated. | |
2060 * <p> | |
2061 * EXPERIMENTAL. Not to be used except by JDT. | |
2062 * This method was added to support JDT's explorations | |
2063 * into grouping by working sets, which requires viewers to support multiple | |
2064 * equal elements. See bug 76482 for more details. This support will | |
2065 * likely be removed in Eclipse 3.3 in favor of proper support for | |
2066 * multiple equal elements (which was implemented for AbtractTreeViewer in 3.2). | |
2067 * </p> | |
2068 * @param widget | |
2069 * the widget for the element | |
2070 * @param element | |
2071 * the element | |
2072 * @param properties | |
2073 * the properties that have changed, or <code>null</code> to | |
2074 * indicate unknown | |
2075 */ | |
2076 protected void internalUpdate(Widget widget, Object element, String[] properties) { | |
2077 bool needsRefilter_ = false; | |
2078 if (properties !is null) { | |
2079 for (int i = 0; i < properties.length; ++i) { | |
2080 needsRefilter_ = needsRefilter(element, properties[i]); | |
2081 if (needsRefilter_) { | |
2082 break; | |
2083 } | |
2084 } | |
2085 } | |
2086 if (needsRefilter_) { | |
2087 preservingSelection(new class Runnable { | |
2088 public void run() { | |
2089 internalRefresh(getRoot()); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2090 refreshOccurred = true; |
10 | 2091 } |
2092 }); | |
2093 return; | |
2094 } | |
2095 | |
2096 bool needsUpdate; | |
2097 if (properties is null) { | |
2098 needsUpdate = true; | |
2099 } else { | |
2100 needsUpdate = false; | |
2101 IBaseLabelProvider labelProvider = getLabelProvider(); | |
2102 for (int i = 0; i < properties.length; ++i) { | |
2103 needsUpdate = labelProvider.isLabelProperty(element, properties[i]); | |
2104 if (needsUpdate) { | |
2105 break; | |
2106 } | |
2107 } | |
2108 } | |
2109 if (needsUpdate) { | |
2110 updateItem(widget, element); | |
2111 } | |
2112 } | |
2113 | |
2114 /** | |
2115 * Copies attributes of the given element into the given widget. | |
2116 * <p> | |
2117 * This method is internal to the framework; subclassers should not call | |
2118 * this method. Calls <code>doUpdateItem(widget, element, true)</code>. | |
2119 * </p> | |
2120 * | |
2121 * @param widget | |
2122 * the widget | |
2123 * @param element | |
2124 * the element | |
2125 */ | |
2126 protected final void updateItem(Widget widget, Object element) { | |
2127 SafeRunnable.run(new UpdateItemSafeRunnable(widget, element, true)); | |
2128 } | |
2129 | |
2130 /** | |
2131 * Updates the selection of this viewer. | |
2132 * <p> | |
2133 * This framework method should be called when the selection in the viewer | |
2134 * widget changes. | |
2135 * </p> | |
2136 * <p> | |
2137 * The default implementation of this method notifies all selection change | |
2138 * listeners recorded in an internal state variable. Overriding this method | |
2139 * is generally not required; however, if overriding in a subclass, | |
2140 * <code>super.updateSelection</code> must be invoked. | |
2141 * </p> | |
2142 * | |
2143 * @param selection | |
2144 * the selection, or <code>null</code> if none | |
2145 */ | |
2146 protected void updateSelection(ISelection selection) { | |
2147 SelectionChangedEvent event = new SelectionChangedEvent(this, selection); | |
2148 fireSelectionChanged(event); | |
2149 } | |
2150 | |
2151 /** | |
2152 * Returns whether this structured viewer is configured to use an internal | |
2153 * map to speed up the mapping between elements and DWT items. | |
2154 * <p> | |
2155 * The default implementation of this framework method checks whether the | |
2156 * internal map has been initialized. | |
2157 * </p> | |
2158 * | |
2159 * @return <code>true</code> if the element map is enabled, and | |
2160 * <code>false</code> if disabled | |
2161 */ | |
2162 protected bool usingElementMap() { | |
2163 return elementMap !is null; | |
2164 } | |
2165 | |
2166 /* (non-Javadoc) | |
2167 * @see dwtx.jface.viewers.ContentViewer#setLabelProvider(dwtx.jface.viewers.IBaseLabelProvider) | |
2168 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2169 public override void setLabelProvider(IBaseLabelProvider labelProvider) { |
10 | 2170 if ( null !is cast(IColorProvider)labelProvider || null !is cast(IFontProvider)labelProvider ) { |
2171 colorAndFontCollector = new ColorAndFontCollectorWithProviders(labelProvider); | |
2172 } else { | |
2173 colorAndFontCollector = new ColorAndFontCollector(); | |
2174 } | |
2175 super.setLabelProvider(labelProvider); | |
2176 | |
2177 } | |
2178 | |
2179 /** | |
2180 * Build a label up for the element using the supplied label provider. | |
2181 * @param updateLabel The ViewerLabel to collect the result in | |
2182 * @param element The element being decorated. | |
2183 */ | |
2184 protected void buildLabel(ViewerLabel updateLabel, Object element){ | |
2185 | |
2186 if ( auto vlp = cast(IViewerLabelProvider)getLabelProvider() ) { | |
2187 IViewerLabelProvider itemProvider = cast(IViewerLabelProvider) getLabelProvider(); | |
2188 itemProvider.updateLabel(updateLabel, element); | |
2189 | |
2190 colorAndFontCollector.setUsedDecorators(); | |
2191 | |
2192 if(updateLabel.hasNewBackground()) { | |
2193 colorAndFontCollector.setBackground(updateLabel.getBackground()); | |
2194 } | |
2195 | |
2196 if(updateLabel.hasNewForeground()) { | |
2197 colorAndFontCollector.setForeground(updateLabel.getForeground()); | |
2198 } | |
2199 | |
2200 if(updateLabel.hasNewFont()) { | |
2201 colorAndFontCollector.setFont(updateLabel.getFont()); | |
2202 } | |
2203 return; | |
2204 | |
2205 } | |
2206 | |
2207 if( cast(ILabelProvider) getLabelProvider() ){ | |
2208 ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider(); | |
2209 updateLabel.setText(labelProvider.getText(element)); | |
2210 updateLabel.setImage(labelProvider.getImage(element)); | |
2211 } | |
2212 | |
2213 } | |
2214 | |
2215 /** | |
2216 * Build a label up for the element using the supplied label provider. | |
2217 * @param updateLabel The ViewerLabel to collect the result in | |
2218 * @param element The element being decorated. | |
2219 * @param labelProvider ILabelProvider the labelProvider for the receiver. | |
2220 */ | |
2221 void buildLabel(ViewerLabel updateLabel, Object element, IViewerLabelProvider labelProvider){ | |
2222 | |
2223 labelProvider.updateLabel(updateLabel, element); | |
2224 | |
2225 colorAndFontCollector.setUsedDecorators(); | |
2226 | |
2227 if(updateLabel.hasNewBackground()) { | |
2228 colorAndFontCollector.setBackground(updateLabel.getBackground()); | |
2229 } | |
2230 | |
2231 if(updateLabel.hasNewForeground()) { | |
2232 colorAndFontCollector.setForeground(updateLabel.getForeground()); | |
2233 } | |
2234 | |
2235 if(updateLabel.hasNewFont()) { | |
2236 colorAndFontCollector.setFont(updateLabel.getFont()); | |
2237 } | |
2238 | |
2239 } | |
2240 | |
2241 /** | |
2242 * Build a label up for the element using the supplied label provider. | |
2243 * @param updateLabel The ViewerLabel to collect the result in | |
2244 * @param elementPath The path of the element being decorated. | |
2245 * @param labelProvider ILabelProvider the labelProvider for the receiver. | |
2246 */ | |
2247 void buildLabel(ViewerLabel updateLabel, TreePath elementPath,ITreePathLabelProvider labelProvider){ | |
2248 | |
2249 labelProvider.updateLabel(updateLabel, elementPath); | |
2250 | |
2251 colorAndFontCollector.setUsedDecorators(); | |
2252 | |
2253 if(updateLabel.hasNewBackground()) { | |
2254 colorAndFontCollector.setBackground(updateLabel.getBackground()); | |
2255 } | |
2256 | |
2257 if(updateLabel.hasNewForeground()) { | |
2258 colorAndFontCollector.setForeground(updateLabel.getForeground()); | |
2259 } | |
2260 | |
2261 if(updateLabel.hasNewFont()) { | |
2262 colorAndFontCollector.setFont(updateLabel.getFont()); | |
2263 } | |
2264 | |
2265 } | |
2266 | |
2267 /** | |
2268 * Build a label up for the element using the supplied label provider. | |
2269 * @param updateLabel The ViewerLabel to collect the result in | |
2270 * @param element The element being decorated. | |
2271 * @param labelProvider ILabelProvider the labelProvider for the receiver. | |
2272 */ | |
2273 void buildLabel(ViewerLabel updateLabel, Object element,ILabelProvider labelProvider){ | |
2274 updateLabel.setText(labelProvider.getText(element)); | |
2275 updateLabel.setImage(labelProvider.getImage(element)); | |
2276 } | |
2277 | |
2278 /** | |
2279 * Get the ColorAndFontCollector for the receiver. | |
2280 * @return ColorAndFontCollector | |
2281 * @since 3.1 | |
2282 */ | |
2283 protected ColorAndFontCollector getColorAndFontCollector() { | |
2284 return colorAndFontCollector; | |
2285 } | |
2286 | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2287 protected override void handleDispose(DisposeEvent event) { |
10 | 2288 super.handleDispose(event); |
2289 sorter = null; | |
2290 comparer = null; | |
2291 if (filters !is null) | |
2292 filters.clear(); | |
2293 elementMap = newHashtable(1); | |
2294 openListeners.clear(); | |
2295 doubleClickListeners.clear(); | |
2296 colorAndFontCollector.clear(); | |
2297 postSelectionChangedListeners.clear(); | |
2298 } | |
2299 | |
2300 } |