Revision: 4489 http://vexi.svn.sourceforge.net/vexi/?rev=4489&view=rev Author: clrg Date: 2013-03-14 02:36:20 +0000 (Thu, 14 Mar 2013) Log Message: ----------- Edit refactor - only show currently visible text - all scrollpanes now implicitly virtual
Added Paths: ----------- branches/org.vexi-vexi.widgets_editrefactor/.project branches/org.vexi-vexi.widgets_editrefactor/.settings/ branches/org.vexi-vexi.widgets_editrefactor/.settings/org.eclipse.ltk.core.refactoring.prefs branches/org.vexi-vexi.widgets_editrefactor/.vexipath branches/org.vexi-vexi.widgets_editrefactor/build.xml branches/org.vexi-vexi.widgets_editrefactor/src_main/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/edit.t branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/line.t branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/scrollpane.t branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/table.t branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/scrollpane.t branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/textarea.t Added: branches/org.vexi-vexi.widgets_editrefactor/.project =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/.project (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/.project 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.vexi-vexi.widgets_editrefactor</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.vexi.vexidev.vexiBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.vexi.vexidev.vexiNature</nature> + </natures> +</projectDescription> Property changes on: branches/org.vexi-vexi.widgets_editrefactor/.project ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/org.vexi-vexi.widgets_editrefactor/.settings/org.eclipse.ltk.core.refactoring.prefs =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/.settings/org.eclipse.ltk.core.refactoring.prefs (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/.settings/org.eclipse.ltk.core.refactoring.prefs 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false Property changes on: branches/org.vexi-vexi.widgets_editrefactor/.settings/org.eclipse.ltk.core.refactoring.prefs ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/org.vexi-vexi.widgets_editrefactor/.vexipath =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/.vexipath (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/.vexipath 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,18 @@ +<project-path> + <main> + <sources> + <source-dir path="src_main"/> + </sources> + <dependencies> + <path-entry type="project" name="org.vexi-vexi.widgets"/> + </dependencies> + </main> + <test> + <sources/> + <dependencies/> + </test> + <poke> + <sources/> + <dependencies/> + </poke> +</project-path> \ No newline at end of file Added: branches/org.vexi-vexi.widgets_editrefactor/build.xml =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/build.xml (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/build.xml 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,6 @@ +<project default="eclipse_setup"> + + <property name="ebuild.home" location="../_ebuild"/> + <import file="${ebuild.home}/interface/workspace.ent"/> + +</project> \ No newline at end of file Property changes on: branches/org.vexi-vexi.widgets_editrefactor/build.xml ___________________________________________________________________ Added: svn:mime-type + text/plain Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/edit.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/edit.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/edit.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,124 @@ +<!-- Copyright 2013 - see COPYING for details [LGPL] --> + +<vexi xmlns:ui="vexi://ui" xmlns:text="org.vexi.lib.text"> + <ui:box layout="place" align="topleft"> + + thisbox.multiline = true; + thisbox.v_text = ""; + + var tip = false; + thisbox.width ++= function(v) { + cascade = v; + if (tip) return; + trace(v); + tip = true; + vexi.thread = function() { + while (tip) { + reflowText(); + tip = false; + vexi.thread.yield(); + } + } + } + + thisbox.text ++= function(v) { + v_text = v==null?"":v; + reflowText(); + // do not put + return; + } + + const NEWLINE = 0; + const WHITESPACE = 1; + const ALPHA_NUMERIC = 2; + const NON_ALPHA_NUMERIC = 3; + + const getCharType = function(n) { + + if ((n == 10) or (n == 13)) { + // 10: \n, 13: \r + return NEWLINE; + } + if ((n==9) or (n==32)) { + // 9: \t, 32: ' ' + return WHITESPACE; + } + if (122>=n and (n>=97 or (n>=48 and (57>=n or (n>=65 and 90>=n))))) { + // alpha numeric -- 48-57 (0-9), 65-90 (A-Z), 97-122 (a-z) + return ALPHA_NUMERIC; + } + + // other + return NON_ALPHA_NUMERIC; + } + + const mh = vexi.ui.font.height(font, fontsize, "dy"); + + thisbox.reflowText = function() { + clear(); + if (!multiline) { + addLine(v_text); + return; + } + + var t = v_text; + var lasti = 0; + var nexti = 0; + var linen = 0; + var linew = 0; + var firstword = true; + var wordend, wordstart; + + const addLine = function(v) { + const b = new text.line(); + b.text = v; + b.minheight = mh; + b.x = 0; + b.y = mh * linen; + add(b); + linen ++; + linew = 0; + firstword = true; + } + + trace(width); + + for (var i=0; t.length>i; i++) { + const c = t.charAt(i); + const n = t.charCodeAt(i); + const w = vexi.ui.font.width(font, fontsize, c); + const n_type = getCharType(n); + + if (300>i) trace(i+":"+c+", "+n+", "+w+" ("+linew+"), "+n_type+", "+wordend+", "+wordstart); + if (n_type == NEWLINE) { + addLine(t.substring(lasti, i)); + lasti = i+1; + linew = 0; + continue; + } + + if (linew + w > width) { + addLine(t.substring(lasti, wordend?:i)+" "); + wordend = null; + lasti = wordstart?:i; + } + + if (n_type != wordtype) { + // new word; mark break point if necessary + if (wordtype != WHITESPACE) { + wordend = i; + } else { + wordstart = i; + } + wordtype = n_type; + } + + linew += w; + firstword = false; + } + + thisbox.scrollheight = (linen+1) * mh; + } + + </ui:box> +</vexi> Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/line.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/line.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/text/line.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,5 @@ +<!-- Copyright 2013 - see COPYING for details [LGPL] --> + +<vexi xmlns:ui="vexi://ui"> + <ui:box shrink="true" /> +</vexi> Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/scrollpane.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/scrollpane.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/scrollpane.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,234 @@ +<!-- Copyright 2009 - see COPYING for details [LGPL] --> + +<vexi xmlns:ui="vexi://ui" xmlns:meta="vexi://meta" xmlns="org.vexi.lib.widget" + xmlns:common="vexi.util.common"> + <meta:doc> + <author>Charles Goodwin</author> + <fixme> + - toggling autohidehorizontal/vertical does not toggle autohide + - setting scrollhorizontal/vertical is not guarranteed as autohide + also sets the display properties on scrollbars + </fixme> + </meta:doc> + + <ui:box> + + // public variables + thisbox.autohide; + thisbox.autohidehorizontal = false; + thisbox.autohidevertical = false; + thisbox.scrollhorizontal = true; + thisbox.scrollvertical = true; + thisbox.virtualhorizontal = false; + thisbox.virtualvertical = false; + + // theme variables + thisbox.th_hscroll; + thisbox.th_vscroll; + thisbox.th_uiport; // actual ui representation of viewport in case viewport is virtual + + thisbox.v_viewport = static.new_virtual(); + + /** reusable function for write traps that constrain the viewport to the contents */ + thisbox.v_constrainPaneH = function(v) { cascade = v; th_uiport.minwidth = v_viewport[0].contentwidth; } + + /** reusable function for write traps that constrain the viewport to the contents */ + thisbox.v_constrainPaneV = function(v) { cascade = v; th_uiport.minheight = v_viewport[0].contentheight; } + + // apply constrain traps + hshrink ++= v_constrainPaneH; + vshrink ++= v_constrainPaneV; + + const sync_vp = function(v) { cascade = v; v_viewport[trapname] = v; } + const sync_vp_0 = function(v) { cascade = v; v_viewport[0][trapname] = v; } +// const sync_ui = function(v) { cascade = v; th_uiport[trapname] = v; } + const sync_ui_0 = function(v) { cascade = v; th_uiport[0][trapname] = v; } + + /** th_uiport is used in case the viewport is virtual + * in which case uiport represents the ui area that + * would otherwise be the viewport + */ + th_uiport ++= function(v) { + cascade = v; + th_hscroll.uiport = v; + th_vscroll.uiport = v; + // these set it up as a standard scrollpane + virtualvertical = virtualvertical; + virtualhorizontal = virtualhorizontal; + // required as scrollbars act on viewport not uiport + v_viewport[0].x ++= sync_ui_0; + v_viewport[0].y ++= sync_ui_0; + th_uiport.height ++= sync_vp; + th_uiport.width ++= sync_vp; + } + + th_hscroll ++= static.assignViewport; + th_vscroll ++= static.assignViewport; + + virtualvertical ++= function(v) { + cascade = v; + if (v) { + th_uiport[0].width --= sync_vp_0; + } else { + th_uiport[0].width ++= sync_vp_0; + } + } + + virtualhorizontal ++= function(v) { + cascade = v; + if (v) { + th_uiport[0].height --= sync_vp_0; + } else { + th_uiport[0].height ++= sync_vp_0; + } + } + + // assign static traps + + thisbox.autohide ++= static.autohideWrite; + thisbox.autohide ++= static.autohideRead; + thisbox.autohidehorizontal ++= static.autohidehorizontalWrite; + thisbox.autohidevertical ++= static.autohideverticalWrite; + thisbox.scroll ++= static.scrollWrite; + thisbox.scroll ++= static.scrollRead; + thisbox.scrollhorizontal ++= static.scrollhorizontalWrite; + thisbox.scrollvertical ++= static.scrollverticalWrite; + thisbox.hinset ++= static.hinsetRead; + thisbox.vinset ++= static.vinsetRead; + thisbox.viewheight ++= static.viewheightRead; + thisbox.viewwidth ++= static.viewwidthRead; + thisbox.viewx ++= static.viewxRead; + thisbox.viewx ++= static.viewxWrite; + thisbox.viewy ++= static.viewyRead; + thisbox.viewy ++= static.viewyWrite; + + </ui:box> + + static.new_virtual = function() { + var vport = {}; + vport.x = vport.y = 0; + vport.width = vport.height = 0; + var vbody = {}; + vbody.x = vbody.y = 0; + vbody.width = vbody.height = 0; + vport[0] = vbody; + return vport; + } + + static.assignViewport = function(v) { + if (v) v.viewport = trapee.v_viewport; + cascade = v; + } + + /** write trap to set autohide on scrollbars */ + static.autohideWrite = function(v) { trapee.autohidehorizontal = v; trapee.autohidevertical = v; return; } + + /** read trap to return current autohide state */ + static.autohideRead = function() { return trapee.autohidehorizontal and trapee.autohidevertical; } + + /** autohide th_hscroll */ + static.autohidehorizontalWrite = function(a) { + if (a == trapee.autohidehorizontal) { + return; + } + trapee.th_hscroll.autohide = a; + cascade = a; + } + + /** autohide th_vscroll */ + static.autohideverticalWrite = function(a) { + if (a == trapee.autohidevertical) { + return; + } + trapee.th_vscroll.autohide = a; + cascade = a; + } + + /** write trap to enable or disable scrollbars */ + static.scrollWrite = function(v) { trapee.scrollhorizontal = v; trapee.scrollvertical = v; return; } + + /** read trap to return current scroll state */ + static.scrollRead = function() { return trapee.scrollhorizontal and trapee.scrollvertical; } + + /** toggle horizontal scrollbar */ + static.scrollhorizontalWrite = function(s) { + const scrollbar = trapee.th_hscroll; + const v_viewport = trapee.v_viewport; + if (s) { + scrollbar.autohide = trapee.autohidehorizontal; + } else { + scrollbar.autohide = false; + scrollbar.display = false; + } + cascade = s; + if (s) { + if (!scrollbar.viewport) + scrollbar.viewport = v_viewport; + var wprop = trapee.virtualhorizontal ? "width" : "contentwidth"; + v_viewport[0][wprop] ++= trapee.v_constrainPaneH; + } else { + scrollbar.viewport = null; + v_viewport[0].contentwidth --= trapee.v_constrainPaneH; + v_viewport[0].width --= trapee.v_constrainPaneH; + } + } + + /** toggle horizontal scrollbar */ + static.scrollverticalWrite = function(s) { + const scrollbar = trapee.th_vcroll; + const v_viewport = trapee.v_viewport; + if (s) { + scrollbar.autohide = trapee.autohidevertical; + } else { + scrollbar.autohide = false; + scrollbar.display = false; + } + cascade = s; + if (s) { + if (!scrollbar.viewport) + scrollbar.viewport = v_viewport; + v_viewport[0].contentheight ++= trapee.v_constrainPaneV; + } else { + scrollbar.viewport = null; + v_viewport[0].contentheight --= trapee.v_constrainPaneV; + } + } + + var max = vexi.math.max; + var min = vexi.math.min; + + /** return horizontal inset caused by vertical scrollbar */ + static.hinsetRead = function() { return trapee.th_vscroll.display ? trapee.th_vscroll.width : 0; } + + /** return vertical inset caused by horizontal scrollbar */ + static.vinsetRead = function() { return trapee.th_hscroll.display ? trapee.th_hscroll.height : 0; } + + /** return the height of the viewport */ + static.viewheightRead = function() { return trapee.v_viewport.height; } + + /** return the width of the viewport */ + static.viewwidthRead = function() { return trapee.v_viewport.width; } + + /** set the view x offset */ + static.viewxWrite = function(v) { + var vp = trapee.v_viewport; + var ox = max(0, min(v, vp[0].width - vp.width)); + vp[0].x = -ox; + return; + } + + /** fetch the view x offset */ + static.viewxRead = function() { return -trapee.v_viewport[0].x; } + + /** set the view y offset */ + static.viewyWrite = function(v) { + var vp = trapee.v_viewport; + var oy = max(0, min(v, vp[0].height - vp.height)); + vp[0].y = -oy; + return; + } + + /** fetch the view y offset */ + static.viewyRead = function() { return -trapee.v_viewport[0].y; } + +</vexi> Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/table.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/table.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/lib/widget/table.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,637 @@ +<!-- Copyright 2012 - see COPYING for details [LGPL] --> + +<vexi xmlns:ui="vexi://ui" + xmlns:lib="org.vexi.lib" + xmlns:util="vexi.util" + xmlns="vexi.theme"> + + <lib:role.focusable /> + <lib:widget.scrollpane /> + <ui:box enabled="true"> + + var max = vexi.math.max; + var min = vexi.math.min; + var ceil = vexi.math.ceil; + var floor = vexi.math.floor; + var maxdim = false; + var numrows = 0; + var sortby; + var sortasc = true; + var viewoffset; + var viewindex; + var viewfinal; + var activeindex; + var activefinal; + + thisbox.th_content; + thisbox.th_head; + thisbox.th_body; + thisbox.th_bodyport; + thisbox.th_foot; + thisbox.th_footview; + thisbox.th_bodyview; + thisbox.th_headview; + thisbox.th_hscroll; + thisbox.th_vscroll; + thisbox.fetchData; + thisbox.setViewInfo; + + // functions that should be forwarded onto th_body + thisbox.loadData = static.bodyNotSet; + thisbox.setFilter = static.bodyNotSet; + thisbox.setCompoundFilter = static.bodyNotSet; + + /***********************\ + * Dynamic table stuff * + \***********************/ + + thisbox.createRow = function() { return new rowtemplate(); } + + /** set the row template to use for new rows in loadData() */ + thisbox.rowtemplate ++= function(t) { + cascade = t; + rowheight = rowtemplate..rowheight; + } + + /** loads a set of data into the body of a table + * + * - data : an array of rows (themselves arrays of data) to load + * - index : the start index that the data represents + * - tempfirst : the first index of any temporary row data + * - tempfinal : the final index of any temporary row data + */ + var rows = []; + var loadDataFunc = function(data, index, tempindex, tempfinal) { + if (data == null) { + throw "tried to load null data"; + } + var b = th_body; + var n = b.numchildren; + var rlen = 0; + var check = {}; + var select; + // find unassigned rows + for (var i=0; n>i; i++) { + var r = b[i]; + var r_ind = r.rowindex; + if (r.selected and selectedindex==r_ind) { + // preserve selected row when scrolling + check[r_ind] = r; + } else if (viewindex>r_ind or r_ind>viewfinal) { + // discard rows that fall outside view + rows[rlen++] = r; + } else if (check[r_ind]) { + // check for duplicates and discard + if (vexi.debug) { + vexi.log.info("duplicate row: "+r_ind); + } + rows[rlen++] = r; + } else { + // row falls within view bounds + check[r_ind] = r; + if (selectedindex==r_ind) { + selected = r; + } + } + } + // limit display to those visible + var start = viewindex>index?viewindex-index:0; + var count = data.length; + if (count+index>viewfinal) { + count = viewfinal-index+1; + } + var fillEffect = th_body.fillEffect; + for (var i=start; count>i; i++) { + // assign new row + var r_ind = index+i; + var r = check[r_ind]; + if (r==null) { + r = rlen>0 ? rows[--rlen] : createRow(); + r.v_head = th_head; + r.rowindex = r_ind; + r.height = rowheight; + r.y = viewoffset + (rowheight*(r_ind-viewindex)); + // place row + if (activeindex>index) { + b[i-start] = r; + } else { + b[n] = r; + } + n++; + // select row if request + if (selectedindex==r_ind) { + selected = r; + } + } + r.rowindex = i; + r.value = data[i]; + // custom fillEffect implementations may be row data dependent + fillEffect(r, r_ind); + } + // clear up unused rows + while (rlen>0) { + rows[--rlen].thisbox = null; + } + if (tempindex == null) { + // no temporary rows - mark all as valid + activeindex = viewindex; + activefinal = viewfinal; + } else if (tempindex > viewindex and viewfinal > tempfinal) { + // temporary rows fall somewhere in the middle - invalidate all + activeindex = null; + activefinal = null; + } else if (tempindex == activeindex) { + // temporary rows at the start + activeindex = tempfinal; + activefinal = viewfinal; + } else { + // temporary rows at the end + activeindex = viewindex; + activefinal = tempfinal; + } + } + + var callFetchData = function(fetchfull) { + // establish the rows the table is attempting to view + viewindex = max(floor(viewy / rowheight), 0); + viewfinal = min(numrows-1, viewindex+floor(th_bodyport.height / rowheight)); + th_body.displayindex = viewindex; + if (setViewInfo) { + setViewInfo(viewindex, viewfinal-viewindex+1); + } + // keep body/rows in sync with bodyport + var b = th_body; + var n = b.numchildren; + b.height = height; + // our starting y position for offsetting rows + viewoffset = -(ceil(viewy)%rowheight); + for (var i=0; n>i; i++) { + r = b[i]; + if (r) { + if (fetchfull) { + r.y = -rowheight; + r.rowindex = -1; + continue; + } + var ind = r.rowindex; + if (ind>=viewindex and viewfinal>=ind) { + r.y = viewoffset + (rowheight*(ind-viewindex)); + } else { + r.y = -rowheight; + } + } + } + // establish fetching parameters + var fetchindex, fetchcount; + if (fetchfull or activeindex==null or activeindex>=viewfinal or viewindex>=activefinal) { + // fetch all the rows on display + fetchindex = viewindex; + fetchcount = viewfinal-viewindex+1; + } else if (activeindex==viewindex and activefinal==viewfinal) { + // repeat attempt to fetch rows on display + //util.common..logException("repeat: "+activeindex+"->"+activefinal); + return; + } else if (activeindex > viewindex) { + // previous display clips above desired display + fetchindex = viewindex; + fetchcount = activeindex-viewindex; + } else { + // previous display clips below desired display + fetchindex = activefinal+1; + fetchcount = viewfinal-activefinal; + } + if (0>=fetchcount) { + // nothing to fetch + return; + } + // establish sorting parameters + var sortcol = sortby ? th_head.indexof(sortby) : null; + if (sortcol == -1) { + sortcol = null; + } + var sortorder = sortcol == null ? null : sortasc; + // fetch and load returned data + var data = fetchData(fetchindex, fetchcount, sortcol, sortorder); + if (data) { + loadData(data, fetchindex, fetchcount); + } + } + + /** foces fetchData to be called with the current table settings */ + thisbox.forceFetchData = function(v) { callFetchData(true); return; } + + /** applied to properties likely to affect visible rows */ + var callrequired = true; + var trapToFetchData = function(v) { + if (callrequired and v!=trapee[trapname]) { + // cascade needs to occur after v!=trapee[trapname] + cascade = v; + callFetchData(); + } else { + cascade = v; + } + } + + /** attempt to select a row by index */ + var selectByIndex = function(i) { + if (i == null or rowcount == 0) { + cascade = null; + return; + } + // constrain i to relevant values + if (i >= rowcount) { + i = rowcount-1; + } + if (0 > i) { + i = 0; + } + if (i == selectedindex) { + return; + } + cascade = i; + var r_y = i*rowheight; + var v_y = viewy; + if (v_y > r_y) { + viewy = r_y; + } else if (r_y + rowheight > v_y + th_bodyport.height) { + viewy = r_y + rowheight - th_bodyport.height; + } + // we have to brute force this as box order is + // not consistent with row order after loading + var b = th_body; + var n = b.numchildren; + for (var j=0; n>j; j++) { + if (b[j].rowindex == i) { + selected = b[j]; + break; + } + } + } + + /** keep view synced with selected item */ + var scrollToSelected = function(v) { + cascade = v; + // make sure selected row is never cut off + if (v) { + if (v.y + v.height + th_bodyview.y > th_bodyport.height) { + viewy = v.y + v.height - th_bodyport.height; + } + if (0 > v.y + th_bodyview.y) { + viewy = v.y; + } + } + } + + /** turn this table into a large dynamic table */ + var fakeviewport; + var realviewport; + var initAsDynamic = function() { + if (fakeviewport) { + return; + } + // init dynamic stuff + if (rowtemplate==null) { + rowtemplate = .row; + } + fakeviewport = static.new_fakeviewport(); + realviewport = th_bodyport; + realviewport.shrink = false; + + fakeviewport[0].x ++= function(v) { + cascade = v; + realviewport[0].x = v; + }; + + th_viewport = fakeviewport; + th_bodyport = fakeviewport; + th_bodyview = fakeviewport[0]; + th_body.align = "topleft"; + th_body.initAsDynamic(); + th_vscroll.lineheight = rowheight; + + // [un]assign relevant traps + rowheight ++= static.rowheightWrite; + selectedindex ++= selectByIndex; + th_uiport.height ++= trapToFetchData; + th_bodyview.y ++= trapToFetchData; + th_body.selected --= scrollToSelected; + // initialize fakeviewport height + th_bodyport.height = realviewport.height; + } + + /** if fetchData is defined, become a large dynamic table */ + thisbox.fetchData ++= function(v) { + cascade = v; + initAsDynamic(); + } + + /** used for setting up dynamic tables */ + thisbox.rowcount ++= function(v) { + if (fetchData == null) { + throw "Define fetchData before assigning rowcount"; + } + if (v == numrows) { + return; + } + numrows = v; + cascade = v; + callrequired = false; + th_body.rowcount = v; + th_bodyview.height = rowheight * v; + callrequired = true; + if (numrows > 0) { + // fetch view contents + forceFetchData(); + return; + } + // clear view contents + viewindex = 0; + viewfinal = 0; + viewoffset = 0; + activeindex = 0; + activefinal = 0; + th_body.clear(); + th_body.displayindex = 0; + } + + /***************************\ + * END Dynamic table stuff * + \***************************/ + + thisbox.clear ++= static.clearRead; + + /** reset the contents of this table */ + thisbox.reset = function() { + th_body.clear(); + th_head.clear(); + if (sortby) { + sortby.sort = null; + } + sortby = null; + sortasc = null; + } + + /** sort into ascending order against column c */ + thisbox.sortAscending = function(c) { + if (typeof(c) == "number") { + c = th_head[c]; + } + sortby = c; + sortasc = false; + c.action = true; + } + + /** sort into descending order against column c */ + thisbox.sortDescending = function(c) { + if (typeof(c) == "number") { + c = th_head[c]; + } + sortby = c; + sortasc = true; + c.action = true; + } + + /** re-sort based on the current sort column */ + thisbox.sort = function() { + if (sortby==null) { + sortby = th_head[0]; + if (sortby==null) { + return; + } + sortasc = true; + } + sortby.action = true; + } + + /** sort by column when activated */ + var actionWrite = function(v) { + cascade = v; + vexi.thread = function(v) { + if (sortby and sortby != trapee) { + // relieve previous column + sortasc = false; + sortby.sort = null; + } + sortby = trapee; + // invoke column sorting + if (!sortasc) { + sortasc = true; + sortby.sort = "asc"; + if (fetchData) { + callFetchData(true); + } else { + th_body.sortAscending(th_head.indexof(trapee), trapee.datatype); + } + } else { + sortasc = false; + sortby.sort = "desc"; + if (fetchData) { + callFetchData(true); + } else { + th_body.sortDescending(th_head.indexof(trapee), trapee.datatype); + } + } + }; + } + + /** match column properties to column header properties */ + var col_propWrite = function(v) { + cascade = v; + var ind = th_head.indexof(trapee); + if (th_foot) { + for (var i,r in th_foot) + if (r[ind]) + r[ind][trapname] = v; + } + for (var i,r in th_body) + r[ind][trapname] = v; + } + + var setupRowContainer = function(c) { + /** assign v_head automatically */ + c.Children ++= function(r) { + if (r) { + r.v_head = th_head; + } else { + var oldr = trapee[trapname]; + if (oldr) { + oldr.v_head = null; + } + } + cascade = r; + }; + }; + + + /** set up table components */ + thisbox.v_container ++= function(v) { + cascade = v; + + if (th_deselect) { + th_deselect.Press1 ++= function(v) { + th_body.selected = null; + return; + } + } + + /** set up table components */ + v_content.Children ++= function(c) { + // set up column headers + if (c and c.v_table_type == "head") { + th_head = c; + th_headview[0] = c; + + // set up existing column headers + for (var i=0; c.numchildren > i; i++) { + var h = c[i]; + h.action ++= actionWrite; + h.width ++= col_propWrite; + h.display ++= col_propWrite; + h.hshrink ++= col_propWrite; + h.maxwidth ++= col_propWrite; + } + + // assign functions to new column headers + c.Children ++= function(h) { + if (h) { + h.action ++= actionWrite; + h.width ++= col_propWrite; + h.display ++= col_propWrite; + h.hshrink ++= col_propWrite; + h.maxwidth ++= col_propWrite; + } else { + var _h = c[trapname]; + if (_h) { + _h.action --= actionWrite; + _h.width --= col_propWrite; + _h.display --= col_propWrite; + _h.hshrink --= col_propWrite; + _h.maxwidth --= col_propWrite; + } + } + cascade = h; + }; + + c.headwidth ++= function(v) { + cascade = v; + var n = th_body.numchildren; + for (var i,r in th_body) + r.rowwidth = v; + for (var i,r in th_foot) + r.rowwidth = v; + } + return; + } + + // set up body content + if (c and c.v_table_type == "body") { + th_body = c; + c.shrink = false; + c.sort = sort; + util.redirect..addRedirect(thisbox, c, "selected", "selectedindex"); + if (!fetchData) { + // not a dynamic table + c.selected ++= scrollToSelected; + } + + thisbox.focused ++= static.focusWrite; + thisbox.KeyPressed ++= static.keypressWrite; + + setupRowContainer(c); + + // for access to relevant internal dimensions + c.rowheight ++= function() { return rowheight; } + c.viewportheight ++= function() { return th_bodyport.height; } + + // th_body required for loadData to work + thisbox.loadData = loadDataFunc; + + cascade = c; + return; + } + + // set up table footer + if (c and c.v_table_type == "foot") { + th_foot = c; + th_footview[0] = c; + + setupRowContainer(c); + return; + } + + cascade = c; + } + } + + /** simply sort again using current sort settings */ + thisbox.sort = function(col) { + if (col==null or sortby==null) { + return; + } + if (sortasc) { + sortAscending(sortby); + } else { + sortDescending(sortby); + } + } + + // apply static traps + + thisbox.viewx ++= static.viewxWrite; + + thisbox.setRowTemplate ++= util.common..noFunction; + + </ui:box> + + static.focusWrite = function(v) { + cascade = v; + if (trapee.th_body.selected) { + trapee.th_body.selected.focused = v; + } + } + + static.keypressWrite = function(v) { + if (vexi.ui.key.control) { + switch (v) { + case 'C-1': case 'C-2': case 'C-3': + case 'C-4': case 'C-5': case 'C-6': + case 'C-7': case 'C-8': case 'C-9': + var col = trapee.th_head[vexi.string.parseInt(v.charAt(2))-1]; + if (col) { + col.action = true; + } + return; + default: + break; + } + } + trapee.th_body.KeyPressed = v; + } + + /** be a little helpful if things are not set up correctly */ + static.bodyNotSet = function() { throw "th_body not set in lib.widget.table"; } + + /** reset the row contents of this table */ + static.clearRead = function() { return trapee.th_body.clear; } + + /** activate fetchData() when rowheight is set */ + static.rowheightWrite = function(v) { + if (!v) { + throw "rowtemplate..rowheight must be a valid integer (>0)"; + } + cascade = v; + trapee.th_vscroll.lineheight = rowheight; + if (trapee.fetchData) { + trapee.forceFetchData(); + } + } + + /** set the view y offset */ + static.viewxWrite = function(v) { + // let lib.scrollpane handle bodyview.x + cascade = v; + // once it is known, match up head/foot + th_headview.x = th_footview.x = th_bodyview.x; + } + +</vexi> Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/scrollpane.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/scrollpane.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/scrollpane.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,40 @@ +<!-- Copyright 2013 - see COPYING for details [LGPL] --> + +<vexi xmlns:ui="vexi://ui" + xmlns:role="org.vexi.lib.role" + xmlns:lib="org.vexi.lib.widget" + xmlns="vexi.theme"> + + <lib:scrollpane redirect=":$content"> + <ui:box orient="vertical"> + <role:draggable id="view" align="topleft" layout="place"> + Press3 ++= function(v) { trace("foo, "+trapee); cascade = v; } + <ui:box id="content" align="topleft" /> + </role:draggable> + <scrollbar id="hscroll" orient="horizontal" /> + </ui:box> + <ui:box orient="vertical" hshrink="true"> + <scrollbar id="vscroll" orient="vertical" /> + <ui:box id="inset" fill=":.settings..panefill" shrink="true" /> + </ui:box> + + thisbox.v_fillbox = $content; + thisbox.th_hscroll = $hscroll; + thisbox.th_vscroll = $vscroll; + thisbox.th_uiport = $view; + + $hscroll.height ++= function(v) { $inset.height = v; cascade = v; } + $vscroll.width ++= function(v) { $inset.width = v; cascade = v; } + + // REMARK: once the scrollbars are shown, they fix the minimum size + // in order to prevent a loop where the scrollbars appear increasing + // the size of $view beyond the content size, hiding the scrollbars + + $hscroll.contentwidth ++= function(v) { $view.minwidth = v; cascade = v; } + $vscroll.contentheight ++= function(v) { $view.minheight = v; cascade = v; } + + $hscroll.display ++= function(v) { $inset.display = (v and $vscroll.display); cascade = v; } + $vscroll.display ++= function(v) { $inset.display = (v and $hscroll.display); cascade = v; } + + </lib:scrollpane> +</vexi> Added: branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/textarea.t =================================================================== --- branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/textarea.t (rev 0) +++ branches/org.vexi-vexi.widgets_editrefactor/src_main/org/vexi/theme/classic/textarea.t 2013-03-14 02:36:20 UTC (rev 4489) @@ -0,0 +1,12 @@ +<!-- Copyright 2013 - see COPYING for details [LGPL] --> + +<vexi xmlns:lib="org.vexi.lib.text" + xmlns="vexi.theme"> + + <bevel redirect=":$content" fill="white" form="down"> + <scrollpane id="content" autohide="true" /> + + th_scroll = $scroll; + + </bevel> +</vexi> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_mar _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn