changeset 146:783969f4665c

Simple, inefficient context menus (displaying content description).
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 11 Feb 2009 12:00:12 +0000
parents 1048b5c7cab1
children 075705ad664a
files data/L10n/en-GB.mtt data/conf/guiDemo.mtt mde/gui/WMScreen.d mde/gui/WidgetManager.d mde/gui/widget/AChildWidget.d mde/gui/widget/Ifaces.d mde/gui/widget/ParentContent.d mde/gui/widget/TextWidget.d mde/gui/widget/layout.d mde/gui/widget/miscContent.d
diffstat 10 files changed, 176 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/data/L10n/en-GB.mtt	Tue Feb 10 13:10:53 2009 +0000
+++ b/data/L10n/en-GB.mtt	Wed Feb 11 12:00:12 2009 +0000
@@ -28,7 +28,7 @@
 <entry|logLevel.Error={0:"Error"}>
 <entry|logLevel.Fatal={0:"Fatal"}>
 <entry|logLevel.None={0:"None"}>
-<entry|logOutput={0:"Logging output",1:"Output to: 0=nowhere, 1=the console, 2=a file, 3=both"}>
+<entry|logOutput={0:"Logging output",1:"Where to output messages."}>
 <entry|logOutput.none={0:"None"}>
 <entry|logOutput.console={0:"Console"}>
 <entry|logOutput.file={0:"File"}>
--- a/data/conf/guiDemo.mtt	Tue Feb 10 13:10:53 2009 +0000
+++ b/data/conf/guiDemo.mtt	Wed Feb 11 12:00:12 2009 +0000
@@ -25,7 +25,7 @@
 <WidgetData|optFont={0:[0x2031],1:["Font","optSec"]}>
 
 !{use optBox for no description, optDBox for descriptions under entries}
-<WidgetData|optSec={0:[0x4110,0],1:["optDBox"]}>
+<WidgetData|optSec={0:[0x4110,0],1:["optBox"]}>
 <WidgetData|optDBox={0:[0x4100,1,2,1],1:["optBox","optDesc"]}>
 <WidgetData|optBox={0:[0x4100,1,1,3],1:["optName","optSep","optVal"]}>
 <WidgetData|optName={0:[0x4040, 0,1]}>
@@ -42,5 +42,7 @@
 <WidgetData|slider label={0:[0x4040,0,1]}>
 <WidgetData|slider={0:[0x2031],1:["MiscOptions.pollInterval","sliderW"]}>
 <WidgetData|sliderW={0:[0x4044]}>
+
+<WidgetData|context={0:[0x4040, 0,2]}>
 {Basic}
 <WidgetData|root={0:[0x21,0x90D970],1:["A string!"]}>
--- a/mde/gui/WMScreen.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/WMScreen.d	Wed Feb 11 12:00:12 2009 +0000
@@ -74,6 +74,7 @@
                 child.draw;
 	    if (childIPPW)
                 childIPPW.drawPopup;
+            drawPopup;
 	}
     }
     
@@ -81,8 +82,7 @@
      *
      * Sends the event on to the relevant windows and all click callbacks. */
     void clickEvent (ushort usx, ushort usy, ubyte b, bool state) {
-        debug scope (failure)
-            logger.warn ("clickEvent: failed!");
+        try {
         mutex.lock;
         scope(exit) mutex.unlock;
         if (child is null) return;
@@ -102,27 +102,42 @@
 	    keyFocus = null;
             input.setLetterCallback (null);
 	}
+        
         // Finally, post the actual event:
+        if (b == 3 && state) {	// right click - open context menu
+            IContent contextContent = underMouse.content;
+            if (contextContent is null) return;
+            // NOTE: Creates new widgets every time; not optimal
+            popupContext = makeWidget (this, "context", contextContent);
+            popupContext.setup (0, 3);
+            positionPopup (underMouse, popupContext, 0);
+            requestRedraw;
+        } else	// post other button presses to clickEvent
         if (underMouse.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state) & 1) {
             // keyboard input requested
             keyFocus = underMouse;
             input.setLetterCallback (&underMouse.keyEvent);
         }
