File: blt2d.tcl

package info (click to toggle)
moodss 5.0-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 1,104 kB
  • ctags: 430
  • sloc: tcl: 12,266; sh: 59; makefile: 43
file content (166 lines) | stat: -rw-r--r-- 8,026 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# copyright (C) 1997-98 Jean-Luc Fontaine (mailto:jfontain@mygale.org)
# this program is free software: please read the COPYRIGHT file enclosed in this package or use the Help Copyright menu

set rcsId {$Id: blt2d.tcl,v 1.25 1998/10/10 20:58:19 jfontain Exp $}

class blt2DViewer {

    # use pie colors for consistency
    set blt2DViewer::(colors) {#7FFFFF #7FFF7F #FF7F7F #FFFF7F #7F7FFF #FFBF00 #BFBFBF #FF7FFF #FFFFFF}

    proc blt2DViewer {this path} viewer {} {
        $path configure -cursor {}
if {$::officialBLT} {
        $path configure -plotpadx 2 -plotpady 2           ;# use minimum padding for extreme values and flat zero line to be visible
        $path yaxis configure -tickshadow {}
}
        $path yaxis configure -title {} -tickfont $font::(smallNormal)
        $path legend configure -borderwidth 1 -font $font::(mediumNormal) -activebackground white

        # allow dropping of data cells
        set blt2DViewer::($this,drop) [new dropSite\
            -path $path -formats DATACELLS -command "viewer::view $this \$dragSite::data(DATACELLS)"\
        ]

        set blt2DViewer::($this,elements) {}                                             ;# initialize list of data line identifiers
        set blt2DViewer::($this,colorIndex) 0
        set blt2DViewer::($this,path) $path
    }

    proc ~blt2DViewer {this} {
        catch {delete $blt2DViewer::($this,drag)}
        delete $blt2DViewer::($this,drop)
        catch {delete $blt2DViewer::($this,selector)}
        eval delete $blt2DViewer::($this,elements)                                                       ;# delete existing elements
    }

    proc supportedTypes {this} {
        return {integer real}
    }

    proc dragData {this format} {
        set selectedElements [selector::selected $blt2DViewer::($this,selector)]
        switch $format {
            OBJECTS {
                if {[llength $selectedElements]>0} {
                    return $selectedElements                                            ;# return selected elements if there are any
                } elseif {[llength $blt2DViewer::($this,elements)]==0} {
                    return $this                                                   ;# return graph itself if it contains no elements
                } else {
                    return {}                                                                            ;# return nothing otherwise
                }
            }
            DATACELLS {
                return [cellsFromElements $this $selectedElements]
            }
        }
    }

    proc validateDrag {this x y} {
        if {[llength $blt2DViewer::($this,elements)]==0} {
            return 1                                                                                   ;# allow drag of empty viewer
        }
        # allow dragging if only from a selected cell
        return [expr {\
            [lsearch -exact [selector::selected $blt2DViewer::($this,selector)] [$blt2DViewer::($this,path) legend get @$x,$y]]>=0\
        }]
    }

    proc monitorCell {this array row column} {
        viewer::registerTrace $this $array
        set cell ${array}($row,$column)
        if {[lsearch -exact [cellsFromElements $this $blt2DViewer::($this,elements)] $cell]>=0} return     ;# already charted, abort
        set element [newElement $this $blt2DViewer::($this,path) -label [viewer::label $array $row $column]]
        switched::configure $element -color [lindex $blt2DViewer::(colors) $blt2DViewer::($this,colorIndex)]
        # keep track of element existence
        switched::configure $element -deletecommand "blt2DViewer::deletedElement $this $array $element"
        # circle through colors
        set blt2DViewer::($this,colorIndex) [expr {($blt2DViewer::($this,colorIndex)+1)%[llength $blt2DViewer::(colors)]}]
        lappend blt2DViewer::($this,elements) $element                                                     ;# register new data line
        set blt2DViewer::($this,cell,$element) $cell
        catch {selector::add $blt2DViewer::($this,selector) $element}               ;# selector may not exist if dragging disallowed
    }

    proc cells {this} {
        return [cellsFromElements $this $blt2DViewer::($this,elements)]
    }

    proc deletedElement {this array element} {
        viewer::unregisterTrace $this $array                                          ;# trace may no longer be needed on this array
        ldelete blt2DViewer::($this,elements) $element
        catch {selector::remove $blt2DViewer::($this,selector) $element}            ;# selector may not exist if dragging disallowed
        unset blt2DViewer::($this,cell,$element)
        if {[llength $blt2DViewer::($this,elements)]==0} {
            delete $this                                                            ;# self destruct when there are no more elements
        }
    }

    proc update {this array args} {                                                               ;# update display using cells data
        updateTimeDisplay $this [set seconds [clock seconds]]
        foreach element $blt2DViewer::($this,elements) {
            set cell $blt2DViewer::($this,cell,$element)
            if {[string first $array $cell]<0} continue                                  ;# check that cell belongs to updated array
            set value {}                                                        ;# set default to void in case data no longer exists
            catch {set value [set $cell]}
            updateElement $this $element $seconds $value
        }
    }

    virtual proc newElement {this path args}                                       ;# let derived class create an element of its own

    virtual proc updateElement {this element seconds value}      ;# let derived class (such as graph, bar chart, ...) update element

    virtual proc updateTimeDisplay {this seconds} {}        ;# eventually let derived class (such as graph) update axis, for example

    proc cellsFromElements {this elements} {
        set cells {}
        foreach element $elements {
            lappend cells $blt2DViewer::($this,cell,$element)
        }
        return $cells
    }

    proc setElementsState {this elements select} {
        if {$select} {
            set action activate
        } else {
            set action deactivate
        }
        set path $blt2DViewer::($this,path)
        foreach element $elements {
            $path legend $action $element
        }
    }

    proc setSelection {this x y} {
        if {[string length [set element [$blt2DViewer::($this,path) legend get @$x,$y]]]>0} {                         ;# in a legend
            selector::select $blt2DViewer::($this,selector) $element
        }
    }

    proc toggleSelection {this x y} {
        if {[string length [set element [$blt2DViewer::($this,path) legend get @$x,$y]]]>0} {                         ;# in a legend
            selector::toggle $blt2DViewer::($this,selector) $element
        }
    }

    proc extendSelection {this x y} {
        if {[string length [set element [$blt2DViewer::($this,path) legend get @$x,$y]]]>0} {                         ;# in a legend
            selector::extend $blt2DViewer::($this,selector) $element
        }
    }

    proc allowDrag {this} {
        set path $blt2DViewer::($this,path)

        set blt2DViewer::($this,drag) [new dragSite -path $path -validcommand "blt2DViewer::validateDrag $this"]
        dragSite::provide $blt2DViewer::($this,drag) OBJECTS "blt2DViewer::dragData $this"                ;# provide list of objects
        dragSite::provide $blt2DViewer::($this,drag) DATACELLS "blt2DViewer::dragData $this"

        set blt2DViewer::($this,selector) [new objectSelector -selectcommand "blt2DViewer::setElementsState $this"]
        bind $path <ButtonRelease-1> "blt2DViewer::setSelection $this %x %y"
        bind $path <Control-ButtonRelease-1> "blt2DViewer::toggleSelection $this %x %y"
        bind $path <Shift-ButtonRelease-1> "blt2DViewer::extendSelection $this %x %y"
    }

}