Mercurial > projects > mde
view mde/gui/widget/Widget.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 | 5132301e9ed7 |
children | 1530d9c04d4d |
line wrap: on
line source
/* LICENSE BLOCK Part of mde: a Modular D game-oriented Engine Copyright © 2007-2008 Diggory Hardy This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /// GUI Widget module. module mde.gui.widget.Widget; public import mde.gui.widget.Ifaces; import mde.gui.exception; import mde.gui.renderer.IRenderer; import tango.io.Stdout; /** An abstract base widget class. * * This abstract class, and the more concrete FixedWidget and ScalableWidget classes provides a * useful basic implementation for widgets. Widgets need not inherit these (they only need implement * IWidget); they are simply provided for convenience and to promote code reuse. */ abstract class Widget : IWidget { // Base this(); all widgets must at least check data.length is correct. this (IWindow wind, int[] data) { window = wind; widgetType = data[0]; } // Most widgets don't need to do adjustments based on mutable data, however they usually do // still need to set their size. int[] adjust (int[] data) { setSize (0,0); return data; } // Widget type should always be the first value. int[] getCreationData () { return [widgetType]; } // Most widgets don't use mutable data. int[] getMutableData () { return []; } void getCurrentSize (out int cw, out int ch) { cw = w; ch = h; } void setPosition (int nx, int ny) { x = nx; y = ny; } /* Return self, since we don't have child widgets and the method wouldn't have been called * unless the location was over us. Valid for all widgets without children. */ IWidget getWidget (int,int) { return this; } /* Dummy event method (widget doesn't respond to events) */ void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {} /* Basic draw method: draw the background (all widgets should do this) */ void draw () { window.renderer.drawWidgetBack (x,y, w,h); } protected: final int widgetType; // the type (stored for saving) IWindow window; // the enclosing window int x, y; // position int w, h; // size } /** A base for fixed-size widgets. */ class FixedWidget : Widget { this (IWindow wind, int[] data) { super (wind, data); w = wF = data[1]; h = hF = data[2]; } int[] getCreationData () { return [widgetType, wF, hF]; } bool isWSizable () { return false; } bool isHSizable () { return false; } /* Not resizable, so return current size. */ void getMinimalSize (out int mw, out int mh) { mw = wF; mh = hF; } /* Ignore: a fixed size widget. */ void setSize (int nw, int nh) { w = (nw >= wF ? nw : wF); h = (nh >= hF ? nh : hF); } protected: int wF, hF; // The "fixed" size, i.e. the preferred & minimal size } /** A base for resizable widgets. */ class SizableWidget : Widget { this (IWindow wind, int[] data) { super (wind, data); } bool isWSizable () { return true; } bool isHSizable () { return true; } /* Return zero. */ void getMinimalSize (out int mw, out int mh) {} /* Set size: a fully resizable widget. */ void setSize (int nw, int nh) { w = (nw >= 0 ? nw : 0); h = (nh >= 0 ? nh : 0); } } //BEGIN Widgets /// A fixed-size blank widget. class FixedBlankWidget : FixedWidget { this (IWindow wind, int[] data) { if (data.length != 3) throw new WidgetDataException; super (wind, data); } } /// A completely resizable blank widget (initial size zero). class SizableBlankWidget : SizableWidget { this (IWindow wind, int[] data) { if (data.length != 1) throw new WidgetDataException; super (wind, data); } } /// First interactible widget class ButtonWidget : FixedWidget { bool pushed = false; // true if button is pushed in (visually) // pushed is not the same as the button being clicked but not yet released. // it is whether the mouse is over the button after being clicked. this (IWindow wind, int[] data) { if (data.length != 3) throw new WidgetDataException; super (wind, data); } void draw () { window.renderer.drawButton (x,y, w,h, pushed); } void clickEvent (ushort, ushort, ubyte b, bool state) { if (b == 1 && state == true) { pushed = true; window.requestRedraw; window.gui.addClickCallback (&clickWhileHeld); window.gui.addMotionCallback (&motionWhileHeld); } } // Called when a mouse motion/click event occurs while (held == true) bool clickWhileHeld (ushort cx, ushort cy, ubyte b, bool state) { //NOTE: which button? test if (cx >= x && cx < x+w && cy >= y && cy < y+h) // button event Stdout ("Button clicked!").newline; pushed = false; window.requestRedraw; window.gui.removeCallbacks (cast(void*) this); return false; } void motionWhileHeld (ushort cx, ushort cy) { bool oldPushed = pushed; if (cx >= x && cx < x+w && cy >= y && cy < y+h) pushed = true; else pushed = false; if (oldPushed != pushed) window.requestRedraw; } } //END Widgets