Mercurial > projects > mde
comparison mde/gui/widget/Window.d @ 41:b3a6ca4516b4
The renderer now controls which parts of the window border allow resizing.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Tue, 13 May 2008 12:02:36 +0100 |
parents | b28d7adc786b |
children | 0fd51d2c6c8a |
comparison
equal
deleted
inserted
replaced
40:b28d7adc786b | 41:b3a6ca4516b4 |
---|---|
20 import mde.gui.widget.Ifaces; | 20 import mde.gui.widget.Ifaces; |
21 import mde.gui.widget.createWidget; | 21 import mde.gui.widget.createWidget; |
22 | 22 |
23 import mde.gui.IGui; | 23 import mde.gui.IGui; |
24 import mde.gui.exception; | 24 import mde.gui.exception; |
25 import mde.gui.renderer.createRenderer; | |
25 | 26 |
26 import mt = mde.mergetag.DataSet; | 27 import mt = mde.mergetag.DataSet; |
27 import tango.scrapple.text.convert.parseTo : parseTo; | 28 import tango.scrapple.text.convert.parseTo : parseTo; |
28 import tango.scrapple.text.convert.parseFrom : parseFrom; | 29 import tango.scrapple.text.convert.parseFrom : parseFrom; |
29 | 30 |
59 } body { | 60 } body { |
60 // Check data was loaded: | 61 // Check data was loaded: |
61 if (widgetData is null) | 62 if (widgetData is null) |
62 throw new WindowLoadException ("No widget creation data"); | 63 throw new WindowLoadException ("No widget creation data"); |
63 | 64 |
65 // Save gui and create the renderer: | |
64 gui_ = gui; | 66 gui_ = gui; |
65 rend = gui.renderer; | 67 rend = createRenderer (gui.rendererName); |
66 | |
67 // Get border sizes | |
68 border = rend.getBorder (BORDER_TYPES.WINDOW_TOTAL); | |
69 resize = rend.getBorder (BORDER_TYPES.WINDOW_RESIZE); | |
70 | 68 |
71 // Create the primary widget (and indirectly all sub-widgets), throwing on error: | 69 // Create the primary widget (and indirectly all sub-widgets), throwing on error: |
72 widget = makeWidget (0); // primary widget always has ID 0. | 70 // Note: GridLayoutWidget's this relies on rend.layoutSpacing. |
71 widget = makeWidget (0); // primary widget always has ID 0. | |
73 widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) | 72 widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) |
74 | 73 |
75 // Note: this should return an empty array, but nothing much should happen if it's not empty: | 74 // get border sizes: |
76 widget.adjust (mutableData); // adjust/set size, etc. | 75 border = rend.setSizable (isWSizable, isHSizable); // depends on widget |
76 | |
77 // Note: this should return an empty array, but we shouldn't make a fuss if it's not empty: | |
78 widget.adjust (mutableData); // adjust/set size, etc., depends on rend | |
77 mutableData = null; // no longer needed | 79 mutableData = null; // no longer needed |
78 | 80 |
79 widget.getCurrentSize (w,h); // and get this size | 81 widget.getCurrentSize (w,h); // and get this size |
80 w += border.l + border.r; // Adjust for border | 82 w += border.l + border.r; // Adjust for border |
81 h += border.t + border.b; | 83 h += border.t + border.b; |
165 widgetData[i] = null; // Make sure the same ID doesn't get used by a recursive call | 167 widgetData[i] = null; // Make sure the same ID doesn't get used by a recursive call |
166 widgetData[i] = widget.getCreationData; | 168 widgetData[i] = widget.getCreationData; |
167 | 169 |
168 return i; | 170 return i; |
169 } | 171 } |
170 | 172 |
171 IGui gui () { | 173 IGui gui () { |
172 return gui_; | 174 return gui_; |
173 } | 175 } |
174 | 176 |
175 IRenderer renderer () { | 177 void requestRedraw () { |
178 gui_.requestRedraw; | |
179 } | |
180 | |
181 IRenderer renderer () | |
182 in { | |
183 assert (rend !is null, "Window.renderer: rend is null"); | |
184 } body { | |
176 return rend; | 185 return rend; |
177 } | 186 } |
178 //END IWindow methods | 187 //END IWindow methods |
179 | 188 |
180 //BEGIN IWidget methods | 189 //BEGIN IWidget methods |
247 else // over the window border | 256 else // over the window border |
248 return this; | 257 return this; |
249 } | 258 } |
250 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { | 259 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { |
251 if (b == 1 && state == true) { | 260 if (b == 1 && state == true) { |
252 if (cx < x + resize.l || cx >= xw - resize.r || | 261 resizeType = rend.getResizeType (cx-x, cy-y, w,h); |
253 cy < y + resize.t || cy >= yh - resize.b) { // window is being resized | 262 |
254 /* check for resizes (different to above; use whole border giving larger area for | 263 if (resizeType != RESIZE_TYPE.NONE) { // Some type of resize |
255 * diagonal resizes). */ | 264 // Set x/yDrag (unfortunately these need to be different for each edge) |
256 resizeType = RESIZE.NONE; | 265 if (resizeType & RESIZE_TYPE.L) |
266 xDrag = w + cx; | |
267 else if (resizeType & RESIZE_TYPE.R) | |
268 xDrag = w - cx; | |
257 | 269 |
258 if (isWSizable) { | 270 if (resizeType & RESIZE_TYPE.T) |
259 if (cx < x + border.l) { | 271 yDrag = h + cy; |
260 xDrag = w + cx; | 272 else if (resizeType & RESIZE_TYPE.B) |
261 resizeType = RESIZE.L; | 273 yDrag = h - cy; |
262 } | |
263 else if (cx >= xw - border.r) { | |
264 xDrag = w - cx; | |
265 resizeType = RESIZE.R; | |
266 } | |
267 } | |
268 if (isHSizable) { | |
269 if (cy < y + border.t) { | |
270 yDrag = h + cy; | |
271 resizeType |= RESIZE.T; | |
272 } | |
273 else if (cy >= yh - border.b) { | |
274 yDrag = h - cy; | |
275 resizeType |= RESIZE.B; | |
276 } | |
277 } | |
278 | 274 |
279 if (resizeType != RESIZE.NONE) { // only if some valid size is being done | 275 // Add the callbacks (they use resizeType which has already been set) |
280 gui_.addClickCallback (&endCallback); | 276 gui_.addClickCallback (&endCallback); |
281 gui_.addMotionCallback (&resizeCallback); | 277 gui_.addMotionCallback (&resizeCallback); |
282 } | 278 } else { // window is being moved |
283 } else { // window is being moved | |
284 xDrag = cx - x; | 279 xDrag = cx - x; |
285 yDrag = cy - y; | 280 yDrag = cy - y; |
286 | 281 |
287 gui_.addClickCallback (&endCallback); | 282 gui_.addClickCallback (&endCallback); |
288 gui_.addMotionCallback (&moveCallback); | 283 gui_.addMotionCallback (&moveCallback); |
298 widget.draw(); | 293 widget.draw(); |
299 } | 294 } |
300 //END IWidget methods | 295 //END IWidget methods |
301 | 296 |
302 private: | 297 private: |
303 alias IRenderer.BorderDimensions BorderDimensions; | 298 alias IRenderer.BorderDimensions BorderDimensions; |
304 alias IRenderer.BORDER_TYPES BORDER_TYPES; | 299 alias IRenderer.RESIZE_TYPE RESIZE_TYPE; |
305 | 300 |
306 //BEGIN Window moving and resizing | 301 //BEGIN Window moving and resizing |
307 void moveCallback (ushort cx, ushort cy) { | 302 void moveCallback (ushort cx, ushort cy) { |
308 setPosition (cx-xDrag, cy-yDrag); | 303 setPosition (cx-xDrag, cy-yDrag); |
309 } | 304 } |
310 void resizeCallback (ushort cx, ushort cy) { | 305 void resizeCallback (ushort cx, ushort cy) { |
311 if (resizeType & RESIZE.L) { | 306 if (resizeType & RESIZE_TYPE.L) { |
312 int mw, nw; | 307 int mw, nw; |
313 getMinimalSize (mw, nw); // (only want mw) | 308 getMinimalSize (mw, nw); // (only want mw) |
314 nw = xDrag - cx; | 309 nw = xDrag - cx; |
315 if (nw < mw) nw = mw; // clamp | 310 if (nw < mw) nw = mw; // clamp |
316 mw = x + w - nw; // reuse | 311 mw = x + w - nw; // reuse |
317 setSize (nw, h); | 312 setSize (nw, h); |
318 setPosition (mw, y); | 313 setPosition (mw, y); |
319 } | 314 } |
320 else if (resizeType & RESIZE.R) { | 315 else if (resizeType & RESIZE_TYPE.R) { |
321 setSize (xDrag + cx, h); | 316 setSize (xDrag + cx, h); |
322 setPosition (x, y); | 317 setPosition (x, y); // required to call after setSize. |
323 } | 318 } |
324 if (resizeType & RESIZE.T) { | 319 if (resizeType & RESIZE_TYPE.T) { |
325 int mh, nh; | 320 int mh, nh; |
326 getMinimalSize (nh, mh); | 321 getMinimalSize (nh, mh); |
327 nh = yDrag - cy; | 322 nh = yDrag - cy; |
328 if (nh < mh) nh = mh; | 323 if (nh < mh) nh = mh; |
329 mh = y + h - nh; | 324 mh = y + h - nh; |
330 setSize (w, nh); | 325 setSize (w, nh); |
331 setPosition (x, mh); | 326 setPosition (x, mh); |
332 } | 327 } |
333 else if (resizeType & RESIZE.B) { | 328 else if (resizeType & RESIZE_TYPE.B) { |
334 setSize (w, yDrag + cy); | 329 setSize (w, yDrag + cy); |
335 setPosition (x, y); | 330 setPosition (x, y); |
336 } | 331 } |
337 } | 332 } |
338 void endCallback (ushort cx, ushort cy, ubyte b, bool state) { | 333 bool endCallback (ushort cx, ushort cy, ubyte b, bool state) { |
339 if (b == 1 && state == false) { | 334 if (b == 1 && state == false) { |
340 // The mouse shouldn't have moved since the motion callback | 335 // The mouse shouldn't have moved since the motion callback |
341 // was last called, so there's nothing else to do now. | 336 // was last called, so there's nothing else to do now. |
342 gui_.removeCallbacks (cast(void*) this); | 337 gui_.removeCallbacks (cast(void*) this); |
343 } | 338 |
339 return true; // we've handled the up-click | |
340 } | |
341 return false; // we haven't handled it | |
344 } | 342 } |
345 int xDrag, yDrag; // where a drag starts relative to x and y | 343 int xDrag, yDrag; // where a drag starts relative to x and y |
346 enum RESIZE : ubyte { | 344 IRenderer.RESIZE_TYPE resizeType; // Type of current resize |
347 NONE = 0x0, L = 0x1, R = 0x2, T = 0x4, B = 0x8 | |
348 } | |
349 RESIZE resizeType; // Type of current resize | |
350 //END Window moving and resizing | 345 //END Window moving and resizing |
351 | 346 |
352 // Load/save data: | 347 // Load/save data: |
353 public char[] name; // The window's name (id from config file) | 348 public char[] name; // The window's name (id from config file) |
354 //bool edited = false; // True if any widgets have been edited (excluding scaling) | 349 //bool edited = false; // True if any widgets have been edited (excluding scaling) |
350 | |
355 // Data used for saving and loading (null in between): | 351 // Data used for saving and loading (null in between): |
356 int[][widgetID] widgetData = null;// Data for all widgets under this window | 352 int[][widgetID] widgetData = null;// Data for all widgets under this window |
357 int[] mutableData = null; // Widget's mutable data (adjusted sizes, etc.) | 353 int[] mutableData = null; // Widget's mutable data (adjusted sizes, etc.) |
358 | 354 |
359 IGui gui_; // The gui managing this window | 355 IGui gui_; // The gui managing this window |
363 | 359 |
364 int x = -1, y = -1; // Window position | 360 int x = -1, y = -1; // Window position |
365 int w,h; // Window size (calculated from Widgets) | 361 int w,h; // Window size (calculated from Widgets) |
366 int xw, yh; // x+w, y+h (frequent use by clickEvent) | 362 int xw, yh; // x+w, y+h (frequent use by clickEvent) |
367 int widgetX, widgetY; // Widget position (= window position plus BORDER_WIDTH) | 363 int widgetX, widgetY; // Widget position (= window position plus BORDER_WIDTH) |
368 int mw = -1, mh = -1; // minimal size | 364 int mw = -1, mh = -1; // minimal size (negative means requires calculation) |
369 | 365 |
370 BorderDimensions border; // Total border size (move plus resize) | 366 BorderDimensions border; // Total border size (move plus resize) |
371 BorderDimensions resize; // The outer resize part of the border | |
372 } | 367 } |