LayoutController in the works for special size control

Forum for general chit-chat or off-topic discussion.

Moderators: CEGUI MVP, CEGUI Team

User avatar
paddy
Not too shy to talk
Not too shy to talk
Posts: 30
Joined: Wed Jan 12, 2005 12:06

LayoutController in the works for special size control

Postby paddy » Sat Dec 25, 2004 07:47

I've been working on a couple classes that make it easy to bind the size of one window to that of another.
I've tested it out with binding a tab control's right edge to the left edge of another panel and tied that's right edge to the right edge of the parent window, so the panel has a fixed width but hugs the right edge and sizes dynamically to the height of the window. Its defined in the window setup with code like:

Code: Select all

   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"test",(utf8*)"Stardawn/Shipbuilder/Tabs",LayoutController::RIGHT_EDGE,(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::LEFT_EDGE,-10.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"test",(utf8*)"Stardawn/Shipbuilder/Tabs",LayoutController::BOTTOM_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-10.0f);

...

   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"test",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::RIGHT_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::WIDTH,-10.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"test",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::LEFT_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::WIDTH,-110.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"test",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::BOTTOM_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-10.0f);


In short, you use an 'addBinding' method to tie one edge, corner, width or height of one window/component to one edge, corner, width or height of another, with a padding parameter, and when the window resizes, it updates the bound components appropriately.

I've seen some posts about people wanting this general functionality, what I am working on isn't especially complex but I'll upload it as soon as the last bugs are worked out.

Image

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

LayoutController in the works for special size control

Postby CrazyEddie » Wed Dec 29, 2004 10:16

Sounds cool :)

CE.

User avatar
paddy
Not too shy to talk
Not too shy to talk
Posts: 30
Joined: Wed Jan 12, 2005 12:06

LayoutController in the works for special size control

Postby paddy » Wed Dec 29, 2004 21:18

Okay, I have tested the code and cleaned it a little, the current version can be found at:

LayoutController.h

LayoutController.cpp


The code isn't that super, I only started working with the STL for the first time a day before I started this, and I am pretty much still learning C++. So far it works and has no bugs that I have found, but I haven't tried beating it to death yet.

I have personally only tried this with ogre projects.

If you want to try it out, it defines a few classes:

CEGUI::LayoutBinding
CEGUI::LayoutBindingSet
CEGUI::LayoutController


First, you need an instance of LayoutController in your project, and to setup the layout of your windows as normal in absolute metrics.

Then, bind 'Window::EventSized' for the windows you want to control with it, I used the code

Code: Select all

   WindowManager::getSingleton().getWindow((utf8*)"Stardawn/Shipbuilder")->
      subscribeEvent(Window::EventSized, boost::bind(&ShipBuilderApplication::handleWindowResize, this, _1));

...

bool    ShipBuilderApplication::handleWindowResize(const CEGUI::EventArgs& e) {
   using namespace CEGUI;
   layoutController->updateLayout((utf8*)"Stardawn/Shipbuilder");
   return true;
}



The method "updateLayout()" takes the parent window name being resized as a parameter, to optimize which windows get resized. You can also call it without a parameter to update all parent windows tracked by bindings in the LayoutController.

To add the actual sizing bindings for the layout, you need to tell the LayoutController what to track and how to resize the windows.



Code: Select all

   
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"tabs/right",(utf8*)"Stardawn/Shipbuilder/Tabs",LayoutController::RIGHT_EDGE,(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::LEFT_EDGE,-10.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"tabs/bottom",(utf8*)"Stardawn/Shipbuilder/Tabs",LayoutController::BOTTOM_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-50.0f);

   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"panel/right",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::RIGHT_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::WIDTH,-10.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"panel/left",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::LEFT_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::WIDTH,-210.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"panel/bottom",(utf8*)"Stardawn/Shipbuilder/Panel",LayoutController::BOTTOM_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-50.0f);
   

   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"output/right",(utf8*)"Stardawn/Shipbuilder/TextOutput",LayoutController::RIGHT_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::WIDTH,-10.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"output/top",(utf8*)"Stardawn/Shipbuilder/TextOutput",LayoutController::TOP_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-50.0f);
   layoutController->addBinding((utf8*)"Stardawn/Shipbuilder",(utf8*)"output/bottom",(utf8*)"Stardawn/Shipbuilder/TextOutput",LayoutController::BOTTOM_EDGE,(utf8*)"Stardawn/Shipbuilder",LayoutController::HEIGHT,-10.0f);




In this case, "Stardawn/Shipbuilder" is the parent window, and it is referenced for its width and height to be able to align windows to hug the right and bottom edges. The corner values however would be relative to it's parent - not these children windows, so we can't use those. Relative to the children, the top left would be 0,0 and the lower right x,y is WIDTH,HEIGHT anyway, so we don't loose any functionality.

The first binding binds the right edge of the window named "tabs" to the left edge of the window called "panel" with a space of 10 pixels.

The second binds the tabs' height to be the same as the parent window, but spaced 50 pixels from the actual bottom.

The next two bind the window "Panel" to have it's right edge and left edge be 10 and 210 pixels distance less than the width of the parent, so it hugs the right edge and is always 200 pixels wide.

Since all bindings treat the corner or edge changes as "resize" requests and not "move" requests moving the right or left edge will always change the width, so you need to move the opposite edge by the same amount to keep the width constant.

Next one binds the height to hug the bottom to within 50 pixels, same as the tabs.

Last three bindings bind the static text field 'TextOutput" to hug the bottom with a 40 pixel height and stretch out to a width of 10 pixels less than the parent window.

Any point on any of these windows, such as the Tabs' x,y or the panel's top edge, never are bound since they never need to move for this layout to resize.

The result of those bindings above look like this in my app:



Image

edit: the menu bar in that pic is not bound at all since it never needs to move or change with the resizing of the window. Also, while it looks like the tabs and panel move vertically they both have fixed y locs, but the tab's panel area is dawn below the relative height of the tab buttons as part of that widget's internal code.

side note: if you don't layout your windows exactly right manually beforehand, they don't look right until the parent window is resized, I call updateLayout() twice in my setup and pushes things around for me and makes them work.

Also, if you bind things 'badly' you can have widgets wander right off the window. Bindings are processed in the order they are placed so you can build heirarchies that are dependant on the results of a binding above it in the list, but if you bind to a window that gets update later in the list, the value you bind to will be based on the last resize.

I am not sure how good the code is - I haven't written much C++ - but it works for me so far. I could use to put in exceptions and such for binding name conflicts but I haven't written my own exceptions before in c++ and such, so I am still figuring some of the stuff out as I go. I hope its useful and I'll fix any problems that are pointed out.

Thanks :)

edit: url link [tags] fixed

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

LayoutController in the works for special size control

Postby CrazyEddie » Sun Jan 02, 2005 11:28

Okay cool.

I'll try and find the time to have a play around with this in the near future :)

User avatar
paddy
Not too shy to talk
Not too shy to talk
Posts: 30
Joined: Wed Jan 12, 2005 12:06

Re: LayoutController in the works for special size control

Postby paddy » Sun Jan 16, 2005 04:14

Sorry, that was me, didn't see I wasn't logged in

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: LayoutController in the works for special size control

Postby CrazyEddie » Sun Jan 16, 2005 07:34

Cool. Thanks for the update :)

CE.


Return to “Offtopic Discussion”

Who is online

Users browsing this forum: No registered users and 2 guests