Index: Makefile.in =================================================================== diff -u -r2076ef459f42cdf6426522aab56be490b66c2436 -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 --- Makefile.in (.../Makefile.in) (revision 2076ef459f42cdf6426522aab56be490b66c2436) +++ Makefile.in (.../Makefile.in) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -237,8 +237,10 @@ $(src_doc_dir)/example-scripts/rosetta-serialization.html \ $(src_doc_dir)/example-scripts/rosetta-singleton.html \ $(src_doc_dir)/example-scripts/rosetta-unknown-method.html \ - $(src_doc_dir)/example-scripts/tk-mini.html \ $(src_doc_dir)/example-scripts/tk-horse-race.html \ + $(src_doc_dir)/example-scripts/tk-locomotive.html \ + $(src_doc_dir)/example-scripts/tk-mini.html \ + $(src_doc_dir)/example-scripts/tk-spread.html \ $(src_doc_dir)/example-scripts/traits-composite.html \ $(src_doc_dir)/example-scripts/traits-simple.html \ Index: TODO =================================================================== diff -u -r6ad7855cd7aba089f7a160293802e1639d0d6198 -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 --- TODO (.../TODO) (revision 6ad7855cd7aba089f7a160293802e1639d0d6198) +++ TODO (.../TODO) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -3620,20 +3620,20 @@ where 2 refcounted items are not freed (value:class, issued from nx.tcl around line 120). Compile with DEBUG86B2 for more info -================================================= -# -*- Tcl -*- -package req nx -package require nx::test + ================================================= + # -*- Tcl -*- + package req nx + package require nx::test -nx::Test case ensemble-next-with-colon-prefix { - nx::Object create obj { - :public method foo {} { return [:info class] } - #:public method bar {} { return [:info] } - :method info {} {;} - } - ? {obj foo} {wrong # args: should be ":info"} -} -================================================= + nx::Test case ensemble-next-with-colon-prefix { + nx::Object create obj { + :public method foo {} { return [:info class] } + #:public method bar {} { return [:info] } + :method info {} {;} + } + ? {obj foo} {wrong # args: should be ":info"} + } + ================================================= - nsf.c: cleanup on DEBUG86B2 @@ -3661,6 +3661,12 @@ - make "/object/ require" an ensemble method - traits: renamed "useTrait" into "require trait" +- added per-object traits (and per-class-object traits) +- added tk-spread and tk-locomotive to example scripts + + + + TODO: - ISSUE: Default-setting mechanism seems to be keen on the relative @@ -3690,7 +3696,6 @@ C setObjectParams {-second:alias {-first "X"}} ? {[C new -second Y] eval {set :first}} X; # NOT OK! should be 'Y'! - - add tk-spreadsheet and tk-railroad to example scripts - allow traits to be added to objects (maybe use :trait instead of "useTrait" and allow modifier "class") - naming of traits. Predefined traits have a leading "T" Index: doc/example-scripts/tk-locomotive.html =================================================================== diff -u --- doc/example-scripts/tk-locomotive.html (revision 0) +++ doc/example-scripts/tk-locomotive.html (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -0,0 +1,946 @@ + + + + + +Listing of doc/example-scripts/tk-locomotive.tcl + + + + + +
+
+
+

Example by <Richard Suchenwirth> +http://wiki.tcl.tk/1329

+
    +
  • +

    +translated from Tcl to XOTcl by gustaf neumann in 2001 +

    +
  • +
  • +

    +translated from XOTcl to NX by gustaf neumann in 2010 +

    +
  • +
+
+
+tk-locomotive.png +
+
+

Left mousebutton starts, middle slows down, right stops

