Sign in to follow this  
jengerer

GUI Layout Management

Recommended Posts

Hey guys,

[b]This post might be a bit winded, but I'd really appreciate if I could get some guidance on this one.[/b]

I've been working on an app/game for a while now, but I keep finding myself having a distaste for how I'm running my GUI framework. The way I have it set up right now is similar to Java Swing, in that I have Components and Containers being the basic classes of the layout, where Containers can have Components within, etc.

The main challenges I'm facing are:

[list=1][*]How to be able to position child components in a layout respective to the parent's position. The way I had it done before was that my Container had an [b]UpdatePosition[/b] virtual function that Container classes would overwrite. I don't like this method much because some containers, such as ones that lay 50+ children out in a grid, can be pretty heavy operations to run each frame.[*]Being able to get the absolute position of the components to do things like checking mouse collision. After doing what I mentioned in #1, I tried using [b]D3DXMATRIX [/b]to transform the world before each container was drawn. That way, if a component was at position (0, 0) relative to its parent, and its parent was at (30, 30), the component would be drawn at (30, 30). However, when it comes to collision detection, I can't simply use these relative positions.[/list]
I was thinking of maybe giving Container a LayoutManager class, which could store the relative position of each child, and then when the container is moved, have it simply add the relative position to the parent's position, but decided to post here and see if maybe I could get some opinions. Anyone done anything similar?

Thanks for getting this far,
Jengerer

Share this post


Link to post
Share on other sites
I can't know what your app is. If it's GUI app, when it needs collision detection?
If we are talking about GUI layout, I found the concept "sizer" in wxWidgets is quite good and easy to use.
With the very simple basic sizers, such as box sizer (layout in a row or in a column), grid sizer, flexible grid sizer, you can give the container any layout by composite the sizers.
But with the sizer concept, all positions are relative, so maybe not good for collision detection.

Share this post


Link to post
Share on other sites
Layouting 2D objects is not that different from layouting 3D objects, and hence most if nor all of the same strategies can be used. E.g. define a global/view placement to be the transformation of an element. This transformation is usually a position/orientation/scale w.r.t. the view space. When an element is bound to a container, it is done by using a 2nd transformation that describes how the element is related to its container. When the layout of a root element is computed, then the layout parameters directly define the global/view transformation. When the layout of a dependent element is computed, then the layout parameters define the relational transformation which needs to be concatenated with the container's global/view transformation to yield in the own global/view transformation.

This builds up a classic dependency tree: The layout of an element can be updated if and only if the layout of its container (if any) is already up-to-date, and the element can itself be a container. Hence all the typical strategies can be used: Sorting the elements into dependency order, concentrating all updates in a sub-system for efficiency (if possible), using "dirty" tags and propagation to avoid working on unchanged layout, ... Especially the last point may be of interest for issue 1: Only those element(s) that need to be updated are processed. If nothing has changed, than only the root elements (perhaps only 1) are started but they terminate the update immediately.

The 2nd issue is a typical collision detection problem. With the up-to-date global/view transformation at hand, the element's bounding box can be transformed. This can efficiently be done by the same sub-system as above. After transforming the mouse position into the same space, it can iteratively (from "leaves to root", so to say) be compared with the bounding boxes, until an element declares the mouse event for being processed.

Share this post


Link to post
Share on other sites
[quote name='wqking' timestamp='1306303976' post='4815463']I can't know what your app is. If it's GUI app, when it needs collision detection?[/quote]
I mentioned in the OP that the collision detection I was referring to was with the mouse, sorry if that wasn't clear from my wall of text. :)

[quote name='haegarr' timestamp='1306308146' post='4815478']The 2nd issue is a typical collision detection problem. With the up-to-date global/view transformation at hand, the element's bounding box can be transformed. This can efficiently be done by the same sub-system as above. After transforming the mouse position into the same space, it can iteratively (from "leaves to root", so to say) be compared with the bounding boxes, until an element declares the mouse event for being processed.[/quote]
I considered a similar solution after I implemented the world transformation before drawing (so that each child would be drawn relative to the parent), but I didn't really like that each child class of container that handled mouse events would have to manually transform the position before iterating on its children. I mean, it would likely be done by a helper function, but it would still need to be called manually for each child component because their positions relative to the parent would be different.

What do you think of the possible solution I posted at the end of my post? To clarify what I meant, each container would have a layout manager, and when you add objects to the container, it stores the relative positions of all its children, and then if you need to move that parent, it'll simply iterate through the children and add the stored relative positions so that all positions are absolute, but the relative positions remain intact. I mean, I think a matrix multiplication for each texture/object is more expensive than doing two additions for each object, and only when the parent object is moved. Plus, it makes mouse event handling easier because all component positions are absolute.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this