Author Topic: wxSmith Feature request: Option to disable calls to Fit() and SetSizeHints()  (Read 16109 times)

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
I use wxSmith to generate layouts but often want to add extra controls or hide controls outside wxSmith's automatically generated code. The problem I have is that for every sizer wxSmith adds this code:   
   theSizer->Fit(theWindow);
   theSizer->SetSizeHints(theWindow);

This locks window sizes causing layout issues if you later hide controls or add extra controls. I am currently manually deleting these calls but if I make any changes to the layout wxSmith puts them back. It's easy to forget to go back and edit the code. It would be really handy to have an option to not put these calls in.

As an aside, is there any need to call Fit and SetSizeHints for every sizer?. None of the wxWidgets samples do this. They only do it for the top level window. Looking at the changelog it appears these calls were added back in 2005 but there is no explanation of why.

Offline Miguel Gimenez

  • Developer
  • Lives here!
  • *****
  • Posts: 1553
You can remove that code from src\plugins\contrib\wxSmith\wxwidgets\wxscontainer.cpp (lines 214 to 217) and recompile C::B

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
Thanks. Yes, I saw that code. The problem is that taking it out would affect all windows in my application. I don't add/hide controls on all windows. Making it optional for a window gives the choice.
I'm sure I'm not the only one caught by this. The big problem is that when you do add/remove controls it is very unpredictable what will happen. Sometimes it works, other times it does not. It took me an embarassingly long to figure out why my layouts sometimes went wrong in strange ways. Without those calls the windows lay out predictably.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Do you want to have control if wxsmith would generate the fit/layout for the top level windows?
Probably this was done this way because of misunderstanding of wx or wx-bug which are no longer present.
I doubt we'll know the exact reason, so I think we should try to modify wxsmith to generate idiomatic wx style code and see what happens.

I suppose we could separate the fit code in a separate section, so the user can just delete it or comment it out.
Something like this:
Code
// * wxsmith
main code
// * wxsmith

// *wxsmith-layout
the layout code
// *wxsmith-layout

With this scheme the user would be able to decide on a case by case basis if he/she wants the layout code.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
Quote
Do you want to have control if wxsmith would generate the fit/layout for the top level windows?
Ideally. For example I quite often create panels in wxSmith which are then used in multiple windows. Calling Fit/Layout in them is redundant.


Quote
I suppose we could separate the fit code in a separate section, so the user can just delete it or comment it out.
That sounds like a good idea. How would it cope with existing code? Currently all of the creation code is marked with
//(*Initialize(myClass)
//*)

To be honest I'd assumed such an option would be a check box in  the top level window's options in the wxSmith designer. I prefer your suggestion though.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
I'm not sure the top level window has any properties anywhere.
I'm not too versed in wxSmith's internals, so I might miss something.

Preserving compatibility would be troublesome, unfortunately, you're correct.
Probably we'll have to use something like "// InitializeNoLayout(myClass)" and this would work for new code only or if the user manually changes from "//* Initialize(myClass)" to "//* IntializeNoLayout(myClass)"

This way it might not require adding "// InitializeLayout(myClass)".
Also I'm not really sure which is better to do.
Someone using wxSmith regularly should do some experimentation with both and tell us the results. :)

Other ideas are welcome of course and mostly patches, the probability for me finding time to work on this is close to 0!
But I can find time to review and apply patches.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
My knowledge of the internals of wxSmith is pretty much zero but I'll take a look. I downloaded the CodeBlocks source but for some reason my built executable won't run. I get 'This application was unable to start correctly (0xc000007b)'. As far as I can figure out it appears to be a 32 bit/64 bit mixup somewhere but I have yet to figure out where.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
You have to run update31.bat or update31_64.bat.
Also you have to copy the wxwidgets dll in the correct folder.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
Thanks. I'll give that a try tomorrow.

