Mercurial > projects > dwt2
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 } |