diff mde/gui/content/Content.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 49e7cfed4b34
children 0ea4a3e651ae
line wrap: on
line diff
--- a/mde/gui/content/Content.d	Wed Nov 12 13:18:51 2008 +0000
+++ b/mde/gui/content/Content.d	Fri Nov 14 12:44:32 2008 +0000
@@ -20,6 +20,7 @@
 //FIXME: efficient conversions? Need to dup result when formatting a string anyway?
 import Int = tango.text.convert.Integer;
 import Float = tango.text.convert.Float;
+import derelict.sdl.keysym;
 
 debug {
     import tango.util.log.Log : Log, Logger;
@@ -151,6 +152,7 @@
     this (char[] symbol, char[] val = null) {
         symb = symbol;
         v = val;
+	pos = v.length;
     }
     
     /** Adds cb to the list of callback functions called when the value is changed. Returns this. */
@@ -177,9 +179,62 @@
     }
     alias opCall opCast;
     
+    /** Acts on a keystroke and returns the new value.
+     *
+     * Supports one-line editing: left/right, home/end, backspace/delete. */
+    char[] keyStroke (ushort sym, char[] i) {
+	debug assert (i.length, "TextContent.keyStroke: no value (??)");	// impossible?
+	char k = *i;
+	if (k > 0x20) {
+	    if (k == 0x7f) {		// delete
+		size_t p = pos;
+		if (p < v.length) ++p;
+		while (p < v.length && (v[p] & 0x80) && !(v[p] & 0x40))
+		    ++p;
+		v = v[0..pos] ~ v[p..$];
+	    } else {			// insert character
+		char[] tail = v[pos..$];
+		v.length = v.length + i.length;
+		size_t npos = pos+i.length;
+		if (tail) v[npos..$] = tail.dup;	// cannot assign with overlapping ranges
+		    v[pos..npos] = i;
+		pos = npos;
+	    }
+	} else {			// use sym; many keys output 0
+	    if (sym == SDLK_BACKSPACE) {	// backspace; k == 0x8
+		char[] tail = v[pos..$];
+		if (pos) --pos;
+		while (pos && (v[pos] & 0x80) && !(v[pos] & 0x40))
+		    --pos;
+		v = v[0..pos] ~ tail;
+	    } else if (sym == SDLK_LEFT) {
+		if (pos) --pos;
+		while (pos && (v[pos] & 0x80) && !(v[pos] & 0x40))
+		    --pos;
+	    } else if (sym == SDLK_RIGHT) {
+		if (pos < v.length) ++pos;
+		while (pos < v.length && (v[pos] & 0x80) && !(v[pos] & 0x40))
+		    ++pos;
+	    } else if (sym == SDLK_HOME || sym == SDLK_UP) {
+		pos = 0;
+	    } else if (sym == SDLK_END || sym == SDLK_DOWN) {
+		pos = v.length;
+	    } else
+		debug logger.trace ("Symbol: {}", sym);
+	}
+	return v;
+    }
+    
+    /// Gives all callbacks the modified value
+    void endEdit () {
+	foreach (cb; cngCb)
+	    cb(symb, v);
+    }
+    
     char[] v;
 protected:
     char[] symb;
+    size_t pos;		// editing position; used by keyStroke
     void delegate (char[],char[])[] cngCb;
 }