changeset 28:b5fadd8d930b

Small addition to GUI, paths work-around for Windows. New GUI widget containing a widget. Paths on windows now uses "." and "./user" as a temporary measure. committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Tue, 08 Apr 2008 15:52:21 +0100
parents 0aa621b3e070
children f985c28c0ec9
files data/conf/gui.mtt mde/gui/IWindow.d mde/gui/Widget.d mde/gui/gui.d mde/resource/paths.d mde/scheduler/Init.d
diffstat 6 files changed, 112 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/data/conf/gui.mtt	Fri Apr 04 17:07:38 2008 +0100
+++ b/data/conf/gui.mtt	Tue Apr 08 15:52:21 2008 +0100
@@ -2,4 +2,8 @@
 {W1}
 <int|x=10>
 <int|y=50>
-<int[][int]|widgetData=[0:[1,200,200]]>
+<int[][int]|widgetData=[0:[1001,200,200]]>
+{W2}
+<int|x=150>
+<int|y=200>
+<int[][int]|widgetData=[0:[1002,2],2:[1001,150,150]]>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mde/gui/IWindow.d	Tue Apr 08 15:52:21 2008 +0100
@@ -0,0 +1,34 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/// Window interface (used by Widgets).
+module mde.gui.IWindow;
+
+import mde.gui.Widget;
+
+interface IWindow
+{
+    /** Widget ID type. Each ID is unique under this window.
+    *
+    * Type is int since this is the widget data type. */
+    alias int widgetID;
+    
+    /** Get a widget by ID.
+    *
+    * Returns the widget with the given ID from the Window's widget list. If the widget hasn't yet
+    * been created, creates it using the Window's widget creation data (throws on error; don't
+    * catch the exception). */
+    Widget getWidget (widgetID i);
+}
--- a/mde/gui/Widget.d	Fri Apr 04 17:07:38 2008 +0100
+++ b/mde/gui/Widget.d	Tue Apr 08 15:52:21 2008 +0100
@@ -16,6 +16,7 @@
 /// GUI Widget module.
 module mde.gui.Widget;
 
+import mde.gui.IWindow;
 import mde.gui.exception;
 
 import gl = mde.gl;
