comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/CoolBar.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 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 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.widgets.CoolBar;
14
15 import org.eclipse.swt.widgets.Composite;
16
17
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.SWTException;
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.graphics.Rectangle;
22 import org.eclipse.swt.internal.win32.OS;
23
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.CoolItem;
27 import org.eclipse.swt.widgets.Event;
28
29 import java.lang.all;
30
31 /**
32 * Instances of this class provide an area for dynamically
33 * positioning the items they contain.
34 * <p>
35 * The item children that may be added to instances of this class
36 * must be of type <code>CoolItem</code>.
37 * </p><p>
38 * Note that although this class is a subclass of <code>Composite</code>,
39 * it does not make sense to add <code>Control</code> children to it,
40 * or set a layout on it.
41 * </p><p>
42 * <dl>
43 * <dt><b>Styles:</b></dt>
44 * <dd>FLAT, HORIZONTAL, VERTICAL</dd>
45 * <dt><b>Events:</b></dt>
46 * <dd>(none)</dd>
47 * </dl>
48 * </p><p>
49 * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
50 * </p><p>
51 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
52 * </p>
53 *
54 * @see <a href="http://www.eclipse.org/swt/snippets/#coolbar">CoolBar snippets</a>
55 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
56 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
57 */
58
59 public class CoolBar : Composite {
60
61 alias Composite.computeSize computeSize;
62 alias Composite.windowProc windowProc;
63
64 CoolItem [] items;
65 CoolItem [] originalItems;
66 bool locked;
67 bool ignoreResize;
68 private static /+const+/ WNDPROC ReBarProc;
69 static const TCHAR* ReBarClass = OS.REBARCLASSNAME.ptr;
70
71 private static bool static_this_completed = false;
72 private static void static_this() {
73 if( static_this_completed ){
74 return;
75 }
76 synchronized {
77 if( static_this_completed ){
78 return;
79 }
80 INITCOMMONCONTROLSEX icex;
81 icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
82 icex.dwICC = OS.ICC_COOL_CLASSES;
83 OS.InitCommonControlsEx (&icex);
84 WNDCLASS lpWndClass;
85 OS.GetClassInfo (null, ReBarClass, &lpWndClass);
86 ReBarProc = lpWndClass.lpfnWndProc;
87 static_this_completed = true;
88 }
89 }
90
91 static const int SEPARATOR_WIDTH = 2;
92 static const int MAX_WIDTH = 0x7FFF;
93 static const int DEFAULT_COOLBAR_WIDTH = 0;
94 static const int DEFAULT_COOLBAR_HEIGHT = 0;
95
96 /**
97 * Constructs a new instance of this class given its parent
98 * and a style value describing its behavior and appearance.
99 * <p>
100 * The style value is either one of the style constants defined in
101 * class <code>SWT</code> which is applicable to instances of this
102 * class, or must be built by <em>bitwise OR</em>'ing together
103 * (that is, using the <code>int</code> "|" operator) two or more
104 * of those <code>SWT</code> style constants. The class description
105 * lists the style constants that are applicable to the class.
106 * Style bits are also inherited from superclasses.
107 * </p>
108 *
109 * @param parent a composite control which will be the parent of the new instance (cannot be null)
110 * @param style the style of control to construct
111 *
112 * @exception IllegalArgumentException <ul>
113 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
114 * </ul>
115 * @exception SWTException <ul>
116 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
117 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
118 * </ul>
119 *
120 * @see SWT
121 * @see Widget#checkSubclass
122 * @see Widget#getStyle
123 */
124 public this (Composite parent, int style) {
125 static_this();
126 super (parent, checkStyle (style));
127 /*
128 * Ensure that either of HORIZONTAL or VERTICAL is set.
129 * NOTE: HORIZONTAL and VERTICAL have the same values
130 * as H_SCROLL and V_SCROLL so it is necessary to first
131 * clear these bits to avoid scroll bars and then reset
132 * the bits using the original style supplied by the
133 * programmer.
134 *
135 * NOTE: The CCS_VERT style cannot be applied when the
136 * widget is created because of this conflict.
137 */
138 if ((style & SWT.VERTICAL) !is 0) {
139 this.style |= SWT.VERTICAL;
140 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
141 OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
142 } else {
143 this.style |= SWT.HORIZONTAL;
144 }
145 }
146
147 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
148 if (handle is null) return 0;
149 return OS.CallWindowProc (ReBarProc, hwnd, msg, wParam, lParam);
150 }
151
152 static int checkStyle (int style) {
153 style |= SWT.NO_FOCUS;
154 /*
155 * Even though it is legal to create this widget
156 * with scroll bars, they serve no useful purpose
157 * because they do not automatically scroll the
158 * widget's client area. The fix is to clear
159 * the SWT style.
160 */
161 return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
162 }
163
164 override protected void checkSubclass () {
165 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
166 }
167
168 override public Point computeSize (int wHint, int hHint, bool changed) {
169 checkWidget ();
170 int width = 0, height = 0;
171 int border = getBorderWidth ();
172 int newWidth = wHint is SWT.DEFAULT ? 0x3FFF : wHint + (border * 2);
173 int newHeight = hHint is SWT.DEFAULT ? 0x3FFF : hHint + (border * 2);
174 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
175 if (count !is 0) {
176 ignoreResize = true;
177 bool redraw = false;
178 if (OS.IsWindowVisible (handle)) {
179 if (OS.COMCTL32_MAJOR >= 6) {
180 redraw = true;
181 OS.UpdateWindow (handle);
182 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
183 } else {
184 redraw = drawCount is 0;
185 if (redraw) {
186 OS.UpdateWindow (handle);
187 OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
188 }
189 }
190 }
191 RECT oldRect;
192 OS.GetWindowRect (handle, &oldRect);
193 int oldWidth = oldRect.right - oldRect.left;
194 int oldHeight = oldRect.bottom - oldRect.top;
195 int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
196 SetWindowPos (handle, null, 0, 0, newWidth, newHeight, flags);
197 RECT rect;
198 OS.SendMessage (handle, OS.RB_GETRECT, count - 1, &rect);
199 height = Math.max (height, rect.bottom);
200 SetWindowPos (handle, null, 0, 0, oldWidth, oldHeight, flags);
201 REBARBANDINFO rbBand;
202 rbBand.cbSize = REBARBANDINFO.sizeof;
203 rbBand.fMask = OS.RBBIM_IDEALSIZE | OS.RBBIM_STYLE;
204 int rowWidth = 0;
205 for (int i = 0; i < count; i++) {
206 OS.SendMessage(handle, OS.RB_GETBANDINFO, i, &rbBand);
207 if ((rbBand.fStyle & OS.RBBS_BREAK) !is 0) {
208 width = Math.max(width, rowWidth);
209 rowWidth = 0;
210 }
211 rowWidth += rbBand.cxIdeal + getMargin (i);
212 }
213 width = Math.max(width, rowWidth);
214 if (redraw) {
215 if (OS.COMCTL32_MAJOR >= 6) {
216 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
217 } else {
218 OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
219 }
220 }
221 ignoreResize = false;
222 }
223 if (width is 0) width = DEFAULT_COOLBAR_WIDTH;
224 if (height is 0) height = DEFAULT_COOLBAR_HEIGHT;
225 if ((style & SWT.VERTICAL) !is 0) {
226 int tmp = width;
227 width = height;
228 height = tmp;
229 }
230 if (wHint !is SWT.DEFAULT) width = wHint;
231 if (hHint !is SWT.DEFAULT) height = hHint;
232 height += border * 2;
233 width += border * 2;
234 return new Point (width, height);
235 }
236
237 override void createHandle () {
238 super.createHandle ();
239 state &= ~(CANVAS | THEME_BACKGROUND);
240
241 /*
242 * Feature in Windows. When the control is created,
243 * it does not use the default system font. A new HFONT
244 * is created and destroyed when the control is destroyed.
245 * This means that a program that queries the font from
246 * this control, uses the font in another control and then
247 * destroys this control will have the font unexpectedly
248 * destroyed in the other control. The fix is to assign
249 * the font ourselves each time the control is created.
250 * The control will not destroy a font that it did not
251 * create.
252 */
253 auto hFont = OS.GetStockObject (OS.SYSTEM_FONT);
254 OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
255 }
256
257 void createItem (CoolItem item, int index) {
258 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
259 if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
260 int id = 0;
261 while (id < items.length && items [id] !is null) id++;
262 if (id is items.length) {
263 CoolItem [] newItems = new CoolItem [items.length + 4];
264 System.arraycopy (items, 0, newItems, 0, items.length);
265 items = newItems;
266 }
267 auto hHeap = OS.GetProcessHeap ();
268 auto lpText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
269 REBARBANDINFO rbBand;
270 rbBand.cbSize = REBARBANDINFO.sizeof;
271 rbBand.fMask = OS.RBBIM_TEXT | OS.RBBIM_STYLE | OS.RBBIM_ID;
272 rbBand.fStyle = OS.RBBS_VARIABLEHEIGHT | OS.RBBS_GRIPPERALWAYS;
273 if ((item.style & SWT.DROP_DOWN) !is 0) {
274 rbBand.fStyle |= OS.RBBS_USECHEVRON;
275 }
276 rbBand.lpText = lpText;
277 rbBand.wID = id;
278
279 /*
280 * Feature in Windows. When inserting an item at end of a row,
281 * sometimes, Windows will begin to place the item on the right
282 * side of the cool bar. The fix is to resize the new items to
283 * the maximum size and then resize the next to last item to the
284 * ideal size.
285 */
286 int lastIndex = getLastIndexOfRow (index - 1);
287 bool fixLast = index is lastIndex + 1;
288 if (fixLast) {
289 rbBand.fMask |= OS.RBBIM_SIZE;
290 rbBand.cx = MAX_WIDTH;
291 }
292
293 /*
294 * Feature in Windows. Is possible that the item at index zero
295 * has the RBBS_BREAK flag set. When a new item is inserted at
296 * position zero, the previous item at position zero moves to
297 * a new line. The fix is to detect this case and clear the
298 * RBBS_BREAK flag on the previous item before inserting the
299 * new item.
300 */
301 if (index is 0 && count > 0) {
302 getItem (0).setWrap (false);
303 }
304
305 /* Insert the item */
306 if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, &rbBand) is 0) {
307 error (SWT.ERROR_ITEM_NOT_ADDED);
308 }
309
310 /* Resize the next to last item to the ideal size */
311 if (fixLast) {
312 resizeToPreferredWidth (lastIndex);
313 }
314
315 OS.HeapFree (hHeap, 0, lpText);
316 items [item.id = id] = item;
317 int length = originalItems.length;
318 CoolItem [] newOriginals = new CoolItem [length + 1];
319 System.arraycopy (originalItems, 0, newOriginals, 0, index);
320 System.arraycopy (originalItems, index, newOriginals, index + 1, length - index);
321 newOriginals [index] = item;
322 originalItems = newOriginals;
323 }
324
325 override void createWidget () {
326 super.createWidget ();
327 items = new CoolItem [4];
328 originalItems = new CoolItem [0];
329 }
330
331 void destroyItem (CoolItem item) {
332 int index = OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
333 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
334 if (count !is 0) {
335 int lastIndex = getLastIndexOfRow (index);
336 if (index is lastIndex) {
337 /*
338 * Feature in Windows. If the last item in a row is
339 * given its ideal size, it will be placed at the far
340 * right hand edge of the coolbar. It is preferred
341 * that the last item appear next to the second last
342 * item. The fix is to size the last item of each row
343 * so that it occupies all the available space to the
344 * right in the row.
345 */
346 resizeToMaximumWidth (lastIndex - 1);
347 }
348 }
349
350 /*
351 * Feature in Windows. When Windows removed a rebar
352 * band, it makes the band child invisible. The fix
353 * is to show the child.
354 */
355 Control control = item.control;
356 bool wasVisible = control !is null && !control.isDisposed() && control.getVisible ();
357
358 /*
359 * When a wrapped item is being deleted, make the next
360 * item in the row wrapped in order to preserve the row.
361 * In order to avoid an unnecessary layout, temporarily
362 * ignore WM_SIZE. If the next item is wrapped then a
363 * row will be deleted and the WM_SIZE is necessary.
364 */
365 CoolItem nextItem = null;
366 if (item.getWrap ()) {
367 if (index + 1 < count) {
368 nextItem = getItem (index + 1);
369 ignoreResize = !nextItem.getWrap ();
370 }
371 }
372 if (OS.SendMessage (handle, OS.RB_DELETEBAND, index, 0) is 0) {
373 error (SWT.ERROR_ITEM_NOT_REMOVED);
374 }
375 items [item.id] = null;
376 item.id = -1;
377 if (ignoreResize) {
378 nextItem.setWrap (true);
379 ignoreResize = false;
380 }
381
382 /* Restore the visible state of the control */
383 if (wasVisible) control.setVisible (true);
384
385 index = 0;
386 while (index < originalItems.length) {
387 if (originalItems [index] is item) break;
388 index++;
389 }
390 int length = originalItems.length - 1;
391 CoolItem [] newOriginals = new CoolItem [length];
392 System.arraycopy (originalItems, 0, newOriginals, 0, index);
393 System.arraycopy (originalItems, index + 1, newOriginals, index, length - index);
394 originalItems = newOriginals;
395 }
396
397 override void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) {
398 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
399 if (background is -1 && (style & SWT.FLAT) !is 0) {
400 Control control = findBackgroundControl ();
401 if (control !is null && control.backgroundImage !is null) {
402 fillBackground (hDC, control.getBackgroundPixel (), rect);
403 return;
404 }
405 }
406 }
407 RECT rect2;
408 OS.GetClientRect (handle, &rect2);
409 OS.MapWindowPoints (handle, hwnd, cast(POINT*) &rect2, 2);
410 POINT lpPoint;
411 OS.SetWindowOrgEx (hDC, -rect2.left, -rect2.top, &lpPoint);
412 OS.SendMessage (handle, OS.WM_PRINT, hDC, OS.PRF_CLIENT | OS.PRF_ERASEBKGND);
413 OS.SetWindowOrgEx (hDC, lpPoint.x, lpPoint.y, null);
414 }
415
416 override Control findThemeControl () {
417 if ((style & SWT.FLAT) !is 0) return this;
418 return background is -1 && backgroundImage is null ? this : super.findThemeControl ();
419 }
420
421 int getMargin (int index) {
422 int margin = 0;
423 if (OS.COMCTL32_MAJOR >= 6) {
424 MARGINS margins;
425 OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, &margins);
426 margin += margins.cxLeftWidth + margins.cxRightWidth;
427 }
428 RECT rect;
429 OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, &rect);
430 if ((style & SWT.FLAT) !is 0) {
431 /*
432 * Bug in Windows. When the style bit RBS_BANDBORDERS is not set
433 * the rectangle returned by RBS_BANDBORDERS is four pixels too small.
434 * The fix is to add four pixels to the result.
435 */
436 if ((style & SWT.VERTICAL) !is 0) {
437 margin += rect.top + 4;
438 } else {
439 margin += rect.left + 4;
440 }
441 } else {
442 if ((style & SWT.VERTICAL) !is 0) {
443 margin += rect.top + rect.bottom;
444 } else {
445 margin += rect.left + rect.right;
446 }
447 }
448 if ((style & SWT.FLAT) is 0) {
449 if (!isLastItemOfRow (index)) {
450 margin += CoolBar.SEPARATOR_WIDTH;
451 }
452 }
453 return margin;
454 }
455
456 /**
457 * Returns the item that is currently displayed at the given,
458 * zero-relative index. Throws an exception if the index is
459 * out of range.
460 *
461 * @param index the visual index of the item to return
462 * @return the item at the given visual index
463 *
464 * @exception IllegalArgumentException <ul>
465 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
466 * </ul>
467 * @exception SWTException <ul>
468 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
469 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
470 * </ul>
471 */
472 public CoolItem getItem (int index) {
473 checkWidget ();
474 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
475 if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
476 REBARBANDINFO rbBand;
477 rbBand.cbSize = REBARBANDINFO.sizeof;
478 rbBand.fMask = OS.RBBIM_ID;
479 OS.SendMessage (handle, OS.RB_GETBANDINFO, index, &rbBand);
480 return items [rbBand.wID];
481 }
482
483 /**
484 * Returns the number of items contained in the receiver.
485 *
486 * @return the number of items
487 *
488 * @exception SWTException <ul>
489 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
490 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
491 * </ul>
492 */
493 public int getItemCount () {
494 checkWidget ();
495 return OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
496 }
497
498 /**
499 * Returns an array of zero-relative ints that map
500 * the creation order of the receiver's items to the
501 * order in which they are currently being displayed.
502 * <p>
503 * Specifically, the indices of the returned array represent
504 * the current visual order of the items, and the contents
505 * of the array represent the creation order of the items.
506 * </p><p>
507 * Note: This is not the actual structure used by the receiver
508 * to maintain its list of items, so modifying the array will
509 * not affect the receiver.
510 * </p>
511 *
512 * @return the current visual order of the receiver's items
513 *
514 * @exception SWTException <ul>
515 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
516 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
517 * </ul>
518 */
519 public int [] getItemOrder () {
520 checkWidget ();
521 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
522 int [] indices = new int [count];
523 REBARBANDINFO rbBand;
524 rbBand.cbSize = REBARBANDINFO.sizeof;
525 rbBand.fMask = OS.RBBIM_ID;
526 for (int i=0; i<count; i++) {
527 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
528 CoolItem item = items [rbBand.wID];
529 int index = 0;
530 while (index<originalItems.length) {
531 if (originalItems [index] is item) break;
532 index++;
533 }
534 if (index is originalItems.length) error (SWT.ERROR_CANNOT_GET_ITEM);
535 indices [i] = index;
536 }
537 return indices;
538 }
539
540 /**
541 * Returns an array of <code>CoolItem</code>s in the order
542 * in which they are currently being displayed.
543 * <p>
544 * Note: This is not the actual structure used by the receiver
545 * to maintain its list of items, so modifying the array will
546 * not affect the receiver.
547 * </p>
548 *
549 * @return the receiver's items in their current visual order
550 *
551 * @exception SWTException <ul>
552 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
553 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
554 * </ul>
555 */
556 public CoolItem [] getItems () {
557 checkWidget ();
558 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
559 CoolItem [] result = new CoolItem [count];
560 REBARBANDINFO rbBand;
561 rbBand.cbSize = REBARBANDINFO.sizeof;
562 rbBand.fMask = OS.RBBIM_ID;
563 for (int i=0; i<count; i++) {
564 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
565 result [i] = items [rbBand.wID];
566 }
567 return result;
568 }
569
570 /**
571 * Returns an array of points whose x and y coordinates describe
572 * the widths and heights (respectively) of the items in the receiver
573 * in the order in which they are currently being displayed.
574 *
575 * @return the receiver's item sizes in their current visual order
576 *
577 * @exception SWTException <ul>
578 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
579 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
580 * </ul>
581 */
582 public Point [] getItemSizes () {
583 checkWidget ();
584 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
585 Point [] sizes = new Point [count];
586 REBARBANDINFO rbBand;
587 rbBand.cbSize = REBARBANDINFO.sizeof;
588 rbBand.fMask = OS.RBBIM_CHILDSIZE;
589 int separator = (style & SWT.FLAT) is 0 ? SEPARATOR_WIDTH : 0;
590 MARGINS margins;
591 for (int i=0; i<count; i++) {
592 RECT rect;
593 OS.SendMessage (handle, OS.RB_GETRECT, i, &rect);
594 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
595 if (OS.COMCTL32_MAJOR >= 6) {
596 OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, &margins);
597 rect.left -= margins.cxLeftWidth;
598 rect.right += margins.cxRightWidth;
599 }
600 if (!isLastItemOfRow(i)) rect.right += separator;
601 if ((style & SWT.VERTICAL) !is 0) {
602 sizes [i] = new Point (rbBand.cyChild, rect.right - rect.left);
603 } else {
604 sizes [i] = new Point (rect.right - rect.left, rbBand.cyChild);
605 }
606 }
607 return sizes;
608 }
609
610 int getLastIndexOfRow (int index) {
611 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
612 if (count is 0) return -1;
613 REBARBANDINFO rbBand;
614 rbBand.cbSize = REBARBANDINFO.sizeof;
615 rbBand.fMask = OS.RBBIM_STYLE;
616 for (int i=index + 1; i<count; i++) {
617 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
618 if ((rbBand.fStyle & OS.RBBS_BREAK) !is 0) {
619 return i - 1;
620 }
621 }
622 return count - 1;
623 }
624
625 bool isLastItemOfRow (int index) {
626 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
627 if (index + 1 is count) return true;
628 REBARBANDINFO rbBand;
629 rbBand.cbSize = REBARBANDINFO.sizeof;
630 rbBand.fMask = OS.RBBIM_STYLE;
631 OS.SendMessage (handle, OS.RB_GETBANDINFO, index + 1, &rbBand);
632 return (rbBand.fStyle & OS.RBBS_BREAK) !is 0;
633 }
634
635 /**
636 * Returns whether or not the receiver is 'locked'. When a coolbar
637 * is locked, its items cannot be repositioned.
638 *
639 * @return true if the coolbar is locked, false otherwise
640 *
641 * @exception SWTException <ul>
642 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
643 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
644 * </ul>
645 *
646 * @since 2.0
647 */
648 public bool getLocked () {
649 checkWidget ();
650 return locked;
651 }
652
653 /**
654 * Returns an array of ints that describe the zero-relative
655 * indices of any item(s) in the receiver that will begin on
656 * a new row. The 0th visible item always begins the first row,
657 * therefore it does not count as a wrap index.
658 *
659 * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row
660 *
661 * @exception SWTException <ul>
662 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
663 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
664 * </ul>
665 */
666 public int [] getWrapIndices () {
667 checkWidget ();
668 CoolItem [] items = getItems ();
669 int [] indices = new int [items.length];
670 int count = 0;
671 for (int i=0; i<items.length; i++) {
672 if (items [i].getWrap ()) indices [count++] = i;
673 }
674 int [] result = new int [count];
675 System.arraycopy (indices, 0, result, 0, count);
676 return result;
677 }
678
679 /**
680 * Searches the receiver's items in the order they are currently
681 * being displayed, starting at the first item (index 0), until
682 * an item is found that is equal to the argument, and returns
683 * the index of that item. If no item is found, returns -1.
684 *
685 * @param item the search item
686 * @return the visual order index of the search item, or -1 if the item is not found
687 *
688 * @exception IllegalArgumentException <ul>
689 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
690 * <li>ERROR_INVALID_ARGUMENT - if the item is disposed</li>
691 * </ul>
692 * @exception SWTException <ul>
693 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
694 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
695 * </ul>
696 */
697 public int indexOf (CoolItem item) {
698 checkWidget ();
699 if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
700 if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
701 return OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
702 }
703
704 void resizeToPreferredWidth (int index) {
705 /*
706 * Bug in Windows. When RB_GETBANDBORDERS is sent
707 * with an index out of range, Windows GP's. The
708 * fix is to ensure the index is in range.
709 */
710 int count = OS.SendMessage(handle, OS.RB_GETBANDCOUNT, 0, 0);
711 if (0 <= index && index < count) {
712 REBARBANDINFO rbBand;
713 rbBand.cbSize = REBARBANDINFO.sizeof;
714 rbBand.fMask = OS.RBBIM_IDEALSIZE;
715 OS.SendMessage (handle, OS.RB_GETBANDINFO, index, &rbBand);
716 RECT rect;
717 OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, &rect);
718 rbBand.cx = rbBand.cxIdeal + rect.left;
719 if ((style & SWT.FLAT) is 0) rbBand.cx += rect.right;
720 rbBand.fMask = OS.RBBIM_SIZE;
721 OS.SendMessage (handle, OS.RB_SETBANDINFO, index, &rbBand);
722 }
723 }
724
725 void resizeToMaximumWidth (int index) {
726 REBARBANDINFO rbBand;
727 rbBand.cbSize = REBARBANDINFO.sizeof;
728 rbBand.fMask = OS.RBBIM_SIZE;
729 rbBand.cx = MAX_WIDTH;
730 OS.SendMessage (handle, OS.RB_SETBANDINFO, index, &rbBand);
731 }
732
733 override void releaseChildren (bool destroy) {
734 if (items !is null) {
735 for (int i=0; i<items.length; i++) {
736 CoolItem item = items [i];
737 if (item !is null && !item.isDisposed ()) {
738 item.release (false);
739 }
740 }
741 items = null;
742 }
743 super.releaseChildren (destroy);
744 }
745
746 override void removeControl (Control control) {
747 super.removeControl (control);
748 for (int i=0; i<items.length; i++) {
749 CoolItem item = items [i];
750 if (item !is null && item.control is control) {
751 item.setControl (null);
752 }
753 }
754 }
755
756 override void setBackgroundPixel (int pixel) {
757 if (pixel is -1) pixel = defaultBackground ();
758 OS.SendMessage (handle, OS.RB_SETBKCOLOR, 0, pixel);
759 setItemColors (OS.SendMessage (handle, OS.RB_GETTEXTCOLOR, 0, 0), pixel);
760 /*
761 * Feature in Windows. For some reason, Windows
762 * does not fully erase the coolbar area and coolbar
763 * items when you set the background. The fix is
764 * to invalidate the coolbar area.
765 */
766 if (!OS.IsWindowVisible (handle)) return;
767 static if (OS.IsWinCE) {
768 OS.InvalidateRect (handle, null, true);
769 } else {
770 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
771 OS.RedrawWindow (handle, null, null, flags);
772 }
773 }
774
775 override void setForegroundPixel (int pixel) {
776 if (pixel is -1) pixel = defaultForeground ();
777 OS.SendMessage (handle, OS.RB_SETTEXTCOLOR, 0, pixel);
778 setItemColors (pixel, OS.SendMessage (handle, OS.RB_GETBKCOLOR, 0, 0));
779 }
780
781 void setItemColors (int foreColor, int backColor) {
782 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
783 REBARBANDINFO rbBand;
784 rbBand.cbSize = REBARBANDINFO.sizeof;
785 rbBand.fMask = OS.RBBIM_COLORS;
786 rbBand.clrFore = foreColor;
787 rbBand.clrBack = backColor;
788 for (int i=0; i<count; i++) {
789 OS.SendMessage (handle, OS.RB_SETBANDINFO, i, &rbBand);
790 }
791 }
792
793 /**
794 * Sets the receiver's item order, wrap indices, and item sizes
795 * all at once. This method is typically used to restore the
796 * displayed state of the receiver to a previously stored state.
797 * <p>
798 * The item order is the order in which the items in the receiver
799 * should be displayed, given in terms of the zero-relative ordering
800 * of when the items were added.
801 * </p><p>
802 * The wrap indices are the indices of all item(s) in the receiver
803 * that will begin on a new row. The indices are given in the order
804 * specified by the item order. The 0th item always begins the first
805 * row, therefore it does not count as a wrap index. If wrap indices
806 * is null or empty, the items will be placed on one line.
807 * </p><p>
808 * The sizes are specified in an array of points whose x and y
809 * coordinates describe the new widths and heights (respectively)
810 * of the receiver's items in the order specified by the item order.
811 * </p>
812 *
813 * @param itemOrder an array of indices that describe the new order to display the items in
814 * @param wrapIndices an array of wrap indices, or null
815 * @param sizes an array containing the new sizes for each of the receiver's items in visual order
816 *
817 * @exception SWTException <ul>
818 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
819 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
820 * </ul>
821 * @exception IllegalArgumentException <ul>
822 * <li>ERROR_INVALID_ARGUMENT - if item order or sizes is not the same length as the number of items</li>
823 * </ul>
824 */
825 public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
826 checkWidget ();
827 setRedraw (false);
828 setItemOrder (itemOrder);
829 setWrapIndices (wrapIndices);
830 setItemSizes (sizes);
831 setRedraw (true);
832 }
833
834 /*
835 * Sets the order that the items in the receiver should
836 * be displayed in to the given argument which is described
837 * in terms of the zero-relative ordering of when the items
838 * were added.
839 *
840 * @param itemOrder the new order to display the items in
841 *
842 * @exception SWTException <ul>
843 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
844 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
845 * </ul>
846 * @exception IllegalArgumentException <ul>
847 * <li>ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items</li>
848 * </ul>
849 */
850 void setItemOrder (int [] itemOrder) {
851 // SWT extension: allow null array
852 //if (itemOrder is null) error (SWT.ERROR_NULL_ARGUMENT);
853 int itemCount = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
854 if (itemOrder.length !is itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
855
856 /* Ensure that itemOrder does not contain any duplicates. */
857 bool [] set = new bool [itemCount];
858 for (int i=0; i<itemOrder.length; i++) {
859 int index = itemOrder [i];
860 if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
861 if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT);
862 set [index] = true;
863 }
864
865 //REBARBANDINFO rbBand;
866 //rbBand.cbSize = REBARBANDINFO.sizeof;
867 for (int i=0; i<itemOrder.length; i++) {
868 int id = originalItems [itemOrder [i]].id;
869 int index = OS.SendMessage (handle, OS.RB_IDTOINDEX, id, 0);
870 if (index !is i) {
871 int lastItemSrcRow = getLastIndexOfRow (index);
872 int lastItemDstRow = getLastIndexOfRow (i);
873 if (index is lastItemSrcRow) {
874 resizeToPreferredWidth (index);
875 }
876 if (i is lastItemDstRow) {
877 resizeToPreferredWidth (i);
878 }
879
880 /* Move the item */
881 OS.SendMessage (handle, OS.RB_MOVEBAND, index, i);
882
883 if (index is lastItemSrcRow && index - 1 >= 0) {
884 resizeToMaximumWidth (index - 1);
885 }
886 if (i is lastItemDstRow) {
887 resizeToMaximumWidth (i);
888 }
889 }
890 }
891 }
892
893 /*
894 * Sets the width and height of the receiver's items to the ones
895 * specified by the argument, which is an array of points whose x
896 * and y coordinates describe the widths and heights (respectively)
897 * in the order in which the items are currently being displayed.
898 *
899 * @param sizes an array containing the new sizes for each of the receiver's items in visual order
900 *
901 * @exception IllegalArgumentException <ul>
902 * <li>ERROR_NULL_ARGUMENT - if the array of sizes is null</li>
903 * <li>ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items</li>
904 * </ul>
905 * @exception SWTException <ul>
906 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
907 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
908 * </ul>
909 */
910 void setItemSizes (Point [] sizes) {
911 // SWT extension: allow null array
912 //if (sizes is null) error (SWT.ERROR_NULL_ARGUMENT);
913 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
914 if (sizes.length !is count) error (SWT.ERROR_INVALID_ARGUMENT);
915 REBARBANDINFO rbBand;
916 rbBand.cbSize = REBARBANDINFO.sizeof;
917 rbBand.fMask = OS.RBBIM_ID;
918 for (int i=0; i<count; i++) {
919 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
920 items [rbBand.wID].setSize (sizes [i].x, sizes [i].y);
921 }
922 }
923
924 /**
925 * Sets whether or not the receiver is 'locked'. When a coolbar
926 * is locked, its items cannot be repositioned.
927 *
928 * @param locked lock the coolbar if true, otherwise unlock the coolbar
929 *
930 * @exception SWTException <ul>
931 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
932 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
933 * </ul>
934 *
935 * @since 2.0
936 */
937 public void setLocked (bool locked) {
938 checkWidget ();
939 this.locked = locked;
940 int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
941 REBARBANDINFO rbBand;
942 rbBand.cbSize = REBARBANDINFO.sizeof;
943 rbBand.fMask = OS.RBBIM_STYLE;
944 for (int i=0; i<count; i++) {
945 OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
946 if (locked) {
947 rbBand.fStyle |= OS.RBBS_NOGRIPPER;
948 } else {
949 rbBand.fStyle &= ~OS.RBBS_NOGRIPPER;
950 }
951 OS.SendMessage (handle, OS.RB_SETBANDINFO, i, &rbBand);
952 }
953 }
954
955 /**
956 * Sets the indices of all item(s) in the receiver that will
957 * begin on a new row. The indices are given in the order in
958 * which they are currently being displayed. The 0th item
959 * always begins the first row, therefore it does not count
960 * as a wrap index. If indices is null or empty, the items
961 * will be placed on one line.
962 *
963 * @param indices an array of wrap indices, or null
964 *
965 * @exception SWTException <ul>
966 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
967 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
968 * </ul>
969 */
970 public void setWrapIndices (int [] indices) {
971 checkWidget ();
972 if (indices is null) indices = new int [0];
973 int count = getItemCount ();
974 for (int i=0; i<indices.length; i++) {
975 if (indices [i] < 0 || indices [i] >= count) {
976 error (SWT.ERROR_INVALID_RANGE);
977 }
978 }
979 setRedraw (false);
980 CoolItem [] items = getItems ();
981 for (int i=0; i<items.length; i++) {
982 CoolItem item = items [i];
983 if (item.getWrap ()) {
984 resizeToPreferredWidth (i - 1);
985 item.setWrap (false);
986 }
987 }
988 resizeToMaximumWidth (count - 1);
989 for (int i=0; i<indices.length; i++) {
990 int index = indices [i];
991 if (0 <= index && index < items.length) {
992 CoolItem item = items [index];
993 item.setWrap (true);
994 resizeToMaximumWidth (index - 1);
995 }
996 }
997 setRedraw (true);
998 }
999
1000 override int widgetStyle () {
1001 int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE;
1002 bits |= OS.RBS_VARHEIGHT | OS.RBS_DBLCLKTOGGLE;
1003 if ((style & SWT.FLAT) is 0) bits |= OS.RBS_BANDBORDERS;
1004 return bits;
1005 }
1006
1007 override String windowClass () {
1008 return TCHARzToStr( ReBarClass );
1009 }
1010
1011 override int windowProc () {
1012 return cast(int) ReBarProc;
1013 }
1014
1015 override LRESULT WM_COMMAND (int wParam, int lParam) {
1016 /*
1017 * Feature in Windows. When the coolbar window
1018 * proc processes WM_COMMAND, it forwards this
1019 * message to its parent. This is done so that
1020 * children of this control that send this message
1021 * type to their parent will notify not only
1022 * this control but also the parent of this control,
1023 * which is typically the application window and
1024 * the window that is looking for the message.
1025 * If the control did not forward the message,
1026 * applications would have to subclass the control
1027 * window to see the message. Because the control
1028 * window is subclassed by SWT, the message
1029 * is delivered twice, once by SWT and once when
1030 * the message is forwarded by the window proc.
1031 * The fix is to avoid calling the window proc
1032 * for this control.
1033 */
1034 LRESULT result = super.WM_COMMAND (wParam, lParam);
1035 if (result !is null) return result;
1036 return LRESULT.ZERO;
1037 }
1038
1039 override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
1040 LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
1041 /*
1042 * Feature in Windows. For some reason, Windows
1043 * does not fully erase the area that the cool bar
1044 * occupies when the size of the cool bar is larger
1045 * than the space occupied by the cool bar items.
1046 * The fix is to erase the cool bar background.
1047 *
1048 * NOTE: On versions of Windows prior to XP, for
1049 * some reason, the cool bar draws separators in
1050 * WM_ERASEBKGND. Therefore it is essential to run
1051 * the cool bar window proc after the background has
1052 * been erased.
1053 */
1054 if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
1055 drawBackground ( cast(HDC) wParam);
1056 return null;
1057 }
1058 return result;
1059 }
1060
1061 override LRESULT WM_NOTIFY (int wParam, int lParam) {
1062 /*
1063 * Feature in Windows. When the cool bar window
1064 * proc processes WM_NOTIFY, it forwards this
1065 * message to its parent. This is done so that
1066 * children of this control that send this message
1067 * type to their parent will notify not only
1068 * this control but also the parent of this control,
1069 * which is typically the application window and
1070 * the window that is looking for the message.
1071 * If the control did not forward the message,
1072 * applications would have to subclass the control
1073 * window to see the message. Because the control
1074 * window is subclassed by SWT, the message
1075 * is delivered twice, once by SWT and once when
1076 * the message is forwarded by the window proc.
1077 * The fix is to avoid calling the window proc
1078 * for this control.
1079 */
1080 LRESULT result = super.WM_NOTIFY (wParam, lParam);
1081 if (result !is null) return result;
1082 return LRESULT.ZERO;
1083 }
1084
1085 override LRESULT WM_SETREDRAW (int wParam, int lParam) {
1086 LRESULT result = super.WM_SETREDRAW (wParam, lParam);
1087 if (result !is null) return result;
1088 /*
1089 * Feature in Windows. When redraw is turned off, the rebar
1090 * control does not call the default window proc. This means
1091 * that the rebar will redraw and children of the rebar will
1092 * also redraw. The fix is to call both the rebar window proc
1093 * and the default window proc.
1094 *
1095 * NOTE: The rebar control can resize itself in WM_SETREDRAW.
1096 * When redraw is turned off by the default window proc, this
1097 * can leave pixel corruption in the parent. The fix is to
1098 * detect the size change and damage the previous area in the
1099 * parent.
1100 *
1101 * NOTE: In version 6.00 of COMCTL32.DLL, when WM_SETREDRAW
1102 * is off, we cannot detect that the size has changed causing
1103 * pixel corruption. The fix is to disallow WM_SETREDRAW by
1104 * not running the default window proc or the rebar window
1105 * proc.
1106 */
1107 if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO;
1108 Rectangle rect = getBounds ();
1109 int /*long*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
1110 OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
1111 if ( rect != getBounds ()) {
1112 parent.redraw (rect.x, rect.y, rect.width, rect.height, true);
1113 }
1114 return new LRESULT (code);
1115 }
1116
1117 override LRESULT WM_SIZE (int wParam, int lParam) {
1118 if (ignoreResize) {
1119 int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
1120 if (code is 0) return LRESULT.ZERO;
1121 return new LRESULT (code);
1122 }
1123 //TEMPORARY CODE
1124 // if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
1125 // if (background is -1 && (style & SWT.FLAT) is 0) {
1126 // OS.InvalidateRect (handle, null, true);
1127 // }
1128 // }
1129 return super.WM_SIZE (wParam, lParam);
1130 }
1131
1132 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
1133 switch (hdr.code) {
1134 case OS.RBN_BEGINDRAG: {
1135 int pos = OS.GetMessagePos ();
1136 POINT pt;
1137 OS.POINTSTOPOINT (pt, pos);
1138 OS.ScreenToClient (handle, &pt);
1139 int button = display.lastButton !is 0 ? display.lastButton : 1;
1140 if (!sendDragEvent (button, pt.x, pt.y)) return LRESULT.ONE;
1141 break;
1142 }
1143 case OS.RBN_CHILDSIZE: {
1144 /*
1145 * Bug in Windows. When Windows sets the size of the rebar band
1146 * child and the child is a combo box, the size of the drop down
1147 * portion of the combo box is resized to zero. The fix is to set
1148 * the size of the control to the current size after the rebar has
1149 * already resized it. If the control is not a combo, this does
1150 * nothing. If the control is a combo, the drop down portion is
1151 * recalculated.
1152 */
1153 NMREBARCHILDSIZE* lprbcs = cast(NMREBARCHILDSIZE*)lParam;
1154 //OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof);
1155 if (lprbcs.uBand !is -1) {
1156 CoolItem item = items [lprbcs.wID];
1157 Control control = item.control;
1158 if (control !is null) {
1159 int width = lprbcs.rcChild.right - lprbcs.rcChild.left;
1160 int height = lprbcs.rcChild.bottom - lprbcs.rcChild.top;
1161 control.setBounds (lprbcs.rcChild.left, lprbcs.rcChild.top, width, height);
1162 }
1163 }
1164 break;
1165 }
1166 case OS.RBN_HEIGHTCHANGE: {
1167 if (!ignoreResize) {
1168 Point size = getSize ();
1169 int border = getBorderWidth ();
1170 int barHeight = OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0);
1171 if ((style & SWT.VERTICAL) !is 0) {
1172 setSize (barHeight + 2 * border, size.y);
1173 } else {
1174 setSize (size.x, barHeight + 2 * border);
1175 }
1176 }
1177 break;
1178 }
1179 case OS.RBN_CHEVRONPUSHED: {
1180 NMREBARCHEVRON* lpnm = cast(NMREBARCHEVRON*)lParam;
1181 //OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof);
1182 CoolItem item = items [lpnm.wID];
1183 if (item !is null) {
1184 Event event = new Event();
1185 event.detail = SWT.ARROW;
1186 if ((style & SWT.VERTICAL) !is 0) {
1187 event.x = lpnm.rc.right;
1188 event.y = lpnm.rc.top;
1189 } else {
1190 event.x = lpnm.rc.left;
1191 event.y = lpnm.rc.bottom;
1192 }
1193 item.postEvent (SWT.Selection, event);
1194 }
1195 break;
1196 }
1197 case OS.NM_CUSTOMDRAW: {
1198 /*
1199 * Bug in Windows. On versions of Windows prior to XP,
1200 * drawing the background color in NM_CUSTOMDRAW erases
1201 * the separators. The fix is to draw the background
1202 * in WM_ERASEBKGND.
1203 */
1204 if (OS.COMCTL32_MAJOR < 6) break;
1205 if (findBackgroundControl () !is null || (style & SWT.FLAT) !is 0) {
1206 NMCUSTOMDRAW* nmcd = cast(NMCUSTOMDRAW*)lParam;
1207 //OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
1208 switch (nmcd.dwDrawStage) {
1209 case OS.CDDS_PREERASE:
1210 return new LRESULT (OS.CDRF_SKIPDEFAULT | OS.CDRF_NOTIFYPOSTERASE);
1211 case OS.CDDS_POSTERASE:
1212 drawBackground (nmcd.hdc);
1213 break;
1214 default:
1215 }
1216 }
1217 break;
1218 }
1219 default:
1220 }
1221 return super.wmNotifyChild (hdr, wParam, lParam);
1222 }
1223 }