Mercurial > projects > mde
view mde/gui/widget/Ifaces.d @ 112:fe061009029d
EnumContent; log level can be selected from a popup list.
New EnumContent, with code to load translations in Items. Editable as an AStringContent.
Hacked OptionsMisc to use an EnumContent.
Implemented a EnumContentWidget providing a pop-up list to select from (still needs improving).
Moved IContent to its own module.
ContentExceptions thrown via WDCCheck now.
Fixed a small bug with reloading translations.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sat, 13 Dec 2008 12:54:43 +0000 |
parents | 1655693702fc |
children | 9824bee909fd |
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/>. */ /************************************************************************************************* * Widget interfaces. * * Widgets are connected as the nodes of a tree. Widgets know their parent as a IParentWidget * class and their children as IChildWidget classes. The gui manager is a special widget only * implementing IParentWidget; all other widgets must implement IChildWidget and optionally * IParentWidget. *************************************************************************************************/ module mde.gui.widget.Ifaces; public import mde.gui.types; public import mde.gui.renderer.IRenderer; import mde.content.IContent; /************************************************************************************************* * Common interface for all widgets. * * Notation: * Positive/negative direction: along the x/y axis in this direction. * Layout widget: a widget containing multiple sub-widges (which hence controls how they are * laid out). *************************************************************************************************/ //NOTE: keep this? interface IWidget { } /************************************************************************************************* * Interface for the widget manager. * * This class handles widget rendering, input, loading and saving. *************************************************************************************************/ interface IWidgetManager : IWidget { // Loading/saving: /** Create a widget by ID. * * Params: * id = Identifier, within data files, of the data for the widget. * data = Pass this data to the widget, not data looked up via id. * content = An IContent may be passed to some widgets on creation. * * Creates a widget, using the widget data with index id. Widget data is loaded from files, * and per design (multiple gui layouts, called designs, may exist; data is per design). * * The function taking a WidgetData is intended for modifier functions and only exists to * avoid circular dependencies between the modifier function's module and createWidget. */ IChildWidget makeWidget (widgetID id, IContent content = null); IChildWidget makeWidget (widgetID id, WidgetData data, IContent content = null); /** Get dimension data for a widget. */ wdims dimData (widgetID id); /** Record some changes, for saving. Should only be called from IWidget.saveChanges() to avoid * multiple calls for instanced widgets of same id. * * WidgetData is for most data, dimensional data (wdims) is for dimensions. */ void setData (widgetID id, WidgetData); void setDimData (widgetID id, wdims d); /// ditto // Rendering: /** For when a widget needs redrawing. * * Must be called because rendering may only be done on events. * * Currently it just causes everything to be redrawn next frame. */ void requestRedraw (); /** Get the window's renderer. * * Normally specific to the GUI, but widgets have no direct contact with the GUI and this * provides the possibility of per-window renderers (if desired). */ IRenderer renderer (); /** Add/remove a pop-up [menu] to be drawn. */ void addPopup (wdabs x, wdabs y, IChildWidget popup); void removePopup (IChildWidget popup); /// ditto // User input: /** Add a mouse click callback. * * This is a delegate this will be called for all mouse click events recieved by the gui, not * simply all click events on the widget (as clickEvent recieves). * * The delegate should return true if it accepts the event and no further processing is * required (i.e. the event should not be handled by anything else), false otherwise. * * Note that this is not a mechanism to prevent unwanted event handling, and in the future * may be removed (so event handling cannot be cut short). */ void addClickCallback (bool delegate (wdabs cx, wdabs cy, ubyte b, bool state) dg); /** Add a mouse motion callback: delegate will be called for all motion events recieved by the * gui. */ void addMotionCallback (void delegate (wdabs cx, wdabs cy) dg); /** Remove all event callbacks on this widget (according to the delegate's .ptr). */ // Note: don't try to pass a reference and cast to void* in the function; it's a different address. void removeCallbacks (void* frame); } /************************************************************************************************* * Interface for (child) widgets, i.e. all widgets other than the manager. * * A widget is a region of a GUI window which handles rendering and user-interaction for itself * and is able to communicate with its manager and child widgets as necessary. (Passing widgets * a reference to their parent has not been found useful.) * * If a widget is to be creatable by IWidgetManager.makeWidget, it must be listed in the * createWidget module, and have a constructor of the following form. It should also update it's * creation data if necessary, either when changed or when saveChanges() is called, using * IWidgetManager.setData(). * It should use Ddoc to explain what initialization data is used. * ---------------------------------- * /++ Constructor for a ... widget. * + * + Widget uses the initialisation data: * + [widgetID, x, y] * + where x is ... and y is ... +/ * this (IWidgetManager mgr, widgetID id, WidgetData data); * * /// The CTOR may take an IContent reference: * this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content); * ---------------------------------- * Where mgr is the widget manager, id is the _id passed to makeWidget() and data is * initialisation data. The method should throw a WidgetDataException (created without * parameters) if the data has wrong length or is otherwise invalid. * * All widgets should set their own size in this() or setup() (must be setup() if it could change), * although some parents may set child-widgets' size during their creation. *************************************************************************************************/ //NOTE: add another this() without the data for default initialization, for the GUI editor? interface IChildWidget : IWidget { //BEGIN Load and save /** 2nd stage of initialization for widgets; also called on some changes. * * Widgets should call recursively on their children, redo anything indicated by flags, and * adjust their size and other cached data dependant on any thing which may have changed. * Widgets may rely on setPosition being called afterwards. * * Params: * n = Indicates this is the (n+1)-th time the function has been called. * flags = if (flags & 1) the renderer has been changed, * if (flags & 2) translation strings are being reloaded. * These flags are always true on first run. * * Returns: * The method should return true if the dimensions (may) have been changed. This may not be * the case on the first run (when n == 0)!. */ bool setup (uint n, uint flags); /** When this is called, if the widget has any changed data to save it should call * IWidgetManager.setData (id, data) to set it and return true. Otherwise it should return * false. * * If the widget has subwidgets, it should also be recursively called on these (passing their * ids). */ bool saveChanges (); /+ Use when widget editing is available? Requires widgets to know their parents. /** Called when a child widget's size has changed. * * Should be propegated up to parents. */ void childChanged (); +/ //END Load and save //BEGIN Size and position /** Is the width / height resizable? * * This really means does the widget benifit from being enlarged? Any widget should occupy * additional area when expanded. * * If not, the widget has fixed dimensions equal to it's minimal size. */ bool isWSizable (); bool isHSizable (); /// ditto /** The minimal size the widget could be shrunk to (or its fixed size). * * Takes into account child-widgets and any other contents. */ wdim minWidth (); wdim minHeight (); /// ditto /** Get the current size of the widget. */ wdim width (); wdim height(); /// ditto /** Used to adjust the size. * * Params: * nw/nh = The new width/height * dir = Direction to resize from. This is only really applicable to layout widgets. * It must be either -1 (start resizing from highest row/col index, decreasing the * index as necessary), or +1 (resize from the lowest index, i.e. 0). * Most widgets can simply ignore it. * * A widget should never be resized smaller than it's minimal size (if it is, it should assume * it's minimal size and print a warning when in debug mode). * A "fixed" size widget should enlarge itself as requested. * * setPosition must be called after calling either setWidth or setHeight. */ void setWidth (wdim nw, int dir); void setHeight (wdim nh, int dir); /// ditto /** Set the current position (called after setup and to move widget). */ void setPosition (wdim x, wdim y); //END Size and position //BEGIN Events /** Recursively scan the widget tree to find the widget under (x,y). * * If called on a widget, that widget should assume the location is over itself, and so should * either return itself or the result of calling getWidget on the appropriate child widget. * * In the case of Window this may not be the case; it should check and return null if not under * (x,y). * * Note: use global coordinates (x,y) not coordinates relative to the widget. */ IChildWidget getWidget (wdim x, wdim y); /** Receive a mouse click event at cx,cy from button b (1-5 correspond to L,M,B, wheel up,down) * which is a down-click if state is true. * * Widget may assume coordinates are on the widget (caller must check). * * The return value has the following flags: 1 to request keyboard input. */ int clickEvent (wdabs cx, wdabs cy, ubyte b, bool state); /** Receives keyboard events when requested. * * Params: * sym SDLKey key sym, useful for keys with no character code such as arrow keys * letter The character input, in UTF-8 */ void keyEvent (ushort sym, char[] letter); /** Called when keyboard input focus is lost. */ void keyFocusLost (); //END Events /** Draw, using the stored values of x and y. * * Maybe later enforce clipping of all sub-widget drawing, particularly for cases where only * part of the widget is visible: scroll bars or a hidden window. */ void draw (); }