[10 Sep 2005] A tour of the Tile internals. There are roughly four major parts to the tile codebase: the theme engine, the widget framework, widget implementations, and theme implementations. What follows is a braindump describing the current codebase and a few future directions. See also http://tktable.sourceforge.net/tile/tile-tcl2004.pdf for a high-level overview of the architecture. THEME ENGINE tkTheme.h -- Public header file. Start here. tkThemeInt.h -- Private header file. Don't look at it :-) tkstate.c -- Routines for manipulating state specifications, state maps, state tables, and other things state-related. Future directions: Looks like this could use some more comments. Very old code; hasn't been revisited (or needed to be) for a long time. tkTheme.c -- The core of the theme engine. This started life as a modified copy of the TIP#48 style support code, but has been revised and expanded since then. The background and rationale from TIP#48 still apply, but the details are quite different now. The main new features relative to the original implementation are: a style database that's used to compute element option values (previously element implementations were responsible for doing this themselves); a layout engine for computing the size and position of a group of elements (see layout.c); and script-level access to both of the above. Future directions: It's been through three or four major refactorings so far, and could probably use one more. The data structures are still more complicated than they need to be. Things are currently neither optimized for space nor for speed, but could be modified to go either way. To save space, greater use of the Flyweight pattern is possible. Alternately, to speed things up, it could cache more internal state. Since the tile widgets don't seem to be too slow on the one hand or too memory-hungry on the other, as long as no performance problems arise this will probably stay as it is. I really, really want to nuke the call to TkGetOptionSpec(). This one line of code has caused more headaches than anything else (with the possible exception of Aqua support). layout.c -- This contains the layout engine. The basic algorithm is the same as the [pack] geometry manager. Future directions: Needs to be split into two pieces, one for the low-level Ttk_Box / Ttk_Padding routines, and the other for the Ttk_Layout implementation proper. As above, the data structures could probably use another refactoring and reorganization. The TTK_EXPAND flag should probably go away. The TTK_BORDER flag is probably not needed either. cache.c -- A resource cache for fonts, colors and other resources. See comments at the top of the file for full details, but the basic problem is: Tk frees fonts and colors whenever the last reference to them goes away; but the style engine accesses these resources on a just-in-time basis and releases them immediately afterwards. This is *very* expensive. The cache holds a semi-permanent reference to resources accessed by the style engine to prevent Tk from freeing them prematurely. Future directions: Preferably, change Tk's (de)allocation policies so that this workaround isn't necessary. Possibly -- but only under great duress -- add support for non-default visuals and colormaps. I really don't want to do this, since it adds a ton of complexity for a feature that nobody uses anymore. image.c -- Implements the 'style element create image' command, an element factory for defining "pixmap" themes. tile.c -- Package initialization routine, plus sort of a dumping ground for miscellaneous stuff that didn't fit anywhere else. WIDGET FRAMEWORK widget.h widget.c -- This module (and the ones below) attempt to encapsulate all of the boilerplate logic involved in a widget implementation. The central data structure is 'struct WidgetSpec_', which consists mostly of a number of callback hooks (or "strategy methods") called at various times during the widget lifecycle. Future directions: This isn't namespace-clean; public entry points, typedefs, and #defines need a Ttk prefix. There are strict rules about when each hook is called and what each hook must, may, and may not do. I need to write these rules down somewhere. scroll.c -- Attempts to encapsulates the control flow logic involved in scrolling widgets. Future directions: This is only half-baked. Needs more work. manager.h manager.c -- Utilities for writing geometry managers; used by the ttk::notebook and ttk::paned widgets. Handles the geometry propagation dance control flow logic and the nasty details about slave removal. Future directions: the Ttk_Manager and Ttk_Slave data structures need to be made opaque. Some of the function signatures are Not Quite Right. The "SlaveConfigured" hook and Ttk_ConfigureSlave() function probably don't belong here; configuration is better left to the caller. Once these are gone, the SlaveAdded hook can go away too, leaving a cleaner and simpler interface. Long-term: write a TIP to push this interface (or one like it) all the way into the core to replace the current Tk_GeomMgr API. This API is a lot easier to use, and has the potential to solve some longstanding problems (e.g., the "pack vs. grid" conflict). trace.c -- A thin wrapper/convenience layer around Tcl_TraceVar() and friends; used by widgets that have linked -variable / -textvariable options. Future directions: minor cleanups, namespace prefix (may already be done by the time you read this, it's near the top of my pile.) track.c -- Routine TrackElementState(). Used by ttk::scrollbars and other widgets where individual elements may be pressed / active instead of the widget as a whole. See header comments for details. blink.c -- Routine BlinkCursor -- registers an event handler / timer callback to blink the cursor on and off when the widget has focus. See header comments for details. WIDGET IMPLEMENTATIONS button.c / button.tcl -- Labels, buttons, checkbuttons, and radiobuttons. Not much to say about these, except that it's worthwhile comparing the Tile implementation with how the core does things. Seriously. This is the best demonstration I can think of for why I think the Tile approach is on the right track. frame.c -- Frames and labelframes. Not much to say here either. Future directions: frame widget: None. This is a simple widget, and shall remain simple. Future directions: labelframe widget: Should use the Ttk_Manager API to manage the -labelwidget. There are several alternate display style possibilities that ought to be, but are currently not, implementable with this widget (see recent discussion on tktable-tile-dev for details). entry.c -- Entry and combobox widgets. The entry widget presented something of a challenge, since the bulk of the display is handled by the widget itself instead of by an element. The theme engine doesn't support "owner-draw" widgets very well (yet). Future directions: Reuse the "scroll.c" API to manage the -xscrollcommand (once the former has been fixed). Remove the backwards-compatibility methods 'scan mark', 'scan dragto', 'selection to', and 'selection adjust'. These are unused (and actually a bad idea). It ought to be possible to build a spinbox widget on top of the [ttk::entry] entirely in Tcl code. And a searchbox widget, and a URL bar, and a bunch of other customized entry-like widgets. I don't think that's possible right now, but it ought to be. combobox: Add library routines to enable autocompletion (must be flexible, as there are lots of different autocompletion styles; a single -autocomplete true|false option will not suffice.) Fix the focus problems on OSX, Windows, and certain X11 WMs. (This might require core patches; I haven't had any luck yet.) notebook.c -- ttk::notebook widget. Future directions: Right now the widget can't do Firefox-style tabs (with a 'close' gizmo on the tab) or Mozilla-style notebooks (with a 'close' gizmo in the upper corner). Both of these should be possible, but currently aren't. Features that will not be implemented: Multiple rows of tabs, scrolling tabs. Both of these options were considered and rejected. paned.c -- ttk::paned widget. Future directions: Jeff wants to rename this to "ttk::panedwindow". Support for "collapse buttons" and other sash controls. progress.c -- ttk::progressbar widget. Future directions: I want to rename this back to "ttk::progress". There are a couple of alternate display styles (OSX-style chasing arrows, throbbers, etc.) that ought to be supported cross-theme with common custom styles. scale.c -- ttk::scale widget. This one isn't finished yet. Future directions: Finish the widget. (See recent tktable-tile-dev discussions for API considerations). scrollbar.c -- ttk::scrollbar widget. Future directions: Native appearance on OSX. This is turning out to be very difficult to do, because of an impedance mismatch with the way Carbon wants to do things. separator.c -- A separator. Use this instead of 0-width frames to get a separator, the latter doesn't look right. treeview.c -- A multi-column hierarchical display. This one isn't finished yet. Future directions: I want this widget to be something a bit more powerful than the BWidget Tree, but still simpler than TkTreeCtrl. That's a useful ecological niche that seems to be unoccupied. The trick is to find the right set of primitive features -- there are a million things you can do with a Tree, but I don't want to have a million options and subcommands. Right now I'm looking at: + Add item tags (similar to text and canvas tags) to give applications more control over appearance; + Add tag event bindings for more control over behavior; and + Fix custom style support (see #1168548). I think that'll do it. Then there's the stuff that's just plain misimplemented -- it should compute item and heading heights from the layout instead of hardcoding them; need to replace the hairball [$tv identify $x $y] command with something reasonable; horizontal scrolling doesn't work; etc... THEME IMPLEMENTATIONS tkElements.c -- Default implementations for most elements, and layout specifications for the "default" / fallback theme. Future directions: This sort of evolved over time as new widgets were added and different approaches to building them were tried out; there's little evidence of intelligent design. This could stand to be reviewed and revised with an eye to consistency and orthogonalization. Ought to remove dependencies on 'Tk_3DBorder's and related routines. label.c -- Implementation of the "text", "image", and "label" elements. This is complicated enough that it warranted being split out into its own file. Future directions: May remove auto-stippling of 'image' elements; this is a lot of effort for a feature that probably shouldn't be implemented in the first place. (Tile widgets provide a more flexible way to specify state-dependent images.) classicTheme.c -- Tk classic look and feel; 1990s-era Motif. Future directions: I might eventually get around to fixing the ttk::button default ring. altTheme.c -- The "alt" / "revitalized" theme. Follows the Windows MSUE guidelines (pre-XP); visually compatible with 1998-era GNOME and KDE. Future directions: Notebook tabs aren't right; there's a performance issue with checkbutton and radiobutton indicators. clamTheme.c -- The "clam" theme; inspired by the XFCE family of GTK+ themes. Future directions: I was going to get rid of this entirely, but due to popular demand it'll be retained. Much of the implementation is rather ad-hoc; it could be refined and streamlined. aquaTheme.c -- Platform-specific theme for OSX. Future directions: Lots of stuff still isn't right here. Still uses the old style of notebook tabs (from OSX "Bobcat") instead of the newer segmented control (from OSX "Ocelot"). Native scrollbars aren't implemented at all (tough to solve). Only supports one style of window background (nested groupboxes, "brushed metal" style, etc., aren't supported). Very tough to solve. winTheme.c -- Platform-specific theme for Windows (pre-XP). Future directions: Spacing parameters might need a bit of tweaking, other than that it seems to be in good shape. xpTheme.c -- Platform-specific theme for Windows (post-XP). Future directions: Same as above; spacing might be a little off, other than that it looks OK. stepTheme.c -- Modelled after the GNUStep/NextStep look and feel; also an experimental playground for trying out new stuff. Future directions: Unless anybody is using this in production, it will probably be shuffled off into the "demos" directory as an example of a dynamically-loadable theme. MISCELLANEOUS: ttkDecls.h ttkStubInit.c ttkStubLib.c -- The stub library; can be used to implement loadable themes written in C. * * * IMPORTANT NOTICE * * * The tile stub table is generated with a modified version of genstubs.tcl. There are a number of small but important differences in the way the Ttk stubs table works, that are intended to make future evolution easier. compat.h -- A ghastly autogenerated mess of C preprocessor macros used to implement the Tk 8.4 compatibility options. This is so people could say "namespace import -force tile::*" in existing applications without immediately breaking everything. (Note: if anyone is still doing that, STOP!) Future directions: Going away. May be gone by the time you read this. gunk.h -- Miscellaneous portability gunk that I had to add to get stuff to compile on various platforms and against different Tcl/Tk distributions. Future directions: Needs to be killed. win/monitor.c -- WIN32 voodoo. Used to detect when the user has switched desktop themes or color schemes. win/nmakehlp.c -- To be honest, I don't know what this is for :-) Has something to do with the MSVC-based build system.