+
+
+
package require Tk
+package require nx
+
+nx::Class create Wheel {
+  :property x
+  :property y
+  :property r
+  :property {spokes 24}
+  :property {pivot 0}
+  :property {color red}
+  :property {tag ""}
+
+  :public method drawSpokes {} {
+    ::nx::var import [:info parent] c alpha
+    set delta [expr {360.0 / ${:spokes}}]
+    set deg2arc [expr {atan(1.0)*8/360.}]
+    for {set i 0} {$i < ${:spokes}} {incr i} {
+      set x1 [expr {${:x} + cos($deg2arc*$alpha) * ${:r}}]
+      set y1 [expr {${:y} + sin($deg2arc*$alpha) * ${:r}}]
+      $c create line ${:x} ${:y} $x1 $y1 -fill ${:color} -tag spoke
+      set alpha [expr {$alpha + $delta}]
+    }
+    if {[info exists :act_pivot]} {
+      foreach {item perc} [set :act_pivot] break
+      set rp [expr {${:r} * $perc}]
+      set xp [expr {${:x} - $rp * cos($deg2arc * $alpha)}]
+      set yp [expr {${:y} - $rp * sin($deg2arc * $alpha)}]
+      $c coords $item $xp $yp [expr {$xp + 1}] [expr {$yp + 1}]
+    }
+  }
+
+  :method init {} {
+    ::nx::var import [:info parent] c alpha
+    set alpha 0.
+
+    set :y [expr {${:y} - ${:r}}]
+    $c create oval \
+        [expr {${:x} - ${:r}}] [expr {${:y} - ${:r}}] \
+        [expr {${:x} + ${:r}}] [expr {${:y} + ${:r}}] \
+        -outline white
+    set r1 [expr {${:r}-2}]
+    set W [$c create oval \
+               [expr {${:x} - $r1}] [expr {${:y} - $r1}] \
+               [expr {${:x} + $r1}] [expr {${:y} + $r1}] \
+               -outline ${:color} -width 2]
+    :drawSpokes
+
+    if {${:pivot}} {
+      set deg2arc [expr {atan(1.0) * 8 / 360.0}]
+      set rp [expr {$r1*${:pivot}}]
+      set xp [expr {${:x} - $rp * cos($deg2arc * $alpha)}]
+      set yp [expr {${:y} - $rp * sin($deg2arc * $alpha)}]
+      set new_pivot [$c create rect $xp $yp [expr {$xp + 1}] [expr {$yp + 1}] \
+                         -fill ${:color} -tag [list ${:tag} pivot]]
+      set :act_pivot [list $new_pivot ${:pivot}]
+
+      $c create arc [expr {${:x} - $r1}] [expr {${:y} - $r1}]\
+          [expr {${:x} + $r1}] [expr {${:y} + $r1}] \
+          -style chord -fill ${:color} -start 310 \
+          -extent 80 -tag counterweight
+      set :pivot $new_pivot
+    }
+    set rh [expr {${:r} / 12.0}]
+    $c create oval \
+        [expr {${:x} - $rh}] [expr {${:y} - $rh}] \
+        [expr {${:x} + $rh}] [expr {${:y} + $rh}] \
+        -fill white -tag hub
+    set :r $r1
+  }
+}
+
+
+nx::Class create Locomotive {
+  :property {speed 4}
+
+  :method turn {} {
+    set :alpha [expr {round(${:alpha} + 360 - ${:speed}) % 360}]
+    foreach i [${:c} find withtag counterweight] {
+      ${:c} itemconfig $i -start [expr {310 - ${:alpha}}]
+    }
+    ${:c} delete spoke
+    foreach wheel [:info children] { $wheel drawSpokes }
+    ${:c} raise hub
+    set xp0 [expr {105 + 15 * sin((${:alpha} - 90) * atan(1.0) * 8 / 360)}]
+    ${:c} delete piston
+    ${:c} coords p0 $xp0 120 [expr {$xp0+2}] 122 ;#CW
+    ${:c} create line 90 121 $xp0 121 -width 2 -fill white -tag piston ;#CW
+    :drawRod p0 p1 p2 p3
+    ${:c} raise p0
+    foreach i [${:c} find withtag smoke] {
+      if {[lindex [${:c} bbox $i] 3]<0} {
+        ${:c} delete $i
+      } else {
+        ${:c} move $i [expr {rand() * ${:speed} / 3.0}] [expr {rand() * 2 - 2}]
+      }
+    }
+    set t [${:c} create oval [${:c} bbox chimney] -fill white -outline white -tag smoke]
+    ${:c} move $t 0 -10
+    ${:c} lower smoke
+  }
+
+  :method drawRod {p0 p1 p2 p3} {
+    ${:c} delete rod
+    ${:c} create rect [${:c} bbox $p1 $p3] -fill white -tag rod
+    ${:c} create line {*}[lrange [${:c} bbox $p0] 0 1] \
+        {*}[lrange [${:c} bbox $p2] 0 1] -width 3 -fill white -tag rod
+    ${:c} raise rod
+    ${:c} raise pivot
+  }
+
+  :public method tick {} {
+    :turn
+    foreach i [after info] {after cancel $i}
+    after 10 [self] tick
+  }
+
+  :public method throttle {} {
+    incr :speed 2
+    :tick
+  }
+
+  :public method break {} {
+    incr :speed -2
+    if {${:speed}<0} {set :speed 0}
+    :tick
+  }
+
+  :public method emergencyBreak {} {
+    set :speed 0
+    :tick
+  }
+
+  :method init {} {
+    set :c [canvas .c -width 600 -height 160 -background lightblue]
+    pack ${:c}
+
+    bind ${:c} <1> [list [self] throttle]
+    bind ${:c} <2> [list [self] break]
+    bind ${:c} <3> [list [self] emergencyBreak]
+
+    ${:c} delete all
+    ${:c} create rect 32 115 360 125 -fill black ;# frame
+    ${:c} create rect 22 118 32 122 -fill grey30 ;# buffer
+    ${:c} create line 22 115 22 125
+    ${:c} create poly 60 95 40 115 50 115 70 95 -fill black
+    ${:c} create rect 60 45 310 95 -fill grey25 ;# boiler
+    ${:c} create oval 55 50 65 90 -fill black ;# smokebox
+    ${:c} create rect 70 32 85 50 -fill black -tag chimney
+    ${:c} create rect 40 52 90 75 -fill black ;# wind diverter
+    ${:c} create oval 130 36 150 52 -fill black ;# dome
+    ${:c} create rect 195 35 215 50 -fill black ;# sandbox
+    ${:c} create oval 260 36 280 52 -fill black ;# dome
+    ${:c} create rect 65 100 90 135 -fill black ;# cylinder
+    ${:c} create rect 90 120 92 122 -fill red -tag p0 ;# crossbar
+    ${:c} create rect 72 87 82 100 -fill black ;# steam tube
+    ${:c} create rect 310 40 370 115 -fill black ;# cab
+    ${:c} create rect 310 32 390 42 -fill grey30 ;# cab roof
+    ${:c} create text 338 82 -text "01 234" -fill gold -font {Times 7}
+    ${:c} create rect 318 48 333 66 -fill white ;# cab window #1
+    ${:c} create rect 338 48 355 66 -fill white ;# cab window #2
+    Wheel new -childof [self] -x 50 -y 150 -r 13 -spokes 12
+    Wheel new -childof [self] -x 105 -y 150 -r 13 -spokes 12
+    Wheel new -childof [self] -x 150 -y 150 -r 30 -pivot 0.5 -tag p1
+    Wheel new -childof [self] -x 215 -y 150 -r 30 -pivot 0.5 -tag p2
+    Wheel new -childof [self] -x 280 -y 150 -r 30 -pivot 0.5 -tag p3
+    :drawRod p0 p1 p2 p3
+    Wheel new -childof [self] -x 340 -y 150 -r 16 -spokes 12
+    ${:c} create rect 360 110 380 118 -fill black
+    ${:c} create rect 380 65 560 125 -fill black -tag tender
+    ${:c} create rect 560 118 570 122 -fill grey30 ;# buffer
+    ${:c} create line 571 116 571 125
+    ${:c} create rect 390 45 525 65 -fill black -tag tender
+    Wheel new -childof [self] -x 395 -y 150 -r 13 -spokes 12
+    Wheel new -childof [self] -x 440 -y 150 -r 13 -spokes 12
+    ${:c} create rect 380 132 456 142 -fill red
+    Wheel new -childof [self] -x 495 -y 150 -r 13 -spokes 12
+    Wheel new -childof [self] -x 540 -y 150 -r 13 -spokes 12
+    ${:c} create rect 480 132 556 142 -fill red -outline red
+    ${:c} create rect 0 150 600 160 -fill brown ;# earth
+    ${:c} create line 0 150 600 150 -fill grey -width 2 ;# rail
+    :tick
+  }
+}
+
+Locomotive new
+
+
+
+

