Version 33 of How to migrate to Tile

Updated 2006-02-14 19:30:37 by escargo

Now that Tile is at 0.7.5 and all 'compatbility options' have been removed, it is impossible to convert many applications to use Tile with the simple recipe of "namespace import -force ttk::*" and a bit of manual tweaking (this was reasonably possible with Tile < 0.7). In fact even Tk's built in dialogs will throw errors all over the place with such an approach. This page is here to help (hopefully!).

I believe the first lesson in migration is a mental one. Tile is designed to be different. Tk was designed so that everything "just works", but Tile is designed so that you have to follow a strict path to achieve your platform-native look. This means that obvious things you may have learned from Tk are just wrong now. For example:

Eg1: What font does this label have?

Tk: set font [$label cget -font] ; set size [font measure $font $text]

Ttk: error no such option '-font'...

or

Eg2: This widget's a bit cramped, let me give it some more space: $widget configure -borderwidth 4

Ttk: error no such option '-borderwidth'

So you have to recognise that your entire approach will have to be different to cope with Tile. It would have been pretty easy to code Tile deal with most standard options just like Tk does, but the developers appear to have made a conscious decision not to do anything like that. (Note that this page does not attempt to justify why the Tile developers rejected the idea of allowing configuration options to actually work and forced the programmer down the path of using styles for absolutely everything.)

Note: currently most of the answers here are empty. Tile's documentation wasn't too helpful, so I'm hoping that one of the Tile developers might step in with some answers.


Here are some common issues in migrating to Tile, together with their resolutions:

1) Tk's dialogs manually adjust buttons with, for example, '$button configure -relief sunken'. Tile has no '-relief' option. How can a dialog's code programmatically press a button with Tile?

Answer: JE Tk's dialogs do this to simulate a button-press (for keyboard accelerators). If that's what you're trying to do, then use: [event generate $button <<Invoke>>] That will toggle the 'pressed' state on and, after a brief delay, back off, and finally call the button's '-command'. Toggling the 'pressed' state updates all of the element options needed to make the button looked pressed, regardless of the theme.

If you're trying to change the -relief for some other reason, then I don't know. It depends on what you're trying to do (note that in many themes, buttons don't even have a traditional Motif-style border.)

2) Labels, checkbuttons etc all have a variety of wrapping options so text can wrap across multiple lines. How can this effect be achieved with Tile? How can I create a Tile checkbutton widget that has wrapped text?

Answer: JE The 'ttk::label' widget supports most of the traditional Tk options (-wraplength, -anchor, -borderwidth, -relief, etc.). One approach is to configure a 'ttk::label' to act like a checkbutton (... details tbd...)

I assume those details are going to be half a page of code just to mimic an option that ought to be there already. Tk is supposed to be simple - that's why we use it. If I wanted something complex I'd code in a different language.

3) Tk's menubuttons have a '-indicatoron' option. How is this handled in Tile?

Answer: ...

4) I want a red label with a large font to warn a user about something important, but there isn't a -font or -foreground option. How is this done with Tile?

Answer: 'ttk::label' widgets support -font and -foreground; see (2).

4b) The answer to question 4 is a lot of work for just a big red warning label. Isn't there an easier way?

Answer: Use the standard Tk widgets.

APN Unless I misunderstand what you're looking for, I don't think you need to create a style for every theme. For example,

  package require tile
  style configure "WarningLabel.TLabel" -foreground red -font TkCaptionFont
  ttk::label .l -text "This is a warning" -style WarningLabel.TLabel
  pack .l

Now if the theme changes, the label will change with the theme except for the label font and color. Everything else will be inherited from TLabel which Tile will initialize based on the theme.

George Peter Staplin: That fails for me in NetBSD with Tile 0.7.2 (see below).

5) I want Tile widgets in Tk dialogs.

Answer: Rewrite the dialogs or use [insert name here]'s rewrite of the Tk dialogs.

6) I need to find out what font a widget is using so I can both display its name and calculate whether the widget will need several lines to fit a given textual string. How can I determine the widget's font?

