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

Reply via email to