Page 1 of 2

Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 4:07 am
by hua
Hi guys,

Is it possible to have 2 rows of BUTTONBAR? If it is, any code snippet to see how it's done?

TIA

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 4:22 am
by nageswaragunupudi
PROMPT "First" + CRLF + "Second" displays the prompt in two lines.
PROMPT "First Second" also displays the prompt in two lines if the button width can not display the entire prompt in single line and breaks the prompt at the space.

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 4:50 am
by hua
Thanks for the prompt reply Rao.

I wasn't referring to the prompts but BUTTONBAR itself because in one of my program the number of buttons are quite a lot. So I need to split some of them onto the next row, if it's possible.

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 5:42 pm
by James Bott
Hua,

Yes, it is possible to have more than one toolbar. Take a look at fwh\samples\rebars.prg for an example. This shows two toolbars and one of them is actually a tabbed toolbar containing two more toolbars on tabs. Note that this uses the windows control, rebar, to create toolbars, not FW's own buttonbar control so there will be some learning curve.

You may also want to look at the Ribbonbar class. See fwh\samples\ribbon.prg for an example. This one is much more complex however there is a ribbonbar designer program in FWH\samples\rbdesign.prg.

Regards,
James

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 9:42 pm
by Enrico Maria Giordano
Hua,
hua wrote:Hi guys,

Is it possible to have 2 rows of BUTTONBAR? If it is, any code snippet to see how it's done?

TIA
Here it is a working sample:

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    LOCAL oBar

    DEFINE WINDOW oWnd

    DEFINE BUTTONBAR OF oWnd 2007;
           SIZE 33, 33

    DEFINE BUTTON OF oWnd:oBar;
           FILE "C:\FWH\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "First bar Ok!" );
           TOOLTIP "This is a test"

    @ 33, -1 BUTTONBAR oBar OF oWnd;
             SIZE 1602, 36;
             BUTTONSIZE 60, 33

    oBar:l2007 = .T.

    DEFINE BUTTON OF oBar;
           FILE "C:\FWH\BITMAPS\SAVE.BMP";
           ACTION MSGINFO( "Second bar Ok!" )

    ACTIVATE WINDOW oWnd

    RETURN NIL
EMG

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Mon Oct 21, 2013 10:58 pm
by cnavarro
Also, a ButtonBar inside another ButtonBar

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    LOCAL oBar1, oBar2, oBar3, oBar4

    DEFINE WINDOW oWnd

    DEFINE BUTTONBAR OF oWnd 2007;
           SIZE 61, 136

    DEFINE BUTTON OF oWnd:oBar;
           FILE "C:\FWH\BITMAPS\identify.BMP";
           ACTION MSGINFO( "First bar Ok!" );
           TOOLTIP "This is a test"
    // 33
    @ -1, 62 BUTTONBAR oBar1 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33

    oBar1:l2007 = .T.

    DEFINE BUTTON OF oBar1;
           FILE "C:\FWH\BITMAPS\SAVE.BMP";
           ACTION MSGINFO( "Second bar Ok!" )

    @ 34, 62 BUTTONBAR oBar2 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33

    oBar2:l2007 = .T.

    DEFINE BUTTON OF oBar2;
           FILE "C:\FWH\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Tercer bar Ok!" )

    @ 68, 62 BUTTONBAR oBar3 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33

    oBar3:l2007 = .T.

    DEFINE BUTTON OF oBar3;
           FILE "C:\FWH\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Cuarto bar Ok!" )

    @ 102, 62 BUTTONBAR oBar4 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33

    oBar4:l2007 = .T.

    DEFINE BUTTON OF oBar4;
           FILE "C:\FWH\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Tercer bar Ok!" )


    ACTIVATE WINDOW oWnd

    RETURN NIL

 
Image

Sin bordes queda mejor

Borderless is better

Image

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 12:14 am
by James Bott
Enrico,

I have that example in my samples from some time ago. If you put a resizeable control in the client area does it resize correctly? Or, does it get drawn over or below the second buttonbar? I seem to remember this being a problem.

James

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 2:17 am
by hua
Thanks for the reply guys.

