diff mde/gui/WidgetManager.d @ 99:5de5810e3516

Implemented an editable TextContent widget; it's now possible to edit text options using the GUI. The widget supports moving the text entry-point using arrows and home/end, but there's no visual indicator or edit-point setting using the mouse.
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 14 Nov 2008 12:44:32 +0000
parents 30470bc19ca4
children 42e241e7be3e
line wrap: on
line diff
--- a/mde/gui/WidgetManager.d	Wed Nov 12 13:18:51 2008 +0000
+++ b/mde/gui/WidgetManager.d	Fri Nov 14 12:44:32 2008 +0000
@@ -102,8 +102,17 @@
         }
         IChildWidget widg = child.getWidget (cast(wdabs)cx,cast(wdabs)cy);
         //debug logger.trace ("Click on {}", widg);
-        if (widg !is null)
-            widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state);
+	if (keyFocus && keyFocus !is widg) {
+	    keyFocus.keyFocusLost;
+	    keyFocus = null;
+	    imde.input.setLetterCallback (null);
+	}
+        if (widg !is null) {
+	    if (widg.clickEvent (cast(wdabs)cx,cast(wdabs)cy,b,state) & 1) {
+		keyFocus = widg;
+		imde.input.setLetterCallback (&widg.keyEvent);
+	    }
+	}
     }
     
     /** For mouse motion events.
@@ -182,13 +191,22 @@
         child.setPosition (0,0);
     }
     
+    void preSave () {
+	if (keyFocus) {
+	    keyFocus.keyFocusLost;
+	    keyFocus = null;
+	    imde.input.setLetterCallback (null);
+	}
+    }
+    
 private:
+    IRenderer rend;
+    wdim w,h;       // area available to the widgets
+    wdim mw,mh;     // minimal area available to the widgets
     // callbacks indexed by their frame pointers:
     bool delegate(wdabs cx, wdabs cy, ubyte b, bool state) [void*] clickCallbacks;
     void delegate(wdabs cx, wdabs cy) [void*] motionCallbacks;
-    IRenderer rend;
-    wdim w,h;       // area available to the widgets
-    wdim mw,mh;     // minimal area available to the widgets
+    IChildWidget keyFocus;	// widget receiving keyboard input when non-null
 }
 
 
@@ -286,10 +304,10 @@
     *  name = Design to load. If null, the default will be loaded.
     */
     void loadDesign (char[] name = null) {
-        if (changes !is null)
+        if (changes !is null)	// A design was previously loaded
             save;       // own lock
             
-            mutex.lock;
+	mutex.lock;
         scope(exit) mutex.unlock;
         
         // Load data (loadData tests if it's already loaded first):
@@ -315,8 +333,7 @@
             changesDS = new mt.DataSet;
         
         mt.IDataSection* q = name in changesDS.sec;
-        if (q && ((changes = cast(WidgetDataChanges) *q) !is null)) {}
-        else {
+        if (!q || ((changes = cast(WidgetDataChanges) *q) is null)) {
             changes = new WidgetDataChanges (curData);
             changesDS.sec[name] = changes;
         }
@@ -329,6 +346,8 @@
     * 
     * Is run when the manager is destroyed, but could be run at other times too. */
     void save () {
+	preSave;
+	
         mutex.lock;
         scope(exit) mutex.unlock;
         
@@ -454,20 +473,24 @@
     */
     void createRootWidget();
     
-    protected:
-        final char[] fileName;
-        char[] defaultDesign;       // The design specified in the file header.
-        char[] rendName;    // Name of renderer; for saving and creating renderers
-        
-        // Loaded data, indexed by design name. May not be loaded for all gui designs:
-        scope WidgetDataSet[char[]] data;
-        private bool allLoaded = false;  // applies to data
-        WidgetDataSet curData;      // Current data
-        WidgetDataChanges changes;  // Changes for the current design.
-        scope mt.DataSet changesDS; // changes and sections from user file (used for saving)
-        bool loadUserFile = true;   // still need to load user file for saving?
-        
-        scope IChildWidget child;   // The primary widget.
-        
-        Mutex mutex;    // lock on methods for use outside the package.
+    /** Called before saving (usually when the GUI is about to be destroyed, although not
+     *  necessarily). */
+    void preSave () {}
+    
+protected:
+    final char[] fileName;
+    char[] defaultDesign;		// The design specified in the file header.
+    char[] rendName;			// Name of renderer; for saving and creating renderers
+    
+    // Loaded data, indexed by design name. May not be loaded for all gui designs:
+    scope WidgetDataSet[char[]] data;
+    private bool allLoaded = false;	// applies to data
+    WidgetDataSet curData;		// Current data
+    WidgetDataChanges changes;		// Changes for the current design.
+    scope mt.DataSet changesDS;		// changes and sections from user file (used for saving)
+    bool loadUserFile = true;		// still need to load user file for saving?
+    
+    scope IChildWidget child;		// The primary widget.
+    
+    Mutex mutex;			// lock on methods for use outside the package.
 }