[BUG] The content of a wxStaticBox control is badly positioned when resizing it under macOS (Issue #22837)

61 views
Skip to first unread message

Gammasoft

unread,
Oct 1, 2022, 3:31:14 PM10/1/22
to wx-...@googlegroups.com, Subscribed

Description

The content of a wxStaticBox control is badly positioned when resizing it under macOS.

  • Consider this example that displays two static boxes in a panel with a box sizer that maintains their size and position according to the window size.
#include <wx/wx.h>

namespace Examples {
  class Frame : public wxFrame {
  public:
    Frame() : wxFrame(nullptr, wxID_ANY, "StaticBox and CheckBox example") {
      SetClientSize(300, 160);
      
      panel->SetSizerAndFit(boxSizer);
      boxSizer->Add(staticBox1, 1, wxGROW, 10);
      boxSizer->Add(staticBox2, 1, wxGROW, 10);

      check2->SetValue(true);
      check6->SetValue(true);
    }
    
  private:
    wxPanel* panel = new wxPanel(this);
    wxBoxSizer* boxSizer = new wxBoxSizer(wxHORIZONTAL);
    wxStaticBox* staticBox1 = new wxStaticBox(panel, wxID_ANY, "Group 1", {10, 10}, {135, 140});
    wxStaticBox* staticBox2 = new wxStaticBox(panel, wxID_ANY, "Group 2", {155, 10}, {135, 140});
    // If you replace the two lines above with the following two lines you will see the correct expected behavior.
    //wxPanel* staticBox1 = new wxPanel(panel, wxID_ANY, {10, 10}, {135, 140});
    //wxPanel* staticBox2 = new wxPanel(panel, wxID_ANY, {155, 10}, {135, 140});
    wxCheckBox* check1 = new wxCheckBox(staticBox1, wxID_ANY, "check 1", {20, 10});
    wxCheckBox* check2 = new wxCheckBox(staticBox1, wxID_ANY, "check 2", {20, 40});
    wxCheckBox* check3 = new wxCheckBox(staticBox1, wxID_ANY, "check 3", {20, 70});
    wxCheckBox* check4 = new wxCheckBox(staticBox2, wxID_ANY, "check 4", {20, 10});
    wxCheckBox* check5 = new wxCheckBox(staticBox2, wxID_ANY, "check 5", {20, 40});
    wxCheckBox* check6 = new wxCheckBox(staticBox2, wxID_ANY, "check 6", {20, 70});
  };

  class Application : public wxApp {
    bool OnInit() override {
      (new Frame())->Show();
      return true;
    }
  };
}

wxIMPLEMENT_APP(Examples::Application);
  • When you run this sample you obtains :

image

  • But if you resize the window vertically by dragging the edge down, you get :

image

  • Normally the contents of the two static boxes should not be moved.
  • If we replace the two static boxes by two panels, the content stays in place.

Remarks

This is similar to the way Cocoa handles the bottom-left control potion by default. While wxWidgets uses the top-left position everywhere.

Platform and version information

  • wxWidgets version you use: 3.2.0
  • wxWidgets port you use: wxOSX
  • OS and its version: macOS 12.6

Remarks

This issue is the same with wxWidgets 3.1.x and older macOS.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837@github.com>

VZ

unread,
Oct 3, 2022, 1:53:25 PM10/3/22
to wx-...@googlegroups.com, Subscribed

Thanks for reporting this, I can confirm that I see this behaviour too, but I don't really know how to fix it. Perhaps we should be calling sizeToFit whenever the window is resized?

@csomor If you have any hints here, they would be very welcome, TIA!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1265820177@github.com>

Gammasoft

unread,
Oct 3, 2022, 2:13:50 PM10/3/22
to wx-...@googlegroups.com, Subscribed

Makeshift external workaround

I've created a makeshift external workaround that may inspire you for an internal solution:

#include <wx/wx.h>

class wxGroupBox : public wxStaticBox {
public:
  wxGroupBox(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxASCII_STR(wxStaticBoxNameStr)) : wxStaticBox(parent, id, label, pos, size, style, name) {
    Bind(wxEVT_SIZE, [&](wxSizeEvent & event) {
      inner_panel->SetPosition(get_inner_box_position());
      inner_panel->SetSize(get_inner_box_size());
    });
  }
  
  wxPoint GetClientAreaOrigin() const override {return {inner_margin, inner_margin + extra_inner_margin_up};}
  
  void DoGetClientSize(int* width, int* height) const override {
    wxStaticBox::DoGetSize(width, height);
    *width = *width - GetClientAreaOrigin().x - inner_margin;
    *height = *height - GetClientAreaOrigin().y - inner_margin;
  }
  
  wxWindow* GetMainWindowOfCompositeControl() override {return inner_panel;}
  
private:
  wxPoint get_inner_box_position() const {
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Windows") return {0, inner_margin + extra_inner_margin_up};
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Macintosh") return {inner_margin, inner_margin + extra_inner_margin_up};
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Unix") return {inner_margin, 0};
    return {0, 0};
  }
  
  wxSize get_inner_box_size() const {
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Windows") return {GetClientSize().GetWidth(), GetClientSize().GetHeight() - GetClientAreaOrigin().y};
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Macintosh") return {GetClientSize().GetWidth() - GetClientAreaOrigin().x - inner_margin, GetClientSize().GetHeight() - GetClientAreaOrigin().y - inner_margin};
    if (wxPlatformInfo::Get().GetOperatingSystemFamilyName() == "Unix") return {GetClientSize().GetWidth() - inner_margin, GetClientSize().GetHeight() - GetClientAreaOrigin().y - inner_margin};
    return GetClientSize();
  }
  
  static constexpr int32_t inner_margin = 3;
  static constexpr int32_t extra_inner_margin_up = 5;
  wxPanel* inner_panel = new wxPanel(this, wxID_ANY, get_inner_box_position(), get_inner_box_size());
};

namespace Examples {
  class Frame : public wxFrame {
  public:
    Frame() : wxFrame(nullptr, wxID_ANY, "StaticBox and CheckBox example") {
      SetClientSize(300, 160);
      
      panel->SetSizerAndFit(boxSizer);
      boxSizer->Add(staticBox1, 1, wxGROW, 10);
      boxSizer->Add(staticBox2, 1, wxGROW, 10);
      
      check2->SetValue(true);
      check6->SetValue(true);
    }
    
  private:
    wxPanel* panel = new wxPanel(this);
    wxBoxSizer* boxSizer = new
 wxBoxSizer(wxHORIZONTAL);
    wxGroupBox* staticBox1 = new wxGroupBox(panel, wxID_ANY, "Group 1", {10, 10}, {135, 140});
    wxGroupBox* staticBox2 = new wxGroupBox(panel, wxID_ANY, "", {155, 10}, {135, 140});
    wxCheckBox* check1 = new wxCheckBox(staticBox1->GetMainWindowOfCompositeControl(), wxID_ANY, "check 1", {20, 10});
    wxCheckBox* check2 = new wxCheckBox(staticBox1->GetMainWindowOfCompositeControl(), wxID_ANY, "check 2", {20, 40});
    wxCheckBox* check3 = new wxCheckBox(staticBox1->GetMainWindowOfCompositeControl(), wxID_ANY, "check 3", {20, 70});
    wxCheckBox* check4 = new wxCheckBox(staticBox2->GetMainWindowOfCompositeControl(), wxID_ANY, "check 4", {20, 10});
    wxCheckBox* check5 = new wxCheckBox(staticBox2->GetMainWindowOfCompositeControl(), wxID_ANY, "check 5", {20, 40});
    wxCheckBox* check6 = new wxCheckBox(staticBox2->GetMainWindowOfCompositeControl(), wxID_ANY, "check 6", {20, 70});
  };
  
  
class Application : public wxApp {
    bool OnInit() override {
      (new Frame())->Show();
      return true;
    }
  };
}

wxIMPLEMENT_APP(Examples::Application);

Remarks

  • The problem with this external "solution" is that child controls must have wxGroupBox::GetMainWindowOfCompositeControl() as parent and not the control itself. But maybe in your internal structures there is a way to bypass this and call the control directly as parent.

  • This has no pretension of correction, it is just to advance the reflection ;-)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1265842483@github.com>

