source: trunk/tester/scripts/statuslist.tcl @ 2136

Last change on this file since 2136 was 2136, checked in by mmc, 14 years ago

Regression tester is mostly working now, although it doesn't bring up
visualizers to plot the difference in output values. It does show
attribute differences and text differences for string results. It
also diffs the input side of the test and provides warnings when the
test seems out of date with respect to the tool definition.

File size: 10.9 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: statuslist - display differences within a test
3#
4#  This is the list of differences shown for a particular test failure.
5#  Each line in this list shows an icon (error or warning) and some
6#  details about the difference.  When you mouse over any entry, it
7#  pops up a "View" button that will invoke the -viewcommand to pop up
8#  a more detailed comparison.
9# ======================================================================
10#  AUTHOR:  Michael McLennan, Purdue University
11#  Copyright (c) 2010-2011  Purdue Research Foundation
12#
13#  See the file "license.terms" for information on usage and
14#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15# ======================================================================
16package require Itk
17package require RapptureGUI
18
19namespace eval Rappture::Tester { # forward declaration }
20
21option add *StatusList.font {Arial -12} widgetDefault
22option add *StatusList.titleFont {Arial -12 bold} widgetDefault
23option add *StatusList.subTitleFont {Arial -10} widgetDefault
24
25itcl::class Rappture::Tester::StatusEntry {
26    public variable title ""
27    public variable subtitle ""
28    public variable body ""
29    public variable help ""
30    public variable icon ""
31    public variable clientdata ""
32
33    constructor {args} { eval configure $args }
34}
35
36itcl::class Rappture::Tester::StatusList {
37    inherit itk::Widget
38
39    itk_option define -font font Font ""
40    itk_option define -titlefont titleFont Font ""
41    itk_option define -subtitlefont subTitleFont Font ""
42    itk_option define -viewcommand viewCommand ViewCommand ""
43    itk_option define -selectbackground selectBackground Foreground ""
44
45    constructor {args} { # defined later }
46    destructor { # defined later }
47
48    public method insert {pos args}
49    public method delete {from {to ""}}
50    public method size {} { return [llength $_entries] }
51    public method get {pos args}
52    public method invoke {{index "current"}}
53    public method view {{index "current"}}
54
55    public method xview {args} {
56        return [eval $itk_component(listview) xview $args]
57    }
58    public method yview {args} {
59        return [eval $itk_component(listview) yview $args]
60    }
61
62    protected method _redraw {}
63    protected method _motion {y}
64
65    private variable _dispatcher ""  ;# dispatcher for !events
66    private variable _entries ""     ;# list of status entries
67    private variable _hover ""       ;# mouse is over item with this tag
68}
69
70# ----------------------------------------------------------------------
71# CONSTRUCTOR
72# ----------------------------------------------------------------------
73itcl::body Rappture::Tester::StatusList::constructor {args} {
74    Rappture::dispatcher _dispatcher
75    $_dispatcher register !redraw
76    $_dispatcher dispatch $this !redraw "[itcl::code $this _redraw]; list"
77
78    itk_component add listview {
79        canvas $itk_interior.lv -relief flat
80    } {
81        usual
82        keep -xscrollcommand -yscrollcommand
83    }
84    pack $itk_component(listview) -expand yes -fill both
85
86    # add binding so that each item reacts to mouseover events
87    bind $itk_component(listview) <Motion> [itcl::code $this _motion %y]
88
89    # add binding for double-click-to-open
90    bind $itk_component(listview) <Double-Button-1> [itcl::code $this view]
91
92    # this pops up on each entry
93    itk_component add view {
94        button $itk_interior.view -text "View"
95    } {
96        usual
97        rename -highlightbackground -selectbackground selectBackground Foreground
98    }
99
100    eval itk_initialize $args
101}
102
103itk::usual StatusList {
104    keep -background -foreground -cursor
105    keep -selectbackground
106    keep -font -titlefont -subtitlefont
107}
108
109# ----------------------------------------------------------------------
110# DESTRUCTOR
111# ----------------------------------------------------------------------
112itcl::body Rappture::Tester::StatusList::destructor {} {
113    delete 0 end
114}
115
116# ----------------------------------------------------------------------
117# USAGE: insert <pos> ?-option value -option value ...?
118#
119# Inserts a new entry into the list at the given <pos>.  The options
120# are those recognized by a StatusEntry object.
121# ----------------------------------------------------------------------
122itcl::body Rappture::Tester::StatusList::insert {pos args} {
123    set entry [eval Rappture::Tester::StatusEntry #auto $args]
124    set _entries [linsert $_entries $pos $entry]
125    $_dispatcher event -idle !redraw
126}
127
128# ----------------------------------------------------------------------
129# USAGE: delete <pos> ?<toPos>?
130#
131# Deletes a single entry or a range of entries from the list displayed
132# in this widget.
133# ----------------------------------------------------------------------
134itcl::body Rappture::Tester::StatusList::delete {pos {to ""}} {
135    if {$to eq ""} {
136        set to $pos
137    }
138    foreach obj [lrange $_entries $pos $to] {
139        itcl::delete object $obj
140    }
141    set _entries [lreplace $_entries $pos $to]
142    $_dispatcher event -idle !redraw
143}
144
145# ----------------------------------------------------------------------
146# USAGE: get <pos> ?-key?
147#
148# Queries information about a particular entry at index <pos>.  With
149# no extra args, it returns a list of "-key value -key value ..."
150# representing all of the data about that entry.  Otherwise, the value
151# for a particular -key can be requested.
152# ----------------------------------------------------------------------
153itcl::body Rappture::Tester::StatusList::get {pos {option ""}} {
154    set obj [lindex $_entries $pos]
155    if {$obj eq ""} {
156        return ""
157    }
158    if {$option eq ""} {
159        set vlist ""
160        foreach opt [$obj configure] {
161            lappend vlist [lindex $opt 0] [lindex $opt end]
162        }
163        return $vlist
164    }
165    return [$obj cget $option]
166}
167
168# ----------------------------------------------------------------------
169# USAGE: view ?<index>?
170#
171# Handles the action of clicking the "View" button on items in the
172# status list.  Invokes the -viewcommand to pop up a more detailed
173# view of the item.  Additional details about the item are appended
174# onto the command as a list of options and values.  These include
175# the integer -index for the position of the selected item, along
176# with details defined when the item was inserted into the list.
177# ----------------------------------------------------------------------
178itcl::body Rappture::Tester::StatusList::view {{index "current"}} {
179    if {$index eq "current"} {
180        set index $_hover
181    }
182    if {[string length $itk_option(-viewcommand)] > 0
183          && [string is integer -strict $index]} {
184
185        set obj [lindex $_entries $index]
186        set vlist ""
187        if {$obj ne ""} {
188            foreach opt [$obj configure] {
189                lappend vlist [lindex $opt 0] [lindex $opt end]
190            }
191        }
192        uplevel #0 $itk_option(-viewcommand) -index $index $vlist
193    }
194}
195
196# ----------------------------------------------------------------------
197# USAGE: _redraw
198#
199# Used internally to update the detailed list of items maintained
200# by this widget.
201# ----------------------------------------------------------------------
202itcl::body Rappture::Tester::StatusList::_redraw {} {
203    set c $itk_component(listview)
204    $c delete all
205
206    # figure out the maximum size of all icons
207    set iw 0
208    set ih 0
209    foreach obj $_entries {
210        set icon [$obj cget -icon]
211        if {$icon ne ""} {
212            if {[image width $icon] > $iw} { set iw [image width $icon] }
213            if {[image height $icon] > $ih} { set ih [image height $icon] }
214        }
215    }
216
217    set tlineh [font metrics $itk_option(-titlefont) -linespace]
218    set stlineh [font metrics $itk_option(-subtitlefont) -linespace]
219
220    set x0 2
221    set y0 2
222    set n 0
223    foreach obj $_entries {
224        set tag "entry$n"
225
226        set icon [$obj cget -icon]
227        set iconh 0
228        if {$icon ne ""} {
229            $c create image [expr {$x0+$iw}] $y0 -anchor ne -image $icon \
230                -tags [list $tag main]
231            set iconh [image height $icon]
232        }
233        set x1 [expr {$x0+$iw+6}]
234        set y1 $y0
235
236        set title [$obj cget -title]
237        if {$title ne ""} {
238            $c create text [expr {$x1-4}] $y1 -anchor nw -text $title \
239                -font $itk_option(-titlefont) -tags [list $tag main]
240            set y1 [expr {$y1+$tlineh+2}]
241        }
242
243        set subtitle [$obj cget -subtitle]
244        if {$subtitle ne ""} {
245            $c create text $x1 $y1 -anchor nw -text $subtitle \
246                -font $itk_option(-subtitlefont) -tags [list $tag main]
247            set y1 [expr {$y1+$stlineh+2}]
248        }
249
250        set body [$obj cget -body]
251        if {$body ne ""} {
252            # a little space between the title/subtitle and the body
253            if {$y1 != $y0} { incr y1 4 }
254
255            set id [$c create text $x1 $y1 -anchor nw -text $body \
256                -font $itk_option(-font) -tags [list $tag main]]
257
258            foreach {tx0 ty0 tx1 ty1} [$c bbox $id] break
259            set y1 [expr {$y1 + ($ty1-$ty0)}]
260        }
261
262        # make sure that y1 is at the bottom of the icon too
263        if {$y1 < $y0+$iconh+2} {
264            set y1 [expr {$y0+$iconh+2}]
265        }
266
267        # make a background selection rectangle
268        set id [$c create rectangle 0 [expr {$y0-2}] 1000 $y1 \
269            -outline "" -fill "" -tags [list allbg $tag:bg]]
270        $c lower $id
271
272        set y0 [expr {$y1+10}]
273        incr n
274    }
275
276    # set the scrolling region to the "main" part (no bg boxes)
277    set x1 0; set y1 0
278    foreach {x0 y0 x1 y1} [$c bbox main] break
279    $c configure -scrollregion [list 0 0 [expr {$x1+4}] [expr {$y1+4}]]
280}
281
282# ----------------------------------------------------------------------
283# USAGE: _motion <y>
284#
285# Called internally when the user moves the mouse over an item in the
286# status list that shows specific test failures.  Highlights the item
287# and posts a "View" button on the right-hand side of the list.
288# ----------------------------------------------------------------------
289itcl::body Rappture::Tester::StatusList::_motion {y} {
290    set c $itk_component(listview)
291
292    set index ""
293    foreach id [$c find overlapping 10 $y 10 $y] {
294        foreach tag [$c gettags $id] {
295            if {[regexp {^entry([0-9]+)} $tag match n]} {
296                set index $n
297                break
298            }
299        }
300        if {$index ne ""} {
301            break
302        }
303    }
304
305    if {$index ne $_hover} {
306        $c itemconfigure allbg -fill ""
307        $c delete viewbtn
308
309        if {$index ne ""} {
310            set tag "entry$index:bg"
311            $c itemconfigure $tag -fill $itk_option(-selectbackground)
312
313            foreach {x0 y0 x1 y1} [$c bbox $tag] break
314            set w [winfo width $c]
315            $c create window [expr {$w-10}] [expr {($y0+$y1)/2}] \
316                -anchor e -window $itk_component(view) -tags viewbtn
317
318            $itk_component(view) configure \
319                -command [itcl::code $this view $index]
320        }
321        set _hover $index
322    }
323}
Note: See TracBrowser for help on using the repository browser.