Page 1 of 2

NEW CLASS TLayout

PostPosted: Sun Sep 22, 2013 6:49 pm
by Daniel Garcia-Gil
Hello,

leave here a new class to build layout inside our windos, allow auto adjust control inside continer, we will can forget @ row, col and control size

to see effect, please resize window

it's a link with 2 samples (exe and sources included)

http://sitasoft.net/fivewin/samples/layout_1.zip

copy the samples inside fivewin samples folder

the source of 1 sample

Code: Select all  Expand view

#include "fivewin.ch"
#include "ribbon.ch"
#include "gif.ch"


function main()
    local oWnd
    local oMainLay
    local hLays := {=>}
    local hButtons := {=>}
    local hBrowses := {=>}
    local oRBar, oFld

    define window oWnd title "testing layout"


    USE CUSTOMER NEW SHARED ALIAS "CUST1"
    USE CUSTOMER NEW SHARED ALIAS "CUST2"

    hLays["MAIN"] = TLayout():new( oWnd )

    hLays["H1"] = hLays["MAIN"]:addHLayout(75)
    hLays["H2"] = hLays["MAIN"]:addHLayout()

    //add 4 layout in H1, will use for 4 buttons
    hLays["H1"]:addVLayout()
    hLays["H1"]:addVLayout()
    hLays["H1"]:addVLayout()
    hLays["H1"]:addVLayout()

    @ 0,0 button hButtons["ONE"] prompt "btn1" of hLays["H1"]:aVLayout[1]
    hLays["H1"]:aVLayout[1]:oClient = hButtons["ONE"]

    @ 0,0 button hButtons["TWO"] prompt "btn2" of hLays["H1"]:aVLayout[2]
    hLays["H1"]:aVLayout[2]:oClient = hButtons["TWO"]

    @ 0,0 button hButtons["THREE"] prompt "btn3" of hLays["H1"]:aVLayout[3]
    hLays["H1"]:aVLayout[3]:oClient = hButtons["THREE"]

    @ 0,0 button hButtons["FOUR"] prompt "btn4" of hLays["H1"]:aVLayout[4]
    hLays["H1"]:aVLayout[4]:oClient = hButtons["FOUR"]

/*
IN THIS POINT THE DISTRIBUTION IS
----------------------------------
|     |                          |
|btn1 |                          |
|-----|                          |
|     |                          |
|btn2 |                          |
|-----|                          |
|     |                          |
|btn3 |                          |
|-----|                          |
|     |                          |
|btn4 |                          |
----------------------------------
->75<-|->REST OF WIDTH         <-|
*/

   
    //add 3 layout in H2, will use for 3 xbrowse
    hLays["H2"]:addVLayout()
    hLays["H2"]:addVLayout()
    hLays["H2"]:addVLayout()


    @ 0,0 XBROWSE hBrowses["ONE"] OF hLays["H2"]:aVLayout[1] ALIAS "CUST1"
    hBrowses["ONE"]:CreateFromCode()
    hLays["H2"]:aVLayout[1]:oClient = hBrowses["ONE"]

   
    @ 0, 0 FOLDEREX oFld PIXEL PROMPT "Gifs", "xbrowse", "layout" of hLays["H2"]:aVLayout[2]
    hLays["H2"]:aVLayout[2]:oClient = oFld

    @ 1,   1 GIF FILE "..\gifs\matrix4.gif" OF oFld:aDialogs[ 1 ]

    @ 0,0 XBROWSE hBrowses["ONE"] OF oFld:aDialogs[2] ALIAS "CUST2"
    hBrowses["ONE"]:CreateFromCode()
    oFld:aDialogs[2]:oClient = hBrowses["ONE"]

    //WORKING INSIDE FOLDERS
    hLays["FOLDER"] = TLayout():new( oFld:aDialogs[3] )

    hLays["FOLDER_H1"] = hLays["FOLDER"]:addHLayout()

    //add 4 layout in FOLDER_H1, will use for 4 buttons
    hLays["FOLDER_H1"]:addVLayout()
    hLays["FOLDER_H1"]:addVLayout()
    hLays["FOLDER_H1"]:addVLayout()
    hLays["FOLDER_H1"]:addVLayout()

    @ 0,0 button hButtons["FOLDER_ONE"] prompt "btn1" of hLays["FOLDER_H1"]:aVLayout[1]
    hLays["FOLDER_H1"]:aVLayout[1]:oClient = hButtons["FOLDER_ONE"]

    @ 0,0 button hButtons["FOLDER_TWO"] prompt "btn2" of hLays["FOLDER_H1"]:aVLayout[2]
    hLays["FOLDER_H1"]:aVLayout[2]:oClient = hButtons["FOLDER_TWO"]

    @ 0,0 button hButtons["FOLDER_THREE"] prompt "btn3" of hLays["FOLDER_H1"]:aVLayout[3]
    hLays["FOLDER_H1"]:aVLayout[3]:oClient = hButtons["FOLDER_THREE"]

    @ 0,0 button hButtons["FOLDER_FOUR"] prompt "btn4" of hLays["FOLDER_H1"]:aVLayout[4]
    hLays["FOLDER_H1"]:aVLayout[4]:oClient = hButtons["FOLDER_FOUR"]




    DEFINE RIBBONBAR oRBar WINDOW  hLays["H2"]:aVLayout[3] PROMPT "One", "Two", "Three" HEIGHT 133 TOPMARGIN 25 2010