Answer: JE By convention, Tile widgets use the symbolic font names defined in library/fonts.tcl. Most use TkDefaultFont; entry widgets use TkTextFont.

But I want to know the font of this widget not the font of some widget's default. My widget may have had various styles configured on it, or the user may have activated my special 'short-sightedness' plugin to temporarily increase font sizes. Surely I can find the font name associated with one specific widget.

7) My application is cross-platform. I'd like it to run if Tile is or is not available. How should I takes advantage of Tile when Tile is available, but works just fine when Tile isn't? Given the dramatically different design philosophy (e.g. of something as simple as the 'red label' above), it seems I'm just going to need to have a lot of different tile and non-tile branches in the code.

Answer: ... I think you need a lot of branches in your code and will have to write 2 versions of a lot of gui stuff. In one branch you configure the -style of tile widgets and in another branch you'll configure the various options of Tk's widgets. Of course you can factor some of this stuff into common procs, but you still need a lot of branches and a vast amount of work.

8) I want a widget that's just the same as another one, but with a red foreground. How do I manage that?

Answer: Create a new style in every single theme which is the same as your old style but with a red foreground. You can't just configure the foreground colour of a single widget. Why would you want to do that when you have the option of creating half a dozen styles instead ;-)

APN See my comment on (4) above. Now, if you really want to have widgets with many different colors then you are right in that you have to create a style for each of these setting the fg/bg to a different color in each style as in (4). But I would claim that for this case, you probably don't really want to use a theme-based engine for those widgets anyways and the Tk widgets are a better fit. For example, if you were writing a color-picker widget, you would not use the ttk::label. You would use Tk's label command or a canvas.

9) I have generic code that uses the configure -state to enable/disable a tree of widgets. Is there a way to make tile accept $widget configure -state?

Answer: JE That approach will continue to work with Tile; buttons, checkbuttons, entry widgets, etc., all support a '-state' option that admits (at least) '-state normal' and '-state disabled', as their Tk counterparts do. Couple caveats: the '-state' option should be considered "write-only" for Tile widgets, and beware that reenabling a widget with [$w configure -state normal] can unintentionally turn a readonly entry widget into an editable one (this goes for the core widgets too).

A more robust approach would be to try [catch {$w state disabled}] first (which will work for all Tile widgets), then [catch {$w configure -state disabled}] if that fails (which will work for most core widgets). If that fails, you can assume that the widget isn't disablable. Use [catch {$w state !disabled}] / [catch {$w configure -state $oldState}] to reenable the widgets.


SRIV I hope i'm wrong, but, due to lack of -options, I feel that tile widgets will be useless for building megawidgets. I do understand the goal of creating a native look and feel, which it does nicely.

APN I think this would depend on the kind of megawidgets you are building. For example, Csaba Nemethi's tablelist package has a tile version which works very well for me. I've also written a couple of megawidgets that clone Windows Explorer - see http://downloads.magicsplat.com/xpthemesample1.png and http://downloads.magicsplat.com/xpthemesample2.png - which combine tile with text and canvas and change when the XP theme is changed. Certainly for some types of megawidgets which expose font/color etc. tile may not be suitable.

George Peter Staplin I feel the pain. I was excited about Tile for a while. I converted several applications to use it. Then I upgraded to tile07.kit and found that most of my applications broke. They were unusable... So, I have removed Tile from all but 1 application -- the Whim window manager. Even there we now have what I consider unnecessary branches that are just tile-specific code. We no longer have the themed dialogs, because every dialog must now be rewritten. After the initial disappointment of Tile 07.x I talked with Joe English and unfortunately he isn't interested in changing things, and now with Tile going into the core it will probably go unused by all but the new apps, or those that pay to have applications converted.

Vince I'm really struggling to update Alphatk to use the latest Tile. In fact I'm beginning to agree with what you write George - Tile just isn't suited to updating complex applications. It demands such a different approach that it's only good if that approach is incorporated into the design from the beginning.

SRIV If you use it such that the OS controls the theme, then you get native looking apps cross platform with little effort. But since you can't predict what the users set theme will look like, you can't really predict what your app will look like, especially when you make megawigets.

