From 4c27f675010da7c0bad2ba1590fb145d189d31de Mon Sep 17 00:00:00 2001 From: Mark Roseman Date: Wed, 7 Dec 2011 15:28:43 -0700 Subject: [PATCH] start of canvas, event bindings; added -wtkoption and _sendWhenCreated to further simplify option handlings that just send javascript messages off to the browser --- wtk-base.tcl | 24 +++++++++++++++++++++--- wtk-widgets.tcl | 33 +++++++++++++++++++++++++++++---- wtk.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/wtk-base.tcl b/wtk-base.tcl index 0ac60c4..8fe56f9 100644 --- a/wtk-base.tcl +++ b/wtk-base.tcl @@ -34,7 +34,7 @@ namespace eval ::wtk { # that use -text or -textvariable, though not every widget will do so. snit::type Widget { - variable id; variable created; variable wobj + variable id; variable created; variable wobj; variable postcreatemsgs "" constructor {_wobj} { if {$_wobj==""} {set _wobj $self}; # used for root window only set wobj $_wobj @@ -46,10 +46,14 @@ namespace eval ::wtk { method _created? {} {return $created} method _create {} { set js [$wobj _createjs] + append js $postcreatemsgs; set postcreatemsgs "" wtk::toclient $js set created 1 return "" } + method _sendWhenCreated {msg} {if {[$self _created?]} {wtk::toclient $msg} else {append postcreatemsgs $msg}} + + method id {} {return $id} method jqobj {} {return "\$('#[$self id]')"} method jsobj {} {return "wtk.widgets\['[$self id]'\]"} @@ -83,8 +87,14 @@ namespace eval ::wtk { $self _setuptextvar } - # variable handling; only relevant if -variable option is delegated to us + # TODO - variable handling; only relevant if -variable option is delegated to us + + + # bindings + variable bindings + method _bind {ev script} {set bindings($ev) $script} + method _fireevent {ev subs} {if {[info exists bindings($ev)]} {uplevel #0 [string map $subs $bindings($ev)]}} } proc getwidget {id} {return $wtk::wobj($id)} @@ -92,7 +102,7 @@ namespace eval ::wtk { proc wm {args} {if {[lindex $args 0]=="title" && [lindex $args 1]=="."} {toclient "document.title='[lindex $args 2]';"}; return ""; # placeholder} proc winfo {args} {; # placeholder} proc focus {w} {$w _focus; return ""} - proc bind {args} {; # placeholder} + proc bind {w ev script} {return [$w _bind $ev $script]} # Macro that can be used to simplify the definition of any widget snit::macro _stdwidget {} { @@ -105,5 +115,13 @@ namespace eval ::wtk { component W; delegate method * to W; delegate option -textvariable to W; delegate option -text to W constructor {args} {install W using Widget %AUTO% $self; $self configurelist $args; $W _setuptextvar} } + + + # Macro used to define options which set their value and then send some Javascript command to the widget + snit::macro _wtkoption {opt default msg} { + option $opt -default $default -configuremethod _wtkoption$opt + method _wtkoption$opt {opt val} "set options(\$opt) \$val; set JS \[\$self jsobj\]; set V \$val; \$self _sendWhenCreated \[subst [list $msg]\]" + } + } diff --git a/wtk-widgets.tcl b/wtk-widgets.tcl index 2620830..ef6728c 100644 --- a/wtk-widgets.tcl +++ b/wtk-widgets.tcl @@ -74,11 +74,10 @@ namespace eval ::wtk { # Entry widgets snit::type entry { _textvarwidget - option -width -configuremethod _widthchanged - method _createjs {} {set r "wtk.createEntry('[$self id]','[$self cget -text]');"; if {$options(-width)!=""} {append r "[$self jsobj].size=$options(-width);"};return $r} + _wtkoption -width "" {$JS.size=$V;} + method _createjs {} {return "wtk.createEntry('[$self id]','[$self cget -text]');"} method _textchangejs {txt} {return "[$self jqobj].val('$txt');"} method _event {which args} {if {$which eq "value"} {$self _textchanged -text $args 1}} - method _widthchanged {opt val} {set options($opt) $val; if {[$self _created?]} {wtk::toclient "[$self jsobj].size=$val;"}} } @@ -88,4 +87,30 @@ namespace eval ::wtk { option -padding method _createjs {} {return "wtk.createFrame('[$self id]');"} } -} \ No newline at end of file + + + # Canvas + snit::type canvas { + variable mousedown 0 + variable nextid 1 + variable items + _stdwidget + _wtkoption -width 100 {$JS.width=$V;$JS.style.width='${V}px';} + _wtkoption -height 100 {$JS.height=$V;$JS.style.height='${V}px';} + _wtkoption -background "#ffffff" {$JS.style.background='$V';} + + method _createjs {} {return "wtk.createCanvas('[$self id]');"} + method create {objtype x0 y0 x1 y1 args} { + set cid $nextid; incr nextid + set items($cid) [list type $objtype coords [list $x0 $y0 $x1 $y1]] + wtk::toclient "wtk.canvasCreateItem('[$self id]',$cid,'$objtype',$x0,$y0,$x1,$y1);" + return $cid + } + method _event {which args} {; # todo - make generic + if {$which=="mousedown"} {set mousedown 1; $W _fireevent "<1>" [list %x [lindex $args 0] %y [lindex $args 1]]} + if {$which=="mousemove"} {if {$mousedown} {set ev ""} else {set ev ""}; $W _fireevent $ev [list %x [lindex $args 0] %y [lindex $args 1]]} + if {$which=="mouseup"} {set mousedown 0; $W _fireevent "" [list %x [lindex $args 0] %y [lindex $args 1]]} + } + } + +} diff --git a/wtk.js b/wtk.js index 8aba104..903c320 100644 --- a/wtk.js +++ b/wtk.js @@ -1,6 +1,7 @@ var wtk = { widgets : new Array(), + widgetInfo : new Array(), /* * Initialize, and manage two AJAX connections to the server; one is used to send @@ -64,5 +65,35 @@ var wtk = { wtk.widgets[parent].appendChild(w); }, + /* + * Canvas + */ + + createCanvas : function(id) { + var w = wtk.CreateWidget(id,'canvas', '', ''); + w.width = 100; w.height = 100; w.style.width = '100px'; w.style.height = '100px'; + w.style.background = '#ffffff'; + w.style.position = 'relative'; + w.style.cursor = 'default'; + w.onmousedown = function(ev) {wtk.canvasMouse(ev, id, 'mousedown');} + w.onmousemove = function(ev) {wtk.canvasMouse(ev, id, 'mousemove');} + w.onmouseup = function(ev) {wtk.canvasMouse(ev, id, 'mouseup');} + w.ondrag = function(ev) {wtk.canvasMouse(ev, id, 'drag');} + wtk.widgetInfo[id] = {items:[]}; + }, + + canvasMouse : function(ev, id, action) { + wtk.sendto('EVENT '+id+' '+action+' '+(ev.pageX-wtk.widgets[id].offsetLeft)+' '+(ev.pageY-wtk.widgets[id].offsetTop)+' '+ev.button); + }, + + canvasCreateItem : function(id, cid, type, x0, y0, x1, y1) { + wtk.widgetInfo[id].items[cid] = {type:type, x0:x0, y0:y0, x1:x1, y1:y1}; + var ctx = wtk.widgets[id].getContext("2d"); + ctx.fillStyle='#ff0000'; + ctx.lineWidth = 3; + ctx.lineCap = 'round'; + if (type=="line") {ctx.moveTo(x0,y0);ctx.lineTo(x1,y1);ctx.stroke();} + } + };