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