source: tol/tolbase/lib/renderpane/renderpane.tcl @ 066693f

1941-docker-image-to-testdevel
Last change on this file since 066693f was 066693f, checked in by Jorge Pérez <josp.jorge@…>, 15 years ago

refs #1396, se activa la fuente mono y se escapan los caracteres ' &, el caracter ' no tenia escape en el widget original

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@4021 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 30.8 KB
RevLine 
[a680983]1package require Tk
2package require snit
3package require trycatch
4package require markupparser
5
6namespace import trycatch::*
7interp alias {} prefs {} ::Notebook::prefs
8
9#-----------------------------------------------------------------------
10# TITLE:
11#       renderpane.tcl
12#
13# AUTHOR:
14#       Will Duquette
15#
16# DESCRIPTION:
17#       A read-only text widget designed to render Notebook markup.
18#       From the standpoint of the caller, the "render" method replaces
19#       the "insert" and "delete" methods, which are effectively no-ops.
20#
21#       All necessary text widget commands are delegated down to the text
22#       widget.  This widget knows how to render and tag Notebook markup,
23#       but it doesn't provide any of the active behavior.
24#
25# LICENSE:
26#       Copyright (C) 2005 by William H. Duquette.  This file may
27#       be used subject to the terms in license.txt.
28#
29#-----------------------------------------------------------------------
30
31snit::widgetadaptor renderpane {
32    #-------------------------------------------------------------------
33    # Text Widget Adaptation
34
35    # Disable the insert and delete methods, to make this readonly.
36    method insert {args} {}
37    method delete {args} {}
38
39    # Pass all otherwise undefined methods and options to the real
40    # text widget, so that the remaining behavior is as expected.
41    delegate method * to hull
42    delegate option * to hull
43
44    #-------------------------------------------------------------------
45    # Widget options
46
47    # The command to use to query about a link's existence.  Must take
48    # a page name as argument and return 1 if it exists, and 0 otherwise.
49    option -querycommand {}
50
51    # The command to call when a page title is clicked.  Should take the
52    # title as its argument.
53    option -titlecommand {}
54
55    # The command to call when a page link is clicked.  Should take the
56    # name of the page to link to as its argument.
57    option -linkcommand {}
58
59    # The command to call when a magic button is clicked.  The command
60    # should take one argument, the script to execute.
61    option -buttoncommand {}
62
63    # The command to call when a macroerror is clicked.  The command
64    # should take one argument, the text of the macro.
65    option -macroerrorcommand {}
66
67    # The command to call to write a message to the message line
68    option -messagecommand {}
69
70    # The notebook file directory; used as the root for relative paths.
71    option -dbdir {}
72
73    # The missing image to show when [!image !] could not be resolved
74    option -missingimage ""
75
76    #-------------------------------------------------------------------
77    # Instance Variables
78   
79    # The code associated with a magic button, where the index is
80    # $button-$index.  $button is the displayed text for the button
81    # and $index is the index of the first character of the displayed text.
82    variable bcode
83
84    # Counter used to generate names for horizontal line elements in
85    # the text pane.
86    variable counter 0
87
88    # Escape character substitutions
89    # TBD: Some of this should probably be done as part of markup parsing.
90    variable escapeMapping \
[066693f]91        "&lt; < &gt; > &lb; \[ &rb; \] &amp; & &ap; '"
[a680983]92
93    # Image List -- loaded images, for later destruction
94    variable imageList {}
95
96    # Image Data array: the index is the text widget index of the image,
97    # and the value is the text to display.
98    variable imageData
99
100    typevariable defaultMissingImage
101
102    # Type constructor: build resources
103    typeconstructor {
104      set defaultMissingImage [ image create photo -data {
105        R0lGODlhIAAgAIAAADNmmQUFBSwAAAAAIAAgAAACYIyPqZvgD6OcztCLn81c7g4C36Vwo8cE2Kml
106        B6lSb1VOLBS3iJx3NRoSNWy9zA/oG/JAR6RRuTTtntIZ9WldFYk3YpC5RXWdvOkVZtZis7D1GBeO
107        pNVfad1+p+fLrn6qAAA7q
108      } ]
109    }
110
111    #-----------------------------------------------------------------------
112    # Constructor and Destructor
113
114    constructor {args} {
115        set options(-querycommand) [codename DefaultQueryCmd]
116        set options(-missingimage) $defaultMissingImage
117
118        # Next, create the rotext pane.
[5c67e4e]119     
120        # setgrid option makes conflict with tolbase geometry
121        #-setgrid true
[a680983]122        installhull using text \
123            -insertwidth 0 \
124            -borderwidth 5 \
125            -relief flat \
126            -wrap word \
127            -cursor xterm
128
129        # At present, all delegated options are delegated to the
130        # hull component, so now we can configure.
131      $self configurelist $args
132
133        # Next, create the bullet icons
134        image create bitmap $win.bullet1 -data {
135            #define button_width 8
136            #define button_height 8
137            static unsigned char button_bits[] = {
138                0x00, 0x3c, 0x7e, 0x7e, 0x7e, 0x7e, 0x3c, 0x00};
139        }
140
141        image create bitmap $win.bullet2 -data {
142            #define bullet2_width 8
143            #define bullet2_height 8
144            static unsigned char bullet2_bits[] = {
145                0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00};
146        }
147
148        image create bitmap $win.bullet3 -data {
149            #define bullet3_width 8
150            #define bullet3_height 8
151            static unsigned char bullet3_bits[] = {
152                0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00};
153        }
154
155        # Next, add the markup tags, using the user preferences.
[5c67e4e]156
[a680983]157        $self UsePreferences
158
159        # Next, copy the default Text bindings to the renderpane,
160        # and adjust the bindtags so that the Text bindings no longer
161        # matter.  This will allow us to override them.
162
163        foreach sym [bind Text] {
164            bind $win $sym [bind Text $sym]
165        }
166
167        set bt [bindtags $win]
168        set ndx [lsearch -exact $bt Text]
169        bindtags $win [lreplace $bt $ndx $ndx]
170
171        # Next, remove the <<Cut>> and <<Paste>> tags, etc., since renderpanes
172        # aren't editable.
173        bind $win <<Cut>> ""
174        bind $win <<Paste>> ""
175        bind $win <<Undo>> ""
176        bind $win <<Redo>> ""
177
178        # When over an active tag, the cursor should be a hand.
179        foreach tag {title link button macroerror} {
180            $hull tag bind $tag <Enter> \
181                [mymethod EnterHandler $tag %x %y]
182               
183            $hull tag bind $tag <Leave> \
184                [mymethod LeaveHandler $tag %x %y]
185        }
186
187        # While over images, display the -text and path.
188        $hull tag bind image <Enter> [mymethod EnterImage %x %y]
189        $hull tag bind image <Leave> [mymethod LeaveImage %x %y]
190
191        # Prepare to receive preferences events; unregister on
192        # destroy.
193        prefs register $selfns [mymethod UsePreferences]
194
195        # Add better navigation keys
196        bind $win <Key-Down>  [list $hull yview scroll  1 units]
197        bind $win <Key-Up>    [list $hull yview scroll -1 units]
198        bind $win <Key-Next>  [list $hull yview scroll  1 pages]
199        bind $win <Key-Prior> [list $hull yview scroll -1 pages]
200        bind $win <Key-Home>  [list $hull yview moveto 0]
201        bind $win <Key-End>   [list $hull yview moveto 1]
202
203        # Add mouse interactions
204        $hull tag bind title <1> \
205            [mymethod TitleHandler %x %y]
206
207        $hull tag bind link <1> \
208            [mymethod LinkHandler %x %y]
209
210        $hull tag bind button <ButtonRelease-1> \
211            [mymethod ButtonHandler %x %y]
212
213        $hull tag bind macroerror <ButtonRelease-1> \
214            [mymethod MacroErrorHandler %x %y]
215
216    }
217
218    destructor {
219        catch {prefs unregister $selfns}
220        catch {image delete $win.bullet1 $win.bullet2 $win.bullet3}
221        catch {$self FreeImages}
222    }
223
224    #-----------------------------------------------------------------------
225    # Public methods
226
227    # Render a page into the page.  Uses ::markupparser::parseWithHandler
228    # and ParseHandler to do the job.
229    method render {title text} {
230        variable sty
231
232        # FIRST, delete all text from the text widget.
233        $hull del 1.0 end
234
235        # NEXT, forget all images
236        $self FreeImages
237
238        # NEXT, forget about any magic buttons; we'll build a new set.
239        array unset bcode
240
241        # NEXT, render the title
242        if { $title ne "" } {
243          $hull insert end " $title\n" title
244          $hull insert end "\n"
245        }
246
247        # NEXT, enable the default text style and indent
248        set sty(para) ""
249        set sty(txt) ""
250        set indent 0
251
252        # NEXT, render the page's text
253        foreach {tag value} [::markupparser::parse $text] {
254            switch -exact -- $tag {
255                META { }
256                HASH {
257                    # FIRST, #--- is always displayed specially.
258                    if {[string match "#---*" $value]} {
259                        $self InsertHLine
260                        continue
261                    }
262
263                    # NEXT, if the prefs flag is set then all directives
264                    # are displayed.
265                    if {[prefs get displaydirectives]} {
266                        $hull insert end $value pre
267                        continue
268                    }
269
270                    # NEXT, display directives based on what they are.
271                    if {[string match "#pre*" $value]} {
272                        # Skip it.
273                    } elseif {[string match "#unpre*" $value]} {
274                        # Skip it.
275                    } elseif {[string match "#meta*" $value]} {
276                        # Skip it.
277                    } elseif {[string match "#rem*" $value]} {
278                        # Skip it.
279                    } elseif {[string match "#data*" $value]} {
280                        # Skip it
281                    } elseif {[string match "#undata*" $value]} {
282                        # Skip it
283                    } elseif {[string match "#Tcl*" $value]} {
284                        # Skip it
285                    } elseif {[string match "#unTcl*" $value]} {
286                        # Skip it
287                    } else {
288                        $hull insert end $value pre
289                    }
290                }
291                PRE {
292                    $hull insert end $value pre
293                }
294                TCL {
295                    $hull insert end $value tcl
296                }
297                DATA {
298                    array set fields $value
299                    $hull insert end $fields(data) pre
300                }
301                H {
302                    set lev [lindex $value 0]
303                    set htext [lindex $value 1]
304
305                    $hull insert end "$htext\n" header$lev
306                }
307                P {
308                    set ptype  [lindex $value 0]
309                    set indent [lindex $value 1]
310
311                    # FIRST, basic paragraph setup.
312                    set sty(bold) ""
313                    set sty(italic) ""
314                    set sty(mono) ""
315                    set sty(strike) ""
316                    set sty(small) ""
317                    set sty(header) ""
318                    set sty(para) ""
319                    set sty(txt) ""
320                    set sty(link) "link"
321                    set sty(button) "button"
322
323                    # NEXT, set up for bulleted and indented paragraphs
324
325                    if {$ptype eq "*"} {
326                        set sty(para) "indent$indent"
327                        set sty(txt) $sty(para)
328                        set sty(link) [concat $sty(txt) link]
329                        set sty(button) [concat $sty(txt) button]
330           
331                        set lead [string repeat "\t" [expr {$indent - 1}]]
332               
333                        switch $indent {
334                            1       {set image $win.bullet1}
335                            2       {set image $win.bullet2}
336                            default {set image $win.bullet3}
337                        }
338                   
339                        $hull insert end "$lead" $sty(para)
340                        $hull image create end -image $image -align center
341                        $hull insert end "\t" $sty(para)
342                    } elseif {$indent > 0} {
343                        set sty(para) "indent$indent"
344                        set sty(txt) $sty(para)
345                        set sty(link) [concat $sty(txt) link]
346                        set sty(button) [concat $sty(txt) button]
347                   
348                        $hull insert end [string repeat "\t" $indent] $sty(para)
349                    }
350                }
351                STY {
352                    switch -exact -- [lindex $value 0] {
353                        m1  {
354                            set sty(mono) "mono"
355                            set sty(header) ""
356                            set sty(small) ""}
357                        m0 {
358                            set sty(mono) ""
359                        }
360                        b1  {
361                            set sty(bold) "bold"
362                            set sty(header) ""
363                            set sty(small) ""
364                        }
365                        b0 {
366                            set sty(bold) ""
367                        }
368                        i1  {
369                            set sty(italic) "italic"
370                            set sty(header) ""
371                            set sty(small) ""
372                        }
373                        i0 {
374                            set sty(italic) ""
375                        }
376                        h1  {
377                            set sty(header) "header3"
378                            set sty(bold) ""
379                            set sty(italic) ""
380                            set sty(mono) ""
381                            set sty(small) ""
382                        }
383                        h0 {
384                            set sty(header) ""
385                        }
386                        s1  {
387                            set sty(small) "small"
388                            set sty(bold) ""
389                            set sty(italic) ""
390                            set sty(mono) ""
391                            set sty(header) ""
392                        }
393                        s0 {
394                            set sty(small) ""
395                        }
396                        x1  {
397                            set sty(strike) "strike"
398                        }
399                        x0 {
400                            set sty(strike) ""
401                        }
402                        default {error "Unknown style: [lindex $value 1]"}
403                    }
404
405                    # Build the style list
406                    if {$sty(header) ne ""} {
407                        set theFont $sty(header)
408                    }
409                   
410                    set sty(txt) "$sty(para) $sty(mono)$sty(bold)$sty(italic) $sty(strike) $sty(header) $sty(small)"
411                    set sty(link) [concat $sty(txt) link]
412                    set sty(button) [concat $sty(txt) button]
413                }
414                LINK {
415                    #set value [NormalizeSpace $value]
416
417                    if {![regexp {^([^|]+)\|(.*$)} $value dummy linktext name]} {
418                        set linktext $value
419                        set name $value
420                    }
421                    set linktext [NormalizeNewlines $linktext]
422                    set name [NormalizeSpace $name]
423
424                    # If it exists, show it normally; if not, show it differently.
425                    if {[$self QueryLink $name]} {
426                        set index [$hull index insert]
427                        $hull insert end $linktext $sty(link)
428                    } else {
429                        $hull insert end "\[" [concat $sty(txt) warning]
430                        set index [$hull index insert]
431                        $hull insert end $linktext $sty(link)
432                        $hull insert end "\]" [concat $sty(txt) warning]
433                    }
434
435                    # Save the page to link to in bcode.
436                    set bcode([string tolower $linktext]-$index) $name
437                }
438                BTN {
439                    if {[regexp {^([^|]+)\|(.*$)} $value dummy bname code]} {
440                        set bname [NormalizeNewlines $bname]
441                        set index [$hull index insert]
442                        set bcode([string tolower $bname]-$index) $code
443                        $hull insert end $bname $sty(button)
444                    } else {
445                        $hull insert end "\[%$value%\]" warningmono
446                    }
447                }
448                OBJECT {
449                    set obj [getobj $value]
450                    switch -exact [lindex $obj 0] {
451                        image {
452                            $self InsertImage $obj
453                        }
454                        error {
455                            $hull insert end "\[!$value!\]" warningmono
456                            $self Msg [lindex $obj 1]
457                        }
458                        default {
459                            $hull insert end "\[!$value!\]" warningmono
460                            $self Msg "Unrecognized object type: $value"
461                        }
462                    }
463                }
464                MACRO {
465                    # We should see this only if macro expansion failed for this
466                    # macro
467                    $hull insert end "\[@$value@\]" macroerror
468                }
469                TXT -
470                HTML {
471                    # Normalize normal text: replace the whitespace between lines
472                    # a single space.
473                    regsub -all {\s*\n\s*} $value " " value
474                    $hull insert end [string map $escapeMapping $value] $sty(txt)
475                }
476                BR {
477                    $hull insert end "\n" $sty(txt)
478                    $hull insert end [string repeat "\t" $indent] $sty(para)
479                }
480                /P -
481                NL {
482                    $hull insert end "\n" $sty(txt)
483                }
484                default {error "Unknown markup tag: $tag"}
485            }
486        }
487    }
488
489    # Tag text that matches the search text.
490    method searchfor {searchText} {
491        $hull tag remove search 1.0 end
492
493        set pattern [string trim $searchText]
494
495        if {$pattern eq ""} {
496            return
497        }
498
499        set done 0
500        set index 1.0
501        set count 0
502        while {1} {
503            set index [$hull search -nocase -count count -- $pattern $index end]
504
505            if {$index eq ""} {
506                return
507            }
508
509            set endIndex [$hull index "$index + $count chars"]
510
511            $hull tag add search $index $endIndex
512
513            set index $endIndex
514        }
515    }
516
517
518    #-----------------------------------------------------------------------
519    # Private Methods and Procs
520
521    # Given the name of a tag that's been clicked on, and the x,y pixel
522    # coordinates of the click, return the tagged text.
523    method GetTagText {tag x y} {
524        set range [$hull tag prevrange $tag "@$x,$y +1 chars"]
525
526        return [$hull get [lindex $range 0] [lindex $range 1]]
527    }
528
529    # Given the name of a tag that's been clicked on, and the x,y pixel
530    # coordinates of the click, return the range {startIndex endIndex}.
531    method GetTagRange {tag x y} {
532        return [$hull tag prevrange $tag "@$x,$y +1 chars"]
533    }
534
535    # Returns 1 if a link exists and 0 otherwise.  Uses the -querycommand.
536    method QueryLink {name} {
537        set command $options(-querycommand)
538        lappend command $name
539        return [uplevel \#0 $command]
540    }
541
542    # Default query; always returns true.
543    proc DefaultQueryCmd {args} {
544        return 1
545    }
546
547    # Called when a special tag is entered
548    method EnterHandler {tag x y} {
549        $hull configure -cursor hand2
550
551        if {$tag eq "link" || $tag eq "button"} {
552            set range [$self GetTagRange $tag $x $y]
553            set name  [$hull get [lindex $range 0] [lindex $range 1]]
554            set index [lindex $range 0]
555
556            set bcodeKey "[string tolower $name]-$index"
557           
558            # TBD: It would be better if there were a -hovercommand;
559            # it could be passed the relevant info, and the caller
560            # could decide how to use it.
561
562            $self Msg $bcode($bcodeKey)
563        }
564    }
565
566    # Called when a special tag is left
567    method LeaveHandler {tag x y} {
568        $hull configure -cursor xterm
569
570        if {$tag eq "link" || $tag eq "button"} {
571            $self Msg ""
572        }
573    }
574
575    # Called when an image is entered
576    method EnterImage {x y} {
577        set ndx [$hull index @$x,$y]
578        $self Msg $imageData($ndx)
579    }
580
581    # Called when an image is left
582    method LeaveImage {x y} {
583        $self Msg ""
584    }
585
586    # Called to write a message to the -messagecommand.
587    method Msg {text} {
588        if {$options(-messagecommand) eq ""} {
589            return
590        }
591
592        set cmd $options(-messagecommand)
593        lappend cmd $text
594        uplevel \#0 $cmd
595    }
596
597    # Called when the title is clicked.
598    method TitleHandler {x y} {
599        set command $options(-titlecommand)
600
601        if {$command eq ""} {
602            return
603        }
604
605        # As formatted, the title includes leading and trailing
606        # whitespace; delete it.
607        lappend command [string trim [$self GetTagText title $x $y]]
608        uplevel \#0 $command
609    }
610
611    # Called when a link is clicked.
612    method LinkHandler {x y} {
613        set command $options(-linkcommand)
614
615        if {$command eq ""} {
616            return
617        }
618
619        set range [$self GetTagRange link $x $y]
620        set name  [$hull get [lindex $range 0] [lindex $range 1]]
621        set index [lindex $range 0]
622
623        lappend command $bcode([string tolower $name]-$index)
624        uplevel \#0 $command
625    }
626
627    # Finds the button script and calls the button command
628    method ButtonHandler {x y} {
629        set command $options(-buttoncommand)
630
631        if {$command eq ""} {
632            return
633        }
634
635        set range [$self GetTagRange button $x $y]
636        set name  [$hull get [lindex $range 0] [lindex $range 1]]
637        set index [lindex $range 0]
638
639        lappend command $bcode([string tolower $name]-$index)
640        uplevel \#0 $command
641    }
642
643    # Finds the macroerror macro text and calls the macroerror command
644    method MacroErrorHandler {x y} {
645        set command $options(-macroerrorcommand)
646
647        if {$command eq ""} {
648            return
649        }
650
651        # The macro [@ @] brackets are included in the text; remove
652        # them.
653        set macro [string range [$self GetTagText macroerror $x $y] 2 end-2]
654
655        lappend command $macro
656        uplevel \#0 $command
657    }
658
659    # defines and updates style tags when preferences change.
660    method UsePreferences {} {
661        # TBD: Make this a preference setting.
662        set tabWidth 0.2
663
664        $win.bullet1 configure \
665            -foreground [prefs get normalfg] \
666            -background [prefs get normalbg] \
667
668        $win.bullet2 configure \
669            -foreground [prefs get normalfg] \
670            -background [prefs get normalbg] \
671
672        $win.bullet3 configure \
673            -foreground [prefs get normalfg] \
674            -background [prefs get normalbg] \
675
676        $hull configure \
677            -foreground [prefs get normalfg] \
678            -background [prefs get normalbg] \
679            -font [prefs get bodytext] \
680            -tabs [list ${tabWidth}i [expr $tabWidth*2]i]
681
682        $hull tag configure title \
683            -font [prefs get titletext] \
684            -foreground [prefs get titlefg] \
685            -background [prefs get titlebg]
686
687        $hull tag configure header1 \
688            -font [prefs get header1text]
689
690        $hull tag configure header2 \
691            -font [prefs get header2text]
692
693        $hull tag configure header3 \
694            -font [prefs get header3text]
695
696        $hull tag configure small \
697            -font [prefs get smalltext]
698
699        $hull tag configure bold \
700            -font [concat [prefs get bodytext] bold]
701
702        $hull tag configure italic \
703            -font [concat [prefs get bodytext] italic]
704
705        $hull tag configure bolditalic \
706            -font [concat [prefs get bodytext] [list bold italic]]
707
708        $hull tag configure mono \
709            -font [prefs get monotext]
710
711        $hull tag configure monobold \
712            -font [concat [prefs get monotext] bold]
713
714        $hull tag configure monoitalic \
715            -font [concat [prefs get monotext] italic]
716
717        $hull tag configure monobolditalic \
718            -font [concat [prefs get monotext] [list bold italic]]
719
720        $hull tag configure strike \
721            -overstrike 1
722
723        $hull tag configure link \
724            -foreground [prefs get linkfg] \
725            -background [prefs get linkbg]
726
727        $hull tag configure warning \
728            -foreground [prefs get warningfg] \
729            -background [prefs get warningbg]
730
731        $hull tag configure warningmono \
732            -font [prefs get monotext] \
733            -foreground [prefs get warningfg] \
734            -background [prefs get warningbg]
735
736        $hull tag configure button \
737            -foreground [prefs get buttonfg] \
738            -background [prefs get buttonbg]
739
740        $hull tag configure macroerror \
741            -font [prefs get monotext] \
742            -foreground [prefs get warningfg] \
743            -background [prefs get warningbg]
744
745        $hull tag configure pre \
746            -font [prefs get monotext] \
747            -foreground [prefs get prefg] \
748            -background [prefs get prebg]
749
750        $hull tag configure tcl \
751            -font [prefs get monotext] \
752            -foreground [prefs get tclfg] \
753            -background [prefs get tclbg]
754
755        $hull tag configure search \
756            -foreground [prefs get searchfg] \
757            -background [prefs get searchbg]
758
759        # Up to 9 levels of indent
760        for {set i 1} {$i <= 9} {incr i} {
761            $hull tag configure "indent$i" \
762                -lmargin2 [expr $i*$tabWidth]i
763        }
764
765        # Give highest priority to the selection to make it visible when some
766        # text with a non-default background is selected
767        $hull tag raise sel
768    }
769
770    # Inserts a horizontal line into the pane by creating a frame widget.
771    method InsertHLine {} {
772        # First, create the frame as a child of the pane.
773        incr counter
774        set f $win.h$counter
775
776        set width [expr {[winfo reqwidth $win] - 20}]
777
778        frame $f -height 4 -width $width -background white \
779            -borderwidth 2 -relief groove
780
781        # Next, insert it into the pane.
782        $hull window create end -window $f -align center -pady 3
783        $hull insert end "\n" pre
784    }
785
786    # Removes leading and trailing whitespace, and reduces internal whitespace
787    # sequences to one space.
788    proc NormalizeSpace {text} {
789        regsub -all {\n} $text " " text
790        regsub -all {\s+} $text " " text
791 
792        return [string trim $text]
793    }
794
795    # Reduces internal whitespace sequences which contain a newline
796    # to a single space.  Other whitespace is left alone.
797    proc NormalizeNewlines {text} {
798        regsub -all {\s*\n\s*} $text " " text
799 
800        return $text
801    }
802
803    # Parses an image request, and loads and inserts the image.
804    method InsertImage {arglist} {
805        set fileName [file join $options(-dbdir) [lindex $arglist 1]]
806
807        array set opts [lindex $arglist 2]
808
809        if {$opts(-text) ne ""} {
810            set disptext "$opts(-text): $fileName"
811        } else {
812            set disptext $fileName
813        }
814
815        try {
816            set images [LoadImage $fileName $opts(-width) $opts(-height)]
817        } catch -msg msg {
818            puts "Couldn't load '$fileName': $msg"
819          set images [ list $options(-missingimage) ]
820        }
821
822        # NEXT, insert it into the text window.  If there's only one
823        # image, just insert it normally; otherwise, insert the strips.
824        # If there's a list, insert them in sequence.
825        if {[llength $images] == 1} {
826            set imageIndex [$hull index insert]
827            set imageData($imageIndex) $disptext
828            $hull image create end -image [lindex $images 0] \
829                -padx $opts(-padwidth)
830
831            $hull tag add image $imageIndex
832        } else {
833            foreach img $images {
834                if {[$hull compare insert > "insert linestart"]} {
835                    $hull insert insert "\n"
836                }
837                set imageIndex [$hull index insert]
838                set imageData($imageIndex) $disptext
839                $hull image create end -image $img \
840                    -padx $opts(-padwidth)
841                $hull tag add image $imageIndex
842            }
843        }
844    }
845
846    # Destroys all loaded images
847    method FreeImages {} {
848        array unset imageData
849
850        foreach img $imageList {
851            image delete $img
852        }
853        set imageList {}
854    }
855
856    # Loads an image, subsampling down to the desired size.
857    # Pass 0 width, 0 height for the default size.
858    # If the image is "tall", it's broken into strips;
859    # this helps everything scroll better.
860    proc LoadImage {filename {width 0} {height 0}} {
861        puts "LoadImage $filename"
862        if { [ file readable $filename ] } {
863          # FIRST, load the image
864          set img [image create photo -file $filename]
865        } elseif { [ lsearch [ image names ] $filename ] != -1 } {
866          # It is a valid tk image
867          set img $filename
868        } else {
869          error "$filename does not reference a valid image"
870        }
871        # NEXT, if the width and height are both 0, scale it..
872        if {$width > 0 || $height > 0} {
873            # FIRST, figure out how to scale it.
874            set iwidth [image width $img]
875            set iheight [image height $img]
876
877            if {$width == 0} {
878                set width $iwidth
879            }
880
881            if {$height == 0} {
882                set height $iheight
883            }
884           
885            set scale 1
886           
887            while {$iheight/$scale > $height ||
888                   $iwidth/$scale > $width} {
889                incr scale
890            }
891
892            # NEXT, scale the image, and delete the original.
893            set iheight [expr {$iheight/$scale}]
894            set iwidth [expr {$iwidth/$scale}]
895            set dest [image create photo]
896            $dest copy $img -subsample $scale
897
898            image delete $img
899
900            set img $dest
901        }
902
903        # NEXT, if the image is tall, cut it into horizontal strips,
904        # and return a list of the strips.  This allows the text
905        # widget to scroll more nicely.
906        set iheight [image height $img]
907        set iwidth [image width $img]
908
909        set stripHeight 25
910       
911        if {1 || $iheight <= $stripHeight} {
912            lappend imageList $img
913
914            return [list $img]
915        }
916
917        set iy 0
918        set results {}
919        while {$iy < $iheight} {
920            if {$iy + $stripHeight > $iheight} {
921                set stripHeight [expr {$iheight - $iy}]
922            }
923
924            set strip [image create photo]
925            $strip copy $img -from 0 $iy $iwidth [incr iy $stripHeight]
926            lappend results $strip
927            lappend imageList $strip
928        }
929       
930        # NEXT, we no longer need the image from which we took the strips.
931        image delete $img
932
933        return $results
934    }
935}
936
937package provide renderpane 2.1.3
Note: See TracBrowser for help on using the repository browser.