8

I'm working on a simple widget system (single window, fixed size). Each widget gets its parent (i.e. the widget containing it) passed into its constructor - except for the root widget, which I called Screen.

I have some doubts if that approach makes sense. I did it because most of the widget systems I used before do it (Qt, GTK, ...), but I realised that these are quite a bit more complex than mine:

  • I have no window resizing
  • I don't plan to size containers based on their children's sizes
  • I don't think I need it for memory management (I'm using C++), I can use shared pointers instead (basically how it would work in Java)

Is there any reason why a widget would need a reference to its parent?

It's a major refactoring to change this. So before I go ahead and implement containers and layouts, I want to have a good idea of whether or not I'm going to need that parent.

Edit: Please note that the parent does know all its children anyway, I'm just wondering if the children need to know the parent as well.

3 Answers 3

5

As you pointed out, the child itself seldomly if at all needs to access the parent, as long as the parent does all the work and keeps track of its children. However, the classic getParent is most useful when you use the framework from outside.

Scenario

A simple operation that may cause problems is the following: given two concrete widgets that are somewhere in your overall widget tree and a use-case that requires you to swap these two, how does the swapping work?

Option 1: Tell the children

Tell your child widget to swap(withOtherChild). But swapping involves updating the parent's children datastructure in some way. As your child does not know its parent, how do you achieve this?

Option 2: Tell the parents

Tell the parent of a child to remove it and add the other one. Oh wait, same problem. You only have the children objects and there's no getParent on those.

Option 3: Grunt work

As a final option, you can traverse your whole widget tree in order to find a parent with hasChild(x) and one with hasChild(y) and then fall back to option 2.

Solution

You should keep the parent if you ever want to build large widget trees and perform operations that require moving a widget's position in the tree. If your widget trees are very small, or only have a very small depth, but fast hasChild accessors, then Option 3 may be acceptable for you and you could omit the parent reference.

References in Datastructures in general

What you are planning to do here is to build up a datastructure for a tree. Let's consider a simplification and for the sake of argument assume that every widget can only have one child. The result, of course, is a list and your question now becomes "should I have a single-linked or double-linked list?".

And just like lists, there is no definite answer, but only pros and cons. Obvious pros for the single-linked (i.e., no parent reference) are a) easier to implement and b) less memory. But the cons include a) some operations become slow as they have to traverse the structure and b) not having easy access to those operations may mean that the datastructure is cumbersome to use, and c) it uses more memory.

On the other hand, the double-linked variant, i.e. with parent reference, pretty much reverses these pros and cons.

In terms of a GUI library/framework though, the memory limits are usually not a problem that prohibits parent pointers. If you rule that out, and realize that it's a library/framework, and hence, it is preferrable for it to be hard to implement, but easy to use, then you essentially rule out the above pros of a single-linked approach.

I am not aware of the peculiarities of your project, so I want to refrain from telling you to keep the parent reference, as some of my above reasoning may well not apply in your case. In general, however, I consider parent references in a widget datastructure to be worthwhile for the above reasons.

2

In most of these cases there is quite some communication going on between parent and children in case of events, signals or state change (or simply to destroy children when necessary). For example a grouping box may handle it's contained radio buttons to ensure only one of them is "on" at a given time.

You may or may not plan to have functionality of this kind. Personally I would doubt if a widget system without it is worth the time since it wouldn't offer much. But then I would simply use one of the existing solution anyway.

6
  • 1
    All of that seems to be possible when the parent knows its children, which is the case for me. I'm just wondering if the child needs to know the parent as well.
    – futlib
    Mar 1, 2013 at 11:56
  • I'd happily use something existing, but we're on a rather unique environment here and figured our own simple system is the best approach.
    – futlib
    Mar 1, 2013 at 11:57
  • There are always reasons of course and Qt for example is quite heavy weight. The reason why the child needs to know its parent is mostly so it can register with it on creation or later send it state changes. Mar 1, 2013 at 12:09
  • You mean like when a radio button is clicked, it needs to inform the parent so that can untick the previously ticked one? Yes I think that'd be hard without the child->parent connection... Can you think of other examples?
    – futlib
    Mar 1, 2013 at 12:21
  • 2
    "Based on size and position" could leave you with really nasty code. I would prefer to trickle down events. Like parent gets click event it then "asks" its children if they are responsible which they decide based on their own position & size information. Other examples? Depends on how complex your widgets are. You say they won't be that complicated. But on the other side: If you add the parent pointer from the start it won't hurt much and you have them when you need them. Scrollbars are another good example I guess. They report scrolling to parent, parent tells view to update. Mar 1, 2013 at 12:30
2

I would say that, when the children know their parents, a widget and all its ancestors form a chain of responsibility. A typical example is a mouse event received by a widget : the widget can either consume the event (and react accordingly), or pass the event to its parent, who can either consume or pass to its parent, etc...

In the case of Qt, each widget is given its parent by constructor, and this indicates that the widget is owned by the parent. In particular, the deletion of the parent triggers the deletion of the widget.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.