masked numctrl diff between 2.8 and 2.9

Anyone has an idea of what causes the masked numCtrl to center the value and to use a bold font in 2.9.2.2?

The attached picture shows it in 2.8.12.0 and the right one is 2.9.2.2.

Werner

wxmasked.jpg

Trying to find more information I notice that when I switch in the numctrl demo (2.9) from a modified to the standard version or visversa I see this in the log window:

OnActivate: True
..\..\src\msw\window.cpp(582): 'SetFocus' failed with error 0x00000057 (param�tre incorrect.).

If I change the 2.9 masked control to use useFixedWidthFont=False the "bold" goes away but content is still badly aligned.

If I activate the dbg for line 2907 in wx.lib.masked.maskededit.py

dbg('font string: "%s"' % font.GetNativeFontInfo().ToString())

and use the non modified demo for numctrl I see the following:

Python 2.6 with wxPython 2.8
font string: "0;-11;0;0;0;400;0;0;0;0;0;0;0;0;MS Shell Dlg 2"
font string: "0;-11;0;0;0;400;0;0;0;1;0;0;2;48;Courier New"

Python 2.7 with wxPython 2.9
font string: "0;-12;0;0;0;400;0;0;0;1;0;0;0;0;Segoe UI"
font string: "0;-12;0;0;0;400;0;0;0;1;0;0;2;48;Courier New"

There is a pretty old ticket #9840 which mentions that MS Vista went to Segoe UI font - did this never make it into 2.8?

But I don't think that explains why text is bold and has an influence on data alignment within the numctrl.

Werner

···

On 09/10/2011 01:12 PM, werner wrote:

Anyone has an idea of what causes the masked numCtrl to center the value and to use a bold font in 2.9.2.2?

The attached picture shows it in 2.8.12.0 and the right one is 2.9.2.2.

Werner

IIRC the masked ctrls use spaces to implement alignment so if the default font has changed then that will affect the alignment of the contents, especially if it has gone from a fixed width font to a proportional spaced font.

I don't have time right now to dig into the code myself, but have you seen how Wil selected the fixed width font? If he's using wx.MODERN for the font family then that could be the problem. It should be wx.TELETYPE (or wx.FONTFAMILY_TELETYPE) instead.

···

On 9/10/11 4:12 AM, werner wrote:

Anyone has an idea of what causes the masked numCtrl to center the value
and to use a bold font in 2.9.2.2?

--
Robin Dunn
Software Craftsman

Very good tip, also Will is already using the wx.TELETYPE, but the change in default font also included a change in point size caused the problem.

If I add the following to wx.lib.masked.maskededit._setFont around line 2899:

             if 'wxMac' in wx.PlatformInfo \
                and self.GetWindowVariant() == wx.WINDOW_VARIANT_MINI:
                 points -= 1
             elif 'wxMSW' in wx.PlatformInfo:
                 # with wxPython 2.9 + the point size was increased to 9
                 # which made things look like bold and all the spacing was off
                 points -= 1

Added the "elif" clause.

This does the trick on Win 7 for me, i.e. the "bold" aspect of the text goes away and all the spacing is looking good again.

Should work also on Vista but might be an issue on XP - don't have easy access to an XP machine. Hopefully someone else can test this.

Werner

···

On 09/11/2011 03:35 AM, Robin Dunn wrote:

On 9/10/11 4:12 AM, werner wrote:

Anyone has an idea of what causes the masked numCtrl to center the value
and to use a bold font in 2.9.2.2?

IIRC the masked ctrls use spaces to implement alignment so if the default font has changed then that will affect the alignment of the contents, especially if it has gone from a fixed width font to a proportional spaced font.

I don't have time right now to dig into the code myself, but have you seen how Wil selected the fixed width font? If he's using wx.MODERN for the font family then that could be the problem. It should be wx.TELETYPE (or wx.FONTFAMILY_TELETYPE) instead.

That only fixes it when using useFixedWidthFont - which is default for masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Werner

···

On 09/11/2011 10:13 AM, werner wrote:

On 09/11/2011 03:35 AM, Robin Dunn wrote:

On 9/10/11 4:12 AM, werner wrote:

Anyone has an idea of what causes the masked numCtrl to center the value
and to use a bold font in 2.9.2.2?