I think I'll look into where options like 'use parent from argument' are implemented. Adding a 'do not lay out' check box there may be a better bet.

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
The running problem was libstdc++-6.dll. A lot of applications install this file (The CodeBlocks + minGW package installs 3 copies!) and I had a mix of 32 bit and 64 bit versions on the path. CodeBlocks was picking the wrong one. I don't normally use MinGW so I haven't come across the problem before.

As expected simply removing Fit+Layout from wxscontainer.cpp messes up windows that don't have Fit + Layout elsewhere in the code.
From a quick glance at the wxSmith code, I think adding a top level option shouldn't be too bad. What are your thoughts on panels? In my opinion panels created in wxSmith should never have Fit and Layout because they are always going to be contained by another window.
 

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
The major problem with wxSmith is that there is no button "regenerate all ui in the project/workspace", so it is hard to change such changes to the code-gen.
I'm pretty sure this would break things for existing users, but I'm not sure if it is a concern.
If we can generate more idiomatic wxwidgets code and it works as expected for new projects then I'm fine to change it.
The changes to the wxsmith code would be visible in the diffs, so people could review them and either fix them or report them.

The second point would require us to have a clear explanation why having Fit+Layout for panels is detrimental.
Do you have an example or link to documentation?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
My knowledge of the internals of wxSmith is pretty much zero but I'll take a look. I downloaded the CodeBlocks source but for some reason my built executable won't run. I get 'This application was unable to start correctly (0xc000007b)'. As far as I can figure out it appears to be a 32 bit/64 bit mixup somewhere but I have yet to figure out where.
Told us how you build the C::B(compiler, wx version and steps), I think we can help you to solve this issue.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
I dug into the code and added a 'Lay out the window' property to wxFrames and wxDialogs (maybe needs a more descriptive name). If this is checked only one SetSizeHints() or Layout() call is generated for the top level sizer. If it is not checked there is no SetSizeHints() or Layout().
wxPanels never have SetSizeHints() or Layout() because they cannot be top level windows.

I'm pretty sure this would break things for existing users, but I'm not sure if it is a concern.

As far as I am concerned, breaking existing projects is not acceptable. I'm testing on an existing project to make sure it doesn't. If 'Lay out the window' is enabled (the default) windows should behave pretty much the same as they do now. The generated code will change slightly when you open the wxs file but that often happens when a new feature is added to wxSmith.

Quote
The second point would require us to have a clear explanation why having Fit+Layout for panels is detrimental.
Do you have an example or link to documentation?
wxSizer::SetSizeHints https://docs.wxwidgets.org/3.0/classwx_sizer.html#abc460cd0e2bb3bde72142fdb434bc546 lays out the window then fixes the window's minimum and maximum sizes based on the current layout. To quote the wxWidgets docs 'This only makes sense when window is actually a wxTopLevelWindow such as a wxFrame or a wxDialog'.

Currently SetSizeHints is called for every window containing a sizer. This effectively fixes the size of every window.  While not recommended, this is not a problem until you change the contents of any child windows. Now when you call Layout() on the top level sizer it cannot resize child windows to fit their updated control layout.

Panels by definition are always child windows so should never use SetSizeHints.


Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
Here is a patch. I tested it on a pretty big project with about 60 windows managed by wxSmith. Some windows have layout disabled. The generated code all looks correct. I haven't tested every window in the application but every one I have tested so far looks as it should.

Offline lesnewell

  • Multiple posting newcomer
  • *
  • Posts: 66
Told us how you build the C::B(compiler, wx version and steps), I think we can help you to solve this issue.

I followed the instructions here http://wiki.codeblocks.org/index.php/Installing_Code::Blocks_from_source_on_Windows. I Installed the CodeBlocks 20.03 with MinGW package and used the recommended wx3.1.4 source. Using 64 bit build.

As I mentioned in a previous post the issue is that there are loads of copies of libstdc++-6.dll on my machine, both 32 bit and 64 bit. I have many open source applications installed and apparently many were built with MinGW. CodeBlocks even installs 3 copies.

I am currently getting around the problem by running CodeBlocks from a command prompt with PATH just set to point to MinGW and the wx dlls.