Ticket UUID: | 5f739d22533a85c47db9ffb5e698f51a3c7d817d | |||
Title: | Inconsistency in whether widgets allow negative borderwidths | |||
Type: | Bug | Version: | 9.0 | |
Submitter: | marc_culler | Created on: | 2024-07-08 21:55:02 | |
Subsystem: | 23. Option Parsing | Assigned To: | marc_culler | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Open | Last Modified: | 2024-08-26 09:20:02 | |
Resolution: | None | Closed By: | nobody | |
Closed on: | ||||
Description: |
In Tk 9.0 a Canvas widget can have a negative borderwidth (whatever that is supposed to mean): % canvas .c .c % .c configure -borderwidth -2 % .c configure -borderwidth -borderwidth borderWidth BorderWidth 0 -2 But a button cannot have a negative borderwidth: % button .b .b % .b configure -borderwidth -2 % .b configure -borderwidth -borderwidth borderWidth BorderWidth 2 0 Surely this inconsistency is not intentional, right? So I think this is a bug. | |||
User Comments: |
jan.nijtmans added on 2024-08-26 09:20:02:
It turned out that for "frame", width and height was still not handled correctly. fixed that now. I'm sure there are more ...., so keeping open marc_culler (claiming to be Marc Culler) added on 2024-07-12 16:32:46: I see that the scrollbar manual page has already been edited as I suggested. (I was looking at the online manual). So all that is needed is to set borderwidth to 0 when a negative value is specified. marc_culler (claiming to be Marc Culler) added on 2024-07-12 16:26:07: Here is a really weird one, which also does not seem to behave the way the manual says: % scrollbar .sb .sb % .sb configure -borderwidth -2 % .sb configure -borderwidth -borderwidth borderWidth BorderWidth 0 -2 % .sb configure -elementborderwidth 3 % .sb configure -elementborderwidth -elementborderwidth elementBorderWidth BorderWidth {} 3 % .sb configure -elementborderwidth -3 % .sb configure -elementborderwidth -elementborderwidth elementBorderWidth BorderWidth {} {} So borderwidth is allowed to have a negative value but elementborderwidth is set to '' if it is assigned a negative value. The manual says (about elementborderwidth): "If this value is less than zero, the value of the -borderwidth option is used in its place." It would seem that feature could never be activated, since the value is never less than 0, although it might be ''. One would need to read the code to learn that setting the option to {} causes the struct field to be set to INT_MIN, which is actually a negative value. Also, the manual says that the -borderwidth is always non-negative: "Specifies a non-negative value indicating the width of the 3-D border to draw around the outside of the widget" There are many ways to interpret the manual, but the intent is revealed by looking at tkUnixScrlbr.c, which says in TkDisplayScrollbar: elementBorderWidth = scrollPtr->elementBorderWidth; if (elementBorderWidth < 0) { elementBorderWidth = scrollPtr->borderWidth; } (The other platforms ignore the option altogether.) So one way to make the behavior agree with the manual would be to (1) replace negative values of borderwidth by 0; and (2) edit the manual to say "negative value or {}" and perhaps point out that the default value is {}. jan.nijtmans added on 2024-07-12 06:37:13: But ... be carefull: If the TK_OPTION_NULL_OK flag is set it's slightly different Then it's best to turn the invalid value into "", so it won't be taken into account. jan.nijtmans added on 2024-07-12 05:23:31: >Can I do it like this? +1 marc_culler (claiming to be Marc Culler) added on 2024-07-12 01:46:24: Can I do it like this? #define FIX_NEGATIVE_OPTION(widget, option) \ if (widget->option < 0) { \ widget->option = 0; \ if (widget->optionPtr) { \ Tcl_DecrRefCount(widget->optionPtr); \ } \ widget->optionPtr = Tcl_NewIntObj(0); \ Tcl_IncrRefCount(widget->optionPtr); \ } :^) jan.nijtmans added on 2024-07-11 21:49:05: And [c15c895b789cd7b6|here] is the fix for those examples :-) Good luck, doing this for all options with the same consistency ... marc_culler (claiming to be Marc Culler) added on 2024-07-09 15:28:36: Here is another inconsistency. A button treats negative width and height values differently from how it treats negative borderwidth values in Tk 9.0: % button .b .b % .b configure -width -100 -height -100 % .b configure -width -width width Width 0 -100 % .b configure -height -height height Height 0 -100 marc_culler (claiming to be Marc Culler) added on 2024-07-09 02:26:36: Another way to drive unit testers crazy is to change the wording of error messages, causing tests which check the error message to start giving false negatives. I think the best strategy for Python would be to raise a Python exception if a negative value is supplied to an option which is *planned* to not use the TK_OPTION_NEG_OK attribute, even if the restriction is not yet enforced by actual Tk widgets. That way when Tk gets around to finishing TIP 698 no extra work will be needed for Python. One way around the error message issue would be to add a prefix to each message containing a numerical code. Then the unit tests only need to check the code, and Tk can change the wording to our heart's content. IF a message changes from: "Tcl_CreateInterp error 123: can't create global namespace" to "Tcl_CreateInterp error 123: cannot create global namespace" then it will not break any correctly written unit tests. PS If I were allowed to offer an opinion about the discussion in [0439e1e1a] I would say that making a message more "formal" by changing can't to cannot while still omitting articles and using incomplete sentences seems Quixotic. marc_culler (claiming to be Marc Culler) added on 2024-07-09 01:46:29: In the tkinter unit tests they test assigning a list of values for each option of each widget type. They use configure to set the opeion and then use configure or cget to read the option. The test compares the input and the output. They have a set of comparison functions that are supposed to cover the different possibilities. But if the behavior varies by widget type, option name, and Tk version, it makes for a lot of extra work. And if it also varies over time with the same Tk version that makes it really hard. It seems like it would be better if it just depended on the Tk version and the option name, and if there weren't too many different behaviors among the different options. jan.nijtmans added on 2024-07-08 22:38:36: In Tk 8.6: % button .b .b % .b configure -borderwidth -2 % .b configure -borderwidth -borderwidth borderWidth BorderWidth 2 -2 This suggests that buttons accepts a negative borderwidth, but in fact it doesn't. See also TIP #698. I think the best way to handle this is as described in the TIP. The second-best way (as some - but not all - widgets already do) is change the negative value to 0 or {}. This is done in Tk 9 for 'button' and 'message', but not yet for other widgets. Indeed, this is not done consistently yet |