IIRC the masked ctrls use spaces to implement alignment so if the default font has changed then that will affect the alignment of the contents, especially if it has gone from a fixed width font to a proportional spaced font.

I don't have time right now to dig into the code myself, but have you seen how Wil selected the fixed width font? If he's using wx.MODERN for the font family then that could be the problem. It should be wx.TELETYPE (or wx.FONTFAMILY_TELETYPE) instead.

Very good tip, also Will is already using the wx.TELETYPE, but the change in default font also included a change in point size caused the problem.

If I add the following to wx.lib.masked.maskededit._setFont around line 2899:

            if 'wxMac' in wx.PlatformInfo \
               and self.GetWindowVariant() == wx.WINDOW_VARIANT_MINI:
                points -= 1
            elif 'wxMSW' in wx.PlatformInfo:
                # with wxPython 2.9 + the point size was increased to 9
                # which made things look like bold and all the spacing was off
                points -= 1

Added the "elif" clause.

This does the trick on Win 7 for me, i.e. the "bold" aspect of the text goes away and all the spacing is looking good again.

Should work also on Vista but might be an issue on XP - don't have easy access to an XP machine. Hopefully someone else can test this.

Werner

...

That only fixes it when using useFixedWidthFont - which is default for masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Might have found the cause, but don't know how to fix it.

In wx.lib.masked.maskededit._calcSize there are these lines with "dbg" line uncommented:

             dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
             w, h = self.GetTextExtent(sizing_text)
             size = (w+4, self.GetSize().height)
             dbg('size:', size, indent=0)

Gives me this output for a numctrl field with 5 as integerWidth and in _calcSize this is adjusted by adding two more "M".

wxP 2.9 using useFixedWidthFont=False
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (81, 23)

wxP 2.9 using useFixedWidthFont=True
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (39, 20)

It looks to me that GetTextExtent in wxP 2.9 has an issue with calculating the width for a proportional font.

Werner

What about using "9" instead of "M" in _calcSize if it is a numCtrl?

Just did it as a test and this is what I get:
len(sizing_text): 7 sizing_text: "9999999"
size: (46, 23)

It is a bit short, but much better, adding an additional "9" is about right.

Note that this still does not fix the alignment issue, value is towards the middle of the control instead of being right aligned (suspect _adjustInt/Float or _setValue - will look into these over the next few days).

Werner

···

On 09/11/2011 11:19 AM, werner wrote:

...

That only fixes it when using useFixedWidthFont - which is default for masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Might have found the cause, but don't know how to fix it.

In wx.lib.masked.maskededit._calcSize there are these lines with "dbg" line uncommented:

            dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
            w, h = self.GetTextExtent(sizing_text)
            size = (w+4, self.GetSize().height)
            dbg('size:', size, indent=0)

Gives me this output for a numctrl field with 5 as integerWidth and in _calcSize this is adjusted by adding two more "M".

wxP 2.9 using useFixedWidthFont=False
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (81, 23)

wxP 2.9 using useFixedWidthFont=True
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (39, 20)

It looks to me that GetTextExtent in wxP 2.9 has an issue with calculating the width for a proportional font.

To fix the size issue I thought of doing this:
         if cont and self._autofit:
             dbg('isinstance(self, wx.lib.masked.numctrl.NumCtrl): "%s"' % self.__class__)
             # check for self.name in 'masked.num' ??? and use 9 instead of M
             if isinstance(self, wx.lib.masked.numctrl.NumCtrl):
                 sizing_text = '9' * self._masklength
                 wAdjust = 8
             else:
                 sizing_text = 'M' * self._masklength
                 wAdjust = 4
             if wx.Platform != "__WXMSW__": # give it a little extra space
                 sizing_text += 'M'
             if wx.Platform == "__WXMAC__": # give it even a little more...
                 sizing_text += 'M'
             dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
             w, h = self.GetTextExtent(sizing_text)
             size = (w+wAdjust, self.GetSize().height)
             dbg('size:', size, indent=0)

wAdjust = 8 ensures that all numbers are shown, "4" which is what it was before is just a little to small.

This still leaves the problem with the right align.

Masked controls pad the value with spaces to align and it seems that there is an issue of "sizing" of a blank, i.e. it works with a fixed size font, but the space does not take up enough space when using a propositional font. Any chance that this is also related with the GetTextExtent method and how it calculates the size of things?

