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