Mercurial > projects > dynamin
annotate dynamin/gui/container.d @ 78:651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Sat, 06 Feb 2010 15:12:52 -0600 |
parents | 340c3777ea68 |
children | 3cfc83a99cbc |
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 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
91 void whenChildAdded(Control child, int) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
92 if(child.parent) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
93 child.parent.remove(child); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
94 child.parent = this; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
95 repaint(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
96 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
97 void callAdded(Control ctrl) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
98 scope e = new HierarchyEventArgs(ctrl); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
99 descendantAdded(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
100 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
101 if(auto cntr = cast(Container)ctrl) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
102 foreach(c; cntr._children) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
103 callAdded(c); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
104 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
105 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
106 callAdded(child); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
107 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
108 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
109 // not an event |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
110 void whenChildRemoved(Control child, int) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
111 child.parent = null; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
112 repaint(); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
113 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
114 scope e = new HierarchyEventArgs(child); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
115 descendantRemoved(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
116 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
117 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
118 void dispatchDescendantAdded(HierarchyEventArgs e) { |
62 | 119 if(e.descendant is defaultButton) |
120 (cast(Button)e.descendant)._isDefault = true; | |
121 | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
122 descendantAdded.callHandlers(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
123 descendantAdded.callMainHandler(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
124 e.levels = e.levels + 1; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
125 if(_parent) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
126 _parent.descendantAdded(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
127 } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
128 void dispatchDescendantRemoved(HierarchyEventArgs e) { |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
129 descendantRemoved.callHandlers(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
130 descendantRemoved.callMainHandler(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
131 e.levels = e.levels + 1; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
132 if(_parent) |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
133 _parent.descendantRemoved(e); |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
134 } |
62 | 135 |
136 override void whenKeyDown(KeyEventArgs e) { | |
137 if(e.key == Key.Enter && defaultButton) { | |
138 scope e2 = new EventArgs; | |
139 defaultButton.clicked(e2); | |
140 e.stopped = true; | |
141 } | |
142 } | |
143 | |
0 | 144 public: |
145 /// Override this method in a subclass to handle the minSizeChanged event. | |
146 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
|
147 /// 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
|
148 Event!(whenMinSizeChanged) minSizeChanged; |
0 | 149 |
8
b621b528823d
whenXX methods have to come before the event if switched to template mixins.
Jordan Miner <jminer7@gmail.com>
parents:
5
diff
changeset
|
150 /// 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
|
151 protected void whenMaxSizeChanged(EventArgs e) { } |
0 | 152 /// 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
|
153 Event!(whenMaxSizeChanged) maxSizeChanged; |
0 | 154 |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
155 /// 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
|
156 protected void whenDescendantAdded(HierarchyEventArgs e) { } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
157 /// 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
|
158 Event!(whenDescendantAdded) descendantAdded; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
159 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
160 /// 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
|
161 protected void whenDescendantRemoved(HierarchyEventArgs e) { } |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
162 /// 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
|
163 Event!(whenDescendantRemoved) descendantRemoved; |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
164 |
0 | 165 this() { |
78
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
166 minSizeChanged .setUp(&whenMinSizeChanged); |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
167 maxSizeChanged .setUp(&whenMaxSizeChanged); |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
168 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
|
169 descendantRemoved.setUp(&whenDescendantRemoved, |
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
70
diff
changeset
|
170 &dispatchDescendantRemoved); |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
171 |
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
172 _children = new ControlList(&whenChildAdded, &whenChildRemoved); |
0 | 173 |
174 elasticX = true; | |
175 elasticY = true; | |
176 } | |
62 | 177 |
178 /** | |
179 * Gets or sets the default button in this container. | |
180 */ | |
181 Button defaultButton() { return _defaultButton; } | |
182 /// ditto | |
183 void defaultButton(Button b) { | |
184 _defaultButton = b; | |
185 foreach(d; &descendants) { | |
186 if(b == d) | |
187 b._isDefault = true; | |
188 } | |
189 } | |
190 | |
0 | 191 override void dispatchPainting(PaintingEventArgs e) { |
192 super.dispatchPainting(e); | |
193 foreach(c; _children) { | |
194 e.graphics.save(); | |
195 e.graphics.translate(c.x, c.y); | |
196 c.setupGraphics(e.graphics); | |
197 c.painting(e); | |
198 e.graphics.restore(); | |
199 } | |
200 } | |
201 // TODO: make these use common code...get rid of copy and paste | |
202 override void dispatchMouseDown(MouseEventArgs e) { | |
203 auto c = getChildAtPoint(e.location); | |
204 if(c && getCaptorControl() !is this) { | |
205 e.location = e.location - c.location; | |
206 c.mouseDown(e); | |
207 e.location = e.location + c.location; | |
208 } else { | |
209 super.dispatchMouseDown(e); | |
210 } | |
211 } | |
212 override void dispatchMouseUp(MouseEventArgs e) { | |
213 auto c = getChildAtPoint(e.location); | |
214 if(c && getCaptorControl() !is this) { | |
215 e.location = e.location - c.location; | |
216 c.mouseUp(e); | |
217 e.location = e.location + c.location; | |
218 } else { | |
219 super.dispatchMouseUp(e); | |
220 } | |
221 } | |
222 override void dispatchMouseMoved(MouseEventArgs e) { | |
223 auto c = getChildAtPoint(e.location); | |
224 if(c && getCaptorControl() !is this) { | |
225 e.location = e.location - c.location; | |
226 c.mouseMoved(e); | |
227 e.location = e.location + c.location; | |
228 } else { | |
229 super.dispatchMouseMoved(e); | |
230 } | |
231 } | |
232 override void dispatchMouseDragged(MouseEventArgs e) { | |
233 auto c = getChildAtPoint(e.location); | |
234 if(c && getCaptorControl() !is this) { | |
235 e.location = e.location - c.location; | |
236 c.mouseDragged(e); | |
237 e.location = e.location + c.location; | |
238 } else { | |
239 super.dispatchMouseDragged(e); | |
240 } | |
241 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
242 |
0 | 243 /** |
244 * Gets the child control at the specified point. If there are | |
245 * multiple child controls at the point, the topmost control is returned. | |
246 * If there is no child control at the point, null is returned. The returned | |
247 * control, if any, is a direct child of this container. | |
248 */ | |
249 Control getChildAtPoint(real[] pt) { | |
250 assert(pt.length == 2, "pt must be just an x and y"); | |
251 return getChildAtPoint(Point(pt[0], pt[1])); | |
252 } | |
253 /// ditto | |
254 Control getChildAtPoint(real x, real y) { | |
255 return getChildAtPoint(Point(x, y)); | |
256 } | |
257 /// ditto | |
258 Control getChildAtPoint(Point pt) { | |
259 for(int i = _children.count-1; i >= 0; --i) { | |
260 pt = pt - _children[i].location; | |
261 scope(exit) pt = pt + _children[i].location; | |
262 if(_children[i].contains(pt)) | |
263 return _children[i]; | |
264 } | |
265 return null; | |
266 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
267 |
0 | 268 /** |
269 * Never returns null. If there is no descendant at the specified point, | |
270 * this container will be returned. | |
271 */ | |
272 Control getDescendantAtPoint(real[] pt) { | |
273 assert(pt.length == 2, "pt must be just an x and y"); | |
274 return getDescendantAtPoint(Point(pt[0], pt[1])); | |
275 } | |
276 /// ditto | |
277 Control getDescendantAtPoint(real x, real y) { | |
278 return getDescendantAtPoint(Point(x, y)); | |
279 } | |
280 /// ditto | |
281 Control getDescendantAtPoint(Point pt) { | |
282 Container des = this; | |
283 while(true) { | |
284 auto child = des.getChildAtPoint(pt); | |
285 if(!child) | |
286 return des; | |
287 auto isContainer = cast(Container)child; | |
288 if(isContainer) { | |
289 des = isContainer; | |
290 pt = pt - des.location; | |
291 // loop around with this container | |
292 } else { | |
293 return child; | |
294 } | |
295 } | |
296 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
297 |
0 | 298 /** |
299 * Gets or sets the minimum size of this window. A minimum width or | |
300 * height of 0 means that there is no minimum width or height. | |
301 * The default is Size(0, 0). | |
302 */ | |
303 Size minSize() { return _minSize; } | |
304 /// ditto | |
305 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
|
306 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
|
307 return; |
0 | 308 _minSize = size; |
309 minSizeChanged(new EventArgs); | |
310 } | |
311 /// ditto | |
312 void minSize(real[] size) { | |
313 assert(size.length == 2, "size must be just a width and height"); | |
314 minSize = Size(size[0], size[1]); | |
315 } | |
316 /// | |
317 real minWidth() { return _minSize.width; } | |
318 /// | |
319 real minHeight() { return _minSize.height; } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
320 |
0 | 321 /** |
322 * Gets or sets the maximum size of this window. A maximum width or | |
323 * height of 0 means that there is no maximum width or height. | |
324 * The default is Size(0, 0). | |
325 */ | |
326 Size maxSize() { return _maxSize; } | |
327 /// ditto | |
328 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
|
329 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
|
330 return; |
0 | 331 _maxSize = size; |
332 minSizeChanged(new EventArgs); | |
333 } | |
334 /// ditto | |
335 void maxSize(real[] size) { | |
336 assert(size.length == 2, "size must be just a width and height"); | |
337 maxSize = Size(size[0], size[1]); | |
338 } | |
339 /// | |
340 real maxWidth() { return _maxSize.width; } | |
341 /// | |
342 real maxHeight() { return _maxSize.height; } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
343 |
0 | 344 /** |
345 * Causes this container to position its child controls. Called on every | |
346 * resize. Usually, this function will get each child's best size, and | |
347 * then set each child's location and height. The definition in Container | |
348 * is empty, as it is intended for subclasses to override. | |
349 */ | |
350 void layout() { | |
351 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
352 |
0 | 353 protected void add(Control child) { |
354 _children.add(child); | |
355 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
356 |
0 | 357 protected void remove(Control child) { |
358 _children.remove(child); | |
359 } | |
5
4029d5af7542
Add blank lines and rewrap some comments.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
360 |
58 | 361 /** |
362 * Calls the specified delegate with each child of this container, for | |
363 * use with foreach. | |
364 */ | |
365 int opApply(int delegate(ref Control item) dg) { | |
0 | 366 for(uint i = 0; i < _children.count; ++i) { |
367 auto tmp = _children[i]; | |
368 if(int result = dg(tmp)) | |
369 return result; | |
370 } | |
371 return 0; | |
372 } | |
58 | 373 /// ditto |
374 int opApply(int delegate(ref uint index, ref Control item) dg) { | |
0 | 375 for(uint i = 0; i < _children.count; ++i) { |
376 auto tmp = _children[i]; | |
377 if(int result = dg(i, tmp)) | |
378 return result; | |
379 } | |
380 return 0; | |
381 } | |
57 | 382 /** |
383 * Calls the specified delegate with each descendant of this container, for | |
384 * use with foreach. | |
385 * | |
386 * Example: | |
387 * ----- | |
388 * foreach(c; &container.descendants) { | |
389 * // do something with c | |
390 * } | |
391 * ----- | |
392 */ | |
393 int descendants(int delegate(ref Control item) dg) { | |
394 for(int i = 0; i < _children.count; ++i) { | |
395 auto tmp = _children[i]; | |
396 if(int result = dg(tmp)) | |
397 return result; | |
398 auto c = cast(Container)_children[i]; | |
399 if(c) | |
400 if(int result = c.descendants(dg)) | |
401 return result; | |
402 } | |
403 return 0; | |
404 } | |
405 /** | |
406 * Same as descendants(), but includes this container in addition to | |
407 * descendants. | |
408 */ | |
409 int descendantsPlus(int delegate(ref Control item) dg) { | |
410 Control tmp = this; | |
411 if(int result = dg(tmp)) | |
412 return result; | |
413 if(int result = descendants(dg)) | |
414 return result; | |
415 return 0; | |
416 } | |
0 | 417 } |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
418 unittest { |
57 | 419 int a = 0, r = 0; |
420 auto container1 = new Panel; | |
421 auto container2 = new Panel; | |
422 auto control1 = new Control; | |
423 auto control2 = new Control; | |
424 auto control3 = new Control; | |
425 container1.descendantAdded += (HierarchyEventArgs e) { a++; }; | |
426 container1.descendantRemoved += (HierarchyEventArgs e) { r++; }; | |
427 | |
428 container2.add(control2); | |
429 container2.children.add(control3); | |
430 assert(control3.parent == container2); | |
431 container1.add(control1); | |
432 assert(a == 1); // test descendantAdded | |
433 container1.add(container2); | |
434 assert(a == 4); // test descendantAdded | |
435 | |
436 // test Container.descendants | |
437 auto list = new List!(Control); | |
438 foreach(c; &container1.descendants) | |
439 list.add(c); | |
440 assert(list.data == [control1, container2, control2, control3]); | |
441 | |
442 list.clear(); | |
443 foreach(c; &container1.descendantsPlus) | |
444 list.add(c); | |
445 assert(list.data == [cast(Control)container1, control1, container2, | |
446 control2, control3]); | |
55
c138461bf845
Add focusing and other changes that are related
Jordan Miner <jminer7@gmail.com>
parents:
35
diff
changeset
|
447 } |
0 | 448 |
58 | 449 /// |
0 | 450 class Panel : Container { |
58 | 451 /// |
0 | 452 ControlList children() { return _children; } |
58 | 453 /// |
0 | 454 void add(Control child) { super.add(child); }; |
58 | 455 /// |
0 | 456 void remove(Control child) { super.remove(child); }; |
58 | 457 /// |
458 int opApply(int delegate(ref Control item) dg) { | |
0 | 459 return super.opApply(dg); |
460 } | |
58 | 461 /// |
462 int opApply(int delegate(ref uint index, ref Control item) dg) { | |
0 | 463 return super.opApply(dg); |
464 } | |
465 } | |
466 |