+        } catch (Exception e) {
+            logger.error ("clickEvent: exception processing event: {}", e.msg);
+        }
     }
     
     /** For mouse motion events.
      *
      * Sends the event on to all motion callbacks. */
     void motionEvent (ushort scx, ushort scy) {
-        debug scope (failure)
-                logger.warn ("motionEvent: failed!");
-        mutex.lock;
-        scope(exit) mutex.unlock;
-	wdabs cx = cast(wdabs) scx, cy = cast(wdabs) scy;
-        foreach (dg; motionCallbacks)
-            dg (cx, cy);
-        
-        updateUnderMouse (cx, cy, false);
+        try {
+            mutex.lock;
+            scope(exit) mutex.unlock;
+            wdabs cx = cast(wdabs) scx, cy = cast(wdabs) scy;
+            foreach (dg; motionCallbacks)
+            	dg (cx, cy);
+            
+            updateUnderMouse (cx, cy, false);
+        } catch (Exception e) {
+            logger.error ("motionEvent: exception processing event: {}", e.msg);
+        }
     }
     
     
--- a/mde/gui/WidgetManager.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/WidgetManager.d	Wed Feb 11 12:00:12 2009 +0000
@@ -329,15 +329,30 @@
     override void menuDone () {}
     
     override IChildWidget getPopupWidget (wdabs cx, wdabs cy, bool closePopup) {
-        IChildWidget ret;
+        if (popupContext) {
+            if (popupContext.onSelf (cx, cy))
+            	return popupContext;
+            if (closePopup) {
+            	menuActive = (childIPPW !is null);
+            	popupContext = null;
+                requestRedraw;
+            }
+        }
         if (childIPPW) {
-            ret = childIPPW.getPopupWidget (cx, cy, closePopup);
-            if (closePopup && ret is null) {
+            IChildWidget ret =
+                    childIPPW.getPopupWidget (cx, cy, closePopup);
+            if (ret) return ret;
+            if (closePopup) {
                 menuActive = false;
                 removeChildIPPW (childIPPW);
             }
         }
-        return ret;
+        return null;
+    }
+    
+    override void drawPopup () {
+        if (popupContext)
+            popupContext.draw();
     }
     
     debug protected override bool isChild (IPopupParentWidget ippw) {
@@ -345,7 +360,6 @@
     }
     
     override void removedIPPW () {}	// irrelevant
-    override void drawPopup () {}
     //END IPopupParentWidget methods
     
     //BEGIN IWidgetManager methods
@@ -401,17 +415,20 @@
              h = popup.height,
              x, y;
         if (flags & 1) {
-            y = parent.yPos;
-            if (y+h > this.h) y += parent.height - h;
-            x = parent.xPos + parent.width;
-            if (x+w > this.w) x = parent.xPos - w;
+            y = parent.yPos;			// height flush with top
+            if (y+h > this.h) y += parent.height - h;	// or bottom
+            x = parent.xPos + parent.width;		// on right
+            if (x+w > this.w) x = parent.xPos - w;	// or left edge
         } else {
             x = parent.xPos;				// align on left edge
             if (x+w > this.w) x += parent.width - w;	// align on right edge
             y = parent.yPos + parent.height;		// place below
-            if (y+h > this.h) y = parent.yPos - h;		// place above
+            if (y+h > this.h) y = parent.yPos - h;	// or above
         }
+        if (x < 0) x = 0;	// may be placed partially off-screen
+        if (y < 0) y = 0;
         popup.setPosition (x, y);
+        //debug logger.trace ("placed popup at {},{}; size: {},{}", x,y, w,h);
     }
 
     void requestRedraw () {
@@ -600,6 +617,9 @@
     bool mAIPPW;			// IPPW variable
     IPopupParentWidget childIPPW;	// child IPPW, if any active
     
+    // Popup(s) handled directly by AWidgetManager:
+    IChildWidget popupContext;		// context menu (active if not null)
+    
     // callbacks indexed by their frame pointers. Must support removal of elements in foreach:
     SortedMap!(void*,bool delegate(wdabs cx, wdabs cy, ubyte b, bool state)) clickCallbacks;
     SortedMap!(void*,void delegate(wdabs cx, wdabs cy)) motionCallbacks;
--- a/mde/gui/widget/AChildWidget.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/AChildWidget.d	Wed Feb 11 12:00:12 2009 +0000
@@ -58,6 +58,11 @@
     override bool saveChanges () {
         return false;
     }
+    
+    // Widgets with content need to override this
+    override IContent content () {
+        return null;
+    }
 //END Load and save
     
 //BEGIN Size and position
--- a/mde/gui/widget/Ifaces.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/Ifaces.d	Wed Feb 11 12:00:12 2009 +0000
@@ -31,7 +31,7 @@
 
 public import mde.gui.types;
 public import mde.gui.renderer.IRenderer;
-import mde.content.IContent;
+public import mde.content.IContent;
 
 
 /******************************************************************************
@@ -199,7 +199,7 @@
     wdims dimData (widgetID id);			/// ditto
     void dimData (widgetID id, wdims d);		/// ditto
     
-    /** Position popup left or right of parent, or left or right of parent
+    /** Position popup below or above parent, or right or left of parent
      * (flags & 1 == 1). */
     void positionPopup (IChildWidget parent, IChildWidget popup, int flags = 0);
     
@@ -240,14 +240,13 @@
 /******************************************************************************
  * 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.)
+ * 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 other
+ * widgets as necessary.
  *
- * 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().
+ * If a widget is to be creatable by IWidgetManager.makeWidget, it must be
+ * listed in the AWidgetManager WIDGET_TYPE enum and WIDGETS list, and have a
+ * constructor of the following form.
  * It should use Ddoc to explain what initialization data is used.
  * ----------------------------------
  * /++ Constructor for a ... widget.
@@ -255,17 +254,20 @@
  *  + Widget uses the initialisation data:
  *  + [widgetID, x, y]
  *  + where x is ... and y is ... +/
- * this (IWidgetManager mgr, widgetID id, WidgetData data);
+ * this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data);
  * 
  * /// The CTOR may take an IContent reference:
- * this (IWidgetManager mgr, widgetID id, WidgetData data, IContent content);
+ * this (IWidgetManager mgr, IParentWidget parent, 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.
+ * Where mgr is the widget manager, parent is the widget's _parent (another
+ * child widget or the widget manager), id is the _id passed to makeWidget()
+ * and data is initialisation _data. The method should throw a
+ * WidgetDataException if the data is invalid, and throw other GuiExceptions on
+ * other errors.
  *
- * 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.
+ * 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
@@ -304,6 +306,8 @@
     void childChanged ();
     +/
     
+    /** Return the widget's content, or null. */
+    IContent content ();
 //END Load and save
     
 //BEGIN Size and position
--- a/mde/gui/widget/ParentContent.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/ParentContent.d	Wed Feb 11 12:00:12 2009 +0000
@@ -42,26 +42,30 @@
 class PopupMenuWidget : APopupParentWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
-	content = cast(Content)c;
-	WDCMinCheck (data, 3,1, content);
+	content_ = cast(Content)c;
+	WDCMinCheck (data, 3,1, content_);
         super (mgr, parent, id);
         
-        //popup = mgr.makeWidget (this, data.strings[0], content);
+        //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);
+            content_.addCallback (&updateVal);
         adapter = mgr.renderer.getAdapter;
-	adapter.text = content.toString (cIndex);
+	adapter.text = content_.toString (cIndex);
 	adapter.getDimensions (mw, mh);
 	w = mw;
 	h = mh;
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
     override void recursionCheck (widgetID wID, IContent c) {
-        if (wID is id && c is content)
+        if (wID is id && c is content_)
             throw new WidgetRecursionException (wID);
         parent.recursionCheck (wID, c);
     }
@@ -109,7 +113,7 @@
     
 protected:
     void updateVal (Content) {	// callback
-        adapter.text = content.toString(cIndex);
+        adapter.text = content_.toString(cIndex);
         wdim omw = mw, omh = mh;
         adapter.getDimensions (mw, mh);
         if (omw != mw)
@@ -119,7 +123,7 @@
     }
     bool pushed = false;
     IRenderer.TextAdapter adapter;
-    Content content;
+    Content content_;
     int cIndex;
 }
 
