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, toggle it back off after a brief delay, and finally call the button's '-command'. All "activatable" tile widgets support <<Invoke>>, and the keynav package adds <<Invoke>> class bindings for many core widgets.If you want to simulate a button press without actually invoking it, just toggle the 'pressed' state. This will update all of the element options needed to make the button looked pressed, regardless of the theme or widget style. (This is considerably simpler than in core Tk, where you need to save and restore a number of interrelated options.)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 .lNow 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.JE: If you've changed the widget font and have forgotten what you changed it to, then [style lookup [$w cget -style] -font [$w state] ] might be what you're looking for; it depends on the widget class. Some widgets (notably ttk::treeview, plus the core text, canvas, and listbox widgets) can use more than one font, so the question as posed doesn't have a single answer. But most of the time when people are trying to figure this out, the right answer is still "just use TkDefaultFont."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.A good starting point is to move widget -option specifications into the option database, leaving just the subset that's supported by both Tile and core widgets in the main code. (YMMV, but for all the applications I've converted this ends up with a net reduction in code complexity.)See recent releases of Coccinella for a real-world example of a large, heavily-customized Tk application that can switch between tile and core widgets.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.10) I have code that uses tk_getoOpenFile and tk_getSaveFile. They don't use Tile. How can I fix that?Answer: Try out the File selection dialog for Tile by Schelte Bron. It also has a message box dialog.
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?JE A guess: you're probably using tile 0.7.3 or earlier. Earlier versions included some hacks to stop BWidgets from breaking when the namespace import trick was used. Unfortunately those hacks interfered with custom styles; they have since been removed, and the above works as expected with current (Feb 2006) CVS.
# 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 stepJE: This is still a problem: application-defined styles and user-settable themes still don't mix very well. Recent Coccinella releases implement a workable technique for managing this, but it's still more complicated than it should be. A better long-term solution is in the works.
# # 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 tooVince: 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).
If Tile has become so incompatible with Tk, then should it ship as an extension that is separate from Tk? If I am reading the above comments correctly, as well as comments on comp.lang.tcl, the TCT mailing list, etc. it sounds as if there is little practical use in trying to mix Tk and Tile - the look and feel would be so different as to make the application nearly universally disliked. And with there being less and less compatibility between the widgets, someone is going to have to somehow recreate useful Tk widgets such as dialogs in terms of Tile to get a unified look. So will it now be considered its own extension and shipped that way?Vince: I would say that the question is "why has tile become to incompatible with Tk" and what can be done to improve the situation. The discussion on the TCLCORE mailing list suggests that (at least some people) believe Tile doesn't need to be so incompatible, and could happily support many standard options. The problem is the extreme design choice that the current Tile makes: "everything is a style." By recognising that Tk's problem was there are no styles, Tile has gone to the opposite extreme (which is equally bad). The middleground is the place to be: some things are options, some things are styles and some things are both.SRIV: I originally felt the same way. As an early adopter of tile, I was estatic to find that I could make themes and styles that look and function IDENTICAL across platforms. But, as native look & feel became a tile priority, more focus was directed toward this goal, and it is an important goal. Native looking Tk apps have more appeal to serious developers than SAME looking apps across platforms. So now, I realize, that there are two separate needs that need to be addressed. The question is, can we leverage the tools that are the core of tile to do both, or should a separate extension be created for the "SAME look across platforms" theming engine?Vince: actually my point isn't that I want things to look non-native at all. I have no interest in things looking the same across platforms. My point is that I want to be able to configure some aspects of widgets without having to write a new style everytime: it's simply about the level of effort the developer has to go to, and in particular (given the title of this wiki page) the level of effort you have to go to migrate existing code. There are plenty of options like padding, borderwidths, anchor, wraplength, etc which are, frankly, almost nothing to do with a native look and feel. Tile gets in the way of configuring such options because it insists you use a style to control them. I'm sure sometimes I will want to use a style to control most options (particularly in new code I write), but I'm equally sure I want to simply configure some options like I've always been able to do -- not to make something look non-native, just to tweak a layout or set a different fontsize, or whatever.SRIV: Good points, I'd probably want the same capabilites too if I were developing native looking apps.
KaKaRoTo: Hi All, I'm KaKaRoTo, admin and developper of the aMSN project (http://amsn-project.net) which is a Tcl/Tk application. We always had a lot of questions about the look and feel of Tk, and requests to use GTK, which is impossible for us to do, so I wanted to use Tile to make aMSN look better. Of course, I bumped into this problem of having to rewrite the whole application in order to get it to work with Tile, which is undoable. It turned out my project of a "simple plugin" that would load Tile became a project involving wrapping the whole Tile widgets to make them compatible with Tk widgets. This involved a lot of work, and it's not yet finished, but for many widgets, the work is done and the Chameleon plugin (the project I work on) seems to be stable enough for everyone to use. I was able to create a common interface to ease the wrapping of the widgets, and now I have the following widgets wrapped :
- button
- frame
- labelframe
- label
- radiobutton
- checkbutton
- entry
- menubutton
- scrollbar (not tested).
- combobox (wrapped from widget : )
- notebook (wrapped from BWidget's NoteBook)
- panedwindow
- progressbar
- dialog/message box
- scale
package require Chameleononce the script you launched it with is idle (using the event 'after idle' ) it will wrap the tk widgets into tile widgets (this should give you enough time to read your program's configuration and set chameleon's options like which widgets to wrap and which theme to use for example). If you want it to wrap the widgets right away (because you build your GUI in the initial script for example), you can simply call ::chameleon::rewrap. To configure Chameleon, you can use the helper proc
::chameleon::ConfigureChameleonit will open a window with options. You can also configure it programatically by looking at the variable ::chameleon::config().If you want to see the debug output (very little output) you can specify a command for this by calling ::chameleon::SetDebugProc $proc, so it can be
::chameleon::SetDebugProc putsor
::chameleon::SetDebugProc [list .my_debug_window.text insert end]Finally, if you want to translate some of the fields, like the 'theme' or 'widgets_to_wrap' labelframes of the configure window, you just need to implement a function named 'trans' that translates one of those keys into the string that you want...To test what Kevin Walzer said, I just tried this new version on TkDiff, and it works fine, I just added these 3 lines in the begining of the tkdiff file, right after the package require Tk :
package require Chameleon ::chameleon::rewrap ::chameleon::ConfigureChameleonand it worked right away.If you want to follow up with the development, you can always get the latest SVN version of Chameleon from this URL : https://svn.sourceforge.net/svnroot/amsn/trunk/amsn-extras/plugins/chameleonNote : This has not been tested and may not work with the tcl/tk 8.5 version that has tile included. Any patches are welcomed (as long as it doesn't break compatibility with tcl/tk 8.4).Any comments are welcomed of course (you can contact me at kakaroto AT kakaroto.homelinux.net).
LV: So are you saying that, with Tile and Chameleon, you track GNOME themes relatively well? That seems like something that perhaps should be considered part of Tk, if it makes using Tile easier.KaKaRoTo: Hi LV, I'm not saying that we can track GNOME themes easily, actually, Tile has a theme 'tile-qt' that makes it integrate fully with QT, but there is no theme 'tile-gtk' that would make it integrate with GTK (but I think that there is a way to tell QT itself to integrate with GTK, but I'm not sure). What Chameleon allows you to do is only to use Tile in your application without any code modifications, to see what it will enable your Tk app to do, you'll need to see what Tile allows you to do, Chameleon is mainly a bridge between Tile and Tk, nothing more.George Petasis: As of august 2008, there is also a TileGTK theme [1].