Mercurial > projects > dynamin
annotate dynamin/gui/container.d @ 83:3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Also, update controls to work with the new API.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Sun, 18 Jul 2010 22:20:50 -0500 |
parents | 651082a9b364 |
children | 73060bc3f004 |
rev | line source |
---|---|
0 | 1 // Written in the D programming language |
2 // www.digitalmars.com/d/ | |
3 | |
4 /* | |
5 * The contents of this file are subject to the Mozilla Public License Version | |
6 * 1.1 (the "License"); you may not use this file except in compliance with | |
7 * the License. You may obtain a copy of the License at | |
8 * http://www.mozilla.org/MPL/ | |
9 * | |
10 * Software distributed under the License is distributed on an "AS IS" basis, | |
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 * for the specific language governing rights and limitations under the | |
13 * License. | |
14 * | |
15 * The Original Code is the Dynamin library. | |
16 * | |
17 * The Initial Developer of the Original Code is Jordan Miner. | |
18 * Portions created by the Initial Developer are Copyright (C) 2006-2009 | |
19 * the Initial Developer. All Rights Reserved. | |
20 * | |
21 * Contributor(s): | |
22 * Jordan Miner <jminer7@gmail.com> | |
23 * | |
24 */ | |
25 | |
26 module dynamin.gui.container; | |
27 | |
28 import dynamin.all_core; | |
29 import dynamin.all_painting; | |
30 import dynamin.all_gui; | |
31 import dynamin.gui.control; | |
32 import dynamin.gui.events; | |
62 | 33 import dynamin.gui.button; |
0 | 34 import tango.io.Stdout; |
35 | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
36 alias List!(Control, true) ControlList; |
0 | 37 |
38 /// | |
39 class Container : Control { | |
40 protected: | |
41 ControlList _children; | |
42 Size _minSize; | |
43 Size _maxSize; | |
62 | 44 Button _defaultButton; |
0 | 45 |
46 override void whenResized(EventArgs e) { | |
47 layout(); | |
48 } | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
49 // If the specified array is large enough to hold the results, no heap |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
50 // allocation will be done. |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
51 Control[] getFocusableDescendants(Control[] des = null) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
52 uint cur = 0; |
70
340c3777ea68
Use Container.descendantsPlus in getFocusableDescendants for shorter code.
Jordan Miner <jminer7@gmail.com>
parents:
68
diff
changeset
|
53 foreach(d; &descendantsPlus) { |
340c3777ea68
Use Container.descendantsPlus in getFocusableDescendants for shorter code.
Jordan Miner <jminer7@gmail.com>
parents:
68
diff
changeset
|
54 if(d.focusable) { // TODO: && ch.enabled) { |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
55 if(cur == des.length) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
56 des.length = des.length + 20; |
70
340c3777ea68
Use Container.descendantsPlus in getFocusableDescendants for shorter code.
Jordan Miner <jminer7@gmail.com>
parents:
68
diff
changeset
|
57 des[cur++] = d; |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
58 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
59 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
60 return des[0..cur]; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
61 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
62 unittest { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
63 class MyControl : Control { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
64 this() { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
65 _focusable = true; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
66 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
67 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
68 auto container1 = new Container(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
69 auto container2 = new Container(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
70 auto container3 = new Container(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
71 auto container4 = new Container(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
72 container2._focusable = true; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
73 container4._focusable = true; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
74 auto ctrl1 = new MyControl(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
75 auto ctrl2 = new MyControl(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
76 auto ctrl3 = new MyControl(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
77 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
78 container1.add(container2); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
79 container1.add(container3); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
80 container3.add(container4); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
81 container2.add(ctrl1); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
82 container4.add(ctrl2); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
83 container4.add(ctrl3); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
84 assert(container1.getFocusableDescendants() == |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
85 [cast(Control)container2, ctrl1, container4, ctrl2, ctrl3]); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
86 Control[5] buf; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
87 assert(container1.getFocusableDescendants(buf).ptr == buf.ptr); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
88 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
89 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
90 // not an event |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
91 void whenChildrenChanged(ListChangeType, Control oldChild, Control newChild, uint) { |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
92 if(oldChild) { |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
93 oldChild.parent = null; |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
94 repaint(); |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
95 |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
96 scope e = new HierarchyEventArgs(oldChild); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
97 descendantRemoved(e); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
98 } |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
99 |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
100 if(newChild) { |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
101 if(newChild.parent) |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
102 newChild.parent.remove(newChild); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
103 newChild.parent = this; |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
104 repaint(); |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
105 |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
106 void callAdded(Control ctrl) { |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
107 scope e = new HierarchyEventArgs(ctrl); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
108 descendantAdded(e); |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
109 |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
110 if(auto cntr = cast(Container)ctrl) { |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
111 foreach(c; cntr._children) |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
112 callAdded(c); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
113 } |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
114 } |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
115 callAdded(newChild); |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
116 } |
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
117 |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
118 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
119 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
120 void dispatchDescendantAdded(HierarchyEventArgs e) { |
62 | 121 if(e.descendant is defaultButton) |
122 (cast(Button)e.descendant)._isDefault = true; | |
123 | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
124 descendantAdded.callHandlers(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
125 descendantAdded.callMainHandler(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
126 e.levels = e.levels + 1; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
127 if(_parent) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
128 _parent.descendantAdded(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
129 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
130 void dispatchDescendantRemoved(HierarchyEventArgs e) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
131 descendantRemoved.callHandlers(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
132 descendantRemoved.callMainHandler(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
133 e.levels = e.levels + 1; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
134 if(_parent) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
135 _parent.descendantRemoved(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
136 } |
62 | 137 |
138 override void whenKeyDown(KeyEventArgs e) { | |
139 if(e.key == Key.Enter && defaultButton) { | |
140 scope e2 = new EventArgs; | |
141 defaultButton.clicked(e2); | |
142 e.stopped = true; | |
143 } | |
144 } | |
145 | |
0 | 146 public: |
147 /// Override this method in a subclass to handle the minSizeChanged event. | |
148 protected void whenMinSizeChanged(EventArgs e) { } | |
8
b621b528823d
whenXX methods have to come before the event if switched to template mixins.
Jordan Miner <jminer7@gmail.com>
parents:
5
diff
changeset
|
149 /// This event occurs after the control's minimum size has been changed. |
10
ccc108b25a0a
Convert to using a struct for events. Fix some comments too.
Jordan Miner <jminer7@gmail.com>
parents:
8
diff
changeset
|
150 Event!(whenMinSizeChanged) minSizeChanged; |
0 | 151 |
8
b621b528823d
whenXX methods have to come before the event if switched to template mixins.
Jordan Miner <jminer7@gmail.com>
parents:
5
diff
changeset
|
152 /// Override this method in a subclass to handle the maxSizeChanged event. |
b621b528823d
whenXX methods have to come before the event if switched to template mixins.
Jordan Miner <jminer7@gmail.com>
parents:
5
diff
changeset
|
153 protected void whenMaxSizeChanged(EventArgs e) { } |
0 | 154 /// This event occurs after the control's maximum size has been changed. |
10
ccc108b25a0a
Convert to using a struct for events. Fix some comments too.
Jordan Miner <jminer7@gmail.com>
parents:
8
diff
changeset
|
155 Event!(whenMaxSizeChanged) maxSizeChanged; |
0 | 156 |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
157 /// Override this method in a subclass to handle the descendantAdded event. |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
158 protected void whenDescendantAdded(HierarchyEventArgs e) { } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
159 /// This event occurs after a control is added as a descendant of this container. |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
160 Event!(whenDescendantAdded) descendantAdded; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
161 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
162 /// Override this method in a subclass to handle the descendantRemoved event. |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
163 protected void whenDescendantRemoved(HierarchyEventArgs e) { } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
164 /// This event occurs after a descendant of this container has been removed. |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
165 Event!(whenDescendantRemoved) descendantRemoved; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
166 |
0 | 167 this() { |
78
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
168 minSizeChanged .setUp(&whenMinSizeChanged); |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
169 maxSizeChanged .setUp(&whenMaxSizeChanged); |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
170 descendantAdded .setUp(&whenDescendantAdded, &dispatchDescendantAdded); |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
171 descendantRemoved.setUp(&whenDescendantRemoved, |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
172 &dispatchDescendantRemoved); |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
173 |
83
3cfc83a99cbc
Add List.opIndexAssign and switch to one callback for change notification.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
174 _children = new ControlList(&whenChildrenChanged); |
0 | 175 |
176 elasticX = true; | |
177 elasticY = true; | |
178 } | |
62 | 179 |
180 /** | |
181 * Gets or sets the default button in this container. | |
182 */ | |
183 Button defaultButton() { return _defaultButton; } | |
184 /// ditto | |
185 void defaultButton(Button b) { | |
186 _defaultButton = b; | |
187 foreach(d; &descendants) { | |
188 if(b == d) | |
189 b._isDefault = true; | |
190 } | |
191 } | |
192 | |
0 | 193 override void dispatchPainting(PaintingEventArgs e) { |
194 super.dispatchPainting(e); | |
195 foreach(c; _children) { | |
196 e.graphics.save(); | |
197 e.graphics.translate(c.x, c.y); | |
198 c.setupGraphics(e.graphics); | |
199 c.painting(e); | |
200 e.graphics.restore(); | |
201 } | |
202 } | |
203 // TODO: make these use common code...get rid of copy and paste | |
204 override void dispatchMouseDown(MouseEventArgs e) { | |
205 auto c = getChildAtPoint(e.location); | |
206 if(c && getCaptorControl() !is this) { | |
207 e.location = e.location - c.location; | |
208 c.mouseDown(e); | |
209 e.location = e.location + c.location; | |
210 } else { | |
211 super.dispatchMouseDown(e); | |
212 } | |
213 } | |
214 override void dispatchMouseUp(MouseEventArgs e) { | |
215 auto c = getChildAtPoint(e.location); | |
216 if(c && getCaptorControl() !is this) { | |
217 e.location = e.location - c.location; | |
218 c.mouseUp(e); | |
219 e.location = e.location + c.location; | |
220 } else { | |
221 super.dispatchMouseUp(e); | |
222 } | |
223 } | |
224 override void dispatchMouseMoved(MouseEventArgs e) { | |
225 auto c = getChildAtPoint(e.location); | |
226 if(c && getCaptorControl() !is this) { | |
227 e.location = e.location - c.location; | |
228 c.mouseMoved(e); | |
229 e.location = e.location + c.location; | |
230 } else { | |
231 super.dispatchMouseMoved(e); | |
232 } | |
233 } | |
234 override void dispatchMouseDragged(MouseEventArgs e) { | |
235 auto c = getChildAtPoint(e.location); | |
236 if(c && getCaptorControl() !is this) { | |
237 e.location = e.location - c.location; | |
238 c.mouseDragged(e); | |
239 e.location = e.location + c.location; | |
240 } else { | |
241 super.dispatchMouseDragged(e); | |
242 } | |
243 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
244 |
0 | 245 /** |
246 * Gets the child control at the specified point. If there are | |
247 * multiple child controls at the point, the topmost control is returned. | |
248 * If there is no child control at the point, null is returned. The returned | |
249 * control, if any, is a direct child of this container. | |
250 */ | |
251 Control getChildAtPoint(real[] pt) { | |
252 assert(pt.length == 2, "pt must be just an x and y"); | |
253 return getChildAtPoint(Point(pt[0], pt[1])); | |
254 } | |
255 /// ditto | |
256 Control getChildAtPoint(real x, real y) { | |
257 return getChildAtPoint(Point(x, y)); | |
258 } | |
259 /// ditto | |
260 Control getChildAtPoint(Point pt) { | |
261 for(int i = _children.count-1; i >= 0; --i) { | |
262 pt = pt - _children[i].location; | |
263 scope(exit) pt = pt + _children[i].location; | |
264 if(_children[i].contains(pt)) | |
265 return _children[i]; | |
266 } | |
267 return null; | |
268 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
269 |
0 | 270 /** |
271 * Never returns null. If there is no descendant at the specified point, | |
272 * this container will be returned. | |
273 */ | |
274 Control getDescendantAtPoint(real[] pt) { | |
275 assert(pt.length == 2, "pt must be just an x and y"); | |
276 return getDescendantAtPoint(Point(pt[0], pt[1])); | |
277 } | |
278 /// ditto | |
279 Control getDescendantAtPoint(real x, real y) { | |
280 return getDescendantAtPoint(Point(x, y)); | |
281 } | |
282 /// ditto | |
283 Control getDescendantAtPoint(Point pt) { | |
284 Container des = this; | |
285 while(true) { | |
286 auto child = des.getChildAtPoint(pt); | |
287 if(!child) | |
288 return des; | |
289 auto isContainer = cast(Container)child; | |
290 if(isContainer) { | |
291 des = isContainer; | |
292 pt = pt - des.location; | |
293 // loop around with this container | |
294 } else { | |
295 return child; | |
296 } | |
297 } | |
298 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
299 |
0 | 300 /** |
301 * Gets or sets the minimum size of this window. A minimum width or | |
302 * height of 0 means that there is no minimum width or height. | |
303 * The default is Size(0, 0). | |
304 */ | |
305 Size minSize() { return _minSize; } | |
306 /// ditto | |
307 void minSize(Size size) { | |
68
6580fabb7dce
Setting a property to the value it already is shouldn't do anything
Jordan Miner <jminer7@gmail.com>
parents:
62
diff
changeset
|
308 if(_minSize == size) |
6580fabb7dce
Setting a property to the value it already is shouldn't do anything
Jordan Miner <jminer7@gmail.com>
parents:
62
diff
changeset
|
309 return; |
0 | 310 _minSize = size; |
311 minSizeChanged(new EventArgs); | |
312 } | |
313 /// ditto | |
314 void minSize(real[] size) { | |
315 assert(size.length == 2, "size must be just a width and height"); | |
316 minSize = Size(size[0], size[1]); | |
317 } | |
318 /// | |
319 real minWidth() { return _minSize.width; } | |
320 /// | |
321 real minHeight() { return _minSize.height; } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
322 |
0 | 323 /** |
324 * Gets or sets the maximum size of this window. A maximum width or | |
325 * height of 0 means that there is no maximum width or height. | |
326 * The default is Size(0, 0). | |
327 */ | |
328 Size maxSize() { return _maxSize; } | |
329 /// ditto | |
330 void maxSize(Size size) { | |
68
6580fabb7dce
Setting a property to the value it already is shouldn't do anything
Jordan Miner <jminer7@gmail.com>
parents:
62
diff
changeset
|
331 if(_maxSize == size) |
6580fabb7dce
Setting a property to the value it already is shouldn't do anything
Jordan Miner <jminer7@gmail.com>
parents:
62
diff
changeset
|
332 return; |
0 | 333 _maxSize = size; |
334 minSizeChanged(new EventArgs); | |
335 } | |
336 /// ditto | |
337 void maxSize(real[] size) { | |
338 assert(size.length == 2, "size must be just a width and height"); | |
339 maxSize = Size(size[0], size[1]); | |
340 } | |
341 /// | |
342 real maxWidth() { return _maxSize.width; } | |
343 /// | |
344 real maxHeight() { return _maxSize.height; } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
345 |
0 | 346 /** |
347 * Causes this container to position its child controls. Called on every | |
348 * resize. Usually, this function will get each child's best size, and | |
349 * then set each child's location and height. The definition in Container | |
350 * is empty, as it is intended for subclasses to override. | |
351 */ | |
352 void layout() { | |
353 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
354 |
0 | 355 protected void add(Control child) { |
356 _children.add(child); | |
357 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
358 |
0 | 359 protected void remove(Control child) { |
360 _children.remove(child); | |
361 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
362 |
58 | 363 /** |
364 * Calls the specified delegate with each child of this container, for | |
365 * use with foreach. | |
366 */ | |
367 int opApply(int delegate(ref Control item) dg) { | |
0 | 368 for(uint i = 0; i < _children.count; ++i) { |
369 auto tmp = _children[i]; | |
370 if(int result = dg(tmp)) | |
371 return result; | |
372 } | |
373 return 0; | |
374 } | |
58 | 375 /// ditto |
376 int opApply(int delegate(ref uint index, ref Control item) dg) { | |
0 | 377 for(uint i = 0; i < _children.count; ++i) { |
378 auto tmp = _children[i]; | |
379 if(int result = dg(i, tmp)) | |
380 return result; | |
381 } | |
382 return 0; | |
383 } | |
57 | 384 /** |
385 * Calls the specified delegate with each descendant of this container, for | |
386 * use with foreach. | |
387 * | |
388 * Example: | |
389 * ----- | |
390 * foreach(c; &container.descendants) { | |
391 * // do something with c | |
392 * } | |
393 * ----- | |
394 */ | |
395 int descendants(int delegate(ref Control item) dg) { | |
396 for(int i = 0; i < _children.count; ++i) { | |
397 auto tmp = _children[i]; | |
398 if(int result = dg(tmp)) | |
399 return result; | |
400 auto c = cast(Container)_children[i]; | |
401 if(c) | |
402 if(int result = c.descendants(dg)) | |
403 return result; | |
404 } | |
405 return 0; | |
406 } | |
407 /** | |
408 * Same as descendants(), but includes this container in addition to | |
409 * descendants. | |
410 */ | |
411 int descendantsPlus(int delegate(ref Control item) dg) { | |
412 Control tmp = this; | |
413 if(int result = dg(tmp)) | |
414 return result; | |
415 if(int result = descendants(dg)) | |
416 return result; | |
417 return 0; | |
418 } | |
0 | 419 } |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
420 unittest { |
57 | 421 int a = 0, r = 0; |
422 auto container1 = new Panel; | |
423 auto container2 = new Panel; | |
424 auto control1 = new Control; | |
425 auto control2 = new Control; | |
426 auto control3 = new Control; | |
427 container1.descendantAdded += (HierarchyEventArgs e) { a++; }; | |
428 container1.descendantRemoved += (HierarchyEventArgs e) { r++; }; | |
429 | |
430 container2.add(control2); | |
431 container2.children.add(control3); | |
432 assert(control3.parent == container2); | |
433 container1.add(control1); | |
434 assert(a == 1); // test descendantAdded | |
435 container1.add(container2); | |
436 assert(a == 4); // test descendantAdded | |
437 | |
438 // test Container.descendants | |
439 auto list = new List!(Control); | |
440 foreach(c; &container1.descendants) | |
441 list.add(c); | |
442 assert(list.data == [control1, container2, control2, control3]); | |
443 | |
444 list.clear(); | |
445 foreach(c; &container1.descendantsPlus) | |
446 list.add(c); | |
447 assert(list.data == [cast(Control)container1, control1, container2, | |
448 control2, control3]); | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
449 } |
0 | 450 |
58 | 451 /// |
0 | 452 class Panel : Container { |
58 | 453 /// |
0 | 454 ControlList children() { return _children; } |
58 | 455 /// |
0 | 456 void add(Control child) { super.add(child); }; |
58 | 457 /// |
0 | 458 void remove(Control child) { super.remove(child); }; |
58 | 459 /// |
460 int opApply(int delegate(ref Control item) dg) { | |
0 | 461 return super.opApply(dg); |
462 } | |
58 | 463 /// |
464 int opApply(int delegate(ref uint index, ref Control item) dg) { | |
0 | 465 return super.opApply(dg); |
466 } | |
467 } | |
468 |