Revision: 4117 http://vexi.svn.sourceforge.net/vexi/?rev=4117&view=rev Author: mkpg2 Date: 2011-05-09 21:05:47 +0000 (Mon, 09 May 2011)
Log Message: ----------- Improve. Reimplement numfield to use vexi.js.Decimal. Modified Paths: -------------- trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/widget/numfield.t trunk/org.vexi-vexi.widgets/src_main/vexi/util/sync.t trunk/org.vexi-vexi.widgets/src_test/test/lib/text/edit.t trunk/org.vexi-vexi.widgets/src_test/test/util/sync.t trunk/org.vexi-vexi.widgets/src_test/test/widget/numfield.t Added Paths: ----------- trunk/org.vexi-vexi.widgets/src_poke/poke/ trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/ trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/poke_numfield.t Removed Paths: ------------- trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/numfield.t trunk/org.vexi-vexi.widgets/src_poke/widgets/ Modified: trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -1741,7 +1741,7 @@ return cWord ? cindex+cPos : cindex; } - thisbox.setCusrorCharIndex = function(index) { + thisbox.setCursorCharIndex = function(index) { var curindex = 0; var numblocks = numchildren; for (var i=0; numblocks>i; i++) { Modified: trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/widget/numfield.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/widget/numfield.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/widget/numfield.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -1,6 +1,6 @@ <!-- Copyright 2009 - see COPYING for details [LGPL] --> -<vexi xmlns:ui="vexi://ui" xmlns:meta="vexi://meta" xmlns="org.vexi.lib" xmlns:decimal="vexi.util.decimal"> +<vexi xmlns:ui="vexi://ui" xmlns:meta="vexi://meta" xmlns="org.vexi.lib" xmlns:sync="vexi.util.sync"> <meta:doc> <author>Mike Goodwin</author> </meta:doc> @@ -9,170 +9,155 @@ <role.tooltipable /> <text.field /> <ui:box> - + thisbox.v_edit; // abstract thisbox.enabled = true; - - // TBD - separate out min/max/decimalPlaces validity and have in a separate template ?? - thisbox.restrict = false; // restrict means ignore any input that breaches its min/max + thisbox.minvalue; thisbox.maxvalue; - thisbox.decimalPlaces; // 0 for an integer, null for unlimited + thisbox.scale; // number of decimal places, if positive. If negative, number of trailing 0's // value and the v_edit.text are synchronized - thisbox.decimal = new decimal(""); - thisbox.v_edit; + thisbox.value; + thisbox.validateText = static.validateTextFunc; + KeyPressed ++= static.keypressEvent; - decimalPlaces ++= static.decimalPlacesWrite; - maxvalue ++= static.maxvalueWrite; - minvalue ++= static.minvalueWrite; - number ++= static.numberRead; - number ++= static.valueWrite; - value ++= static.valueRead; - value ++= static.valueWrite; + scale ++= static.scale; + maxvalue ++= static.limitvalueWrite; + minvalue ++= static.limitvalueWrite; + const Decimal = vexi.js.Decimal; + + thisbox.validateNumber = function(d){ + if(d==null) return null; + var d0 = d; + + + if(maxvalue!=null){ + if(0>Decimal.compare(maxvalue, d)){ + d = maxvalue; + } + } + + if(minvalue!=null){ + if(0 > Decimal.compare(d, minvalue)){ + d = minvalue; + } + } + + if(scale!=null){ + d = d.round(scale); + } + return d; + }; + + + thisbox.focused ++= function(v){ + if(!v){ + // trigger value setting + v_edit.text = v_edit.text; + } + cascade = v; + }; + + thisbox.value ++= function(v){ + cascade = validateNumber(Decimal.cast(v)); + }; + + + thisbox.text2decimal = function(v){ + var d = Decimal.tryParseString(v); + if(d!=null){ + d = validateNumber(d); + } + return d; + }; + + var decimal2text= function(d){ + if(d==null) return ""; + return d+""; + }; + + thisbox.v_edit ++= function(v){ + cascade = v; + sync..syncTransform(thisbox, v, "value", "text", decimal2text, text2decimal); + thisbox[trapname] --= callee; + }; + + </ui:box> + + var Decimal = vexi.js.Decimal; - var modifyVal = function(val,i,key) { - switch (key) { - case "delete": - return val.attemptRemove(i); - case "back_space": - return val.attemptRemove(i-1); - //case "escape": ... - case "left": case "right": case "up": case "down": - case "home": case "end": - return null; - } - return val.attemptInsert(i,key); - }; - /** fire action or filter key in case of password fields */ static.keypressEvent = function(v) { var t = trapee; var e = t.v_edit; - if (e.select) { - cascade = v; - try { t.value = e.text; } - catch(e) { if (vexi.debug) vexi.log.info(e); } + var txt0 = e.text; + + + switch(v){ + // Handle '-' specially. Toggles sign. + case '-': { + var cpos = e.getCursorCharIndex(); + if(txt0.length==0 or txt0.charAt(0)!='-'){ + e.text = '-'+txt0; + cpos++; + }else{ + e.text = txt0.substring(1); + if(cpos!=0) cpos--; + } + e.setCursorCharIndex(cpos); return; } - var val = t.decimal; - var txt = e.text; - var cpos = e.getCursorCharIndex(); - - var prev = val; - val = modifyVal(val, cpos, v); - if (val==null) { - cascade = v; + case "ENTER": + case "enter": { + var cpos = e.getCursorCharIndex(); + t.value = t.text2decimal(e.text); + cpos = vexi.math.max(e.text.length, cpos); + e.setCursorCharIndex(cpos); return; } - - var newvalid = true; - if ((t.minvalue and (0>val.compareTo(t.minvalue))) - || (t.maxvalue and (val.compareTo(t.maxvalue)>0)) - || (t.decimalPlaces and (val.after > t.decimalPlaces))) { - if (trapee.restrict) { - return; + case ".": { + var cpos = e.getCursorCharIndex(); + cascade = v; + // If invalid revert ... + if(e.text.indexOf(".")!=e.text.lastIndexOf(".")){ + e.text = txt0; + e.setCursorCharIndex(cpos); } - newvalid = false; - } else { - t.decimal = val; + return; } + case "C-a": case "C-x": case "C-v": + case "LEFT": case "RIGHT": case "UP": case "DOWN": + case "left": case "right": case "up": case "down": + case "HOME": case "END": + case "home": case "end": + case "BACK_SPACE": case "DELETE": + case "back_space": case "delete": - cascade = v; - if (t.valid!=newvalid) { - t.valid = newvalid; + case "0": case "1": case "2": case "3": case "4": + case "5": case "6": case "7": case "8": case "9": + // Due to possibility of selection, not just editing a single char + // let the text widget handle this and correct as necessary + cascade = v; } } + /** constrain value to min */ - static.minvalueWrite = function(v) { - if (v!=null and !(v instanceof decimal)) { - v = new decimal(v); - } + static.limitvalueWrite = function(v) { + v = Decimal.cast(v); cascade = v; // constrain/set validity trapee.value = trapee.value; } /** constrain value to max */ - static.maxvalueWrite = function(v) { - if (v!=null and !(v instanceof decimal)) { - v = new decimal(v); - } + static.scale = function(v) { cascade = v; // constrain/set validity trapee.value = trapee.value; } - /** constrain value to max */ - static.decimalPlacesWrite = function(v) { - cascade = v; - // constrain/set validity - trapee.value = trapee.value; - } - - /** return value as a number */ - static.numberRead = function() { - var r = trapee.decimal.canonical; - if (trapee.decimalPlaces and trapee.decimalPlaces==0) { - return vexi.string.parseInt(r); - } - return vexi.string.parseFloat(r); - } - - /** parse and return value as a string */ - static.valueRead = function() { - // FIXME: decimal is returning haywire numbers after edits - var r = trapee.decimal.canonical; - var v = new decimal(r); - var dpsActual = v.after; - var dpsWanted = trapee.decimalPlaces; - if (dpsWanted==null || dpsActual==dpsWanted) { - return r; - } - if (dpsWanted>dpsActual) { - if (dpsActual==0) { - r += '.'; - } - var addzeros = dpsWanted-dpsActual; - while ((addzeros--)>0) { - r += '0'; - } - } else { - r = v.truncate(dpsWanted).canonical; - } - return r; - } - - /** verify the user-set value */ - static.valueWrite = function(v) { - var t = trapee; - if (!(v instanceof decimal)) { - v = new decimal(v); - } - v.assertValid(); - - if (t.restrict) { - if (t.minvalue and (0>v.compareTo(t.minvalue))) { - v = t.minvalue; - } else if (t.maxvalue and (v.compareTo(t.maxvalue)>0)) { - v = t.maxvalue; - } - if (t.decimalPlaces and (v.after > t.decimalPlaces)) { - v = v.truncate(t.decimalPlaces); - } - } else if ((t.minvalue and (0>v.compareTo(t.minvalue))) || - (t.maxvalue and (v.compareTo(t.maxvalue)>0)) || - (t.decimalPlaces and (v.after > t.decimalPlaces))) { - t.valid = false; - } - t.decimal = v; - if (t.v_edit.text != v.canonical) { - t.v_edit.text = v.canonical; - } - return; - } - </vexi> Modified: trunk/org.vexi-vexi.widgets/src_main/vexi/util/sync.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_main/vexi/util/sync.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_main/vexi/util/sync.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -56,7 +56,7 @@ cascade = v; if (fromB) return; fromA = true; - try { b[kb] = v; } + try { b[kb] = trapee[trapname]; } finally { fromA = false; } }; @@ -64,7 +64,7 @@ cascade = v; if (fromA) return; fromB = true; - try { a[ka] = v; } + try { a[ka] = trapee[trapname]; } finally { fromB = false; } }; @@ -97,7 +97,7 @@ cascade = v; if (fromB) return; fromA = true; - try { b[kb] = a2b(v); } + try { b[kb] = a2b(trapee[trapname]); } finally { fromA = false; } }; @@ -105,7 +105,7 @@ cascade = v; if (fromA) return; fromB = true; - try { a[ka] = b2a(v); } + try { a[ka] = b2a(trapee[trapname]); } finally { fromB = false; } }; Deleted: trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/numfield.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_poke/widgets/numfield.t 2011-04-04 12:31:07 UTC (rev 4104) +++ trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/numfield.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -1,37 +0,0 @@ -<vexi xmlns:ui="vexi://ui" xmlns:w="vexi.widget"> - <w:surface /> - <ui:box orient="vertical"> - <ui:box shrink="true"> - <w:check id="restrict" text="restrict"/> - <w:check id="three_dp" text="3dp"/> - <w:check id="positive" text="positive"/> - </ui:box> - <w:numfield id="numfield" /> - - $restrict.selected ++= function(v) { - cascade = v; - $positive.enabled = $three_dp.enabled = v; - $numfield.restrict = v; - }; - - $positive.selected ++= function(v) { - cascade = v; - $numfield.minvalue = v?"0":null; - }; - - $three_dp.selected ++= function(v) { - cascade = v; - $numfield.decimalPlaces = v?3:null; - }; - - $restrict.selected = false; - - $numfield.value ++= function(v) { - cascade = v; - vexi.log.info(v); - }; - - vexi.ui.frame = thisbox; - - </ui:box> -</vexi> Added: trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/poke_numfield.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/poke_numfield.t (rev 0) +++ trunk/org.vexi-vexi.widgets/src_poke/poke/widgets/poke_numfield.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -0,0 +1,36 @@ +<vexi xmlns:ui="vexi://ui" xmlns:w="vexi.widget"> + <w:surface /> + <ui:box orient="vertical"> + <ui:box shrink="true"> + <w:check id="three_dp" text="3dp"/> + <w:check id="positive" text="positive"/> + <w:check id="maximum" text="max==100"/> + </ui:box> + <w:numfield id="numfield" /> + $three_dp.selected ++= function(v) { + cascade = v; + $numfield.scale = v?3:null; + }; + + $positive.selected ++= function(v) { + cascade = v; + $numfield.minvalue = v?0:null; + }; + + $maximum.selected ++= function(v) { + cascade = v; + $numfield.maxvalue = v?100:null; + }; + + $numfield.value ++= function(v) { + cascade = v; + vexi.log.info("Value: "+v); + }; + + + $numfield.value = "300.00"; + + vexi.ui.frame = thisbox; + + </ui:box> +</vexi> Modified: trunk/org.vexi-vexi.widgets/src_test/test/lib/text/edit.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_test/test/lib/text/edit.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_test/test/lib/text/edit.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -35,13 +35,13 @@ suite.setCursorPosition = function() { var b1 = .edit(vexi.box); b1.text = "sausage and beans"; - b1.setCusrorPosition(3); + b1.setCursorCharIndex(3); assertEq(3, b1.getCursorPosition()); - b1.setCusrorPosition(7); + b1.setCursorCharIndex(7); assertEq(7, b1.getCursorPosition()); - b1.setCusrorPosition(10); + b1.setCursorCharIndex(10); assertEq(10, b1.getCursorPosition()); - b1.setCusrorPosition(17); + b1.setCursorCharIndex(17); assertEq(17, b1.getCursorPosition()); }; Modified: trunk/org.vexi-vexi.widgets/src_test/test/util/sync.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_test/test/util/sync.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_test/test/util/sync.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -2,45 +2,74 @@ <meta:doc> <author>Charles Goodwin</author> </meta:doc> + + var assertEq = .test.vunit..assertEq; + var assertObjEq = .test.vunit..assertObjectEquals; + + + /// Quick Suite + var suite = {}; + + + suite.testBasic = function() { + var a = {x: "a"}; + var b = {y: "b"}; + var token = sync..sync(a, b, "x", "y"); + + assertEq("a",a.x); + assertEq("b",b.y); + a.x = "c"; + assertEq("c",a.x); + assertEq("c",b.y); + + sync..unsync(token); + a.x = "d"; + assertEq("d",a.x); + assertEq("c",b.y); + }; - <ui:box> - var assertEq = .test.vunit..assertEq; - var assertObjEq = .test.vunit..assertObjectEquals; + suite.testTransform = function() { + var a = {x: "a.b"}; + var b = {y: []}; + var a2b = function(s){ return s.split("."); }; + var b2a = function(a){ return a.join("."); }; + var token = sync..syncTransform(a, b, "x", "y", a2b, b2a); - { // normal - var a = {x: "a"}; - var b = {y: "b"}; - var token = sync..sync(a, b, "x", "y"); - - assertEq("a",a.x); - assertEq("b",b.y); - a.x = "c"; - assertEq("c",a.x); - assertEq("c",b.y); - - sync..unsync(token); - a.x = "d"; - assertEq("d",a.x); - assertEq("c",b.y); - } + assertObjEq("a.b",a.x); + assertObjEq([],b.y); + a.x = a.x; + assertObjEq(["a","b"],b.y); + b.y = ["c","d"]; + assertEq("c.d",a.x); - { // transform - var a = {x: "a.b"}; - var b = {y: []}; - var a2b = function(s){ return s.split("."); }; - var b2a = function(a){ return a.join("."); }; - var token = sync..syncTransform(a, b, "x", "y", a2b, b2a); - - assertObjEq("a.b",a.x); - assertObjEq([],b.y); - a.x = a.x; - assertObjEq(["a","b"],b.y); - b.y = ["c","d"]; - assertEq("c.d",a.x); - - sync..unsync(token); - a.x = "e.f"; - assertObjEq(["c","d"],b.y); - } - </ui:box> + sync..unsync(token); + a.x = "e.f"; + assertObjEq(["c","d"],b.y); + }; + + + suite.testChain = function() { + var a = {v: 0}; + var b = {v: null}; + var c = {v: null}; + + var a2b = sync..sync(a, b, "v", "v"); + var b2c = sync..sync(b, c, "v", "v"); + + a.v = 1; + assertEq(1,a.v); + assertEq(1,b.v); + assertEq(1,c.v); + + b.v = 2; + assertEq(2,a.v); + assertEq(2,b.v); + assertEq(2,c.v); + }; + + static.test = suite; + + + <ui:box/> + </vexi> \ No newline at end of file Modified: trunk/org.vexi-vexi.widgets/src_test/test/widget/numfield.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_test/test/widget/numfield.t 2011-05-09 20:13:23 UTC (rev 4116) +++ trunk/org.vexi-vexi.widgets/src_test/test/widget/numfield.t 2011-05-09 21:05:47 UTC (rev 4117) @@ -3,6 +3,8 @@ <author>Charles Goodwin</author> </meta:doc> + const Decimal = vexi.js.Decimal; + /// Quick Suite var suite = {}; @@ -14,20 +16,27 @@ /** * basic numfield value write tests */ - var b = .numfield(vexi.box); - b.decimalPlaces = 2; + var b = new .numfield(); + b.scale = 2; b.value = "1.00"; - assertEq("1.00",b.value); + assertEq("1.00",b.value+""); b.value = "1.000"; - assertEq("1.00",b.value); + assertEq("1.00",b.value+""); b.value = "1.0"; - assertEq("1.00",b.value); - b.number = 2; - assertEq("2.00",b.value); + assertEq("1.00",b.value+""); + b.value = new Decimal(21.2); + assertEq("21.20",b.value+""); + b.scale = 4; + assertEq("21.2000",b.value+""); + b.scale = -1; + assertEq("20",b.value+""); - assertExceptionThrown(function() { b.value = "sausage"; }); }; +// suite.testException = function() { +// assertExceptionThrown(function() { b.value = "sausage"; }); +// }; + suite.testInteraction1 = function() { /** * test numfield focusable and @@ -36,16 +45,17 @@ var focusmodel = { setFocus:function(t, f) { return true; } }; var fmsurface = { focus:focusmodel }; var b1 = .numfield(vexi.box); - b1.decimalPlaces = 2; + b1.scale = 2; b1.surface ++= function() { return fmsurface; } b1.value = "1.00"; b1.focused = true; +// FIXME assertEq(true,b1.v_edit.select); b1.KeyPressed = "2"; b1.KeyPressed = "."; b1.KeyPressed = "0"; b1.focused = false; - assertEq("2.00",b1.value); + assertEq("2.00",b1.value+""); }; suite.testInteraction2 = function() { @@ -55,31 +65,36 @@ */ var b2 = .numfield(vexi.box); b2.surface ++= function() { return fmsurface; } - b2.decimalPlaces = 2; + b2.scale = 2; b2.KeyPressed = "1"; b2.KeyPressed = "."; b2.KeyPressed = "0"; - assertEq("1.00",b2.value); + b2.KeyPressed = "enter"; + assertEq("1.00",b2.value+""); b2.KeyPressed = "C-a"; b2.KeyPressed = "delete"; b2.KeyPressed = "2"; - assertEq("2.00",b2.value); + b2.KeyPressed = "enter"; + assertEq("2.00",b2.value+""); b2.KeyPressed = "C-a"; b2.KeyPressed = "delete"; b2.KeyPressed = "3"; b2.KeyPressed = "0"; b2.KeyPressed = "0"; - assertEq("300.00",b2.value); + b2.KeyPressed = "enter"; + assertEq("300.00",b2.value+""); b2.KeyPressed = "C-a"; b2.KeyPressed = "delete"; b2.KeyPressed = "1"; b2.KeyPressed = "."; b2.KeyPressed = "2"; b2.KeyPressed = "delete"; - assertEq("1.20",b2.value); + b2.KeyPressed = "enter"; + assertEq("1.20",b2.value+""); b2.KeyPressed = "back_space"; b2.KeyPressed = "5"; - assertEq("1.50",b2.value); + b2.KeyPressed = "enter"; + assertEq("1.50",b2.value+""); }; static.test = suite; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ WhatsUp Gold - Download Free Network Management Software The most intuitive, comprehensive, and cost-effective network management toolset available today. Delivers lowest initial acquisition cost and overall TCO of any competing solution. http://p.sf.net/sfu/whatsupgold-sd _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn