WJG (06/06/06) Ah, 666, the number of the beast or the beastly BWidget ButtonBox? This stalwart member of the BWidget set is useful for making clusters of Buttons but what if you want other items such as everyone's favourite -ComboBox? Mmm, not really. So, here'a an alternative.
RH (07/06/06) There is already a nice Toolbar from George Petasis. It doesn't rely on any widget extension.
WJG (09/06/06) Here's revised version of the earlier code (now deleted). The proc arguments remain the same but now toolbars can be detached into floating palettes. Close the palette and the toolbar returns to its orginal ordering in its container. I did look at GP's ToolBar, nice work. GP's package allows for the side and bottom packing of toolbars which I haven't allowed for. It's not particularly a feature that I would personally use, but seeing as it's what's expected perhaps I'll have a go at it next.
#--------------- # ToolBar.tcl #--------------- # William J Giddings, 2006 #--------------- # Provide a ToolBar megawidget using the BWidget package. # # This is a hack of the code found at https://wiki.tcl-lang.org/1916. #--------------- # Notes: # ----- # BWidget has the ButtonBox widget but, this only adds buttons. # This method allows ** any ** other sort of widget to be added, # typically a ComboBox or spinbox. # To detach a toolbar, Button-1 click on the blue rule and a floating palette will appear. # Closing the palette will result in the toolbar re-appearing. #---------------- package require BWidget #--------------- # define the widget #--------------- namespace eval ToolBar { Widget::define ToolBar ToolBar # include other widgets Widget::tkinclude ToolBar frame .f Widget::declare ToolBar { } } #--------------- # create the thing.. #--------------- proc ToolBar::create { path args } { # define maps array set maps [list ToolBar {} :cmd {} .f {}] array set maps [Widget::parseArgs ToolBar $args] # map the various args Widget::initFromODB ToolBar "$path" $maps(ToolBar) # add the container set frame [eval frame $path [Widget::subcget $path :cmd] \ -class ToolBar -relief groove -bd 1 -highlightthickness 0] # include other widgets here.. set fr [eval frame $frame.f $maps(.f)] pack $fr -fill both -expand true # create the palette set p .pal_[string trimleft $path .] toplevel $p wm withdraw $p wm attributes $p -tool 1 wm title $p {} wm transient $p . wm resizable $p 0 0 # create containers -palette pack [frame $p.fr -relief groove -borderwidth 0] -side left -anchor nw # add ruler pack [frame $fr.rule -bg #9999ff -relief raised -borderwidth 1 -width 3] -side left -anchor nw -fill y # detach palette bind $fr.rule <Button-1> [ list ToolBar::rule_cmd $path $p %X %Y ] return [Widget::create ToolBar $path] } #--------------- # called when the palette closes #--------------- proc ToolBar::palette_cmd {a b c} { set opts "-side left -anchor nw" # obtain a list of currently packed items set slave_list [pack slaves $c] ; # sort the list by ending index set slave_list [lsort [lappend slave_list $a]] # repack everything on the list eval pack $slave_list -in $c $opts # hide the assocated palette wm withdraw $b } #--------------- # called when the toolbar rule is clicked #--------------- proc ToolBar::rule_cmd {b p x y} { wm geometry $p =+$x+$y wm deiconify $p set c [lindex [pack info $b] 1] wm protocol $p WM_DELETE_WINDOW [list ToolBar::palette_cmd $b $p $c] pack forget $b } #--------------- # change settings.. #--------------- proc ToolBar::configure { path args } { set res [Widget::configure $path $args] return $res } #--------------- # inquire about currents settings.. #--------------- proc ToolBar::cget { path option } { return [Widget::cget $path $option] } #--------------- # add a new widget to the toolbar #--------------- proc ToolBar::add { path class indx args} { # name the palette set p .pal_[string trimleft $path .] # add rule if {[string tolower $class] == "rule"} { # one for the toolbar frame $path.f.r$indx -width 2 -borderwidth 1 -relief groove pack $path.f.r$indx -side left -anchor nw -fill y -padx 2 # one for the palette frame $p.r$indx -width 2 -borderwidth 1 -relief groove pack $p.r$indx -side left -anchor nw -fill y -padx 2 return } # add other types of widget # create some storage set args1 {} ;# core widget options set args2 {} ;# anything else, add switches below set argsp1 {} ;# same for the palette set argsp2 {} foreach {arg val} $args { switch -- $arg { -help { append args1 "DynamicHelp::add $path.f.$indx -help ballon -text \{$val\}" append argsp1 "DynamicHelp::add $p.$indx -help ballon -text \{$val\}" } default { append args2 " $arg \{$val\} " append argsp2 " $arg \{$val\} " } } } # create child widget eval "$class $path.f.$indx $args2" ;# toolbar eval "$class $p.$indx $argsp2" ;# palette # do the extra stuff -toolbar eval $args1 pack $path.f.$indx -side left -padx 2 # do the extra stuff -palette eval $argsp1 pack $p.$indx -side left -padx 2 return $path.f.$indx } #--------------- # the ubiquitous demo #--------------- proc ToolBar::demo {} { catch {console show} BWidget::place . 500 500 center # create toolbar holder and sample text set base [frame .fr -relief groove -bd 2] pack $base -side top -anchor nw -fill x pack [text .txt] -side top -anchor nw -expand 1 -fill both # populate the toolbar holder pack [ToolBar .tb1 ] -in $base -side left -padx 0 -anchor nw foreach {i img hlp} { 1 New "New Document" 2 Open "Open New File" 3 Save "Save Work" } { .tb1 add button b$i \ -image [Bitmap::get $img] \ -relief flat -overrelief raised \ -help abc \ -command cmd$img } # create toolbar 2 -EDIT pack [ToolBar .tb2 ] -in $base -side left -padx 0 -anchor nw foreach {i img hlp} { 1 Cut "Cut selection to clipboard" 2 Copy "Copy selection to clipboard" 3 Paste "Paste clipboard into selection" } { .tb2 add button b$i \ -image [Bitmap::get $img] \ -relief flat -overrelief raised \ -help abc \ -command cmd$img } # and some BWidget buttons pack [ToolBar .tb3 ] -in $base -side left -padx 0 -anchor nw foreach {i img hlp} { 1 Bold "Embolden Selection" 2 Overstrike "Overstrike Selection" 3 Underline "Underline Selection" } { .tb3 add Button b$i \ -image [Bitmap::get $img] \ -relief link \ -help abc \ -command cmd$img } # and, a combox .tb3 add Rule 2 .tb3 add ComboBox cmb1 -values {How Now Brown Cow} .tb3 add Rule 3 .tb3 add checkbutton cb1 -text test } ToolBar::demo