@@ -27,6 +28,13 @@
 */
 interface Widget
 {
+    /* this() should look like this:
+    this (IWindow window, int[] data)
+    * where:
+    *   window is the parent window (only needed for getting sub-widgets, hence no need to store)
+    *   data is the widget creation data, stripped of the widget type (see createWidget).
+    */
+    
     /** Draw, starting from given x and y.
     *
     * Maybe replace later with drawClipped, especially for cases where only part of the widget is
@@ -44,7 +52,7 @@
 {
     int w, h;   // size
     
-    this (int[] data) {
+    this (IWindow, int[] data) {
         if (data.length != 2) throw new WidgetDataException;
         
         w = data[0];
@@ -62,15 +70,46 @@
     }
 }
 
-enum WIDGET_TYPES : int {
-    BOX = 1
+/// Encapsulates another widget
+class SingleWidget : Widget
+{
+    int w, h;           // size
+    Widget subWidget;
+    
+    this (IWindow window, int[] data) {
+        if (data.length != 1) throw new WidgetDataException;
+        
+        subWidget = window.getWidget (data[0]);
+        
+        subWidget.getSize (w,h);
+        w += 10;
+        h += 10;
+    }
+    
+    void draw (int x, int y) {
+        gl.setColor (1.0f, 0.6f, 0.0f);
+        gl.drawBox (x,x+w, y,y+h);
+        
+        subWidget.draw (x+5, y+5);
+    }
+    
+    void getSize (out int w, out int h) {
+        w = this.w;
+        h = this.h;
+    }
 }
 
-Widget createWidget (int[] data) {
+// Widget types. Start high so they can be reordered easily later.
+enum WIDGET_TYPES : int {
+    BOX = 1001, SINGLE
+}
+
+Widget createWidget (IWindow window, int[] data) {
     if (data.length < 1) throw new WidgetDataException ("No widget data");
     int type = data[0];     // type is first element of data
     data = data[1..$];      // the rest is passed to the Widget
     
-    if (type == WIDGET_TYPES.BOX) return new BoxWidget (data);
+    if (type == WIDGET_TYPES.BOX) return new BoxWidget (window, data);
+    else if (type == WIDGET_TYPES.SINGLE) return new SingleWidget (window, data);
     else throw new WidgetDataException ("Bad widget type");
 }
--- a/mde/gui/gui.d	Fri Apr 04 17:07:38 2008 +0100
+++ b/mde/gui/gui.d	Tue Apr 08 15:52:21 2008 +0100
@@ -16,6 +16,7 @@
 /// Base GUI module.
 module mde.gui.gui;
 
+import mde.gui.IWindow;
 import mde.gui.Widget;
 import mde.gui.exception;
 
@@ -68,11 +69,11 @@
                 windows ~= w;
                 try {
                     w.finalise();
+                    
+                    gl.addDrawCallback (&w.draw);
                 } catch (WindowLoadException e) {
                     logger.error ("Window failed to load: " ~ e.msg);
                 }
-                
-                gl.addDrawCallback (&w.draw);
             }
         }
     }
@@ -91,7 +92,7 @@
 * Let the window load a table of widget data, of type int[][widgetID]. Each widget will, when
 * created, be given its int[] of data, which this() must confirm is valid (or throw).
 */
-class Window : mt.IDataSection
+class Window : mt.IDataSection, IWindow
 {
     alias int widgetID;     // Widget ID type. Each ID is unique under this window. Type is int since this is the widget data type.
     private int[][widgetID] widgetData;     // Data for all widgets under this window.
@@ -101,7 +102,7 @@
     int x,y;                        // Window position
     int w,h;                        // Window size (calculated from Widgets)
     
-    const BORDER_WIDTH = 5;         // Temporary way to handle window decorations
+    const BORDER_WIDTH = 8;         // Temporary way to handle window decorations
     
     
     // Call after loading is finished to setup the window and confirm that it's valid.
@@ -122,7 +123,7 @@
             if (d is null) throw new WindowLoadException ("Widget not found");
             
             // Throws WidgetDataException (a WindowLoadException) if bad data:
-            Widget w = createWidget (*d);
+            Widget w = createWidget (this, *d);
             widgets[i] = w;
             return w;
         }
--- a/mde/resource/paths.d	Fri Apr 04 17:07:38 2008 +0100
+++ b/mde/resource/paths.d	Tue Apr 08 15:52:21 2008 +0100
@@ -37,10 +37,11 @@
 import mde.mergetag.DataSet;
 import mde.mergetag.exception;
 
+import tango.io.Console;
 import tango.io.FilePath;
-import tango.util.log.Log : Log, Logger;
 import tango.stdc.stdlib;
 import tango.stdc.stringz;
+//import tango.scrapple.sys.win32.Registry;     // Trouble getting this to work
 
 /** Order to read files in.
 *
@@ -124,8 +125,8 @@
                 paths[pathsLen++] = fp.toString~'/';
                 return true;
             } catch (Exception e) {
-                logger.error ("Creating path "~path~" failed:");
-                logger.error (e.msg);
+                // No logging avaiable yet: Use Stdout/Cout
+                Cout ("Creating path "~path~" failed:" ~ e.msg).newline;
             }
         }
         return false;
@@ -142,14 +143,14 @@
 char[] logDir;
 
 //BEGIN Path resolution
-static this() {
-    logger = Log.getLogger ("mde.resource.paths");
-}
-
 // These are used several times:
 const DATA = "/data";
 const CONF = "/conf";
 
+/** Find at least one path for each required directory.
+*
+* Note: the logger cannot be used yet, so only output is exception messages. */
+
 version (linux) {
     void resolvePaths () {
         // Home directory:
@@ -177,26 +178,27 @@
     }
 } else version (Windows) {
     void resolvePaths () {
-        static assert (false, "No registry code");
+        //FIXME: Get path from registry
+        //FIXME: Get user path (Docs&Settings/USER/Local Settings/Application data/mde)
         
         // Base paths:
-        char[] userPath = `...`;
-        char[] installPath = `registryInstallPath or "."`;
-        char[] staticPath = findPath (installPath ~ DATA);
+        PathView installPath = findPath (false, "");;
+        PathView userPath = findPath (true, "user");   // FIXME: see above
+        PathView staticPath = findPath (false, "data");
         
         // Static data paths:
         dataDir.addPath (staticPath.toString);   // we know this is valid anyway
         dataDir.tryPath (userPath.toString ~ DATA);
         if (!dataDir.pathsLen) throw new mdeException ("Fatal: no data path found!");
-                
+        
         // Configuration paths:
         confDir.tryPath (staticPath.toString ~ CONF);
-        bool sysConf = confDir.tryPath (installPath ~ CONF);
-        confDir.tryPath (userPath.toString ~ CONF, !sysConf);   // create if no system conf dir
+        confDir.tryPath ("conf");
+        confDir.tryPath (userPath.toString ~ CONF, true);
         if (!confDir.pathsLen) throw new mdeException ("Fatal: no conf path found!");
         
         // Logging path:
-        logDir = userPath;
+        logDir = userPath.toString;
     }
 } else {
     static assert (false, "Platform is not linux or Windows: no support for paths on this platform yet!");
@@ -207,8 +209,6 @@
 // There are NO CHECKS that this is not exceeded.
 const MAX_PATHS = 3;
 
-Logger logger;
-
 /* Try each path in succession, returning the first to exist and be a folder.
 * If none are valid and create is true, will try creating each in turn.
 * If still none are valid, throws. */
@@ -219,17 +219,17 @@
     }
     if (create) {   // try to create a folder, using each path in turn until succesful
         foreach (path; paths) {
-            PathView pv = new FilePath (path);
+            FilePath fp = new FilePath (path);
             try {
-                return pv;
+                return fp.create;
             }
             catch (Exception e) {}
         }
     }
     // no valid path...
-    logger.fatal ("Unable to find"~(create ? " or create" : "")~" a required path! The following were tried:");
-    foreach (path; paths) logger.fatal ('\t' ~ path);
-    throw new mdeException ("Unable to resolve a required path (see log for details).");
+    char[] msg = "Unable to find"~(create ? " or create" : "")~" a required path! The following were tried:";
+    foreach (path; paths) msg ~= "  \"" ~ path ~ '\"';
+    throw new mdeException (msg);
 }
 //END Path resolution
 
--- a/mde/scheduler/Init.d	Fri Apr 04 17:07:38 2008 +0100
+++ b/mde/scheduler/Init.d	Tue Apr 08 15:52:21 2008 +0100
@@ -55,6 +55,7 @@
     try {
         paths.resolvePaths();
     } catch (Exception e) {
+        // NOTE: an exception thrown here cannot be caught by main()!
         throw new InitException ("Resolving paths failed: " ~ e.msg);
     }