1#!/bin/sh
2# the next line restarts using wish \
3exec wish "$0" "$@"
4
5# widget --
6# This script demonstrates the various widgets provided by Tk, along with many
7# of the features of the Tk toolkit. This file only contains code to generate
8# the main window for the application, which invokes individual
9# demonstrations. The code for the actual demonstrations is contained in
10# separate ".tcl" files is this directory, which are sourced by this script as
11# needed.
12#
13# RCS: @(#) $Id$
14
15package require Tcl	8.5
16package require Tk	8.5
17package require msgcat
18package require Ttk
19
20eval destroy [winfo child .]
21set tk_demoDirectory [file join [pwd] [file dirname [info script]]]
22::msgcat::mcload $tk_demoDirectory
23namespace import ::msgcat::mc
24wm title . [mc "Widget Demonstration"]
25if {[tk windowingsystem] eq "x11"} {
26    # This won't work everywhere, but there's no other way in core Tk at the
27    # moment to display a coloured icon.
28    image create photo TclPowered \
29	    -file [file join $tk_library images logo64.gif]
30    wm iconwindow . [toplevel ._iconWindow]
31    pack [label ._iconWindow.i -image TclPowered]
32    wm iconname . [mc "tkWidgetDemo"]
33}
34
35if {"defaultFont" ni [font names]} {
36    # TIP #145 defines some standard named fonts
37    if {"TkDefaultFont" in [font names] && "TkFixedFont" in [font names]} {
38        # FIX ME: the following technique of cloning the font to copy it works
39        #         fine but means that if the system font is changed by Tk
40        #         cannot update the copied font. font alias might be useful
41        #         here -- or fix the app to use TkDefaultFont etc.
42        font create mainFont   {*}[font configure TkDefaultFont]
43        font create fixedFont  {*}[font configure TkFixedFont]
44        font create boldFont   {*}[font configure TkDefaultFont] -weight bold
45        font create titleFont  {*}[font configure TkDefaultFont] -weight bold
46        font create statusFont {*}[font configure TkDefaultFont]
47        font create varsFont   {*}[font configure TkDefaultFont]
48	if {[tk windowingsystem] eq "aqua"} {
49	    font configure titleFont -size 17
50	}
51    } else {
52        font create mainFont   -family Helvetica -size 12
53        font create fixedFont  -family Courier   -size 10
54        font create boldFont   -family Helvetica -size 12 -weight bold
55        font create titleFont  -family Helvetica -size 18 -weight bold
56        font create statusFont -family Helvetica -size 10
57        font create varsFont   -family Helvetica -size 14
58    }
59}
60
61set widgetDemo 1
62set font mainFont
63
64image create photo ::img::refresh -format GIF -data {
65    R0lGODlhEAAQAJEDAP///wAAACpnKv///yH5BAEAAAMALAAAAAAQABAAAAI63IKp
66    xgcPH2ouwgBCw1HIxHCQ4F3hSJKmwZXqWrmWxj7lKJ2dndcon9EBUq+gz3brVXAR
67    2tICU0gXBQA7
68}
69
70image create photo ::img::view -format GIF -data {
71    R0lGODlhEAAQAKIHAP///wwMDAAAAMDAwNnZ2SYmJmZmZv///yH5BAEAAAcALAAA
72    AAAQABAAAANMKLos90+ASamDRxJCgw9YVnlDOXiQBgRDBRgHKE6sW8QR3doPKK27
73    yg33q/GIOhdg6OsEJzeZykiBSUcs06e56Xx6np8ScIkFGuhQAgA7
74}
75
76image create photo ::img::delete -format GIF -data {
77    R0lGODlhEAAQAIABAIQAAP///yH5BAEAAAEALAAAAAAQABAAAAIjjI+pmwAc3HGy
78    PUSvqYpuvWQg40FfSVacBa5nN6JYDI3mzRQAOw==
79}
80
81image create photo ::img::print -format GIF -data {
82    R0lGODlhEAAQALMKAAAAAP///52VunNkl8C82Yl+qldBgq+pyrOzs1fYAP///wAA
83    AAAAAAAAAAAAAAAAACH5BAEAAAoALAAAAAAQABAAAARGUMlJKwU4AztB+ODGeUiJ
84    fGLlgeEYmGWQXmx7aXgmAUTv/74N4EAsGhOJg1DAbDqbwoJ0Sp0KB9isNis0eL/g
85    ryhH5pgnEQA7
86}
87
88# Note that this is run through the message catalog! This is because this is
89# actually an image of a word.
90image create photo ::img::new -format GIF -data [mc {
91    R0lGODlhHgAOALMPALMAANyIiOu7u8dEROaqqvru7sxVVeGZmbgREfXd3b0iItZ3
92    d8IzM9FmZvDMzP///yH5BAEAAA8ALAAAAAAeAA4AAASa8MlJq7046827WVOCHEkw
93    nANhUgJlEBIABJIwL3K+4IcUALCHjfbItYZDSgJgkBiYPmBMAUAkkLPKs/BAyLgM
94    wAQwOAAY2ByCaw4QAFQSoDEePJ6DmU1xInYZTw5nOEFFdgVUelkVDTIMd3AKFGQ1
95    MgI2AwEmQW8APZ0gdRONAks5nhIFVVxdAAkUAS2pAVwFl7ITB4UqHb0XEQA7
96}]
97
98#----------------------------------------------------------------
99# The code below create the main window, consisting of a menu bar and a text
100# widget that explains how to use the program, plus lists all of the demos as
101# hypertext items.
102#----------------------------------------------------------------
103
104menu .menuBar -tearoff 0
105
106if {[tk windowingsystem] ne "aqua"} {
107    # This is a tk-internal procedure to make i18n easier
108    ::tk::AmpMenuArgs .menuBar add cascade -label [mc "&File"] \
109	    -menu .menuBar.file
110    menu .menuBar.file -tearoff 0
111    ::tk::AmpMenuArgs .menuBar.file add command -label [mc "&About..."] \
112	    -command {tkAboutDialog} -accelerator [mc "<F1>"]
113    bind . <F1> {tkAboutDialog}
114    .menuBar.file add sep
115    if {[string match win* [tk windowingsystem]]} {
116	# Windows doesn't usually have a Meta key
117	::tk::AmpMenuArgs .menuBar.file add command -label [mc "&Quit"] \
118		-command {exit} -accelerator [mc "Ctrl+Q"]
119	bind . <[mc "Control-q"]> {exit}
120    } else {
121	::tk::AmpMenuArgs .menuBar.file add command -label [mc "&Quit"] \
122		-command {exit} -accelerator [mc "Meta-Q"]
123	bind . <[mc "Meta-q"]> {exit}
124    }
125}
126
127. configure -menu .menuBar
128
129ttk::frame .statusBar
130ttk::label .statusBar.lab -text "   " -anchor w
131if {[tk windowingsystem] eq "aqua"} {
132    ttk::separator .statusBar.sep
133    pack .statusBar.sep -side top -expand yes -fill x -pady 0
134}
135pack .statusBar.lab -side left -padx 2 -expand yes -fill both
136if {[tk windowingsystem] ne "aqua"} {
137    ttk::sizegrip .statusBar.foo
138    pack .statusBar.foo -side left -padx 2
139}
140pack .statusBar -side bottom -fill x -pady 2
141
142set textheight 30
143catch {
144    set textheight [expr {
145	([winfo screenheight .] * 0.7) /
146	[font metrics mainFont -displayof . -linespace]
147    }]
148}
149
150ttk::frame .textFrame
151scrollbar .s -orient vertical -command {.t yview} -takefocus 1
152pack .s -in .textFrame -side right -fill y
153text .t -yscrollcommand {.s set} -wrap word -width 70 -height $textheight \
154	-font mainFont -setgrid 1 -highlightthickness 0 \
155	-padx 4 -pady 2 -takefocus 0
156pack .t -in .textFrame -expand y -fill both -padx 1
157pack .textFrame -expand yes -fill both
158if {[tk windowingsystem] eq "aqua"} {
159    pack configure .statusBar.lab -padx {10 18} -pady {4 6}
160    pack configure .statusBar -pady 0
161    .t configure -padx 10 -pady 0
162}
163
164# Create a bunch of tags to use in the text widget, such as those for section
165# titles and demo descriptions. Also define the bindings for tags.
166
167.t tag configure title -font titleFont
168.t tag configure subtitle -font titleFont
169.t tag configure bold  -font boldFont
170if {[tk windowingsystem] eq "aqua"} {
171    .t tag configure title -spacing1 8
172    .t tag configure subtitle -spacing3 3
173}
174
175# We put some "space" characters to the left and right of each demo
176# description so that the descriptions are highlighted only when the mouse
177# cursor is right over them (but not when the cursor is to their left or
178# right).
179#
180.t tag configure demospace -lmargin1 1c -lmargin2 1c
181
182if {[winfo depth .] == 1} {
183    .t tag configure demo -lmargin1 1c -lmargin2 1c \
184	-underline 1
185    .t tag configure visited -lmargin1 1c -lmargin2 1c \
186	-underline 1
187    .t tag configure hot -background black -foreground white
188} else {
189    .t tag configure demo -lmargin1 1c -lmargin2 1c \
190	-foreground blue -underline 1
191    .t tag configure visited -lmargin1 1c -lmargin2 1c \
192	-foreground #303080 -underline 1
193    .t tag configure hot -foreground red -underline 1
194}
195.t tag bind demo <ButtonRelease-1> {
196    invoke [.t index {@%x,%y}]
197}
198set lastLine ""
199.t tag bind demo <Enter> {
200    set lastLine [.t index {@%x,%y linestart}]
201    .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
202    .t config -cursor [::ttk::cursor link]
203    showStatus [.t index {@%x,%y}]
204}
205.t tag bind demo <Leave> {
206    .t tag remove hot 1.0 end
207    .t config -cursor [::ttk::cursor text]
208    .statusBar.lab config -text ""
209}
210.t tag bind demo <Motion> {
211    set newLine [.t index {@%x,%y linestart}]
212    if {$newLine ne $lastLine} {
213	.t tag remove hot 1.0 end
214	set lastLine $newLine
215
216	set tags [.t tag names {@%x,%y}]
217	set i [lsearch -glob $tags demo-*]
218	if {$i >= 0} {
219	    .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
220	}
221    }
222    showStatus [.t index {@%x,%y}]
223}
224
225##############################################################################
226# Create the text for the text widget.
227
228# addFormattedText --
229#
230#	Add formatted text (but not hypertext) to the text widget after first
231#	passing it through the message catalog to allow for localization.
232#	Lines starting with @@ are formatting directives (insert title, insert
233#	demo hyperlink, begin newline, or change style) and all other lines
234#	are literal strings to be inserted. Substitutions are performed,
235#	allowing processing pieces through the message catalog. Blank lines
236#	are ignored.
237#
238proc addFormattedText {formattedText} {
239    set style normal
240    set isNL 1
241    set demoCount 0
242    set new 0
243    foreach line [split $formattedText \n] {
244	set line [string trim $line]
245	if {$line eq ""} {
246	    continue
247	}
248	if {[string match @@* $line]} {
249	    set data [string range $line 2 end]
250	    set key [lindex $data 0]
251	    set values [lrange $data 1 end]
252	    switch -exact -- $key {
253		title {
254		    .t insert end [mc $values]\n title \n normal
255		}
256		newline {
257		    .t insert end \n $style
258		    set isNL 1
259		}
260		subtitle {
261		    .t insert end "\n" {} [mc $values] subtitle \
262			    " \n " demospace
263		    set demoCount 0
264		}
265		demo {
266		    set description [lassign $values name]
267		    .t insert end "[incr demoCount]. [mc $description]" \
268			    [list demo demo-$name]
269		    if {$new} {
270			.t image create end -image ::img::new -padx 5
271			set new 0
272		    }
273		    .t insert end " \n " demospace
274		}
275		new {
276		    set new 1
277		}
278		default {
279		    set style $key
280		}
281	    }
282	    continue
283	}
284	if {!$isNL} {
285	    .t insert end " " $style
286	}
287	set isNL 0
288	.t insert end [mc $line] $style
289    }
290}
291
292addFormattedText {
293    @@title	Tk Widget Demonstrations
294
295    This application provides a front end for several short scripts
296    that demonstrate what you can do with Tk widgets.  Each of the
297    numbered lines below describes a demonstration; you can click on
298    it to invoke the demonstration.  Once the demonstration window
299    appears, you can click the
300    @@bold
301    See Code
302    @@normal
303    button to see the Tcl/Tk code that created the demonstration.  If
304    you wish, you can edit the code and click the
305    @@bold
306    Rerun Demo
307    @@normal
308    button in the code window to reinvoke the demonstration with the
309    modified code.
310    @@newline
311
312    @@subtitle	Labels, buttons, checkbuttons, and radiobuttons
313    @@demo label	Labels (text and bitmaps)
314    @@demo unicodeout	Labels and UNICODE text
315    @@demo button	Buttons
316    @@demo check	Check-buttons (select any of a group)
317    @@demo radio	Radio-buttons (select one of a group)
318    @@demo puzzle	A 15-puzzle game made out of buttons
319    @@demo icon		Iconic buttons that use bitmaps
320    @@demo image1	Two labels displaying images
321    @@demo image2	A simple user interface for viewing images
322    @@demo labelframe	Labelled frames
323    @@new
324    @@demo ttkbut	The simple Themed Tk widgets
325
326    @@subtitle	Listboxes and Trees
327    @@demo states	The 50 states
328    @@demo colors	Colors: change the color scheme for the application
329    @@demo sayings	A collection of famous and infamous sayings
330    @@new
331    @@demo mclist	A multi-column list of countries
332    @@new
333    @@demo tree		A directory browser tree
334
335    @@subtitle	Entries, Spin-boxes and Combo-boxes
336    @@demo entry1	Entries without scrollbars
337    @@demo entry2	Entries with scrollbars
338    @@demo entry3	Validated entries and password fields
339    @@demo spin		Spin-boxes
340    @@new
341    @@demo combo	Combo-boxes
342    @@demo form		Simple Rolodex-like form
343
344    @@subtitle	Text
345    @@demo text		Basic editable text
346    @@demo style	Text display styles
347    @@demo bind		Hypertext (tag bindings)
348    @@demo twind	A text widget with embedded windows and other features
349    @@demo search	A search tool built with a text widget
350    @@new
351    @@demo textpeer	Peering text widgets
352
353    @@subtitle	Canvases
354    @@demo items	The canvas item types
355    @@demo plot		A simple 2-D plot
356    @@demo ctext	Text items in canvases
357    @@demo arrow	An editor for arrowheads on canvas lines
358    @@demo ruler	A ruler with adjustable tab stops
359    @@demo floor	A building floor plan
360    @@demo cscroll	A simple scrollable canvas
361    @@new
362    @@demo knightstour  A Knight's tour of the chess board
363
364    @@subtitle	Scales and Progress Bars
365    @@demo hscale	Horizontal scale
366    @@demo vscale	Vertical scale
367    @@new
368    @@demo ttkscale	Themed scale linked to a label with traces
369    @@new
370    @@demo ttkprogress	Progress bar
371
372    @@subtitle	Paned Windows and Notebooks
373    @@demo paned1	Horizontal paned window
374    @@demo paned2	Vertical paned window
375    @@new
376    @@demo ttkpane	Themed nested panes
377    @@new
378    @@demo ttknote	Notebook widget
379
380    @@subtitle	Menus and Toolbars
381    @@demo menu		Menus and cascades (sub-menus)
382    @@demo menubu	Menu-buttons
383    @@new
384    @@demo ttkmenu	Themed menu buttons
385    @@new
386    @@demo toolbar	Themed toolbar
387
388    @@subtitle	Common Dialogs
389    @@demo msgbox	Message boxes
390    @@demo filebox	File selection dialog
391    @@demo clrpick	Color picker
392
393    @@subtitle	Animation
394    @@new
395    @@demo anilabel	Animated labels
396    @@new
397    @@demo aniwave	Animated wave
398    @@new
399    @@demo pendulum	Pendulum simulation
400    @@new
401    @@demo goldberg	A celebration of Rube Goldberg
402
403    @@subtitle	Miscellaneous
404    @@demo bitmap	The built-in bitmaps
405    @@demo dialog1	A dialog box with a local grab
406    @@demo dialog2	A dialog box with a global grab
407}
408
409##############################################################################
410
411.t configure -state disabled
412focus .s
413
414# addSeeDismiss --
415# Add "See Code" and "Dismiss" button frame, with optional "See Vars"
416#
417# Arguments:
418# w -		The name of the frame to use.
419
420proc addSeeDismiss {w show {vars {}} {extra {}}} {
421    ## See Code / Dismiss buttons
422    ttk::frame $w
423    ttk::separator $w.sep
424    #ttk::frame $w.sep -height 2 -relief sunken
425    grid $w.sep -columnspan 4 -row 0 -sticky ew -pady 2
426    ttk::button $w.dismiss -text [mc "Dismiss"] \
427	-image ::img::delete -compound left \
428	-command [list destroy [winfo toplevel $w]]
429    ttk::button $w.code -text [mc "See Code"] \
430	-image ::img::view -compound left \
431	-command [list showCode $show]
432    set buttons [list x $w.code $w.dismiss]
433    if {[llength $vars]} {
434	ttk::button $w.vars -text [mc "See Variables"] \
435	    -image ::img::view -compound left \
436	    -command [concat [list showVars $w.dialog] $vars]
437	set buttons [linsert $buttons 1 $w.vars]
438    }
439    if {$extra ne ""} {
440	set buttons [linsert $buttons 1 [uplevel 1 $extra]]
441    }
442    grid {*}$buttons -padx 4 -pady 4
443    grid columnconfigure $w 0 -weight 1
444    if {[tk windowingsystem] eq "aqua"} {
445	foreach b [lrange $buttons 1 end] {$b configure -takefocus 0}
446	grid configure $w.sep -pady 0
447	grid configure {*}$buttons -pady {10 12}
448	grid configure [lindex $buttons 1] -padx {16 4}
449	grid configure [lindex $buttons end] -padx {4 18}
450    }
451    return $w
452}
453
454# positionWindow --
455# This procedure is invoked by most of the demos to position a new demo
456# window.
457#
458# Arguments:
459# w -		The name of the window to position.
460
461proc positionWindow w {
462    wm geometry $w +300+300
463}
464
465# showVars --
466# Displays the values of one or more variables in a window, and updates the
467# display whenever any of the variables changes.
468#
469# Arguments:
470# w -		Name of new window to create for display.
471# args -	Any number of names of variables.
472
473proc showVars {w args} {
474    catch {destroy $w}
475    toplevel $w
476    if {[tk windowingsystem] eq "x11"} {wm attributes $w -type dialog}
477    wm title $w [mc "Variable values"]
478
479    set b [ttk::frame $w.frame]
480    grid $b -sticky news
481    set f [ttk::labelframe $b.title -text [mc "Variable values:"]]
482    foreach var $args {
483	ttk::label $f.n$var -text "$var:" -anchor w
484	ttk::label $f.v$var -textvariable $var -anchor w
485	grid $f.n$var $f.v$var -padx 2 -pady 2 -sticky w
486    }
487    ttk::button $b.ok -text [mc "OK"] \
488	-command [list destroy $w] -default active
489    bind $w <Return> [list $b.ok invoke]
490    bind $w <Escape> [list $b.ok invoke]
491
492    grid $f -sticky news -padx 4
493    grid $b.ok -sticky e -padx 4 -pady {6 4}
494    if {[tk windowingsystem] eq "aqua"} {
495	$b.ok configure -takefocus 0
496	grid configure $b.ok -pady {10 12} -padx {16 18}
497	grid configure $f -padx 10 -pady {10 0}
498    }
499    grid columnconfig $f 1 -weight 1
500    grid rowconfigure $f 100 -weight 1
501    grid columnconfig $b 0 -weight 1
502    grid rowconfigure $b 0 -weight 1
503    grid columnconfig $w 0 -weight 1
504    grid rowconfigure $w 0 -weight 1
505}
506
507# invoke --
508# This procedure is called when the user clicks on a demo description. It is
509# responsible for invoking the demonstration.
510#
511# Arguments:
512# index -	The index of the character that the user clicked on.
513
514proc invoke index {
515    global tk_demoDirectory
516    set tags [.t tag names $index]
517    set i [lsearch -glob $tags demo-*]
518    if {$i < 0} {
519	return
520    }
521    set cursor [.t cget -cursor]
522    .t configure -cursor [::ttk::cursor busy]
523    update
524    set demo [string range [lindex $tags $i] 5 end]
525    uplevel 1 [list source [file join $tk_demoDirectory $demo.tcl]]
526    update
527    .t configure -cursor $cursor
528
529    .t tag add visited "$index linestart +1 chars" "$index lineend -1 chars"
530}
531
532# showStatus --
533#
534#	Show the name of the demo program in the status bar. This procedure is
535#	called when the user moves the cursor over a demo description.
536#
537proc showStatus index {
538    set tags [.t tag names $index]
539    set i [lsearch -glob $tags demo-*]
540    set cursor [.t cget -cursor]
541    if {$i < 0} {
542	.statusBar.lab config -text " "
543	set newcursor [::ttk::cursor text]
544    } else {
545	set demo [string range [lindex $tags $i] 5 end]
546	.statusBar.lab config -text [mc "Run the \"%s\" sample program" $demo]
547	set newcursor [::ttk::cursor link]
548    }
549    if {$cursor ne $newcursor} {
550	.t config -cursor $newcursor
551    }
552}
553
554# evalShowCode --
555#
556# Arguments:
557# w -		Name of text widget containing code to eval
558
559proc evalShowCode {w} {
560    set code [$w get 1.0 end-1c]
561    uplevel #0 $code
562}
563
564# showCode --
565# This procedure creates a toplevel window that displays the code for a
566# demonstration and allows it to be edited and reinvoked.
567#
568# Arguments:
569# w -		The name of the demonstration's window, which can be used to
570#		derive the name of the file containing its code.
571
572proc showCode w {
573    global tk_demoDirectory
574    set file [string range $w 1 end].tcl
575    set top .code
576    if {![winfo exists $top]} {
577	toplevel $top
578	if {[tk windowingsystem] eq "x11"} {wm attributes $top -type dialog}
579
580	set t [frame $top.f]
581	set text [text $t.text -font fixedFont -height 24 -wrap word \
582		      -xscrollcommand [list $t.xscroll set] \
583		      -yscrollcommand [list $t.yscroll set] \
584		      -setgrid 1 -highlightthickness 0 -pady 2 -padx 3]
585	scrollbar $t.xscroll -command [list $t.text xview] -orient horizontal
586	scrollbar $t.yscroll -command [list $t.text yview] -orient vertical
587
588	grid $t.text $t.yscroll -sticky news
589	#grid $t.xscroll
590	grid rowconfigure $t 0 -weight 1
591	grid columnconfig $t 0 -weight 1
592
593	set btns [ttk::frame $top.btns]
594	ttk::separator $btns.sep
595	grid $btns.sep -columnspan 4 -row 0 -sticky ew -pady 2
596	ttk::button $btns.dismiss -text [mc "Dismiss"] \
597	    -default active -command [list destroy $top] \
598	    -image ::img::delete -compound left
599	ttk::button $btns.print   -text [mc "Print Code"] \
600	    -command [list printCode $text $file] \
601	    -image ::img::print -compound left
602	ttk::button $btns.rerun   -text [mc "Rerun Demo"] \
603	    -command [list evalShowCode $text] \
604	    -image ::img::refresh -compound left
605	set buttons [list x $btns.rerun $btns.print $btns.dismiss]
606	grid {*}$buttons -padx 4 -pady 4
607	grid columnconfigure $btns 0 -weight 1
608	if {[tk windowingsystem] eq "aqua"} {
609	    foreach b [lrange $buttons 1 end] {$b configure -takefocus 0}
610	    grid configure $btns.sep -pady 0
611	    grid configure {*}$buttons -pady {10 12}
612	    grid configure [lindex $buttons 1] -padx {16 4}
613	    grid configure [lindex $buttons end] -padx {4 18}
614	}
615	grid $t    -sticky news
616	grid $btns -sticky ew
617	grid rowconfigure $top 0 -weight 1
618	grid columnconfig $top 0 -weight 1
619
620	bind $top <Return> {
621	    if {[winfo class %W] ne "Text"} { .code.btns.dismiss invoke }
622	}
623	bind $top <Escape> [bind $top <Return>]
624    } else {
625	wm deiconify $top
626	raise $top
627    }
628    wm title $top [mc "Demo code: %s" [file join $tk_demoDirectory $file]]
629    wm iconname $top $file
630    set id [open [file join $tk_demoDirectory $file]]
631    $top.f.text delete 1.0 end
632    $top.f.text insert 1.0 [read $id]
633    $top.f.text mark set insert 1.0
634    close $id
635}
636
637# printCode --
638# Prints the source code currently displayed in the See Code dialog. Much
639# thanks to Arjen Markus for this.
640#
641# Arguments:
642# w -		Name of text widget containing code to print
643# file -		Name of the original file (implicitly for title)
644
645proc printCode {w file} {
646    set code [$w get 1.0 end-1c]
647
648    set dir "."
649    if {[info exists ::env(HOME)]} {
650	set dir "$::env(HOME)"
651    }
652    if {[info exists ::env(TMP)]} {
653	set dir $::env(TMP)
654    }
655    if {[info exists ::env(TEMP)]} {
656	set dir $::env(TEMP)
657    }
658
659    set filename [file join $dir "tkdemo-$file"]
660    set outfile [open $filename "w"]
661    puts $outfile $code
662    close $outfile
663
664    switch -- $::tcl_platform(platform) {
665	unix {
666	    if {[catch {exec lp -c $filename} msg]} {
667		tk_messageBox -title "Print spooling failure" \
668			-message "Print spooling probably failed: $msg"
669	    }
670	}
671	windows {
672	    if {[catch {PrintTextWin32 $filename} msg]} {
673		tk_messageBox -title "Print spooling failure" \
674			-message "Print spooling probably failed: $msg"
675	    }
676	}
677	default {
678	    tk_messageBox -title "Operation not Implemented" \
679		    -message "Wow! Unknown platform: $::tcl_platform(platform)"
680	}
681    }
682
683    #
684    # Be careful to throw away the temporary file in a gentle manner ...
685    #
686    if {[file exists $filename]} {
687	catch {file delete $filename}
688    }
689}
690
691# PrintTextWin32 --
692#    Print a file under Windows using all the "intelligence" necessary
693#
694# Arguments:
695# filename -		Name of the file
696#
697# Note:
698# Taken from the Wiki page by Keith Vetter, "Printing text files under
699# Windows".
700# Note:
701# Do not execute the command in the background: that way we can dispose of the
702# file smoothly.
703#
704proc PrintTextWin32 {filename} {
705    package require registry
706    set app [auto_execok notepad.exe]
707    set pcmd "$app /p %1"
708    catch {
709	set app [registry get {HKEY_CLASSES_ROOT\.txt} {}]
710	set pcmd [registry get \
711		{HKEY_CLASSES_ROOT\\$app\\shell\\print\\command} {}]
712    }
713
714    regsub -all {%1} $pcmd $filename pcmd
715    puts $pcmd
716
717    regsub -all {\\} $pcmd {\\\\} pcmd
718    set command "[auto_execok start] /min $pcmd"
719    eval exec $command
720}
721
722# tkAboutDialog --
723#
724#	Pops up a message box with an "about" message
725#
726proc tkAboutDialog {} {
727    tk_messageBox -icon info -type ok -title [mc "About Widget Demo"] \
728	    -message [mc "Tk widget demonstration application"] -detail \
729"[mc {Copyright (c) %s} {1996-1997 Sun Microsystems, Inc.}]
730[mc {Copyright (c) %s} {1997-2000 Ajuba Solutions, Inc.}]
731[mc {Copyright (c) %s} {2001-2007 Donal K. Fellows}]
732[mc {Copyright (c) %s} {2002-2007 Daniel A. Steffen}]"
733}
734
735# Local Variables:
736# mode: tcl
737# End:
738