Objective Toolkit : Chapter 23 Layout Manager Framework : Layout Manager Examples
Layout Manager Examples
The following examples demonstrate integration of the Layout Manager. For more information, see the Layout demo provided with Objective Toolkit. All examples assume you have added the layout factory to your class header, as described in “Adding Layout Management to Your Applications.”The code in the examples is to be inserted in the appropriate initialization handler (OnCreate(), OnInitDialog(), OnInitialUpdate()).
Scale Layout in a Dialog
 
// Create top-level layout node
SECLNScale* pScaleNode=(SECLNScale *) m_LayoutFactory.CreateNode(
NODE_CLASS(SECLNScale));
 
// Optional: configure the top level layout node’s minimum
// and maximum size. This means the dialog will never get
// smaller than 150x225 or larger than 900x600
pScaleNode->SetMinMaxSize(CSize(150,225),CSize(900,600),0);
 
// This useful factory function can iterate through all child
// windows of this dialog, creating an SECLayoutNodeWnd for each,
// and linking as children of the pScaleNode object.
m_LayoutFactory.AutoPopulateNodeWnd(pScaleNode,this);
 
// create and attach the listener. If we didn’t use the listener,
// we would have to manually catch WM_SIZE and WM_GETMINMAXINFO and
// kick off the Layout Manager as needed. It is highly recommended
// that you use the listener, but if you can’t, there is an
// alternate solution. You should check out the
// SECLayoutNodeWndListner message handlers and duplicate the
// code as needed.
SECLayoutWndListener* pListener =
m_LayoutFactory.CreateLayoutWndListener();
pListener->AutoInit(pScaleNode,this);
Relative Layout in a Dialog
// Create the top-level relative layout node
SECLNRelative* pRelNode=(SECLNRelative *)
m_LayoutFactory.CreateNode(NODE_CLASS(SECLNRelative));
 
// Say we have 2 buttons, create 1 window node for each.
// Set relative layout node as the parent.
SECLayoutNodeWnd* pNode = m_LayoutFactory.CreateNodeWnd(
IDC_BUTTON1,this,pRelNode);
SECLayoutNodeWnd* pNode2 =
m_LayoutFactory.CreateNodeWnd(
IDC_BUTTON2,this,pRelNode);
 
// Set the constraints, see documentation on relative layout
// for more information
pRelNode->SetConstraint(pNode1,REL_MOVER,pRelNode,REL_RIGHT,-20);
pRelNode->SetConstraint(pNode2,REL_MOVET,pNode1,REL_BOTTOM,10);
 
// Set the window listener
SECLayoutWndListener* pListener =
m_LayoutFactory.CreateLayoutWndListener();
pListener->AutoInit(pScaleNode,this);
Grid Layout, Alignment Layout and Splitter in a Formview
 
// Link layout in OnInitialUpdate, not OnCreate, as
// child dialog controls must exist for proper attachment
 
// Manually populate the children - we are not using
// autopopulate here since we want to better customize
// the layout configuration.
 
// Layout will be a simple 2x1 grid, with the bottom grid
// cell occupied by a splitter "sublayout". Note that if
// zero is passed as one of the 2 grid dimensions, grid
// will autogrow specified direction.
SECLNGrid* pGrid = (SECLNGrid *) m_LayoutFactory.CreateNode(
NODE_CLASS(SECLNGrid));
pGrid->SetGridDimensions(0,1); // n rows by 1 column
 
// Add a simple text message in top grid cell
// Use an alignment node to center the text inside the grid.
SECLNAlign* pAlign = (SECLNAlign *) m_LayoutFactory.CreateNode(
NODE_CLASS(SECLNAlign));
SECLayoutNode* pNode = m_LayoutFactory.CreateNodeWnd(
IDC_STATIC1,this);
 
// the alignment node controls the static window node
pAlign->AddLayoutNode(pNode);
pAlign->SetAlignment(SECLAYOUT_ALIGN_CENTER_HORZ |
SECLAYOUT_ALIGN_CENTER_VERT);
 
// first grid cell, row 0, col 0
pGrid->AddLayoutNode(pAlign);
 
// Add the splitter node to the bottom grid cell.
// The splitter node will in turn have 3 window node
// children (2 buttons and a MLE)
SECLayoutNodeSplitter* pSplitNode = (SECLayoutNodeSplitter *)
m_LayoutFactory.CreateNode(
NODE_CLASS(SECLayoutNodeSplitter));
pSplitNode->Create(this);
pSplitNode->SetSplitterFlags(SEC_SPLITTER_REALTIME_DRAG);
pGrid->AddLayoutNode(pSplitNode); // 2nd grid cell, row 1, col 0
 
// Set the 2 push buttons from the dialog template as separate
// splitter children
pNode=m_LayoutFactory.CreateNodeWnd(IDC_BUTTON1,this);
pSplitNode->AddPane(0,0,pNode); // splitter pane row 0, col 0
pNode=m_LayoutFactory.CreateNodeWnd(IDC_BUTTON2,this);
pSplitNode->AddPane(1,0,pNode); // splitter pane row 1, col 0
pNode=m_LayoutFactory.CreateNodeWnd(IDC_EDIT1,this);
pSplitNode->AddPane(0,1,pNode); // splitter pane row 0, col 1
 
// link a layout listener for auto-sizing
SECLayoutWndListener* pListener=m_LayoutFactory.CreateLayoutWndListener();
pListener->AutoInit(pGrid,this);
NOTE >> Both SECLNScale and SECLNGrid are derived from a common class—SECLayoutNode.
To specify min/max sizes for layout nodes
Call the SetMinMaxSize() method on the node. For example:
 
// the dialog will never get smaller than 150x225
// or larger than 900x600
pScaleNode->SetMinMaxSize(CSize(150,225),CSize(900,600),0);
To implement a custom layout manager
1. Derive a class from SECLayoutNode.
2. Override the OnRecalcLayout() method. A node’s parent calls this method whenever a size/position recalculation is required.
3. In your override, reposition your custom node’s children as you see fit, issuing a call to RecalcLayout() on each node. Any of the provided layout algorithms can be used as a model for this customization.