You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tderadio/plugins/gui-quickbar/buttonflowlayout.cpp

233 lines
5.9 KiB

/****************************************************************************
** $Id: buttonflowtqlayout.cpp 272 2005-05-18 08:12:51Z emw $
**
** Implementing your own layout: flow example
**
** Copyright (C) 1996 by Trolltech AS. All rights reserved.
**
** This file is part of an example program for TQt. This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/
/**
Modified 2002 by Klas Kalass (klas.kalass@gmx.de) for tderadio
*/
#include <kdebug.h>
#include "buttonflowlayout.h"
/*********************************************/
/* Iterator */
class ButtonFlowLayoutIterator :public TQGLayoutIterator
{
public:
ButtonFlowLayoutIterator( TQPtrList<TQLayoutItem> *l ) :idx(0), list(l) {}
uint count() const;
TQLayoutItem *current();
TQLayoutItem *next();
TQLayoutItem *takeCurrent();
private:
int idx;
TQPtrList<TQLayoutItem> *list;
};
uint ButtonFlowLayoutIterator::count() const
{
return list->count();
}
TQLayoutItem *ButtonFlowLayoutIterator::current()
{
return idx < int(count()) ? list->at(idx) : 0;
}
TQLayoutItem *ButtonFlowLayoutIterator::next()
{
idx++; return current();
}
TQLayoutItem *ButtonFlowLayoutIterator::takeCurrent()
{
return idx < int(count()) ? list->take( idx ) : 0;
}
/**************************************************************/
ButtonFlowLayout::ButtonFlowLayout( TQWidget *parent, int margin, int spacing,
const char *name )
: TQLayout( parent, margin, spacing, name ),
cached_width(0)
{
}
ButtonFlowLayout::ButtonFlowLayout( TQLayout* parentLayout, int spacing, const char *name )
: TQLayout( parentLayout, spacing, name ),
cached_width(0)
{
}
ButtonFlowLayout::ButtonFlowLayout( int spacing, const char *name )
: TQLayout( spacing, name ),
cached_width(0)
{
}
ButtonFlowLayout::~ButtonFlowLayout()
{
deleteAllItems();
}
int ButtonFlowLayout::heightForWidth( int w ) const
{
if ( cached_width != w ) {
//Not all C++ compilers support "mutable" yet:
ButtonFlowLayout * mthis = (ButtonFlowLayout*)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 ButtonFlowLayout::addItem( TQLayoutItem *item)
{
list.append( item );
}
bool ButtonFlowLayout::hasHeightForWidth() const
{
return TRUE;
}
TQSize ButtonFlowLayout::sizeHint() const
{
return minimumSize();
}
TQSizePolicy::ExpandData ButtonFlowLayout::expanding() const
{
return TQSizePolicy::NoDirection;
}
TQLayoutIterator ButtonFlowLayout::iterator()
{
return TQLayoutIterator( new ButtonFlowLayoutIterator( &list ) );
}
void ButtonFlowLayout::setGeometry( const TQRect &r )
{
TQLayout::setGeometry( r );
doLayout( r );
}
int ButtonFlowLayout::doLayout( const TQRect &r, bool testonly )
{
/* kdDebug() << "buttonflowlayout::doLayout ("
<< r.x() << "," << r.y() << ","
<< r.width() << "," << r.height() << ", " << testonly << ")\n";
*/
float x = r.x();
float y = r.y();
int h = 0; //height of this line so far.
float buttonWidth = 0;
int buttonHeight = 0;
int linecount = 0;
int totalWidth = r.width();
int totalHeight = r.height();
TQPtrListIterator<TQLayoutItem> it(list);
TQLayoutItem *o;
// get the width of the biggest Button
it.toFirst();
while ( (o=it.current()) != 0 ) {
++it;
buttonWidth = TQMAX( buttonWidth, o->sizeHint().width() );
buttonHeight = TQMAX( buttonHeight, o->sizeHint().height() );
}
// calculate the optimal width
unsigned int columns = (totalWidth + spacing()) /
((int)buttonWidth + spacing());
if (columns > it.count() ) columns = it.count();
if (columns == 0) columns = 1; // avoid division by zero
int rows = (it.count() - 1) / columns + 1;
float deltaH = (float)(totalHeight - rows * buttonHeight - (rows - 1) * spacing())
/ (float)(rows + 1) ;
if (deltaH < 0) deltaH = 0;
y += deltaH;
buttonWidth = (float)(totalWidth - spacing()*(columns-1)) / (float)columns;
/* fprintf (stderr, "cols = %i col-width = %f\n"
"rows = %i row-height = %i\n"
"w = %i h = %i\n",
columns, buttonWidth,
rows, buttonHeight,
totalWidth, totalHeight
);
*/
// calculate the positions and sizes
it.toFirst();
while ( (o = it.current()) != 0 ) {
// fprintf (stderr, "x = %i y = %i\n", x, (int)y);
++it;
int btnRight = (int)rint(x + buttonWidth) - 1,
btnLeft = (int)rint(x);
if ( btnRight > r.right() && h > 0 ) {
x = r.x();
btnRight = (int)rint(x + buttonWidth) - 1;
btnLeft = (int)rint(x);
y += h + spacing() + deltaH;
h = 0;
linecount++;
}
if (!testonly)
o->setGeometry( TQRect( TQPoint( btnLeft, (int)rint(y) ),
TQSize( btnRight - btnLeft + 1,
buttonHeight) )
);
x += buttonWidth + spacing();
h = TQMAX( h, buttonHeight );
}
int ret = (int)rint(y + h + deltaH) - r.y();
// kdDebug() << "ButtonFlowLayout::doLayout() = " << ret << endl;
return ret;
}
TQSize ButtonFlowLayout::minimumSize() const
{
return minimumSize(geometry().size());
}
TQSize ButtonFlowLayout::minimumSize(const TQSize &r) const
{
TQSize s(0, 0);
for (TQPtrListIterator<TQLayoutItem> it(list); it.current(); ++it) {
TQLayoutItem *o = it.current();
s = s.expandedTo( o->sizeHint()); //minimumSize() );
}
s.setHeight(heightForWidth(r.width()));
return s;
}