diff mde/gui/widget/Ifaces.d @ 131:9cff74f68b84

Major revisions to popup handling. Buttons can close menus now, plus some smaller impovements. Removed Widget module. Moved Widget.AWidget to AChildWidget.AChildWidget and Widget.AParentWidget to AParentWidget.AParentWidget. Removed ASingleParentWidget to improve code sharing. AChildWidget doesn't implement IParentWidget like AWidget did. New IPopupParentWidget extending IParentWidget for the WM and some widgets to handle popups. Cut old popup management code. New underMouse() function replacing highlight(); called on all widgets. Separate menu-popup and button widgets aren't needed for menus now. Functions returning content widgets have been moved to their own module. Cleaned up jobs.txt. Switched to 80 line length for Ddoc.
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 21 Jan 2009 13:01:40 +0000
parents c5c38eaadb64
children 9fd705793568
line wrap: on
line diff
--- a/mde/gui/widget/Ifaces.d	Sat Jan 17 16:11:26 2009 +0000
+++ b/mde/gui/widget/Ifaces.d	Wed Jan 21 13:01:40 2009 +0000
@@ -13,17 +13,20 @@
 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.
  * 
- * This module contains the primary documentation for the declared methods; also the Widget module
- * has some brief comments and basic implementations.
+ * This module contains the primary documentation for the declared methods;
+ * also the Widget module has some brief comments and basic implementations.
  *
- * 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.
- *************************************************************************************************/
+ * 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.
+ * 
+ * It's recommended that widgets inherit one of the A*Widget classes rather
+ * than impement I*Widget directly.
+ *****************************************************************************/
 module mde.gui.widget.Ifaces;
 
 public import mde.gui.types;
@@ -31,21 +34,24 @@
 import mde.content.Content;
 
 