+ + + Index: doc/example-scripts/tk-locomotive.png =================================================================== diff -u Binary files differ Index: doc/example-scripts/tk-locomotive.tcl =================================================================== diff -u --- doc/example-scripts/tk-locomotive.tcl (revision 0) +++ doc/example-scripts/tk-locomotive.tcl (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -0,0 +1,196 @@ +# +# Example by +# http://wiki.tcl.tk/1329 +# +# - translated from Tcl to XOTcl by gustaf neumann in 2001 +# - translated from XOTcl to NX by gustaf neumann in 2010 +# +# image::tk-locomotive.png[] +# +# Left mousebutton starts, middle slows down, right stops +# +package require Tk +package require nx + +nx::Class create Wheel { + :property x + :property y + :property r + :property {spokes 24} + :property {pivot 0} + :property {color red} + :property {tag ""} + + :public method drawSpokes {} { + ::nx::var import [:info parent] c alpha + set delta [expr {360.0 / ${:spokes}}] + set deg2arc [expr {atan(1.0)*8/360.}] + for {set i 0} {$i < ${:spokes}} {incr i} { + set x1 [expr {${:x} + cos($deg2arc*$alpha) * ${:r}}] + set y1 [expr {${:y} + sin($deg2arc*$alpha) * ${:r}}] + $c create line ${:x} ${:y} $x1 $y1 -fill ${:color} -tag spoke + set alpha [expr {$alpha + $delta}] + } + if {[info exists :act_pivot]} { + foreach {item perc} [set :act_pivot] break + set rp [expr {${:r} * $perc}] + set xp [expr {${:x} - $rp * cos($deg2arc * $alpha)}] + set yp [expr {${:y} - $rp * sin($deg2arc * $alpha)}] + $c coords $item $xp $yp [expr {$xp + 1}] [expr {$yp + 1}] + } + } + + :method init {} { + ::nx::var import [:info parent] c alpha + set alpha 0. + + set :y [expr {${:y} - ${:r}}] + $c create oval \ + [expr {${:x} - ${:r}}] [expr {${:y} - ${:r}}] \ + [expr {${:x} + ${:r}}] [expr {${:y} + ${:r}}] \ + -outline white + set r1 [expr {${:r}-2}] + set W [$c create oval \ + [expr {${:x} - $r1}] [expr {${:y} - $r1}] \ + [expr {${:x} + $r1}] [expr {${:y} + $r1}] \ + -outline ${:color} -width 2] + :drawSpokes + + if {${:pivot}} { + set deg2arc [expr {atan(1.0) * 8 / 360.0}] + set rp [expr {$r1*${:pivot}}] + set xp [expr {${:x} - $rp * cos($deg2arc * $alpha)}] + set yp [expr {${:y} - $rp * sin($deg2arc * $alpha)}] + set new_pivot [$c create rect $xp $yp [expr {$xp + 1}] [expr {$yp + 1}] \ + -fill ${:color} -tag [list ${:tag} pivot]] + set :act_pivot [list $new_pivot ${:pivot}] + + $c create arc [expr {${:x} - $r1}] [expr {${:y} - $r1}]\ + [expr {${:x} + $r1}] [expr {${:y} + $r1}] \ + -style chord -fill ${:color} -start 310 \ + -extent 80 -tag counterweight + set :pivot $new_pivot + } + set rh [expr {${:r} / 12.0}] + $c create oval \ + [expr {${:x} - $rh}] [expr {${:y} - $rh}] \ + [expr {${:x} + $rh}] [expr {${:y} + $rh}] \ + -fill white -tag hub + set :r $r1 + } +} + + +nx::Class create Locomotive { + :property {speed 4} + + :method turn {} { + set :alpha [expr {round(${:alpha} + 360 - ${:speed}) % 360}] + foreach i [${:c} find withtag counterweight] { + ${:c} itemconfig $i -start [expr {310 - ${:alpha}}] + } + ${:c} delete spoke + foreach wheel [:info children] { $wheel drawSpokes } + ${:c} raise hub + set xp0 [expr {105 + 15 * sin((${:alpha} - 90) * atan(1.0) * 8 / 360)}] + ${:c} delete piston + ${:c} coords p0 $xp0 120 [expr {$xp0+2}] 122 ;#CW + ${:c} create line 90 121 $xp0 121 -width 2 -fill white -tag piston ;#CW + :drawRod p0 p1 p2 p3 + ${:c} raise p0 + foreach i [${:c} find withtag smoke] { + if {[lindex [${:c} bbox $i] 3]<0} { + ${:c} delete $i + } else { + ${:c} move $i [expr {rand() * ${:speed} / 3.0}] [expr {rand() * 2 - 2}] + } + } + set t [${:c} create oval [${:c} bbox chimney] -fill white -outline white -tag smoke] + ${:c} move $t 0 -10 + ${:c} lower smoke + } + + :method drawRod {p0 p1 p2 p3} { + ${:c} delete rod + ${:c} create rect [${:c} bbox $p1 $p3] -fill white -tag rod + ${:c} create line {*}[lrange [${:c} bbox $p0] 0 1] \ + {*}[lrange [${:c} bbox $p2] 0 1] -width 3 -fill white -tag rod + ${:c} raise rod + ${:c} raise pivot + } + + :public method tick {} { + :turn + foreach i [after info] {after cancel $i} + after 10 [self] tick + } + + :public method throttle {} { + incr :speed 2 + :tick + } + + :public method break {} { + incr :speed -2 + if {${:speed}<0} {set :speed 0} + :tick + } + + :public method emergencyBreak {} { + set :speed 0 + :tick + } + + :method init {} { + set :c [canvas .c -width 600 -height 160 -background lightblue] + pack ${:c} + + bind ${:c} <1> [list [self] throttle] + bind ${:c} <2> [list [self] break] + bind ${:c} <3> [list [self] emergencyBreak] + + ${:c} delete all + ${:c} create rect 32 115 360 125 -fill black ;# frame + ${:c} create rect 22 118 32 122 -fill grey30 ;# buffer + ${:c} create line 22 115 22 125 + ${:c} create poly 60 95 40 115 50 115 70 95 -fill black + ${:c} create rect 60 45 310 95 -fill grey25 ;# boiler + ${:c} create oval 55 50 65 90 -fill black ;# smokebox + ${:c} create rect 70 32 85 50 -fill black -tag chimney + ${:c} create rect 40 52 90 75 -fill black ;# wind diverter + ${:c} create oval 130 36 150 52 -fill black ;# dome + ${:c} create rect 195 35 215 50 -fill black ;# sandbox + ${:c} create oval 260 36 280 52 -fill black ;# dome + ${:c} create rect 65 100 90 135 -fill black ;# cylinder + ${:c} create rect 90 120 92 122 -fill red -tag p0 ;# crossbar + ${:c} create rect 72 87 82 100 -fill black ;# steam tube + ${:c} create rect 310 40 370 115 -fill black ;# cab + ${:c} create rect 310 32 390 42 -fill grey30 ;# cab roof + ${:c} create text 338 82 -text "01 234" -fill gold -font {Times 7} + ${:c} create rect 318 48 333 66 -fill white ;# cab window #1 + ${:c} create rect 338 48 355 66 -fill white ;# cab window #2 + Wheel new -childof [self] -x 50 -y 150 -r 13 -spokes 12 + Wheel new -childof [self] -x 105 -y 150 -r 13 -spokes 12 + Wheel new -childof [self] -x 150 -y 150 -r 30 -pivot 0.5 -tag p1 + Wheel new -childof [self] -x 215 -y 150 -r 30 -pivot 0.5 -tag p2 + Wheel new -childof [self] -x 280 -y 150 -r 30 -pivot 0.5 -tag p3 + :drawRod p0 p1 p2 p3 + Wheel new -childof [self] -x 340 -y 150 -r 16 -spokes 12 + ${:c} create rect 360 110 380 118 -fill black + ${:c} create rect 380 65 560 125 -fill black -tag tender + ${:c} create rect 560 118 570 122 -fill grey30 ;# buffer + ${:c} create line 571 116 571 125 + ${:c} create rect 390 45 525 65 -fill black -tag tender + Wheel new -childof [self] -x 395 -y 150 -r 13 -spokes 12 + Wheel new -childof [self] -x 440 -y 150 -r 13 -spokes 12 + ${:c} create rect 380 132 456 142 -fill red + Wheel new -childof [self] -x 495 -y 150 -r 13 -spokes 12 + Wheel new -childof [self] -x 540 -y 150 -r 13 -spokes 12 + ${:c} create rect 480 132 556 142 -fill red -outline red + ${:c} create rect 0 150 600 160 -fill brown ;# earth + ${:c} create line 0 150 600 150 -fill grey -width 2 ;# rail + :tick + } +} + +Locomotive new Index: doc/example-scripts/tk-spread.html =================================================================== diff -u --- doc/example-scripts/tk-spread.html (revision 0) +++ doc/example-scripts/tk-spread.html (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -0,0 +1,887 @@ + + + + + +Listing of doc/example-scripts/tk-spread.tcl + + + + + +
+
+
+

A small Spreadsheet implementation, originally developed by Richard +Suchenwirth in plain Tcl (see http://wiki.tcl.tk/1287). The +spreadsheet was rewritten in an object oriented manner as a design +study in NX by Gustaf Neumann in May 2011.

+
+
+tk-spread.png +
+
+
+
+
package require Tk
+package require nx::callback
+
+ ##############################################################################
+ # Class SpreadSheet
+ #
+ # The SpreadSheet computes simply totals for rows and columns.
+ ##############################################################################
+ nx::Class create SpreadSheet {
+   #
+   # The following attributes can be used for configuring the
+   # spreadsheet.
+   #
+   :property {rows:integer 3}
+   :property {cols:integer 2}
+   :property {width:integer 8}
+
+   #
+   # If no widget is provided, use the name of the object as widget
+   # name.
+   #
+   :property {widget ".[namespace tail [self]]"}
+
+   #
+   # Use the nx callback trait
+   #
+   :require trait nx::TCallback
+
+   #
+   # The method "cell" hides the internal respresentation and sets a
+   # cell to a value.
+   #
+   :method cell {pair value} {
+     set :data($pair) $value
+   }
+
+   #
+   # The constructor builds the SpreadSheet matrix via multiple text
+   # entry fields.
+   #
+   :method init {} {
+     set :last ${:rows},${:cols}  ;# keep grand total field
+     trace var [:bindvar data] w [:callback redo]
+     frame ${:widget}
+     for {set y 0} {$y <= ${:rows}} {incr y} {
+       set row [list]
+       for {set x 0} {$x <= ${:cols}} {incr x} {
+         set e [entry ${:widget}.$y,$x -width ${:width} \
+                    -textvar [:bindvar data($y,$x)] -just right]
+         if {$x==${:cols} || $y==${:rows}} {
+           $e config -state disabled -background grey -relief flat
+         }
+         lappend row $e
+       }
+       grid {*}$row -sticky news
+     }
+     $e config -relief solid
+   }
+
+   #
+   # The method "redo" is triggered via the updates in the cells
+   #
+   :public method redo {varname el op} {
+     if {$el ne ${:last}} {
+       lassign [split $el ,] y x
+       if {$x ne ""} {
+         :sum $y,* $y,${:cols}
+         :sum *,$x ${:rows},$x
+       } ;# otherwise 'el' was not a cell index
+     }   ;# prevent endless recalculation of grand total
+   }
+
+   #
+   # The method "sum" adds the values matched by pattern (typically a
+   # row or column) and sets finally the target column with the total
+   #
+   :method sum {pat target} {
+     set sum 0
+     set total "" ;# default if no addition succeeds
+     foreach {i value} [array get :data $pat] {
+       if {$i != $target} {
+         if {[string is double -strict $value]} {
+           set total [set sum [expr {$sum + $value}]]
+         }
+       }
+     }
+     :cell $target $total
+   }
+ }
+

Build spreadsheet "x"

+
+
+
SpreadSheet create x {
+   # populate with some values
+   :cell 0,0 Spread1
+   :cell 1,0 47
+   :cell 2,1 11
+ }
+

Build spreadsheet "y"

+
+
+
SpreadSheet create y -rows 4 -cols 4 {
+   :cell 0,0 Spread2
+   :cell 1,0 12
+   :cell 2,2 22
+ }
+

Pack the spreadsheets into one pane

+
+
+
pack [x widget] [y widget] -fill both
+
+
+
+

+ + + Index: doc/example-scripts/tk-spread.png =================================================================== diff -u Binary files differ Index: doc/example-scripts/tk-spread.tcl =================================================================== diff -u --- doc/example-scripts/tk-spread.tcl (revision 0) +++ doc/example-scripts/tk-spread.tcl (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -0,0 +1,115 @@ +# A small Spreadsheet implementation, originally developed by Richard +# Suchenwirth in plain Tcl (see http://wiki.tcl.tk/1287). The +# spreadsheet was rewritten in an object oriented manner as a design +# study in NX by Gustaf Neumann in May 2011. +# +# image::tk-spread.png[] +# +package require Tk +package require nx::callback + + ############################################################################## + # Class SpreadSheet + # + # The SpreadSheet computes simply totals for rows and columns. + ############################################################################## + nx::Class create SpreadSheet { + # + # The following attributes can be used for configuring the + # spreadsheet. + # + :property {rows:integer 3} + :property {cols:integer 2} + :property {width:integer 8} + + # + # If no widget is provided, use the name of the object as widget + # name. + # + :property {widget ".[namespace tail [self]]"} + + # + # Use the nx callback trait + # + :require trait nx::TCallback + + # + # The method "cell" hides the internal respresentation and sets a + # cell to a value. + # + :method cell {pair value} { + set :data($pair) $value + } + + # + # The constructor builds the SpreadSheet matrix via multiple text + # entry fields. + # + :method init {} { + set :last ${:rows},${:cols} ;# keep grand total field + trace var [:bindvar data] w [:callback redo] + frame ${:widget} + for {set y 0} {$y <= ${:rows}} {incr y} { + set row [list] + for {set x 0} {$x <= ${:cols}} {incr x} { + set e [entry ${:widget}.$y,$x -width ${:width} \ + -textvar [:bindvar data($y,$x)] -just right] + if {$x==${:cols} || $y==${:rows}} { + $e config -state disabled -background grey -relief flat + } + lappend row $e + } + grid {*}$row -sticky news + } + $e config -relief solid + } + + # + # The method "redo" is triggered via the updates in the cells + # + :public method redo {varname el op} { + if {$el ne ${:last}} { + lassign [split $el ,] y x + if {$x ne ""} { + :sum $y,* $y,${:cols} + :sum *,$x ${:rows},$x + } ;# otherwise 'el' was not a cell index + } ;# prevent endless recalculation of grand total + } + + # + # The method "sum" adds the values matched by pattern (typically a + # row or column) and sets finally the target column with the total + # + :method sum {pat target} { + set sum 0 + set total "" ;# default if no addition succeeds + foreach {i value} [array get :data $pat] { + if {$i != $target} { + if {[string is double -strict $value]} { + set total [set sum [expr {$sum + $value}]] + } + } + } + :cell $target $total + } + } + +# Build spreadsheet "x" +SpreadSheet create x { + # populate with some values + :cell 0,0 Spread1 + :cell 1,0 47 + :cell 2,1 11 + } + +# Build spreadsheet "y" +SpreadSheet create y -rows 4 -cols 4 { + :cell 0,0 Spread2 + :cell 1,0 12 + :cell 2,2 22 + } + +# Pack the spreadsheets into one pane +pack [x widget] [y widget] -fill both + Index: library/lib/pkgIndex.tcl =================================================================== diff -u -r2076ef459f42cdf6426522aab56be490b66c2436 -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 --- library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision 2076ef459f42cdf6426522aab56be490b66c2436) +++ library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) @@ -16,5 +16,5 @@ package ifneeded nx::doc::xowiki 1.0 [list source [file join $dir nxdoc-xowiki.tcl]] package ifneeded nx::pp 1.0 [list source [file join $dir pp.tcl]] package ifneeded nx::test 1.0 [list source [file join $dir test.tcl]] -package ifneeded nx::trait 0.1 [list source [file join $dir nx-traits.tcl]] +package ifneeded nx::trait 0.2 [list source [file join $dir nx-traits.tcl]] package ifneeded nx::zip 1.1 [list source [file join $dir nx-zip.tcl]]