@@ -131,16 +135,20 @@
 {
     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)
+        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)
+        foreach (i,sc; content_.list)
             subWidgets[i] = mgr.makeWidget (this, data.strings[i], sc);
-        currentW = subWidgets[content()];
+        currentW = subWidgets[content_()];
         
-        content.addCallback (&switchWidget);
+        content_.addCallback (&switchWidget);
+    }
+    
+    override IContent content () {
+        return content_;
     }
     
     override bool setup (uint n, uint flags) {
@@ -152,7 +160,7 @@
             h = currentW.height;
             static if (SIZABILITY & SIZABILITY_ENUM.START_TRUE)
                     isWS = isHS = true;
-            foreach (i,sc; content.list) {
+            foreach (i,sc; content_.list) {
                 static if (SIZABILITY == SIZABILITY_ENUM.ANY_SUBWIDGETS) {
                     isWS |= subWidgets[i].isWSizable;
                     isHS |= subWidgets[i].isHSizable;
@@ -207,9 +215,9 @@
     }
     
 protected:
-    // callback on content
+    // callback on content_
     void switchWidget (Content) {
-        currentW = subWidgets[content()];
+        currentW = subWidgets[content_()];
         mw = currentW.minWidth;
         mh = currentW.minHeight;
         parent.minWChange (this, mw);
@@ -223,7 +231,7 @@
     }
     
     IChildWidget currentW;
-    EnumContent content;
+    EnumContent content_;
     
     bool isWS, isHS;	// no infrastructure for changing sizability, so need to fix it.
 }
@@ -238,18 +246,18 @@
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
         super (mgr, parent, id);
-        content = cast(BoolContent) c;
-        WDCCheck (data, 1, 1, content);
+        content_ = cast(BoolContent) c;
+        WDCCheck (data, 1, 1, content_);
         
         subWidgets = [mgr.makeWidget (this, data.strings[0])];
         
-        content.addCallback (&collapse);
+        content_.addCallback (&collapse);
     }
     
     override bool setup (uint n, uint flags) {
         bool r = super.setup (n, flags);
         if (r) {
-            collapsed = content();
+            collapsed = content_();
             if (!collapsed) {
             	mw = subWidgets[0].minWidth;
             	mh = subWidgets[0].minHeight;
@@ -260,6 +268,10 @@
         return r;
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
     override void minWChange (IChildWidget widget, wdim nmw) {
         debug assert (widget is subWidgets[0]);
         mw = nmw;
@@ -305,9 +317,9 @@
     }
     
 protected:
-    // callback on content
+    // callback on content_
     void collapse (Content) {
-        collapsed = content();
+        collapsed = content_();
         if (collapsed) {
             mw = mh = 0;
         } else {
@@ -324,5 +336,5 @@
     }
     
     bool collapsed = false;
-    BoolContent content;
+    BoolContent content_;
 }
--- a/mde/gui/widget/TextWidget.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/TextWidget.d	Wed Feb 11 12:00:12 2009 +0000
@@ -88,27 +88,31 @@
 class DisplayContentWidget : ATextWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
-	content = cast(Content) c;
-	WDCMinCheck (data, 1, 0, content);
+	content_ = cast(Content) c;
+	WDCMinCheck (data, 1, 0, content_);
         super (mgr, parent, id);
         
         if (data.ints.length >= 3)
             cIndex = data.ints[2];	// otherwise display '0', the value
         if (cIndex == 0)
-            content.addCallback (&updateVal);
+            content_.addCallback (&updateVal);
         
         adapter = mgr.renderer.getAdapter ();
     }
     
     override bool setup (uint n, uint flags) {
 	if (!(flags & 3)) return false;	// string or renderer (and possibly font) changed
-	adapter.text = content.toString(cIndex);
+	adapter.text = content_.toString(cIndex);
         return super.setup (n, 3);	// force redimensioning
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
 protected:
     void updateVal (Content) {	// callback
-        adapter.text = content.toString(cIndex);
+        adapter.text = content_.toString(cIndex);
         wdim omw = mw, omh = mh;
         adapter.getDimensions (mw, mh);
         if (omw != mw)
@@ -116,7 +120,7 @@
         if (omh != mh)
             parent.minHChange (this, mh);
     }
-    Content content;
+    Content content_;
     int cIndex;
 }
 
@@ -124,13 +128,17 @@
 class AStringContentWidget : ATextWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
-	content = cast(AStringContent) c;
-        if (content is null) throw new ContentException (this);
+	content_ = cast(AStringContent) c;
+        if (content_ is null) throw new ContentException (this);
         super (mgr, parent, id);
         
-        content.addCallback (&update);
+        content_.addCallback (&update);
         adapter = mgr.renderer.getAdapter ();
-	adapter.text = content.toString(0);
+	adapter.text = content_.toString(0);
+    }
+    
+    override IContent content () {
+        return content_;
     }
     
     override bool isWSizable () {
@@ -142,15 +150,15 @@
     
     /** On click, request keyboard input. */
     override int clickEvent (wdabs cx, wdabs, ubyte, bool) {
-	//adapter.index = content.editIndex;
-        content.editIndex = adapter.setIndex (cx - x);
+	//adapter.index = content_.editIndex;
+        content_.editIndex = adapter.setIndex (cx - x);
 	mgr.requestRedraw;
 	return 1;	// get keyboard input via keyEvent
     }
     
     override void keyEvent (ushort s, char[] i) {
-	adapter.text = content.keyStroke (s, i);
-	adapter.index = content.editIndex;
+	adapter.text = content_.keyStroke (s, i);
+	adapter.index = content_.editIndex;
         wdim omw = mw, omh = mh;
         adapter.getDimensions (mw, mh);
         if (omw != mw)
@@ -160,14 +168,14 @@
 	mgr.requestRedraw;
     }
     override void keyFocusLost () {
-	adapter.text = content.endEdit;	// update other users of content relying on callbacks
+	adapter.text = content_.endEdit;	// update other users of content_ relying on callbacks
 	adapter.index;
 	mgr.requestRedraw;
     }
     
 protected:
     void update (Content) {	// callback
-        adapter.text = content.toString(0);
+        adapter.text = content_.toString(0);
         wdim omw = mw, omh = mh;
         adapter.getDimensions (mw, mh);
         if (omw != mw)
@@ -175,5 +183,5 @@
         if (omh != mh)
             parent.minHChange (this, mh);
     }
-    AStringContent content;
+    AStringContent content_;
 }
--- a/mde/gui/widget/layout.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/layout.d	Wed Feb 11 12:00:12 2009 +0000
@@ -116,6 +116,10 @@
         }
     }
     
