Mercurial > projects > mde
diff mde/gui/widget/Window.d @ 38:8c4c96f04e7f
Windows can now be resized!
Windows have both a resize border and a move border with independant size for each side.
Windows resizing support.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Mon, 05 May 2008 17:02:21 +0100 |
parents | 052df9b2fe07 |
children | 5132301e9ed7 |
line wrap: on
line diff
--- a/mde/gui/widget/Window.d Mon May 05 14:47:25 2008 +0100 +++ b/mde/gui/widget/Window.d Mon May 05 17:02:21 2008 +0100 @@ -68,13 +68,17 @@ widget = makeWidget (0, this); // primary widget always has ID 0. widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) + // Get border sizes + border = rend.getBorder (BORDER_TYPES.WINDOW_TOTAL); + resize = rend.getBorder (BORDER_TYPES.WINDOW_RESIZE); + widget.setSize (0,0); // set the minimal size widget.getCurrentSize (w,h); // and get this size - w += rend.windowBorder * 2; // Adjust for border - h += rend.windowBorder * 2; + w += border.l + border.r; // Adjust for border + h += border.t + border.b; - widgetX = x + rend.windowBorder; // widget position - widgetY = y + rend.windowBorder; // must be updated if the window is moved + widgetX = x + border.l; // widget position + widgetY = y + border.t; // must be updated if the window is moved widget.setPosition (widgetX, widgetY); xw = x+w; @@ -125,9 +129,6 @@ return gui_; } - /+void requestRedraw () { - }+/ - IRenderer renderer () { return rend; } @@ -141,9 +142,14 @@ return widget.isHSizable; } - void getMinimalSize (out int mw, out int mh) { - mw = w + rend.windowBorder * 2; - mh = h + rend.windowBorder * 2; + void getMinimalSize (out int wM, out int hM) { + if (mh < 0) { // calculate if necessary + widget.getMinimalSize (mw, mh); + mw += border.l + border.r; + mh += border.t + border.b; + } + wM = mw; + hM = mh; } void getCurrentSize (out int cw, out int ch) { cw = w; @@ -151,13 +157,16 @@ } void setSize (int nw, int nh) { - w = nw; - h = nh; + getMinimalSize (w,h); + if (nw > w) w = nw; // expand if new size is larger, but don't go smaller + if (nh > h) h = nh; xw = x+w; yh = y+h; - widget.setSize (w - rend.windowBorder * 2, h - rend.windowBorder * 2); + widget.setSize (w - border.l - border.r, h - border.t - border.b); + + gui_.requestRedraw (); // obviously necessary whenever the window's size is changed } void setPosition (int nx, int ny) { @@ -167,8 +176,8 @@ xw = x+w; yh = y+h; - widgetX = x + rend.windowBorder; - widgetY = y + rend.windowBorder; + widgetX = x + border.l; + widgetY = y + border.t; widget.setPosition (widgetX, widgetY); @@ -178,7 +187,7 @@ IWidget getWidget (int cx, int cy) { if (cx < x || cx >= xw || cy < y || cy >= yh) // not over window return null; - if (cx >= widgetX && cx < xw-rend.windowBorder && cy >= widgetY && cy < yh-rend.windowBorder) + if (cx >= widgetX && cx < xw-border.r && cy >= widgetY && cy < yh-border.b) // over the widget return widget.getWidget (cx, cy); else // over the window border @@ -186,11 +195,37 @@ } void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { if (b == 1 && state == true) { - xDrag = cx; - yDrag = cy; - - gui_.addClickCallback (&dragEndCallback); // handle repositioning - gui_.addMotionCallback (&dragCallback); // handle repositioning + if (cx < x + resize.l || cx >= xw - resize.r || + cy < y + resize.t || cy >= yh - resize.b) { // window is being resized + /* check for resizes (different to above; use whole border giving larger area for + * diagonal resizes). */ + resizeType = RESIZE.NONE; + if (cx < x + border.l) { + xDrag = w + cx; + resizeType = RESIZE.L; + } + else if (cx >= xw - border.r) { + xDrag = w - cx; + resizeType = RESIZE.R; + } + if (cy < y + border.t) { + yDrag = h + cy; + resizeType |= RESIZE.T; + } + else if (cy >= yh - border.b) { + yDrag = h - cy; + resizeType |= RESIZE.B; + } + + gui_.addClickCallback (&endCallback); + gui_.addMotionCallback (&resizeCallback); + } else { // window is being moved + xDrag = cx - x; + yDrag = cy - y; + + gui_.addClickCallback (&endCallback); + gui_.addMotionCallback (&moveCallback); + } } } @@ -204,19 +239,50 @@ //END IWidget methods private: - /* For window dragging. */ - void dragCallback (ushort cx, ushort cy) { - setPosition (x+cx-xDrag, y+cy-yDrag); - xDrag = cx; - yDrag = cy; + alias IRenderer.BorderDimensions BorderDimensions; + alias IRenderer.BORDER_TYPES BORDER_TYPES; + + //BEGIN Window moving and resizing + void moveCallback (ushort cx, ushort cy) { + setPosition (cx-xDrag, cy-yDrag); } - void dragEndCallback (ushort cx, ushort cy, ubyte b, bool state) { + void resizeCallback (ushort cx, ushort cy) { + if (resizeType & RESIZE.L) { + int mw, nw; + getMinimalSize (mw, nw); // (only want mw) + nw = xDrag - cx; + if (nw < mw) nw = mw; // clamp + setPosition (x + w - nw, y); + setSize (nw, h); + } + else if (resizeType & RESIZE.R) { + setSize (xDrag + cx, h); + } + if (resizeType & RESIZE.T) { + int mh, nh; + getMinimalSize (nh, mh); // (only want mh) + nh = yDrag - cy; + if (nh < mh) nh = mh; // clamp + setPosition (x, y + h - nh); + setSize (w, nh); + } + else if (resizeType & RESIZE.B) { + setSize (w, yDrag + cy); + } + } + void endCallback (ushort cx, ushort cy, ubyte b, bool state) { if (b == 1 && state == false) { - setPosition (x+cx-xDrag, y+cy-yDrag); + // The mouse shouldn't have moved since the motion callback + // was last called, so there's nothing else to do now. gui_.removeCallbacks (cast(void*) this); } } - int xDrag, yDrag; // locations where a drag starts (used by dragCallback). + int xDrag, yDrag; // where a drag starts relative to x and y + enum RESIZE : ubyte { + NONE = 0x0, L = 0x1, R = 0x2, T = 0x4, B = 0x8 + } + RESIZE resizeType; // Type of current resize + //END Window moving and resizing char[] name; // The window's name (id from config file) IGui gui_; // The gui managing this window @@ -231,4 +297,8 @@ int w,h; // Window size (calculated from Widgets) int xw, yh; // x+w, y+h (frequent use by clickEvent) int widgetX, widgetY; // Widget position (= window position plus BORDER_WIDTH) + int mw = -1, mh = -1; // minimal size + + BorderDimensions border; // Total border size (move plus resize) + BorderDimensions resize; // The outer resize part of the border }