-
Notifications
You must be signed in to change notification settings - Fork 31
Gui layout
nuiContainer is the top class for creating a layout. Using a container, you can organize the widgets, catch the mouse and keyboard events, implement a drag’n drop behavior, …
You should never use nuiContainer directly, but nuiSimpleContainer instead, which is the the simplest class designed for this purpose.
void MainWindow::OnCreation()
{
nuiSimpleContainer* pMyCont = new nuiSimpleContainer();
AddChild(pMyCont);
// create a simple button with a text inside
nuiButton* myButton = new nuiButton(_T("push me"));
// the button will be centered and will have the smallest size it needs to display the text
myButton->SetPosition(nuiCenter);
pMyCont->AddChild(myButton);
}
You can add children the way you would add layers in a graphic software like Photoshop:
nuiButton* pButton = new nuiButton(_T("first"));
pButton->SetPosition(nuiTop);
pMyCont->AddChild(pButton);
pButton = new nuiButton(_T("second"));
pButton->SetPosition(nuiBottom);
pMyCont->AddChild(pButton);
You can use a grid to organize the widgets:
nuiGrid* pGrid = new nuiGrid(2,2);
nuiButton* pButton = new nuiButton(_T("1"));
// put the button in the first column, first row
pGrid->SetCell(0,0, pButton, nuiCenter);
[...]
If you need a single dimension grid, use a vertical box or horizontal box instead. nuiHBox, nuiVBox and nuiGrid have the same API.
nuiHBox* pBox = new nuiHBox(2);
pBox->SetCell(0, new nuiButton(_T("1")));
pBox->SetCell(1, new nuiButton(_T("2")));
Another way to build the grid is to keep everything dynamic:
nuiHBox* pBox = new nuiHBox(0);
pBox->AddCell(new nuiButton(_T("1")));
pBox->AddCell(new nuiButton(_T("2")));
You can tell a cell to expand and follow the size of its father, during the runtime:
nuiVBox* pBox = new nuiVBox(2);
// means the box expands horizontally
pBox->SetExpand(nuiExpandShrinkAndGrow); // default value is nuiExpandFixed
pBox->SetCell(0, pMyWidget1);
pBox->SetCell(1, pMyWidget2);
pBox->SetCellExpand(1, nuiExpandShrinkAndGrow); // cell 0 won't resize, cell 1 will resize according to its father
In some cases you will need to achieve pixel accurate widget positioning, for example to place your widgets over an image provided by a graphic artist. In this case automatic layout can’t help you and you have to define each widget rectangle by hand.
The container to use in that case is nuiFixed. Here is how to use it to put a button at position (10, 10) with a size of (120, 30):
nuiFixed* pFixed = new nuiFixed();
nuiButton* pButton = new nuiButton(_T("Some text for the button"));
pButton->SetUserRect(nuiRect(10, 10, 120, 30));
pFixed->AddChild(pButton);
nuiFixed always honor the ideal rectangle of its children, thus using SetUserRect on the children to override their ideal rectangle calculation.
Use a nuiSplitter to let the user change the size of a cell.
nuiSplitter* pSplitter = new nuiSplitter(nuiHorizontal);
AddChild(pSplitter);
nuiSimpleContainer* pCell1 = new nuiSimpleContainer();
nuiSimpleContainer* pCell2 = new nuiSimpleContainer();
pSplitter->SetMasterChild(false);
pSplitter->AddChild(pCell1);
pSplitter->AddChild(pCell2);
// if you need to know when the splitter bar is moved
mEventSink.Connect(pSplitter->HandleMoved, &MyClass::OnSplitterMoved, (void*)pSplitter);
[...]
bool MyClass::OnSplitterMoved(const nuiEvent& rEvent)
{
// get the splitter pointer from the user parameter
nuiSplitter* pSplitter = (nuiSplitter*)rEvent.mpUser;
nuiSize pos = pSplitter->GetHandlePos;
// maybe you want this value registered in the app's preferences?
}
to be continued…