source: tol/tolbase/lib/markupviewer/markupviewer.tcl

devel
Last change on this file was 3634546, checked in by Pedro Gea <pgea@…>, 11 years ago

Se modifica el uso que se hace del paquete trycatch para evitar incompatibilidades con tcl8.6:

+ No se importan los métodos del paquete
+ Se llaman las llamadas a try haciendo uso del namespace: ::trycatach::try

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

  • Property mode set to 100644
File size: 14.3 KB
Line 
1#-----------------------------------------------------------------------
2# TITLE:
3#       markupviewer.tcl
4#
5# AUTHOR:
6#       inspired in Will Duquette
7#
8# DESCRIPTION:
9#       A viewer for browsing Notebook pages. Simplified version of
10#       pageviewer.tcl
11#
12# LICENSE:
13#
14#-----------------------------------------------------------------------
15
16package require snit
17package require renderpane
18
19package require autoscroll 1.1
20
21snit::widget markupviewer {
22    # A command to use for outputting messages.  The message will be
23    # appended.
24    option -messagecommand {}
25 
26    #-------------------------------------------------------------------
27    # Other options
28
29    # A command that's called when the displayed page changes. The
30    # command gets one argument, the page name.
31    option -pagecommand {}
32
33    # A command that's called when we try to display a page that
34    # doesn't exist.
35    option -unknowncommand {}
36
37    # The notebook database
38    option -db -default {} -readonly 1
39
40    # control if the title is rendered on the renderpane
41    option -showtitle -default 1
42
43    #-------------------------------------------------------------------
44    # Components
45
46    variable db
47
48    # The renderpane is the component that actually displays the
49    # rendered page.
50    variable rp
51
52    #--------------------------------------------------------------------
53    # Other variables
54
55    # The history list is a list of {PageName PagePos} pairs.
56    variable history {}
57
58    # The histPos is the index of the currently displayed page in the
59    # history list.  It's initially -1 because there's nothing in the
60    # list.
61    variable histPos -1
62
63    # A list of recently displayed pages.  Each page appears only once,
64    # regardless of how often (and where) it appears in the history list.
65    # There will be ten pages listed, maximum; no more than one of them
66    # are guaranteed to still exist.
67    variable recentPages {}
68
69    #--------------------------------------------------------------------
70    # Constructor
71
72    constructor {args} {
73        # As yet we have no option delegation, so go ahead and get the
74        # args
75        $self configurelist $args
76
77        if { $options(-db) eq "" } {
78          error "Invalid database option: '$options(-db)'"
79        }
80        set db $options(-db)
81
82        # Create the renderpane.
83
84        install rp using renderpane $win.rp \
85            -yscrollcommand "$win.scroll set" \
86            -querycommand      [mymethod pageexists] \
87            -titlecommand      [mymethod TitleHandler] \
88            -linkcommand       [mymethod LinkHandler] \
89            -buttoncommand     [mymethod ButtonHandler] \
90            -macroerrorcommand [mymethod MacroErrorHandler] \
91            -messagecommand    $options(-messagecommand)
92
93        scrollbar $win.scroll \
94            -command "$win.rp yview"
95
96        # grid them in.
97        # josp: use grid and autoscroll
98        if { 0 } {
99          pack $win.scroll  -side right -fill y    -expand false
100          pack $rp          -side top   -fill both -expand true
101        }
102
103        grid $rp -row 0 -column 0 -sticky "snew"
104        grid $win.scroll -row 0 -column 1 -sticky "ns"
105        grid rowconfigure $win 0 -weight 1
106        grid columnconfigure $win 0 -weight 1
107        ::autoscroll::autoscroll $win.scroll
108
109        #---------------------------------------------------------------
110        # User Interactions
111
112        # Add the pageviewer window itself to the renderpane's bindtags,
113        # so that keys bound to the pageviewer will take effect when the
114        # renderpane has focus
115        set tags [bindtags $rp]
116        lappend tags $win
117        bindtags $rp $tags
118
119        # Go to the previous page when <BackSpace> is pressed.
120        bind $rp <BackSpace> [list $self backpage]
121
122        # User Menu.
123        # josp: no user menu considered
124        if { 0 } {
125          menu $rp.user -tearoff no -postcommand [mymethod PostUserMenu]
126         
127          $rp.user add command -label "User Menu"
128          $rp.user add separator
129          $rp.user add command -label "Dummy"
130         
131          bind $rp <Control-1> [list tk_popup $rp.user %X %Y 2]
132          bind $rp <3>         [list tk_popup $rp.user %X %Y 2]
133         
134          # Recent Pages Menu.
135          menu $rp.recent -tearoff no -postcommand [mymethod PostRecent]
136         
137          $rp.recent add command -label "Recent Pages"
138          $rp.recent add separator
139          $rp.recent add command -label "Dummy"
140         
141          bind $rp <Shift-1> [list tk_popup $rp.recent %X %Y 2]
142        }
143        #---------------------------------------------------------------
144        # Prepare to receive preferences events; unregister on
145        # destroy.
146        prefs register $selfns [mymethod UsePreferences]
147    }
148
149    destructor {
150        catch {prefs unregister $selfns}
151    }
152
153    # josp: delegate methods in order to use it as text
154    delegate method tag to rp
155    delegate method index to rp
156    delegate method search to rp
157    delegate method compare to rp
158    delegate method mark to rp
159    delegate method see to rp
160    delegate method edit to rp
161    delegate method get to rp
162    delegate option -autoseparators to rp
163    delegate option -font to rp
164
165    delegate method UsePreferences to rp
166    # josp: delegate UsePreferences on renderpane
167    if { 0 } {
168      method UsePreferences {} {
169        # Update the display when the preferences change.
170        $self showpage
171      }
172    }
173
174    #-------------------------------------------------------------------
175    # Public Methods
176
177    delegate method searchfor to rp
178
179    delegate method pagetime     to db
180    delegate method pagename     to db      as name
181
182    method pageexists { name } {
183      if { [ $db exists $name ] } {
184        return 1
185      } else {
186        return [ regexp "(http|https)://" $name ]
187      }
188    }
189
190    # Returns the expanded text of the page, which must exist.
191    method pageexpand {name} {
192      ::trycatch::try {
193        set result [$db expand [$db get $name]]
194      }
195      return $result
196    }
197
198    # Returns the name of the currently displayed page, or "" if none.
199    # Note that during a deletion or page renaming the named page
200    # is not guaranteed to exist.
201    method current {} {
202      return [lindex $history $histPos 0]
203    }
204
205    # Tells the pageviewer to take the keyboard focus.
206    # If -friendly, we take the focus only if our toplevel already
207    # has it (e.g., we take the focus back from the search box).
208    method focus {{option {}}} {
209      set focusWin [focus]
210     
211      if {$focusWin eq ""} {
212        return
213      }
214     
215      if {$option ne "-friendly" ||
216          [winfo toplevel $win] eq [winfo toplevel $focusWin]} {
217        focus $rp
218      }
219    }
220   
221    # Shows the named page.  The -unknowncommand is called if the
222    # page doesn't exist.
223    method showpage {{name ""}} {
224        # FIRST, remember the position for the page we're showing now.
225        if {$histPos >= 0} {
226            lset history $histPos 1 [$self GetPos]
227        }
228
229        # NEXT, default to the current page.
230        if {$name eq ""} {
231            set name [$self current]
232
233            if {$name eq ""} {
234                error "no current page."
235            }
236        }
237
238        # NEXT, if the page doesn't exist, call the -unknowncommand.
239        if {![$self pageexists $name]} {
240            if {$options(-unknowncommand) ne {}} {
241                set command $options(-unknowncommand)
242                lappend command $name
243                uplevel \#0 $command
244            } else {
245                return -code error -errorcode USER "No such page: '$name'"
246            }
247
248            return
249        }
250
251        # NEXT, save the new page in the history list.  When we show
252        # a new page, any pages forward of our position go away.
253        set history [lrange $history 0 $histPos]
254        lappend history [list [$self pagename $name] 0]
255        incr histPos
256
257        # NEXT, display it.
258        $self DisplayPage
259    }
260    # Steps back one page, if possible
261    method backpage {} {
262        # FIRST, remember the position for the page we're showing now.
263        if {$histPos >= 0} {
264            lset history $histPos 1 [$self GetPos]
265        }
266
267        # NEXT, Look back through the history list for a page that exists,
268        # and is also different than the current page.
269        set current [lindex $history $histPos 0]
270        set pos [expr {$histPos - 1}]
271
272        while {$pos >= 0} {
273            set candidate [lindex $history $pos 0]
274
275            if {[$self pageexists $candidate]} {
276
277                if {![string equal -nocase $candidate $current]} {
278                    break
279                }
280            }
281
282            incr pos -1
283        }
284
285        if {$pos < 0} {
286            bell
287            return
288        }
289
290        set histPos $pos
291
292        $self DisplayPage
293    }
294
295    # Steps forward one page, if possible
296    method forwardpage {} {
297        # FIRST, remember the position for the page we're showing now.
298        if {$histPos >= 0} {
299            lset history $histPos 1 [$self GetPos]
300        }
301
302        # NEXT, Look forward through the history list for a page that exists,
303        # and is also different than the current page.
304        set current [lindex $history $histPos 0]
305        set pos [expr {$histPos + 1}]
306        set len [llength $history]
307
308        while {$pos < $len} {
309            set candidate [lindex $history $pos 0]
310
311            if {[$self pageexists $candidate]} {
312
313                if {![string equal -nocase $candidate $current]} {
314                    break
315                }
316            }
317
318            incr pos
319        }
320
321        if {$pos >= $len} {
322            bell
323            return
324        }
325
326        set histPos $pos
327
328        $self DisplayPage
329    }
330
331    # Shows the page from the beginning of the Recent Pages list, if it exists.
332    method cyclerecent {} {
333        foreach id $recentPages {
334            if {[$self pageexists $id]} {
335                $self showpage $id
336                break
337            }
338        }
339    }
340
341    #-------------------------------------------------------------------
342    # Private Methods
343
344    # Display the current page
345    method DisplayPage { } {
346        # FIRST, Get the current page specs
347        set name [$self pagename [lindex $history $histPos 0]]
348        set ypos [lindex $history $histPos 1]
349
350        # NEXT, add the name to the list of recent pages
351        $self SaveRecentPage $name
352
353        # NEXT, Expand the requested page and display it.
354        set pagetext [$self pageexpand $name]
355
356        if { $options(-showtitle) } {
357          $rp render $name $pagetext
358        } else {
359          $rp render "" $pagetext
360        }
361       
362        # josp: don't known what is it for
363        if { 0 } {
364          $rp searchfor [$self searchtext]
365        }
366        # NEXT, give the renderpane the focus so that we don't
367        # need to click in it.
368
369        #$self focus -friendly
370
371        $self setpos $ypos
372
373        # NEXT, notify those concerned.
374        if {$options(-pagecommand) ne {}} {
375            set command $options(-pagecommand)
376            lappend command $name
377            uplevel \#0 $command
378        }
379    }
380
381    # Save the specified page to the recent pages list, removing
382    # any previous entry with the same name.  Names are stored
383    # in lower case.  No more than ten names are stored.
384    method SaveRecentPage {name} {
385        set name [string tolower $name]
386
387        set ndx [lsearch -exact $recentPages $name]
388
389        if {$ndx != -1} {
390            set recentPages [lreplace $recentPages $ndx $ndx]
391        }
392
393        lappend recentPages $name
394       
395        # Cut down back to ten, if need be
396        if {[llength $recentPages] == 11} {
397            set recentPages [lreplace $recentPages 0 0]
398        }
399    }
400   
401
402    # Get the y-position of the text at the top of the window.
403    method GetPos {} {
404        lindex [$rp yview] 0
405    }
406
407    # Set the y-position of the text at the top of the window.
408    method setpos  {ypos} {
409        $rp yview moveto $ypos
410    }
411
412    # Called when the user clicks on the title text.
413    method TitleHandler {title} {
414        $self showsearch $title
415    }
416
417    # Called when the user clicks on a link; shows the linked page.
418    method LinkHandler {linkName} {
419      if { [ regexp "(http|https)://" $linkName ] } {
420        LaunchBrowser $linkName
421      } else {
422        $self showpage $linkName
423      }
424    }
425
426    # Called when the user clicks on a magic button; calls the button's script
427    method ButtonHandler {script} {
428        $self evaluser $script
429    }
430
431    # Finds the macro error text and displays the error message.
432    method MacroErrorHandler {macro} {
433        $self evaluser $macro
434        # TBD: If macros are disabled, then clicking on this won't
435        # display an error.  We need to handle this somehow.
436    }
437
438    # procs
439
440    proc LaunchBrowser { url } {
441      global tcl_platform
442     
443      # It *is* generally a mistake to switch on $tcl_platform(os), particularly
444      # in comparison to $tcl_platform(platform).  For now, let's just regard it
445      # as a stylistic variation subject to debate.
446      switch $tcl_platform(os) {
447        Darwin {
448          set command [list open $url]
449        }
450        HP-UX -
451        Linux  -
452        SunOS {
453          foreach executable {firefox mozilla netscape iexplorer opera lynx
454            w3m links epiphany galeon konqueror mosaic amaya
455            browsex elinks} {
456            set executable [auto_execok $executable]
457            if [string length $executable] {
458              # Do you want to mess with -remote?  How about other browsers?
459              # Frank Darby says the '&' leads on his Ubuntu to attempts to
460              # open 'www.&.com', and so on.
461              set command [list $executable $url &]
462              set command [list $executable $url]
463              break
464            }
465          }
466        }
467        {Windows 95} -
468        {Windows NT} {
469          set command "[auto_execok start] {} [list $url]"
470        }
471      }
472      if [info exists command] {
473        # Replace {*}$command by eval "$command" if you want < tcl 8.5 compatibility ([RA])
474        # Added the '&' to launch the browser as background process. [Duoas]
475        if [catch {eval exec $command &} err] {
476          tk_messageBox -icon error -message "error '$err' with '$command'"
477        }
478      } else {
479        tk_messageBox -icon error -message \
480            "Please tell CL that ($tcl_platform(os), $tcl_platform(platform)) is not yet ready for browsing."
481      }
482    }
483}
484
485package provide markupviewer 1.0
Note: See TracBrowser for help on using the repository browser.