@James: Thank you for the hint and suggestion. I'm hoping to be able to still use BUTTONBAR because it's an existing program and I wish to minimize any changes that need to be done. But I'm keeping your suggestion in my ideas note. Thanks

@Enrico: Thank you for the helpful code snippet!

@cnavarro: I didn't even know that kind of thing is possible! Thank you for sharing

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 8:16 am
by Enrico Maria Giordano
James,
James Bott wrote:Enrico,

I have that example in my samples from some time ago. If you put a resizeable control in the client area does it resize correctly?
Don't know, sorry. Never tried. :-)

EMG

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 9:38 am
by cnavarro
hua wrote:Thanks for the reply guys.

@James: Thank you for the hint and suggestion. I'm hoping to be able to still use BUTTONBAR because it's an existing program and I wish to minimize any changes that need to be done. But I'm keeping your suggestion in my ideas note. Thanks

@Enrico: Thank you for the helpful code snippet!

@cnavarro: I didn't even know that kind of thing is possible! Thank you for sharing
Si usted usa mi ejemplo, deberia añadir :

If you use my example, you would add:

Code: Select all

    oWnd:oBar:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar1:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar2:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar3:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar4:bRClicked  := { |nRow, nCol, nFlags| .T. }

  ACTIVATE WINDOW oWnd
 

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 11:43 am
by TecniSoftware
cnavarro wrote:Also, a ButtonBar inside another ButtonBar

Sin bordes queda mejor

Borderless is better

Image
Muy bueno tu ejemplo, no sabia que se podia hacer eso.
Te pregunto, como se hace para que quede sin bordes? tienes razon, queda mucho mejor.

Saludos

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 2:37 pm
by cnavarro
TecniSoftware wrote:
Muy bueno tu ejemplo, no sabia que se podia hacer eso.
Te pregunto, como se hace para que quede sin bordes? tienes razon, queda mucho mejor.

Saludos
Alejandro
Te adjunto el ejemplo junto con la clase que uso (heredada de TBar), con el parametro lBorder
La idea original fue de Francisco
http://forums.fivetechsupport.com/viewt ... ar#p145961

Espero que te sea de utilidad

Code: Select all

#include "Fivewin.ch"

#xcommand @ <nRow>, <nCol> CBUTTONBAR [ <oBar> ] ;
             [ SIZE <nWidth>, <nHeight> ] ;
             [ BUTTONSIZE <nBtnWidth>, <nBtnHeight> ] ;
             [ <_3d: 3D, 3DLOOK, _3DLOOK> ] ;
             [ <mode: TOP, LEFT, RIGHT, BOTTOM, FLOAT> ] ;
             [ <wnd: OF, WINDOW, DIALOG> <oWnd> ] ;
             [ CURSOR <oCursor> ] ;
             [ <lNoBorder: NOBORDER> ] ;
      => ;
         [ <oBar> := ] TBarC():NewAt( <nRow>, <nCol>, <nWidth>, <nHeight>,;
             <nBtnWidth>, <nBtnHeight>, <oWnd>, <._3d.>, [ Upper(<(mode)>) ],;
             <oCursor>, !<.lNoBorder.> )


/*
#xcommand DEFINE CBUTTONBAR [ <oBar> ] ;
             [ <size: SIZE, BUTTONSIZE, SIZEBUTTON > <nWidth>, <nHeight> ] ;
             [ <_3d: _3D, 3D, 3DLOOK, _3DLOOK> ] ;
             [ <mode: TOP, LEFT, RIGHT, BOTTOM, FLOAT> ] ;
             [ <wnd: OF, WINDOW, DIALOG> <oWnd> ] ;
             [ CURSOR <oCursor> ] ;
             [ <l2007: 2007, _2007> ] ;
             [ <l2010: 2010, _2010> ] ;
             [ <lNoBorder: NOBORDER> ] ;
      => ;
         [ <oBar> := ] TBarC():New( <oWnd>, <nWidth>, <nHeight>, <._3d.>,;
             [ Upper(<(mode)>) ], <oCursor>, <.l2007.>, <.l2010.>, !<.lNoBorder.> )

*/

