diff mde/gui/widget/Window.d @ 34:6b4116e6355c

Work on the Gui: some of the framework for drag & drop. Also made Window an IWidget. Implemented getWidget(x,y) to find the widget under this location for IWidgets (but not Gui). Made Window an IWidget and made it work a little more similarly to widgets. Implemented callbacks on the Gui for mouse events (enabling drag & drop, etc.). committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 02 May 2008 16:03:52 +0100
parents 316b0230a849
children 928db3c75ed3
line wrap: on
line diff
--- a/mde/gui/widget/Window.d	Thu May 01 10:55:04 2008 +0100
+++ b/mde/gui/widget/Window.d	Fri May 02 16:03:52 2008 +0100
@@ -28,6 +28,13 @@
 // not yet implemented:
 //import tango.scrapple.text.convert.parseFrom : parseFrom;
 
+import tango.util.log.Log : Log, Logger;
+
+private Logger logger;
+static this () {
+    logger = Log.getLogger ("mde.gui.widget.Window");
+}
+
 /** GUI Window class
  *
  * A window class instance does two things: (1) specify a region of the screen upon which the window
@@ -39,23 +46,31 @@
 class Window : mt.IDataSection, IWindow
 {
     //BEGIN Methods for GUI
+    this (char[] id) {
+        name = id;
+    }
+    
     /** Call after loading is finished to setup the window and confirm that it's valid.
      *
      * Throws: WindowLoadException. Do not use the instance in this case! */
-    void finalise (IGui gui) {
+    void finalise (IGui gui)
+    in {
+        assert (gui !is null, "Window.finalise ("~name~"): gui is null");
+    } body {
         // Check data was loaded:
         if (widgetData is null) throw new WindowLoadException ("No widget data");
         
-        // Create the renderer:
+        gui_ = gui;
         rend = gui.renderer;
         
         // Create the primary widget (and indirectly all sub-widgets), throwing on error:
-        widget = getWidget (0, this);// primary widget always has ID 0.
+        widget = makeWidget (0, this);// primary widget always has ID 0.
         
         widgetData = null;          // data is no longer needed: allow GC to collect (cannot safely delete)
         
         widgetX = x + rend.windowBorder;  // widget position
         widgetY = y + rend.windowBorder;  // must be updated if the window is moved
+        widget.setPosition (widgetX, widgetY);
         
         widget.getCurrentSize (w,h);// Find the initial size
         w += rend.windowBorder * 2;       // Adjust for border
@@ -64,23 +79,6 @@
         xw = x+w;
         yh = y+h;
     }
-    
-    void draw () {
-        // background
-        rend.drawWindow (x,y, w,h);
-        
-        // Tell the widget to draw itself:
-        widget.draw(widgetX, widgetY);
-    }
-    
-    void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {
-        if (cx >= x && cx < xw && cy >= y && cy < yh) { // click on window?
-            if (cx >= widgetX && cx < xw-rend.windowBorder && cy >= widgetY && cy < yh-rend.windowBorder)   // click on widget?
-                widget.clickEvent (cx-widgetX, cy-widgetY, b, state);
-            // FIXME: else window dragging?
-        }
-    }
-    
     //BEGIN Mergetag code
     void addTag (char[] tp, mt.ID id, char[] dt) {
         if (tp == "int[][int]") {
@@ -104,17 +102,21 @@
     /** Get/create a widget by ID.
      *
      * Should $(I only) be called internally and by sub-widgets! */
-    IWidget getWidget (widgetID i, IParentWidget parent)
+    IWidget makeWidget (widgetID i, IWidget parent)
     in {
         // widgetData is normally left to be garbage collected after widgets have been created:
-        assert (widgetData !is null, "getWidget: widgetData is null");
+        assert (widgetData !is null, "Window.makeWidget ("~name~"): widgetData is null");
     } body {
         // See if it's already been created:
         IWidget* p = i in widgets;
-        if (p !is null) return *p;  // yes
-        else {                      // no
+        if (p !is null) {   // yes
+            char[128] tmp;
+            logger.warn (logger.format (tmp, "Window.makeWidget ("~name~"): widget {} has multiple uses!", i));
+            return *p;
+        }
+        else {              // no
             int[]* d = i in widgetData;
-            if (d is null) throw new WindowLoadException ("Widget not found");
+            if (d is null) throw new WindowLoadException ("Window.makeWidget ("~name~"): Widget not found");
             
             // Throws WidgetDataException (a WindowLoadException) if bad data:
             IWidget widg = createWidget (this, parent, *d);
@@ -123,6 +125,10 @@
         }
     }
     
+    IGui gui () {
+        return gui_;
+    }
+    
     /+void requestRedraw () {
     }+/
     
@@ -131,15 +137,62 @@
     }
     //END IWindow methods
     
-    //BEGIN IParentWidget methods
-    //END IParentWidget methods
+    //BEGIN IWidget methods
+    void getMinimumSize (out int w, out int h) {
+        widget.getMinimumSize (x,y);
+        w += rend.windowBorder * 2;       // Adjust for border
+        h += rend.windowBorder * 2;
+    }
+    void getCurrentSize (out int cw, out int ch) {
+        cw = w;
+        ch = h;
+    }
+    
+    void setPosition (int x, int y) {
+        /+ Note: this is currently unused. Maybe only use it internally?
+        this.x = x;
+        this.y = y;
+        
+        widgetX = x + rend.windowBorder;
+        widgetY = y + rend.windowBorder;
+        
+        widget.setPosition (widgetX, widgetY);
+        +/
+    }
+    
+    IWidget getWidget (int cx, int cy) {
+        if (cx < x || cx >= xw || cy < y || cy >= yh)   // not over window
+            return null;
+        if (cx >= widgetX && cx < xw-rend.windowBorder && cy >= widgetY && cy < yh-rend.windowBorder)
+                                                        // over the widget
+            return widget.getWidget (cx, cy);
+        else                                            // over the window border
+            return this;
+    }
+    void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {
+        //if (cx >= x && cx < xw && cy >= y && cy < yh) { // click on window?
+        // FIXME: repositioning?
+    }
+    
+    void draw () {
+        // background
+        rend.drawWindow (x,y, w,h);
+        
+        // Tell the widget to draw itself:
+        widget.draw();
+    }
+    //END IWidget methods
     
 private:
+    char[] name;                    // The window's name (id from config file)
+    IGui gui_;                      // The gui managing this window
+    
     int[][widgetID] widgetData;     // Data for all widgets under this window (deleted after loading)
     IWidget[widgetID] widgets;      // List of all widgets under this window (created on demand).
     IWidget widget;                 // The primary widget in this window.
     
     IRenderer rend;                 // The window's renderer
+    // FIXME: revise which parameters are stored once Gui knows window position
     int x,y;                        // Window position
     int w,h;                        // Window size (calculated from Widgets)
     int xw, yh;                     // x+w, y+h (frequent use by clickEvent)