Werner

···

On 09/11/2011 11:56 AM, werner wrote:

On 09/11/2011 11:19 AM, werner wrote:

...

That only fixes it when using useFixedWidthFont - which is default for masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Might have found the cause, but don't know how to fix it.

In wx.lib.masked.maskededit._calcSize there are these lines with "dbg" line uncommented:

            dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
            w, h = self.GetTextExtent(sizing_text)
            size = (w+4, self.GetSize().height)
            dbg('size:', size, indent=0)

Gives me this output for a numctrl field with 5 as integerWidth and in _calcSize this is adjusted by adding two more "M".

wxP 2.9 using useFixedWidthFont=False
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (81, 23)

wxP 2.9 using useFixedWidthFont=True
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (39, 20)

It looks to me that GetTextExtent in wxP 2.9 has an issue with calculating the width for a proportional font.

What about using "9" instead of "M" in _calcSize if it is a numCtrl?

Just did it as a test and this is what I get:
len(sizing_text): 7 sizing_text: "9999999"
size: (46, 23)

It is a bit short, but much better, adding an additional "9" is about right.

Note that this still does not fix the alignment issue, value is towards the middle of the control instead of being right aligned (suspect _adjustInt/Float or _setValue - will look into these over the next few days).

Werner

Is this on Windows?

You can use something like the attached to test if there is something wrong with GetTextExtent. The red box should be the same size as the text it encloses. You may also want to test if using self.SetFont/self.GetTextExtent has different results than when measuring with the dc. If so then perhaps the Masked controls should create a wx.ClientDC when they need to measure text. (Although that may already be what wx.Window is doing internally...)

test_GetTextExtent.py (857 Bytes)

···

On 9/11/11 2:19 AM, werner wrote:

...

That only fixes it when using useFixedWidthFont - which is default for
masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Might have found the cause, but don't know how to fix it.

In wx.lib.masked.maskededit._calcSize there are these lines with "dbg"
line uncommented:

dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' %
sizing_text)
w, h = self.GetTextExtent(sizing_text)
size = (w+4, self.GetSize().height)
dbg('size:', size, indent=0)

Gives me this output for a numctrl field with 5 as integerWidth and in
_calcSize this is adjusted by adding two more "M".

wxP 2.9 using useFixedWidthFont=False
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (81, 23)

wxP 2.9 using useFixedWidthFont=True
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (39, 20)

It looks to me that GetTextExtent in wxP 2.9 has an issue with
calculating the width for a proportional font.

--
Robin Dunn
Software Craftsman

...

That only fixes it when using useFixedWidthFont - which is default
for masked controls, but a bit ugly:-( .

Still hunting down the problem when useFixedWidthFont = False

Might have found the cause, but don't know how to fix it.

In wx.lib.masked.maskededit._calcSize there are these lines with
"dbg" line uncommented:

dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' %
sizing_text)
w, h = self.GetTextExtent(sizing_text)
size = (w+4, self.GetSize().height)
dbg('size:', size, indent=0)

Gives me this output for a numctrl field with 5 as integerWidth and
in _calcSize this is adjusted by adding two more "M".

wxP 2.9 using useFixedWidthFont=False
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (81, 23)

wxP 2.9 using useFixedWidthFont=True
len(sizing_text): 7 sizing_text: "MMMMMMM"
size: (39, 20)

It looks to me that GetTextExtent in wxP 2.9 has an issue with
calculating the width for a proportional font.

What about using "9" instead of "M" in _calcSize if it is a numCtrl?

Just did it as a test and this is what I get:
len(sizing_text): 7 sizing_text: "9999999"
size: (46, 23)

It is a bit short, but much better, adding an additional "9" is about
right.

Note that this still does not fix the alignment issue, value is
towards the middle of the control instead of being right aligned
(suspect _adjustInt/Float or _setValue - will look into these over the
next few days).

Werner

