Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

BoxPlanner - Simple Layout Algorithm

0.00/5 (No votes)
19 Mar 2009 1  
A layout algorithm for layout controls in a row or column

Introduction

Many Windows applications specify absolute position and absolute sizes when they lay out controls in the parent window. This strategy has some drawbacks: The created windows cannot be resized, changes are difficult and creation of good looking windows is time consuming. 

Another way which is very common in cross platform frameworks (wxWidgets, QT, Java …) is to use layout algorithm. A layout algorithm determines the size and position of its controls based on its policy. Although every control can provide its preferences about its size, position and alignment, the layout algorithm can ignore these preferences if they are against its layout policy. 

Using the Code 

What is a Planner?

A planner implements a layout algorithm. Controls can be added to it with their preferences about their size, position and alignment with the Add method while the SetControl method sets their parent control. The Layout method is used to lay out the controls.

class Planner {
public:
    virtual void Layout() = 0;
    virtual void SetControl(const Control& item) = 0;
    virtual void AddControl(const Control& item,int factor,int style) = 0;
    ...
};

What is BoxPlanner?

A BoxPlanner allows laying out controls in a row or in a column. A BoxPlanner has a main direction: Horizontal (psHorizontal -to lay out controls in a row) and Vertical ( psVertical - to lay out controls in a column). The main direction can be given in the construction or by using SetDirection  method. The other direction will be the secondary direction.

When control is added to the planner – it can specify its factor and style.

  • The factor is a hint to the planner how to size the control in the main direction. If the factor is 0 – its desired size in the main direction will be used. Otherwise, its size in the main direction will be factor unit (factor unit - free space in the main direction divided by the sum of all controls factor). 
  • In the secondary direction, the control can specify that it wants all available space (psGrowAll) or wants use its desired size in the secondary direction and to be aligned to window -- psAlignLeft,psAlignCenter, psAlignRight for horizontal direction or  psAlignTop, psAlignMiddle, psAlignBottom).

Demo for BoxPlanner?

In window creation, we create the controls and add them to BoxPlanner instance:  

LRESULT OnCreate ( LPCREATESTRUCT lpcs ) {
    button1.Create(m_hWnd,CRect(0,0,100,50),_T("button 1"),WS_CHILD | WS_VISIBLE);
    button2.Create(m_hWnd,CRect(0,0,100,40),_T("button 2"),WS_CHILD | WS_VISIBLE);
    button3.Create(m_hWnd,CRect(0,0,100,40),_T("button 3"),WS_CHILD | WS_VISIBLE);
    button4.Create(m_hWnd,CRect(0,0,100,40),_T("button 4"),WS_CHILD | WS_VISIBLE);
    button5.Create(m_hWnd,CRect(0,0,100,50),_T("button 5"),WS_CHILD | WS_VISIBLE);
    
    planner.AddControl(Control(button1.m_hWnd),2,Planner::psAlignLeft );
    planner.AddControl(Control(button2.m_hWnd),2,Planner::psAlignRight );
    planner.AddControl(Control(button3.m_hWnd),5,Planner::psGrowAll );
    planner.AddControl(Spacer(10,10),2,Planner::psGrowAll );
    planner.AddControl(Control(button4.m_hWnd),2,Planner::psGrowAll );
    planner.AddControl(Spacer(10,10),0,Planner::psGrowAll );
    planner.AddControl(Control(button5.m_hWnd),2,Planner::psGrowAll );
    planner.SetControl(Control(m_hWnd));

    SetMsgHandled(false);
    return 0;
}

Now when on size event, we call the Layout method:  

void OnSize(UINT nType, CSize size) {
    planner.Layout();
} 

History

  • 19th March, 2009: Initial post 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here