FUNCTION MAIN()

    LOCAL oWnd

    LOCAL oBar1, oBar2, oBar3, oBar4

    DEFINE WINDOW oWnd

    DEFINE BUTTONBAR OF oWnd 2007;
           SIZE 61, 136

    DEFINE BUTTON OF oWnd:oBar;
           FILE "C:\FWH\FWH1308_3\BITMAPS\identify.BMP";
           ACTION MSGINFO( "First bar Ok!" );
           TOOLTIP "This is a test"
    // 33
    @ -1, 62 CBUTTONBAR oBar1 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33 ;
             NOBORDER

    oBar1:l2007 = .T.

    DEFINE BUTTON OF oBar1;
           FILE "C:\FWH\FWH1308_3\BITMAPS\SAVE.BMP";
           ACTION MSGINFO( "Second bar Ok!" )

    @ 34, 62 CBUTTONBAR oBar2 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33 ;
             NOBORDER

    oBar2:l2007 = .T.

    DEFINE BUTTON OF oBar2;
           FILE "C:\FWH\FWH1308_3\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Tercer bar Ok!" )

    @ 68, 62 CBUTTONBAR oBar3 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33 ;
             NOBORDER

    oBar3:l2007 = .T.

    DEFINE BUTTON OF oBar3;
           FILE "C:\FWH\FWH1308_3\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Cuarto bar Ok!" )

    @ 102, 62 CBUTTONBAR oBar4 OF oWnd:oBar;
             SIZE 160, 34;
             BUTTONSIZE 60, 33 ;
             NOBORDER

    oBar4:l2007 = .T.
    
    DEFINE BUTTON OF oBar4;
           FILE "C:\FWH\FWH1308_3\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "Tercer bar Ok!" )

    oWnd:oBar:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar1:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar2:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar3:bRClicked  := { |nRow, nCol, nFlags| .T. }
    oBar4:bRClicked  := { |nRow, nCol, nFlags| .T. }

    ACTIVATE WINDOW oWnd 

    RETURN NIL


//----------------------------------------------------------------------------//

#define BAR_HEIGHT           28
#define GRAY_BRUSH            2

#define BAR_TOP               1
#define BAR_LEFT              2
#define BAR_RIGHT             3
#define BAR_DOWN              4
#define BAR_FLOAT             5

#define SM_CYBORDER           6
#define SM_CYCAPTION          4

#define COLOR_BTNFACE        15
#define COLOR_BTNSHADOW      16
#define COLOR_BTNHIGHLIGHT   20

#define GROUP_SEP            8

//----------------------------------------------------------------------------//

CLASS TBarC FROM TBar

CLASSDATA lRegistered AS LOGICAL
DATA lBorder

METHOD New( oWnd, nBtnWidth, nBtnHeight, l3D, cMode, oCursor, l2007, l2010,;
            lBorder, oBrush, aGrad ) CONSTRUCTOR