APN To some extent, I feel the above discussion misses the point that Tile is not intended as a replacement for Tk, either now or in the future. If you want your widgets to look like the currently configured theme on the OS, use Tile. For the "client" areas (which are generally not theme-dependent) of the app, use Tk as that's generally more convenient. This is the same as what native apps do. Certainly, changing an entire app to use Tile is (IMHO) difficult, unnecessary and undesirable.

George Peter Staplin APN, I think you miss the point. The GUI looks like a mismash of different widgets when that's done. Your example of the big red label also fails to work properly. (see below)

Vince APN, I also think you miss the point. If Tile is to be useful it has to be usable for an entire app, except for some special cases (e.g. colour picker labels). 99% of widgets in any application are likely to want to be themed (certainly in my applications). So it is desirable to change an entire app to use Tile. If Tile doesn't allow that with a reasonable effort level, then Tile is poorly designed, unless there are compelling reasons to the contrary. I certainly see nothing in TIP#248 to say that migrating an application to tile is supposed to be "difficult, unnecessary and undesirable".

 style configure "WarningLabel.TLabel" -foreground red -font TkCaptionFont
 ttk::label .l -text "This is a warning" -style WarningLabel.TLabel
 pack .l

 #
 #That's ok, but I want a larger font.
 #
 style configure WarningLabel.TLabel -font {Helvetica 22}

 #
 # At this point nothing changes, so I wonder what's wrong?
 # I decide that tile is probably not updating the widget.
 #
 .l config -style WarningLabel.TLabel

 # 
 # Nothing changed, so at this point I decide to try *recreating* the widget (ugh!).
 #
 destroy .l
 pack [ttk::label .l -text "This is a warning" -style WarningLabel.TLabel]

 #
 # Hmm it's not using my big font.  Oh well.  Let's see if the style is retained after a theme change.
 #
 tile::setTheme step

 #
 # At this point the label loses its red color, and my earlier argument stands. 
 #

APN Wouldn't be the first time I missed a point :-). However, the example you gave above works for me (well kind of). The call to style configure to update the font does in fact result in the font being updated. This is on XP SP2 with Tcl 8.4.12, tile 0.7.3. So maybe this is a platform specific bug? On the other hand, setTheme generates a "package not found" error for me, probably because I hand installed tile and am missing some files.

George Peter Staplin Ah, so it works in Windows? I guess it may be a bug in Tile, or it could be that you are missing the files that break it. Before I came to my somewhat angsty view of Tile I talked with Joe English about my concerns. Unfortunately based on my interpretation of his responses he wasn't interested, in changing anything. In fact at the time he told me that he thought it was a mistake that Tile is going into the core. Perhaps it's still in the Tcler's Chat logs. It was a public conversation.

I also once asked if we could have -background and -foreground in native Tile widgets, and was told that "it's not possible in Windows." I later found an article in C/C++ User's Journal that had example code for doing so in Windows with the native widgets. I was excited, so I told Joe English about it. He wasn't interested. I even found the code on the C/C++ User's Journal website for him. And KBK also said it was possible. Joe English wasn't interested. So, I'm disappointed now.

JE More precisely, it's not possible in all themes. You can, with a lot of work, change the background color of Windows XP buttons. But you still can't do it in Aqua (at least, not to my knowledge), or in a pixmap theme. And if you do change the background color there are often a lot of other related colors that also need to be changed depending on the platform (active background, pressed background, border colors, foreground color in the various states...).

It wouldn't be hard to add a '-background' option, as long as you don't care whether or not it works.

I don't want to discount what Joe has done. He and the others have done something that's pretty good for native widgets, but it's not ideal for me, or the majority of existing applications. Rather than blaming tile or trying to convince the primary author of Tile, or the Tcl Core Team to change things I have decided to work on my own compatible version of themed widgets.

stevel it works in AquaTk too

Vince the above example doesn't work on Window XP with latest cvs head of Tile: the last call 'tile::setTheme step' results in a label which no longer has a large font nor red text - those style options seem to have vanished. The earlier stages of the example do work (i.e. the 'nothing changed' comments above don't apply in my testing).


Category Discussion