comparison dwt/widgets/Composite.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.Composite;
12
13 import dwt.dwthelper.utils;
14
15
16 import dwt.DWT;
17 import dwt.DWTException;
18 import dwt.graphics.Point;
19 import dwt.graphics.Rectangle;
20 import dwt.internal.cocoa.NSArray;
21 import dwt.internal.cocoa.NSEvent;
22 import dwt.internal.cocoa.NSRect;
23 import dwt.internal.cocoa.NSView;
24 import dwt.internal.cocoa.OS;
25 import dwt.internal.cocoa.SWTScrollView;
26 import dwt.internal.cocoa.SWTView;
27
28 /**
29 * Instances of this class are controls which are capable
30 * of containing other controls.
31 * <dl>
32 * <dt><b>Styles:</b></dt>
33 * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
34 * <dt><b>Events:</b></dt>
35 * <dd>(none)</dd>
36 * </dl>
37 * <p>
38 * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
39 * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
40 * They can be used with <code>Composite</code> if you are drawing your own, but their
41 * behavior is undefined if they are used with subclasses of <code>Composite</code> other
42 * than <code>Canvas</code>.
43 * </p><p>
44 * Note: The <code>CENTER</code> style, although undefined for composites, has the
45 * same value as <code>EMBEDDED</code> (which is used to embed widgets from other
46 * widget toolkits into DWT). On some operating systems (GTK, Motif), this may cause
47 * the children of this composite to be obscured. The <code>EMBEDDED</code> style
48 * is for use by other widget toolkits and should normally never be used.
49 * </p><p>
50 * This class may be subclassed by custom control implementors
51 * who are building controls that are constructed from aggregates
52 * of other controls.
53 * </p>
54 *
55 * @see Canvas
56 */
57 public class Composite extends Scrollable {
58 Layout layout;
59 Control[] tabList;
60 int scrolledVisibleRgn, siblingsVisibleRgn;
61 int layoutCount, backgroundMode;
62
63 Composite () {
64 /* Do nothing */
65 }
66
67 /**
68 * Constructs a new instance of this class given its parent
69 * and a style value describing its behavior and appearance.
70 * <p>
71 * The style value is either one of the style constants defined in
72 * class <code>DWT</code> which is applicable to instances of this
73 * class, or must be built by <em>bitwise OR</em>'ing together
74 * (that is, using the <code>int</code> "|" operator) two or more
75 * of those <code>DWT</code> style constants. The class description
76 * lists the style constants that are applicable to the class.
77 * Style bits are also inherited from superclasses.
78 * </p>
79 *
80 * @param parent a widget which will be the parent of the new instance (cannot be null)
81 * @param style the style of widget to construct
82 *
83 * @exception IllegalArgumentException <ul>
84 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
85 * </ul>
86 * @exception DWTException <ul>
87 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
88 * </ul>
89 *
90 * @see DWT#NO_BACKGROUND
91 * @see DWT#NO_FOCUS
92 * @see DWT#NO_MERGE_PAINTS
93 * @see DWT#NO_REDRAW_RESIZE
94 * @see DWT#NO_RADIO_GROUP
95 * @see Widget#getStyle
96 */
97 public Composite (Composite parent, int style) {
98 super (parent, style);
99 }
100
101 Control [] _getChildren () {
102 NSArray views = contentView().subviews();
103 int count = views.count();
104 Control [] children = new Control [count];
105 int j = 0;
106 for (int i=0; i<count; i++){
107 int tag = new NSView(views.objectAtIndex(i)).tag();
108 if (tag !is 0 && tag !is -1) {
109 Object widget = OS.JNIGetObject(tag);
110 if (widget !is null && widget !is this) {
111 if (widget instanceof Control) {
112 children [j++] = (Control) widget;
113 }
114 }
115 }
116 }
117 if (j is count) return children;
118 Control [] newChildren = new Control [j];
119 System.arraycopy (children, 0, newChildren, 0, j);
120 return newChildren;
121 }
122
123 Control [] _getTabList () {
124 if (tabList is null) return null;
125 int count = 0;
126 for (int i=0; i<tabList.length; i++) {
127 if (!tabList [i].isDisposed ()) count++;
128 }
129 if (count is tabList.length) return tabList;
130 Control [] newList = new Control [count];
131 int index = 0;
132 for (int i=0; i<tabList.length; i++) {
133 if (!tabList [i].isDisposed ()) {
134 newList [index++] = tabList [i];
135 }
136 }
137 tabList = newList;
138 return tabList;
139 }
140
141 bool acceptsFirstResponder () {
142 if ((state & CANVAS) !is 0) {
143 return ((style & DWT.NO_FOCUS) is 0);
144 }
145 return super.acceptsFirstResponder ();
146 }
147
148
149 /**
150 * Clears any data that has been cached by a Layout for all widgets that
151 * are in the parent hierarchy of the changed control up to and including the
152 * receiver. If an ancestor does not have a layout, it is skipped.
153 *
154 * @param changed an array of controls that changed state and require a recalculation of size
155 *
156 * @exception IllegalArgumentException <ul>
157 * <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
158 * <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
159 * </ul>
160 * @exception DWTException <ul>
161 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
162 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
163 * </ul>
164 *
165 * @since 3.1
166 */
167 public void changed (Control[] changed) {
168 checkWidget ();
169 if (changed is null) error (DWT.ERROR_INVALID_ARGUMENT);
170 for (int i=0; i<changed.length; i++) {
171 Control control = changed [i];
172 if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
173 if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
174 bool ancestor = false;
175 Composite composite = control.parent;
176 while (composite !is null) {
177 ancestor = composite is this;
178 if (ancestor) break;
179 composite = composite.parent;
180 }
181 if (!ancestor) error (DWT.ERROR_INVALID_PARENT);
182 }
183 for (int i=0; i<changed.length; i++) {
184 Control child = changed [i];
185 Composite composite = child.parent;
186 while (child !is this) {
187 if (composite.layout is null || !composite.layout.flushCache (child)) {
188 composite.state |= LAYOUT_CHANGED;
189 }
190 child = composite;
191 composite = child.parent;
192 }
193 }
194 }
195
196 public Point computeSize (int wHint, int hHint, bool changed) {
197 checkWidget();
198 Point size;
199 if (layout !is null) {
200 if ((wHint is DWT.DEFAULT) || (hHint is DWT.DEFAULT)) {
201 changed |= (state & LAYOUT_CHANGED) !is 0;
202 size = layout.computeSize (this, wHint, hHint, changed);
203 state &= ~LAYOUT_CHANGED;
204 } else {
205 size = new Point (wHint, hHint);
206 }
207 } else {
208 size = minimumSize (wHint, hHint, changed);
209 }
210 if (size.x is 0) size.x = DEFAULT_WIDTH;
211 if (size.y is 0) size.y = DEFAULT_HEIGHT;
212 if (wHint !is DWT.DEFAULT) size.x = wHint;
213 if (hHint !is DWT.DEFAULT) size.y = hHint;
214 Rectangle trim = computeTrim (0, 0, size.x, size.y);
215 return new Point (trim.width, trim.height);
216 }
217
218 protected void checkSubclass () {
219 /* Do nothing - Subclassing is allowed */
220 }
221
222 Control [] computeTabList () {
223 Control result [] = super.computeTabList ();
224 if (result.length is 0) return result;
225 Control [] list = tabList !is null ? _getTabList () : _getChildren ();
226 for (int i=0; i<list.length; i++) {
227 Control child = list [i];
228 Control [] childList = child.computeTabList ();
229 if (childList.length !is 0) {
230 Control [] newResult = new Control [result.length + childList.length];
231 System.arraycopy (result, 0, newResult, 0, result.length);
232 System.arraycopy (childList, 0, newResult, result.length, childList.length);
233 result = newResult;
234 }
235 }
236 return result;
237 }
238
239 NSView contentView () {
240 return view;
241 }
242
243 void createHandle () {
244 createHandle (parent.contentView());
245 }
246
247 void createHandle (NSView parent) {
248 state |= CANVAS;
249 NSRect rect = new NSRect();
250 if ((style & (DWT.V_SCROLL | DWT.H_SCROLL)) !is 0 || hasBorder ()) {
251 SWTScrollView scrollWidget = (SWTScrollView)new SWTScrollView().alloc();
252 scrollWidget.initWithFrame (rect);
253 scrollWidget.setDrawsBackground(false);
254 if ((style & DWT.H_SCROLL) !is 0) scrollWidget.setHasHorizontalScroller(true);
255 if ((style & DWT.V_SCROLL) !is 0) scrollWidget.setHasVerticalScroller(true);
256 scrollWidget.setBorderType(hasBorder() ? OS.NSBezelBorder : OS.NSNoBorder);
257 scrollWidget.setTag(jniRef);
258 scrollView = scrollWidget;
259 rect.width = rect.height = 100000;
260 }
261 SWTView widget = (SWTView)new SWTView().alloc();
262 widget.initWithFrame (rect);
263 // widget.setFocusRingType(OS.NSFocusRingTypeExterior);
264 widget.setTag(jniRef);
265 view = widget;
266 if (scrollView !is null) {
267 // view.setAutoresizingMask (OS.NSViewWidthSizable | OS.NSViewHeightSizable);
268 scrollView.setDocumentView(view);
269 if (parent !is null) parent.addSubview_(scrollView);
270 } else {
271 if (parent !is null) parent.addSubview_(view);
272 }
273 }
274
275 Composite findDeferredControl () {
276 return layoutCount > 0 ? this : parent.findDeferredControl ();
277 }
278
279 Menu [] findMenus (Control control) {
280 if (control is this) return new Menu [0];
281 Menu result [] = super.findMenus (control);
282 Control [] children = _getChildren ();
283 for (int i=0; i<children.length; i++) {
284 Control child = children [i];
285 Menu [] menuList = child.findMenus (control);
286 if (menuList.length !is 0) {
287 Menu [] newResult = new Menu [result.length + menuList.length];
288 System.arraycopy (result, 0, newResult, 0, result.length);
289 System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
290 result = newResult;
291 }
292 }
293 return result;
294 }
295
296 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
297 super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
298 Control [] children = _getChildren ();
299 for (int i=0; i<children.length; i++) {
300 children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
301 }
302 }
303
304 void fixTabList (Control control) {
305 if (tabList is null) return;
306 int count = 0;
307 for (int i=0; i<tabList.length; i++) {
308 if (tabList [i] is control) count++;
309 }
310 if (count is 0) return;
311 Control [] newList = null;
312 int length = tabList.length - count;
313 if (length !is 0) {
314 newList = new Control [length];
315 int index = 0;
316 for (int i=0; i<tabList.length; i++) {
317 if (tabList [i] !is control) {
318 newList [index++] = tabList [i];
319 }
320 }
321 }
322 tabList = newList;
323 }
324
325 /**
326 * Returns the receiver's background drawing mode. This
327 * will be one of the following constants defined in class
328 * <code>DWT</code>:
329 * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
330 * <code>INHERTIT_FORCE</code>.
331 *
332 * @return the background mode
333 *
334 * @exception DWTException <ul>
335 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
336 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
337 * </ul>
338 *
339 * @see DWT
340 *
341 * @since 3.2
342 */
343 public int getBackgroundMode () {
344 checkWidget ();
345 return backgroundMode;
346 }
347
348 /**
349 * Returns a (possibly empty) array containing the receiver's children.
350 * Children are returned in the order that they are drawn. The topmost
351 * control appears at the beginning of the array. Subsequent controls
352 * draw beneath this control and appear later in the array.
353 * <p>
354 * Note: This is not the actual structure used by the receiver
355 * to maintain its list of children, so modifying the array will
356 * not affect the receiver.
357 * </p>
358 *
359 * @return an array of children
360 *
361 * @see Control#moveAbove
362 * @see Control#moveBelow
363 *
364 * @exception DWTException <ul>
365 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
366 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
367 * </ul>
368 */
369 public Control [] getChildren () {
370 checkWidget();
371 return _getChildren ();
372 }
373
374 int getChildrenCount () {
375 /*
376 * NOTE: The current implementation will count
377 * non-registered children.
378 */
379 // short [] count = new short [1];
380 // OS.CountSubControls (handle, count);
381 // return count [0];
382 return 0;
383 }
384
385 /**
386 * Returns layout which is associated with the receiver, or
387 * null if one has not been set.
388 *
389 * @return the receiver's layout or null
390 *
391 * @exception DWTException <ul>
392 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
393 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
394 * </ul>
395 */
396 public Layout getLayout () {
397 checkWidget();
398 return layout;
399 }
400
401 /**
402 * Returns <code>true</code> if the receiver has deferred
403 * the performing of layout, and <code>false</code> otherwise.
404 *
405 * @return the receiver's deferred layout state
406 *
407 * @exception DWTException <ul>
408 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
409 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
410 * </ul>
411 *
412 * @see #setLayoutDeferred(bool)
413 * @see #isLayoutDeferred()
414 *
415 * @since 3.1
416 */
417 public bool getLayoutDeferred () {
418 checkWidget ();
419 return layoutCount > 0 ;
420 }
421
422 /**
423 * Gets the (possibly empty) tabbing order for the control.
424 *
425 * @return tabList the ordered list of controls representing the tab order
426 *
427 * @exception DWTException <ul>
428 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
429 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
430 * </ul>
431 *
432 * @see #setTabList
433 */
434 public Control [] getTabList () {
435 checkWidget ();
436 Control [] tabList = _getTabList ();
437 if (tabList is null) {
438 int count = 0;
439 Control [] list =_getChildren ();
440 for (int i=0; i<list.length; i++) {
441 if (list [i].isTabGroup ()) count++;
442 }
443 tabList = new Control [count];
444 int index = 0;
445 for (int i=0; i<list.length; i++) {
446 if (list [i].isTabGroup ()) {
447 tabList [index++] = list [i];
448 }
449 }
450 }
451 return tabList;
452 }
453
454 bool hooksKeys () {
455 return hooks (DWT.KeyDown) || hooks (DWT.KeyUp);
456 }
457
458 /**
459 * Returns <code>true</code> if the receiver or any ancestor
460 * up to and including the receiver's nearest ancestor shell
461 * has deferred the performing of layouts. Otherwise, <code>false</code>
462 * is returned.
463 *
464 * @return the receiver's deferred layout state
465 *
466 * @exception DWTException <ul>
467 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
468 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
469 * </ul>
470 *
471 * @see #setLayoutDeferred(bool)
472 * @see #getLayoutDeferred()
473 *
474 * @since 3.1
475 */
476 public bool isLayoutDeferred () {
477 checkWidget ();
478 return findDeferredControl () !is null;
479 }
480
481 bool isTabGroup () {
482 if ((state & CANVAS) !is 0) return true;
483 return super.isTabGroup ();
484 }
485
486 /**
487 * If the receiver has a layout, asks the layout to <em>lay out</em>
488 * (that is, set the size and location of) the receiver's children.
489 * If the receiver does not have a layout, do nothing.
490 * <p>
491 * This is equivalent to calling <code>layout(true)</code>.
492 * </p>
493 * <p>
494 * Note: Layout is different from painting. If a child is
495 * moved or resized such that an area in the parent is
496 * exposed, then the parent will paint. If no child is
497 * affected, the parent will not paint.
498 * </p>
499 *
500 * @exception DWTException <ul>
501 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
502 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
503 * </ul>
504 */
505 public void layout () {
506 checkWidget ();
507 layout (true);
508 }
509
510 /**
511 * If the receiver has a layout, asks the layout to <em>lay out</em>
512 * (that is, set the size and location of) the receiver's children.
513 * If the argument is <code>true</code> the layout must not rely
514 * on any information it has cached about the immediate children. If it
515 * is <code>false</code> the layout may (potentially) optimize the
516 * work it is doing by assuming that none of the receiver's
517 * children has changed state since the last layout.
518 * If the receiver does not have a layout, do nothing.
519 * <p>
520 * If a child is resized as a result of a call to layout, the
521 * resize event will invoke the layout of the child. The layout
522 * will cascade down through all child widgets in the receiver's widget
523 * tree until a child is encountered that does not resize. Note that
524 * a layout due to a resize will not flush any cached information
525 * (same as <code>layout(false)</code>).
526 * </p>
527 * <p>
528 * Note: Layout is different from painting. If a child is
529 * moved or resized such that an area in the parent is
530 * exposed, then the parent will paint. If no child is
531 * affected, the parent will not paint.
532 * </p>
533 *
534 * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
535 *
536 * @exception DWTException <ul>
537 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
538 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
539 * </ul>
540 */
541 public void layout (bool changed) {
542 checkWidget ();
543 if (layout is null) return;
544 layout (changed, false);
545 }
546
547 /**
548 * If the receiver has a layout, asks the layout to <em>lay out</em>
549 * (that is, set the size and location of) the receiver's children.
550 * If the changed argument is <code>true</code> the layout must not rely
551 * on any information it has cached about its children. If it
552 * is <code>false</code> the layout may (potentially) optimize the
553 * work it is doing by assuming that none of the receiver's
554 * children has changed state since the last layout.
555 * If the all argument is <code>true</code> the layout will cascade down
556 * through all child widgets in the receiver's widget tree, regardless of
557 * whether the child has changed size. The changed argument is applied to
558 * all layouts. If the all argument is <code>false</code>, the layout will
559 * <em>not</em> cascade down through all child widgets in the receiver's widget
560 * tree. However, if a child is resized as a result of a call to layout, the
561 * resize event will invoke the layout of the child. Note that
562 * a layout due to a resize will not flush any cached information
563 * (same as <code>layout(false)</code>).
564 * </p>
565 * <p>
566 * Note: Layout is different from painting. If a child is
567 * moved or resized such that an area in the parent is
568 * exposed, then the parent will paint. If no child is
569 * affected, the parent will not paint.
570 * </p>
571 *
572 * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
573 * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
574 *
575 * @exception DWTException <ul>
576 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
577 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
578 * </ul>
579 *
580 * @since 3.1
581 */
582 public void layout (bool changed, bool all) {
583 checkWidget ();
584 if (layout is null && !all) return;
585 markLayout (changed, all);
586 updateLayout (all);
587 }
588
589 /**
590 * Forces a lay out (that is, sets the size and location) of all widgets that
591 * are in the parent hierarchy of the changed control up to and including the
592 * receiver. The layouts in the hierarchy must not rely on any information
593 * cached about the changed control or any of its ancestors. The layout may
594 * (potentially) optimize the work it is doing by assuming that none of the
595 * peers of the changed control have changed state since the last layout.
596 * If an ancestor does not have a layout, skip it.
597 * <p>
598 * Note: Layout is different from painting. If a child is
599 * moved or resized such that an area in the parent is
600 * exposed, then the parent will paint. If no child is
601 * affected, the parent will not paint.
602 * </p>
603 *
604 * @param changed a control that has had a state change which requires a recalculation of its size
605 *
606 * @exception IllegalArgumentException <ul>
607 * <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
608 * <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
609 * </ul>
610 * @exception DWTException <ul>
611 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
612 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
613 * </ul>
614 *
615 * @since 3.1
616 */
617 public void layout (Control [] changed) {
618 checkWidget ();
619 if (changed is null) error (DWT.ERROR_INVALID_ARGUMENT);
620 for (int i=0; i<changed.length; i++) {
621 Control control = changed [i];
622 if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
623 if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
624 bool ancestor = false;
625 Composite composite = control.parent;
626 while (composite !is null) {
627 ancestor = composite is this;
628 if (ancestor) break;
629 composite = composite.parent;
630 }
631 if (!ancestor) error (DWT.ERROR_INVALID_PARENT);
632 }
633 int updateCount = 0;
634 Composite [] update = new Composite [16];
635 for (int i=0; i<changed.length; i++) {
636 Control child = changed [i];
637 Composite composite = child.parent;
638 while (child !is this) {
639 if (composite.layout !is null) {
640 composite.state |= LAYOUT_NEEDED;
641 if (!composite.layout.flushCache (child)) {
642 composite.state |= LAYOUT_CHANGED;
643 }
644 }
645 if (updateCount is update.length) {
646 Composite [] newUpdate = new Composite [update.length + 16];
647 System.arraycopy (update, 0, newUpdate, 0, update.length);
648 update = newUpdate;
649 }
650 child = update [updateCount++] = composite;
651 composite = child.parent;
652 }
653 }
654 for (int i=updateCount-1; i>=0; i--) {
655 update [i].updateLayout (false);
656 }
657 }
658
659 void markLayout (bool changed, bool all) {
660 if (layout !is null) {
661 state |= LAYOUT_NEEDED;
662 if (changed) state |= LAYOUT_CHANGED;
663 }
664 if (all) {
665 Control [] children = _getChildren ();
666 for (int i=0; i<children.length; i++) {
667 children [i].markLayout (changed, all);
668 }
669 }
670 }
671
672 Point minimumSize (int wHint, int Hint, bool changed) {
673 Control [] children = _getChildren ();
674 int width = 0, height = 0;
675 for (int i=0; i<children.length; i++) {
676 Rectangle rect = children [i].getBounds ();
677 width = Math.max (width, rect.x + rect.width);
678 height = Math.max (height, rect.y + rect.height);
679 }
680 return new Point (width, height);
681 }
682
683 void releaseChildren (bool destroy) {
684 Control [] children = _getChildren ();
685 for (int i=0; i<children.length; i++) {
686 Control child = children [i];
687 if (child !is null && !child.isDisposed ()) {
688 child.release (false);
689 }
690 }
691 super.releaseChildren (destroy);
692 }
693
694 void releaseWidget () {
695 super.releaseWidget ();
696 layout = null;
697 tabList = null;
698 }
699
700 void removeControl (Control control) {
701 fixTabList (control);
702 }
703
704 /**
705 * Sets the background drawing mode to the argument which should
706 * be one of the following constants defined in class <code>DWT</code>:
707 * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
708 * <code>INHERIT_FORCE</code>.
709 *
710 * @param mode the new background mode
711 *
712 * @exception DWTException <ul>
713 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
714 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
715 * </ul>
716 *
717 * @see DWT
718 *
719 * @since 3.2
720 */
721 public void setBackgroundMode (int mode) {
722 checkWidget ();
723 backgroundMode = mode;
724 Control [] children = _getChildren ();
725 for (int i = 0; i < children.length; i++) {
726 children [i].updateBackgroundMode ();
727 }
728 }
729
730 int setBounds (int x, int y, int width, int height, bool move, bool resize) {
731 int result = super.setBounds (x, y, width, height, move, resize);
732 if (layout !is null && (result & RESIZED) !is 0) {
733 markLayout (false, false);
734 updateLayout (false);
735 }
736 return result;
737 }
738
739 public bool setFocus () {
740 checkWidget ();
741 Control [] children = _getChildren ();
742 for (int i= 0; i < children.length; i++) {
743 if (children [i].setFocus ()) return true;
744 }
745 return super.setFocus ();
746 }
747
748 /**
749 * Sets the layout which is associated with the receiver to be
750 * the argument which may be null.
751 *
752 * @param layout the receiver's new layout or null
753 *
754 * @exception DWTException <ul>
755 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
756 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
757 * </ul>
758 */
759 public void setLayout (Layout layout) {
760 checkWidget();
761 this.layout = layout;
762 }
763
764 /**
765 * If the argument is <code>true</code>, causes subsequent layout
766 * operations in the receiver or any of its children to be ignored.
767 * No layout of any kind can occur in the receiver or any of its
768 * children until the flag is set to false.
769 * Layout operations that occurred while the flag was
770 * <code>true</code> are remembered and when the flag is set to
771 * <code>false</code>, the layout operations are performed in an
772 * optimized manner. Nested calls to this method are stacked.
773 *
774 * @param defer the new defer state
775 *
776 * @exception DWTException <ul>
777 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
778 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
779 * </ul>
780 *
781 * @see #layout(bool)
782 * @see #layout(Control[])
783 *
784 * @since 3.1
785 */
786 public void setLayoutDeferred (bool defer) {
787 if (!defer) {
788 if (--layoutCount is 0) {
789 if ((state & LAYOUT_CHILD) !is 0 || (state & LAYOUT_NEEDED) !is 0) {
790 updateLayout (true);
791 }
792 }
793 } else {
794 layoutCount++;
795 }
796 }
797
798
799 bool setScrollBarVisible (ScrollBar bar, bool visible) {
800 bool changed = super.setScrollBarVisible (bar, visible);
801 if (changed && layout !is null) {
802 markLayout (false, false);
803 updateLayout (false);
804 }
805 return changed;
806 }
807
808 bool setTabGroupFocus () {
809 if (isTabItem ()) return setTabItemFocus ();
810 bool takeFocus = (style & DWT.NO_FOCUS) is 0;
811 if ((state & CANVAS) !is 0) takeFocus = hooksKeys ();
812 if (takeFocus && setTabItemFocus ()) return true;
813 Control [] children = _getChildren ();
814 for (int i=0; i<children.length; i++) {
815 Control child = children [i];
816 if (child.isTabItem () && child.setTabItemFocus ()) return true;
817 }
818 return false;
819 }
820
821 /**
822 * Sets the tabbing order for the specified controls to
823 * match the order that they occur in the argument list.
824 *
825 * @param tabList the ordered list of controls representing the tab order or null
826 *
827 * @exception IllegalArgumentException <ul>
828 * <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
829 * <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
830 * </ul>
831 * @exception DWTException <ul>
832 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
833 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
834 * </ul>
835 */
836 public void setTabList (Control [] tabList) {
837 checkWidget ();
838 if (tabList !is null) {
839 for (int i=0; i<tabList.length; i++) {
840 Control control = tabList [i];
841 if (control is null) error (DWT.ERROR_INVALID_ARGUMENT);
842 if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
843 if (control.parent !is this) error (DWT.ERROR_INVALID_PARENT);
844 }
845 Control [] newList = new Control [tabList.length];
846 System.arraycopy (tabList, 0, newList, 0, tabList.length);
847 tabList = newList;
848 }
849 this.tabList = tabList;
850 }
851
852 int traversalCode (int key, NSEvent theEvent) {
853 if ((state & CANVAS) !is 0) {
854 if ((style & DWT.NO_FOCUS) !is 0) return 0;
855 if (hooksKeys ()) return 0;
856 }
857 return super.traversalCode (key, theEvent);
858 }
859
860 void updateBackgroundMode () {
861 super.updateBackgroundMode ();
862 Control [] children = _getChildren ();
863 for (int i = 0; i < children.length; i++) {
864 children [i].updateBackgroundMode ();
865 }
866 }
867
868 void updateLayout (bool all) {
869 Composite parent = findDeferredControl ();
870 if (parent !is null) {
871 parent.state |= LAYOUT_CHILD;
872 return;
873 }
874 if ((state & LAYOUT_NEEDED) !is 0) {
875 bool changed = (state & LAYOUT_CHANGED) !is 0;
876 state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
877 layout.layout (this, changed);
878 }
879 if (all) {
880 state &= ~LAYOUT_CHILD;
881 Control [] children = _getChildren ();
882 for (int i=0; i<children.length; i++) {
883 children [i].updateLayout (all);
884 }
885 }
886 }
887
888 }