Mac style tables with tablelist

TR - Often, Mac applications use tables for data display. The incredible tablelist widget goes a long way in supporting a good native look under the Aqua environment. Using the tablelist_tile package, you get them using the following command:

 package require tile
 package require tablelist_tile 4.8
 tablelist::tablelist .table -columns {0 "first column" 0 "second column" 0 "third column"} -stretch all -relief flat -labelrelief flat -showseparators 0 -borderwidth 0
 # packing left to make space for the scrollbar, leaving some extra space at the bottom because of the sizegrip:
 pack .table -fill both -expand 1 -side left -pady {0 20}

But there is one drawback. Vertical scrollbars around this tablelist will appear beside the table whereas the Aqua tables have this scrollbar appear under a separate column-like header (tha example is talen from Apple's Mail program):

http://www.typoscriptics.de/misc/aqua-table.gif

To mimic this with tablelist too, you just need to put the scrollbar into a separate frame and add a little ttk::label on top of the scrollbar. Note, that we don't use ttk::scrollbar but tk's scrollbar, since the tile scrollbar does not (yet) have a native look (see also Perfect Aqua Look):

 frame .f -borderwidth 0
 scrollbar .f.sy -orient vertical -command [list .table yview] -elementborderwidth 1
 # Create small widget for the upper right corner:
 ttk::label .f.corner -style TablelistHeader.TLabel
 pack .f.corner -side top -fill x
 pack .f.sy -side top -fill y -expand 1
 pack .f -side right -fill y -pady {0 20}
 .table configure -yscrollcommand [list .f.sy set]

Note here, that the extra label has a custm style: 'TablelistHeader.TLabel'. This is the style used by tablelist 4.8 to make the table headers look native on the Mac. This is how it looks like:

http://www.typoscriptics.de/misc/tablelist-table.gif

The only visible difference is that the header separators are a bit too wide or not so sharp, and the column separators (when drawn with '-showseparators 1') will not appear exactly under the header separators but shifted a bit to the right. (When you also need horizontal scrollbars, you should rather use the grid layout manager instead of pack.)

Csaba Nemethi 2007-11-03: Very nice work! That visual difference is no longer present in the newest CVS version of Tablelist. TR - Great, thanks!


Additional functionality

The extra label in the corner of the tablelist does not need to go unused. For example, in Komodo Edit and other Mac applications, you can click on the label and get a menu with some actions. Let's make it possible to have a menu there, to show or hide the tablelist columns. Thus:

http://www.typoscriptics.de/misc/tablelist-table-menu.gif

And comes the complete code (including the bits from above):

 package require tile
 package require tablelist_tile 4.8
 tablelist::tablelist .table -columns {0 "first column" 0 "second column" 0 "third column"} -stretch all -relief flat -labelrelief flat -showseparators 0 -borderwidth 0
 # packing left to make space for the scrollbar, leaving some extra space at the bottom because of the sizegrip:
 pack .table -fill both -expand 1 -side left -pady {0 20}

 frame .f -borderwidth 0
 scrollbar .f.sy -orient vertical -command [list .table yview] -elementborderwidth 1
 # Create small widget for the upper right corner:
 ttk::label .f.corner -style TablelistHeader.TLabel
 pack .f.corner -side top -fill x
 pack .f.sy -side top -fill y -expand 1
 pack .f -side right -fill y -pady {0 20}
 .table configure -yscrollcommand [list .f.sy set]

 # this is the callback triggered by the menu items:
 proc TableColumnsShow {} {
         global tableCol 
        foreach col [array names tableCol] {
                .table columnconfigure $col -hide [expr ! $tableCol($col)]
        }
 }

 # build the menu that should appear on clicking the label:
 menu .m
 set num 0
 # fill menu with column names and use an array to store menu info:
 foreach {width name align} [.table cget -columns] {
        .m add checkbutton -label $name -variable tableCol($num) -command TableColumnsShow
        set tableCol($num) 1
        incr num
 }

 # nake the label show the menu on clicking:
 bind .f.corner <ButtonPress-1> {.m post %X %Y}

 # fill in some data:
 foreach {a b c} {
        1 one et
        2 two to
        3 thre tre
        4 four fire
        5 five fem
        6 six seks
        7 seven syv
        8 eight otte
        9 nine ni
        10 ten ti
        11 eleven elleve
        12 twelve tolv
 } {
        .table insert end [list $a $b $c]
 }

 # done!
 wm title . Tablelist!