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