To fix the size issue I thought of doing this:
if cont and self._autofit:
dbg('isinstance(self, wx.lib.masked.numctrl.NumCtrl): "%s"' %
self.__class__)
# check for self.name in 'masked.num' ??? and use 9 instead of M
if isinstance(self, wx.lib.masked.numctrl.NumCtrl):
sizing_text = '9' * self._masklength
wAdjust = 8
else:
sizing_text = 'M' * self._masklength
wAdjust = 4
if wx.Platform != "__WXMSW__": # give it a little extra space
sizing_text += 'M'
if wx.Platform == "__WXMAC__": # give it even a little more...
sizing_text += 'M'
dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' %
sizing_text)
w, h = self.GetTextExtent(sizing_text)
size = (w+wAdjust, self.GetSize().height)
dbg('size:', size, indent=0)

wAdjust = 8 ensures that all numbers are shown, "4" which is what it was
before is just a little to small.

Please use a diff tool (using the unified context format option if available) and send this change as a patch so I can be sure I'm testing/applying the right thing.

This still leaves the problem with the right align.

Masked controls pad the value with spaces to align and it seems that
there is an issue of "sizing" of a blank, i.e. it works with a fixed
size font, but the space does not take up enough space when using a
propositional font.

Did this work in 2.8? I'm not sure I see how using a space in a proportional font could ever fully be relied upon for alignment. It might sorta work for some fonts, but I would think that it could always be way off for others.

···

On 9/12/11 2:21 AM, werner wrote:

On 09/11/2011 11:56 AM, werner wrote:

On 09/11/2011 11:19 AM, werner wrote:

Any chance that this is also related with the
GetTextExtent method and how it calculates the size of things?

--
Robin Dunn
Software Craftsman

Did some more testing/searching on this and the only way I could find to fix it is to use wx.TE_RIGHT style flag for the numctrl. As per doc this is only available in wxMSW and wxGTK2 (can't test this at the moment).

Attached are two patches for this.

numctrl - add the style if on wxMSW, I guess one should add wxGTK2 here too.
maskededit - change the char "M" to "9" if it is a numctrl to have better space/size calculation when using useFixedWidthFont=False

Patches are against wxPython 2.9.2.4

Would be great if someone on Mac and or GTK2 platform could check what is the status of masked.numctrl on there.

Werner

numctrl.patch (674 Bytes)

maskededit.patch (1.43 KB)

I get a ex.FontFamily error under XP, all fine under Win7:
wx._core.PyAssertionError: C++ assertion "ff_family != (0<<4)" failed at
..\..\src\msw\font.cpp(625) in wxNativeFontInfo::SetFamily(): unknown
wxFontFamily
File "C:\Dokumente und
Einstellungen\shelter\Desktop\OKI-OPO\gui2-standaloneV22-intl.py", line
6807, in <module>
  app.MainLoop()
File "C:\Python27\Lib\site-packages\wx-2.9.3-msw\wx\_core.py", line
8651, in MainLoop
  wx.PyApp.MainLoop(self)
File "C:\Python27\Lib\site-packages\wx-2.9.3-msw\wx\_core.py", line
7943, in MainLoop
  return _core_.PyApp_MainLoop(*args, **kwargs)
File "C:\Dokumente und
Einstellungen\shelter\Desktop\OKI-OPO\gui2-standaloneV22-intl.py", line
5526, in SaveAllProducts
  self.OnStartHwCalc(self)
File "C:\Dokumente und
Einstellungen\shelter\Desktop\OKI-OPO\gui2-standaloneV22-intl.py", line
5994, in OnStartHwCalc
  dlg.SetFont(wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, False))
File "C:\Python27\Lib\site-packages\wx-2.9.3-msw\wx\_gdi.py", line 2242,
in __init__
  _gdi_.Font_swiginit(self,_gdi_.new_Font(*args, **kwargs))

No probs under 2.8.x.
Added on top I also get the described "bold"-looking font ..
I looked into the att. patches but that does not cure it.

Are there any (tested) patches still out there?

Cheers

Tobi

···

Am 13.09.11 11:43, schrieb werner:

Did some more testing/searching on this and the only way I could find
to fix it is to use wx.TE_RIGHT style flag for the numctrl. As per
doc this is only available in wxMSW and wxGTK2 (can't test this at the
moment).

Attached are two patches for this.

numctrl - add the style if on wxMSW, I guess one should add wxGTK2
here too.
maskededit - change the char "M" to "9" if it is a numctrl to have
better space/size calculation when using useFixedWidthFont=False

Patches are against wxPython 2.9.2.4

Would be great if someone on Mac and or GTK2 platform could check what
is the status of masked.numctrl on there.

Werner