# HG changeset patch # User Diggory Hardy # Date 1234222061 0 # Node ID 2ac3e001278863e90ba47a330f169d804206e237 # Parent 9dabcc44f515110476363b17c331fa2d19cb0d8f Added a simple Slider widget. Moved SwitchWidget into PopupMenuWidget's module and renamed the module ParentContent. Made editContent create DisplayContentWidgets for DebugContent (instead of ButtonContentWidgets). diff -r 9dabcc44f515 -r 2ac3e0012788 codeDoc/jobs.txt --- a/codeDoc/jobs.txt Sun Feb 08 17:36:57 2009 +0000 +++ b/codeDoc/jobs.txt Mon Feb 09 23:27:41 2009 +0000 @@ -8,7 +8,8 @@ To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): Also search for FIXME/NOTE/BUG/WARNING comment marks. -4 Revise widgets/functions available +4 Revise widgets/functions available: remove TextLabel, add VoidContent creation +3 Too many redraws: mouse-over causes them 3 Glyph 's' drawn incorrectly in release mode - ?? 3 Widget saving: how to deal with modifier functions, esp. when they discard parameters? Remove feature except for dimdata and handle gui editing separately? 3 glBindTexture not working with non-0 index - perhaps use a higher level graphics library at some point. diff -r 9dabcc44f515 -r 2ac3e0012788 data/conf/guiDemo.mtt --- a/data/conf/guiDemo.mtt Sun Feb 08 17:36:57 2009 +0000 +++ b/data/conf/guiDemo.mtt Mon Feb 09 23:27:41 2009 +0000 @@ -3,7 +3,7 @@ {Working} - + @@ -33,5 +33,8 @@ + {Basic} diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/WidgetManager.d --- a/mde/gui/WidgetManager.d Sun Feb 08 17:36:57 2009 +0000 +++ b/mde/gui/WidgetManager.d Mon Feb 09 23:27:41 2009 +0000 @@ -44,7 +44,7 @@ import mde.gui.widget.contentFunctions; import mde.gui.widget.miscContent; import mde.gui.widget.Floating; -import mde.gui.widget.PopupMenu; +import mde.gui.widget.ParentContent; import tango.core.sync.Mutex; import tango.util.log.Log : Log, Logger; @@ -502,6 +502,7 @@ BoolContent = TAKES_CONTENT | 0x41, AStringContent = TAKES_CONTENT | 0x42, ButtonContent = TAKES_CONTENT | 0x43, + SliderContent = TAKES_CONTENT | 0x44, GridLayout = TAKES_CONTENT | 0x100, ContentList = TAKES_CONTENT | 0x110, @@ -522,6 +523,7 @@ "BoolContent", "AStringContent", "ButtonContent", + "SliderContent", "GridLayout", "ContentList", "FloatingArea", diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/renderer/IRenderer.d --- a/mde/gui/renderer/IRenderer.d Sun Feb 08 17:36:57 2009 +0000 +++ b/mde/gui/renderer/IRenderer.d Mon Feb 09 23:27:41 2009 +0000 @@ -21,11 +21,18 @@ /** Interface for renderers. * -* Renderers provide unified drawing methods for widget, e.g. to draw a window background, a frame, -* or a button. The renderer will effectively be synonymous with the theme, except that a scripted -* renderer may also be available. -* -* The renderer is intended to be per-GUI. */ +* Renderers provide unified drawing methods for widget, e.g. to draw a window +* background, a frame, or a button. +* +* A theme could be hard-coded into a renderer, or use a texture set and/or +* scripting with a more flexible renderer. There's currently no support for +* per-widget theming, although it shouldn't be too hard (e.g. if widgets get a +* renderer from their parent instead of the manager). +* +* The renderer interface could be improved by using more objects and interfaces +* (e.g. with a generic drawable interface for getting dimensions and drawing), +* but requiring more class objects seems excessive and structs don't support +* interfaces in D1. */ interface IRenderer { //BEGIN Types @@ -182,6 +189,12 @@ wdimPair getToggleSize (); void drawToggle (wdim x, wdim y, bool state, bool pushed); /// ditto + /** Slider / progress bar. + * + * Width is resizable. */ + wdimPair getSliderSize (); + void drawSlider (wdim x, wdim y, wdim w, double proportion); + /** Get a TextAdapter to draw some text. * * If no colour is passes, a default is used (white). */ diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/renderer/SimpleRenderer.d --- a/mde/gui/renderer/SimpleRenderer.d Sun Feb 08 17:36:57 2009 +0000 +++ b/mde/gui/renderer/SimpleRenderer.d Mon Feb 09 23:27:41 2009 +0000 @@ -145,7 +145,18 @@ glColor3f (0f, c, 0f); else glColor3f (c, 0f, 0f); - glRecti (x+2,y+14, x+14,y+2); + glRecti (x,y+16, x+16,y); + } + + override wdimPair getSliderSize () { + wdimPair r; + r.x = 20; + r.y = 16; + return r; + } + override void drawSlider (wdim x, wdim y, wdim w, double proportion) { + glColor3f (0f, 0f, .5f); + glRecti (x,y+16, x+cast(wdim) (proportion*w),y); } override TextAdapter getAdapter (int col) { diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/widget/ParentContent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mde/gui/widget/ParentContent.d Mon Feb 09 23:27:41 2009 +0000 @@ -0,0 +1,229 @@ +/* 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 . */ + +/****************************************************************************** + * A pop-up widget and a switch (tab) widget (both parent widgets using + * content). + *****************************************************************************/ +module mde.gui.widget.ParentContent; + +import mde.gui.widget.AParentWidget; +import mde.gui.widget.layout; +import mde.content.AStringContent; +import mde.gui.exception; + +debug { + import tango.util.log.Log : Log, Logger; + private Logger logger; + static this () { + logger = Log.getLogger ("mde.gui.widget.ParentContent"); + } +} + +/****************************************************************************** + * Widget which pops up a ContentListWidget created with its content. + * + * Is a button displaying a content string, just like DisplayContentWidget. + * + * Popped up widget is a ContentListWidget created from the same creation data. + *****************************************************************************/ +class PopupMenuWidget : APopupParentWidget +{ + this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) { + content = cast(Content)c; + WDCMinCheck (data, 3,1, content); + super (mgr, parent, id); + + //popup = mgr.makeWidget (this, data.strings[0], content); + popup = new ContentListWidget (mgr, this, id, data, c); + subWidgets = [popup]; + + cIndex = data.ints[2]; + if (cIndex == 0) + content.addCallback (&updateVal); + adapter = mgr.renderer.getAdapter; + adapter.text = content.toString (cIndex); + adapter.getDimensions (mw, mh); + w = mw; + h = mh; + } + + override void recursionCheck (widgetID wID, IContent c) { + if (wID is id && c is content) + throw new WidgetRecursionException (wID); + parent.recursionCheck (wID, c); + } + + override int clickEvent (wdabs, wdabs, ubyte b, bool state) { + if (b == 1 && state == true) { + if (!pushed) { + parentIPPW.addChildIPPW (this); + parentIPPW.menuActive = true; + if (popup.width != w && popup.minWidth <= w) + popup.setWidth (w, -1); // neatness + mgr.positionPopup (this, popup); + pushed = true; + } else if (!parentIPPW.parentMenuActive) { // if not a submenu + parentIPPW.removeChildIPPW (this); + } + } + return 0; + } + + override void removedIPPW () { + super.removedIPPW; + pushed = false; + } + + override void underMouse (bool state) { + if (state && !pushed && parentIPPW.menuActive) { + parentIPPW.addChildIPPW (this); + menuActive = true; + if (parentIPPW.parentMenuActive) + mgr.positionPopup (this, popup, 1); + else { + if (popup.width != w && popup.minWidth <= w) + popup.setWidth (w, -1); // neatness + mgr.positionPopup (this, popup); + } + pushed = true; + } + } + + override void draw () { + mgr.renderer.drawButton (x,y, w,h, pushed); + adapter.draw (x,y); + } + +protected: + void updateVal (Content) { // callback + adapter.text = content.toString(cIndex); + wdim omw = mw, omh = mh; + adapter.getDimensions (mw, mh); + if (omw != mw) + parent.minWChange (this, mw); + if (omh != mh) + parent.minHChange (this, mh); + } + bool pushed = false; + IRenderer.TextAdapter adapter; + Content content; + int cIndex; +} + +/** A "tab" widget: it doesn't display the tabs, but shows one of a number of + * widgets dependant on an EnumContent. + * + * Sizability is set once. Min-size is updated when switching. */ +class SwitchWidget : AParentWidget +{ + this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) { + super (mgr, parent, id); + content = cast(EnumContent) c; + if (content is null || (subWidgets.length = content.list.length) == 0) + throw new ContentException (this); + WDCheck (data, 1, subWidgets.length); + + foreach (i,sc; content.list) + subWidgets[i] = mgr.makeWidget (this, data.strings[i], sc); + currentW = subWidgets[content()]; + + content.addCallback (&switchWidget); + } + + override bool setup (uint n, uint flags) { + bool r = super.setup (n, flags); + if (r) { + mw = currentW.minWidth; + mh = currentW.minHeight; + w = currentW.width; + h = currentW.height; + static if (SIZABILITY & SIZABILITY_ENUM.START_TRUE) + isWS = isHS = true; + foreach (i,sc; content.list) { + static if (SIZABILITY == SIZABILITY_ENUM.ANY_SUBWIDGETS) { + isWS |= subWidgets[i].isWSizable; + isHS |= subWidgets[i].isHSizable; + } else static if (SIZABILITY == SIZABILITY_ENUM.ALL_SUBWIDGETS) { + isWS &= subWidgets[i].isWSizable; + isHS &= subWidgets[i].isHSizable; + } + } + } + return r; + } + + override void minWChange (IChildWidget widget, wdim nmw) { + if (widget !is currentW) return; + mw = nmw; + parent.minWChange (this, nmw); + } + override void minHChange (IChildWidget widget, wdim nmh) { + if (widget !is currentW) return; + mh = nmh; + parent.minHChange (this, nmh); + } + + override bool isWSizable () { + return isWS; + } + override bool isHSizable () { + return isHS; + } + + override void setWidth (wdim nw, int dir) { + w = (nw >= mw ? nw : mw); + currentW.setWidth (w, dir); + } + override void setHeight (wdim nh, int dir) { + h = (nh >= mh ? nh : mh); + currentW.setHeight (h, dir); + } + + override void setPosition (wdim nx, wdim ny) { + x = nx; + y = ny; + currentW.setPosition (nx,ny); + } + + override IChildWidget getWidget (wdim cx, wdim cy) { + return currentW.getWidget (cx, cy); + } + + override void draw () { + currentW.draw; + } + +protected: + // callback on content + void switchWidget (Content) { + currentW = subWidgets[content()]; + mw = currentW.minWidth; + mh = currentW.minHeight; + parent.minWChange (this, mw); + parent.minHChange (this, mh); + // Parent may change size. If it doesn't, we must set child's size. + // We can't tell if it did, so do it (call will be fast if size isn't + // changed anyway). + currentW.setWidth (w, -1); + currentW.setHeight (h, -1); + currentW.setPosition (x,y); + } + + IChildWidget currentW; + EnumContent content; + + bool isWS, isHS; // no infrastructure for changing sizability, so need to fix it. +} diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/widget/PopupMenu.d --- a/mde/gui/widget/PopupMenu.d Sun Feb 08 17:36:57 2009 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* 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 . */ - -/****************************************************************************** - * Pop-up menus based on content structures. - *****************************************************************************/ -module mde.gui.widget.PopupMenu; - -import mde.gui.widget.AParentWidget; - -import mde.gui.widget.layout; -import mde.content.Content; -import mde.gui.exception; - -debug { - import tango.util.log.Log : Log, Logger; - private Logger logger; - static this () { - logger = Log.getLogger ("mde.gui.widget.PopupMenu"); - } -} - -/****************************************************************************** - * Widget which pops up a menu based on a content. - * - * Is a button displaying a content string, just like DisplayContentWidget. - * - * Popped up widget is a ContentListWidget created from the same creation data. - *****************************************************************************/ -class PopupMenuWidget : APopupParentWidget -{ - this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) { - content = cast(Content)c; - WDCMinCheck (data, 3,1, content); - super (mgr, parent, id); - - //popup = mgr.makeWidget (this, data.strings[0], content); - popup = new ContentListWidget (mgr, this, id, data, c); - subWidgets = [popup]; - - cIndex = data.ints[2]; - if (cIndex == 0) - content.addCallback (&updateVal); - adapter = mgr.renderer.getAdapter; - adapter.text = content.toString (cIndex); - adapter.getDimensions (mw, mh); - w = mw; - h = mh; - } - - override void recursionCheck (widgetID wID, IContent c) { - if (wID is id && c is content) - throw new WidgetRecursionException (wID); - parent.recursionCheck (wID, c); - } - - override int clickEvent (wdabs, wdabs, ubyte b, bool state) { - if (b == 1 && state == true) { - if (!pushed) { - parentIPPW.addChildIPPW (this); - parentIPPW.menuActive = true; - if (popup.width != w && popup.minWidth <= w) - popup.setWidth (w, -1); // neatness - mgr.positionPopup (this, popup); - pushed = true; - } else if (!parentIPPW.parentMenuActive) { // if not a submenu - parentIPPW.removeChildIPPW (this); - } - } - return 0; - } - - override void removedIPPW () { - super.removedIPPW; - pushed = false; - } - - override void underMouse (bool state) { - if (state && !pushed && parentIPPW.menuActive) { - parentIPPW.addChildIPPW (this); - menuActive = true; - if (parentIPPW.parentMenuActive) - mgr.positionPopup (this, popup, 1); - else { - if (popup.width != w && popup.minWidth <= w) - popup.setWidth (w, -1); // neatness - mgr.positionPopup (this, popup); - } - pushed = true; - } - } - - override void draw () { - mgr.renderer.drawButton (x,y, w,h, pushed); - adapter.draw (x,y); - } - -protected: - void updateVal (Content) { // callback - adapter.text = content.toString(cIndex); - wdim omw = mw, omh = mh; - adapter.getDimensions (mw, mh); - if (omw != mw) - parent.minWChange (this, mw); - if (omh != mh) - parent.minHChange (this, mh); - } - bool pushed = false; - IRenderer.TextAdapter adapter; - Content content; - int cIndex; -} diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/widget/contentFunctions.d --- a/mde/gui/widget/contentFunctions.d Sun Feb 08 17:36:57 2009 +0000 +++ b/mde/gui/widget/contentFunctions.d Mon Feb 09 23:27:41 2009 +0000 @@ -22,10 +22,11 @@ import mde.gui.widget.Ifaces; import mde.gui.widget.TextWidget; import mde.gui.widget.layout; -import mde.gui.widget.PopupMenu; +import mde.gui.widget.ParentContent; import mde.gui.widget.miscContent; import mde.content.AStringContent; +import mde.content.miscContent; /****************************************************************************** * A function which uses Items.get (data.strings[0]) to get a content and @@ -57,7 +58,7 @@ if (cast(IContentList) c) return new ContentListWidget(mgr,parent,id,data,c); // Normally only EventContents are used for buttons, but any Content can be: - if (cast(Content) c) + if (cast(EventContent) c) return new ButtonContentWidget(mgr,parent,id,data,c); // generic uneditable option return new DisplayContentWidget(mgr,parent,id,data,c); diff -r 9dabcc44f515 -r 2ac3e0012788 mde/gui/widget/miscContent.d --- a/mde/gui/widget/miscContent.d Sun Feb 08 17:36:57 2009 +0000 +++ b/mde/gui/widget/miscContent.d Mon Feb 09 23:27:41 2009 +0000 @@ -14,14 +14,16 @@ along with this program. If not, see . */ /****************************************************************************** - * Widgets using content not organised into other modules. + * Some non-parent widgets for displaying or editing content. + * + * (There are other non-parent content widgets in TextWidget). *****************************************************************************/ module mde.gui.widget.miscContent; -import mde.gui.widget.AParentWidget; +import mde.gui.widget.AChildWidget; +import mde.content.AStringContent; import mde.gui.exception; -import mde.content.AStringContent; debug { import tango.util.log.Log : Log, Logger; @@ -91,108 +93,27 @@ int index; } -/** A "tab" widget: it doesn't display the tabs, but shows one of a number of widgets dependant on - * an EnumContent. - * - * Sizability is set once (currently true if any widget is sizable). Size is kept when switching - * widgets if allowed (if this is large enough and resizable). */ -class SwitchWidget : AParentWidget +/// Display a double in a progress bar/slider. Non-editable. +class SliderContentWidget : AChildWidget { - this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) { + this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) { + content = cast(DoubleContent) c; + if (content is null) throw new ContentException (this); super (mgr, parent, id); - content = cast(EnumContent) c; - if (content is null || (subWidgets.length = content.list.length) == 0) - throw new ContentException (this); - WDCheck (data, 1, subWidgets.length); - - foreach (i,sc; content.list) - subWidgets[i] = mgr.makeWidget (this, data.strings[i], sc); - currentW = subWidgets[content()]; - - content.addCallback (&switchWidget); - } - - override bool setup (uint n, uint flags) { - bool r = super.setup (n, flags); - if (r) { - mw = currentW.minWidth; - mh = currentW.minHeight; - w = currentW.width; - h = currentW.height; - static if (SIZABILITY & SIZABILITY_ENUM.START_TRUE) - isWS = isHS = true; - foreach (i,sc; content.list) { - static if (SIZABILITY == SIZABILITY_ENUM.ANY_SUBWIDGETS) { - isWS |= subWidgets[i].isWSizable; - isHS |= subWidgets[i].isHSizable; - } else static if (SIZABILITY == SIZABILITY_ENUM.ALL_SUBWIDGETS) { - isWS &= subWidgets[i].isWSizable; - isHS &= subWidgets[i].isHSizable; - } - } - } - return r; - } - - override void minWChange (IChildWidget widget, wdim nmw) { - if (widget !is currentW) return; - mw = nmw; - parent.minWChange (this, nmw); - } - override void minHChange (IChildWidget widget, wdim nmh) { - if (widget !is currentW) return; - mh = nmh; - parent.minHChange (this, nmh); + wdimPair s = mgr.renderer.getSliderSize; + w = mw = s.x; + h = mh = s.y; } override bool isWSizable () { - return isWS; - } - override bool isHSizable () { - return isHS; - } - - override void setWidth (wdim nw, int dir) { - w = (nw >= mw ? nw : mw); - currentW.setWidth (w, dir); - } - override void setHeight (wdim nh, int dir) { - h = (nh >= mh ? nh : mh); - currentW.setHeight (h, dir); - } - - override void setPosition (wdim nx, wdim ny) { - x = nx; - y = ny; - currentW.setPosition (nx,ny); - } - - override IChildWidget getWidget (wdim cx, wdim cy) { - return currentW.getWidget (cx, cy); + return true; } override void draw () { - currentW.draw; + mgr.renderer.drawSlider (x,y, w, content()); } protected: - // callback on content - void switchWidget (Content) { - currentW = subWidgets[content()]; - mw = currentW.minWidth; - mh = currentW.minHeight; - parent.minWChange (this, mw); - parent.minHChange (this, mh); - // Parent may change size. If it doesn't, we must set child's size. - // We can't tell if it did, so do it (call will be fast if size isn't - // changed anyway). - currentW.setWidth (w, -1); - currentW.setHeight (h, -1); - currentW.setPosition (x,y); - } - - IChildWidget currentW; - EnumContent content; - - bool isWS, isHS; // no infrastructure for changing sizability, so need to fix it. + DoubleContent content; } +