Mercurial > projects > dwt-mac
comparison dwt/widgets/TreeColumn.d @ 45:d8635bb48c7c
Merge with SWT 3.5
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Mon, 01 Dec 2008 17:07:00 +0100 |
parents | e831403a80a9 |
children | 6c56264306a6 |
comparison
equal
deleted
inserted
replaced
44:ca5e494f2bbf | 45:d8635bb48c7c |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
16 import dwt.DWT; | 16 import dwt.DWT; |
17 import dwt.DWTException; | 17 import dwt.DWTException; |
18 import dwt.events.ControlListener; | 18 import dwt.events.ControlListener; |
19 import dwt.events.SelectionEvent; | 19 import dwt.events.SelectionEvent; |
20 import dwt.events.SelectionListener; | 20 import dwt.events.SelectionListener; |
21 import dwt.graphics.GC; | |
21 import dwt.graphics.Image; | 22 import dwt.graphics.Image; |
23 import dwt.internal.cocoa.NSAffineTransform; | |
24 import dwt.internal.cocoa.NSAttributedString; | |
25 import dwt.internal.cocoa.NSGraphicsContext; | |
26 import dwt.internal.cocoa.NSMutableDictionary; | |
27 import dwt.internal.cocoa.NSMutableParagraphStyle; | |
28 import dwt.internal.cocoa.NSOutlineView; | |
29 import dwt.internal.cocoa.NSRect; | |
30 import dwt.internal.cocoa.NSSize; | |
22 import dwt.internal.cocoa.NSString; | 31 import dwt.internal.cocoa.NSString; |
23 import dwt.internal.cocoa.NSTableColumn; | 32 import dwt.internal.cocoa.NSTableColumn; |
33 import dwt.internal.cocoa.NSTableHeaderCell; | |
34 import dwt.internal.cocoa.NSTableHeaderView; | |
35 import dwt.internal.cocoa.NSView; | |
24 import dwt.internal.cocoa.OS; | 36 import dwt.internal.cocoa.OS; |
25 | 37 |
26 /** | 38 /** |
27 * Instances of this class represent a column in a tree widget. | 39 * Instances of this class represent a column in a tree widget. |
28 * <p><dl> | 40 * <p><dl> |
34 * </p><p> | 46 * </p><p> |
35 * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified. | 47 * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified. |
36 * </p><p> | 48 * </p><p> |
37 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | 49 * IMPORTANT: This class is <em>not</em> intended to be subclassed. |
38 * </p> | 50 * </p> |
51 * | |
52 * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a> | |
53 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
39 * | 54 * |
40 * @since 3.1 | 55 * @since 3.1 |
41 */ | 56 */ |
42 public class TreeColumn : Item { | 57 public class TreeColumn : Item { |
43 NSTableColumn nsColumn; | 58 NSTableColumn nsColumn; |
44 Tree parent; | 59 Tree parent; |
45 String toolTipText; | 60 String toolTipText, displayText; |
61 | |
62 static final int MARGIN = 2; | |
46 | 63 |
47 /** | 64 /** |
48 * Constructs a new instance of this class given its parent | 65 * Constructs a new instance of this class given its parent |
49 * (which must be a <code>Tree</code>) and a style value | 66 * (which must be a <code>Tree</code>) and a style value |
50 * describing its behavior and appearance. The item is added | 67 * describing its behavior and appearance. The item is added |
77 * @see Widget#getStyle | 94 * @see Widget#getStyle |
78 */ | 95 */ |
79 public this (Tree parent, int style) { | 96 public this (Tree parent, int style) { |
80 super (parent, checkStyle (style)); | 97 super (parent, checkStyle (style)); |
81 this.parent = parent; | 98 this.parent = parent; |
82 parent.createItem (this, parent.getColumnCount ()); | 99 parent.createItem (this, parent.columnCount); |
83 } | 100 } |
84 | 101 |
85 /** | 102 /** |
86 * Constructs a new instance of this class given its parent | 103 * Constructs a new instance of this class given its parent |
87 * (which must be a <code>Tree</code>), a style value | 104 * (which must be a <code>Tree</code>), a style value |
94 * (that is, using the <code>int</code> "|" operator) two or more | 111 * (that is, using the <code>int</code> "|" operator) two or more |
95 * of those <code>DWT</code> style constants. The class description | 112 * of those <code>DWT</code> style constants. The class description |
96 * lists the style constants that are applicable to the class. | 113 * lists the style constants that are applicable to the class. |
97 * Style bits are also inherited from superclasses. | 114 * Style bits are also inherited from superclasses. |
98 * </p> | 115 * </p> |
99 * | 116 * <p> |
117 * Note that due to a restriction on some platforms, the first column | |
118 * is always left aligned. | |
119 * </p> | |
100 * @param parent a composite control which will be the parent of the new instance (cannot be null) | 120 * @param parent a composite control which will be the parent of the new instance (cannot be null) |
101 * @param style the style of control to construct | 121 * @param style the style of control to construct |
102 * @param index the zero-relative index to store the receiver in its parent | 122 * @param index the zero-relative index to store the receiver in its parent |
103 * | 123 * |
104 * @exception IllegalArgumentException <ul> | 124 * @exception IllegalArgumentException <ul> |
187 | 207 |
188 protected void checkSubclass () { | 208 protected void checkSubclass () { |
189 if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); | 209 if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); |
190 } | 210 } |
191 | 211 |
212 void deregister () { | |
213 super.deregister (); | |
214 display.removeWidget (nsColumn.headerCell()); | |
215 } | |
216 | |
192 void destroyWidget () { | 217 void destroyWidget () { |
193 parent.destroyItem (this); | 218 parent.destroyItem (this); |
194 releaseHandle (); | 219 releaseHandle (); |
220 } | |
221 | |
222 void drawInteriorWithFrame_inView (int /*long*/ id, int /*long*/ sel, int /*long*/ cellFrame, int /*long*/ view) { | |
223 NSRect cellRect = new NSRect (); | |
224 OS.memmove (cellRect, cellFrame, NSRect.sizeof); | |
225 | |
226 /* | |
227 * Feature in Cocoa. When the last column in a tree does not reach the | |
228 * rightmost edge of the tree view, the cell that draws the rightmost- | |
229 * column's header is also invoked to draw the header space between its | |
230 * right edge and the tree's right edge. If this case is detected then | |
231 * nothing should be drawn. | |
232 */ | |
233 NSOutlineView outlineView = (NSOutlineView)parent.view; | |
234 int columnIndex = (int)/*64*/outlineView.columnWithIdentifier (nsColumn); | |
235 NSRect headerRect = parent.headerView.headerRectOfColumn (columnIndex); | |
236 if (headerRect.x !is cellRect.x || headerRect.width !is cellRect.width) return; | |
237 | |
238 NSGraphicsContext context = NSGraphicsContext.currentContext (); | |
239 context.saveGraphicsState (); | |
240 | |
241 int contentWidth = 0; | |
242 NSSize stringSize = null, imageSize = null; | |
243 NSAttributedString attrString = null; | |
244 NSTableHeaderCell headerCell = nsColumn.headerCell (); | |
245 if (displayText !is null) { | |
246 NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity(4); | |
247 dict.setObject (headerCell.font (), OS.NSFontAttributeName); | |
248 NSMutableParagraphStyle paragraphStyle = (NSMutableParagraphStyle)new NSMutableParagraphStyle ().alloc ().init (); | |
249 paragraphStyle.autorelease (); | |
250 paragraphStyle.setLineBreakMode (OS.NSLineBreakByClipping); | |
251 dict.setObject (paragraphStyle, OS.NSParagraphStyleAttributeName); | |
252 NSString string = NSString.stringWith (displayText); | |
253 attrString = ((NSAttributedString)new NSAttributedString ().alloc ()).initWithString (string, dict); | |
254 stringSize = attrString.size (); | |
255 contentWidth += Math.ceil (stringSize.width); | |
256 if (image !is null) contentWidth += MARGIN; /* space between image and text */ | |
257 } | |
258 if (image !is null) { | |
259 imageSize = image.handle.size (); | |
260 contentWidth += Math.ceil (imageSize.width); | |
261 } | |
262 | |
263 if (parent.sortColumn is this && parent.sortDirection !is DWT.NONE) { | |
264 bool ascending = parent.sortDirection is DWT.UP; | |
265 headerCell.drawSortIndicatorWithFrame (cellRect, new NSView(view), ascending, 0); | |
266 /* remove the arrow's space from the available drawing width */ | |
267 NSRect sortRect = headerCell.sortIndicatorRectForBounds (cellRect); | |
268 cellRect.width = Math.max (0, sortRect.x - cellRect.x); | |
269 } | |
270 | |
271 int drawX = 0; | |
272 if ((style & DWT.CENTER) !is 0) { | |
273 drawX = (int)(cellRect.x + Math.max (MARGIN, ((cellRect.width - contentWidth) / 2))); | |
274 } else if ((style & DWT.RIGHT) !is 0) { | |
275 drawX = (int)(cellRect.x + Math.max (MARGIN, cellRect.width - contentWidth - MARGIN)); | |
276 } else { | |
277 drawX = (int)cellRect.x + MARGIN; | |
278 } | |
279 | |
280 if (image !is null) { | |
281 NSRect destRect = new NSRect (); | |
282 destRect.x = drawX; | |
283 destRect.y = cellRect.y; | |
284 destRect.width = Math.min (imageSize.width, cellRect.width - 2 * MARGIN); | |
285 destRect.height = Math.min (imageSize.height, cellRect.height); | |
286 bool isFlipped = new NSView (view).isFlipped(); | |
287 if (isFlipped) { | |
288 context.saveGraphicsState (); | |
289 NSAffineTransform transform = NSAffineTransform.transform (); | |
290 transform.scaleXBy (1, -1); | |
291 transform.translateXBy (0, -(destRect.height + 2 * destRect.y)); | |
292 transform.concat (); | |
293 } | |
294 NSRect sourceRect = new NSRect (); | |
295 sourceRect.width = destRect.width; | |
296 sourceRect.height = destRect.height; | |
297 image.handle.drawInRect (destRect, sourceRect, OS.NSCompositeSourceOver, 1f); | |
298 if (isFlipped) context.restoreGraphicsState (); | |
299 drawX += destRect.width; | |
300 } | |
301 | |
302 if (displayText !is null && displayText.length () > 0) { | |
303 if (image !is null) drawX += MARGIN; /* space between image and text */ | |
304 NSRect destRect = new NSRect (); | |
305 destRect.x = drawX; | |
306 destRect.y = cellRect.y; | |
307 destRect.width = Math.min (stringSize.width, cellRect.x + cellRect.width - MARGIN - drawX); | |
308 destRect.height = Math.min (stringSize.height, cellRect.height); | |
309 attrString.drawInRect (destRect); | |
310 attrString.release (); | |
311 } | |
312 | |
313 context.restoreGraphicsState (); | |
195 } | 314 } |
196 | 315 |
197 /** | 316 /** |
198 * Returns a value which describes the position of the | 317 * Returns a value which describes the position of the |
199 * text or image in the receiver. The value will be one of | 318 * text or image in the receiver. The value will be one of |
322 * </ul> | 441 * </ul> |
323 * | 442 * |
324 */ | 443 */ |
325 public void pack () { | 444 public void pack () { |
326 checkWidget (); | 445 checkWidget (); |
327 // GC gc = new GC (parent); | 446 |
328 // int width = gc.stringExtent (text).x; | 447 int width = 0; |
329 //TODO extra header | 448 |
330 // int index = parent.indexOf (this); | 449 /* compute header width */ |
331 // width = Math.max (width, calculateWidth (parent.childIds, index, gc, width)); | 450 if (displayText !is null) { |
332 // | 451 NSMutableDictionary dict = NSMutableDictionary.dictionaryWithCapacity (4); |
333 // gc.dispose (); | 452 NSTableHeaderCell headerCell = nsColumn.headerCell (); |
334 // setWidth (width + parent.getInsetWidth (id, true)); | 453 dict.setObject (headerCell.font (), OS.NSFontAttributeName); |
335 //TODO this only takes care of the header | 454 NSString string = NSString.stringWith (displayText); |
336 nsColumn.sizeToFit(); | 455 NSAttributedString attrString = ((NSAttributedString)new NSAttributedString ().alloc ()).initWithString (string, dict); |
456 NSSize stringSize = attrString.size (); | |
457 attrString.release (); | |
458 width += Math.ceil (stringSize.width); | |
459 if (image !is null) width += MARGIN; /* space between image and text */ | |
460 } | |
461 if (image !is null) { | |
462 NSSize imageSize = image.handle.size (); | |
463 width += Math.ceil (imageSize.width); | |
464 } | |
465 if (parent.sortColumn is this && parent.sortDirection !is DWT.NONE) { | |
466 NSTableHeaderCell headerCell = nsColumn.headerCell (); | |
467 NSRect rect = new NSRect (); | |
468 rect.width = rect.height = Float.MAX_VALUE; | |
469 NSSize cellSize = headerCell.cellSizeForBounds (rect); | |
470 rect.height = cellSize.height; | |
471 NSRect sortRect = headerCell.sortIndicatorRectForBounds (rect); | |
472 width += Math.ceil (sortRect.width); | |
473 } | |
474 | |
475 /* compute item widths down column */ | |
476 GC gc = new GC (parent); | |
477 int index = parent.indexOf (this); | |
478 for (int i=0; i<parent.itemCount; i++) { | |
479 TreeItem item = parent.items [i]; | |
480 if (item !is null && !item.isDisposed () && item.cached) { | |
481 width = Math.max (width, item.calculateWidth (index, gc, true, true)); | |
482 if (isDisposed ()) { | |
483 gc.dispose (); | |
484 return; | |
485 } | |
486 if (gc.isDisposed ()) gc = new GC (parent); | |
487 } | |
488 } | |
489 gc.dispose (); | |
490 setWidth (width + parent.getInsetWidth ()); | |
337 } | 491 } |
338 | 492 |
339 void releaseHandle () { | 493 void releaseHandle () { |
340 super.releaseHandle (); | 494 super.releaseHandle (); |
341 if (nsColumn !is null) nsColumn.release(); | 495 if (nsColumn !is null) { |
496 nsColumn.headerCell ().release (); | |
497 nsColumn.release (); | |
498 } | |
342 nsColumn = null; | 499 nsColumn = null; |
343 parent = null; | 500 parent = null; |
344 } | 501 } |
345 | 502 |
346 void releaseWidget () { | 503 void releaseWidget () { |
402 | 559 |
403 /** | 560 /** |
404 * Controls how text and images will be displayed in the receiver. | 561 * Controls how text and images will be displayed in the receiver. |
405 * The argument should be one of <code>LEFT</code>, <code>RIGHT</code> | 562 * The argument should be one of <code>LEFT</code>, <code>RIGHT</code> |
406 * or <code>CENTER</code>. | 563 * or <code>CENTER</code>. |
407 * | 564 * <p> |
565 * Note that due to a restriction on some platforms, the first column | |
566 * is always left aligned. | |
567 * </p> | |
408 * @param alignment the new alignment | 568 * @param alignment the new alignment |
409 * | 569 * |
410 * @exception DWTException <ul> | 570 * @exception DWTException <ul> |
411 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 571 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
412 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 572 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
417 if ((alignment & (DWT.LEFT | DWT.RIGHT | DWT.CENTER)) is 0) return; | 577 if ((alignment & (DWT.LEFT | DWT.RIGHT | DWT.CENTER)) is 0) return; |
418 int index = parent.indexOf (this); | 578 int index = parent.indexOf (this); |
419 if (index is -1 || index is 0) return; | 579 if (index is -1 || index is 0) return; |
420 style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); | 580 style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); |
421 style |= alignment & (DWT.LEFT | DWT.RIGHT | DWT.CENTER); | 581 style |= alignment & (DWT.LEFT | DWT.RIGHT | DWT.CENTER); |
422 //TODO | 582 NSOutlineView outlineView = ((NSOutlineView) parent.view); |
583 NSTableHeaderView headerView = outlineView.headerView (); | |
584 if (headerView is null) return; | |
585 index = (int)/*64*/outlineView.columnWithIdentifier (nsColumn); | |
586 NSRect rect = headerView.headerRectOfColumn (index); | |
587 headerView.setNeedsDisplayInRect (rect); | |
588 rect = outlineView.rectOfColumn (index); | |
589 parent.view.setNeedsDisplayInRect (rect); | |
423 } | 590 } |
424 | 591 |
425 public void setImage (Image image) { | 592 public void setImage (Image image) { |
426 checkWidget(); | 593 checkWidget(); |
427 if (image !is null && image.isDisposed ()) { | 594 if (image !is null && image.isDisposed ()) { |
428 error (DWT.ERROR_INVALID_ARGUMENT); | 595 error (DWT.ERROR_INVALID_ARGUMENT); |
429 } | 596 } |
430 // int index = parent.indexOf (this); | 597 super.setImage (image); |
431 // if (index is -1) return; | 598 NSTableHeaderView headerView = ((NSOutlineView) parent.view).headerView (); |
432 // if (iconRef !is 0) { | 599 if (headerView is null) return; |
433 // OS.ReleaseIconRef (iconRef); | 600 int /*long*/ index = ((NSOutlineView)parent.view).columnWithIdentifier (nsColumn); |
434 // iconRef = 0; | 601 NSRect rect = headerView.headerRectOfColumn (index); |
435 // } | 602 headerView.setNeedsDisplayInRect (rect); |
436 // super.setImage (image); | |
437 // if (image !is null) { | |
438 // if (OS.VERSION < 0x1040) { | |
439 // iconRef = createIconRef (image); | |
440 // } | |
441 // } | |
442 // updateHeader (); | |
443 } | 603 } |
444 | 604 |
445 /** | 605 /** |
446 * Sets the moveable attribute. A column that is | 606 * Sets the moveable attribute. A column that is |
447 * moveable can be reordered by the user by dragging | 607 * moveable can be reordered by the user by dragging |
463 * | 623 * |
464 * @since 3.2 | 624 * @since 3.2 |
465 */ | 625 */ |
466 public void setMoveable (bool moveable) { | 626 public void setMoveable (bool moveable) { |
467 checkWidget (); | 627 checkWidget (); |
628 // TODO how to make only some columns movable? And handle moveable is false. | |
629 if (moveable) { | |
630 ((NSOutlineView)parent.view).setAllowsColumnReordering (true); | |
631 } | |
468 // int [] flags = new int [1]; | 632 // int [] flags = new int [1]; |
469 // OS.GetDataBrowserPropertyFlags (parent.handle, id, flags); | 633 // OS.GetDataBrowserPropertyFlags (parent.handle, id, flags); |
470 // if (moveable) { | 634 // if (moveable) { |
471 // flags [0] |= OS.kDataBrowserListViewMovableColumn; | 635 // flags [0] |= OS.kDataBrowserListViewMovableColumn; |
472 // } else { | 636 // } else { |
497 if (string is null) error (DWT.ERROR_NULL_ARGUMENT); | 661 if (string is null) error (DWT.ERROR_NULL_ARGUMENT); |
498 super.setText (string); | 662 super.setText (string); |
499 char [] buffer = new char [text.length ()]; | 663 char [] buffer = new char [text.length ()]; |
500 text.getChars (0, buffer.length, buffer, 0); | 664 text.getChars (0, buffer.length, buffer, 0); |
501 int length = fixMnemonic (buffer); | 665 int length = fixMnemonic (buffer); |
502 nsColumn.headerCell().setTitle(NSString.stringWithCharacters(buffer, length)); | 666 displayText = new String (buffer, 0, length); |
667 NSString title = NSString.stringWith (displayText); | |
668 nsColumn.headerCell ().setTitle (title); | |
669 NSTableHeaderView headerView = ((NSOutlineView) parent.view).headerView (); | |
670 if (headerView is null) return; | |
671 int /*long*/ index = ((NSOutlineView)parent.view).columnWithIdentifier (nsColumn); | |
672 NSRect rect = headerView.headerRectOfColumn (index); | |
673 headerView.setNeedsDisplayInRect (rect); | |
503 } | 674 } |
504 | 675 |
505 /** | 676 /** |
506 * Sets the receiver's tool tip text to the argument, which | 677 * Sets the receiver's tool tip text to the argument, which |
507 * may be null indicating that no tool tip text should be shown. | 678 * may be null indicating that no tool tip text should be shown. |