Stefan Csomor

unread,
Oct 7, 2022, 2:05:58 PM10/7/22
to wx-...@googlegroups.com, Subscribed

Within wx we are usually using "flipped" coordinates Apple Docs so wxPanel has 'children' coordinates the way wx thinks of them (origin top-left), but a group box needs a Cocoa type origin, ie non-flipped, otherwise the label is to tight at the top. A NSBox has a contentView that is the parent of the children, this is already allocated by the System, non-flipped of course :-( I'll see whether I could replace that one with a flipped NSView ...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1271891201@github.com>

Stefan Csomor

unread,
Oct 7, 2022, 2:19:57 PM10/7/22
to wx-...@googlegroups.com, Subscribed

I've implemented a flipped contentView, @gammasoft71 could you please retest with 3d478ce


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1271914039@github.com>

Gammasoft

unread,
Oct 7, 2022, 2:44:31 PM10/7/22
to wx-...@googlegroups.com, Subscribed

It works well for me.

Thanks for the correction.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1271957068@github.com>

Stefan Csomor

unread,
Oct 8, 2022, 7:25:27 AM10/8/22
to wx-...@googlegroups.com, Subscribed

Closed #22837 as completed.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/22837/issue_event/7547878491@github.com>

Stefan Csomor

unread,
Oct 8, 2022, 7:25:27 AM10/8/22
to wx-...@googlegroups.com, Subscribed

Thanks for testing. You are welcome :-)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1272296988@github.com>

VZ

unread,
Oct 8, 2022, 6:36:23 PM10/8/22
to wx-...@googlegroups.com, Subscribed

Thanks Stefan for fixing this! I believe this should be backported to 3.2 (please correct me if I'm wrong), so I'm reopening it and will close it after applying it there.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1272407925@github.com>

VZ

unread,
Oct 8, 2022, 6:36:24 PM10/8/22
to wx-...@googlegroups.com, Subscribed

Reopened #22837.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/22837/issue_event/7548578461@github.com>

Stefan Csomor

unread,
Oct 9, 2022, 3:05:31 AM10/9/22
to wx-...@googlegroups.com, Subscribed

@vadz sorry, I forgot, yes, I definitely think so, thank you.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22837/1272473263@github.com>

VZ

unread,
Oct 15, 2022, 11:53:37 AM10/15/22
to wx-...@googlegroups.com, Subscribed

Closed #22837 as completed.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/22837/issue_event/7595162580@github.com>

Reply all
Reply to author
Forward
0 new messages