/*************************************************************************** * 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 // debugging class FlowLayoutIterator :public TQGLayoutIterator{ public: FlowLayoutIterator( TQPtrList* layoutItems ): index(0), mLayoutItems(layoutItems){ } uint count() const; TQLayoutItem* current(); TQLayoutItem* next(); TQLayoutItem* takeCurrent(); private: int index; TQPtrList* 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(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(widget))->text() << endl; widget->hide(); TQPtrListIterator 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(); // retqlayout // kdDebug() << "oldPos: " << oldPos << ", newPos: " << newPos << endl; return true; } void FlowLayout::updatePositions(KConfig * inKConfig){ //kdDebug() << "updating all positions..." << endl; int pos = 0; TQPtrListIterator it(mLayoutItems); while(it.current() != NULL) { mSources[it.current()]->setPosition(pos, inKConfig); ++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 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 it(mLayoutItems); TQLayoutItem *o; while((o=it.current()) != 0){ ++it; size = size.expandedTo(o->minimumSize()); } return size; } TQSizePolicy::ExpandData FlowLayout::expanding() const{ return TQ_SPNoDirection; } TQLayoutIterator FlowLayout::iterator(){ // [FIXME] #ifdef USE_QT4 #warning [FIXME] ContainerAreaLayout iterators may not function correctly under Qt4 return TQLayoutIterator( this ); // [FIXME] #else // USE_QT4 return TQLayoutIterator(new FlowLayoutIterator(&mLayoutItems)); #endif // USE_QT4 } 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 it(mLayoutItems); TQLayoutItem* layoutItem; TQPtrList 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() ); } // retqlayout 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->tqgeometry(); 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 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 } #ifdef USE_QT4 /*! \reimp */ int FlowLayout::count() const { return mLayoutItems.count(); } /*! \reimp */ TQLayoutItem* FlowLayout::itemAt(int index) const { return index >= 0 && index < mLayoutItems.count() ? (const_cast&>(mLayoutItems).tqat(index)) : 0; } /*! \reimp */ TQLayoutItem* FlowLayout::takeAt(int index) { if (index < 0 || index >= mLayoutItems.count()) return 0; TQLayoutItem *item = mLayoutItems.tqat(index); mLayoutItems.remove(mLayoutItems.tqat(index)); delete item; invalidate(); return item; } #endif // USE_QT4