# -*- tcl -*- tcl.tk//DSL diagram//EN//1.0 set pad [5 mm] # XXX - put function call boxes into a procedure # XXX - put call/references styling into procedure, or variables ... # - procedure would use internal block to set everything up. proc labelframe {label script args} { variable pad return [block { text text $label down set X [block { east ; eval $script } with nw at [[last text sw] by $pad s]] box at [last block c] \ width [expr {$pad + [last block width]}] \ height [expr {$pad + [last block height]}] \ color red stroke 2 # fillcolor lightyellow - don't fill, order of drawing means that the inside elements are painted over, becoming invisible. # XXX need commands to control order -> raise/lower # Export the corners of the inner block as our corners. foreach v [$X names] { set $v [$X $v] } unset X } {*}$args] } proc connector {name corner {shape {}} {off {}}} { if {$shape eq {}} {set shape box} group { if {$off eq {}} { set connector [circle at [last $shape $corner] fillcolor gray radius 5] } else { switch -exact -- $corner { n { set l nw ; set r ne } s { set r sw ; set l se } w { set l nw ; set r sw } e { set r ne ; set l se } } set connector [circle \ at [$off between [last $shape $l] [last $shape $r]] \ fillcolor gray radius 5] } } # XXX should track through the upvar for proper look&feel. set $name [$connector $corner] return } proc S {from dir to args} { group { move from $from then $dir set P [last move end] set A [arrow from $from then $P then [$P | $to] to $to {*}$args] } return $A } proc SX {from dir to f args} { variable pad group { move from $from then $dir then $dir [expr {$f * $pad}] set P [last move end] set A [arrow from $from then $P then [$P | $to] to $to {*}$args] } return $A } proc Lx {from to args} { group { set A [arrow from $from then [$from | $to] to $to {*}$args] } return $A } proc Ly {from to args} { group { set A [arrow from $from then [$to | $from] to $to {*}$args] } return $A } proc GC {args} { return [labelframe "Generic Channelsystem" { text "\[\]" arrow <- text "call ChannelHandlers," "EventScripts" group { arrow <- "call" above box "Tcl_NotifyChannel" width [4 cm] connector TNC1 e {} 0.75 connector TNC2 e {} 0.25 down arrow <- "call" anchor nw down down down down down down color blue box "ChannelTimerProc" width [4 cm] connector CTP1 e {} 0.75 connector CTP2 e {} 0.5 connector CTP3 e {} 0.25 move move move box "UpdateInterest" width [4 cm] connector UI1 e {} 0.75 connector UI2 e {} 0.25 arrow from [0.5 between [1st last box nw] [1st last box n]] up up up "call" anchor ne color blue arrow from [0.5 between [2nd last box se] [2nd last box s]] down down down "call" anchor sw color blue } ; down arrow <- "setup" ljust text "\[fileevent\]" arrow from [last text s] then [[last text s] | [last box w]] to [last box w] color blue text "call" with nw at [[last arrow start] by $pad se] } {*}$args] } proc NFES {args} { return [labelframe "Notifier (Unix, File EventSource)" { box "Tcl_CreateFileHandler" width [5 cm] connector TCFH w ; up arrow "create" ljust ellipse "FileHandler" width [3 cm] fillcolor lightblue connector FH w ellipse arrow <- "query" ljust box "FileHandlerEventProc" width [5 cm] connector FHEP0 w connector FHEP1 n connector FHEP2 e right move box "Tcl_WaitForEvent" width [4 cm] connector TWFE0 e connector TWFE1 n down arrow "call" rjust color blue circle "select" arrow <- "timeout" rjust box "Tcl_SetMaxBlockTime" width [5 cm] connector TSMBT s } {*}$args] } proc CD {args} { return [labelframe "Channel Driver" { box "(WatchProc)" width [4 cm] connector WPinA w {} 0.25 connector WPinB w {} 0.75 connector WPout e } {*}$args] } proc TES {args} { return [labelframe "EventSource \"Timer\"" { box "Tcl_CreateTimerHandler" width [5 cm] connector TCTH1 w {} 0.75 connector TCTH2 w {} 0.5 connector TCTH3 w {} 0.25 up arrow "create" ljust ellipse "TimerHandler" width [3 cm] fillcolor lightblue connector TH w ellipse right arrow <- "query" above box "TimerSetupProc" width [4 cm] connector TSP0 e connector TSP1 n up ; move up right up right box "TimerCheckProc" width [4 cm] connector TCP0 e ; left connector TCP1 n ; left arrow <- "query" from [last ellipse nw] rjust up box "TimerHandlerEventProc" width [5 cm] down connector THEP1 w connector THEP2 e {} 0.75 connector THEP3 e {} 0.25 arrow "query" to [last ellipse ne] from [2nd last box sw] anchor se } {*}$args] } proc NGEQ {args} { return [labelframe "Notifier (Generic, EventQueue)" { box "Tcl_(Thread)QueueEvent" width [6 cm] connector TTQE0 w {} 0.15 connector TTQE1 w {} 0.35 connector TTQE2 w {} 0.55 connector TTQE3 w {} 0.75 down arrow "queue" ljust ellipse width [6 cm] height [4 cm] fillcolor lightblue right ; arrow <- "dequeue" above right box "Tcl_ServiceEvent" width [4 cm] ; down arrow <- "call" rjust color blue box "Tcl_DoOneEvent" width [4 cm] connector TDOE0 w connector TDOE1 s {} 0.9 connector TDOE2 s {} 0.8 text "EventQueue" with nw at [last ellipse nw] group { ellipse "File/Timer\nEvent" width [3 cm] with nw at [last ellipse center] } arrow "dispatch" anchor nw from [2nd last box w] to [last ellipse e] set D [last ellipse e] } {*}$args] } # ==================================================================================================== ## skeleton, the big blocks, and their placement set GC [GC] arrow <- from [$GC TNC1] then right [12 cm] "call" above color blue set NFES [NFES with FHEP0] arrow <- from [$NFES TCFH] then left "call" above color blue set CD [CD with WPout] arrow <- from [$GC CTP1] then right [12 cm] "call" above color blue set TES [TES with THEP1] arrow <- from [$NFES TWFE0] right [14 cm] "call" above color blue set NGEQ [NGEQ with TDOE0] # ==================================================================================================== ## All the additional interconnections #return set CDGC [S [$CD WPinA] left [$GC TNC2] color orange] arrow from [$NFES FH] "references" above \ to [intersect \ [move from [$NFES FH] to [by 100 west]] \ [move from [$CDGC 2] to [$CDGC 3]]] \ color orange set GCTES [SX [$GC CTP2] right [$TES TCTH3] 1 <- color orange] arrow from [$TES TH] "references" above \ to [intersect \ [move from [$TES TH] to [by 100 west]] \ [move from [$GCTES 2] to [$GCTES 3]]] \ color orange arrow from [$TES TSP1] to [$NFES TSMBT] "call" ljust color blue arrow <- from [$TES THEP2] up right up right right right color orange text "references" with se at [[Lx [last end] [$NGEQ TTQE2] - color orange] end] text "call" with nw at [[arrow from [$NGEQ D] then down down down down down to [$TES THEP3] color blue] end] text "call" with sw at [[arrow from [$NGEQ D] then down then left down left down left then left left left left left then [$NFES FHEP2] color blue] end] text "call" with nw at [[S [$GC CTP3] right [$TES TCTH2] color blue] start] text "call" with nw at [[SX [$GC UI2] right [$TES TCTH1] 4 color blue] start] text "call" with nw at [[SX [$GC UI1] right [$CD WPinB] 3 color blue] start] text "call" with sw at [[Lx [$TES TCP1] [$NGEQ TTQE3] color blue] start] text "call" with sw at [[Lx [$NFES TWFE1] [$NGEQ TTQE1] color blue] start] text "references" with se at [[Lx [$NFES FHEP1] [$NGEQ TTQE0] <- color orange] end] text "dispatch" with ne at [[Lx [$NGEQ TDOE1] [$TES TCP0]] start] text "dispatch" with nw at [[Lx [$NGEQ TDOE2] [$TES TSP0]] start]