METHOD NewAt( nRow, nCol, nWidth, nHeight, nBtnWidth, nBtnHeight, oWnd, l3D,;
              cMode, oCursor, lBorder, oBrush, aGrad ) CONSTRUCTOR

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( oWnd, nBtnWidth, nBtnHeight, l3D, cMode, oCursor, l2007, l2010,;
            lBorder, oBrush, aGrad ) CLASS TBarC

   local oRect

   DEFAULT oWnd := GetWndDefault(), nBtnWidth := BAR_HEIGHT,;
           nBtnHeight := BAR_HEIGHT, l3D := .f., cMode := "TOP", l2007 := .F.,;
           l2010 := .F., lBorder := .F. //, oBrush := Nil, aGrad := {}

   oRect = oWnd:GetCliRect()

   ::nStyle = if( lBorder, nOR( WS_BORDER, WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN ),;
                          nOR( WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN ) )

   ::lBorder     = lBorder
   ::aControls   = {}
   ::nGroups     = 0
   ::oWnd        = oWnd
   ::nTop        = If( cMode == "BOTTOM", oRect:nBottom - nBtnHeight, -1 )
   ::nLeft       = If( cMode == "RIGHT", oRect:nRight - nBtnWidth - ;
                   If( l3D, 3, 0 ), -1 )
   ::nBottom     = If( cMode == "TOP", nBtnHeight, oRect:nBottom + 1 )
   ::nRight      = If( cMode == "TOP" .or. cMode == "BOTTOM",;
                       oRect:nRight,;
                   If( cMode == "LEFT", nBtnWidth + If( l3D, 3, 0 ), oRect:nRight + 1 ) )
   ::nBtnWidth   = nBtnWidth
   ::nBtnHeight  = nBtnHeight
   ::nId         = ::GetNewId()
   ::lDrag       = .f.
   ::lCaptured   = .f.
   ::nClrPane    = If( l3D, GetSysColor( COLOR_BTNFACE ), CLR_GRAY )
   ::lVisible    = .t.
   ::l3D         = l3D
   ::nMode       = AScan( { "TOP", "LEFT", "RIGHT", "BOTTOM", "FLOAT" }, cMode )
   ::oCursor     = oCursor
   ::lValidating = .f.
   ::l2007       = l2007
   ::l2010       = l2010

   ::SetColor( If( ValType( ::nClrText ) == "B", Eval( ::nClrText, .F. ), ::nClrText ), ::nClrPane )

   do case
      case l2007
           ::bClrGrad = { | lInvert | If( ! lInvert,;
                                        { { 0.25, RGB( 219, 230, 244 ), RGB( 207, 221, 239 ) },;
                                          { 0.75, RGB( 201, 217, 237 ), RGB( 231, 242, 255 ) } },;
                                        { { 0.25, RGB( 255, 253, 222 ), RGB( 255, 231, 151 ) }, ;
                                          { 0.75, RGB( 255, 215,  84 ), RGB( 255, 233, 162 ) } } ) }
      case l2010
           ::bClrGrad = { | lInvert | If( ! lInvert,;
                                        { { 1, RGB( 255, 255, 255 ), RGB( 229, 233, 238 ) } },;
                                        { { 2/5, RGB( 255, 253, 222 ), RGB( 255, 231, 147 ) },;
                                          { 3/5, RGB( 255, 215,  86 ), RGB( 255, 231, 153 ) } } ) }
      otherwise
           if Empty( aGrad )
           ::bClrGrad = { | lInvert | If( ! lInvert,;
                                        { { 0.25, RGB( 219, 230, 244 ), RGB( 207, 221, 239 ) },;
                                          { 0.75, RGB( 201, 217, 237 ), RGB( 231, 242, 255 ) } },;
                                        { { 0.25, RGB( 255, 253, 222 ), RGB( 255, 231, 151 ) }, ;
                                          { 0.75, RGB( 255, 215,  84 ), RGB( 255, 233, 162 ) } } ) }
           else
              if Empty( oBrush )
                 ::bClrGrad = { | lInvert | If( ! lInvert,;
                                            { aGrad[1], aGrad[2] } ,;
                                            { aGrad[3], aGrad[4] }  )  }
              else
                 ::SetBrush( oBrush )
              endif
           endif
   endcase

   ::Register( nOR( CS_VREDRAW, CS_HREDRAW ) )
   ::Create()

   do case
      case ::nMode == BAR_TOP
           oWnd:oBar = Self
           oWnd:oTop = Self

      case ::nMode == BAR_LEFT
           oWnd:oLeft = Self

      case ::nMode == BAR_RIGHT
           oWnd:oRight = Self

      case ::nMode == BAR_DOWN
           oWnd:oBottom = Self
   endcase

return Self

//----------------------------------------------------------------------------//

