Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

Customized Layoutmanager

This examples demonstrates how to write customized layout (geometry) managers like card layouts, border layout and flow layouts.

See also: Documentation of Geometry Management.


Header file of the flow layout:

/****************************************************************************
** $Id: qt/flow.h   3.3.8   edited Jan 11 14:46 $
**
** Definition of simple flow layout for custom layout example
**
** Created : 979899
**
** Copyright (C) 1997-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#ifndef FLOW_H
#define FLOW_H

#include <qlayout.h>
#include <qptrlist.h>

class SimpleFlow : public TQLayout
{
public:
    SimpleFlow( TQWidget *parent, int border=0, int space=-1,
                const char *name=0 )
        : TQLayout( parent, border, space, name ),
        cached_width(0) {}
    SimpleFlow( TQLayout* parent, int space=-1, const char *name=0 )
        : TQLayout( parent, space, name ),
        cached_width(0) {}
    SimpleFlow( int space=-1, const char *name=0 )
        : TQLayout( space, name ),
        cached_width(0) {}

    ~SimpleFlow();

    void addItem( TQLayoutItem *item);
    bool hasHeightForWidth() const;
    int heightForWidth( int ) const;
    TQSize sizeHint() const;
    TQSize minimumSize() const;
    TQLayoutIterator iterator();
    TQSizePolicy::ExpandData expanding() const;

protected:
    void setGeometry( const TQRect& );

private:
    int doLayout( const TQRect&, bool testonly = FALSE );
    TQPtrList<TQLayoutItem> list;
    int cached_width;
    int cached_hfw;

};

#endif


Implementation of the flow layout:

/****************************************************************************
** $Id: qt/flow.cpp   3.3.8   edited Jan 11 14:46 $
**
** Implementing your own layout: flow example
**
** Copyright (C) 1996-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "flow.h"

class SimpleFlowIterator :public TQGLayoutIterator
{
public:
    SimpleFlowIterator( TQPtrList<TQLayoutItem> *l ) :idx(0), list(l)  {}
    uint count() const;
    TQLayoutItem *current();
    TQLayoutItem *next();
    TQLayoutItem *takeCurrent();

private:
    int idx;
    TQPtrList<TQLayoutItem> *list;

};

uint SimpleFlowIterator::count() const
{
    return list->count();
}

TQLayoutItem *SimpleFlowIterator::current()
{
    return idx < int(count()) ? list->at(idx) : 0;
}

TQLayoutItem *SimpleFlowIterator::next()
{
    idx++; return current();
}

TQLayoutItem *SimpleFlowIterator::takeCurrent()
{
    return idx < int(count()) ? list->take( idx ) : 0;
}

SimpleFlow::~SimpleFlow()
{
    deleteAllItems();
}


int SimpleFlow::heightForWidth( int w ) const
{
    if ( cached_width != w ) {
        //Not all C++ compilers support "mutable" yet:
        SimpleFlow * mthis = (SimpleFlow*)this;
        int h = mthis->doLayout( TQRect(0,0,w,0), TRUE );
        mthis->cached_hfw = h;
        mthis->cached_width = w;
        return h;
    }
    return cached_hfw;
}

void SimpleFlow::addItem( TQLayoutItem *item)
{
    list.append( item );
}

bool SimpleFlow::hasHeightForWidth() const
{
    return TRUE;
}

TQSize SimpleFlow::sizeHint() const
{
    return minimumSize();
}

TQSizePolicy::ExpandData SimpleFlow::expanding() const
{
    return TQSizePolicy::NoDirection;
}

TQLayoutIterator SimpleFlow::iterator()
{
    return TQLayoutIterator( new SimpleFlowIterator( &list ) );
}

void SimpleFlow::setGeometry( const TQRect &r )
{
    TQLayout::setGeometry( r );
    doLayout( r );
}

int SimpleFlow::doLayout( const TQRect &r, bool testonly )
{
    int x = r.x();
    int y = r.y();
    int h = 0;          //height of this line so far.
    TQPtrListIterator<TQLayoutItem> it(list);
    TQLayoutItem *o;
    while ( (o=it.current()) != 0 ) {
        ++it;
        int nextX = x + o->sizeHint().width() + spacing();
        if ( nextX - spacing() > r.right() && h > 0 ) {
            x = r.x();
            y = y + h + spacing();
            nextX = x + o->sizeHint().width() + spacing();
            h = 0;
        }
        if ( !testonly )
            o->setGeometry( TQRect( TQPoint( x, y ), o->sizeHint() ) );
        x = nextX;
        h = TQMAX( h,  o->sizeHint().height() );
    }
    return y + h - r.y();
}

TQSize SimpleFlow::minimumSize() const
{
    TQSize s(0,0);
    TQPtrListIterator<TQLayoutItem> it(list);
    TQLayoutItem *o;
    while ( (o=it.current()) != 0 ) {
        ++it;
        s = s.expandedTo( o->minimumSize() );
    }
    return s;
}


Header file of the border layout:

/****************************************************************************
** $Id: qt/border.h   3.3.8   edited Jan 11 14:46 $
**
** Definition of simple flow layout for custom layout example
**
** Created : 979899
**
** Copyright (C) 1997-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#ifndef BORDER_H
#define BORDER_H

#include <qlayout.h>
#include <qptrlist.h>

class BorderWidgetItem : public TQWidgetItem
{
public:
    BorderWidgetItem( TQWidget *w )
        : TQWidgetItem( w )
    {}

    void setGeometry( const TQRect &r )
    { widget()->setGeometry( r ); }

};

class BorderLayout : public TQLayout
{
public:
    enum Position {
        West = 0,
        North,
        South,
        East,
        Center
    };

    struct BorderLayoutStruct
    {
        BorderLayoutStruct( TQLayoutItem *i, Position p ) {
            item = i;
            pos = p;
        }

        TQLayoutItem *item;
        Position pos;
    };

    enum SizeType {
        Minimum = 0,
        SizeHint
    };

    BorderLayout( TQWidget *parent, int border = 0, int autoBorder = -1,
                  const char *name = 0 )
        : TQLayout( parent, border, autoBorder, name ), cached( 0, 0 ), mcached( 0, 0 ),
          sizeDirty( TRUE ), msizeDirty( TRUE )
    {}

    BorderLayout( TQLayout* parent, int autoBorder = -1, const char *name = 0 )
        : TQLayout( parent, autoBorder, name  ), cached( 0, 0 ), mcached( 0, 0 ),
          sizeDirty( TRUE ), msizeDirty( TRUE )
    {}

    BorderLayout( int autoBorder = -1, const char *name = 0 )
        : TQLayout( autoBorder, name ), cached( 0, 0 ), mcached( 0, 0 ),
          sizeDirty( TRUE ), msizeDirty( TRUE )
    {}

    ~BorderLayout();

    void addItem( TQLayoutItem *item );

    void addWidget( TQWidget *widget, Position pos );
    void add( TQLayoutItem *item, Position pos );

    bool hasHeightForWidth() const;

    TQSize sizeHint() const;
    TQSize minimumSize() const;

    TQLayoutIterator iterator();

    TQSizePolicy::ExpandData expanding() const;

protected:
    void setGeometry( const TQRect &rect );

private:
    void doLayout( const TQRect &rect, bool testonly = FALSE );
    void calcSize( SizeType st );

    TQPtrList<BorderLayoutStruct> list;
    TQSize cached, mcached;
    bool sizeDirty, msizeDirty;

};

#endif


Implementation of the border layout:

/****************************************************************************
** $Id: qt/border.cpp   3.3.8   edited Jan 11 14:46 $
**
** Implementing your own layout: flow example
**
** Copyright (C) 1996-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "border.h"

class BorderLayoutIterator : public TQGLayoutIterator
{
public:
    BorderLayoutIterator( const TQPtrList<BorderLayout::BorderLayoutStruct> *l )
        : idx( 0 ) , list( (TQPtrList<BorderLayout::BorderLayoutStruct>*)l )
    {}

    uint count() const;
    TQLayoutItem *current();
    BorderLayout::BorderLayoutStruct *currentStruct();
    void toFirst();
    TQLayoutItem *next();
    TQLayoutItem *takeCurrent();
    BorderLayoutIterator &operator++();

private:
    int idx;
    TQPtrList<BorderLayout::BorderLayoutStruct> *list;

};

uint BorderLayoutIterator::count() const
{
    return list->count();
}

TQLayoutItem *BorderLayoutIterator::current()
{
    return idx < (int)count() ? list->at( idx )->item : 0;
}

BorderLayout::BorderLayoutStruct *BorderLayoutIterator::currentStruct()
{
    return idx < (int)count() ? list->at( idx ) : 0;
}

void BorderLayoutIterator::toFirst()
{
    idx = 0;
}

TQLayoutItem *BorderLayoutIterator::next()
{
    idx++;
    return current();
}

TQLayoutItem *BorderLayoutIterator::takeCurrent()
{
    BorderLayout::BorderLayoutStruct *b
        = idx < int( list->count() ) ? list->take(  idx  ) : 0;
    TQLayoutItem *item =  b ? b->item : 0;
    delete b;
    return item;
}

BorderLayoutIterator &BorderLayoutIterator::operator++()
{
    next();
    return *this;
}

BorderLayout::~BorderLayout()
{
    deleteAllItems();
}


void BorderLayout::addItem( TQLayoutItem *item )
{
    add( item, West );
}

void BorderLayout::addWidget( TQWidget *widget, Position pos )
{
    add( new BorderWidgetItem( widget ), pos );
}

void BorderLayout::add( TQLayoutItem *item, Position pos )
{
    list.append( new BorderLayoutStruct( item, pos ) );
    sizeDirty = TRUE; msizeDirty = TRUE;
    calcSize( SizeHint ); calcSize( Minimum );
}

bool BorderLayout::hasHeightForWidth() const
{
    return FALSE;
}

TQSize BorderLayout::sizeHint() const
{
    return cached;
}

TQSize BorderLayout::minimumSize() const
{
    return cached;
}

TQSizePolicy::ExpandData BorderLayout::expanding() const

{
    return TQSizePolicy::BothDirections;
}

TQLayoutIterator BorderLayout::iterator()
{
    return TQLayoutIterator( new BorderLayoutIterator( &list ) );
}

void BorderLayout::setGeometry( const TQRect &rct )
{
    TQLayout::setGeometry( rct );
    doLayout( rct );
}

void BorderLayout::doLayout( const TQRect &rct, bool /*testonly*/ )
{
    int ew = 0, ww = 0, nh = 0, sh = 0;
    int h = 0;

    BorderLayoutIterator it( &list );
    BorderLayoutStruct *o;
    BorderLayoutStruct *center = 0;
    while ( ( o = it.currentStruct() ) != 0 ) {
        ++it;

        if ( o->pos == North ) {
            o->item->setGeometry( TQRect( rct.x(), nh, rct.width(), o->item->sizeHint().height() ) );
            nh += o->item->geometry().height() + spacing();
        }
        if ( o->pos == South ) {
            o->item->setGeometry( TQRect( o->item->geometry().x(), o->item->geometry().y(),
                                         rct.width(), o->item->sizeHint().height() ) );
            sh += o->item->geometry().height() + spacing();
            o->item->setGeometry( TQRect( rct.x(), rct.y() + rct.height() - sh + spacing(),
                                         o->item->geometry().width(), o->item->geometry().height() ) );
        }
        if ( o->pos == Center )
            center = o;
    }

    h = rct.height() - nh - sh;

    it.toFirst();
    while ( ( o = it.currentStruct() ) != 0 ) {
        ++it;

        if ( o->pos == West ) {
            o->item->setGeometry( TQRect( rct.x() + ww, nh, o->item->sizeHint().width(), h ) );
            ww += o->item->geometry().width() + spacing();
        }
        if ( o->pos == East ) {
            o->item->setGeometry( TQRect( o->item->geometry().x(), o->item->geometry().y(),
                                         o->item->sizeHint().width(), h ) );
            ew += o->item->geometry().width() + spacing();
            o->item->setGeometry( TQRect( rct.x() + rct.width() - ew + spacing(), nh,
                                         o->item->geometry().width(), o->item->geometry().height() ) );
        }
    }

    if ( center )
        center->item->setGeometry( TQRect( ww, nh, rct.width() - ew - ww, h ) );
}

