---- [http://mini.net/files/vnotebook.jpg] set docu(VNotebook) { [Richard Suchenwirth] 2002-08-20 - This is a study in using the [BWidgets] toolkit, in particular using their PagesManager to implement a notebook with vertically-stacked tabs, by default to the right. The demo at end shows a usage example which may be used as a telephone booklet. As added goodie (if you have the code from [An i15d date chooser] and [A little calculator] available), the last page contains one of each - just to show that you can pack other things than text widgets. Enjoy! } package require BWidget proc VNotebook {w args} { frame $w ;# container around the whole frame $w.tabs ;# will hold tab buttons # dummy button, not managed, to keep font info set opt(-font) [[button $w.tabs.0] cget -font] set defaults {-side right} array set opt [concat $defaults $args] foreach i {font side} { set $i $opt(-$i); unset opt(-$i) } ;# so PageManager won't see those $w.tabs.0 config -font $font ;# so others can cget it eval PagesManager $w.nb [array get opt] pack $w.tabs -side $side -fill both pack $w.nb -side $side -fill both -expand 1 -padx 0 rename $w _$w ;# won't use it anymore, but must survive proc $w {cmd args} { set fileopt {-filetypes {{Notebook .not} {{All files} .*}}\ -defaultextension .not} set w [lindex [info level 0] 0] ;# retrieve own name switch -- $cmd { add { set font [$w.tabs.0 cget -font] set b [button $w.tabs.b$args -text $args -font $font\ -command [list $w raise $args] -bg white \ -borderwidth 1 -pady 0] pack $b -fill both -expand 1 } delete {destroy $w.tabs.b$args} open { set file [eval tk_getOpenFile $fileopt] if {$file!=""} { foreach {page content} [source $file] { set t [$w.nb getframe $page].t $t delete 1.0 end $t insert end $content } } return $file } raise { set bg [$w.tabs.0 cget -bg] foreach i [winfo children $w.tabs] { $i configure -bg $bg } $w.tabs.b$args configure -bg white catch {focus [$w.nb getframe $args].t} } raisewhere { foreach page [$w.nb pages] { set f [$w.nb getframe $page] if [regexp -nocase $args [$f.t get 1.0 end]] { $w raise $page break } } return ;# this command is not known to P.M. } save { set file [eval tk_getSaveFile $fileopt] if {$file!=""} { set fp [open $file w] puts $fp "return {" foreach page [$w.nb pages] { set t [$w.nb getframe $page].t catch {puts $fp [list $page [$t get 1.0 end-1c]]} } puts $fp "}" close $fp } return $file } } eval $w.nb $cmd $args ;# let PagesManager do the rest } set w } if {[file tail [info script]]==[file tail $argv0]} { # demo and example code, runs when sourced alone proc img {name} { image create photo -file $::env(BWIDGET_LIBRARY)/images/$name } frame .0 button .0.load -image [img open.gif] -command ".v open" button .0.save -image [img save.gif] -command ".v save" LabelEntry .0.f -label " Find: " -textvariable Find .0.f bind {.v raisewhere $Find} eval pack [winfo children .0] -side left -fill y pack .0.f -fill x -expand 1 VNotebook .v ;#-side left pack .0 .v -fill both -expand 1 -pady 2 foreach i {AB CD EF GH IJ KL MN OPQ RS TU VW XYZ} { set w [.v add $i] pack [text $w.t -wrap word -width 40] -fill both -expand 1 } # remove next 3 lines if you don't have/want these goodies set w [.v add +] source Calendar.tcl; pack [date::chooser $w.c] -fill both -expand 1 source sep_calc.tcl; pack [calculator $w.f] -fill both -expand 1 tkwait visibility .v set p0 [lindex [.v pages] 0] [.v.nb getframe $p0].t insert end [string map {\n " "} $docu(VNotebook)] wm protocol . WM_DELETE_WINDOW {.v save; exit} after 100 .v raise $p0 ;# delay so top page is correct } ---- ''[escargo] 11 Jul 2003'' - I saw this code had changed a little, and used my [wish-reaper] to download it. When I tried to get it to run, I had to define the environment variable '''BWIDGET_LIBRARY'''. After that, I discovered that, since I did not have the optional Calendar.tcl and sep_calc.tcl files, I had to modify the code not to source them. Finally, there seems to be no definition of '''docu(VNotebook)'''. Is that supposed to be defined in some other context? [RS]: It is defined, but never used :D I used this convention for a while in the context of [htext], so such comments would be available as online documentation too. So it does no harm, but might as well have been the usual ''if 0 {...}''. ''[escargo]'' - I see the problem now. [wish-reaper] only collects the code that's indented. The '''set docu(VNotebook)''' at the beginning, is not indented, and therefore not seen when the page was reaped. So when I looked in the reaped file, there was no definition of '''docu''' at all. Now the source of the problem makes sense. Should the '''set ...''' be indented and part of the code? [RS]: Technically, it is part of the code even if not indented - as well as the if 0 {...} construct. I like the line formatting of unindented text better... ''[escargo]'' - I'm not sure I know what you mean by "technically" in this context. According to the reaper applications (such as [wish-reaper]) if it's code then it needs to be indented. ''Human'' interpretation can recognize that the nonindented portion is significant, but the semantics of ''part of the code'' is open to interpretation. I know you did it that way, but it does make mechanical capture of the code (by the reapers) a bit hard. [LV] Jul 11, 2003 should wish-reaper perhaps look for optional pragma/metadata/some sort of marker that could be used in cases like this to help delineate code? ''[escargo]'' - The guts of it are in the '''proc reap''' body for [wish-reaper], which is code I stole from the other reaper application. In short, only lines that start with exactly a single space are written to the output file (right now). This is certainly simple. Perhaps it is too simple. However, some very old pages have turned out to be reapable because they follow this convention already. [RS] - On most of my pages, comments longer than a line are always in ''if 0 {...}'' blocks, because the whole file is sourced by Tcl, so reaping those shouldn't hurt. ---- [Category Example] | [Category GUI]