# HG changeset patch # User Diggory Hardy # Date 1229861030 0 # Node ID 5ee69b3ed9c9f1f39a48581212b4a9946d04c266 # Parent 1b1e2297e2fc8d8ce11dea65391be2196c4ec4fd Partial implementation of infinite widget recursion protection; some cleanup. Implemented recursion protection which only allowed unsafe widgets to be instantiated once; realised this was far too restrictive (multiple sibling instances are needed) and a check against parent widgets would be needed. Could be implemented by passing widgets a reference to parents. Removed ButtonWidget aka First interactible widget. diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 codeDoc/debugCodes.txt --- a/codeDoc/debugCodes.txt Sat Dec 20 17:57:05 2008 +0000 +++ b/codeDoc/debugCodes.txt Sun Dec 21 12:03:50 2008 +0000 @@ -13,3 +13,4 @@ mdeUnitTest Compile in unittest code (including extra imports, and a few other bits outside the unittest itself). drawGlyphCache Draw the font texture in the upper-left corner of the screen, with a pretty background. mdeWidgets Log trace messages for the creation of all widgets. +SDLCalls Log a message before some SDL calls. diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 data/conf/gui.mtt --- a/data/conf/gui.mtt Sat Dec 20 17:57:05 2008 +0000 +++ b/data/conf/gui.mtt Sun Dec 21 12:03:50 2008 +0000 @@ -2,20 +2,24 @@ {Working} - - - + + + - - - - - - + + + + + + - - + + + + + + + diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/gui/WidgetManager.d --- a/mde/gui/WidgetManager.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/gui/WidgetManager.d Sun Dec 21 12:03:50 2008 +0000 @@ -523,10 +523,6 @@ debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); return createWidget (this, id, curData[id], content); } - override IChildWidget makeWidget (widgetID id, WidgetData data, IContent content = null) { - debug (mdeWidgets) logger.trace ("Creating widget \""~id~'"'); - return createWidget (this, id, data, content); - } override wdims dimData (widgetID id) { return curData.dims (id); diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/gui/widget/Ifaces.d --- a/mde/gui/widget/Ifaces.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/gui/widget/Ifaces.d Sun Dec 21 12:03:50 2008 +0000 @@ -58,12 +58,8 @@ * 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. */ + * and per design (multiple gui layouts, called designs, may exist; data is per design). */ 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); diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/gui/widget/createWidget.d --- a/mde/gui/widget/createWidget.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/gui/widget/createWidget.d Sun Dec 21 12:03:50 2008 +0000 @@ -20,8 +20,9 @@ module mde.gui.widget.createWidget; import mde.gui.widget.Ifaces; -import mde.gui.exception : WidgetDataException; +import mde.gui.exception; import mde.content.Content; +import Items = mde.content.Items; // Widgets to create: import mde.gui.widget.layout; @@ -31,6 +32,7 @@ import mde.gui.widget.textContent; import mde.gui.widget.Floating; import mde.gui.widget.PopupMenu; + import tango.util.log.Log : Log, Logger; private Logger logger; @@ -71,22 +73,29 @@ return new DebugWidget (mgr, id, data); } -/+ for converting to a char[] name (unused) -static this() { - WIDGET_NAMES = [ - FixedBlank : "FixedBlank", - SizableBlank : "SizableBlank", - Button : "Button", - GridLayout : "GridLayout" - ]; -}+/ +/************************************************************************************************* + * A function which uses Items.get (data.strings[0]) to get a content and creates a widget from + * data.ints[1]. The first item in each ints and strings is removed before passing data to the new + * widget. + * + * The function only takes an IContent parameter to satisfy createWidget; it's value is ignored. + * + * Circularly depends on createWidget, so should be in this module. + *************************************************************************************************/ +IChildWidget addContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent) { + if (data.ints.length < 2 || data.strings.length < 1) throw new WidgetDataException; + char[] cItem = data.strings[0]; + data.strings = data.strings[1..$]; + data.ints = data.ints [1..$]; + return createWidget (mgr, id, data, Items.get (cItem)); +} private: /// Widget types. enum WIDGET_TYPE : int { FUNCTION = 0x2000, // Function called instead of widget created (no "Widget" appended to fct name) TAKES_CONTENT = 0x4000, // Flag indicates widget's this should be passed an IContent reference. - PARENT = 0x8000, // widget can have children; not used by code (except in data files) + SAFE_RECURSION = 0x8000, // Safe to instantiate recursively without infinite looping. // Use widget names rather than usual capitals convention Unnamed = 0x0, // Only for use by widgets not created with createWidget @@ -97,15 +106,14 @@ Debug = 0xF, // buttons: 0x10 - Button = 0x10, - PopupMenu = TAKES_CONTENT | PARENT | 0x11, + PopupMenu = TAKES_CONTENT | 0x11, // labels: 0x20 ContentLabel = TAKES_CONTENT | 0x20, TextLabel = 0x21, // content functions: 0x30 - editContent = FUNCTION | TAKES_CONTENT | 0x30, + editContent = FUNCTION | TAKES_CONTENT | SAFE_RECURSION | 0x30, addContent = FUNCTION | 0x31, // content widgets: 0x40 @@ -113,12 +121,11 @@ BoolContent = TAKES_CONTENT | 0x41, AStringContent = TAKES_CONTENT | 0x42, ButtonContent = TAKES_CONTENT | 0x43, - //EnumContent = TAKES_CONTENT | 0x44, - GridLayout = TAKES_CONTENT | PARENT | 0x100, - ContentList = TAKES_CONTENT | PARENT | 0x110, + GridLayout = TAKES_CONTENT | 0x100, + ContentList = TAKES_CONTENT | SAFE_RECURSION | 0x110, - FloatingArea = PARENT | 0x200, + FloatingArea = 0x200, } //const char[][int] WIDGET_NAMES; @@ -128,20 +135,18 @@ "FixedBlank", "SizableBlank", "Debug", - "Button", "TextLabel", + "FloatingArea", "addContent", + "PopupMenu", "ContentLabel", "DisplayContent", "BoolContent", "AStringContent", "ButtonContent", - //"EnumContent", - "editContent", - "FloatingArea", - "PopupMenu", - "GridLayout", - "ContentList"]; + "GridLayout", + "ContentList", + "editContent"]; /* Generates a binary search algorithm. */ char[] binarySearch (char[] var, char[][] consts) { @@ -154,15 +159,20 @@ } else { char[] ret; foreach (c; consts) { - ret ~= "if (" ~ var ~ " == WIDGET_TYPE." ~ c ~ ") {\n" ~ - " debug (mdeWidgets) logger.trace (\"Creating new "~c~"Widget.\");\n" ~ - " static if (WIDGET_TYPE."~c~" & WIDGET_TYPE.FUNCTION)\n" ~ - " return " ~ c ~ " (mgr, id, data, content);\n" ~ - " else static if (WIDGET_TYPE."~c~" & WIDGET_TYPE.TAKES_CONTENT)\n" ~ - " return new " ~ c ~ "Widget (mgr, id, data, content);\n" ~ - " else\n" ~ - " return new " ~ c ~ "Widget (mgr, id, data);\n" ~ - "} else "; + ret ~= "if (" ~ var ~ " == WIDGET_TYPE." ~ c ~ ") {\n"~ + /+if ((WIDGET_TYPE."~c~" & WIDGET_TYPE.SAFE_RECURSION) || + "not being recursed (no parent with same id)") {\n + For recursion detection; would probably work with above check and some modification to widgets. +/ + "debug (mdeWidgets) logger.trace (\"Creating new "~c~"Widget.\");\n + static if (WIDGET_TYPE."~c~" & WIDGET_TYPE.FUNCTION)\n + return " ~ c ~ " (mgr, id, data, content);\n + else static if (WIDGET_TYPE."~c~" & WIDGET_TYPE.TAKES_CONTENT)\n + return new " ~ c ~ "Widget (mgr, id, data, content);\n + else\n + return new " ~ c ~ "Widget (mgr, id, data);\n"~ + /+} else + throw new GuiException (\"Widget not safe to be recursed: "~c~"\");+/ + "} else "; } ret = ret[0..$-6] ~ '\n'; // remove last else return ret; diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/gui/widget/miscContent.d --- a/mde/gui/widget/miscContent.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/gui/widget/miscContent.d Sun Dec 21 12:03:50 2008 +0000 @@ -27,7 +27,6 @@ import mde.gui.renderer.IRenderer; import mde.content.AStringContent; import mde.content.miscContent; -import Items = mde.content.Items; debug { import tango.util.log.Log : Log, Logger; @@ -38,27 +37,13 @@ } /************************************************************************************************* - * A function which uses Items.get (data.strings[0]) to get a content and creates a widget from - * data.ints[1]. The first item in each ints and strings is removed before passing data to the new - * widget. - * - * The function only takes an IContent parameter to satisfy createWidget; it's value is ignored. - *************************************************************************************************/ -IChildWidget addContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent) { - if (data.ints.length < 2 || data.strings.length < 1) throw new WidgetDataException; - char[] cItem = data.strings[0]; - data.strings = data.strings[1..$]; - data.ints = data.ints [1..$]; - return mgr.makeWidget (id, data, Items.get (cItem)); -} - -/************************************************************************************************* * A function which returns the most appropriate content editing widget. * * Widgets which can be returned: BoolContentWidget (toggle button), ValueContentWidget (generic * text-box editor), DisplayContentWidget (generic text label). *************************************************************************************************/ IChildWidget editContent (IWidgetManager mgr, widgetID id, WidgetData data, IContent c) { + // Note: SAFE_RECURSION enabled if (c is null) throw new ContentException; else if (cast(AStringContent) c) { if (cast(EnumContent) c) // can be PopupMenuWidget or ContentListWidget diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/gui/widget/miscWidgets.d --- a/mde/gui/widget/miscWidgets.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/gui/widget/miscWidgets.d Sun Dec 21 12:03:50 2008 +0000 @@ -20,7 +20,12 @@ import mde.gui.exception; import mde.gui.renderer.IRenderer; -import tango.io.Stdout; +import tango.util.log.Log : Log, Logger; + +private Logger logger; +static this () { + logger = Log.getLogger ("mde.gui.widget.miscWidgets"); +} /// A fixed-size blank widget. @@ -58,14 +63,7 @@ { this (IWidgetManager mgr, widgetID id, WidgetData data) { super (mgr, id, data); - - Stdout ("Debug widget - parameters: int: ["); - foreach (x; data.ints) - Stdout (" ")(x); - Stdout (" ], char[]: ["); - foreach (x; data.strings) - Stdout (" \"")(x)('"'); - Stdout (" ]").newline; + logger.warn ("Debug widget - parameters: ints = {}, strings = {}", data.ints, data.strings); } override void draw () { @@ -74,18 +72,3 @@ mgr.renderer.drawBlank (x,y, w,h); } } - -/// First interactible widget -class ButtonWidget : AButtonWidget -{ - this (IWidgetManager mgr, widgetID id, WidgetData data) { - WDCheck (data, 3); - w = mw = cast(wdim) data.ints[1]; - h = mh = cast(wdim) data.ints[2]; - super (mgr, id, data); - } - - override void activated () { - Stdout ("Button clicked!").newline; - } -} diff -r 1b1e2297e2fc -r 5ee69b3ed9c9 mde/setup/Screen.d --- a/mde/setup/Screen.d Sat Dec 20 17:57:05 2008 +0000 +++ b/mde/setup/Screen.d Sun Dec 21 12:03:50 2008 +0000 @@ -56,7 +56,7 @@ /** Init function to initialize SDL. */ StageState init () { // init func // Initialise SDL - debug logger.trace ("Calling SDL_Init (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)"); + debug (SDLCalls) logger.trace ("Calling SDL_Init (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)"); if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK /+| SDL_INIT_EVENTTHREAD+/)) { logger.fatal ("SDL initialisation failed:"); char* msg = SDL_GetError (); @@ -68,7 +68,7 @@ } /** SDL shutdown */ StageState cleanup () { - debug logger.trace ("Calling SDL_Quit ()"); + debug (SDLCalls) logger.trace ("Calling SDL_Quit ()"); SDL_Quit(); return StageState.INACTIVE; } @@ -214,7 +214,7 @@ } //debug logger.trace ("Setting video mode {}x{}, 32-bit, flags: {}", w,h,flags); - debug logger.trace ("Calling SDL_SetVideoMode ({}, {}, 32, 0x{:x})", w,h, flags); + debug (SDLCalls) logger.trace ("Calling SDL_SetVideoMode ({}, {}, 32, 0x{:x})", w,h, flags); if (SDL_SetVideoMode (w, h, 32, flags) is null) { logger.fatal ("Unable to set video mode:"); char* msg = SDL_GetError ();