Mercurial > projects > dwt-mac
comparison dwt/widgets/Tree.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | 649b8e223d5a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:380af2bdd8e5 |
---|---|
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 *******************************************************************************/ | |
11 module dwt.widgets.Tree; | |
12 | |
13 import dwt.dwthelper.utils; | |
14 | |
15 | |
16 import dwt.DWT; | |
17 import dwt.DWTException; | |
18 import dwt.events.SelectionEvent; | |
19 import dwt.events.SelectionListener; | |
20 import dwt.events.TreeListener; | |
21 import dwt.graphics.Color; | |
22 import dwt.graphics.Font; | |
23 import dwt.graphics.Image; | |
24 import dwt.graphics.Point; | |
25 import dwt.graphics.Rectangle; | |
26 import dwt.internal.cocoa.NSBrowserCell; | |
27 import dwt.internal.cocoa.NSButtonCell; | |
28 import dwt.internal.cocoa.NSIndexSet; | |
29 import dwt.internal.cocoa.NSNumber; | |
30 import dwt.internal.cocoa.NSOutlineView; | |
31 import dwt.internal.cocoa.NSRect; | |
32 import dwt.internal.cocoa.NSString; | |
33 import dwt.internal.cocoa.NSTableColumn; | |
34 import dwt.internal.cocoa.NSTableHeaderView; | |
35 import dwt.internal.cocoa.NSTableView; | |
36 import dwt.internal.cocoa.OS; | |
37 import dwt.internal.cocoa.SWTOutlineView; | |
38 import dwt.internal.cocoa.SWTScrollView; | |
39 import dwt.internal.cocoa.SWTTreeItem; | |
40 import dwt.internal.cocoa.id; | |
41 | |
42 /** | |
43 * Instances of this class provide a selectable user interface object | |
44 * that displays a hierarchy of items and issues notification when an | |
45 * item in the hierarchy is selected. | |
46 * <p> | |
47 * The item children that may be added to instances of this class | |
48 * must be of type <code>TreeItem</code>. | |
49 * </p><p> | |
50 * Style <code>VIRTUAL</code> is used to create a <code>Tree</code> whose | |
51 * <code>TreeItem</code>s are to be populated by the client on an on-demand basis | |
52 * instead of up-front. This can provide significant performance improvements for | |
53 * trees that are very large or for which <code>TreeItem</code> population is | |
54 * expensive (for example, retrieving values from an external source). | |
55 * </p><p> | |
56 * Here is an example of using a <code>Tree</code> with style <code>VIRTUAL</code>: | |
57 * <code><pre> | |
58 * final Tree tree = new Tree(parent, DWT.VIRTUAL | DWT.BORDER); | |
59 * tree.setItemCount(20); | |
60 * tree.addListener(DWT.SetData, new Listener() { | |
61 * public void handleEvent(Event event) { | |
62 * TreeItem item = (TreeItem)event.item; | |
63 * TreeItem parentItem = item.getParentItem(); | |
64 * String text = null; | |
65 * if (parentItem is null) { | |
66 * text = "node " + tree.indexOf(item); | |
67 * } else { | |
68 * text = parentItem.getText() + " - " + parentItem.indexOf(item); | |
69 * } | |
70 * item.setText(text); | |
71 * System.out.println(text); | |
72 * item.setItemCount(10); | |
73 * } | |
74 * }); | |
75 * </pre></code> | |
76 * </p><p> | |
77 * Note that although this class is a subclass of <code>Composite</code>, | |
78 * it does not make sense to add <code>Control</code> children to it, | |
79 * or set a layout on it. | |
80 * </p><p> | |
81 * <dl> | |
82 * <dt><b>Styles:</b></dt> | |
83 * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL</dd> | |
84 * <dt><b>Events:</b></dt> | |
85 * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd> | |
86 * </dl> | |
87 * </p><p> | |
88 * Note: Only one of the styles SINGLE and MULTI may be specified. | |
89 * </p><p> | |
90 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
91 * </p> | |
92 */ | |
93 public class Tree extends Composite { | |
94 NSTableColumn firstColumn, checkColumn; | |
95 NSTableHeaderView headerView; | |
96 TreeItem [] items; | |
97 int itemCount; | |
98 TreeColumn [] columns; | |
99 TreeColumn sortColumn; | |
100 int columnCount; | |
101 int sortDirection; | |
102 bool ignoreExpand, ignoreSelect; | |
103 | |
104 /** | |
105 * Constructs a new instance of this class given its parent | |
106 * and a style value describing its behavior and appearance. | |
107 * <p> | |
108 * The style value is either one of the style constants defined in | |
109 * class <code>DWT</code> which is applicable to instances of this | |
110 * class, or must be built by <em>bitwise OR</em>'ing together | |
111 * (that is, using the <code>int</code> "|" operator) two or more | |
112 * of those <code>DWT</code> style constants. The class description | |
113 * lists the style constants that are applicable to the class. | |
114 * Style bits are also inherited from superclasses. | |
115 * </p> | |
116 * | |
117 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
118 * @param style the style of control to construct | |
119 * | |
120 * @exception IllegalArgumentException <ul> | |
121 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
122 * </ul> | |
123 * @exception DWTException <ul> | |
124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
125 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
126 * </ul> | |
127 * | |
128 * @see DWT#SINGLE | |
129 * @see DWT#MULTI | |
130 * @see DWT#CHECK | |
131 * @see Widget#checkSubclass | |
132 * @see Widget#getStyle | |
133 */ | |
134 public Tree (Composite parent, int style) { | |
135 super (parent, checkStyle (style)); | |
136 } | |
137 | |
138 void _addListener (int eventType, Listener listener) { | |
139 super._addListener (eventType, listener); | |
140 for (int i = 0; i < items.length; i++) { | |
141 if (items [i] !is null) items [i].width = -1; | |
142 } | |
143 } | |
144 | |
145 TreeItem _getItem (TreeItem parentItem, int index) { | |
146 int count; | |
147 TreeItem[] items; | |
148 if (parentItem !is null) { | |
149 count = parentItem.itemCount; | |
150 items = parentItem.items; | |
151 } else { | |
152 count = this.itemCount; | |
153 items = this.items; | |
154 } | |
155 if (index < 0 || index >= count) return null; | |
156 TreeItem item = items [index]; | |
157 if (item !is null || (style & DWT.VIRTUAL) is 0) return item; | |
158 item = new TreeItem (this, parentItem, DWT.NONE, index, false); | |
159 items [index] = item; | |
160 return item; | |
161 } | |
162 | |
163 /** | |
164 * Adds the listener to the collection of listeners who will | |
165 * be notified when the user changes the receiver's selection, by sending | |
166 * it one of the messages defined in the <code>SelectionListener</code> | |
167 * interface. | |
168 * <p> | |
169 * When <code>widgetSelected</code> is called, the item field of the event object is valid. | |
170 * If the receiver has the <code>DWT.CHECK</code> style and the check selection changes, | |
171 * the event object detail field contains the value <code>DWT.CHECK</code>. | |
172 * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked. | |
173 * The item field of the event object is valid for default selection, but the detail field is not used. | |
174 * </p> | |
175 * | |
176 * @param listener the listener which should be notified when the user changes the receiver's selection | |
177 * | |
178 * @exception IllegalArgumentException <ul> | |
179 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
180 * </ul> | |
181 * @exception DWTException <ul> | |
182 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
183 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
184 * </ul> | |
185 * | |
186 * @see SelectionListener | |
187 * @see #removeSelectionListener | |
188 * @see SelectionEvent | |
189 */ | |
190 public void addSelectionListener(SelectionListener listener) { | |
191 checkWidget (); | |
192 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); | |
193 TypedListener typedListener = new TypedListener (listener); | |
194 addListener (DWT.Selection, typedListener); | |
195 addListener (DWT.DefaultSelection, typedListener); | |
196 } | |
197 | |
198 /** | |
199 * Adds the listener to the collection of listeners who will | |
200 * be notified when an item in the receiver is expanded or collapsed | |
201 * by sending it one of the messages defined in the <code>TreeListener</code> | |
202 * interface. | |
203 * | |
204 * @param listener the listener which should be notified | |
205 * | |
206 * @exception IllegalArgumentException <ul> | |
207 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
208 * </ul> | |
209 * @exception DWTException <ul> | |
210 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
211 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
212 * </ul> | |
213 * | |
214 * @see TreeListener | |
215 * @see #removeTreeListener | |
216 */ | |
217 public void addTreeListener(TreeListener listener) { | |
218 checkWidget (); | |
219 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); | |
220 TypedListener typedListener = new TypedListener (listener); | |
221 addListener (DWT.Expand, typedListener); | |
222 addListener (DWT.Collapse, typedListener); | |
223 } | |
224 | |
225 bool checkData (TreeItem item, bool redraw) { | |
226 if (item.cached) return true; | |
227 if ((style & DWT.VIRTUAL) !is 0) { | |
228 item.cached = true; | |
229 Event event = new Event (); | |
230 TreeItem parentItem = item.getParentItem (); | |
231 event.item = item; | |
232 event.index = parentItem is null ? indexOf (item) : parentItem.indexOf (item); | |
233 // ignoreRedraw = true; | |
234 sendEvent (DWT.SetData, event); | |
235 //widget could be disposed at this point | |
236 // ignoreRedraw = false; | |
237 if (isDisposed () || item.isDisposed ()) return false; | |
238 if (redraw) { | |
239 // if (!setScrollWidth (item)) item.redraw (OS.kDataBrowserNoItem); | |
240 } | |
241 } | |
242 return true; | |
243 } | |
244 | |
245 static int checkStyle (int style) { | |
246 /* | |
247 * Feature in Windows. Even when WS_HSCROLL or | |
248 * WS_VSCROLL is not specified, Windows creates | |
249 * trees and tables with scroll bars. The fix | |
250 * is to set H_SCROLL and V_SCROLL. | |
251 * | |
252 * NOTE: This code appears on all platforms so that | |
253 * applications have consistent scroll bar behavior. | |
254 */ | |
255 if ((style & DWT.NO_SCROLL) is 0) { | |
256 style |= DWT.H_SCROLL | DWT.V_SCROLL; | |
257 } | |
258 return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); | |
259 } | |
260 | |
261 protected void checkSubclass () { | |
262 if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); | |
263 } | |
264 | |
265 void clear (TreeItem parentItem, int index, bool all) { | |
266 // int [] ids = parentItem is null ? childIds : parentItem.childIds; | |
267 // TreeItem item = _getItem (ids [index], false); | |
268 // if (item !is null) { | |
269 // item.clear(); | |
270 // if (all) { | |
271 // clearAll (item, true); | |
272 // } else { | |
273 // int container = parentItem is null ? OS.kDataBrowserNoItem : parentItem.id; | |
274 // OS.UpdateDataBrowserItems (handle, container, 1, new int[] {item.id}, OS.kDataBrowserItemNoProperty, OS.kDataBrowserNoItem); | |
275 // } | |
276 // } | |
277 } | |
278 | |
279 void clearAll (TreeItem parentItem, bool all) { | |
280 // bool update = !inClearAll; | |
281 // int count = getItemCount (parentItem); | |
282 // if (count is 0) return; | |
283 // inClearAll = true; | |
284 // int [] ids = parentItem is null ? childIds : parentItem.childIds; | |
285 // for (int i=0; i<count; i++) { | |
286 // TreeItem item = _getItem (ids [i], false); | |
287 // if (item !is null) { | |
288 // item.clear (); | |
289 // if (all) clearAll (item, true); | |
290 // } | |
291 // } | |
292 // if (update) { | |
293 // OS.UpdateDataBrowserItems (handle, 0, 0, null, OS.kDataBrowserItemNoProperty, OS.kDataBrowserNoItem); | |
294 // inClearAll = false; | |
295 // } | |
296 } | |
297 | |
298 /** | |
299 * Clears the item at the given zero-relative index in the receiver. | |
300 * The text, icon and other attributes of the item are set to the default | |
301 * value. If the tree was created with the <code>DWT.VIRTUAL</code> style, | |
302 * these attributes are requested again as needed. | |
303 * | |
304 * @param index the index of the item to clear | |
305 * @param all <code>true</code> if all child items of the indexed item should be | |
306 * cleared recursively, and <code>false</code> otherwise | |
307 * | |
308 * @exception IllegalArgumentException <ul> | |
309 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> | |
310 * </ul> | |
311 * @exception DWTException <ul> | |
312 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
313 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
314 * </ul> | |
315 * | |
316 * @see DWT#VIRTUAL | |
317 * @see DWT#SetData | |
318 * | |
319 * @since 3.2 | |
320 */ | |
321 public void clear (int index, bool all) { | |
322 checkWidget (); | |
323 int count = getItemCount (); | |
324 if (index < 0 || index >= count) error (DWT.ERROR_INVALID_RANGE); | |
325 clear (null, index, all); | |
326 } | |
327 | |
328 /** | |
329 * Clears all the items in the receiver. The text, icon and other | |
330 * attributes of the items are set to their default values. If the | |
331 * tree was created with the <code>DWT.VIRTUAL</code> style, these | |
332 * attributes are requested again as needed. | |
333 * | |
334 * @param all <code>true</code> if all child items should be cleared | |
335 * recursively, and <code>false</code> otherwise | |
336 * | |
337 * @exception DWTException <ul> | |
338 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
339 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
340 * </ul> | |
341 * | |
342 * @see DWT#VIRTUAL | |
343 * @see DWT#SetData | |
344 * | |
345 * @since 3.2 | |
346 */ | |
347 public void clearAll (bool all) { | |
348 checkWidget (); | |
349 clearAll (null, all); | |
350 } | |
351 | |
352 public Point computeSize (int wHint, int hHint, bool changed) { | |
353 checkWidget (); | |
354 int width = 0, height = 0; | |
355 if (wHint is DWT.DEFAULT) { | |
356 if (columnCount !is 0) { | |
357 for (int i=0; i<columnCount; i++) { | |
358 width += columns [i].getWidth (); | |
359 } | |
360 } else { | |
361 // int levelIndent = DISCLOSURE_COLUMN_LEVEL_INDENT; | |
362 // if (OS.VERSION >= 0x1040) { | |
363 // float [] metric = new float [1]; | |
364 // OS.DataBrowserGetMetric (handle, OS.kDataBrowserMetricDisclosureColumnPerDepthGap, null, metric); | |
365 // levelIndent = (int) metric [0]; | |
366 // } | |
367 // GC gc = new GC (this); | |
368 // width = calculateWidth (childIds, gc, true, 0, levelIndent); | |
369 // gc.dispose (); | |
370 // width += getInsetWidth (column_id, true); | |
371 } | |
372 if ((style & DWT.CHECK) !is 0) width += getCheckColumnWidth (); | |
373 } else { | |
374 width = wHint; | |
375 } | |
376 if (hHint is DWT.DEFAULT) { | |
377 height = ((NSTableView)view).numberOfRows() * getItemHeight () + getHeaderHeight(); | |
378 } else { | |
379 height = hHint; | |
380 } | |
381 if (width <= 0) width = DEFAULT_WIDTH; | |
382 if (height <= 0) height = DEFAULT_HEIGHT; | |
383 Rectangle rect = computeTrim (0, 0, width, height); | |
384 return new Point (rect.width, rect.height); | |
385 } | |
386 | |
387 void createHandle () { | |
388 SWTScrollView scrollWidget = (SWTScrollView)new SWTScrollView().alloc(); | |
389 scrollWidget.initWithFrame(new NSRect ()); | |
390 scrollWidget.setHasHorizontalScroller(true); | |
391 scrollWidget.setHasVerticalScroller(true); | |
392 scrollWidget.setAutohidesScrollers(true); | |
393 scrollWidget.setBorderType(hasBorder() ? OS.NSBezelBorder : OS.NSNoBorder); | |
394 scrollWidget.setTag(jniRef); | |
395 | |
396 NSOutlineView widget = (NSOutlineView)new SWTOutlineView().alloc(); | |
397 widget.initWithFrame(new NSRect()); | |
398 widget.setAllowsMultipleSelection((style & DWT.MULTI) !is 0); | |
399 widget.setAutoresizesOutlineColumn(false); | |
400 widget.setAutosaveExpandedItems(true); | |
401 widget.setDataSource(widget); | |
402 widget.setDelegate(widget); | |
403 widget.setDoubleAction(OS.sel_sendDoubleSelection); | |
404 if (!hasBorder()) widget.setFocusRingType(OS.NSFocusRingTypeNone); | |
405 widget.setTag(jniRef); | |
406 | |
407 headerView = widget.headerView(); | |
408 headerView.retain(); | |
409 widget.setHeaderView(null); | |
410 | |
411 NSString str = NSString.stringWith(""); | |
412 if ((style & DWT.CHECK) !is 0) { | |
413 checkColumn = (NSTableColumn)new NSTableColumn().alloc(); | |
414 checkColumn.initWithIdentifier(str); | |
415 checkColumn.headerCell().setTitle(str); | |
416 widget.addTableColumn (checkColumn); | |
417 widget.setOutlineTableColumn(checkColumn); | |
418 NSButtonCell cell = (NSButtonCell)new NSButtonCell().alloc().init(); | |
419 checkColumn.setDataCell(cell); | |
420 cell.setButtonType(OS.NSSwitchButton); | |
421 cell.setImagePosition(OS.NSImageOnly); | |
422 cell.setAllowsMixedState(true); | |
423 checkColumn.setWidth(getCheckColumnWidth()); | |
424 checkColumn.setResizingMask(OS.NSTableColumnNoResizing); | |
425 checkColumn.setEditable(false); | |
426 cell.release(); | |
427 } | |
428 | |
429 firstColumn = (NSTableColumn)new NSTableColumn().alloc(); | |
430 firstColumn.initWithIdentifier(str); | |
431 firstColumn.headerCell().setTitle(str); | |
432 widget.addTableColumn (firstColumn); | |
433 widget.setOutlineTableColumn(firstColumn); | |
434 NSBrowserCell cell = (NSBrowserCell)new NSBrowserCell().alloc().init(); | |
435 cell.setLeaf(true); | |
436 firstColumn.setDataCell(cell); | |
437 cell.release(); | |
438 | |
439 scrollView = scrollWidget; | |
440 view = widget; | |
441 scrollView.setDocumentView(widget); | |
442 parent.contentView().addSubview_(scrollView); | |
443 } | |
444 | |
445 void createItem (TreeColumn column, int index) { | |
446 if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE); | |
447 if (index is 0) { | |
448 // first column must be left aligned | |
449 column.style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); | |
450 column.style |= DWT.LEFT; | |
451 } | |
452 if (columnCount is columns.length) { | |
453 TreeColumn [] newColumns = new TreeColumn [columnCount + 4]; | |
454 System.arraycopy (columns, 0, newColumns, 0, columns.length); | |
455 columns = newColumns; | |
456 } | |
457 NSTableColumn nsColumn; | |
458 if (columnCount is 0) { | |
459 //TODO - clear attributes, alignment etc. | |
460 nsColumn = firstColumn; | |
461 firstColumn = null; | |
462 } else { | |
463 //TODO - set attributes, alignment etc. | |
464 NSString str = NSString.stringWith(""); | |
465 nsColumn = (NSTableColumn)new NSTableColumn().alloc(); | |
466 nsColumn.initWithIdentifier(str); | |
467 nsColumn.headerCell().setTitle(str); | |
468 ((NSTableView)view).addTableColumn (nsColumn); | |
469 int checkColumn = (style & DWT.CHECK) !is 0 ? 1 : 0; | |
470 ((NSTableView)view).moveColumn (columnCount + checkColumn, index + checkColumn); | |
471 NSBrowserCell cell = (NSBrowserCell)new NSBrowserCell().alloc().init(); | |
472 cell.setLeaf(true); | |
473 nsColumn.setDataCell(cell); | |
474 cell.release(); | |
475 } | |
476 column.nsColumn = nsColumn; | |
477 nsColumn.headerCell().setTitle(NSString.stringWith("")); | |
478 nsColumn.setWidth(0); | |
479 System.arraycopy (columns, index, columns, index + 1, columnCount++ - index); | |
480 columns [index] = column; | |
481 if (columnCount > 1) { | |
482 for (int i=0; i<items.length; i++) { | |
483 TreeItem item = items [i]; | |
484 if (item !is null) { | |
485 String [] strings = item.strings; | |
486 if (strings !is null) { | |
487 String [] temp = new String [columnCount]; | |
488 System.arraycopy (strings, 0, temp, 0, index); | |
489 System.arraycopy (strings, index, temp, index+1, columnCount-index-1); | |
490 temp [index] = ""; | |
491 item.strings = temp; | |
492 } | |
493 if (index is 0) item.text = ""; | |
494 Image [] images = item.images; | |
495 if (images !is null) { | |
496 Image [] temp = new Image [columnCount]; | |
497 System.arraycopy (images, 0, temp, 0, index); | |
498 System.arraycopy (images, index, temp, index+1, columnCount-index-1); | |
499 item.images = temp; | |
500 } | |
501 if (index is 0) item.image = null; | |
502 Color [] cellBackground = item.cellBackground; | |
503 if (cellBackground !is null) { | |
504 Color [] temp = new Color [columnCount]; | |
505 System.arraycopy (cellBackground, 0, temp, 0, index); | |
506 System.arraycopy (cellBackground, index, temp, index+1, columnCount-index-1); | |
507 item.cellBackground = temp; | |
508 } | |
509 Color [] cellForeground = item.cellForeground; | |
510 if (cellForeground !is null) { | |
511 Color [] temp = new Color [columnCount]; | |
512 System.arraycopy (cellForeground, 0, temp, 0, index); | |
513 System.arraycopy (cellForeground, index, temp, index+1, columnCount-index-1); | |
514 item.cellForeground = temp; | |
515 } | |
516 Font [] cellFont = item.cellFont; | |
517 if (cellFont !is null) { | |
518 Font [] temp = new Font [columnCount]; | |
519 System.arraycopy (cellFont, 0, temp, 0, index); | |
520 System.arraycopy (cellFont, index, temp, index+1, columnCount-index-1); | |
521 item.cellFont = temp; | |
522 } | |
523 } | |
524 } | |
525 } | |
526 } | |
527 | |
528 void createItem (TreeItem item, TreeItem parentItem, int index) { | |
529 int count; | |
530 TreeItem[] items; | |
531 if (parentItem !is null) { | |
532 count = parentItem.itemCount; | |
533 items = parentItem.items; | |
534 } else { | |
535 count = this.itemCount; | |
536 items = this.items; | |
537 } | |
538 if (index is -1) index = count; | |
539 if (!(0 <= index && index <= count)) error (DWT.ERROR_INVALID_RANGE); | |
540 if (count is items.length) { | |
541 TreeItem [] newItems = new TreeItem [items.length + 4]; | |
542 System.arraycopy (items, 0, newItems, 0, items.length); | |
543 items = newItems; | |
544 if (parentItem !is null) { | |
545 parentItem.items = items; | |
546 } else { | |
547 this.items = items; | |
548 } | |
549 } | |
550 System.arraycopy (items, index, items, index + 1, count++ - index); | |
551 items [index] = item; | |
552 item.items = new TreeItem[4]; | |
553 item.createJNIRef(); | |
554 SWTTreeItem handle = (SWTTreeItem)new SWTTreeItem().alloc().init(); | |
555 handle.setTag(item.jniRef); | |
556 item.handle = handle; | |
557 if (parentItem !is null) { | |
558 parentItem.itemCount = count; | |
559 } else { | |
560 this.itemCount = count; | |
561 } | |
562 //TODO ? | |
563 ((NSTableView)view).reloadData(); | |
564 } | |
565 | |
566 void createWidget () { | |
567 super.createWidget (); | |
568 items = new TreeItem [4]; | |
569 columns = new TreeColumn [4]; | |
570 } | |
571 | |
572 Color defaultBackground () { | |
573 return display.getSystemColor (DWT.COLOR_LIST_BACKGROUND); | |
574 } | |
575 | |
576 Color defaultForeground () { | |
577 return display.getSystemColor (DWT.COLOR_LIST_FOREGROUND); | |
578 } | |
579 | |
580 /** | |
581 * Deselects all selected items in the receiver. | |
582 * | |
583 * @exception DWTException <ul> | |
584 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
585 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
586 * </ul> | |
587 */ | |
588 public void deselectAll () { | |
589 checkWidget (); | |
590 NSTableView widget = (NSTableView)view; | |
591 ignoreSelect = true; | |
592 widget.deselectAll(null); | |
593 ignoreSelect = false; | |
594 } | |
595 | |
596 public void deselect (TreeItem item) { | |
597 checkWidget (); | |
598 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
599 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
600 // ignoreSelect = true; | |
601 // /* | |
602 // * Bug in the Macintosh. When the DataBroswer selection flags includes | |
603 // * both kDataBrowserNeverEmptySelectionSet and kDataBrowserSelectOnlyOne, | |
604 // * two items are selected when SetDataBrowserSelectedItems() is called | |
605 // * with kDataBrowserItemsAssign to assign a new seletion despite the fact | |
606 // * that kDataBrowserSelectOnlyOne was specified. The fix is to save and | |
607 // * restore kDataBrowserNeverEmptySelectionSet around each call to | |
608 // * SetDataBrowserSelectedItems(). | |
609 // */ | |
610 // int [] selectionFlags = null; | |
611 // if ((style & DWT.SINGLE) !is 0) { | |
612 // selectionFlags = new int [1]; | |
613 // OS.GetDataBrowserSelectionFlags (handle, selectionFlags); | |
614 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0] & ~OS.kDataBrowserNeverEmptySelectionSet); | |
615 // } | |
616 // OS.SetDataBrowserSelectedItems (handle, 1, new int [] {item.id}, OS.kDataBrowserItemsRemove); | |
617 // if ((style & DWT.SINGLE) !is 0) { | |
618 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0]); | |
619 // } | |
620 // ignoreSelect = false; | |
621 } | |
622 | |
623 | |
624 void destroyItem (TreeColumn column) { | |
625 int index = 0; | |
626 while (index < columnCount) { | |
627 if (columns [index] is column) break; | |
628 index++; | |
629 } | |
630 for (int i=0; i<items.length; i++) { | |
631 TreeItem item = items [i]; | |
632 if (item !is null) { | |
633 if (columnCount <= 1) { | |
634 item.strings = null; | |
635 item.images = null; | |
636 item.cellBackground = null; | |
637 item.cellForeground = null; | |
638 item.cellFont = null; | |
639 } else { | |
640 if (item.strings !is null) { | |
641 String [] strings = item.strings; | |
642 if (index is 0) { | |
643 item.text = strings [1] !is null ? strings [1] : ""; | |
644 } | |
645 String [] temp = new String [columnCount - 1]; | |
646 System.arraycopy (strings, 0, temp, 0, index); | |
647 System.arraycopy (strings, index + 1, temp, index, columnCount - 1 - index); | |
648 item.strings = temp; | |
649 } else { | |
650 if (index is 0) item.text = ""; | |
651 } | |
652 if (item.images !is null) { | |
653 Image [] images = item.images; | |
654 if (index is 0) item.image = images [1]; | |
655 Image [] temp = new Image [columnCount - 1]; | |
656 System.arraycopy (images, 0, temp, 0, index); | |
657 System.arraycopy (images, index + 1, temp, index, columnCount - 1 - index); | |
658 item.images = temp; | |
659 } else { | |
660 if (index is 0) item.image = null; | |
661 } | |
662 if (item.cellBackground !is null) { | |
663 Color [] cellBackground = item.cellBackground; | |
664 Color [] temp = new Color [columnCount - 1]; | |
665 System.arraycopy (cellBackground, 0, temp, 0, index); | |
666 System.arraycopy (cellBackground, index + 1, temp, index, columnCount - 1 - index); | |
667 item.cellBackground = temp; | |
668 } | |
669 if (item.cellForeground !is null) { | |
670 Color [] cellForeground = item.cellForeground; | |
671 Color [] temp = new Color [columnCount - 1]; | |
672 System.arraycopy (cellForeground, 0, temp, 0, index); | |
673 System.arraycopy (cellForeground, index + 1, temp, index, columnCount - 1 - index); | |
674 item.cellForeground = temp; | |
675 } | |
676 if (item.cellFont !is null) { | |
677 Font [] cellFont = item.cellFont; | |
678 Font [] temp = new Font [columnCount - 1]; | |
679 System.arraycopy (cellFont, 0, temp, 0, index); | |
680 System.arraycopy (cellFont, index + 1, temp, index, columnCount - 1 - index); | |
681 item.cellFont = temp; | |
682 } | |
683 } | |
684 } | |
685 } | |
686 // if (columnCount is 1) { | |
687 // column_id = column.id; idCount = 0; | |
688 // DataBrowserListViewHeaderDesc desc = new DataBrowserListViewHeaderDesc (); | |
689 // desc.version = OS.kDataBrowserListViewLatestHeaderDesc; | |
690 // short [] width = new short [1]; | |
691 // OS.GetDataBrowserTableViewNamedColumnWidth (handle, column_id, width); | |
692 // desc.minimumWidth = desc.maximumWidth = width [0]; | |
693 // int str = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, null, 0); | |
694 // desc.titleString = str; | |
695 // OS.SetDataBrowserListViewHeaderDesc (handle, column_id, desc); | |
696 // OS.CFRelease (str); | |
697 // } else { | |
698 // int [] disclosure = new int [1]; | |
699 // bool [] expandableRows = new bool [1]; | |
700 // OS.GetDataBrowserListViewDisclosureColumn (handle, disclosure, expandableRows); | |
701 // if (disclosure [0] is column.id) { | |
702 // TreeColumn firstColumn = columns [1]; | |
703 // firstColumn.style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); | |
704 // firstColumn.style |= DWT.LEFT; | |
705 // firstColumn.updateHeader(); | |
706 // OS.SetDataBrowserListViewDisclosureColumn (handle, firstColumn.id, expandableRows [0]); | |
707 // } | |
708 // if (OS.RemoveDataBrowserTableViewColumn (handle, column.id) !is OS.noErr) { | |
709 // error (DWT.ERROR_ITEM_NOT_REMOVED); | |
710 // } | |
711 // } | |
712 System.arraycopy (columns, index + 1, columns, index, --columnCount - index); | |
713 columns [columnCount] = null; | |
714 for (int i=index; i<columnCount; i++) { | |
715 columns [i].sendEvent (DWT.Move); | |
716 } | |
717 } | |
718 | |
719 void destroyItem (TreeItem item) { | |
720 int count; | |
721 TreeItem[] items; | |
722 TreeItem parentItem = item.parentItem; | |
723 if (parentItem !is null) { | |
724 count = parentItem.itemCount; | |
725 items = parentItem.items; | |
726 } else { | |
727 count = this.itemCount; | |
728 items = this.items; | |
729 } | |
730 int index = 0; | |
731 while (index < count) { | |
732 if (items [index] is item) break; | |
733 index++; | |
734 } | |
735 // if (index !is itemCount - 1) fixSelection (index, false); | |
736 System.arraycopy (items, index + 1, items, index, --count - index); | |
737 items [count] = null; | |
738 if (parentItem !is null) { | |
739 parentItem.itemCount = count; | |
740 ((NSOutlineView)view).reloadItem_reloadChildren_(parentItem.handle, true); | |
741 } else { | |
742 this.itemCount = count; | |
743 ((NSOutlineView)view).reloadItem_(null); | |
744 } | |
745 | |
746 //noteNumberOfRowsChanged was causing crashes whenever | |
747 //a TreeItem was disposed. | |
748 //Using reloadItem avoids the crashes. | |
749 //Not sure that this NSTableView function | |
750 //makes sense in an NSOutlineView. | |
751 | |
752 //((NSTableView)view).noteNumberOfRowsChanged(); | |
753 | |
754 // setScrollWidth (true); | |
755 // fixScrollBar (); | |
756 } | |
757 | |
758 | |
759 void fixScrollBar () { | |
760 /* | |
761 * Bug in the Macintosh. For some reason, the data browser does not update | |
762 * the vertical scrollbar when it is scrolled to the bottom and items are | |
763 * removed. The fix is to check if the scrollbar value is bigger the | |
764 * maximum number of visible items and clamp it when needed. | |
765 */ | |
766 // int [] top = new int [1], left = new int [1]; | |
767 // OS.GetDataBrowserScrollPosition (handle, top, left); | |
768 // int maximum = Math.max (0, getItemHeight () * visibleCount - getClientArea ().height); | |
769 // if (top [0] > maximum) { | |
770 // OS.SetDataBrowserScrollPosition (handle, maximum, left [0]); | |
771 // } | |
772 } | |
773 | |
774 int getCheckColumnWidth () { | |
775 return 20; //TODO - compute width | |
776 } | |
777 | |
778 /** | |
779 * Returns the column at the given, zero-relative index in the | |
780 * receiver. Throws an exception if the index is out of range. | |
781 * Columns are returned in the order that they were created. | |
782 * If no <code>TreeColumn</code>s were created by the programmer, | |
783 * this method will throw <code>ERROR_INVALID_RANGE</code> despite | |
784 * the fact that a single column of data may be visible in the tree. | |
785 * This occurs when the programmer uses the tree like a list, adding | |
786 * items but never creating a column. | |
787 * | |
788 * @param index the index of the column to return | |
789 * @return the column at the given index | |
790 * | |
791 * @exception IllegalArgumentException <ul> | |
792 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> | |
793 * </ul> | |
794 * @exception DWTException <ul> | |
795 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
796 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
797 * </ul> | |
798 * | |
799 * @see Tree#getColumnOrder() | |
800 * @see Tree#setColumnOrder(int[]) | |
801 * @see TreeColumn#getMoveable() | |
802 * @see TreeColumn#setMoveable(bool) | |
803 * @see DWT#Move | |
804 * | |
805 * @since 3.1 | |
806 */ | |
807 public TreeColumn getColumn (int index) { | |
808 checkWidget (); | |
809 if (!(0 <=index && index < columnCount)) error (DWT.ERROR_INVALID_RANGE); | |
810 return columns [index]; | |
811 } | |
812 | |
813 /** | |
814 * Returns the number of columns contained in the receiver. | |
815 * If no <code>TreeColumn</code>s were created by the programmer, | |
816 * this value is zero, despite the fact that visually, one column | |
817 * of items may be visible. This occurs when the programmer uses | |
818 * the tree like a list, adding items but never creating a column. | |
819 * | |
820 * @return the number of columns | |
821 * | |
822 * @exception DWTException <ul> | |
823 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
824 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
825 * </ul> | |
826 * | |
827 * @since 3.1 | |
828 */ | |
829 public int getColumnCount () { | |
830 checkWidget (); | |
831 return columnCount; | |
832 } | |
833 | |
834 /** | |
835 * Returns an array of zero-relative integers that map | |
836 * the creation order of the receiver's items to the | |
837 * order in which they are currently being displayed. | |
838 * <p> | |
839 * Specifically, the indices of the returned array represent | |
840 * the current visual order of the items, and the contents | |
841 * of the array represent the creation order of the items. | |
842 * </p><p> | |
843 * Note: This is not the actual structure used by the receiver | |
844 * to maintain its list of items, so modifying the array will | |
845 * not affect the receiver. | |
846 * </p> | |
847 * | |
848 * @return the current visual order of the receiver's items | |
849 * | |
850 * @exception DWTException <ul> | |
851 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
852 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
853 * </ul> | |
854 * | |
855 * @see Tree#setColumnOrder(int[]) | |
856 * @see TreeColumn#getMoveable() | |
857 * @see TreeColumn#setMoveable(bool) | |
858 * @see DWT#Move | |
859 * | |
860 * @since 3.2 | |
861 */ | |
862 public int [] getColumnOrder () { | |
863 checkWidget (); | |
864 int [] order = new int [columnCount]; | |
865 int [] position = new int [1]; | |
866 for (int i=0; i<columnCount; i++) { | |
867 TreeColumn column = columns [i]; | |
868 // OS.GetDataBrowserTableViewColumnPosition (handle, column.id, position); | |
869 // if ((style & DWT.CHECK) !is 0) position [0] -= 1; | |
870 order [position [0]] = i; | |
871 } | |
872 return order; | |
873 } | |
874 | |
875 /** | |
876 * Returns an array of <code>TreeColumn</code>s which are the | |
877 * columns in the receiver. Columns are returned in the order | |
878 * that they were created. If no <code>TreeColumn</code>s were | |
879 * created by the programmer, the array is empty, despite the fact | |
880 * that visually, one column of items may be visible. This occurs | |
881 * when the programmer uses the tree like a list, adding items but | |
882 * never creating a column. | |
883 * <p> | |
884 * Note: This is not the actual structure used by the receiver | |
885 * to maintain its list of items, so modifying the array will | |
886 * not affect the receiver. | |
887 * </p> | |
888 * | |
889 * @return the items in the receiver | |
890 * | |
891 * @exception DWTException <ul> | |
892 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
893 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
894 * </ul> | |
895 * | |
896 * @see Tree#getColumnOrder() | |
897 * @see Tree#setColumnOrder(int[]) | |
898 * @see TreeColumn#getMoveable() | |
899 * @see TreeColumn#setMoveable(bool) | |
900 * @see DWT#Move | |
901 * | |
902 * @since 3.1 | |
903 */ | |
904 public TreeColumn [] getColumns () { | |
905 checkWidget (); | |
906 TreeColumn [] result = new TreeColumn [columnCount]; | |
907 System.arraycopy (columns, 0, result, 0, columnCount); | |
908 return result; | |
909 } | |
910 | |
911 /** | |
912 * Returns the width in pixels of a grid line. | |
913 * | |
914 * @return the width of a grid line in pixels | |
915 * | |
916 * @exception DWTException <ul> | |
917 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
918 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
919 * </ul> | |
920 * | |
921 * @since 3.1 | |
922 */ | |
923 public int getGridLineWidth () { | |
924 checkWidget (); | |
925 return 0; | |
926 } | |
927 | |
928 /** | |
929 * Returns the height of the receiver's header | |
930 * | |
931 * @return the height of the header or zero if the header is not visible | |
932 * | |
933 * @exception DWTException <ul> | |
934 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
935 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
936 * </ul> | |
937 * | |
938 * @since 3.1 | |
939 */ | |
940 public int getHeaderHeight () { | |
941 checkWidget (); | |
942 NSTableHeaderView headerView = ((NSTableView)view).headerView(); | |
943 if (headerView is null) return 0; | |
944 return (int)headerView.bounds().height; | |
945 } | |
946 | |
947 /** | |
948 * Returns <code>true</code> if the receiver's header is visible, | |
949 * and <code>false</code> otherwise. | |
950 * <p> | |
951 * If one of the receiver's ancestors is not visible or some | |
952 * other condition makes the receiver not visible, this method | |
953 * may still indicate that it is considered visible even though | |
954 * it may not actually be showing. | |
955 * </p> | |
956 * | |
957 * @return the receiver's header's visibility state | |
958 * | |
959 * @exception DWTException <ul> | |
960 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
961 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
962 * </ul> | |
963 * | |
964 * @since 3.1 | |
965 */ | |
966 public bool getHeaderVisible () { | |
967 checkWidget (); | |
968 return ((NSTableView)view).headerView() !is null; | |
969 } | |
970 | |
971 /** | |
972 * Returns the item at the given, zero-relative index in the | |
973 * receiver. Throws an exception if the index is out of range. | |
974 * | |
975 * @param index the index of the item to return | |
976 * @return the item at the given index | |
977 * | |
978 * @exception IllegalArgumentException <ul> | |
979 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> | |
980 * </ul> | |
981 * @exception DWTException <ul> | |
982 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
983 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
984 * </ul> | |
985 * | |
986 * @since 3.1 | |
987 */ | |
988 public TreeItem getItem (int index) { | |
989 checkWidget (); | |
990 int count = getItemCount (); | |
991 if (index < 0 || index >= count) error (DWT.ERROR_INVALID_RANGE); | |
992 return _getItem (null, index); | |
993 } | |
994 | |
995 /** | |
996 * Returns the item at the given point in the receiver | |
997 * or null if no such item exists. The point is in the | |
998 * coordinate system of the receiver. | |
999 * <p> | |
1000 * The item that is returned represents an item that could be selected by the user. | |
1001 * For example, if selection only occurs in items in the first column, then null is | |
1002 * returned if the point is outside of the item. | |
1003 * Note that the DWT.FULL_SELECTION style hint, which specifies the selection policy, | |
1004 * determines the extent of the selection. | |
1005 * </p> | |
1006 * | |
1007 * @param point the point used to locate the item | |
1008 * @return the item at the given point, or null if the point is not in a selectable item | |
1009 * | |
1010 * @exception IllegalArgumentException <ul> | |
1011 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> | |
1012 * </ul> | |
1013 * @exception DWTException <ul> | |
1014 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1015 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1016 * </ul> | |
1017 */ | |
1018 public TreeItem getItem (Point point) { | |
1019 checkWidget (); | |
1020 if (point is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1021 // Rect rect = new Rect (); | |
1022 // dwt.internal.carbon.Point pt = new dwt.internal.carbon.Point (); | |
1023 // OS.SetPt (pt, (short) point.x, (short) point.y); | |
1024 // if (0 < lastHittest && lastHittest <= items.length && lastHittestColumn !is 0) { | |
1025 // TreeItem item = _getItem (lastHittest, false); | |
1026 // if (item !is null) { | |
1027 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, lastHittestColumn, OS.kDataBrowserPropertyDisclosurePart, rect) is OS.noErr) { | |
1028 // if (OS.PtInRect (pt, rect)) return null; | |
1029 // } | |
1030 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, lastHittestColumn, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) { | |
1031 // if (rect.top <= pt.v && pt.v <= rect.bottom) { | |
1032 // if ((style & DWT.FULL_SELECTION) !is 0) { | |
1033 // return item; | |
1034 // } else { | |
1035 // return OS.PtInRect (pt, rect) ? item : null; | |
1036 // } | |
1037 // } | |
1038 // } | |
1039 // } | |
1040 // } | |
1041 // //TODO - optimize | |
1042 // for (int i=0; i<items.length; i++) { | |
1043 // TreeItem item = items [i]; | |
1044 // if (item !is null) { | |
1045 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, column_id, OS.kDataBrowserPropertyDisclosurePart, rect) is OS.noErr) { | |
1046 // if (OS.PtInRect (pt, rect)) return null; | |
1047 // } | |
1048 // if (columnCount is 0) { | |
1049 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, column_id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) { | |
1050 // if (rect.top <= pt.v && pt.v <= rect.bottom) { | |
1051 // if ((style & DWT.FULL_SELECTION) !is 0) { | |
1052 // return item; | |
1053 // } else { | |
1054 // return OS.PtInRect (pt, rect) ? item : null; | |
1055 // } | |
1056 // } | |
1057 // } | |
1058 // } else { | |
1059 // for (int j = 0; j < columnCount; j++) { | |
1060 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, columns [j].id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) { | |
1061 // if (rect.top <= pt.v && pt.v <= rect.bottom) { | |
1062 // if ((style & DWT.FULL_SELECTION) !is 0) { | |
1063 // return item; | |
1064 // } else { | |
1065 // return OS.PtInRect (pt, rect) ? item : null; | |
1066 // } | |
1067 // } | |
1068 // } | |
1069 // } | |
1070 // } | |
1071 // } | |
1072 // } | |
1073 return null; | |
1074 } | |
1075 | |
1076 /** | |
1077 * Returns the number of items contained in the receiver | |
1078 * that are direct item children of the receiver. The | |
1079 * number that is returned is the number of roots in the | |
1080 * tree. | |
1081 * | |
1082 * @return the number of items | |
1083 * | |
1084 * @exception DWTException <ul> | |
1085 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1086 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1087 * </ul> | |
1088 */ | |
1089 public int getItemCount () { | |
1090 checkWidget (); | |
1091 return itemCount; | |
1092 } | |
1093 | |
1094 /** | |
1095 * Returns the height of the area which would be used to | |
1096 * display <em>one</em> of the items in the tree. | |
1097 * | |
1098 * @return the height of one item | |
1099 * | |
1100 * @exception DWTException <ul> | |
1101 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1102 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1103 * </ul> | |
1104 */ | |
1105 public int getItemHeight () { | |
1106 checkWidget (); | |
1107 return (int)((NSTableView)view).rowHeight(); | |
1108 } | |
1109 | |
1110 /** | |
1111 * Returns a (possibly empty) array of items contained in the | |
1112 * receiver that are direct item children of the receiver. These | |
1113 * are the roots of the tree. | |
1114 * <p> | |
1115 * Note: This is not the actual structure used by the receiver | |
1116 * to maintain its list of items, so modifying the array will | |
1117 * not affect the receiver. | |
1118 * </p> | |
1119 * | |
1120 * @return the items | |
1121 * | |
1122 * @exception DWTException <ul> | |
1123 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1125 * </ul> | |
1126 */ | |
1127 public TreeItem [] getItems () { | |
1128 checkWidget (); | |
1129 TreeItem [] result = new TreeItem [itemCount]; | |
1130 for (int i=0; i<itemCount; i++) { | |
1131 result [i] = _getItem (null, i); | |
1132 } | |
1133 return result; | |
1134 } | |
1135 | |
1136 /** | |
1137 * Returns <code>true</code> if the receiver's lines are visible, | |
1138 * and <code>false</code> otherwise. | |
1139 * <p> | |
1140 * If one of the receiver's ancestors is not visible or some | |
1141 * other condition makes the receiver not visible, this method | |
1142 * may still indicate that it is considered visible even though | |
1143 * it may not actually be showing. | |
1144 * </p> | |
1145 * | |
1146 * @return the visibility state of the lines | |
1147 * | |
1148 * @exception DWTException <ul> | |
1149 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1150 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1151 * </ul> | |
1152 * | |
1153 * @since 3.1 | |
1154 */ | |
1155 public bool getLinesVisible () { | |
1156 checkWidget (); | |
1157 // if (OS.VERSION >= 0x1040) { | |
1158 // int [] attrib = new int [1]; | |
1159 // OS.DataBrowserGetAttributes (handle, attrib); | |
1160 // return (attrib [0] & (OS.kDataBrowserAttributeListViewAlternatingRowColors | OS.kDataBrowserAttributeListViewDrawColumnDividers)) !is 0; | |
1161 // } | |
1162 return false; | |
1163 } | |
1164 | |
1165 /** | |
1166 * Returns the receiver's parent item, which must be a | |
1167 * <code>TreeItem</code> or null when the receiver is a | |
1168 * root. | |
1169 * | |
1170 * @return the receiver's parent item | |
1171 * | |
1172 * @exception DWTException <ul> | |
1173 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1174 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1175 * </ul> | |
1176 */ | |
1177 public TreeItem getParentItem () { | |
1178 checkWidget (); | |
1179 return null; | |
1180 } | |
1181 | |
1182 /** | |
1183 * Returns an array of <code>TreeItem</code>s that are currently | |
1184 * selected in the receiver. The order of the items is unspecified. | |
1185 * An empty array indicates that no items are selected. | |
1186 * <p> | |
1187 * Note: This is not the actual structure used by the receiver | |
1188 * to maintain its selection, so modifying the array will | |
1189 * not affect the receiver. | |
1190 * </p> | |
1191 * @return an array representing the selection | |
1192 * | |
1193 * @exception DWTException <ul> | |
1194 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1195 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1196 * </ul> | |
1197 */ | |
1198 public TreeItem [] getSelection () { | |
1199 checkWidget (); | |
1200 NSOutlineView widget = (NSOutlineView)view; | |
1201 if (widget.numberOfSelectedRows() is 0) { | |
1202 return new TreeItem [0]; | |
1203 } | |
1204 NSIndexSet selection = widget.selectedRowIndexes(); | |
1205 int count = selection.count(); | |
1206 int [] indexBuffer = new int [count]; | |
1207 selection.getIndexes(indexBuffer, count, 0); | |
1208 TreeItem [] result = new TreeItem [count]; | |
1209 for (int i=0; i<count; i++) { | |
1210 id item = widget.itemAtRow(indexBuffer [i]); | |
1211 int jniRef = OS.objc_msgSend(item.id, OS.sel_tag); | |
1212 if (jniRef !is -1 && jniRef !is 0) { | |
1213 //TODO virtual | |
1214 result[i] = (TreeItem)OS.JNIGetObject(jniRef); | |
1215 } | |
1216 } | |
1217 return result; | |
1218 } | |
1219 | |
1220 /** | |
1221 * Returns the number of selected items contained in the receiver. | |
1222 * | |
1223 * @return the number of selected items | |
1224 * | |
1225 * @exception DWTException <ul> | |
1226 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1227 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1228 * </ul> | |
1229 */ | |
1230 public int getSelectionCount () { | |
1231 checkWidget (); | |
1232 return ((NSTableView)view).numberOfSelectedRows(); | |
1233 } | |
1234 | |
1235 /** | |
1236 * Returns the column which shows the sort indicator for | |
1237 * the receiver. The value may be null if no column shows | |
1238 * the sort indicator. | |
1239 * | |
1240 * @return the sort indicator | |
1241 * | |
1242 * @exception DWTException <ul> | |
1243 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1244 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1245 * </ul> | |
1246 * | |
1247 * @see #setSortColumn(TreeColumn) | |
1248 * | |
1249 * @since 3.2 | |
1250 */ | |
1251 public TreeColumn getSortColumn () { | |
1252 checkWidget (); | |
1253 return sortColumn; | |
1254 } | |
1255 | |
1256 /** | |
1257 * Returns the direction of the sort indicator for the receiver. | |
1258 * The value will be one of <code>UP</code>, <code>DOWN</code> | |
1259 * or <code>NONE</code>. | |
1260 * | |
1261 * @return the sort direction | |
1262 * | |
1263 * @exception DWTException <ul> | |
1264 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1265 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1266 * </ul> | |
1267 * | |
1268 * @see #setSortDirection(int) | |
1269 * | |
1270 * @since 3.2 | |
1271 */ | |
1272 public int getSortDirection () { | |
1273 checkWidget (); | |
1274 return sortDirection; | |
1275 } | |
1276 | |
1277 /** | |
1278 * Returns the item which is currently at the top of the receiver. | |
1279 * This item can change when items are expanded, collapsed, scrolled | |
1280 * or new items are added or removed. | |
1281 * | |
1282 * @return the item at the top of the receiver | |
1283 * | |
1284 * @exception DWTException <ul> | |
1285 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1286 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1287 * </ul> | |
1288 * | |
1289 * @since 2.1 | |
1290 */ | |
1291 public TreeItem getTopItem () { | |
1292 checkWidget(); | |
1293 // //TODO - optimize | |
1294 // Rect rect = new Rect (); | |
1295 // int y = getBorder () + getHeaderHeight (); | |
1296 // for (int i=0; i<items.length; i++) { | |
1297 // TreeItem item = items [i]; | |
1298 // if (item !is null) { | |
1299 // int columnId = (columnCount is 0) ? column_id : columns [0].id; | |
1300 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, columnId, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) { | |
1301 // if (rect.top <= y && y <= rect.bottom) return item; | |
1302 // } | |
1303 // } | |
1304 // } | |
1305 return null; | |
1306 } | |
1307 | |
1308 /** | |
1309 * Searches the receiver's list starting at the first column | |
1310 * (index 0) until a column is found that is equal to the | |
1311 * argument, and returns the index of that column. If no column | |
1312 * is found, returns -1. | |
1313 * | |
1314 * @param column the search column | |
1315 * @return the index of the column | |
1316 * | |
1317 * @exception IllegalArgumentException <ul> | |
1318 * <li>ERROR_NULL_ARGUMENT - if the column is null</li> | |
1319 * </ul> | |
1320 * @exception DWTException <ul> | |
1321 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1322 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1323 * </ul> | |
1324 * | |
1325 * @since 3.1 | |
1326 */ | |
1327 public int indexOf (TreeColumn column) { | |
1328 checkWidget (); | |
1329 if (column is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1330 if (column.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
1331 for (int i=0; i<columnCount; i++) { | |
1332 if (columns [i] is column) return i; | |
1333 } | |
1334 return -1; | |
1335 } | |
1336 | |
1337 /** | |
1338 * Searches the receiver's list starting at the first item | |
1339 * (index 0) until an item is found that is equal to the | |
1340 * argument, and returns the index of that item. If no item | |
1341 * is found, returns -1. | |
1342 * | |
1343 * @param item the search item | |
1344 * @return the index of the item | |
1345 * | |
1346 * @exception IllegalArgumentException <ul> | |
1347 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
1348 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
1349 * </ul> | |
1350 * @exception DWTException <ul> | |
1351 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1352 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1353 * </ul> | |
1354 * | |
1355 * @since 3.1 | |
1356 */ | |
1357 public int indexOf (TreeItem item) { | |
1358 checkWidget (); | |
1359 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1360 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
1361 if (item.parentItem !is null) return -1; | |
1362 for (int i = 0; i < itemCount; i++) { | |
1363 if (item is items[i]) return i; | |
1364 } | |
1365 return -1; | |
1366 } | |
1367 | |
1368 int outlineView_child_ofItem(int outlineView, int index, int ref) { | |
1369 TreeItem parent = null; | |
1370 if (ref !is 0) parent = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1371 TreeItem item = _getItem(parent, index); | |
1372 return item.handle.id; | |
1373 } | |
1374 | |
1375 int outlineView_objectValueForTableColumn_byItem(int outlineView, int tableColumn, int ref) { | |
1376 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1377 if (checkColumn !is null && tableColumn is checkColumn.id) { | |
1378 NSNumber value; | |
1379 if (item.checked && item.grayed) { | |
1380 value = NSNumber.numberWithInt(OS.NSMixedState); | |
1381 } else { | |
1382 value = NSNumber.numberWithInt(item.checked ? OS.NSOnState : OS.NSOffState); | |
1383 } | |
1384 return value.id; | |
1385 } | |
1386 for (int i=0; i<columnCount; i++) { | |
1387 if (columns [i].nsColumn.id is tableColumn) { | |
1388 return item.createString(i).id; | |
1389 } | |
1390 } | |
1391 return item.createString(0).id; | |
1392 } | |
1393 | |
1394 bool outlineView_isItemExpandable(int outlineView, int ref) { | |
1395 if (ref is 0) return true; | |
1396 return ((TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag))).itemCount !is 0; | |
1397 } | |
1398 | |
1399 int outlineView_numberOfChildrenOfItem(int outlineView, int ref) { | |
1400 if (ref is 0) return itemCount; | |
1401 return ((TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag))).itemCount; | |
1402 } | |
1403 | |
1404 void outlineView_willDisplayCell_forTableColumn_item(int outlineView, int cell, int tableColumn, int ref) { | |
1405 if (checkColumn !is null && tableColumn is checkColumn.id) return; | |
1406 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1407 Image image = item.image; | |
1408 for (int i=0; i<columnCount; i++) { | |
1409 if (columns [i].nsColumn.id is tableColumn) { | |
1410 image = item.getImage(i); | |
1411 } | |
1412 } | |
1413 NSBrowserCell browserCell = new NSBrowserCell(cell); | |
1414 browserCell.setImage(image !is null ? image.handle : null); | |
1415 } | |
1416 | |
1417 void outlineViewSelectionDidChange(int notification) { | |
1418 if (ignoreSelect) return; | |
1419 NSOutlineView widget = (NSOutlineView)view; | |
1420 int row = widget.selectedRow(); | |
1421 if(row is -1) | |
1422 postEvent(DWT.Selection); | |
1423 else { | |
1424 id _id = widget.itemAtRow(row); | |
1425 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(_id.id, OS.sel_tag)); | |
1426 Event event = new Event(); | |
1427 event.item = item; | |
1428 event.index = row; | |
1429 postEvent(DWT.Selection, event); | |
1430 } | |
1431 } | |
1432 | |
1433 bool outlineView_shouldCollapseItem(int outlineView, int ref) { | |
1434 if (!ignoreExpand) { | |
1435 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1436 Event event = new Event(); | |
1437 event.item = item; | |
1438 sendEvent(DWT.Collapse, event); | |
1439 item.expanded = false; | |
1440 } | |
1441 return true; | |
1442 } | |
1443 | |
1444 bool outlineView_shouldExpandItem(int outlineView, int ref) { | |
1445 if (!ignoreExpand) { | |
1446 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1447 Event event = new Event(); | |
1448 event.item = item; | |
1449 sendEvent(DWT.Expand, event); | |
1450 item.expanded = true; | |
1451 } | |
1452 return true; | |
1453 } | |
1454 | |
1455 void outlineView_setObjectValue_forTableColumn_byItem(int outlineView, int object, int tableColumn, int ref) { | |
1456 TreeItem item = (TreeItem)OS.JNIGetObject(OS.objc_msgSend(ref, OS.sel_tag)); | |
1457 if (checkColumn !is null && tableColumn is checkColumn.id) { | |
1458 item.checked = !item.checked; | |
1459 Event event = new Event(); | |
1460 event.detail = DWT.CHECK; | |
1461 event.item = item; | |
1462 postEvent(DWT.Selection, event); | |
1463 } | |
1464 } | |
1465 | |
1466 void releaseChildren (bool destroy) { | |
1467 for (int i=0; i<items.length; i++) { | |
1468 TreeItem item = items [i]; | |
1469 if (item !is null && !item.isDisposed ()) { | |
1470 item.release (false); | |
1471 } | |
1472 } | |
1473 items = null; | |
1474 if (columns !is null) { | |
1475 for (int i=0; i<columnCount; i++) { | |
1476 TreeColumn column = columns [i]; | |
1477 if (column !is null && !column.isDisposed ()) { | |
1478 column.release (false); | |
1479 } | |
1480 } | |
1481 columns = null; | |
1482 } | |
1483 super.releaseChildren (destroy); | |
1484 } | |
1485 | |
1486 void releaseHandle () { | |
1487 super.releaseHandle (); | |
1488 if (headerView !is null) headerView.release(); | |
1489 headerView = null; | |
1490 if (firstColumn !is null) firstColumn.release(); | |
1491 firstColumn = null; | |
1492 if (checkColumn !is null) checkColumn.release(); | |
1493 checkColumn = null; | |
1494 } | |
1495 | |
1496 void releaseWidget () { | |
1497 super.releaseWidget (); | |
1498 //release handle | |
1499 sortColumn = null; | |
1500 } | |
1501 | |
1502 /** | |
1503 * Removes all of the items from the receiver. | |
1504 * | |
1505 * @exception DWTException <ul> | |
1506 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1507 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1508 * </ul> | |
1509 */ | |
1510 public void removeAll () { | |
1511 checkWidget (); | |
1512 for (int i=0; i<items.length; i++) { | |
1513 TreeItem item = items [i]; | |
1514 if (item !is null && !item.isDisposed ()) item.release (false); | |
1515 } | |
1516 items = new TreeItem [4]; | |
1517 itemCount = 0; | |
1518 ((NSOutlineView)view).reloadItem_(null); | |
1519 //((NSTableView)view).noteNumberOfRowsChanged(); | |
1520 // setScrollWidth (true); | |
1521 } | |
1522 | |
1523 /** | |
1524 * Removes the listener from the collection of listeners who will | |
1525 * be notified when the user changes the receiver's selection. | |
1526 * | |
1527 * @param listener the listener which should no longer be notified | |
1528 * | |
1529 * @exception IllegalArgumentException <ul> | |
1530 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
1531 * </ul> | |
1532 * @exception DWTException <ul> | |
1533 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1534 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1535 * </ul> | |
1536 * | |
1537 * @see SelectionListener | |
1538 * @see #addSelectionListener | |
1539 */ | |
1540 public void removeSelectionListener (SelectionListener listener) { | |
1541 checkWidget (); | |
1542 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1543 eventTable.unhook (DWT.Selection, listener); | |
1544 eventTable.unhook (DWT.DefaultSelection, listener); | |
1545 } | |
1546 | |
1547 /** | |
1548 * Removes the listener from the collection of listeners who will | |
1549 * be notified when items in the receiver are expanded or collapsed. | |
1550 * | |
1551 * @param listener the listener which should no longer be notified | |
1552 * | |
1553 * @exception IllegalArgumentException <ul> | |
1554 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
1555 * </ul> | |
1556 * @exception DWTException <ul> | |
1557 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1559 * </ul> | |
1560 * | |
1561 * @see TreeListener | |
1562 * @see #addTreeListener | |
1563 */ | |
1564 public void removeTreeListener(TreeListener listener) { | |
1565 checkWidget (); | |
1566 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1567 if (eventTable is null) return; | |
1568 eventTable.unhook (DWT.Expand, listener); | |
1569 eventTable.unhook (DWT.Collapse, listener); | |
1570 } | |
1571 | |
1572 /** | |
1573 * Display a mark indicating the point at which an item will be inserted. | |
1574 * The drop insert item has a visual hint to show where a dragged item | |
1575 * will be inserted when dropped on the tree. | |
1576 * | |
1577 * @param item the insert item. Null will clear the insertion mark. | |
1578 * @param before true places the insert mark above 'item'. false places | |
1579 * the insert mark below 'item'. | |
1580 * | |
1581 * @exception IllegalArgumentException <ul> | |
1582 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
1583 * </ul> | |
1584 * @exception DWTException <ul> | |
1585 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1586 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1587 * </ul> | |
1588 */ | |
1589 public void setInsertMark (TreeItem item, bool before) { | |
1590 checkWidget (); | |
1591 if (item !is null) { | |
1592 if (item.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); | |
1593 } | |
1594 } | |
1595 | |
1596 /** | |
1597 * Selects all of the items in the receiver. | |
1598 * <p> | |
1599 * If the receiver is single-select, do nothing. | |
1600 * </p> | |
1601 * | |
1602 * @exception DWTException <ul> | |
1603 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1604 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1605 * </ul> | |
1606 */ | |
1607 public void selectAll () { | |
1608 checkWidget (); | |
1609 if ((style & DWT.SINGLE) !is 0) return; | |
1610 NSTableView widget = (NSTableView)view; | |
1611 ignoreSelect = true; | |
1612 widget.selectAll(null); | |
1613 ignoreSelect = false; | |
1614 } | |
1615 | |
1616 public void select (TreeItem item) { | |
1617 checkWidget (); | |
1618 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1619 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
1620 // showItem (item, false); | |
1621 // ignoreSelect = true; | |
1622 // /* | |
1623 // * Bug in the Macintosh. When the DataBroswer selection flags includes | |
1624 // * both kDataBrowserNeverEmptySelectionSet and kDataBrowserSelectOnlyOne, | |
1625 // * two items are selected when SetDataBrowserSelectedItems() is called | |
1626 // * with kDataBrowserItemsAssign to assign a new seletion despite the fact | |
1627 // * that kDataBrowserSelectOnlyOne was specified. The fix is to save and | |
1628 // * restore kDataBrowserNeverEmptySelectionSet around each call to | |
1629 // * SetDataBrowserSelectedItems(). | |
1630 // */ | |
1631 // int [] selectionFlags = null; | |
1632 // if ((style & DWT.SINGLE) !is 0) { | |
1633 // selectionFlags = new int [1]; | |
1634 // OS.GetDataBrowserSelectionFlags (handle, selectionFlags); | |
1635 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0] & ~OS.kDataBrowserNeverEmptySelectionSet); | |
1636 // } | |
1637 // OS.SetDataBrowserSelectedItems (handle, 1, new int [] {item.id}, OS.kDataBrowserItemsAssign); | |
1638 // if ((style & DWT.SINGLE) !is 0) { | |
1639 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0]); | |
1640 // } | |
1641 // ignoreSelect = false; | |
1642 } | |
1643 | |
1644 void sendDoubleSelection() { | |
1645 postEvent (DWT.DefaultSelection); | |
1646 } | |
1647 | |
1648 /** | |
1649 * Sets the order that the items in the receiver should | |
1650 * be displayed in to the given argument which is described | |
1651 * in terms of the zero-relative ordering of when the items | |
1652 * were added. | |
1653 * | |
1654 * @param order the new order to display the items | |
1655 * | |
1656 * @exception DWTException <ul> | |
1657 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1658 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1659 * </ul> | |
1660 * @exception IllegalArgumentException <ul> | |
1661 * <li>ERROR_NULL_ARGUMENT - if the item order is null</li> | |
1662 * <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li> | |
1663 * </ul> | |
1664 * | |
1665 * @see Tree#getColumnOrder() | |
1666 * @see TreeColumn#getMoveable() | |
1667 * @see TreeColumn#setMoveable(bool) | |
1668 * @see DWT#Move | |
1669 * | |
1670 * @since 3.2 | |
1671 */ | |
1672 public void setColumnOrder (int [] order) { | |
1673 checkWidget (); | |
1674 if (order is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1675 if (columnCount is 0) { | |
1676 if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT); | |
1677 return; | |
1678 } | |
1679 if (order.length !is columnCount) error (DWT.ERROR_INVALID_ARGUMENT); | |
1680 int [] oldOrder = getColumnOrder (); | |
1681 bool reorder = false; | |
1682 bool [] seen = new bool [columnCount]; | |
1683 for (int i=0; i<order.length; i++) { | |
1684 int index = order [i]; | |
1685 if (index < 0 || index >= columnCount) error (DWT.ERROR_INVALID_ARGUMENT); | |
1686 if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT); | |
1687 seen [index] = true; | |
1688 if (order [i] !is oldOrder [i]) reorder = true; | |
1689 } | |
1690 if (reorder) { | |
1691 int [] disclosure = new int [1]; | |
1692 bool [] expandableRows = new bool [1]; | |
1693 // OS.GetDataBrowserListViewDisclosureColumn (handle, disclosure, expandableRows); | |
1694 TreeColumn firstColumn = columns [order [0]]; | |
1695 // if (disclosure [0] !is firstColumn.id) { | |
1696 // OS.SetDataBrowserListViewDisclosureColumn (handle, firstColumn.id, expandableRows [0]); | |
1697 // } | |
1698 int x = 0; | |
1699 short [] width = new short [1]; | |
1700 int [] oldX = new int [oldOrder.length]; | |
1701 for (int i=0; i<oldOrder.length; i++) { | |
1702 int index = oldOrder [i]; | |
1703 TreeColumn column = columns [index]; | |
1704 oldX [index] = x; | |
1705 // OS.GetDataBrowserTableViewNamedColumnWidth(handle, column.id, width); | |
1706 x += width [0]; | |
1707 } | |
1708 x = 0; | |
1709 int [] newX = new int [order.length]; | |
1710 for (int i=0; i<order.length; i++) { | |
1711 int index = order [i]; | |
1712 TreeColumn column = columns [index]; | |
1713 int position = (style & DWT.CHECK) !is 0 ? i + 1 : i; | |
1714 // OS.SetDataBrowserTableViewColumnPosition(handle, column.id, position); | |
1715 // column.lastPosition = position; | |
1716 newX [index] = x; | |
1717 // OS.GetDataBrowserTableViewNamedColumnWidth(handle, column.id, width); | |
1718 x += width [0]; | |
1719 } | |
1720 TreeColumn[] newColumns = new TreeColumn [columnCount]; | |
1721 System.arraycopy (columns, 0, newColumns, 0, columnCount); | |
1722 for (int i=0; i<columnCount; i++) { | |
1723 TreeColumn column = newColumns [i]; | |
1724 if (!column.isDisposed ()) { | |
1725 if (newX [i] !is oldX [i]) { | |
1726 column.sendEvent (DWT.Move); | |
1727 } | |
1728 } | |
1729 } | |
1730 } | |
1731 } | |
1732 | |
1733 /** | |
1734 * Marks the receiver's header as visible if the argument is <code>true</code>, | |
1735 * and marks it invisible otherwise. | |
1736 * <p> | |
1737 * If one of the receiver's ancestors is not visible or some | |
1738 * other condition makes the receiver not visible, marking | |
1739 * it visible may not actually cause it to be displayed. | |
1740 * </p> | |
1741 * | |
1742 * @param show the new visibility state | |
1743 * | |
1744 * @exception DWTException <ul> | |
1745 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1746 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1747 * </ul> | |
1748 * | |
1749 * @since 3.1 | |
1750 */ | |
1751 public void setHeaderVisible (bool show) { | |
1752 checkWidget (); | |
1753 ((NSTableView)view).setHeaderView (show ? headerView : null); | |
1754 } | |
1755 | |
1756 /** | |
1757 * Sets the number of root-level items contained in the receiver. | |
1758 * | |
1759 * @param count the number of items | |
1760 * | |
1761 * @exception DWTException <ul> | |
1762 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1763 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1764 * </ul> | |
1765 * | |
1766 * @since 3.2 | |
1767 */ | |
1768 public void setItemCount (int count) { | |
1769 checkWidget (); | |
1770 count = Math.max (0, count); | |
1771 setItemCount (null, count); | |
1772 } | |
1773 | |
1774 void setItemCount (TreeItem parentItem, int count) { | |
1775 // int itemCount = getItemCount (parentItem); | |
1776 // if (count is itemCount) return; | |
1777 // setRedraw (false); | |
1778 // int [] top = new int [1], left = new int [1]; | |
1779 // OS.GetDataBrowserScrollPosition (handle, top, left); | |
1780 // DataBrowserCallbacks callbacks = new DataBrowserCallbacks (); | |
1781 // OS.GetDataBrowserCallbacks (handle, callbacks); | |
1782 // callbacks.v1_itemNotificationCallback = 0; | |
1783 // callbacks.v1_itemCompareCallback = 0; | |
1784 // OS.SetDataBrowserCallbacks (handle, callbacks); | |
1785 // int[] ids = parentItem is null ? childIds : parentItem.childIds; | |
1786 // if (count < itemCount) { | |
1787 // for (int index = ids.length - 1; index >= count; index--) { | |
1788 // int id = ids [index]; | |
1789 // if (id !is 0) { | |
1790 // TreeItem item = _getItem (id, false); | |
1791 // if (item !is null && !item.isDisposed ()) { | |
1792 // item.dispose (); | |
1793 // } else { | |
1794 // if (parentItem is null || parentItem.getExpanded ()) { | |
1795 // if (OS.RemoveDataBrowserItems (handle, OS.kDataBrowserNoItem, 1, new int [] {id}, 0) !is OS.noErr) { | |
1796 // error (DWT.ERROR_ITEM_NOT_REMOVED); | |
1797 // break; | |
1798 // } | |
1799 // visibleCount--; | |
1800 // } | |
1801 // } | |
1802 // } | |
1803 // } | |
1804 // //TODO - move shrink to paint event | |
1805 // // shrink items array | |
1806 // int lastIndex = items.length; | |
1807 // for (int i=items.length; i>0; i--) { | |
1808 // if (items [i-1] !is null) { | |
1809 // lastIndex = i; | |
1810 // break; | |
1811 // } | |
1812 // } | |
1813 // if (lastIndex < items.length - 4) { | |
1814 // int length = Math.max (4, (lastIndex + 3) / 4 * 4); | |
1815 // TreeItem [] newItems = new TreeItem [length]; | |
1816 // System.arraycopy(items, 0, newItems, 0, Math.min(items.length, lastIndex)); | |
1817 // } | |
1818 // } | |
1819 // | |
1820 // if (parentItem !is null) parentItem.itemCount = count; | |
1821 // int length = Math.max (4, (count + 3) / 4 * 4); | |
1822 // int [] newIds = new int [length]; | |
1823 // if (ids !is null) { | |
1824 // System.arraycopy (ids, 0, newIds, 0, Math.min (count, itemCount)); | |
1825 // } | |
1826 // ids = newIds; | |
1827 // if (parentItem is null) { | |
1828 // childIds = newIds; | |
1829 // } else { | |
1830 // parentItem.childIds = newIds; | |
1831 // } | |
1832 // | |
1833 // if (count > itemCount) { | |
1834 // if ((getStyle() & DWT.VIRTUAL) is 0) { | |
1835 // int delta = Math.max (4, (count - itemCount + 3) / 4 * 4); | |
1836 // TreeItem [] newItems = new TreeItem [items.length + delta]; | |
1837 // System.arraycopy (items, 0, newItems, 0, items.length); | |
1838 // items = newItems; | |
1839 // for (int i=itemCount; i<count; i++) { | |
1840 // items [i] = new TreeItem (this, parentItem, DWT.NONE, i, true); | |
1841 // } | |
1842 // } else { | |
1843 // if (parentItem is null || parentItem.getExpanded ()) { | |
1844 // int parentID = parentItem is null ? OS.kDataBrowserNoItem : parentItem.id; | |
1845 // int [] addIds = _getIds (count - itemCount); | |
1846 // if (OS.AddDataBrowserItems (handle, parentID, addIds.length, addIds, OS.kDataBrowserItemNoProperty) !is OS.noErr) { | |
1847 // error (DWT.ERROR_ITEM_NOT_ADDED); | |
1848 // } | |
1849 // visibleCount += (count - itemCount); | |
1850 // System.arraycopy (addIds, 0, ids, itemCount, addIds.length); | |
1851 // } | |
1852 // } | |
1853 // } | |
1854 // | |
1855 // callbacks.v1_itemNotificationCallback = display.itemNotificationProc; | |
1856 // callbacks.v1_itemCompareCallback = display.itemCompareProc; | |
1857 // OS.SetDataBrowserCallbacks (handle, callbacks); | |
1858 // setRedraw (true); | |
1859 // if (itemCount is 0 && parentItem !is null) parentItem.redraw (OS.kDataBrowserNoItem); | |
1860 } | |
1861 | |
1862 /*public*/ void setItemHeight (int itemHeight) { | |
1863 checkWidget (); | |
1864 if (itemHeight < -1) error (DWT.ERROR_INVALID_ARGUMENT); | |
1865 if (itemHeight is -1) { | |
1866 //TODO - reset item height, ensure other API's such as setFont don't do this | |
1867 } else { | |
1868 // OS.SetDataBrowserTableViewRowHeight (handle, (short) itemHeight); | |
1869 } | |
1870 } | |
1871 | |
1872 void setItemHeight (Image image) { | |
1873 // Rectangle bounds = image !is null ? image.getBounds () : imageBounds; | |
1874 // if (bounds is null) return; | |
1875 // imageBounds = bounds; | |
1876 // short [] height = new short [1]; | |
1877 // if (OS.GetDataBrowserTableViewRowHeight (handle, height) is OS.noErr) { | |
1878 // if (height [0] < bounds.height) { | |
1879 // OS.SetDataBrowserTableViewRowHeight (handle, (short) bounds.height); | |
1880 // } | |
1881 // } | |
1882 } | |
1883 | |
1884 /** | |
1885 * Marks the receiver's lines as visible if the argument is <code>true</code>, | |
1886 * and marks it invisible otherwise. | |
1887 * <p> | |
1888 * If one of the receiver's ancestors is not visible or some | |
1889 * other condition makes the receiver not visible, marking | |
1890 * it visible may not actually cause it to be displayed. | |
1891 * </p> | |
1892 * | |
1893 * @param show the new visibility state | |
1894 * | |
1895 * @exception DWTException <ul> | |
1896 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1897 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1898 * </ul> | |
1899 * | |
1900 * @since 3.1 | |
1901 */ | |
1902 public void setLinesVisible (bool show) { | |
1903 checkWidget (); | |
1904 ((NSTableView)view).setUsesAlternatingRowBackgroundColors(show); | |
1905 } | |
1906 | |
1907 public void setRedraw (bool redraw) { | |
1908 checkWidget(); | |
1909 super.setRedraw (redraw); | |
1910 if (redraw && drawCount is 0) { | |
1911 setScrollWidth (true); | |
1912 } | |
1913 } | |
1914 | |
1915 bool setScrollWidth (TreeItem item) { | |
1916 // if (ignoreRedraw || drawCount !is 0) return false; | |
1917 if (columnCount !is 0) return false; | |
1918 // TreeItem parentItem = item.parentItem; | |
1919 // if (parentItem !is null && !parentItem._getExpanded ()) return false; | |
1920 // GC gc = new GC (this); | |
1921 // int newWidth = item.calculateWidth (0, gc); | |
1922 // gc.dispose (); | |
1923 // newWidth += getInsetWidth (column_id, false); | |
1924 // short [] width = new short [1]; | |
1925 // OS.GetDataBrowserTableViewNamedColumnWidth (handle, column_id, width); | |
1926 // if (width [0] < newWidth) { | |
1927 // OS.SetDataBrowserTableViewNamedColumnWidth (handle, column_id, (short) newWidth); | |
1928 // return true; | |
1929 // } | |
1930 // firstColumn.setWidth(400); | |
1931 return false; | |
1932 } | |
1933 | |
1934 bool setScrollWidth (bool set) { | |
1935 // return setScrollWidth(set, childIds, true); | |
1936 return false; | |
1937 } | |
1938 | |
1939 bool setScrollWidth (bool set, int[] childIds, bool recurse) { | |
1940 // if (ignoreRedraw || drawCount !is 0) return false; | |
1941 // if (columnCount !is 0 || childIds is null) return false; | |
1942 // GC gc = new GC (this); | |
1943 // int newWidth = calculateWidth (childIds, gc, recurse, 0, 0); | |
1944 // gc.dispose (); | |
1945 // newWidth += getInsetWidth (column_id, false); | |
1946 // if (!set) { | |
1947 // short [] width = new short [1]; | |
1948 // OS.GetDataBrowserTableViewNamedColumnWidth (handle, column_id, width); | |
1949 // if (width [0] >= newWidth) return false; | |
1950 // } | |
1951 // OS.SetDataBrowserTableViewNamedColumnWidth (handle, column_id, (short) newWidth); | |
1952 return true; | |
1953 } | |
1954 | |
1955 /** | |
1956 * Sets the receiver's selection to the given item. | |
1957 * The current selection is cleared before the new item is selected. | |
1958 * <p> | |
1959 * If the item is not in the receiver, then it is ignored. | |
1960 * </p> | |
1961 * | |
1962 * @param item the item to select | |
1963 * | |
1964 * @exception IllegalArgumentException <ul> | |
1965 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
1966 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
1967 * </ul> | |
1968 * @exception DWTException <ul> | |
1969 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1970 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1971 * </ul> | |
1972 * | |
1973 * @since 3.2 | |
1974 */ | |
1975 public void setSelection (TreeItem item) { | |
1976 checkWidget (); | |
1977 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
1978 setSelection (new TreeItem [] {item}); | |
1979 } | |
1980 | |
1981 /** | |
1982 * Sets the receiver's selection to be the given array of items. | |
1983 * The current selection is cleared before the new items are selected. | |
1984 * <p> | |
1985 * Items that are not in the receiver are ignored. | |
1986 * If the receiver is single-select and multiple items are specified, | |
1987 * then all items are ignored. | |
1988 * </p> | |
1989 * | |
1990 * @param items the array of items | |
1991 * | |
1992 * @exception IllegalArgumentException <ul> | |
1993 * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li> | |
1994 * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li> | |
1995 * </ul> | |
1996 * @exception DWTException <ul> | |
1997 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1998 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1999 * </ul> | |
2000 * | |
2001 * @see Tree#deselectAll() | |
2002 */ | |
2003 public void setSelection (TreeItem [] items) { | |
2004 checkWidget (); | |
2005 if (items is null) error (DWT.ERROR_NULL_ARGUMENT); | |
2006 deselectAll (); | |
2007 // int length = items.length; | |
2008 // if (length is 0 || ((style & DWT.SINGLE) !is 0 && length > 1)) return; | |
2009 // int count = 0; | |
2010 // int[] ids = new int [length]; | |
2011 // for (int i=0; i<length; i++) { | |
2012 // if (items [i] !is null) { | |
2013 // if (items [i].isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
2014 // ids [count++] = items [i].id; | |
2015 // showItem (items [i], false); | |
2016 // } | |
2017 // } | |
2018 // ignoreSelect = true; | |
2019 // /* | |
2020 // * Bug in the Macintosh. When the DataBroswer selection flags includes | |
2021 // * both kDataBrowserNeverEmptySelectionSet and kDataBrowserSelectOnlyOne, | |
2022 // * two items are selected when SetDataBrowserSelectedItems() is called | |
2023 // * with kDataBrowserItemsAssign to assign a new seletion despite the fact | |
2024 // * that kDataBrowserSelectOnlyOne was specified. The fix is to save and | |
2025 // * restore kDataBrowserNeverEmptySelectionSet around each call to | |
2026 // * SetDataBrowserSelectedItems(). | |
2027 // */ | |
2028 // int [] selectionFlags = null; | |
2029 // if ((style & DWT.SINGLE) !is 0) { | |
2030 // selectionFlags = new int [1]; | |
2031 // OS.GetDataBrowserSelectionFlags (handle, selectionFlags); | |
2032 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0] & ~OS.kDataBrowserNeverEmptySelectionSet); | |
2033 // } | |
2034 // OS.SetDataBrowserSelectedItems (handle, count, ids, OS.kDataBrowserItemsAssign); | |
2035 // if ((style & DWT.SINGLE) !is 0) { | |
2036 // OS.SetDataBrowserSelectionFlags (handle, selectionFlags [0]); | |
2037 // } | |
2038 // ignoreSelect = false; | |
2039 // if (length > 0) { | |
2040 // int index = -1; | |
2041 // for (int i=0; i<items.length; i++) { | |
2042 // if (items [i] !is null) { | |
2043 // index = i; | |
2044 // break; | |
2045 // } | |
2046 // } | |
2047 // if (index !is -1) showItem (items [index], true); | |
2048 // } | |
2049 } | |
2050 | |
2051 /** | |
2052 * Sets the column used by the sort indicator for the receiver. A null | |
2053 * value will clear the sort indicator. The current sort column is cleared | |
2054 * before the new column is set. | |
2055 * | |
2056 * @param column the column used by the sort indicator or <code>null</code> | |
2057 * | |
2058 * @exception IllegalArgumentException <ul> | |
2059 * <li>ERROR_INVALID_ARGUMENT - if the column is disposed</li> | |
2060 * </ul> | |
2061 * @exception DWTException <ul> | |
2062 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2063 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2064 * </ul> | |
2065 * | |
2066 * @since 3.2 | |
2067 */ | |
2068 public void setSortColumn (TreeColumn column) { | |
2069 checkWidget (); | |
2070 if (column !is null && column.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
2071 if (column is sortColumn) return; | |
2072 // if (column is null) { | |
2073 // if (sortColumn !is null && !sortColumn.isDisposed () && sortDirection !is DWT.NONE) { | |
2074 // OS.SetDataBrowserSortOrder (handle, (short) OS.kDataBrowserOrderIncreasing); | |
2075 // sortColumn = null; | |
2076 // OS.SetDataBrowserSortProperty (handle, 0); | |
2077 // } | |
2078 // } | |
2079 // sortColumn = column; | |
2080 // if (sortColumn !is null && !sortColumn.isDisposed () && sortDirection !is DWT.NONE) { | |
2081 // OS.SetDataBrowserSortProperty (handle, sortColumn.id); | |
2082 // int order = sortDirection is DWT.DOWN ? OS.kDataBrowserOrderDecreasing : OS.kDataBrowserOrderIncreasing; | |
2083 // OS.SetDataBrowserSortOrder (handle, (short) order); | |
2084 // } | |
2085 } | |
2086 | |
2087 /** | |
2088 * Sets the direction of the sort indicator for the receiver. The value | |
2089 * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>. | |
2090 * | |
2091 * @param direction the direction of the sort indicator | |
2092 * | |
2093 * @exception DWTException <ul> | |
2094 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2095 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2096 * </ul> | |
2097 * | |
2098 * @since 3.2 | |
2099 */ | |
2100 public void setSortDirection (int direction) { | |
2101 checkWidget (); | |
2102 if (direction !is DWT.UP && direction !is DWT.DOWN && direction !is DWT.NONE) return; | |
2103 // if (direction is sortDirection) return; | |
2104 // sortDirection = direction; | |
2105 // if (sortColumn !is null && !sortColumn.isDisposed ()) { | |
2106 // if (sortDirection is DWT.NONE) { | |
2107 // OS.SetDataBrowserSortOrder (handle, (short) OS.kDataBrowserOrderIncreasing); | |
2108 // TreeColumn column = sortColumn; | |
2109 // sortColumn = null; | |
2110 // OS.SetDataBrowserSortProperty (handle, 0); | |
2111 // sortColumn = column; | |
2112 // } else { | |
2113 // OS.SetDataBrowserSortProperty (handle, 0); | |
2114 // OS.SetDataBrowserSortProperty (handle, sortColumn.id); | |
2115 // int order = sortDirection is DWT.DOWN ? OS.kDataBrowserOrderDecreasing : OS.kDataBrowserOrderIncreasing; | |
2116 // OS.SetDataBrowserSortOrder (handle, (short) order); | |
2117 // } | |
2118 // } | |
2119 } | |
2120 | |
2121 /** | |
2122 * Sets the item which is currently at the top of the receiver. | |
2123 * This item can change when items are expanded, collapsed, scrolled | |
2124 * or new items are added or removed. | |
2125 * | |
2126 * @param item the item to be shown | |
2127 * | |
2128 * @exception IllegalArgumentException <ul> | |
2129 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
2130 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
2131 * </ul> | |
2132 * @exception DWTException <ul> | |
2133 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2134 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2135 * </ul> | |
2136 * | |
2137 * @see Tree#getTopItem() | |
2138 * | |
2139 * @since 2.1 | |
2140 */ | |
2141 public void setTopItem (TreeItem item) { | |
2142 checkWidget(); | |
2143 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
2144 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
2145 // showItem (item, false); | |
2146 // int columnId = (columnCount is 0) ? column_id : columns [0].id; | |
2147 // OS.RevealDataBrowserItem (handle, item.id, columnId, (byte) OS.kDataBrowserRevealWithoutSelecting); | |
2148 // Rect rect = new Rect (); | |
2149 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, column_id, OS.kDataBrowserPropertyEnclosingPart, rect) is OS.noErr) { | |
2150 // int border = getBorder (); | |
2151 // int [] top = new int [1], left = new int [1]; | |
2152 // OS.GetDataBrowserScrollPosition (handle, top, left); | |
2153 // OS.SetDataBrowserScrollPosition (handle, Math.max (0, top [0] + rect.top - border - getHeaderHeight ()), left [0]); | |
2154 // } | |
2155 } | |
2156 | |
2157 /** | |
2158 * Shows the column. If the column is already showing in the receiver, | |
2159 * this method simply returns. Otherwise, the columns are scrolled until | |
2160 * the column is visible. | |
2161 * | |
2162 * @param column the column to be shown | |
2163 * | |
2164 * @exception IllegalArgumentException <ul> | |
2165 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
2166 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
2167 * </ul> | |
2168 * @exception DWTException <ul> | |
2169 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2170 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2171 * </ul> | |
2172 * | |
2173 * @since 3.1 | |
2174 */ | |
2175 public void showColumn (TreeColumn column) { | |
2176 checkWidget (); | |
2177 if (column is null) error (DWT.ERROR_NULL_ARGUMENT); | |
2178 if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); | |
2179 if (column.parent !is this) return; | |
2180 int index = indexOf (column); | |
2181 if (columnCount <= 1 || !(0 <= index && index < columnCount)) return; | |
2182 ((NSTableView)view).scrollColumnToVisible(index + ((style & DWT.CHECK) !is 0 ? 1 : 0)); | |
2183 } | |
2184 | |
2185 /** | |
2186 * Shows the item. If the item is already showing in the receiver, | |
2187 * this method simply returns. Otherwise, the items are scrolled | |
2188 * and expanded until the item is visible. | |
2189 * | |
2190 * @param item the item to be shown | |
2191 * | |
2192 * @exception IllegalArgumentException <ul> | |
2193 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
2194 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
2195 * </ul> | |
2196 * @exception DWTException <ul> | |
2197 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2198 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2199 * </ul> | |
2200 * | |
2201 * @see Tree#showSelection() | |
2202 */ | |
2203 public void showItem (TreeItem item) { | |
2204 checkWidget (); | |
2205 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); | |
2206 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); | |
2207 showItem (item, true); | |
2208 } | |
2209 | |
2210 void showItem (TreeItem item, bool scroll) { | |
2211 int count = 0; | |
2212 // TreeItem parentItem = item.parentItem; | |
2213 // while (parentItem !is null && !parentItem._getExpanded ()) { | |
2214 // count++; | |
2215 // parentItem = parentItem.parentItem; | |
2216 // } | |
2217 // int index = 0; | |
2218 // parentItem = item.parentItem; | |
2219 // TreeItem [] path = new TreeItem [count]; | |
2220 // while (parentItem !is null && !parentItem._getExpanded ()) { | |
2221 // path [index++] = parentItem; | |
2222 // parentItem = parentItem.parentItem; | |
2223 // } | |
2224 // for (int i=path.length-1; i>=0; --i) { | |
2225 // path [i].setExpanded (true); | |
2226 // } | |
2227 // if (scroll) { | |
2228 // /* | |
2229 // * Bug in the Macintosh. When there is not room to show a | |
2230 // * single item in the data browser, RevealDataBrowserItem() | |
2231 // * scrolls the item such that it is above the top of the data | |
2232 // * browser. The fix is to remember the index and scroll when | |
2233 // * the data browser is resized. | |
2234 // * | |
2235 // * Bug in the Macintosh. When items are added to the data | |
2236 // * browser after is has been hidden, RevealDataBrowserItem() | |
2237 // * when called before the controls behind the data browser | |
2238 // * are repainted causes a redraw. This redraw happens right | |
2239 // * away causing pixel corruption. The fix is to remember the | |
2240 // * index and scroll when the data browser is shown. | |
2241 // */ | |
2242 // Rectangle rect = getClientArea (); | |
2243 // if (rect.height < getItemHeight () || !OS.IsControlVisible (handle)) { | |
2244 // showItem = item; | |
2245 // return; | |
2246 // } | |
2247 // showItem = null; | |
2248 // Rectangle itemRect = item.getBounds (); | |
2249 // if (!itemRect.isEmpty()) { | |
2250 // if (rect.contains (itemRect.x, itemRect.y) | |
2251 // && rect.contains (itemRect.x, itemRect.y + itemRect.height)) return; | |
2252 // } | |
2253 // int [] top = new int [1], left = new int [1]; | |
2254 // OS.GetDataBrowserScrollPosition (handle, top, left); | |
2255 // int columnId = (columnCount is 0) ? column_id : columns [0].id; | |
2256 // int options = OS.kDataBrowserRevealWithoutSelecting; | |
2257 // /* | |
2258 // * This code is intentionally commented, since kDataBrowserRevealAndCenterInView | |
2259 // * does not scroll the item to the center always (it seems to scroll to the | |
2260 // * end in some cases). | |
2261 // */ | |
2262 // //options |= OS.kDataBrowserRevealAndCenterInView; | |
2263 // OS.RevealDataBrowserItem (handle, item.id, columnId, (byte) options); | |
2264 // int [] newTop = new int [1], newLeft = new int [1]; | |
2265 // if (columnCount is 0) { | |
2266 // bool fixScroll = false; | |
2267 // Rect content = new Rect (); | |
2268 // if (OS.GetDataBrowserItemPartBounds (handle, item.id, columnId, OS.kDataBrowserPropertyContentPart, content) is OS.noErr) { | |
2269 // fixScroll = content.left < rect.x || content.left >= rect.x + rect.width; | |
2270 // if (!fixScroll) { | |
2271 // GC gc = new GC (this); | |
2272 // int contentWidth = calculateWidth (new int[]{item.id}, gc, false, 0, 0); | |
2273 // gc.dispose (); | |
2274 // fixScroll = content.left + contentWidth > rect.x + rect.width; | |
2275 // } | |
2276 // } | |
2277 // if (fixScroll) { | |
2278 // int leftScroll = getLeftDisclosureInset (columnId); | |
2279 // int levelIndent = DISCLOSURE_COLUMN_LEVEL_INDENT; | |
2280 // if (OS.VERSION >= 0x1040) { | |
2281 // float [] metric = new float [1]; | |
2282 // OS.DataBrowserGetMetric (handle, OS.kDataBrowserMetricDisclosureColumnPerDepthGap, null, metric); | |
2283 // levelIndent = (int) metric [0]; | |
2284 // } | |
2285 // TreeItem temp = item; | |
2286 // while (temp.parentItem !is null) { | |
2287 // leftScroll += levelIndent; | |
2288 // temp = temp.parentItem; | |
2289 // } | |
2290 // OS.GetDataBrowserScrollPosition (handle, newTop, newLeft); | |
2291 // OS.SetDataBrowserScrollPosition (handle, newTop [0], leftScroll); | |
2292 // } | |
2293 // } | |
2294 // | |
2295 // /* | |
2296 // * Bug in the Macintosh. For some reason, when the DataBrowser is scrolled | |
2297 // * by RevealDataBrowserItem(), the scrollbars are not redrawn. The fix is to | |
2298 // * force a redraw. | |
2299 // */ | |
2300 // OS.GetDataBrowserScrollPosition (handle, newTop, newLeft); | |
2301 // if (horizontalBar !is null && newLeft [0] !is left [0]) horizontalBar.redraw (); | |
2302 // if (verticalBar !is null && newTop [0] !is top [0]) verticalBar.redraw (); | |
2303 // } | |
2304 } | |
2305 | |
2306 /** | |
2307 * Shows the selection. If the selection is already showing in the receiver, | |
2308 * this method simply returns. Otherwise, the items are scrolled until | |
2309 * the selection is visible. | |
2310 * | |
2311 * @exception DWTException <ul> | |
2312 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
2313 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
2314 * </ul> | |
2315 * | |
2316 * @see Tree#showItem(TreeItem) | |
2317 */ | |
2318 public void showSelection () { | |
2319 checkWidget (); | |
2320 //checkItems (false); | |
2321 //TODO - optimize | |
2322 TreeItem [] selection = getSelection (); | |
2323 if (selection.length > 0) showItem (selection [0], true); | |
2324 } | |
2325 | |
2326 } |