1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
|
[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.
|