source: trunk/gui/scripts/textresult.tcl @ 5106

Last change on this file since 5106 was 3799, checked in by gah, 11 years ago

add -simulation to plotadd calls

File size: 15.4 KB
RevLine 
[3330]1# -*- mode: tcl; indent-tabs-mode: nil -*-
[11]2# ----------------------------------------------------------------------
3#  COMPONENT: TextResult - Log output for ResultSet
4#
5#  This widget is used to show text output in a ResultSet.  The log
6#  output from a tool, for example, is rendered as a TextResult.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
[3177]9#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
[115]10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
[11]13# ======================================================================
14package require Itk
15package require BLT
16
17option add *TextResult.width 4i widgetDefault
18option add *TextResult.height 4i widgetDefault
[46]19option add *TextResult.textBackground white widgetDefault
[11]20option add *TextResult.font \
[676]21    -*-helvetica-medium-r-normal-*-12-* widgetDefault
[46]22option add *TextResult.textFont \
[676]23    -*-courier-medium-r-normal-*-12-* widgetDefault
[11]24
25itcl::class Rappture::TextResult {
26    inherit itk::Widget
27
[1930]28    constructor {args} {
29        # defined below
30    }
[11]31    public method add {dataobj {settings ""}}
[13]32    public method get {}
[11]33    public method delete {args}
34    public method scale {args}
[1930]35    public method parameters {title args} {
36        # do nothing
37    }
[464]38    public method download {option args}
[13]39
[46]40    public method select {option args}
41    public method find {option}
[1930]42    public method popup {option args}
[46]43
[413]44    private variable _dataobj ""  ;# data object currently being displayed
45    private variable _raised      ;# maps all data objects => -raise param
[11]46}
[1929]47                                                                               
[11]48itk::usual TextResult {
49    keep -background -foreground -cursor -font
50}
51
52# ----------------------------------------------------------------------
53# CONSTRUCTOR
54# ----------------------------------------------------------------------
55itcl::body Rappture::TextResult::constructor {args} {
56    option add hull.width hull.height
57    pack propagate $itk_component(hull) no
58
[46]59    #
60    # CONTROL BAR with find/select functions
61    #
62    itk_component add controls {
[1929]63        frame $itk_interior.cntls
[46]64    }
65    pack $itk_component(controls) -side bottom -fill x -pady {4 0}
66
67    itk_component add selectall {
[1929]68        button $itk_component(controls).selall -text "Select All" \
69            -command [itcl::code $this select all]
[46]70    }
71    pack $itk_component(selectall) -side right -fill y
72
73    itk_component add findl {
[1929]74        label $itk_component(controls).findl -text "Find:"
[46]75    }
76    pack $itk_component(findl) -side left
77
78    itk_component add find {
[1929]79        entry $itk_component(controls).find -width 20
[46]80    }
81    pack $itk_component(find) -side left
82
83    itk_component add finddown {
[1929]84        button $itk_component(controls).finddown \
85            -image [Rappture::icon finddn] \
86            -relief flat -overrelief raised \
87            -command [itcl::code $this find down]
[46]88    } {
[1929]89        usual
90        ignore -relief
[46]91    }
92    pack $itk_component(finddown) -side left
93
94    itk_component add findup {
[1929]95        button $itk_component(controls).findup \
96            -image [Rappture::icon findup] \
97            -relief flat -overrelief raised \
98            -command [itcl::code $this find up]
[46]99    } {
[1929]100        usual
101        ignore -relief
[46]102    }
103    pack $itk_component(findup) -side left
104
105    itk_component add findstatus {
[1929]106        label $itk_component(controls).finds -width 10 -anchor w
[46]107    }
108    pack $itk_component(findstatus) -side left -expand yes -fill x
109
110    # shortcut for Return in search field
111    bind $itk_component(find) <KeyPress-Return> "
[1929]112        $itk_component(finddown) configure -relief sunken
113        update idletasks
114        after 200
115        $itk_component(finddown) configure -relief flat
116        $itk_component(finddown) invoke
[46]117    "
118    bind $itk_component(find) <KeyPress> \
[1929]119        [itcl::code $this find reset]
[46]120
121    #
122    # TEXT AREA
123    #
[11]124    itk_component add scroller {
[1929]125        Rappture::Scroller $itk_interior.scroller \
126            -xscrollmode auto -yscrollmode auto
[11]127    }
128    pack $itk_component(scroller) -expand yes -fill both
129
130    itk_component add text {
[1929]131        text $itk_component(scroller).text -width 1 -height 1 -wrap none
[46]132    } {
[1929]133        usual
134        rename -background -textbackground textBackground Background
135        rename -font -textfont textFont Font
[11]136    }
137    $itk_component(scroller) contents $itk_component(text)
138    $itk_component(text) configure -state disabled
139
[23]140    $itk_component(text) tag configure ERROR -foreground red
141
[1930]142    itk_component add emenu {
143        menu $itk_component(text).menu -tearoff 0
144    } {
145        ignore -tearoff
146    }
147    $itk_component(emenu) add command \
148        -label "Select All" -accelerator "Ctrl+A" \
149        -command [itcl::code $this select all]
150    $itk_component(emenu) add command \
151        -label "Select None" -accelerator "Esc" \
152        -command [itcl::code $this select none]
153    bind $itk_component(text) <<PopupMenu>> \
154        [itcl::code $this popup menu emenu %X %Y]
155    $itk_component(emenu) add command \
156        -label "Copy" -accelerator "Ctrl+C" \
157        -command [list event generate $itk_component(text) <<Copy>>]
158
159    bind $itk_component(text) <Control-KeyPress-a> \
160        [list $itk_component(emenu) invoke "Select All"]
161    bind $itk_component(text) <Control-KeyPress-c> \
162        [list $itk_component(emenu) invoke "Copy"]
163    bind $itk_component(text) <Escape> \
164        [list $itk_component(emenu) invoke "Select None" ]
165    bind $itk_component(text) <Enter> [list ::focus $itk_component(text)]
166
[11]167    eval itk_initialize $args
168}
169
170# ----------------------------------------------------------------------
171# USAGE: add <dataobj> ?<settings>?
172#
173# Clients use this to add a data object to the plot.  If the optional
174# <settings> are specified, then the are applied to the data.  Allowed
[13]175# settings are -color and -brightness, -width, -linestyle and -raise.
176# (Many of these are ignored.)
[11]177# ----------------------------------------------------------------------
178itcl::body Rappture::TextResult::add {dataobj {settings ""}} {
179    array set params {
[1929]180        -color ""
181        -brightness ""
182        -width ""
183        -linestyle ""
184        -raise 0
185        -description ""
186        -param ""
[11]187    }
[3799]188    array set params $settings
[11]189
[413]190    set replace 0
191    if {"" != $dataobj} {
[1929]192        set _raised($dataobj) $params(-raise)
193        if {"" == $_dataobj} {
194            set replace 1
195        } elseif {$_raised($_dataobj) == 0 && $params(-raise)} {
196            set replace 1
197        }
[413]198    }
[11]199
[413]200    if {$replace} {
[1929]201        $itk_component(text) configure -state normal
202        $itk_component(text) delete 1.0 end
[413]203
[1929]204        if {[$dataobj element -as type] == "log"} {
205            # log output -- remove special =RAPPTURE-???=> messages
206            set message [$dataobj get]
207            while {[regexp -indices \
208                       {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
209                        match type mesg]} {
[23]210
[1929]211                foreach {i0 i1} $match break
212                set first [string range $message 0 [expr {$i0-1}]]
213                if {[string length $first] > 0} {
214                    $itk_component(text) insert end $first
215                }
[23]216
[1929]217                foreach {t0 t1} $type break
218                set type [string range $message $t0 $t1]
219                foreach {m0 m1} $mesg break
220                set mesg [string range $message $m0 $m1]
221                if {[string length $mesg] > 0
222                       && $type != "RUN" && $type != "PROGRESS"} {
223                    $itk_component(text) insert end $mesg $type
224                    $itk_component(text) insert end \n $type
225                }
226                set message [string range $message [expr {$i1+1}] end]
227            }
[23]228
[1929]229            if {[string length $message] > 0} {
230                $itk_component(text) insert end $message
231                if {[$itk_component(text) get end-2char] != "\n"} {
232                    $itk_component(text) insert end "\n"
233                }
234            }
235        } elseif {[$dataobj element -as type] == "string"} {
236            # add string values
237            set data [$dataobj get current]
238            if {[Rappture::encoding::is binary $data]} {
239                set data [Rappture::utils::hexdump -lines 1000 $data]
240            }
241            $itk_component(text) insert end $data
242        } else {
243            # any other string output -- add it directly
244            $itk_component(text) insert end [$dataobj get]
245        }
246        $itk_component(text) configure -state disabled
[413]247
[1929]248        set _dataobj $dataobj
[11]249    }
250}
251
252# ----------------------------------------------------------------------
[13]253# USAGE: get
254#
255# Clients use this to query the list of objects being plotted, in
256# order from bottom to top of this result.
257# ----------------------------------------------------------------------
258itcl::body Rappture::TextResult::get {} {
259    return $_dataobj
260}
261
262# ----------------------------------------------------------------------
[11]263# USAGE: delete ?<curve1> <curve2> ...?
264#
265# Clients use this to delete a curve from the plot.  If no curves
266# are specified, then all curves are deleted.
267# ----------------------------------------------------------------------
268itcl::body Rappture::TextResult::delete {args} {
[413]269    if {[llength $args] == 0} {
[1929]270        # delete everything
271        catch {unset _raised}
272        set _dataobj ""
273        $itk_component(text) configure -state normal
274        $itk_component(text) delete 1.0 end
275        $itk_component(text) configure -state disabled
[413]276    } else {
[1929]277        # delete these specific objects
278        foreach obj $args {
279            catch {unset _raised($obj)}
280            if {$obj == $_dataobj} {
281                set _dataobj ""
282                $itk_component(text) configure -state normal
283                $itk_component(text) delete 1.0 end
284                $itk_component(text) configure -state disabled
285            }
286        }
[413]287    }
[11]288}
289
290# ----------------------------------------------------------------------
291# USAGE: scale ?<curve1> <curve2> ...?
292#
293# Sets the default limits for the overall plot according to the
294# limits of the data for all of the given <curve> objects.  This
295# accounts for all curves--even those not showing on the screen.
296# Because of this, the limits are appropriate for all curves as
297# the user scans through data in the ResultSet viewer.
298# ----------------------------------------------------------------------
299itcl::body Rappture::TextResult::scale {args} {
300    # nothing to do for text
301}
[46]302
303# ----------------------------------------------------------------------
[193]304# USAGE: download coming
[464]305# USAGE: download controls <downloadCommand>
[193]306# USAGE: download now
[50]307#
308# Clients use this method to create a downloadable representation
309# of the plot.  Returns a list of the form {ext string}, where
310# "ext" is the file extension (indicating the type of data) and
311# "string" is the data itself.
312# ----------------------------------------------------------------------
[464]313itcl::body Rappture::TextResult::download {option args} {
[193]314    switch $option {
[1929]315        coming {
316            # nothing to do
317        }
318        controls {
319            # no controls for this download yet
320            return ""
321        }
322        now {
323            if {"" == $_dataobj} {
324                return ""
325            }
326            if {[$_dataobj element -as type] == "log"} {
327                set val [$itk_component(text) get 1.0 end]
328            } elseif {[$_dataobj element -as type] == "string"} {
329                set val [$_dataobj get current]
330            } else {
331                set val [$_dataobj get]
332            }
[702]333
[1929]334            set ext [$_dataobj get filetype]
335            if {"" == $ext} {
336                if {[Rappture::encoding::is binary $val]} {
337                    set ext ".dat"
338                } else {
339                    set ext ".txt"
340                }
341            }
342            return [list $ext $val]
343        }
344        default {
345            error "bad option \"$option\": should be coming, controls, now"
346        }
[193]347    }
[50]348}
349
350# ----------------------------------------------------------------------
[46]351# USAGE: select all
352#
353# Handles various selection operations within the text.
354# ----------------------------------------------------------------------
355itcl::body Rappture::TextResult::select {option args} {
356    switch -- $option {
[1929]357        all {
358            $itk_component(text) tag add sel 1.0 end
359        }
[1930]360        none {
361            if { [$itk_component(text) tag ranges "sel"] != "" } {
362                selection clear
363            }
364        }
[1929]365        default {
[1930]366            error "bad option \"$option\": should be all or none"
[1929]367        }
[46]368    }
369}
370
371# ----------------------------------------------------------------------
372# USAGE: find up
373# USAGE: find down
374# USAGE: find reset
375#
376# Handles various find operations within the text.  These find a
377# bit of text and highlight it within the widget.  The find operation
378# starts from the end of the currently highlighted text, or from the
379# beginning if there is no highlight.
380# ----------------------------------------------------------------------
381itcl::body Rappture::TextResult::find {option} {
382    # handle the reset case...
383    $itk_component(find) configure \
[1929]384        -background $itk_option(-background) \
385        -foreground $itk_option(-foreground)
[46]386    $itk_component(findstatus) configure -text ""
387
388    if {$option == "reset"} {
[1929]389        return
[46]390    }
391
392    # handle the up/down cases...
393    set t $itk_component(text)
394    set pattern [string trim [$itk_component(find) get]]
395
396    if {"" == $pattern} {
[1929]397        $itk_component(find) configure -background red -foreground white
398        $itk_component(findstatus) configure -text "<< Enter a search string"
399        return
[46]400    }
401
402    # find the starting point for the search
403    set seln [$t tag nextrange sel 1.0]
404    if {$seln == ""} {
[1929]405        set t0 1.0
406        set t1 end
[46]407    } else {
[1929]408        foreach {t0 t1} $seln break
[46]409    }
410    $t tag remove sel 1.0 end
411
412    # search up or down
413    switch -- $option {
[1929]414        up {
415            set start [$t index $t0-1char]
416            set next [$t search -backwards -nocase -- $pattern $start]
[3186]417            Rappture::Logger::log text find -up $pattern
[1929]418        }
419        down {
420            set start [$t index $t1+1char]
421            set next [$t search -forwards -nocase -- $pattern $start]
[3186]422            Rappture::Logger::log text find -down $pattern
[1929]423        }
[46]424    }
425
426    if {"" != $next} {
[1929]427        set len [string length $pattern]
428        $t tag add sel $next $next+${len}chars
429        $t see $next
430        set lnum [lindex [split $next .] 0]
431        set lines [lindex [split [$t index end] .] 0]
432        set percent [expr {round(100.0*$lnum/$lines)}]
433        set status "line $lnum   --$percent%--"
[46]434    } else {
[1929]435        set status "Not found"
436        $itk_component(find) configure -background red -foreground white
[46]437    }
438    $itk_component(findstatus) configure -text $status
439}
[1930]440
441# ----------------------------------------------------------------------
442# USAGE: _popup menu <which> <X> <Y>
443#
444# Used internally to manage edit operations.
445# ----------------------------------------------------------------------
446itcl::body Rappture::TextResult::popup {option args} {
447    switch -- $option {
448        menu {
449            if {[llength $args] != 3} {
450                error "wrong # args: should be \"_popup $option which x y\""
451            }
452            set mname [lindex $args 0]
453            set x [lindex $args 1]
454            set y [lindex $args 2]
455            tk_popup $itk_component($mname) $x $y
456        }
457        default {
458            error "bad option \"$option\": should be menu"
459        }
460    }
461}
Note: See TracBrowser for help on using the repository browser.