METHOD NewAt( nRow, nCol, nWidth, nHeight, nBtnWidth, nBtnHeight, oWnd, l3D,;
              cMode, oCursor, lBorder, oBrush, aGrad ) CLASS TBarC
   local oRect

   DEFAULT oWnd := GetWndDefault(), nBtnWidth := BAR_HEIGHT,;
           nBtnHeight := BAR_HEIGHT, nHeight := BAR_HEIGHT,;
           l3D := .f., cMode := "TOP", lBorder := .f.    //FranciscoA May, 31/2013

   oRect = oWnd:GetCliRect()

  ::nStyle = if( lBorder, nOR( WS_BORDER, WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN ),;
                          nOR( WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN ) )

   ::lBorder     = lBorder
   ::aControls   = {}
   ::nGroups     = 0
   ::oWnd        = oWnd
   ::nTop        = nRow
   ::nLeft       = nCol
   ::nBottom     = nRow + nHeight - 1
   ::nRight      = nCol + nWidth - 1
   ::nBtnWidth   = nBtnWidth
   ::nBtnHeight  = nBtnHeight
   ::nId         = ::GetNewId()
   ::lDrag       = .f.
   ::lCaptured   = .f.
   ::nClrPane    = If( l3D, GetSysColor( COLOR_BTNFACE ), RGB( 240,240,240) ) //CLR_GRAY )
   ::lVisible    = .t.
   ::l3D         = l3D
   ::nMode       = AScan( { "TOP", "LEFT", "RIGHT", "BOTTOM", "FLOAT" }, cMode )
   ::oCursor     = oCursor
   ::lValidating = .f.
   ::l2007       = .F.
   ::l2010       = .F.

   ::SetColor( If( ValType( ::nClrText ) == "B", Eval( ::nClrText, .F. ), ::nClrText ), ::nClrPane )

   ::bClrGrad = { | lInvert | If( ! lInvert,;
                                  { { 0.25, nRGB( 219, 230, 244 ), nRGB( 207, 221, 239 ) },;
                                    { 0.75, nRGB( 201, 217, 237 ), nRGB( 231, 242, 255 ) } },;
                                  { { 0.25, nRGB( 255, 253, 222 ), nRGB( 255, 231, 151 ) }, ;
                                    { 0.75, nRGB( 255, 215,  84 ), nRGB( 255, 233, 162 ) } } ) }

   ::Register( nOR( CS_VREDRAW, CS_HREDRAW ) )
   ::Create()


return Self

//----------------------------------------------------------------------------//
 

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 22, 2013 2:56 pm
by TecniSoftware
cnavarro wrote:
Alejandro
Te adjunto el ejemplo junto con la clase que uso (heredada de TBar), con el parametro lBorder
La idea original fue de Francisco
http://forums.fivetechsupport.com/viewt ... ar#p145961

Espero que te sea de utilidad
Muchas gracias!!!

Saludos!

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 29, 2013 1:33 pm
by James Bott
As I mentioned in a previous message in this thread, there is a problem using two buttonbars in a window if you are using oWnd:oClient. The oClient control is painted over the second buttonbar. See the example below.

James

Code: Select all

/*
Purpose: Sample showing two buttonbars
and problem with oWnd:oClient control
*/

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    LOCAL oBrw, aData:={}

    LOCAL oBar

    aadd(aData,"100")
    aadd(aData,"200")
    aadd(aData,"300")
    aadd(aData,"400")

    DEFINE WINDOW oWnd

    DEFINE BUTTONBAR OF oWnd 2007;
           SIZE 33, 33

    DEFINE BUTTON OF oWnd:oBar;
           FILE "C:\FWH\BITMAPS\OPEN.BMP";
           ACTION MSGINFO( "First bar Ok!" );
           TOOLTIP "This is a test"

    @ 33, -1 BUTTONBAR oBar OF oWnd;
             SIZE 1602, 36;
             BUTTONSIZE 60, 33

    oBar:l2007 = .T.

    DEFINE BUTTON OF oBar;
           FILE "C:\FWH\BITMAPS\SAVE.BMP";
           ACTION MSGINFO( "Second bar Ok!" )

    @ 0,0 XBROWSE oBrw OF oWnd ARRAY aData

    oBrw:CreateFromCode()

    oWnd:oClient:= oBrw

    ACTIVATE WINDOW oWnd

    RETURN NIL

Re: Is it possible to have 2 rows of BUTTONBAR?

Posted: Tue Oct 29, 2013 2:24 pm
by TecniSoftware
James Bott wrote:As I mentioned in a previous message in this thread, there is a problem using two buttonbars in a window if you are using oWnd:oClient. The oClient control is painted over the second buttonbar. See the example below.

James
James

Use the class TLayout from Daniel Garcia! no need to use oWnd:oClient:oBrw, see sample

Code: Select all

#include "fivewin.ch"


