Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ExpandBar.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.ExpandBar; | |
14 | |
15 | |
16 import org.eclipse.swt.SWT; | |
17 import org.eclipse.swt.SWTException; | |
18 import org.eclipse.swt.events.ExpandAdapter; | |
19 import org.eclipse.swt.events.ExpandEvent; | |
20 import org.eclipse.swt.events.ExpandListener; | |
21 import org.eclipse.swt.graphics.Font; | |
22 import org.eclipse.swt.graphics.GC; | |
23 import org.eclipse.swt.graphics.GCData; | |
24 import org.eclipse.swt.graphics.Point; | |
25 import org.eclipse.swt.graphics.Rectangle; | |
26 import org.eclipse.swt.graphics.Drawable; | |
27 import org.eclipse.swt.internal.win32.OS; | |
28 | |
29 import org.eclipse.swt.widgets.Composite; | |
30 import org.eclipse.swt.widgets.Control; | |
31 import org.eclipse.swt.widgets.ExpandItem; | |
32 import org.eclipse.swt.widgets.ScrollBar; | |
33 import org.eclipse.swt.widgets.ExpandItem; | |
34 import org.eclipse.swt.widgets.TypedListener; | |
35 import org.eclipse.swt.widgets.Event; | |
36 | |
37 import java.lang.all; | |
38 | |
39 /** | |
40 * Instances of this class support the layout of selectable | |
41 * expand bar items. | |
42 * <p> | |
43 * The item children that may be added to instances of this class | |
44 * must be of type <code>ExpandItem</code>. | |
45 * </p><p> | |
46 * <dl> | |
47 * <dt><b>Styles:</b></dt> | |
48 * <dd>V_SCROLL</dd> | |
49 * <dt><b>Events:</b></dt> | |
50 * <dd>Expand, Collapse</dd> | |
51 * </dl> | |
52 * </p><p> | |
53 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
54 * </p> | |
55 * | |
56 * @see ExpandItem | |
57 * @see ExpandEvent | |
58 * @see ExpandListener | |
59 * @see ExpandAdapter | |
60 * @see <a href="http://www.eclipse.org/swt/snippets/#expandbar">ExpandBar snippets</a> | |
61 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> | |
62 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
63 * | |
64 * @since 3.2 | |
65 */ | |
66 public class ExpandBar : Composite { | |
67 | |
68 alias Composite.computeSize computeSize; | |
69 alias Composite.windowProc windowProc; | |
70 | |
71 ExpandItem[] items; | |
72 int itemCount; | |
73 ExpandItem focusItem; | |
74 int spacing = 4; | |
75 int yCurrentScroll; | |
76 HFONT hFont; | |
77 | |
78 | |
79 /** | |
80 * Constructs a new instance of this class given its parent | |
81 * and a style value describing its behavior and appearance. | |
82 * <p> | |
83 * The style value is either one of the style constants defined in | |
84 * class <code>SWT</code> which is applicable to instances of this | |
85 * class, or must be built by <em>bitwise OR</em>'ing together | |
86 * (that is, using the <code>int</code> "|" operator) two or more | |
87 * of those <code>SWT</code> style constants. The class description | |
88 * lists the style constants that are applicable to the class. | |
89 * Style bits are also inherited from superclasses. | |
90 * </p> | |
91 * | |
92 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
93 * @param style the style of control to construct | |
94 * | |
95 * @exception IllegalArgumentException <ul> | |
96 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
97 * </ul> | |
98 * @exception SWTException <ul> | |
99 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
100 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
101 * </ul> | |
102 * | |
103 * @see Widget#checkSubclass | |
104 * @see Widget#getStyle | |
105 */ | |
106 public this (Composite parent, int style) { | |
107 super (parent, checkStyle (style)); | |
108 } | |
109 | |
110 /** | |
111 * Adds the listener to the collection of listeners who will | |
112 * be notified when an item in the receiver is expanded or collapsed | |
113 * by sending it one of the messages defined in the <code>ExpandListener</code> | |
114 * interface. | |
115 * | |
116 * @param listener the listener which should be notified | |
117 * | |
118 * @exception IllegalArgumentException <ul> | |
119 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
120 * </ul> | |
121 * @exception SWTException <ul> | |
122 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
123 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
124 * </ul> | |
125 * | |
126 * @see ExpandListener | |
127 * @see #removeExpandListener | |
128 */ | |
129 public void addExpandListener (ExpandListener listener) { | |
130 checkWidget (); | |
131 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
132 TypedListener typedListener = new TypedListener (listener); | |
133 addListener (SWT.Expand, typedListener); | |
134 addListener (SWT.Collapse, typedListener); | |
135 } | |
136 | |
137 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
138 if (handle is null) return 0; | |
139 return OS.DefWindowProc (hwnd, msg, wParam, lParam); | |
140 } | |
141 | |
142 override protected void checkSubclass () { | |
143 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
144 } | |
145 | |
146 static int checkStyle (int style) { | |
147 style &= ~SWT.H_SCROLL; | |
148 return style | SWT.NO_BACKGROUND; | |
149 } | |
150 | |
151 override public Point computeSize (int wHint, int hHint, bool changed) { | |
152 checkWidget (); | |
153 int height = 0, width = 0; | |
154 if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) { | |
155 if (itemCount > 0) { | |
156 auto hDC = OS.GetDC (handle); | |
157 HTHEME hTheme; | |
158 if (isAppThemed ()) { | |
159 hTheme = display.hExplorerBarTheme (); | |
160 } | |
161 HFONT hCurrentFont, oldFont; | |
162 if (hTheme is null) { | |
163 if (hFont !is null) { | |
164 hCurrentFont = hFont; | |
165 } else { | |
166 static if (!OS.IsWinCE) { | |
167 NONCLIENTMETRICS info; | |
168 info.cbSize = NONCLIENTMETRICS.sizeof; | |
169 if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) { | |
170 LOGFONT* logFont = &info.lfCaptionFont; | |
171 hCurrentFont = OS.CreateFontIndirect (logFont); | |
172 } | |
173 } | |
174 } | |
175 if (hCurrentFont !is null) { | |
176 oldFont = OS.SelectObject (hDC, hCurrentFont); | |
177 } | |
178 } | |
179 height += spacing; | |
180 for (int i = 0; i < itemCount; i++) { | |
181 ExpandItem item = items [i]; | |
182 height += item.getHeaderHeight (); | |
183 if (item.expanded) height += item.height; | |
184 height += spacing; | |
185 width = Math.max (width, item.getPreferredWidth (hTheme, hDC)); | |
186 } | |
187 if (hCurrentFont !is null) { | |
188 OS.SelectObject (hDC, oldFont); | |
189 if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont); | |
190 } | |
191 OS.ReleaseDC (handle, hDC); | |
192 } | |
193 } | |
194 if (width is 0) width = DEFAULT_WIDTH; | |
195 if (height is 0) height = DEFAULT_HEIGHT; | |
196 if (wHint !is SWT.DEFAULT) width = wHint; | |
197 if (hHint !is SWT.DEFAULT) height = hHint; | |
198 Rectangle trim = computeTrim (0, 0, width, height); | |
199 return new Point (trim.width, trim.height); | |
200 } | |
201 | |
202 override void createHandle () { | |
203 super.createHandle (); | |
204 state &= ~CANVAS; | |
205 state |= TRACK_MOUSE; | |
206 } | |
207 | |
208 void createItem (ExpandItem item, int style, int index) { | |
209 if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE); | |
210 if (itemCount is items.length) { | |
211 ExpandItem [] newItems = new ExpandItem [itemCount + 4]; | |
212 System.arraycopy (items, 0, newItems, 0, items.length); | |
213 items = newItems; | |
214 } | |
215 System.arraycopy (items, index, items, index + 1, itemCount - index); | |
216 items [index] = item; | |
217 itemCount++; | |
218 if (focusItem is null) focusItem = item; | |
219 | |
220 RECT rect; | |
221 OS.GetWindowRect (handle, &rect); | |
222 item.width = Math.max (0, rect.right - rect.left - spacing * 2); | |
223 layoutItems (index, true); | |
224 } | |
225 | |
226 override void createWidget () { | |
227 super.createWidget (); | |
228 items = new ExpandItem [4]; | |
229 if (!isAppThemed ()) { | |
230 backgroundMode = SWT.INHERIT_DEFAULT; | |
231 } | |
232 } | |
233 | |
234 override int defaultBackground() { | |
235 if (!isAppThemed ()) { | |
236 return OS.GetSysColor (OS.COLOR_WINDOW); | |
237 } | |
238 return super.defaultBackground(); | |
239 } | |
240 | |
241 void destroyItem (ExpandItem item) { | |
242 int index = 0; | |
243 while (index < itemCount) { | |
244 if (items [index] is item) break; | |
245 index++; | |
246 } | |
247 if (index is itemCount) return; | |
248 if (item is focusItem) { | |
249 int focusIndex = index > 0 ? index - 1 : 1; | |
250 if (focusIndex < itemCount) { | |
251 focusItem = items [focusIndex]; | |
252 focusItem.redraw (true); | |
253 } else { | |
254 focusItem = null; | |
255 } | |
256 } | |
257 System.arraycopy (items, index + 1, items, index, --itemCount - index); | |
258 items [itemCount] = null; | |
259 item.redraw (true); | |
260 layoutItems (index, true); | |
261 } | |
262 | |
263 override void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) { | |
264 RECT rect2; | |
265 OS.GetClientRect (handle, &rect2); | |
266 OS.MapWindowPoints (handle, hwnd, cast(POINT*) &rect2, 2); | |
267 OS.DrawThemeBackground (display.hExplorerBarTheme (), hDC, OS.EBP_NORMALGROUPBACKGROUND, 0, &rect2, null); | |
268 } | |
269 | |
270 void drawWidget (GC gc, RECT* clipRect) { | |
271 HTHEME hTheme; | |
272 if (isAppThemed ()) { | |
273 hTheme = display.hExplorerBarTheme (); | |
274 } | |
275 if (hTheme !is null) { | |
276 RECT rect; | |
277 OS.GetClientRect (handle, &rect); | |
278 OS.DrawThemeBackground (hTheme, gc.handle, OS.EBP_HEADERBACKGROUND, 0, &rect, clipRect); | |
279 } else { | |
280 drawBackground (gc.handle); | |
281 } | |
282 bool drawFocus = false; | |
283 if (handle is OS.GetFocus ()) { | |
284 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); | |
285 drawFocus = (uiState & OS.UISF_HIDEFOCUS) is 0; | |
286 } | |
287 HFONT hCurrentFont, oldFont; | |
288 if (hTheme is null) { | |
289 if (hFont !is null) { | |
290 hCurrentFont = hFont; | |
291 } else { | |
292 if (!OS.IsWinCE) { | |
293 NONCLIENTMETRICS info; | |
294 info.cbSize = NONCLIENTMETRICS.sizeof; | |
295 if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) { | |
296 LOGFONT* logFont = &info.lfCaptionFont; | |
297 hCurrentFont = OS.CreateFontIndirect (logFont); | |
298 } | |
299 } | |
300 } | |
301 if (hCurrentFont !is null) { | |
302 oldFont = OS.SelectObject (gc.handle, hCurrentFont); | |
303 } | |
304 if (foreground !is -1) { | |
305 OS.SetTextColor (gc.handle, foreground); | |
306 } | |
307 } | |
308 for (int i = 0; i < itemCount; i++) { | |
309 ExpandItem item = items[i]; | |
310 item.drawItem (gc, hTheme, clipRect, item is focusItem && drawFocus); | |
311 } | |
312 if (hCurrentFont !is null) { | |
313 OS.SelectObject (gc.handle, oldFont); | |
314 if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont); | |
315 } | |
316 } | |
317 | |
318 override Control findBackgroundControl () { | |
319 Control control = super.findBackgroundControl (); | |
320 if (!isAppThemed ()) { | |
321 if (control is null) control = this; | |
322 } | |
323 return control; | |
324 } | |
325 | |
326 override Control findThemeControl () { | |
327 return isAppThemed () ? this : super.findThemeControl (); | |
328 } | |
329 | |
330 int getBandHeight () { | |
331 if (hFont is null) return ExpandItem.CHEVRON_SIZE; | |
332 auto hDC = OS.GetDC (handle); | |
333 auto oldHFont = OS.SelectObject (hDC, hFont); | |
334 TEXTMETRIC lptm; | |
335 OS.GetTextMetrics (hDC, &lptm); | |
336 OS.SelectObject (hDC, oldHFont); | |
337 OS.ReleaseDC (handle, hDC); | |
338 return Math.max (ExpandItem.CHEVRON_SIZE, lptm.tmHeight + 4); | |
339 } | |
340 | |
341 /** | |
342 * Returns the item at the given, zero-relative index in the | |
343 * receiver. Throws an exception if the index is out of range. | |
344 * | |
345 * @param index the index of the item to return | |
346 * @return the item at the given index | |
347 * | |
348 * @exception IllegalArgumentException <ul> | |
349 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> | |
350 * </ul> | |
351 * @exception SWTException <ul> | |
352 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
353 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
354 * </ul> | |
355 */ | |
356 public ExpandItem getItem (int index) { | |
357 checkWidget (); | |
358 if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE); | |
359 return items [index]; | |
360 } | |
361 | |
362 /** | |
363 * Returns the number of items contained in the receiver. | |
364 * | |
365 * @return the number of items | |
366 * | |
367 * @exception SWTException <ul> | |
368 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
369 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
370 * </ul> | |
371 */ | |
372 public int getItemCount () { | |
373 checkWidget (); | |
374 return itemCount; | |
375 } | |
376 | |
377 /** | |
378 * Returns an array of <code>ExpandItem</code>s which are the items | |
379 * in the receiver. | |
380 * <p> | |
381 * Note: This is not the actual structure used by the receiver | |
382 * to maintain its list of items, so modifying the array will | |
383 * not affect the receiver. | |
384 * </p> | |
385 * | |
386 * @return the items in the receiver | |
387 * | |
388 * @exception SWTException <ul> | |
389 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
390 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
391 * </ul> | |
392 */ | |
393 public ExpandItem [] getItems () { | |
394 checkWidget (); | |
395 ExpandItem [] result = new ExpandItem [itemCount]; | |
396 System.arraycopy (items, 0, result, 0, itemCount); | |
397 return result; | |
398 } | |
399 | |
400 /** | |
401 * Returns the receiver's spacing. | |
402 * | |
403 * @return the spacing | |
404 * | |
405 * @exception SWTException <ul> | |
406 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
407 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
408 * </ul> | |
409 */ | |
410 public int getSpacing () { | |
411 checkWidget (); | |
412 return spacing; | |
413 } | |
414 | |
415 /** | |
416 * Searches the receiver's list starting at the first item | |
417 * (index 0) until an item is found that is equal to the | |
418 * argument, and returns the index of that item. If no item | |
419 * is found, returns -1. | |
420 * | |
421 * @param item the search item | |
422 * @return the index of the item | |
423 * | |
424 * @exception IllegalArgumentException <ul> | |
425 * <li>ERROR_NULL_ARGUMENT - if the item is null</li> | |
426 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li> | |
427 * </ul> | |
428 * @exception SWTException <ul> | |
429 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
430 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
431 * </ul> | |
432 */ | |
433 public int indexOf (ExpandItem item) { | |
434 checkWidget (); | |
435 if (item is null) error (SWT.ERROR_NULL_ARGUMENT); | |
436 for (int i = 0; i < itemCount; i++) { | |
437 if (items [i] is item) return i; | |
438 } | |
439 return -1; | |
440 } | |
441 | |
442 bool isAppThemed () { | |
443 if (background !is -1) return false; | |
444 if (foreground !is -1) return false; | |
445 if (hFont !is null) return false; | |
446 return OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed (); | |
447 } | |
448 | |
449 void layoutItems (int index, bool setScrollbar_) { | |
450 if (index < itemCount) { | |
451 int y = spacing - yCurrentScroll; | |
452 for (int i = 0; i < index; i++) { | |
453 ExpandItem item = items [i]; | |
454 if (item.expanded) y += item.height; | |
455 y += item.getHeaderHeight () + spacing; | |
456 } | |
457 for (int i = index; i < itemCount; i++) { | |
458 ExpandItem item = items [i]; | |
459 item.setBounds (spacing, y, 0, 0, true, false); | |
460 if (item.expanded) y += item.height; | |
461 y += item.getHeaderHeight () + spacing; | |
462 } | |
463 } | |
464 if (setScrollbar_) setScrollbar (); | |
465 } | |
466 | |
467 override void releaseChildren (bool destroy) { | |
468 if (items !is null) { | |
469 for (int i=0; i<items.length; i++) { | |
470 ExpandItem item = items [i]; | |
471 if (item !is null && !item.isDisposed ()) { | |
472 item.release (false); | |
473 } | |
474 } | |
475 items = null; | |
476 } | |
477 focusItem = null; | |
478 super.releaseChildren (destroy); | |
479 } | |
480 | |
481 /** | |
482 * Removes the listener from the collection of listeners who will | |
483 * be notified when items in the receiver are expanded or collapsed. | |
484 * | |
485 * @param listener the listener which should no longer be notified | |
486 * | |
487 * @exception IllegalArgumentException <ul> | |
488 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
489 * </ul> | |
490 * @exception SWTException <ul> | |
491 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
492 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
493 * </ul> | |
494 * | |
495 * @see ExpandListener | |
496 * @see #addExpandListener | |
497 */ | |
498 public void removeExpandListener (ExpandListener listener) { | |
499 checkWidget (); | |
500 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
501 if (eventTable is null) return; | |
502 eventTable.unhook (SWT.Expand, listener); | |
503 eventTable.unhook (SWT.Collapse, listener); | |
504 } | |
505 | |
506 override void setBackgroundPixel (int pixel) { | |
507 super.setBackgroundPixel (pixel); | |
508 static if (!OS.IsWinCE) { | |
509 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; | |
510 OS.RedrawWindow (handle, null, null, flags); | |
511 } | |
512 } | |
513 | |
514 override public void setFont (Font font) { | |
515 super.setFont (font); | |
516 hFont = font !is null ? font.handle : null; | |
517 layoutItems (0, true); | |
518 } | |
519 | |
520 override void setForegroundPixel (int pixel) { | |
521 super.setForegroundPixel (pixel); | |
522 static if (!OS.IsWinCE) { | |
523 int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; | |
524 OS.RedrawWindow (handle, null, null, flags); | |
525 } | |
526 } | |
527 | |
528 void setScrollbar () { | |
529 if (itemCount is 0) return; | |
530 if ((style & SWT.V_SCROLL) is 0) return; | |
531 RECT rect; | |
532 OS.GetClientRect (handle, &rect); | |
533 int height = rect.bottom - rect.top; | |
534 ExpandItem item = items [itemCount - 1]; | |
535 int maxHeight = item.y + getBandHeight () + spacing; | |
536 if (item.expanded) maxHeight += item.height; | |
537 | |
538 //claim bottom free space | |
539 if (yCurrentScroll > 0 && height > maxHeight) { | |
540 yCurrentScroll = Math.max (0, yCurrentScroll + maxHeight - height); | |
541 layoutItems (0, false); | |
542 } | |
543 maxHeight += yCurrentScroll; | |
544 | |
545 SCROLLINFO info; | |
546 info.cbSize = SCROLLINFO.sizeof; | |
547 info.fMask = OS.SIF_RANGE | OS.SIF_PAGE | OS.SIF_POS; | |
548 info.nMin = 0; | |
549 info.nMax = maxHeight; | |
550 info.nPage = height; | |
551 info.nPos = Math.min (yCurrentScroll, info.nMax); | |
552 if (info.nPage !is 0) info.nPage++; | |
553 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true); | |
554 } | |
555 | |
556 /** | |
557 * Sets the receiver's spacing. Spacing specifies the number of pixels allocated around | |
558 * each item. | |
559 * | |
560 * @param spacing the spacing around each item | |
561 * | |
562 * @exception SWTException <ul> | |
563 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
564 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
565 * </ul> | |
566 */ | |
567 public void setSpacing (int spacing) { | |
568 checkWidget (); | |
569 if (spacing < 0) return; | |
570 if (spacing is this.spacing) return; | |
571 this.spacing = spacing; | |
572 RECT rect; | |
573 OS.GetClientRect (handle, &rect); | |
574 int width = Math.max (0, (rect.right - rect.left) - spacing * 2); | |
575 for (int i = 0; i < itemCount; i++) { | |
576 ExpandItem item = items[i]; | |
577 if (item.width !is width) item.setBounds (0, 0, width, item.height, false, true); | |
578 } | |
579 layoutItems (0, true); | |
580 OS.InvalidateRect (handle, null, true); | |
581 } | |
582 | |
583 void showItem (ExpandItem item) { | |
584 Control control = item.control; | |
585 if (control !is null && !control.isDisposed ()) { | |
586 control.setVisible (item.expanded); | |
587 } | |
588 item.redraw (true); | |
589 int index = indexOf (item); | |
590 layoutItems (index + 1, true); | |
591 } | |
592 | |
593 void showFocus (bool up) { | |
594 RECT rect; | |
595 OS.GetClientRect (handle, &rect); | |
596 int height = rect.bottom - rect.top; | |
597 int updateY = 0; | |
598 if (up) { | |
599 if (focusItem.y < 0) { | |
600 updateY = Math.min (yCurrentScroll, -focusItem.y); | |
601 } | |
602 } else { | |
603 int itemHeight = focusItem.y + getBandHeight (); | |
604 if (focusItem.expanded) { | |
605 if (height >= getBandHeight () + focusItem.height) { | |
606 itemHeight += focusItem.height; | |
607 } | |
608 } | |
609 if (itemHeight > height) { | |
610 updateY = height - itemHeight; | |
611 } | |
612 } | |
613 if (updateY !is 0) { | |
614 yCurrentScroll = Math.max (0, yCurrentScroll - updateY); | |
615 if ((style & SWT.V_SCROLL) !is 0) { | |
616 SCROLLINFO info; | |
617 info.cbSize = SCROLLINFO.sizeof; | |
618 info.fMask = OS.SIF_POS; | |
619 info.nPos = yCurrentScroll; | |
620 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true); | |
621 } | |
622 OS.ScrollWindowEx (handle, 0, updateY, null, null, null, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE); | |
623 for (int i = 0; i < itemCount; i++) { | |
624 items [i].y += updateY; | |
625 } | |
626 } | |
627 } | |
628 | |
629 override String windowClass () { | |
630 return display.windowClass; | |
631 } | |
632 | |
633 override int windowProc () { | |
634 return cast(int) display.windowProc; | |
635 } | |
636 | |
637 override LRESULT WM_KEYDOWN (int wParam, int lParam) { | |
638 LRESULT result = super.WM_KEYDOWN (wParam, lParam); | |
639 if (result !is null) return result; | |
640 if (focusItem is null) return result; | |
641 switch (wParam) { | |
642 case OS.VK_SPACE: | |
643 case OS.VK_RETURN: | |
644 Event event = new Event (); | |
645 event.item = focusItem; | |
646 sendEvent (focusItem.expanded ? SWT.Collapse : SWT.Expand, event); | |
647 focusItem.expanded = !focusItem.expanded; | |
648 showItem (focusItem); | |
649 return LRESULT.ZERO; | |
650 case OS.VK_UP: { | |
651 int focusIndex = indexOf (focusItem); | |
652 if (focusIndex > 0) { | |
653 focusItem.redraw (true); | |
654 focusItem = items [focusIndex - 1]; | |
655 focusItem.redraw (true); | |
656 showFocus (true); | |
657 return LRESULT.ZERO; | |
658 } | |
659 break; | |
660 } | |
661 case OS.VK_DOWN: { | |
662 int focusIndex = indexOf (focusItem); | |
663 if (focusIndex < itemCount - 1) { | |
664 focusItem.redraw (true); | |
665 focusItem = items [focusIndex + 1]; | |
666 focusItem.redraw (true); | |
667 showFocus (false); | |
668 return LRESULT.ZERO; | |
669 } | |
670 break; | |
671 } | |
672 default: | |
673 } | |
674 return result; | |
675 } | |
676 | |
677 override LRESULT WM_KILLFOCUS (int wParam, int lParam) { | |
678 LRESULT result = super.WM_KILLFOCUS (wParam, lParam); | |
679 if (focusItem !is null) focusItem.redraw (true); | |
680 return result; | |
681 } | |
682 | |
683 override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { | |
684 LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam); | |
685 if (result is LRESULT.ZERO) return result; | |
686 int x = OS.GET_X_LPARAM (lParam); | |
687 int y = OS.GET_Y_LPARAM (lParam); | |
688 for (int i = 0; i < itemCount; i++) { | |
689 ExpandItem item = items[i]; | |
690 bool hover = item.isHover (x, y); | |
691 if (hover && focusItem !is item) { | |
692 focusItem.redraw (true); | |
693 focusItem = item; | |
694 focusItem.redraw (true); | |
695 forceFocus (); | |
696 break; | |
697 } | |
698 } | |
699 return result; | |
700 } | |
701 | |
702 override LRESULT WM_LBUTTONUP (int wParam, int lParam) { | |
703 LRESULT result = super.WM_LBUTTONUP (wParam, lParam); | |
704 if (result is LRESULT.ZERO) return result; | |
705 if (focusItem is null) return result; | |
706 int x = OS.GET_X_LPARAM (lParam); | |
707 int y = OS.GET_Y_LPARAM (lParam); | |
708 bool hover = focusItem.isHover (x, y); | |
709 if (hover) { | |
710 Event event = new Event (); | |
711 event.item = focusItem; | |
712 sendEvent (focusItem.expanded ? SWT.Collapse : SWT.Expand, event); | |
713 focusItem.expanded = !focusItem.expanded; | |
714 showItem (focusItem); | |
715 } | |
716 return result; | |
717 } | |
718 | |
719 override LRESULT WM_MOUSELEAVE (int wParam, int lParam) { | |
720 LRESULT result = super.WM_MOUSELEAVE (wParam, lParam); | |
721 if (result !is null) return result; | |
722 for (int i = 0; i < itemCount; i++) { | |
723 ExpandItem item = items [i]; | |
724 if (item.hover) { | |
725 item.hover = false; | |
726 item.redraw (false); | |
727 break; | |
728 } | |
729 } | |
730 return result; | |
731 } | |
732 | |
733 override LRESULT WM_MOUSEMOVE (int wParam, int lParam) { | |
734 LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); | |
735 if (result is LRESULT.ZERO) return result; | |
736 int x = OS.GET_X_LPARAM (lParam); | |
737 int y = OS.GET_Y_LPARAM (lParam); | |
738 for (int i = 0; i < itemCount; i++) { | |
739 ExpandItem item = items [i]; | |
740 bool hover = item.isHover (x, y); | |
741 if (item.hover !is hover) { | |
742 item.hover = hover; | |
743 item.redraw (false); | |
744 } | |
745 } | |
746 return result; | |
747 } | |
748 | |
749 override LRESULT WM_PAINT (int wParam, int lParam) { | |
750 PAINTSTRUCT ps; | |
751 GCData data = new GCData (); | |
752 data.ps = &ps; | |
753 data.hwnd = handle; | |
754 GC gc = new_GC (data); | |
755 if (gc !is null) { | |
756 int width = ps.rcPaint.right - ps.rcPaint.left; | |
757 int height = ps.rcPaint.bottom - ps.rcPaint.top; | |
758 if (width !is 0 && height !is 0) { | |
759 RECT rect; | |
760 OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); | |
761 drawWidget (gc, &rect); | |
762 if (hooks (SWT.Paint) || filters (SWT.Paint)) { | |
763 Event event = new Event (); | |
764 event.gc = gc; | |
765 event.x = rect.left; | |
766 event.y = rect.top; | |
767 event.width = width; | |
768 event.height = height; | |
769 sendEvent (SWT.Paint, event); | |
770 event.gc = null; | |
771 } | |
772 } | |
773 gc.dispose (); | |
774 } | |
775 return LRESULT.ZERO; | |
776 } | |
777 | |
778 override LRESULT WM_PRINTCLIENT (int wParam, int lParam) { | |
779 LRESULT result = super.WM_PRINTCLIENT (wParam, lParam); | |
780 RECT rect; | |
781 OS.GetClientRect (handle, &rect); | |
782 GCData data = new GCData (); | |
783 data.device = display; | |
784 data.foreground = getForegroundPixel (); | |
785 GC gc = GC.win32_new ( cast(Drawable)cast(void*)wParam, data); | |
786 drawWidget (gc, &rect); | |
787 gc.dispose (); | |
788 return result; | |
789 } | |
790 | |
791 override LRESULT WM_SETCURSOR (int wParam, int lParam) { | |
792 LRESULT result = super.WM_SETCURSOR (wParam, lParam); | |
793 if (result !is null) return result; | |
794 int hitTest = cast(short) OS.LOWORD (lParam); | |
795 if (hitTest is OS.HTCLIENT) { | |
796 for (int i = 0; i < itemCount; i++) { | |
797 ExpandItem item = items [i]; | |
798 if (item.hover) { | |
799 auto hCursor = OS.LoadCursor (null, OS.IDC_HAND); | |
800 OS.SetCursor (hCursor); | |
801 return LRESULT.ONE; | |
802 } | |
803 } | |
804 } | |
805 return result; | |
806 } | |
807 | |
808 override LRESULT WM_SETFOCUS (int wParam, int lParam) { | |
809 LRESULT result = super.WM_SETFOCUS (wParam, lParam); | |
810 if (focusItem !is null) focusItem.redraw (true); | |
811 return result; | |
812 } | |
813 | |
814 override LRESULT WM_SIZE (int wParam, int lParam) { | |
815 LRESULT result = super.WM_SIZE (wParam, lParam); | |
816 RECT rect; | |
817 OS.GetClientRect (handle, &rect); | |
818 int width = Math.max (0, (rect.right - rect.left) - spacing * 2); | |
819 for (int i = 0; i < itemCount; i++) { | |
820 ExpandItem item = items[i]; | |
821 if (item.width !is width) item.setBounds (0, 0, width, item.height, false, true); | |
822 } | |
823 setScrollbar (); | |
824 OS.InvalidateRect (handle, null, true); | |
825 return result; | |
826 } | |
827 | |
828 override LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int wParam, int lParam) { | |
829 LRESULT result = super.wmScroll (bar, true, hwnd, msg, wParam, lParam); | |
830 SCROLLINFO info; | |
831 info.cbSize = SCROLLINFO.sizeof; | |
832 info.fMask = OS.SIF_POS; | |
833 OS.GetScrollInfo (handle, OS.SB_VERT, &info); | |
834 int updateY = yCurrentScroll - info.nPos; | |
835 OS.ScrollWindowEx (handle, 0, updateY, null, null, null, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE); | |
836 yCurrentScroll = info.nPos; | |
837 if (updateY !is 0) { | |
838 for (int i = 0; i < itemCount; i++) { | |
839 items [i].y += updateY; | |
840 } | |
841 } | |
842 return result; | |
843 } | |
844 } | |
845 |