/*
IN THIS POINT THE DISTRIBUTION IS
----------------------------------
|     |                          |
|btn1 |                          |
|-----| xbrowse                  |
|     |--------------------------|
|btn2 |                          |
|-----|                          |
|     | folderex                 |
|btn3 |--------------------------|
|-----|                          |
|     |                          |
|btn4 | ribbonbar                |
----------------------------------
->75<-|->REST OF WIDTH         <-|
*/


    activate window oWnd

return nil
 


Code: Select all  Expand view


#include "fivewin.ch"

#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


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

 


Image
Image
Image
Image

Re: NEW CLASS TLayout

PostPosted: Sun Sep 22, 2013 9:07 pm
by nageswaragunupudi
Very Nice and very useful!!!!
Uses are unlimited.

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 1:22 am
by MGA
Thanks :)

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 7:46 am
by Silvio.Falconi
Nice Daniel,
Instead of buttons we can use explorerbar ?
it's possible insert a splitter from a xbrowse to another ? (sample : layout.prg - > from xbrowse and folderex)

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 2:15 pm
by Antonio Linares
Daniel,

You keep being the magician of the numbers (amongst many other areas) :-)

many thanks

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 4:30 pm
by rhlawek
When I compile this I get a persistent unresolved external error for _Max, using VS2012 32 bit and harbour. Adding a dummy function _Max() does not clear the error and at least allow it to link, and adding a function Max() throws a conflict error with a harbour. Any idea how to resolve this?

Compiling...
Harbour 3.2.0dev (r1309161336)
Copyright (c) 1999-2013, http://harbour-project.org/
Compiling 'test_layout.prg' and generating preprocessed output to 'test_layout.p
po'...
Lines 4782, Functions/Procedures 8
Generating C source output to 'test_layout.c'... Done.
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.

test_layout.c
Creating library test_layout.lib and object test_layout.exp
FiveH32.lib(FLDEX.obj) : error LNK2019: unresolved external symbol _Max referenc
ed in function _CalcPos

test_layout.exe : fatal error LNK1120: 1 unresolved externals
* Linking errors *

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 4:39 pm
by Antonio Linares
Robb,

There is a 2nd revision of FWH 13.08 that solves that issue, are you using it ? In FWH web site it is shown and also when you run the FWH setup (fwh.exe)

We have announced it in the forums, but maybe you missed it, thanks

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 4:55 pm
by Antonio Linares
Robb,