#xcommand DEFINE LAYOUT <oLayout> <of:OF, WINDOW, DIALOG, LAYOUT> <oDlg> ;
    => ;
    <oLayout> := TLayout():new(<oDlg>)

#xcommand DEFINE VERTICAL LAYOUT [<oLayout>] OF <oMainLay> [ SIZE <nSize> ]  ;
    => ;
    [<oLayout> :=] <oMainLay>:addVLayout([<nSize>])

#xcommand DEFINE HORIZONTAL LAYOUT  [<oLayout>] OF <oMainLay> [ SIZE <nSize> ]  ;
    => ;
    [<oLayout> :=] <oMainLay>:addHLayout([<nSize>])

#xcommand SET LAYOUT CONTROL <oControl> OF <oLayout>;
    =>;
    <oLayout>:oClient := <oControl>


function main()

    local oWnd
    local xLay := {=>}
    local oBar1, oBar2
    local oBrw

    USE CUSTOMER NEW SHARED ALIAS "CUST1"

    define window oWnd

    define LAYOUT xLay["main"] of oWnd

    define VERTICAL LAYOUT of xLay["main"] size 32
    define VERTICAL LAYOUT of xLay["main"] size 32


    define buttonbar oBar1 of xLay["main"]:aVLayout[1] size 32,32 2010
    define buttonbar oBar2 of xLay["main"]:aVLayout[2] size 32,32 2007

    DEFINE BUTTON OF oBar1 FILENAME "..\bitmaps\alphabmp\bs_close.bmp"
    DEFINE BUTTON OF oBar2 FILENAME "..\bitmaps\alphabmp\bs_open.bmp"

    DEFINE BUTTON OF oBar1 FILENAME "..\bitmaps\alphabmp\bs_exit.bmp"
    DEFINE BUTTON OF oBar2 FILENAME "..\bitmaps\alphabmp\bs_options.bmp"




    define VERTICAL LAYOUT of xLay["main"]

    @ 0,0 XBROWSE oBrw of xLay["main"]:aVLayout[3] ALIAS "CUST1"
    oBrw:CreateFromCode()
    xLay["main"]:aVLayout[3]:oClient := oBrw

    activate window oWnd

return nil















#define LAYOUT_TYPE_MAIN       0
#define LAYOUT_TYPE_HORIZONTAL 1
#define LAYOUT_TYPE_VERTICAL   2


class TLayout from TPanel

    data bOnResize
    data aHLayout, aVLayout
    data nType
    data nTop, nLeft, nWidth, nHeight
    data lFixed

    data nSumHFix, nHFix, nSumVFix, nVFix HIDDEN

    method new( oWnd )
    method addHLayout()
    method addVLayout()

    method calculeHorizontal( nWidth, nHeight ) HIDDEN
    method calculeVertical( nWidth, nHeight ) HIDDEN

    method onResized( nWidth, nHeight )


endclass


//----------------------------------------------------//

method TLayout:new( oWnd )

    local bOnResize

    ::aHLayout  = {}
    ::aVLayout  = {}

    ::nTop      = 0
    ::nLeft     = 0
    ::nWidth    = 0
    ::nHeight   = 0

    ::lFixed  = .F.
    ::nSumHFix = 0
    ::nHFix    = 0
    ::nSumVFix = 0
    ::nVFix    = 0

    ::nId = ::GetNewId()

    ::bOnResize = oWnd:bResized

    oWnd:bResized = {| nType, nWidth, nHeight | ::onResized( nType, nWidth, nHeight ) }

    if ! oWnd:isKindOf("TLAYOUT")
        ::nType = LAYOUT_TYPE_MAIN
        oWnd:oClient = self
    endif

return ::Super:new(0,0, oWnd:nHeight, oWnd:nWidth, oWnd)

//----------------------------------------------------//

method TLayout:addVLayout( nHeight )

    local oChild

    DEFAULT nHeight := 0

    oChild = TLayout():new( self )

    oChild:nType = LAYOUT_TYPE_VERTICAL
    oChild:lFixed = nHeight > 0
    oChild:nHeight = nHeight

    if oChild:lFixed
        ::nSumVFix++
        ::nVFix += nHeight
    endif

    aadd( ::aVLayout, oChild )

