|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2005 by Ken Werner *
|
|
|
|
* ken.werner@web.de *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
#include "flowlayout.h"
|
|
|
|
#include "sources/source.h"
|
|
|
|
|
|
|
|
//#include "kdebug.h"
|
|
|
|
//#include <tqlabel.h> // debugging
|
|
|
|
|
|
|
|
class FlowLayoutIterator :public TQGLayoutIterator{
|
|
|
|
public:
|
|
|
|
FlowLayoutIterator( TQPtrList<TQLayoutItem>* layoutItems ):
|
|
|
|
index(0),
|
|
|
|
mLayoutItems(layoutItems){
|
|
|
|
}
|
|
|
|
uint count() const;
|
|
|
|
TQLayoutItem* current();
|
|
|
|
TQLayoutItem* next();
|
|
|
|
TQLayoutItem* takeCurrent();
|
|
|
|
private:
|
|
|
|
int index;
|
|
|
|
TQPtrList<TQLayoutItem>* mLayoutItems;
|
|
|
|
};
|
|
|
|
TQLayoutItem* FlowLayoutIterator::current(){
|
|
|
|
return index < int(mLayoutItems->count()) ? mLayoutItems->at(index) : 0;
|
|
|
|
/*if(index < int(mLayoutItems->count())){
|
|
|
|
TQLayoutItem* item = mLayoutItems->at(index);
|
|
|
|
kdDebug() << "FlowLayoutIterator::current(index " << index << ") returns: " << item << endl;
|
|
|
|
return item;
|
|
|
|
}else{
|
|
|
|
kdDebug() << "FlowLayoutIterator::current(index " << index << ") returns: NULL" << endl;
|
|
|
|
return 0;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
TQLayoutItem* FlowLayoutIterator::next(){
|
|
|
|
index++;
|
|
|
|
//kdDebug() << "FlowLayoutIterator::next, index: " << index << endl;
|
|
|
|
return current();
|
|
|
|
}
|
|
|
|
TQLayoutItem* FlowLayoutIterator::takeCurrent(){
|
|
|
|
return index < int(mLayoutItems->count()) ? mLayoutItems->take(index) : 0;
|
|
|
|
/*if(index < int(mLayoutItems->count())){
|
|
|
|
TQLayoutItem* item = mLayoutItems->take(index);
|
|
|
|
kdDebug() << "FlowLayoutIterator::takeCurrent(index " << index << ") returns: " << item << endl;
|
|
|
|
return item;
|
|
|
|
}else{
|
|
|
|
kdDebug() << "FlowLayoutIterator::takeCurrent(index " << index << ") returns: NULL" << endl;
|
|
|
|
return 0;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FlowLayout::FlowLayout( TQWidget* parent, Qt::Orientation orientation, int border, int space, const char* name )
|
|
|
|
: TQLayout( parent, border, space, name ),
|
|
|
|
mOrientation(orientation), mLastItem(NULL){
|
|
|
|
}
|
|
|
|
FlowLayout::FlowLayout( TQLayout* parent, Qt::Orientation orientation, int space, const char* name )
|
|
|
|
: TQLayout( parent, space, name ),
|
|
|
|
mOrientation(orientation), mLastItem(NULL){
|
|
|
|
}
|
|
|
|
FlowLayout::FlowLayout( Qt::Orientation orientation, int space, const char* name )
|
|
|
|
: TQLayout( space, name ),
|
|
|
|
mOrientation(orientation), mLastItem(NULL){
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FlowLayout::~FlowLayout(){
|
|
|
|
deleteAllItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
int FlowLayout::heightForWidth( int w ) const{
|
|
|
|
FlowLayout* mthis = (FlowLayout*)this;
|
|
|
|
int h = mthis->doLayout( TQRect(0,0,w,0), TRUE );
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
int FlowLayout::widthForHeight( int h ) const{
|
|
|
|
FlowLayout* mthis = (FlowLayout*)this;
|
|
|
|
int w = mthis->doLayout( TQRect(0,0,0,h), TRUE );
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::addItem(TQLayoutItem* item){
|
|
|
|
//kdDebug() << "FlowLayout::addItem: " << (static_cast<TQLabel*>(item->widget()))->text() << ", width: " << item->widget()->width() << ", height: " << item->widget()->height()<< endl;
|
|
|
|
// we are indirectly called from addSource. this
|
|
|
|
// is a hint for addSource, to let it know which item
|
|
|
|
// was added.
|
|
|
|
mLastItem = TQT_TQLAYOUTITEM(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::addSource(Source* src){
|
|
|
|
add(src->getWidget());
|
|
|
|
mSources[mLastItem] = src;
|
|
|
|
src->getWidget()->show();
|
|
|
|
|
|
|
|
// step back until we find an item which has a
|
|
|
|
// smaller position stored in its config. then, we found
|
|
|
|
// the right position for the new item.
|
|
|
|
TQLayoutItem * qli = mLayoutItems.last();
|
|
|
|
while(qli && mSources[qli]->getPosition() > src->getPosition())
|
|
|
|
qli = mLayoutItems.prev();
|
|
|
|
mLayoutItems.insert(mLayoutItems.at()+1, mLastItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::remove(TQWidget* widget){
|
|
|
|
//kdDebug() << "FlowLayout::remove: " << (static_cast<TQLabel*>(widget))->text() << endl;
|
|
|
|
widget->hide();
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
while(it.current() != NULL) {
|
|
|
|
if(it.current()->widget() == widget) {
|
|
|
|
mSources.erase(it.current());
|
|
|
|
mLayoutItems.remove(it.current());
|
|
|
|
// removes and deletes only the TQLayoutItem
|
|
|
|
// (TQWidgetItem)
|
|
|
|
TQLayout::remove(widget);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint FlowLayout::count(){
|
|
|
|
return mLayoutItems.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FlowLayout::moveItem(const TQLayoutItem* which, const TQLayoutItem* relate, DIRECTION direction){
|
|
|
|
int newPos = mLayoutItems.findRef(relate);
|
|
|
|
int oldPos = mLayoutItems.findRef(which);
|
|
|
|
|
|
|
|
// check whether the widget is already at a correct position
|
|
|
|
if(oldPos+1 == newPos && direction == ABOVE || oldPos-1 == newPos && direction == BELOW)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove the item
|
|
|
|
mLayoutItems.remove(which);
|
|
|
|
if(oldPos < newPos)
|
|
|
|
newPos--;
|
|
|
|
|
|
|
|
newPos += direction;
|
|
|
|
// actually reinsert the item
|
|
|
|
mLayoutItems.insert(newPos, which);
|
|
|
|
activate(); // relayout
|
|
|
|
// kdDebug() << "oldPos: " << oldPos << ", newPos: " << newPos << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::updatePositions(TDEConfig * inTDEConfig){
|
|
|
|
//kdDebug() << "updating all positions..." << endl;
|
|
|
|
int pos = 0;
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
while(it.current() != NULL) {
|
|
|
|
mSources[it.current()]->setPosition(pos, inTDEConfig);
|
|
|
|
++it;
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
//kdDebug() << "positions updated!" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FlowLayout::hasHeightForWidth() const{
|
|
|
|
return mOrientation != Qt::Horizontal;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FlowLayout::hasWidthForHeight() const{
|
|
|
|
return mOrientation == Qt::Horizontal;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSize FlowLayout::sizeHint() const{
|
|
|
|
//return minimumSize();
|
|
|
|
TQSize size(0,0);
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
TQLayoutItem *o;
|
|
|
|
while((o=it.current()) != 0){
|
|
|
|
++it;
|
|
|
|
size = size.expandedTo( o->sizeHint() );
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSize FlowLayout::minimumSize() const{
|
|
|
|
TQSize size(0,0);
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
TQLayoutItem *o;
|
|
|
|
while((o=it.current()) != 0){
|
|
|
|
++it;
|
|
|
|
size = size.expandedTo(o->minimumSize());
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSizePolicy::ExpandData FlowLayout::expanding() const{
|
|
|
|
return TQSizePolicy::NoDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQLayoutIterator FlowLayout::iterator(){
|
|
|
|
return TQLayoutIterator(new FlowLayoutIterator(&mLayoutItems));
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::Orientation FlowLayout::getOrientation() const{
|
|
|
|
return mOrientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::setOrientation(Qt::Orientation orientation){
|
|
|
|
mOrientation = orientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlowLayout::setGeometry( const TQRect& rect ){
|
|
|
|
TQLayout::setGeometry( rect );
|
|
|
|
doLayout( rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
int FlowLayout::doLayout( const TQRect& rect, bool testonly ){
|
|
|
|
if(mOrientation == Qt::Horizontal)
|
|
|
|
return doLayoutHorizontal(rect, testonly);
|
|
|
|
else
|
|
|
|
return doLayoutVertical(rect, testonly);
|
|
|
|
}
|
|
|
|
|
|
|
|
int FlowLayout::doLayoutHorizontal( const TQRect& rect, bool testOnly ){
|
|
|
|
//kdDebug() << "spacing: " << spacing() << endl;
|
|
|
|
|
|
|
|
int x = rect.x();
|
|
|
|
int y = rect.y();
|
|
|
|
int width = 0; // width of this column so far
|
|
|
|
int height = 0; // height of this column so far
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
TQLayoutItem* layoutItem;
|
|
|
|
TQPtrList<TQLayoutItem> column; // stores the items of one column
|
|
|
|
while((layoutItem = it.current()) != 0){
|
|
|
|
++it;
|
|
|
|
//int nextY = y + layoutItem->sizeHint().height() + spacing(); // next y
|
|
|
|
int nextY = y + layoutItem->sizeHint().height(); // next y
|
|
|
|
//if( nextY - spacing() > rect.bottom() && width > 0 ) {
|
|
|
|
if( nextY > rect.bottom() && width > 0 ) {
|
|
|
|
// next column
|
|
|
|
y = rect.y(); // reset y
|
|
|
|
x = x + width + spacing(); // new x
|
|
|
|
//nextY = y + layoutItem->sizeHint().height() + spacing(); // next y with changed y
|
|
|
|
nextY = y + layoutItem->sizeHint().height(); // next y with changed y
|
|
|
|
width = 0; // reset width for the next column
|
|
|
|
}
|
|
|
|
if(!testOnly){
|
|
|
|
layoutItem->setGeometry( TQRect( TQPoint( x, y ), layoutItem->sizeHint() ) );
|
|
|
|
column.append(layoutItem);
|
|
|
|
height += layoutItem->sizeHint().height(); // add the height of the current item to the column height
|
|
|
|
if( it.current() == 0 || nextY + it.current()->sizeHint().height() > rect.bottom() ){ // test it it's the last item (of this column)
|
|
|
|
// calculate real needed width
|
|
|
|
int rWidth = 0;
|
|
|
|
for(TQLayoutItem* item = column.first(); item; item = column.next()){
|
|
|
|
rWidth = TQMAX( rWidth, item->widget()->sizeHint().width() );
|
|
|
|
}
|
|
|
|
// relayout the items of the former column
|
|
|
|
int space = (rect.height() - height) / (column.count() + 1);
|
|
|
|
int i = 0; // counts the items of this column
|
|
|
|
for(TQLayoutItem* item = column.first(); item; item = column.next()){
|
|
|
|
TQRect r = item->geometry();
|
|
|
|
item->setGeometry( TQRect(r.left(), r.top() + ((++i) * space), rWidth, r.height()) );
|
|
|
|
}
|
|
|
|
column.clear(); // remove the items of the former column
|
|
|
|
height = 0; // reset height for the next column
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y = nextY;
|
|
|
|
width = TQMAX( width, layoutItem->sizeHint().width() );
|
|
|
|
}
|
|
|
|
return x + width - rect.x(); // width
|
|
|
|
}
|
|
|
|
|
|
|
|
int FlowLayout::doLayoutVertical( const TQRect& rect, bool testOnly ){
|
|
|
|
int x = rect.x();
|
|
|
|
int y = rect.y();
|
|
|
|
int height = 0; // height of this line so far
|
|
|
|
TQPtrListIterator<TQLayoutItem> it(mLayoutItems);
|
|
|
|
TQLayoutItem* layoutItem;
|
|
|
|
while((layoutItem = it.current() ) != 0){
|
|
|
|
++it;
|
|
|
|
//int nextX = x + layoutItem->sizeHint().width() + spacing();
|
|
|
|
int nextX = x + layoutItem->sizeHint().width();
|
|
|
|
if(nextX - spacing() > rect.right() && height > 0) {
|
|
|
|
// next line
|
|
|
|
x = rect.x(); // reset x
|
|
|
|
//y = y + height + spacing(); // new y
|
|
|
|
y = y + height; // new y
|
|
|
|
//nextX = x + layoutItem->sizeHint().width() + spacing(); // next x
|
|
|
|
nextX = x + layoutItem->sizeHint().width(); // next x
|
|
|
|
height = 0; // reset height for the next line
|
|
|
|
}
|
|
|
|
const int itemHeight = layoutItem->sizeHint().height();
|
|
|
|
if(!testOnly)
|
|
|
|
layoutItem->setGeometry(TQRect(x, y, rect.right(), itemHeight));
|
|
|
|
x = nextX;
|
|
|
|
height = TQMAX(height, itemHeight);
|
|
|
|
}
|
|
|
|
return y + height - rect.y(); // height
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "flowlayout.moc"
|