Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ttk::style element image sticks to base image width

44 views
Skip to first unread message

tombert

unread,
Nov 17, 2011, 10:31:16 AM11/17/11
to
Hi,

currently I'am deep into ttk and trying to build my custom widgets.
The following example is a simplification but it nicely explains my
problem. I want to create an entry containing custom images showing
the current state (e.g. warning and error). For this I'am using the
user definable states "user1" and "user2".

The problem is that the image element always has the width of the base
image (from file ttkImage.c imageSpec->baseImage) wheras I found in
ImageElementDraw a recalculation of the image width with
Tk_SizeOfImage.


************
set inull [image create bitmap]
set ierror [image create photo -file ".../14x14/error.png"]
set iwarning [image create photo -file ".../14x14/warning.png"]

toplevel .tt
ttk::entry .tt.e1
pack .tt.e1 -fill x -expand yes

ttk::style element create Warning image [list $iwarning user1
$inull]
ttk::style element create Error image [list $ierror user2 $inull]

ttk::style layout TEntry {Entry.field -sticky nswe -children
{Entry.padding -sticky nswe -children {Error -side right -sticky w
Warning -side right -sticky e Entry.textarea}}}

.tt.e1 state user2
************

When the states user1 and user2 are activated/deactivated the user2
state leaves an unwanted whitespace. In my opinion the width should go
to 0 because of the empty image.

Is this a bug? Can I easily force an image width recalculation?

thx for your help!
Thomas

Joe English

unread,
Nov 17, 2011, 2:36:28 PM11/17/11
to
tombert wrote:
>
> currently I'am deep into ttk and trying to build my custom widgets.
> The following example is a simplification but it nicely explains my
> problem. I want to create an entry containing custom images showing
> the current state (e.g. warning and error). For this I'am using the
> user definable states "user1" and "user2".
>
> The problem is that the image element always has the width of the base
> image (from file ttkImage.c imageSpec->baseImage) [ ... ]

[ ... example snipped ... ]

> When the states user1 and user2 are activated/deactivated the user2
> state leaves an unwanted whitespace. In my opinion the width should go
> to 0 because of the empty image.
>
> Is this a bug? Can I easily force an image width recalculation?


This is mostly intended behaviour. The basic idea was that
the layout, and hence the overall widget size, should not
depend on the widget state. Otherwise the application would
need to do a (potentially very expensive) geometry propagation
dance every time the focus changed or the mouse moved.

This might be worth revisiting though. Recomputing widget internal
layout isn't expensive -- it does this on every redraw anyway --
the only expensive part is when the required size changes.
It should be possible to use state=0 to compute the default
required baseline size, but let the internal layout vary
within the allocated parcel depending on state.

It would require an incompatible ABI change, though, since
the widget state isn't passed to Ttk_ElementSizeProcs at
present. Maybe for 8.7.

Could you open a bug report at SourceForge so this doesn't
get forgotten?


--Joe English

tombert

unread,
Nov 17, 2011, 3:52:04 PM11/17/11
to
>
> Could you open a bug report at SourceForge so this doesn't
> get forgotten?
>

https://sourceforge.net/tracker/?func=detail&aid=3439581&group_id=12997&atid=362997

tombert

unread,
Nov 18, 2011, 2:30:22 PM11/18/11
to
Can you give me another hint please?
I tried the above code with the winnative theme which fails because of the -border option in the layout:

{Entry.field -sticky nswe -border 1 -children {Entry.padding -sticky nswe -children {Entry.textarea -sticky nswe -children {image}}}}

When I remove the -border or set it to zero the image appears!?
I assume that -border is applied for Entry.field only, or does it have an effect on all the children?

thx

Joe English

unread,
Nov 18, 2011, 8:11:19 PM11/18/11
to
tombert asked:
> Can you give me another hint please?
> I tried the above code with the winnative theme which fails
> because of the -border option in the layout:
>
> {Entry.field -sticky nswe -border 1 -children {
> Entry.padding -sticky nswe -children {
> Entry.textarea -sticky nswe -children {image}}}}
>
> When I remove the -border or set it to zero the image appears!?


The "-border" layout option is an undocumented hack;
if specified, the element will be drawn *after* its children.
This hack was added to handle cases where child elements draw
outside their parcel -- drawing the border last overwrites anything
that scribbled out of bounds.

The winnative theme Entry.field element draws the whole edit box,
(EP_EDITTEXT, which includes the background fill pattern as
well as the border), so you should not specify "-border 1"
for this element.

You might also want to make the image element a sibling
of the textarea instead of a child:

Entry.field -children {
Entry.padding -children {
Entry.image -side right
Entry.textarea
}
}

That way the textarea parcel won't overlap the image;
otherwise the the entry widget may draw over it.


--Joe English

tombert

unread,
Nov 20, 2011, 4:11:46 PM11/20/11
to
Thx for this insider info.
Up to now I didn't see any difference when omitting the -border option - so I go with that.

The reason why I don't want to make it a sibling is that I don't want to mess the internal and outside size of the text-box each time I'am showing an icon. Which brings me to the next point.

In order to show up custom icons I'am going to create a separate layout for each entry and then dynamically changing the layout according to the state I'am in - just like:

No state:
Entry.field -sticky nswe -children {
Entry.padding -sticky nswe -children {
Entry.textarea -sticky nswe -children {
%gttk
}
}
}

and then replacing %gttk with my icons e.g.:
Some other state:
Entry.field -sticky nswe -children {
Entry.padding -sticky nswe -children {
Entry.textarea -sticky nswe -children {
icon1 -side right sticky e icon2 -side right -sticky e
}
}
}

So I'am ending up with some hundred or more layouts.
You wrote:

> Recomputing widget internal
> layout isn't expensive -- it does this on every redraw anyway --
> the only expensive part is when the required size changes

I tested the speed and don't see any significant drawback up to now.

Are there any other counter-arguments against my solution (each entry having its own layout)?

thx for your support

thomas

tombert

unread,
Nov 22, 2011, 7:43:54 AM11/22/11
to
0 new messages