How to find my windows? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
a little bit
In need of some credit
In need of some credit
Posts: 6
Joined: Sat Apr 10, 2021 11:46 am

How to find my windows?

Post by a little bit » Mon Apr 12, 2021 10:37 am

I have built a wxWidgets application with a dozen windows or so with a single wxFrame as the root of the hierarchy. These windows interact with each other. More precisely, most of them need to access (i.e., call public member functions of) other windows in the hierarchy (e.g., the left pane of a wxSplitterWindow needs to access the right pane and vice versa). During the implementation, the most challenging problem for me was how to make these other windows available to a given window.

So far, I came up with two solutions:

1. global (lazy, f*ck it) approach: make Window IDs global. I maintain a list of global window IDs with one window ID for each window that needs to be accessed somewhere. The benefit is that I never have to think how to pass that needed window ID / pointer to the respective window. A macro-wrapped call of wxWindow::FindWindowById() is all I need then. Furthermore, I do rarely need to derive classes from wxWidgets standard window classes. I just need to configure an instance of the respective standard class since it does not need to store the window IDs / pointers of its accessed windows. The downside are the perils when using global variables. For instance, from the outside it is not clear what resources

Code: Select all

wxFrame* CreateMainWindow(wxString const& title);
actually accesses outside of its underlying window hierarchy. Furthmore, a function like the one before can only be called once in the application since it has the window IDs "burned in" (their names not their actual values; passing them via parameters is not an option since there are so many of them).

2. local (clean, crafted) approach: this is what I see often in the wxWidgets samples. Each window class has pointers to the other windows in the hierarchy it needs to access. The downside is, this requires deriving from the standard wxWidgets window classes since those pointers have to be stored somewhere (namely in the derived class). It makes setting up the whole hierarchy also somewhat complicated if you realize somewhere in the implementation that you need to access that grand-grand-grand-child of the 6th sibling of your grand-grand-grand-parent window to implement a feature. The good side is, that if you managed to do it right, you have no hidden global variables in your hierarchy. You could then call

Code: Select all

new MyFrame {/* all your needed parameters */};
and an entire hierarchy is built up. You could call that even multiple times with completely independent setups which is nice for reasoning about the application or its window hierarchy.

To make a long story short: What is the preferred (canonical, wxWidgets-esque) style of accessing windows in a non-trivial application? Is the global approach frowned upon? Should I "fumble" through the local approach instead?

PB
Part Of The Furniture
Part Of The Furniture
Posts: 3041
Joined: Sun Jan 03, 2010 5:45 pm

Re: How to find my windows?

Post by PB » Mon Apr 12, 2021 12:06 pm

I am not sure if either mentioned approach is "clean". Generally, such tight coupling of most classes is frown upon and using approaches such as MVC and similar is recommended.

However, I do understand that implementing stuff "properly" may take more time and effort and it is on programmer to decide whether it will pay off or not on case by case bases.

a little bit
In need of some credit
In need of some credit
Posts: 6
Joined: Sat Apr 10, 2021 11:46 am

Re: How to find my windows?

Post by a little bit » Wed Apr 14, 2021 6:10 pm

I am not sure if either mentioned approach is "clean". Generally, such tight coupling of most classes is frowned upon and using approaches such as MVC and similar is recommended.
You are right.

I rewrote my app using MVP pattern and now the pointers to the individual windows of the app have become private members of the view (and only the view). Hence, every window of the app is accessible by the view to fulfill the presenter's requests. Each interaction between the windows themselves (for instance, update the right window if there is a selection change in the left window) goes through the presenter (which in turn connects to the model, i.e., the actual domain-specific data processing). The presenter accesses the view, i.e., the set of windows, by a clean interface, i.e., a pure abstract base class, of which the actual concrete view is just an implementation. In fact, I could indeed swap that concrete wxWidgets-based view implementation for some other UI / framework if I like. The view in turn informs the presenter using hookable wxWidgets event handler bindings (I use boost::signals2 as recommended in a very old thread somewhere in this forum), i.e., the presenter registers at the view for the specific events it is interested in and supplies an appropriate handler function for each event. The model is also just an implementation of an abstract base class (model interface) and could be swapped for another implementation if needed.

The view does not know the presenter (let alone the model). The model does not know the presenter (let alone the view). The presenter effectively only operates between view and model interface and does not know their actual concrete implementations.

All in all, this looks clean to me. Thanks.

Post Reply