Jump to content
  • Advertisement
Sign in to follow this  
Ivorne

Designing UI library - positioning items in containers

This topic is 876 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I am not trying to write whole new UI library, I use existing library, but I just want my own code to control positions of objects. I have one exact question, but I would apperciate any advices on how this can / is / should be done. I am familiar with multiple ui libraries, but I want to make sure that I am not forgetting anything.

 

Basic idea of my approach to UI composition is that there are <basic items> (buttons, images, and such) and <containers>. A <container> can contain multiple instances of both <containers> and <basic items>. Each item should propagate some informations about its preferred size to its parent. After this information propagates to the top level, each container will reize its children properly, dividing its size between those children. This way the UI should adapt to size changes nicely.

 

The thing I am not sure about is what exactly should be this information about required size of an item, that propagates to parent containers. I see two optons:

    a) vec2 required_size_min, vec2 required_size_max

    b) vec2 preferred_size

 

I initialy chose the first option (gtk has it like this I think), but then I realize, that:

    - I might not be able to satisfy these requirements all the time

    - required_size_max is too often 'infinity'

 

So currently I am leaning towards the second option (have just preferred_size), but I am afraid that I might run in another problems in the future.

 

Any advices?

Thx :-)

 

 

Share this post


Link to post
Share on other sites
Advertisement

It's been a while since I wrote my own UI library, but here's my opinion.  Take it with a grain of salt:

 

Preferred size/min/max

I am not in favor of preferred size, min, or max.  I think this pollutes the logic.  Consider two child items side by side, both with preferred size of 100.  Container is resized to 150, what is the size of each child item?  If your answer is 75, then why bother with preferred size at all?  Why have a parameter at all only to be ignored?

 

Instead, each child should be responsible in its own proper rendering and logic in any size.  By any size, I mean even down to 1x1 pixel.  No minimum size, no maximum size.  You have a button, that button better works even when its 1x1.  You have a radio button, it better works at 1x1.

 

You can enforce minimum size at the container level, but child item (which cannot contain another child) should be able to handle any size.  Object positioning should be handled by the container, and any items should not dictate to its container how it should be positioned, neither preferred, min, nor max.

 

The reason why is that I have worked on some custom UI library that follows this Java's swing approach, and it has these preferred size, min, and max etc, and they dictate the way the container align and position its children.  It's hard to resolve conflicts at the container level if the child items can dictate to its container how to position itself.  One child say my min is 100, another say my min is 150, and container is resized to 200, which one should you resize?

 

It gets worse if child items are engineered with these preferred, min and max in mind, that certain logic starts to fail when the size goes beyond or lower than these arbitrary thresholds.  "Since my size won't ever go lower than 100, right?, so I'll draw this 5x5 important UI element at exactly the 95th pixel"  Guess what, your width is now 80, and that important UI element is now gone.  Great.

 

So, no min, max, or preferred at all.  As a matter of fact, maybe let the container tells its children their size.

Share this post


Link to post
Share on other sites

I wrote a gui system where I started with min-size (ie the smallest size possible that you need to draw yourself) propagation bottom up, together with resizing (either some step size, or "not really"). This gives you smallest possible size at the top, which you push down, taking resize steps into account. It also may mean that some not really resizable widgets do get more room, as one of their neighbours require it.

This gives you smallest consistent size, as small as possible, but no holes on the window. (To illustrate, imagine a label "A" and a label "AA". The latter is longer in minimal size. If you put them under each other in one container, the "A" one needs to extend to match the "AA" label width, or you have a hole in the window.)

 

From here you probably want resizing, which all widgets also use a stepsize or 'no thanks' for,

This also propagates up, but 'no thanks' now limits resizing of the neighbours.

Edited by Alberth

Share this post


Link to post
Share on other sites

Thx for answers.

However, the way I see it is: we have two items with preferred sizes 100 and 150. Container has size 300 -> real sizes of items are 100 and 150 and then there is 50 px of empty space. Then container gets resized to 200 px -> first item will get 100 px and second 100 px (the last one gets cropped). Or I will use scrolling view, which will give both of them what they want.

Then I might have containers with capacity for one item only, that will try to expand the item to a fixed size. And I think that i might need a way to tell this container, which size will be too big. Then i will need a way to align the item inside the bigger container. Or i will just resize it to the full size of the container.

Share this post


Link to post
Share on other sites
However, the way I see it is: we have two items with preferred sizes 100 and 150. Container has size 300

I solved container size by defining it as "all its children fit exactly in it".

 

 

Edit: Also, just skip a single horizontal row or a single vertical column container. Only do the generalized grid container, and you get the former two for free.

I didn't do span, as I didn't seem to need it, and it complicates the system a lot.

Edited by Alberth

Share this post


Link to post
Share on other sites

It can get very complicated once you add row and column views and anchoring.  If a child is set to ANCHOR_BOTTOM (its Y position is fixed to the bottom of its container, spanning to the container's full width), how does min/max/preferred play into this?  If a child's max width is set to 100 and ANCHOR_BOTTOM, then the container is resized to 1000, shall it respect ANCHOR_BOTTOM or child's max?  What if two or more children are ANCHOR_BOTTOM, the another ANCHOR_RIGHT, placed into another container that has row/column views?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!