-/*************************************************************************************************
+/******************************************************************************
  * Interface for parent widgets, including IWidgetManager.
  *
  * All widgets implement this via AWidget to make things simpler (code sharing).
  *
  * 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).
- *************************************************************************************************/
+ *  Layout widget: a widget containing multiple sub-widges (which hence
+ *   controls how they are laid out).
+ *****************************************************************************/
 interface IParentWidget
 {
     /** Checks for recursion of unsafe widgets to prevent infinite recursion. */
     void recursionCheck (widgetID);
     
+    /** IPPWs return self, other widgets recurse call on parent. */
+    IPopupParentWidget getParentIPPW ();
+    
     /** Child widgets should call this on their parent if their minimal size changes, since they
      * cannot resize themselves.
      * 
@@ -65,7 +71,7 @@
      * NEVER and ALWAYS often don't result in usable GUIs, and aren't expected to be used except
      * for debugging.
      * 
-     * NOTE: ANY_SUBWIDGETS can cause problems like enlarging a menu bar containing a resizable
+     * Note: ANY_SUBWIDGETS can cause problems like enlarging a menu bar containing a resizable
      * blank instead of the main part of a window. */
     enum SIZABILITY_ENUM {
         NEVER		= 0,	/// Parents are never resizable
@@ -78,13 +84,86 @@
     static const SIZABILITY = SIZABILITY_ENUM.ALL_SUBWIDGETS;	/// ditto
 }
 
+/******************************************************************************
+ * Interface for parents of popups and the widget manager.
+ * 
+ * An IPopupParentWidget (IPPW) may have 0 or 1 child IPPWs; the child may have
+ * its own IPPW. Each IPPW when added to a parent IPPW is responsible for
+ * managing one popup.
+ * 
+ * So any child IPPW should also be a descendant widget, and is usually the or
+ * a descendant of the popup.
+ * 
+ * An IPPW usually has one popup to manage (the popup being one of its child
+ * widgets), but the popup is only active if the IPPW is added as a child of
+ * its parent IPPW.
+ * 
+ * The widget manager is an IPPW, but unlike most IPPWs its popup(s), if
+ * existing, probably have nothing to do with its child IPPWs.
+ *****************************************************************************/
+interface IPopupParentWidget : IParentWidget
+{
+    /** Add caller ippw as current child IPopupParentWidget of called IPPW.
+     *
+     * ippw is added as called IPPW's child IPPW, and its functions are
+     * called to draw popup and pass events. The called IPPW's previous child
+     * IPPW is replaced.
+     * 
+     * ippw is then responsible for managing a popup. */
+    void addChildIPPW (IPopupParentWidget ippw);
+    /** Remove ippw from being the called IPPW's child IPPW and disable
+     * menuActive.
+     * 
+     * Do nothing if ippw is not the called IPPW's child IPPW.
+     *
+     * Returns: true if ippw was the child IPPW.
+     *
+     * I.e. this deactivates ippw's popup. */
+    bool removeChildIPPW (IPopupParentWidget ippw);
+    
+    /** Notify the called IPPW that it has been removed. */
+    void removedIPPW ();
+    
+    /** Set/get menuActive state.
+     *
+     * This is set on the parent IPPW when a popup menu is opened and unset
+     * when the menu is closed.
+     * If set on the parent IPPW, popup menus can be opened with just a mouse-
+     * over and buttons activated with an up-click. */
+    void menuActive (bool);
+    bool menuActive ();
+    
+    /** Called by descendant widgets such as buttons when an action occurred,
+     * which should close a menu. (But also called when not in a menu.) */
+    void menuDone ();
+    
+    /** Get the widget under cx,cy.
+     *
+     * The IPPW should first recurse the call to its child IPPW if it exists.
+     * If this doesn't yield a widget, it should try getting one from its popup
+     * and then itself. It should return the first widget found or null.
+     * 
+     * If closePopup is true and a widget isn't returned from the childIPPW,
+     * the childIPPW should be removed (to close popups when a click is not on
+     * the popup or its parent) and menuActive set false. */
+    IChildWidget getPopupWidget (wdabs cx, wdabs cy, bool closePopup);
+    
+    /** Draw.
+     *
+     * The IPPW should first draw its popup, then call on its child IPPW if
+     * that exists. */
+    void drawPopup ();
+    
+    /// Returns true if ippw is child IPPW.
+    debug bool isChild (IPopupParentWidget ippw);
+}
 
-/*************************************************************************************************
+/******************************************************************************
  * Interface for the widget manager.
  * 
  * This class handles widget rendering, input, loading and saving.
- *************************************************************************************************/
-interface IWidgetManager : IParentWidget
+ *****************************************************************************/
+interface IWidgetManager : IPopupParentWidget
 {
     // Loading/saving:
     /** Create a widget by looking up the data for id then looking up data.ints[0] in WIDGET_TYPES.
@@ -112,6 +191,10 @@
     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
+     * (flags & 1 == 1). */
+    void positionPopup (IChildWidget parent, IChildWidget popup, int flags = 0);
+    
     // Rendering:
     /** For when a widget needs redrawing.
      * 
@@ -126,21 +209,6 @@
     * provides the possibility of per-window renderers (if desired). */
     IRenderer renderer ();
     
-    /** Creates and positions a pop-up widget (widg),
-     *
-     * Set flags = 1 to place widg left or right of parent, otherwise it will be placed above or
-     * below parent.
-     *
-     * WidgetManager sets its position, draws it, and passes it click events. If a click event
-     * occurs which isn't on the popup or it's parent, it is removed (unless a newer
-     * popup is not removed).
-     *
-     * Popups currently should not change their size while active. */
-    void addPopup (IChildWidget parent, IChildWidget popup, int flags = 0);
-    /** Remove the popup added by this parent, and any popups added afterwards.
-     * If parent added multiple popups, this would just remove the top one. */
-    void removePopup (IChildWidget parent);
-    
     // User input:
     /** Add a mouse click callback.
      * 
@@ -161,7 +229,7 @@
 }
 
 
-/*************************************************************************************************
+/******************************************************************************
  * 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
@@ -190,9 +258,9 @@
  *
  * 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 : IParentWidget
+interface IChildWidget
 {
 //BEGIN Load and save
     /** 2nd stage of initialization for widgets; also called on some changes.
@@ -309,9 +377,9 @@
     /** Called when keyboard input focus is lost. */
     void keyFocusLost ();
     
-    /** Called when the mouse moves over the button and when it leaves. No need to call
-     * requestRedraw. */
-    void highlight (bool state);
+    /** Called on all widgets when the mouse moves over it (state == true) and
+     * when it leaves (state == false). */
+    void underMouse (bool state);
     
     /** When a pop-up is closed the manager calls requestRedraw and this function on its parent. */
     void popupClose ();