::bartabsTop

The bartabs package provides a bar widget containing tabs that are

  • scrollable
  • markable
  • moveable
  • closeable
  • disabled and enabled
  • static and changeable
  • selectable and multi-selectable
  • configureable
  • enhanceable with popup menu

The bartabs defines three TclOO classes:

  • Tab deals with tabs
  • Bar deals with a bar of tabs
  • Bars deals with bars of tabs

However, only the Bars class is used to create bars along with tabs. It can be also used to deal with any bars and tabs, providing all necessary interface.

The Bar does not create a real TclOO object, rather it provides syntax sugar for a convenient access to the bar methods.

The Tab does not create a real TclOO object as well. It serves actually for structuring bartabs code as for tab methods. Thus, its methods are accessible through the Bars ("real" TclOO) and Bar ("sugar") objects.


A common work flow with bartabs looks like this:

Firstly, we create a Bars object, e.g.

bartabs::Bars create NS::bars

Then we create a Bar object, e.g.

NS::bars create NS::bar $barOptions

If a tab of the bar should be displayed (with its possible contents), we show the bar and select the current tab:

set TID [NS::bar tabID "tab label"] ;# get the tab's ID by its label

NS::bar $TID show ;# show the bar and select the tab

or just draw the bar without mind-breaking about a tab:

NS::bar draw ;# show the bar without selecting a tab

The rest actions include:

  • responses to a selection of tab (through -csel command option of Bar object)
  • responses to a deletion of tab (through -cdel command option of Bar object)
  • responses to a reorganization of bar (through -cmov command option of Bar object)
  • inserting and renaming tabs
  • disabling and enabling tabs
  • marking tabs with colors or icons
  • processing the marked tabs
  • processing multiple tabs selected with Ctrl+click
  • scrolling tabs to left/right through key bindings
  • calling other handlers through key bindings and bartabs menu
  • using cget and configure methods to change the bar/tab appearance
  • redrawing bars at some events
  • removing and creating as much bars as required


The methods of Tab class are called from Bars or Bar object and are passed: tab ID (TID), method name, arguments. Syntax:

OBJECT TID method arguments

For example: NS::bars $TID close or NS::bar $TID show false


The methods of Bar class are called from Bar object or (more wordy) from Bars object. Syntax:

BAR_OBJECT method arguments

BARS_OBJECT BID method arguments

For example: NS::bar popList $X $Y or NS::bars $BID popList $X $Y


The methods of Bars class need no TID nor BID, though not protesting them passed before method name. Syntax:

BARS_OBJECT method arguments

For example:

NS::bars drawAll ;# good boy

NS::bars tab11 drawAll ;# bad boy uses the useless tab11 (TID)

NS::bars bar1 drawAll ;# bad boy's BID is useless as well


There are three "virtual" methods:

  • NS::bar create NS::tab $label creates a tab object NS::tab for a tab labeled $label to access the tab methods, e.g. NS::tab show
  • NS::tab cget $option gets an option of tab, e.g. NS::tab cget -text
  • NS::tab configure $option $value sets an option of tab, e.g. NS::tab configure -text "new label"


Few words about BID and TID mentioned throughout the bartabs.

These are identifiers of bars and tabs, of form bar<index> and tab<index> where <index> is integer increased from 0 in order of bar/tab creation. The bars and the tabs of all bars have unique IDs.

You can use these literals freely, along with BIDs and TIDs gotten from bartabs methods. For example, if you know that "some tab" was created third, you can show it straightforward:

NS::bar tab2 show ;# show the 3rd tab (TID=tab2)

instead of

NS::bar [NS::bar tabID "some tab"] show ;# find and show the tab by its name


Links:

Documentation

Reference on bartabs

Reference on baltip (the package used by bartabs)


Commandsbartabs, Top




drawAll [::bartabs]bartabs, Top

Draws all bars. Used at updating themes etc.

drawAll