void BorderLayout::calcSize( SizeType st )
{
    if ( ( st == Minimum && !msizeDirty ) ||
         ( st == SizeHint && !sizeDirty ) )
        return;

    int w = 0, h = 0;

    BorderLayoutIterator it( &list );
    BorderLayoutStruct *o;
    while ( ( o = it.currentStruct() ) != 0 ) {
        ++it;
        if ( o->pos == North ||
             o->pos == South ) {
            if ( st == Minimum )
                h += o->item->minimumSize().height();
            else
                h += o->item->sizeHint().height();
        }
        else if ( o->pos == West ||
                  o->pos == East ) {
            if ( st == Minimum )
                w += o->item->minimumSize().width();
            else
                w += o->item->sizeHint().width();
        } else {
            if ( st == Minimum ) {
                h += o->item->minimumSize().height();
                w += o->item->minimumSize().width();
            }
            else {
                h += o->item->sizeHint().height();
                w += o->item->sizeHint().width();
            }
        }
    }

    if ( st == Minimum ) {
        msizeDirty = FALSE;
        mcached = TQSize( w, h );
    } else {
        sizeDirty = FALSE;
        cached = TQSize( w, h );
    }

    return;
}


Header file of the card layout:

/****************************************************************************
** $Id: qt/card.h   3.3.8   edited Jan 11 14:46 $
**
** Definition of simple flow layout for custom layout example
**
** Created : 979899
**
** Copyright (C) 1997-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#ifndef CARD_H
#define CARD_H

#include <qlayout.h>
#include <qptrlist.h>

class CardLayout : public TQLayout
{
public:
    CardLayout( TQWidget *parent, int dist )
        : TQLayout( parent, 0, dist ) {}
    CardLayout( TQLayout* parent, int dist)
        : TQLayout( parent, dist ) {}
    CardLayout( int dist )
        : TQLayout( dist ) {}
    ~CardLayout();

    void addItem( TQLayoutItem *item );
    TQSize sizeHint() const;
    TQSize minimumSize() const;
    TQLayoutIterator iterator();
    void setGeometry( const TQRect &rect );

private:
    TQPtrList<TQLayoutItem> list;

};

#endif


Implementation of the card layout:

/****************************************************************************
** $Id: qt/card.cpp   3.3.8   edited Jan 11 14:46 $
**
** Implementing your own layout: flow example
**
** Copyright (C) 1996-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "card.h"

class CardLayoutIterator :public TQGLayoutIterator
{
public:
    CardLayoutIterator( TQPtrList<TQLayoutItem> *l )
        : idx( 0 ), list( l )  {}

    TQLayoutItem *current();
    TQLayoutItem *next();
    TQLayoutItem *takeCurrent();

private:
    int idx;
    TQPtrList<TQLayoutItem> *list;
};

TQLayoutItem *CardLayoutIterator::current()
{
    return idx < int( list->count() ) ? list->at( idx ) : 0;
}

TQLayoutItem *CardLayoutIterator::next()
{
    idx++; return current();
}

TQLayoutItem *CardLayoutIterator::takeCurrent()
{
    return idx < int( list->count() ) ?list->take( idx ) : 0;
}



TQLayoutIterator CardLayout::iterator()
{
    return TQLayoutIterator(  new CardLayoutIterator( &list )  );
}

CardLayout::~CardLayout()
{
    deleteAllItems();
}

void CardLayout::addItem(  TQLayoutItem *item  )
{
    list.append( item );
}

void CardLayout::setGeometry( const TQRect &rct )
{
    TQLayout::setGeometry( rct );

    TQPtrListIterator<TQLayoutItem> it( list );
    if ( it.count() == 0 )
        return;

    TQLayoutItem *o;

    int i = 0;

    int w = rct.width() - ( list.count() - 1 ) * spacing();
    int h = rct.height() - ( list.count() - 1 ) * spacing();

    while ( ( o=it.current() ) != 0 ) {
        ++it;
        TQRect geom( rct.x() + i * spacing(), rct.y() + i * spacing(),
                    w, h  );
        o->setGeometry(  geom  );
        ++i;
    }
}

TQSize CardLayout::sizeHint() const
{
    TQSize s(0,0);
    int n = list.count();
    if ( n > 0 )
        s = TQSize(100,70); //start with a nice default size
    TQPtrListIterator<TQLayoutItem> it(list);
    TQLayoutItem *o;
    while ( (o=it.current()) != 0 ) {
        ++it;
        s = s.expandedTo( o->minimumSize() );
    }
    return s + n*TQSize(spacing(),spacing());
}

TQSize CardLayout::minimumSize() const
{
    TQSize s(0,0);
    int n = list.count();
    TQPtrListIterator<TQLayoutItem> it(list);
    TQLayoutItem *o;
    while ( (o=it.current()) != 0 ) {
        ++it;
        s = s.expandedTo( o->minimumSize() );
    }
    return s + n*TQSize(spacing(),spacing());
}


Main:

/****************************************************************************
** $Id: qt/main.cpp   3.3.8   edited Jan 11 14:46 $
**
** Main for custom layout example
**
** Copyright (C) 1996-2007 Trolltech ASA.  All rights reserved.
**
** This file is part of an example program for TQt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "flow.h"
#include "border.h"
#include "card.h"

#include <qapplication.h>
#include <qlabel.h>
#include <qcolor.h>
#include <qgroupbox.h>
#include <qpushbutton.h>
#include <qmultilineedit.h>
#include <qcolor.h>

int main( int argc, char **argv )
{
    TQApplication a( argc, argv );

    TQWidget *f = new TQWidget;
    TQBoxLayout *gm = new TQVBoxLayout( f, 5 );

    SimpleFlow *b1 = new SimpleFlow( gm );

    b1->add( new TQPushButton( "Short", f ) );
    b1->add( new TQPushButton( "Longer", f ) );
    b1->add( new TQPushButton( "Different text", f ) );
    b1->add( new TQPushButton( "More text", f ) );
    b1->add( new TQPushButton( "Even longer button text", f ) );
    TQPushButton* qb = new TQPushButton( "Quit", f );
    a.connect( qb, SIGNAL( clicked() ), SLOT( tquit() ) );
    b1->add( qb );

    TQWidget *wid = new TQWidget( f );

    BorderLayout *large = new BorderLayout( wid );
    large->setSpacing( 5 );
    large->addWidget( new TQPushButton( "North", wid ), BorderLayout::North );
    large->addWidget( new TQPushButton( "West", wid ), BorderLayout::West );
    TQMultiLineEdit* m = new TQMultiLineEdit( wid );
    m->setText( "Central\nWidget" );
    large->addWidget( m, BorderLayout::Center );
    TQWidget *east1 = new TQPushButton( "East", wid );
    large->addWidget( east1, BorderLayout::East );
    TQWidget *east2 = new TQPushButton( "East 2", wid );
    large->addWidget( east2 , BorderLayout::East );
    large->addWidget( new TQPushButton( "South", wid ), BorderLayout::South );
    //Left-to-right tab order looks better:
    TQWidget::setTabOrder( east2, east1 );
    gm->addWidget( wid );


    wid = new TQWidget( f );
    CardLayout *card = new CardLayout( wid, 10 );

    TQWidget *crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::red );
    card->add( crd );
    crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::green );
    card->add( crd );
    crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::blue );
    card->add( crd );
    crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::white );
    card->add( crd );
    crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::black );
    card->add( crd );
    crd = new TQWidget( wid );
    crd->setBackgroundColor( TQt::yellow );
    card->add( crd );

    gm->addWidget( wid );

    TQLabel* s = new TQLabel( f );
    s->setText( "outermost box" );
    s->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
    s->setAlignment( TQt::AlignVCenter | TQt::AlignHCenter );
    gm->addWidget( s );
    a.setMainWidget( f );
    f->setCaption("TQt Example - Custom Layout");
    f->show();

    int result = a.exec();
    delete f;
    return result;
}

See also Examples.


Copyright © 2007 TrolltechTrademarks
TQt 3.3.8