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 }