Due two little bugs found today, we are going to publish a third revision of FWH 13.08 and we expect to publish it today.

We have been talking (Rao, Daniel, me) about a way to reduce these bugs on new versions, and my opinion is that we need a very complete FWH test app that tests almost every FWH feature, but how to build it ?

Usually we build and test large apps that we have built but they don't test all possibilities in FWH and this is the problem. Even if we stop changing code for some days, if we don't tests all the possibilities, then the bugs will remain there and will reach the users. So for now, the only valid way to asure a bug free version is after some of you build your apps and check that they are fine. Fortunately just a few of us are needed to quickly check this.

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 5:05 pm
by TimStone
Antonio,

Bugs are just part of the process. Sometimes a release needs to go general and be tested across a wide range of systems for all the bugs to be found. Technology is so complex today, I'm not sure any test program can actually evaluate every possible opportunity for bugs.

Tim

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 5:18 pm
by Antonio Linares
Tim,

I fully agree with you. If we adopt a conservative way to get a bug free version, then we will be blocking us for all the new features and enhancements that we are constantly adding to FWH. Anyhow, usually in less than a week we have a real stable version, so it is not so long time to be patient :-)

thanks for the understanding :-)

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 7:07 pm
by TimStone
Antonio,

Its because of the integration between various functions/methods. Sometimes what we do in one area of a program may be used somewhere else and have a different effect. In theory, classes should be self contained, but sometimes changing a class will have a result in how it is implemented elsewhere, like in a sub class. We only find this out when we apply the newly changed class and see a result pop up.

You can't test for this ! We just have to fix it when it occurs.

Tim

Re: NEW CLASS TLayout

PostPosted: Mon Sep 23, 2013 7:20 pm
by Antonio Linares
In this case it was a C function that was similar in C5 and in FWH, so we combined both but there was a little mistake, and because that function was used from different places, the bug spreaded easily.

The lesson is that just a little change in a little C function is enough to break an app... We knew this, but it is quite difficult to protect from it. When it happens, it happens.

Anyhow, we are a great team (ALL OF US), and we have an incredibly reaction speed so a bug remains alive very little time between us :-)

Re: NEW CLASS TLayout

PostPosted: Tue Sep 24, 2013 12:44 am
by rhlawek
Thank you, that addressed the problem and I am able to build the test programs now.

Daniel, I did not mean to be so rude and appear so thankless. This is a wonderful class, practical, useful and educational. Thank you so much for sharing.

Antonio, I understand the testing challenges. Personally I choose to write unit test code for every new class and function I write, not too different than the test utility that is provide with harbour itself. It doesn't catch everything, but it catches a lot. Nothing new ever makes it to my main build machine before it passes on my sandbox machine where I run all the tests. This code was being tested on the sandbox. My test utilities wouldn't have caught this one. As always, thank you for the prompt attention.

Robb

Re: NEW CLASS TLayout

PostPosted: Tue Sep 24, 2013 8:39 am
by lucasdebeltran
Antonio,

You may consider to have a Certification section at Fivetech, where the incomming libs should be tested with a real application before launching the new build to the public.

Also, to create a big application to use as many as controls posible: all classic gets, says, folders, etc, plus ribbon, richedit, xbrowse, report, etc etc.

In this application calls to setresdebug() and checkres should be incorporated to detect remaining objets. I beleive there are one at rpreview.prg, the richedit was fixed?

FiveDbu uses very Little of those controls, so it is not good to test the libs.

But also it is very important to say that bugs are very quicly solved here.

Thank you.

Re: NEW CLASS TLayout

PostPosted: Tue Sep 24, 2013 10:53 am
by Antonio Linares
Lucas,

We are not Microsoft, neither the company where you work at.

Not all the companies are the big and have the resources as the one where you work at :-)

We do our best to provide the tools that we use for building our own apps. If you are not satisfied with us, please consider to use Microsoft tools, etc. there are lots of choices availables.

We pay good care of reasonable suggestions. But they have to be reasonable :-)