return oChild

//----------------------------------------------------//

method TLayout:addHLayout( nWidth )

    local oChild

    DEFAULT nWidth := 0

    oChild = TLayout():new( self )

    oChild:nType = LAYOUT_TYPE_HORIZONTAL
    oChild:lFixed = nWidth > 0
    oChild:nWidth = nWidth

    if oChild:lFixed
        ::nSumHFix++
        ::nHFix += nWidth
    endif

    aadd( ::aHLayout, oChild )

return oChild

//----------------------------------------------------//

method TLayout:calculeVertical( nWidth, nHeight )
    local nLen
    local nNewHeight
    local nAuxHeight, nCalcHeight
    local nItem, nCountNotFixed := 0
    local nTop, nLeft
    local oItem
    local nAcum := 0

    nLen = Len( ::oWnd:aVLayout )
    nCalcHeight := ( nHeight - ::oWnd:nVFix ) / Max( 1, ( nLen - ::oWnd:nSumVFix ) )
    nNewHeight = nCalcHeight
    nTop = 0
    nLeft = 0
    for nItem = 1 to nLen
        oItem = ::oWnd:aVLayout[ nItem ]
        if oItem:nId == ::nId
            if oItem:lFixed
                nAuxHeight = nNewHeight
                nNewHeight = oItem:nHeight
            else
                nCountNotFixed++
                nNewHeight = Round( nCalcHeight * nCountNotFixed, 0 ) - nAcum
                nAuxHeight = nNewHeight
            endif
            ::Move( nTop, nLeft, nWidth, nNewHeight )
            nNewHeight = nAuxHeight
            exit
        else
            if oItem:lFixed
                nTop += oItem:nHeight
            else
                nCountNotFixed++
                nNewHeight = Round( nCalcHeight * nCountNotFixed, 0 ) - nAcum
                nAcum += nNewHeight
                nTop += nNewHeight
            endif
        endif
    next
return nil

//----------------------------------------------------//

method TLayout:calculeHorizontal( nWidth, nHeight )
    local nLen
    local nNewWidth
    local nAuxWidth, nCalcWidth
    local nItem, nCountNotFixed := 0
    local nTop, nLeft
    local oItem
    local nAcum := 0

    nLen = Len( ::oWnd:aHLayout )
    nCalcWidth := ( nWidth - ::oWnd:nHFix ) / Max( 1, ( nLen - ::oWnd:nSumHFix ) )
    nNewWidth = nCalcWidth
    nTop = 0
    nLeft = 0
    for nItem = 1 to nLen
        oItem = ::oWnd:aHLayout[ nItem ]
        if oItem:nId == ::nId
            if oItem:lFixed
                nAuxWidth = nNewWidth
                nNewWidth = oItem:nWidth
            else
                nCountNotFixed++
                nNewWidth = Round( nCalcWidth * nCountNotFixed, 0 ) - nAcum
                nAuxWidth = nNewWidth
            endif
            ::Move( nTop, nLeft, nNewWidth, nHeight )
            nNewWidth = nAuxWidth
            exit
        else
            if oItem:lFixed
                nLeft += oItem:nWidth
            else
                nCountNotFixed++
                nNewWidth = Round( nCalcWidth * nCountNotFixed, 0 ) - nAcum
                nAcum += nNewWidth
                nLeft += nNewWidth
            endif
        endif
    next
return nil

//----------------------------------------------------//

method TLayout:onResized( nType, nWidth, nHeight )
    if ::nType != LAYOUT_TYPE_MAIN
        if ::oWnd:isKindOf( "TLAYOUT" )
            switch ::nType
                case LAYOUT_TYPE_HORIZONTAL
                    ::calculeHorizontal( nWidth, nHeight )
                    exit
                case LAYOUT_TYPE_VERTICAL
                    ::calculeVertical( nWidth, nHeight )
                    exit
            endswitch
        endif
    end

    if ! ( ::bOnResize == NIL )
        Eval( ::bOnResize, nType, nWidth, nHeight )
    endif

return 0


//----------------------------------------------------//
Regards
Alejandro