Layout Manager Tutorial

The use of panels is not imediatly obvious. A panel is a virtual component, that means that is does not display any control on the screen. Its use is that it can automatically position components, this keeps us from making guesses like we did in the Edit Tutorial. The down side is that there is some processing overhead involved. Also there are only three predefined ways to layout components.

Here is our program, it can be found in LayoutManagerSample.cpp:

00001:   #include <WKGL.h>
00002:   
00003:   using namespace wkgl;
00004:   
00005:   BOOL OnButton( Component*, UINT, WPARAM, LPARAM );
00006:   
00007:   LAYOUT_INFO linfo;
00008:   LayoutManager *lm;
00009:   
00010:   WPARAM main()
00011:   {
00012:     Window win( "Test LayoutManager" );
00013:     Button button( "Change Layout", 0, 120 );
00014:     Static s1( "Type some text:", AUTOPOS, AUTOPOS );
00015:     Static s2( "Type some more text:", AUTOPOS, AUTOPOS );
00016:     Edit edit1( AUTOPOS, AUTOPOS, 10 );
00017:     Edit edit2( AUTOPOS, AUTOPOS, 15 );
00018:   
00019:     //Set the information about the layout
00020:     linfo.hgap = 5;
00021:     linfo.vgap = 5;
00022:     linfo.client.top = 0;
00023:     linfo.client.left = 0;
00024:     
00025:     //Create the panel
00026:     lm = new LayoutManager( &win, linfo, FormLayout );
00027:        
00028:     //Add the controls to the panel, order matters
00029:     lm->add( &s1 );    
00030:     lm->add( &edit1 );
00031:     lm->add( &s2 );    
00032:     lm->add( &edit2 ); 
00033:     
00034:     //Add the contols to the window.
00035:     win.add( &s1 );
00036:     win.add( &edit1 );
00037:     win.add( &s2 );
00038:     win.add( &edit2 );   
00039:     win.add( &button );
00040:     
00041:     button.addCallBack( OnButton );
00042:   
00043:     //Layout the components.
00044:     lm->layout();
00045:        
00046:     //Show the window
00047:     win.show();
00048:   
00049:     WPARAM param = win.beginMessageLoop();
00050:   
00051:     //Delete the layout manager
00052:     delete lm;
00053:   
00054:     return param;
00055:   }
00056:   
00057:   BOOL OnButton( Component *com, UINT message, WPARAM wParam, LPARAM lParam )
00058:   {
00059:     static int clicked = 0;
00060:     
00061:     if ( message == BN_CLICKED )
00062:     {
00063:       //Change the layout
00064:       switch ( clicked )
00065:       {
00066:         case 0:
00067:           lm->setLayout( FlowLayoutL ); //Set the layout
00068:           clicked = 1;
00069:           break;
00070:        case 1:
00071:          //The right field may have a bogus value so set it correctly.
00072:          linfo.client.right = ((Control*)com->getParent())->getWidth();
00073:          lm->setLayoutInfo( linfo );   //Set the layout information
00074:          lm->setLayout( FlowLayoutR ); //Set the layout
00075:          clicked = 0;
00076:          break;
00077:       }
00078:   
00079:       //Layout the component.
00080:       lm->layout();
00081:   
00082:       return TRUE;
00083:     }
00084:   
00085:     return FALSE;
00086:   }

When using a layout manager it is important to use AUTOPOS for the x, y parameters if you want the layout manager to layout your components (FormLayout disregards a components x, y preference). The FormLayout positions your components so that the odd numbered ones are on the left and the even ones are on the right. Also the right-hand column is left aligned acording to the size of the largest left-handed component. This layout is basically the layout of allmost every form or dialog box. FlowLayoutL lines all your components up in a left aligned horizontal line. If a components x, or y is set to something other than AUTOPOS then it positions it in its prefered location. FlowLayoutR does the same thing as FlowLayoutL except the components are right aligned. There is one layout that is not mentioned here and that is NoLayout this function does nothing and is used for layout managers that do not want to layout the components.