comparison dwtx/jface/viewers/TableViewer.d @ 10:b6c35faf97c8

Viewers
author Frank Benoit <benoit@tionex.de>
date Mon, 31 Mar 2008 00:47:19 +0200
parents
children cf7413989c65
comparison
equal deleted inserted replaced
9:6c14e54dfc11 10:b6c35faf97c8
1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
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 <tom.schindl@bestsolution.at> - concept of ViewerRow,
11 * fix for 159597, refactoring (bug 153993),
12 * widget-independency (bug 154329), fix for 187826, 191468
13 * Port to the D programming language:
14 * Frank Benoit <benoit@tionex.de>
15 *******************************************************************************/
16
17 module dwtx.jface.viewers.TableViewer;
18
19 import dwtx.jface.viewers.AbstractTableViewer;
20 import dwtx.jface.viewers.TableViewerRow;
21 import dwtx.jface.viewers.ColumnViewerEditor;
22 import dwtx.jface.viewers.ISelection;
23 import dwtx.jface.viewers.ViewerRow;
24 import dwtx.jface.viewers.TableViewerEditor;
25 import dwtx.jface.viewers.ColumnViewerEditorActivationStrategy;
26
27 import dwt.DWT;
28 import dwt.graphics.Point;
29 import dwt.widgets.Composite;
30 import dwt.widgets.Control;
31 import dwt.widgets.Item;
32 import dwt.widgets.Table;
33 import dwt.widgets.TableItem;
34 import dwt.widgets.Widget;
35 import dwtx.core.runtime.Assert;
36
37 import dwt.dwthelper.utils;
38 import dwt.dwthelper.Runnable;
39
40 /**
41 * A concrete viewer based on a DWT <code>Table</code> control.
42 * <p>
43 * This class is not intended to be subclassed outside the viewer framework. It
44 * is designed to be instantiated with a pre-existing DWT table control and
45 * configured with a domain-specific content provider, table label provider,
46 * element filter (optional), and element sorter (optional).
47 * </p>
48 * <p>
49 * Label providers for table viewers must implement either the
50 * <code>ITableLabelProvider</code> or the <code>ILabelProvider</code>
51 * interface (see <code>TableViewer.setLabelProvider</code> for more details).
52 * </p>
53 * <p>
54 * As of 3.1 the TableViewer now supports the DWT.VIRTUAL flag. If the
55 * underlying table is DWT.VIRTUAL, the content provider may implement
56 * {@link ILazyContentProvider} instead of {@link IStructuredContentProvider}.
57 * Note that in this case, the viewer does not support sorting or filtering.
58 * Also note that in this case, the Widget based APIs may return null if the
59 * element is not specified or not created yet.
60 * </p>
61 * <p>
62 * Users of DWT.VIRTUAL should also avoid using getItems() from the Table within
63 * the TreeViewer as this does not necessarily generate a callback for the
64 * TreeViewer to populate the items. It also has the side effect of creating all
65 * of the items thereby eliminating the performance improvements of DWT.VIRTUAL.
66 * </p>
67 *
68 * @see DWT#VIRTUAL
69 * @see #doFindItem(Object)
70 * @see #internalRefresh(Object, bool)
71 */
72 public class TableViewer : AbstractTableViewer {
73
74 public alias AbstractTableViewer.preservingSelection preservingSelection;
75
76 /**
77 * This viewer's table control.
78 */
79 private Table table;
80
81 /**
82 * The cached row which is reused all over
83 */
84 private TableViewerRow cachedRow;
85
86 /**
87 * Creates a table viewer on a newly-created table control under the given
88 * parent. The table control is created using the DWT style bits
89 * <code>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>. The
90 * viewer has no input, no content provider, a default label provider, no
91 * sorter, and no filters. The table has no columns.
92 *
93 * @param parent
94 * the parent control
95 */
96 public this(Composite parent) {
97 this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
98 }
99
100 /**
101 * Creates a table viewer on a newly-created table control under the given
102 * parent. The table control is created using the given style bits. The
103 * viewer has no input, no content provider, a default label provider, no
104 * sorter, and no filters. The table has no columns.
105 *
106 * @param parent
107 * the parent control
108 * @param style
109 * DWT style bits
110 */
111 public this(Composite parent, int style) {
112 this(new Table(parent, style));
113 }
114
115 /**
116 * Creates a table viewer on the given table control. The viewer has no
117 * input, no content provider, a default label provider, no sorter, and no
118 * filters.
119 *
120 * @param table
121 * the table control
122 */
123 public this(Table table) {
124 this.table = table;
125 hookControl(table);
126 }
127
128 public Control getControl() {
129 return table;
130 }
131
132 /**
133 * Returns this table viewer's table control.
134 *
135 * @return the table control
136 */
137 public Table getTable() {
138 return table;
139 }
140
141 protected ColumnViewerEditor createViewerEditor() {
142 return new TableViewerEditor(this,null,new ColumnViewerEditorActivationStrategy(this),ColumnViewerEditor.DEFAULT);
143 }
144
145 /**
146 * <p>
147 * Sets a new selection for this viewer and optionally makes it visible. The
148 * TableViewer implementation of this method is inefficient for the
149 * ILazyContentProvider as lookup is done by indices rather than elements
150 * and may require population of the entire table in worse case.
151 * </p>
152 * <p>
153 * Use Table#setSelection(int[] indices) and Table#showSelection() if you
154 * wish to set selection more efficiently when using a ILazyContentProvider.
155 * </p>
156 *
157 * @param selection
158 * the new selection
159 * @param reveal
160 * <code>true</code> if the selection is to be made visible,
161 * and <code>false</code> otherwise
162 * @see Table#setSelection(int[])
163 * @see Table#showSelection()
164 */
165 public void setSelection(ISelection selection, bool reveal) {
166 super.setSelection(selection, reveal);
167 }
168
169 protected ViewerRow getViewerRowFromItem(Widget item) {
170 if( cachedRow is null ) {
171 cachedRow = new TableViewerRow(cast(TableItem) item);
172 } else {
173 cachedRow.setItem(cast(TableItem) item);
174 }
175
176 return cachedRow;
177 }
178
179 /**
180 * Create a new row with style at index
181 *
182 * @param style
183 * @param rowIndex
184 * @return ViewerRow
185 * @since 3.3
186 */
187 protected ViewerRow internalCreateNewRowPart(int style, int rowIndex) {
188 TableItem item;
189
190 if (rowIndex >= 0) {
191 item = new TableItem(table, style, rowIndex);
192 } else {
193 item = new TableItem(table, style);
194 }
195
196 return getViewerRowFromItem(item);
197 }
198
199 protected Item getItemAt(Point p) {
200 TableItem[] selection = table.getSelection();
201
202 if( selection.length is 1 ) {
203 int columnCount = table.getColumnCount();
204
205 for( int i = 0; i < columnCount; i++ ) {
206 if( selection[0].getBounds(i).contains(p) ) {
207 return selection[0];
208 }
209 }
210 }
211
212 return table.getItem(p);
213 }
214
215 // Methods to provide widget independency
216
217 protected int doGetItemCount() {
218 return table.getItemCount();
219 }
220
221 protected int doIndexOf(Item item) {
222 return table.indexOf(cast(TableItem)item);
223 }
224
225 protected void doSetItemCount(int count) {
226 table.setItemCount(count);
227 }
228
229 protected Item[] doGetItems() {
230 return table.getItems();
231 }
232
233 protected int doGetColumnCount() {
234 return table.getColumnCount();
235 }
236
237 protected Widget doGetColumn(int index) {
238 return table.getColumn(index);
239 }
240
241 protected Item doGetItem(int index) {
242 return table.getItem(index);
243 }
244
245 protected Item[] doGetSelection() {
246 return table.getSelection();
247 }
248
249 protected int[] doGetSelectionIndices() {
250 return table.getSelectionIndices();
251 }
252
253 protected void doClearAll() {
254 table.clearAll();
255 }
256
257 protected void doResetItem(Item item) {
258 TableItem tableItem = cast(TableItem) item;
259 int columnCount = Math.max(1, table.getColumnCount());
260 for (int i = 0; i < columnCount; i++) {
261 tableItem.setText(i, ""); //$NON-NLS-1$
262 if (tableItem.getImage(i) !is null) {
263 tableItem.setImage(i, null);
264 }
265 }
266 }
267
268 protected void doRemove(int start, int end) {
269 table.remove(start, end);
270 }
271
272 protected void doRemoveAll() {
273 table.removeAll();
274 }
275
276 protected void doRemove(int[] indices) {
277 table.remove(indices);
278 }
279
280 protected void doShowItem(Item item) {
281 table.showItem(cast(TableItem)item);
282 }
283
284 protected void doDeselectAll() {
285 table.deselectAll();
286 }
287
288 protected void doSetSelection(Item[] items) {
289 // Assert.isNotNull(items, "Items-Array can not be null"); //$NON-NLS-1$
290
291 TableItem[] t = new TableItem[items.length];
292 System.arraycopy(items, 0, t, 0, t.length);
293
294 table.setSelection(t);
295 }
296
297 protected void doShowSelection() {
298 table.showSelection();
299 }
300
301 protected void doSetSelection(int[] indices) {
302 table.setSelection(indices);
303 }
304
305 protected void doClear(int index) {
306 table.clear(index);
307 }
308
309 protected void doSelect(int[] indices) {
310 table.select(indices);
311 }
312
313 /**
314 * Refreshes this viewer starting with the given element. Labels are updated
315 * as described in <code>refresh(bool updateLabels)</code>. The
316 * methods attempts to preserve the selection.
317 * <p>
318 * Unlike the <code>update</code> methods, this handles structural changes
319 * to the given element (e.g. addition or removal of children). If only the
320 * given element needs updating, it is more efficient to use the
321 * <code>update</code> methods.
322 * </p>
323 *
324 * <p>
325 * Subclasses who can provide this feature can open this method for the
326 * public
327 * </p>
328 *
329 * @param element
330 * the element
331 * @param updateLabels
332 * <code>true</code> to update labels for existing elements,
333 * <code>false</code> to only update labels as needed, assuming
334 * that labels for existing elements are unchanged.
335 * @param reveal
336 * <code>true</code> to make the preserved selection visible
337 * afterwards
338 *
339 * @since 3.3
340 */
341 public void refresh(Object element, bool updateLabels,
342 bool reveal) {
343 if (isBusy())
344 return;
345
346 if( isCellEditorActive() ) {
347 cancelEditing();
348 }
349
350 preservingSelection(new class Runnable {
351 Object element_;
352 bool updateLabels_;
353 this(){
354 element_ = element;
355 updateLabels_ = updateLabels;
356 }
357 public void run() {
358 internalRefresh(element_, updateLabels_);
359 }
360 }, reveal);
361 }
362
363 /**
364 * Refreshes this viewer with information freshly obtained from this
365 * viewer's model. If <code>updateLabels</code> is <code>true</code>
366 * then labels for otherwise unaffected elements are updated as well.
367 * Otherwise, it assumes labels for existing elements are unchanged, and
368 * labels are only obtained as needed (for example, for new elements).
369 * <p>
370 * Calling <code>refresh(true)</code> has the same effect as
371 * <code>refresh()</code>.
372 * <p>
373 * Note that the implementation may still obtain labels for existing
374 * elements even if <code>updateLabels</code> is false. The intent is
375 * simply to allow optimization where possible.
376 *
377 * @param updateLabels
378 * <code>true</code> to update labels for existing elements,
379 * <code>false</code> to only update labels as needed, assuming
380 * that labels for existing elements are unchanged.
381 * @param reveal
382 * <code>true</code> to make the preserved selection visible
383 * afterwards
384 *
385 * @since 3.3
386 */
387 public void refresh(bool updateLabels, bool reveal) {
388 refresh(getRoot(), updateLabels, reveal);
389 }
390 }