+    override IContent content () {
+        return cList;
+    }
+    
     override void recursionCheck (widgetID wID, IContent c) {
         if (wID is id && c is cList)
             throw new WidgetRecursionException (wID);
--- a/mde/gui/widget/miscContent.d	Tue Feb 10 13:10:53 2009 +0000
+++ b/mde/gui/widget/miscContent.d	Wed Feb 11 12:00:12 2009 +0000
@@ -37,39 +37,43 @@
 class BoolContentWidget : AButtonWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
-	content = cast(BoolContent) c;
-        if (content is null) throw new ContentException (this);
+	content_ = cast(BoolContent) c;
+        if (content_ is null) throw new ContentException (this);
         super (mgr, parent, id);
         wdimPair s = mgr.renderer.getToggleSize;
         w = mw = s.x;
         h = mh = s.y;
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
     override void draw () {
-        mgr.renderer.drawToggle (x,y, content(), pushed);
+        mgr.renderer.drawToggle (x,y, content_(), pushed);
     }
     
     override void activated () {
-        content = !content();
+        content_ = !content_();
     }
     
 protected:
-    BoolContent content;
+    BoolContent content_;
 }
 
 /// A button connected to an EventContent
 class ButtonContentWidget : AButtonWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
-	content = cast(Content) c;
-        if (content is null) throw new ContentException (this);
+	content_ = cast(Content) c;
+        if (content_ is null) throw new ContentException (this);
         adapter = mgr.renderer.getAdapter ();
         super (mgr, parent, id);
     }
     
     override bool setup (uint n, uint flags) {
 	if (!(flags & 3)) return false;	// string or renderer (and possibly font) changed
-	adapter.text = content.toString(1);
+	adapter.text = content_.toString(1);
 	adapter.getDimensions (mw, mh);
 	if (mw != w || mh != h) {
 	    w = mw;
@@ -78,18 +82,22 @@
 	return true;
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
     override void draw () {
 	super.draw();
 	adapter.draw (x,y);
     }
     
     override void activated () {
-	content.endEvent;
+	content_.endEvent;
     }
     
 protected:
     IRenderer.TextAdapter adapter;
-    Content content;
+    Content content_;
     int index;
 }
 
@@ -97,23 +105,27 @@
 class SliderContentWidget : AChildWidget
 {
     this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
-	content = cast(DoubleContent) c;
-        if (content is null) throw new ContentException (this);
+	content_ = cast(DoubleContent) c;
+        if (content_ is null) throw new ContentException (this);
         super (mgr, parent, id);
         wdimPair s = mgr.renderer.getSliderSize;
         w = mw = s.x;
         h = mh = s.y;
     }
     
+    override IContent content () {
+        return content_;
+    }
+    
     override bool isWSizable () {
         return true;
     }
     
     override void draw () {
-        mgr.renderer.drawSlider (x,y, w, content());
+        mgr.renderer.drawSlider (x,y, w, content_());
     }
     
 protected:
-    DoubleContent content;
+    DoubleContent content_;
 }