When developing additional widgets which are to match with the current
style/theme it can be useful to "cget" existing widgets.
Is this something that will work with future releases of Tile?
Many Thanks,
=Adrian=
Many widget options in Tile have a NULL default value,
which means that the actual value will be taken from
the theme.
>When developing additional widgets which are to match with the current
>style/theme it can be useful to "cget" existing widgets.
That approach should still work -- if you say [ttk::label .l1] ;
[ttk::label .l2 -background [.l1 cget -background]] it'll
set .l2's -background to the empty string, which in turn
will cause the actual background to be inherited from the theme.
But it's easier to do nothing at all, and just use the built-in
defaults.
What doesn't work is to [cget] an option value from a Tile widget
and try to apply it to a core widget -- most of the core widgets
don't allow NULL / empty values for things like -background and -font.
For -font, you can use one of the symbolic font names defined
in $tile_library/fonts.tcl -- TkDefaultFont is usually what you want.
For -background and -foreground (not to mention -activebackground,
-activeforeground, -disabledforeground, etc., ...) it's not so
straightforward. My recommendation here is, again, don't do anything.
The default tile widget defaults match the default core widget defaults
on all platforms unless the application, user, or desktop environment
has changed them via the option database.
--Joe English
> What doesn't work is to [cget] an option value from a Tile widget
> and try to apply it to a core widget -- most of the core widgets
> don't allow NULL / empty values for things like -background and -font.
>...
> For -background and -foreground (not to mention -activebackground,
> -activeforeground, -disabledforeground, etc., ...) it's not so
> straightforward. My recommendation here is, again, don't do anything.
I hope we can come up with a better plan than "don't do anything".
One example might be that I find I must use a tk entry widget for one
specific case, but can use ttk entry for all other cases. I would want
to be able to change the look of the native entry to match the
ttk::entry if the user chooses a different style at runtime.
Another example is where I want to create a megawidget button (frame,
internal button, maybe some other stuff), but I want it to look as close
as possible to the tiled widgets. It would be nice to be able to query
the internal widgets to decide how to render the frame.
I'm just thinking out loud here... it just seems that hiding information
about the themed widgets is taking away some flexibility that doesn't
need to be taken away. I could live with "cget" returning what it
returns now (ie the empty string) as long as it was possible one way or
another to get the information. Maybe something like [theme info
ttk::button -background] command or something ...?
One of tk's great strengths is it's introspection; I'd hate to have to
choose between that or tile (though, frankly, tile might win that fight :-)
That sort of thing is not, in general, possible.
On the one hand, the core widgets aren't typically flexible enough
to match the ttk ones in all cases -- e.g., NextStep-style scrollbars,
or 8.4 [button]s on Windows XP. And on the other hand, the Tile
style database doesn't in general even have enough information to specify
an "as-close-as-possible" appearance for the core widgets -- in the Aqua
theme for instance there is no -background setting for frames, anywhere,
since Aqua frames don't use a solid background color.
But again: by default, as long as the user, application, and
desktop environment have not changed the defaults by modifying
the option database / xrdb settings or explicitly calling
[tile::setTheme], Tile widgets' appearance will match core
widgets' appearance to the maximum extent possible based on
what the core widgets support. So in this case "do nothing"
really is the most effective way to make things match.
For cases where the user, application, or desktop environment
_have_ changed the defaults, I've got a half-cooked scheme in my
work-in-progress repository [*] that will apply Tile theme defaults
to the Tk option database, which (once it's integrated) will make
the core widgets match Tile widgets (again to the extent possible).
With this scheme in place, "do nothing" will still be the most
effective way to make things match.
Trying to extract Tile defaults and applying them individually to
core widgets is IMO solving the problem in the wrong place; that's
why I recommend not doing anything, at least not at widget creation
time. The right place to solve the problem is in the option database.
[*] http://www.flightlab.com/~joe/repos/themebag/palette.tcl
--Joe English
> Trying to extract Tile defaults and applying them individually to
> core widgets is IMO solving the problem in the wrong place; that's
> why I recommend not doing anything, at least not at widget creation
> time. The right place to solve the problem is in the option database.
Hmmm. So you're advocating that if I detect that colors have changed
(eg: user selected a different theme) I must do something like:
if {$theme_changed} {
<1 save any custom changes I've made to the option database>
<2 ttk::apply_theme_to_option_database>
<3 fetch color definitions from the option database>
<4 restore my custom changes>
.myWidget configure -background <fetched color>
}
That seems rather cumbersome. Admittedly I'm being a bit over dramatic
in that example since I rarely store custom values in the option
database in the first place and would try not to have to resort to such
shenanigans. In my own case, steps 1 and 4 wouldn't normally need to be
done.
Still, that seems like a valid scenario if I have things configured the
way I want and simply want to get the name of the background used by
ttk::entry. Besides copying attributes from a themed widget to a
non-themed widget, maybe I just want to stick the value in a listbox in
a dialog.
It seems to me that if you have the ability to populate the option
database from the theme, it should be possible to write a procedure to
extract a subset of that information without having to get the option db
involved.
<shrug>
It's not the end of the world and you certainly have a better handle on
the difficulty of the problem than I do, but I'll stick to my guns in
thinking a little more introspection would be useful.
Why wouldn't you make use of the "priority" argument of the [option]
command to give your custom changes priority over those controlled
by the option db (and presumably any Tile-driven defaults)?
Am I missing something?
--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
Why wouldn't I? Mostly out of ignorance. I've never had much luck with
the option database, and there have been times when I swore I was using
option correctly and the only priority I could make work was "100".
Still, that's beside the point. I guess I don't see why, if we can
populate the option database with values from the styles, why we can't
have a procedural interface that lets me avoid the option database.
>Hmmm. So you're advocating that if I detect that colors have changed
>(eg: user selected a different theme) I must do something like:
>
> if {$theme_changed} {
> <1 save any custom changes I've made to the option database>
> <2 ttk::apply_theme_to_option_database>
> <3 fetch color definitions from the option database>
> <4 restore my custom changes>
> .myWidget configure -background <fetched color>
> }
That would be one approach; it's sort of how tk_setPalette works,
and the Tile theme => core option mapping code has a little bit of
support for doing just this. True, it's full of pitfalls and has
lots of failure cases, but I really can't think of any other way to
do it that's any easier or more reliable.
>That seems rather cumbersome.
Agreed. But it wouldn't get any better with the approach you
suggest below -- the only thing that would change is the mechanism
for fetching color definitions (and fonts, and borderwidth settings,
et cetera.)
>Still, that seems like a valid scenario if I have things configured the
>way I want and simply want to get the name of the background used by
>ttk::entry. Besides copying attributes from a themed widget to a
>non-themed widget, maybe I just want to stick the value in a listbox in
>a dialog.
OK, but the thing is: a [ttk::entry] widget doesn't *know*
what its background color is; only the theme does. For some
widgets in some themes, that's not even a sensible question
to ask of a widget, or of the widget's style: TButton on
Windows XP and TFrame on OSX don't even *have* a -background,
for example.
Right now there's no reliable way to get that information out
of the theme, either, but long-term that'll be the place to look.
>It seems to me that if you have the ability to populate the option
>database from the theme, it should be possible to write a procedure to
>extract a subset of that information without having to get the option db
>involved.
Note that Tile doesn't have that ability yet -- the main thing
that's missing is that themes will have to define settings appropriate
for all the core widgets in addition to defining how all the
Tile widgets look. Once that's there, it'll be in a well-known
place -- most likely the option database -- but it's not there yet.
>It's not the end of the world and you certainly have a better handle on
>the difficulty of the problem than I do, but I'll stick to my guns in
>thinking a little more introspection would be useful.
Recent Tile releases do have some style database introspection
features -- but the information you want to pull out of it
simply isn't there, at least not reliably. Tile theme definitions
currently specify how tile widgets should look; they don't say
anything about how core widgets should look.
--Joe English
For example: I'd like to be able to create a label which has the same
font as an existing (themed) label, but with either or both of the
underline/bold attributes set and possibly in a different size. What
would be the recommended Tile method to achieve this?
Many Thanks,
=Adrian=
The Tile widgets uniformly use TIP#145(-inspired) named fonts.
First check if one of the following predefined symbolic font
names are appropriate for your purposes. If so, just use that:
# TkDefaultFont -- default for GUI items not otherwise specified
# TkTextFont -- font for user text (entry, listbox, others).
# TkHeadingFont -- headings (column headings, etc)
# TkCaptionFont -- dialog captions (primary text in alert dialogs, etc.)
# TkTooltipFont -- font to use for tooltip windows
If not, use [font configure TkDefaultFont] (or TkTextFont, or
whichever one you want to use as a base font) to extract the
default -family, -size, and -weight; modify to suit; and create
a new font with those attributes.
(See also library/fonts.tcl for more details).
--Joe English