proc ::bartabs::drawAll {} { # Draws all bars. Used at updating themes etc. foreach bars $bartabs::BarsList {$bars drawAll} }


Classesbartabs, Top



Bar [::bartabs]bartabs, Top

Method summary
cgetGets values of options of bars & tabs.
clearForgets (hides) the shown tabs.
closeSee Tab.close
configureSets values of options for bars & tabs.
drawDraws the bar tabs at slight changes.
insertTabInserts a new tab into a bar.
listFlagGets a list of TID + flags "visible", "marked", "selected", "disabled".
listTabGets a list of tabs.
popListShows a menu of tabs.
removeRemoves a bar.
scrollLeftScrolls tabs to the left.
scrollRightScrolls tabs to the right.
showSee Tab.show
tabIDGets TID by tab's label.
updateUpdates the bar in hard way.
Superclasses

Tab

Subclasses

Bars



cget [::bartabs::Bar]Bar, Top

Gets values of options of bars & tabs.

OBJECT cget ?args?
Parameters
argslist of options, e.g. {-tabcurrent -MyOpt}
Description

Return a list of values or one value if args is one option.


method cget {args} { # Gets values of options of bars & tabs. # args - list of options, e.g. {-tabcurrent -MyOpt} # Return a list of values or one value if args is one option. set BID [my ID] variable btData set res [list] foreach opt $args { if {$opt eq "-listlen"} { lappend res [dict get $btData $BID -LLEN] } elseif {$opt eq "-width"} { lassign [dict get [dict get $btData $BID] -wbar] wbar lappend res [my Aux_WidgetWidth $wbar] } elseif {[dict exists $btData $BID $opt]} { lappend res [dict get $btData $BID $opt] } else { lappend res "" } } if {[llength $args]==1} {return [lindex $res 0]} return $res }



clear [::bartabs::Bar]Bar, Top

Forgets (hides) the shown tabs.

OBJECT clear

method clear {} { # Forgets (hides) the shown tabs. if {[my Locked [set BID [my ID]]]} return foreach tab [my $BID listTab] { lassign $tab TID text wb wb1 wb2 pf if {[my Tab_Is $wb] && $pf ne ""} { pack forget $wb my $TID configure -pf "" } } }



configure [::bartabs::Bar]Bar, Top

Sets values of options for bars & tabs.

OBJECT configure ?args?
Parameters
argslist of pairs "option value"

method configure {args} { # Sets values of options for bars & tabs. # args - list of pairs "option value" set BID [my ID] variable btData foreach {opt val} $args { dict set btData $BID $opt $val if {$opt eq "-TABS"} {dict set btData $BID -LLEN [llength $val]} } if {[dict exists $args -static]} {my $BID Style} }



draw [::bartabs::Bar]Bar, Top

Draws the bar tabs at slight changes.

OBJECT draw ?upd?
Parameters
updif "yes", run "update" before redrawing; optional, default yes

method draw {{upd yes}} { # Draws the bar tabs at slight changes. # upd - if "yes", run "update" before redrawing if {[my Locked [set BID [my ID]]]} return if {$upd} update lassign [my Aux_InitDraw $BID] bwidth vislen bd arrlen llen tleft hidearr tabs wframe set tright [expr {$llen-1}] for {set i $tleft} {$i<$llen} {incr i} { lassign [my Tab_DictItem [lindex $tabs $i]] TID text wb wb1 wb2 pf lassign [my Tab_Create $BID $TID $wframe $text] wb wb1 wb2 if {[my Aux_CheckTabVisible $wb $wb1 $wb2 $i $tleft tright vislen $llen $hidearr $arrlen $bd $bwidth tabs $TID $text]} { my Tab_Pack $BID $TID $wb $wb1 $wb2 } } my Aux_EndDraw $BID $tleft $tright $llen my Tab_MarkBar $BID }



insertTab [::bartabs::Bar]Bar, Top

Inserts a new tab into a bar.

OBJECT insertTab txt ?pos? ?img?
Parameters
txttab's label
postab's position in tab list; optional, default end
imgtab's image; optional, default ""
Return value

Returns TID of new tab or "".


method insertTab {txt {pos end} {img {}}} { # Inserts a new tab into a bar. # txt - tab's label # pos - tab's position in tab list # img - tab's image # Returns TID of new tab or "". set tabs [my [set BID [my ID]] cget -TABS] set tab [my Tab_Data $BID $txt] if {$tab eq ""} {return ""} if {$pos eq "end"} { lappend tabs $tab } else { set tabs [linsert $tabs $pos $tab] } if {$img ne ""} { set imagetabs [my $BID cget -IMAGETABS] lappend imagetabs [list [lindex $tab 0] $img] my $BID configure -IMAGETABS $imagetabs } my $BID configure -TABS $tabs my $BID Refill $pos [expr {$pos ne "end"}] return [lindex $tab 0] }



listFlag [::bartabs::Bar]Bar, Top

Gets a list of TID + flags "visible", "marked", "selected", "disabled".

OBJECT listFlag ?filter?
Parameters
filter"" for all or "v","m","s","d" for visible, marked, selected, disabled; optional, default ""
Return value

Returns a list "TID, text, visible, marked, selected, disabled" for all or a list of TID for filtered.


method listFlag {{filter {}}} { # Gets a list of TID + flags "visible", "marked", "selected", "disabled". # filter - "" for all or "v","m","s","d" for visible, marked, selected, disabled # Returns a list "TID, text, visible, marked, selected, disabled" for all or a list of TID for filtered. set BID [my ID] lassign [my $BID cget -mark -disable -select -tabcurrent] mark dsbl fewsel tcurr set res [list] foreach tab [my $BID listTab] { lassign $tab TID text wb wb1 wb2 pf set visibl [expr {[my Tab_Is $wb] && $pf ne ""}] set marked [expr {[lsearch $mark $TID]>=0}] set dsbled [expr {[lsearch $dsbl $TID]>=0}] set select [expr {$TID == $tcurr || [lsearch $fewsel $TID]>-1}] if {$filter eq ""} { lappend res [list $TID $text $visibl $marked $select $dsbled] } elseif {$filter eq "v" && $visibl || $filter eq "m" && $marked || $filter eq "d" && $dsbled || $filter eq "s" && $select} { lappend res $TID } } return $res }



listTab [::bartabs::Bar]Bar, Top

Gets a list of tabs.

OBJECT listTab
Return value

Returns a list of TID, text, wb, wb1, wb2, pf.


method listTab {} { # Gets a list of tabs. # Returns a list of TID, text, wb, wb1, wb2, pf. set res [list] foreach tab [my [my ID] cget -TABS] {lappend res [my Tab_DictItem $tab]} return $res }



popList [::bartabs::Bar]Bar, Top

Shows a menu of tabs.

OBJECT popList X Y
Parameters
Xx coordinate of mouse pointer
Yy coordinate of mouse pointer

method popList {X Y} { # Shows a menu of tabs. # X - x coordinate of mouse pointer # Y - y coordinate of mouse pointer set BID [my ID] my $BID DestroyMoveWindow set wbar [my $BID cget -wbar] set popi $wbar.popupList catch {destroy $popi} menu $popi -tearoff 0 if {[set plist [my $BID FillMenuList $BID $popi]] eq "s"} { destroy $popi } else { my Bar_MenuList $BID -1 $popi $plist tk_popup $popi $X $Y } }



remove [::bartabs::Bar]Bar, Top

Removes a bar.

OBJECT remove
Return value

Returns "yes" at success.


method remove {} { # Removes a bar. # Returns "yes" at success. set BID [my ID] variable btData if {[dict exists $btData $BID]} { lassign [my $BID cget -BINDWBASE] wb bnd if {$wb ne ""} {bind $wb <Configure> $bnd} set bar [dict get $btData $BID] foreach tab [dict get $bar -TABS] {my Tab_RemoveLinks $BID [lindex $tab 0]} foreach wb [dict get $bar -WWID] {catch {destroy $wb}} if {[set bc [my $BID cget -BARCOM]] ne ""} {catch {rename $bc ""}} foreach tc [my $BID cget -TABCOM] {catch {rename [lindex $tc 1] ""}} dict unset btData $BID return yes } return no }



scrollLeft [::bartabs::Bar]Bar, Top

Scrolls tabs to the left.

OBJECT scrollLeft ?dotip?
Parameters
dotipflag 'show tip'; optional, default no

method scrollLeft {{dotip no}} { # Scrolls tabs to the left. # dotip - flag 'show tip' set BID [my ID] set w [my $BID cget -wbar] set wlarr $w.larr ;# left arrow if {[my $BID ScrollCurr -1]} { if {$dotip} {catch {::baltip::repaint $wlarr}} return } lassign [my $BID cget -tleft -LLEN -scrollsel] tleft llen sccur if {![string is integer -strict $tleft]} {set tleft 0} if {$tleft && $tleft<$llen} { incr tleft -1 set tID [lindex [my $BID listTab] $tleft 0] my $BID configure -tleft $tleft my $BID Refill $tleft yes if {$sccur} {my $tID Tab_BeCurrent} if {$dotip} {catch {::baltip::repaint $wlarr}} } }



scrollRight [::bartabs::Bar]Bar, Top

Scrolls tabs to the right.

OBJECT scrollRight ?dotip?
Parameters
dotipflag 'show tip'; optional, default no

method scrollRight {{dotip no}} { # Scrolls tabs to the right. # dotip - flag 'show tip' set BID [my ID] set w [my $BID cget -wbar] set wrarr $w.rarr ;# left arrow if {[my $BID ScrollCurr 1]} { if {$dotip} {catch {::baltip::repaint $wrarr}} return } lassign [my $BID cget -tright -LLEN -scrollsel] tright llen sccur if {![string is integer -strict $tright]} {set tright [expr {$llen-2}]} if {$tright<($llen-1)} { incr tright set tID [lindex [my $BID listTab] $tright 0] my $BID configure -tright $tright my $BID Refill $tright no if {$sccur} {my $tID Tab_BeCurrent} if {$dotip} {catch {::baltip::repaint $wrarr}} } }



tabID [::bartabs::Bar]Bar, Top

Gets TID by tab's label.

OBJECT tabID txt
Parameters
txtlabel
Return value

Returns TID or -1.


method tabID {txt} { # Gets TID by tab's label. # txt - label # Returns TID or -1. set BID [my ID] if {[catch {set ellipse [my $BID cget -ELLIPSE]}]} {return ""} if {[string first $ellipse $txt]} { set pattern [string map [list $ellipse "*"] $txt] } else { set pattern "" } foreach tab [my $BID listTab] { lassign $tab tID ttxt if {$txt eq $ttxt} {return $tID} if {$pattern ne "" && [string match $pattern $ttxt]} {return $tID} } return "" }



update [::bartabs::Bar]Bar, Top

Updates the bar in hard way.

OBJECT update

method update {} { # Updates the bar in hard way. if {[my Locked [set BID [my ID]]]} return update my $BID Refill 0 yes }



Bars [::bartabs]bartabs, Top

Method summary
constructorConstructor for the class.
destructorDestructor for the class.
cgetSee Bar.cget
clearSee Bar.clear
closeSee Tab.close
configureSee Bar.configure
createCreates a bar.
disableTabDisables tab(s).
drawSee Bar.draw
drawAllRedraws all bars.
enableTabEnables tab(s).
insertTabSee Bar.insertTab
isTabChecks if a tab exists.
listFlagSee Bar.listFlag
listTabSee Bar.listTab
markTabMarks tab(s).
moveTabChanged a tab's position in bar.
popListSee Bar.popList
removeSee Bar.remove
removeAllRemoves all bars.
scrollLeftSee Bar.scrollLeft
scrollRightSee Bar.scrollRight
selectTabSelects tab(s).
showSee Tab.show
tabIDSee Bar.tabID
unmarkTabUnmarks tab(s).
unselectTabUnselects tab(s).
updateSee Bar.update
updateAllUpdates all bars in hard way.
Superclasses

Bar



constructor [::bartabs::Bars]Bars, Top

Bars create ?args?
Parameters
argsOptional arguments.

method constructor {args} { set btData [dict create] if {[llength [self next]]} { next {*}$args } oo::objdefine [self] "method tab-1 {args} {return {-1}}" lappend bartabs::BarsList [self] }



destructor [::bartabs::Bars]Bars, Top

OBJECT destroy

method destructor {} { my removeAll unset btData set i [lsearch -exact $bartabs::BarsList [self]] set bartabs::BarsList [lreplace $bartabs::BarsList $i $i] if {[llength [self next]]} next }



create [::bartabs::Bars]Bars, Top

Creates a bar.

OBJECT create barCom ?barOpts?
Parameters
barCombar command's name or barOpts
barOptslist of bar's options; optional, default ""
Return value

Returns BID.


method create {barCom {barOpts {}}} { # Creates a bar. # barCom - bar command's name or barOpts # barOpts - list of bar's options # Returns BID. if {[set noComm [expr {$barOpts eq ""}]]} {set barOpts $barCom} set w [dict get $barOpts -wbar] ;# parent window set wframe $w.frame ;# frame set wlarr $w.larr ;# left arrow set wrarr $w.rarr ;# right arrow lappend barOpts -WWID [list $wframe $wlarr $wrarr] my My [set BID [my Bar_Data $barOpts]] my $BID Style ttk::button $wlarr -style ClButton$BID -image bts_ImgLeft -command [list [self] $BID scrollLeft yes] -takefocus 0 ttk::button $wrarr -style ClButton$BID -image bts_ImgRight -command [list [self] $BID scrollRight yes] -takefocus 0 ttk::frame $wframe -relief flat pack $wlarr -side left -padx 0 -pady 0 -anchor e pack $wframe -after $wlarr -side left -padx 0 -pady 0 -fill x -expand 1 pack $wrarr -after $wframe -side right -padx 0 -pady 0 -anchor w foreach w {wlarr wrarr} { bind [set $w] <Button-3> "[self] $BID popList %X %Y" } set wbase [my $BID cget -wbase] if {$wbase ne ""} { my $BID configure -BINDWBASE [list $wbase [bind $wbase <Configure>]] bind $wbase <Configure> [list + [self] $BID NeedDraw] } after idle [list [self] $BID NeedDraw ; [self] $BID draw] if {!$noComm} { proc $barCom {args} "return \[[self] $BID {*}\$args\]" my $BID configure -BARCOM $barCom } return $BID }



disableTab [::bartabs::Bars]Bars, Top

Disables tab(s).

OBJECT disableTab ?args?
Parameters
argslist of TID

method disableTab {args} { # Disables tab(s). # args - list of TID my MarkTab -disable {*}$args }



drawAll [::bartabs::Bars]Bars, Top

Redraws all bars.

OBJECT drawAll ?upd?
Parameters
updif "yes", run "update" before redrawing; optional, default yes

method drawAll {{upd yes}} { # Redraws all bars. # upd - if "yes", run "update" before redrawing if {$upd} update my Bars_Method draw no }



enableTab [::bartabs::Bars]Bars, Top

Enables tab(s).

OBJECT enableTab ?args?
Parameters
argslist of TID or {}

method enableTab {args} { # Enables tab(s). # args - list of TID or {} my UnmarkTab -disable {*}$args }



isTab [::bartabs::Bars]Bars, Top

Checks if a tab exists.

OBJECT isTab TID
Parameters
TIDtab ID
Return value

Returns true if the tab exists.


method isTab {TID} { # Checks if a tab exists. # TID - tab ID # Returns true if the tab exists. return [expr {[my Tab_BID $TID check] ne ""}] }



markTab [::bartabs::Bars]Bars, Top

Marks tab(s).

OBJECT markTab ?args?
Parameters
argslist of TID

method markTab {args} { # Marks tab(s). # args - list of TID my MarkTab -mark {*}$args }



moveTab [::bartabs::Bars]Bars, Top

Changed a tab's position in bar.

OBJECT moveTab TID1 TID2
Parameters
TID1TID of the moved tab
TID2TID of a tab to move TID1 behind
Description

TID1 and TID2 must be of the same bar.


method moveTab {TID1 TID2} { # Changed a tab's position in bar. # TID1 - TID of the moved tab # TID2 - TID of a tab to move TID1 behind # TID1 and TID2 must be of the same bar. lassign [my Tab_BID $TID1] BID1 i1 lassign [my Tab_BID $TID2] BID2 i2 if {$i1!=$i2 && $BID1 eq $BID2} { set tabs [my $BID1 cget -TABS] set tab [lindex $tabs $i1] set tabs [lreplace $tabs $i1 $i1] set i [expr {$i1>$i2?($i2+1):$i2}] my $BID1 configure -TABS [linsert $tabs $i $tab] my $TID1 show 1 } }



removeAll [::bartabs::Bars]Bars, Top

Removes all bars.

OBJECT removeAll

method removeAll {} { # Removes all bars. my Bars_Method remove }



selectTab [::bartabs::Bars]Bars, Top

Selects tab(s).

OBJECT selectTab ?args?
Parameters
argslist of TID

method selectTab {args} { # Selects tab(s). # args - list of TID my MarkTab -select {*}$args }



unmarkTab [::bartabs::Bars]Bars, Top

Unmarks tab(s).

OBJECT unmarkTab ?args?
Parameters
argslist of TID or {}

method unmarkTab {args} { # Unmarks tab(s). # args - list of TID or {} my UnmarkTab -mark {*}$args }



unselectTab [::bartabs::Bars]Bars, Top

Unselects tab(s).

OBJECT unselectTab ?args?
Parameters
argslist of TID or {}

method unselectTab {args} { # Unselects tab(s). # args - list of TID or {} my UnmarkTab -select {*}$args }



updateAll [::bartabs::Bars]Bars, Top

Updates all bars in hard way.

OBJECT updateAll

method updateAll {} { # Updates all bars in hard way. my Bars_Method Refill 0 yes }



Tab [::bartabs]bartabs, Top

Method summary
closeCloses a tab and updates the bar.
showShows a tab in a bar and sets it current.
Subclasses

Bar



close [::bartabs::Tab]Tab, Top

Closes a tab and updates the bar.

OBJECT close ?redraw?
Parameters
redrawif "yes", update the bar and select the new tab; optional, default yes
Return value

Returns "1" if the deletion was successful, otherwise 0 (no) or -1 (cancel).


method close {{redraw yes}} { # Closes a tab and updates the bar. # redraw - if "yes", update the bar and select the new tab # Returns "1" if the deletion was successful, otherwise 0 (no) or -1 (cancel). lassign [my Tab_BID [set TID [my ID]]] BID icurr if {[my Disabled $TID]} {return 0} if {[set res [my $TID Tab_Cmd -cdel]]<1} {return $res} if {$redraw} {my $BID clear} lassign [my $BID cget -TABS -tleft -tright -tabcurrent] tabs tleft tright tcurr my Tab_RemoveLinks $BID $TID destroy [my $TID cget -wb] set tabs [lreplace $tabs $icurr $icurr] my $BID configure -TABS $tabs if {$redraw} { if {$icurr>=$tleft && $icurr<$tright} { my $BID draw my [lindex $tabs $icurr 0] Tab_BeCurrent } else { if {[set TID [lindex $tabs end 0]] ne ""} { my $TID show 1 ;# last tab deleted: show the new last if any } } } return 1 }



show [::bartabs::Tab]Tab, Top

Shows a tab in a bar and sets it current.

OBJECT show ?anyway?
Parameters
anywayif "yes", refill the bar anyway (for choosing from menu); optional, default no

method show {{anyway no}} { # Shows a tab in a bar and sets it current. # anyway - if "yes", refill the bar anyway (for choosing from menu) lassign [my IDs [my ID]] TID BID if {$anyway} {my $BID clear} set itab 0 foreach tab [my $BID listTab] { lassign $tab tID text wb wb1 wb2 pf if {$TID eq $tID} { set anyway [expr {$pf eq ""}] ;# check if visible break } incr itab } if {$anyway} {my $BID Refill $itab no yes} my $TID Tab_BeCurrent }

Document generated by Ruff!