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.
tdebase/kicker/applets/launcher/flowgridmanager.cpp

317 lines
9.2 KiB

/* Copyright 2004, Daniel Woods Bullok <dan.devel@bullok.com>
distributed under the terms of the
GNU GENERAL PUBLIC LICENSE Version 2 -
See the file kdebase/COPYING for details
*/
#include "flowgridmanager.h"
#include <kdebug.h>
#ifdef DEBUG
#define DEBUGSTR kdDebug()
#else
#define DEBUGSTR kndDebug()
#endif
FlowGridManager::FlowGridManager(QSize p_item_size,
QSize p_space_size,
QSize p_border_size,
QSize p_frame_size,
Qt::Orientation orient,
int num_items,
Slack slack_x,Slack slack_y)
{
_pItemSize=p_item_size;
_pSpaceSize=p_space_size;
_pBorderSize=p_border_size;
_pFrameSize=p_frame_size;
_orientation=orient;
_numItems=num_items;
_slackX=slack_x;
_slackY=slack_y;
_conserveSpace=false;
_dirty=true;
_valid=false;
}
// set members.
// These all set the _dirty flag if the new value is different.
void FlowGridManager::setNumItems(int num_items)
{ if (_numItems==num_items)
return;
_numItems=num_items; _dirty=true;
}
void FlowGridManager::setItemSize(QSize p_item_size)
{ if (_pItemSize==p_item_size)
return;
_pItemSize=p_item_size; _dirty=true;
}
void FlowGridManager::setSpaceSize(QSize p_space_size)
{ if (_pSpaceSize==p_space_size)
return;
_pSpaceSize=p_space_size; _dirty=true;
}
void FlowGridManager::setBorderSize(QSize p_border_size)
{ if (_pBorderSize==p_border_size)
return;
_pBorderSize=p_border_size; _dirty=true;
}
void FlowGridManager::setFrameSize(QSize p_frame_size)
{ if (_pFrameSize==p_frame_size)
return;
_pFrameSize=p_frame_size;
if (_pFrameSize.width()<=0) {
_orientation=Qt::Vertical;
}
if (_pFrameSize.height()<=0) {
_orientation=Qt::Horizontal;
}
_dirty=true;
}
void FlowGridManager::setOrientation(Qt::Orientation orient)
{ if (orient==_orientation)
return;
_orientation=orient; _dirty=true;
}
void FlowGridManager::setSlack(Slack slack_x, Slack slack_y)
{ if (slack_x==_slackX && slack_y==_slackY) return;
_slackX=slack_x; _slackY=slack_y; _dirty=true;}
void FlowGridManager::setConserveSpace(bool conserve)
{ if (_conserveSpace==conserve)
return;
_conserveSpace=conserve; _dirty=true;
}
// get members
QSize FlowGridManager::itemSize() const
{ _checkReconfigure(); return _itemSize;}
QSize FlowGridManager::spaceSize() const
{ _checkReconfigure(); return _spaceSize;}
QSize FlowGridManager::borderSize() const
{ _checkReconfigure(); return _borderSize;}
QSize FlowGridManager::gridDim() const
{ _checkReconfigure(); return _gridDim;}
QSize FlowGridManager::gridSpacing() const
{ _checkReconfigure(); return _gridSpacing;}
QSize FlowGridManager::frameSize() const
{ _checkReconfigure(); return _frameSize;}
QPoint FlowGridManager::origin() const
{ _checkReconfigure(); return _origin;}
Qt::Orientation FlowGridManager::orientation() const
{ _checkReconfigure(); return _orientation;}
/*Slack FlowGridManager::slackX() const
{ return _slackY;}
Slack FlowGridManager::slackY() const
{ return _slackY;}
*/
bool FlowGridManager::conserveSpace() const
{ return _conserveSpace; }
bool FlowGridManager::isValid() const
{ _checkReconfigure(); return _valid;}
QPoint FlowGridManager::posAtCell(int x,int y) const
{ _checkReconfigure();
return _origin+QPoint(_gridSpacing.width()*x,_gridSpacing.height()*y);
}
QPoint FlowGridManager::pos(int i) const
{ return posAtCell(cell(i).x(),cell(i).y());
}
QPoint FlowGridManager::cell(int index) const
{ _checkReconfigure();
//assert((index>=0) && (index<_gridDim.width()*_gridDim.height()));
int x=index % _gridDim.width(),
y=index / _gridDim.width();
return QPoint(x,y);
}
// return height if orientation is Horizontal
// return width if orientation is Vertical
int FlowGridManager::_getHH(QSize size) const
{ if (_orientation==Qt::Horizontal)
return size.height();
return size.width();
}
// return height if orientation is Vertical
// return width if orientation is Horizontal
int FlowGridManager::_getWH(QSize size) const
{ if (_orientation==Qt::Horizontal)
return size.width();
return size.height();
}
// swap horizontal and vertical if orientation is Vertical, otherwise return arg
QSize FlowGridManager::_swapHV(QSize hv) const
{ if (_orientation==Qt::Horizontal)
return hv;
QSize temp=hv;
temp.transpose();
return temp;
}
// return the amount of slack when:
// nitems = # of items
// length = total length of space where items will be placed
// item, space, border = length of respective entities
int FlowGridManager::_slack(int nitems,int length,int item,int space,int border) const
{ return length-(2*border)-(nitems-1)*space-nitems*item;}
void FlowGridManager::_clear() const
{
_borderSize=QSize(0,0);
_spaceSize=QSize(0,0);
_itemSize=QSize(0,0);
_gridDim=QSize(0,0);
_gridSpacing=QSize(0,0);
_origin=QPoint(0,0);
_frameSize=QSize(0,0);
_dirty=false;
_valid=false;
}
int FlowGridManager::indexNearest(QPoint p) const
{ if (!isValid()) return -1;
QPoint c=(p-_origin)-QPoint(_spaceSize.width(),_spaceSize.height())/2;
int x=c.x()/_gridSpacing.width(),
y=c.y()/_gridSpacing.height();
int i= x+y*_gridDim.width();
if (i>_numItems) return -1;
return i;
}
// Redistribute the boxes
void FlowGridManager::_reconfigure() const
{ if ((!_pFrameSize.isValid()) ||
(!_pItemSize.isValid()) ||
_numItems==0 ) {
_clear();
return;
}
int height=_getHH(_pFrameSize),
pItemHeight=_getHH(_pItemSize),
pSpaceHeight=_getHH(_pSpaceSize),
pBorderHeight=_getHH(_pBorderSize),
spanlen=(height-2*pBorderHeight+pSpaceHeight)/(pItemHeight+pSpaceHeight);
int slack,iSlack;
if (spanlen==0) {
_dirty=false;
_valid=false;
return;
}
// figure out the number of spans required for all items
int numspans=_numItems/spanlen;
if (numspans*spanlen<_numItems) {
numspans++;
}
slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight); // total slack
iSlack=slack/spanlen; // slack per item
// Items pick up extra slack
if (_slackX==ItemSlack) pItemHeight+=iSlack;
slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight);
// space picks up extra slack
if (spanlen>1) {
iSlack=slack/(spanlen+1);
pSpaceHeight+=iSlack;
}
slack=_slack(spanlen,height,pItemHeight,pSpaceHeight,pBorderHeight);
iSlack=slack/2;
pBorderHeight+=iSlack;
if (_conserveSpace) {
_itemSize=_swapHV(QSize(_getWH(_pItemSize),pItemHeight));
_spaceSize=_swapHV(QSize(_getWH(_pSpaceSize),pSpaceHeight));
_borderSize=_swapHV(QSize(_getWH(_pBorderSize),pBorderHeight));
}
else {
_itemSize=_swapHV(QSize(pItemHeight,pItemHeight));
_spaceSize=_swapHV(QSize(pSpaceHeight,pSpaceHeight));
_borderSize=_swapHV(QSize(pBorderHeight,pBorderHeight));
}
_gridDim=_swapHV(QSize(numspans,spanlen));
_gridSpacing=_itemSize+_spaceSize;
_origin=QPoint(_borderSize.width(),_borderSize.height());
_frameSize=2*_borderSize+QSize(_gridDim.width()*_gridSpacing.width()-_spaceSize.width(),
_gridDim.height()*_gridSpacing.height()-_spaceSize.height());
_dirty=false;
_valid=true;
}
void FlowGridManager::dump()
{
DEBUGSTR<<endl<<flush;
DEBUGSTR<<"_pItemSize=("<<_pItemSize.width()<<","<<_pItemSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_pSpaceSize=("<<_pSpaceSize.width()<<","<<_pSpaceSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_pBorderSize=("<<_pBorderSize.width()<<","<<_pBorderSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_pFrameSize=("<<_pFrameSize.width()<<","<<_pFrameSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_borderSize=("<<_borderSize.width()<<","<<_borderSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_spaceSize=("<<_spaceSize.width()<<","<<_spaceSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_itemSize=("<<_itemSize.width()<<","<<_itemSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_gridDim=("<<_gridDim.width()<<","<<_gridDim.height()<<")"<<endl<<flush;
DEBUGSTR<<"_gridSpacing=("<<_gridSpacing.width()<<","<<_gridSpacing.height()<<")"<<endl<<flush;
DEBUGSTR<<"_origin=("<<_origin.x()<<","<<_origin.y()<<")"<<endl<<flush;
DEBUGSTR<<"_frameSize=("<<_frameSize.width()<<","<<_frameSize.height()<<")"<<endl<<flush;
DEBUGSTR<<"_conserveSpace="<<_conserveSpace<<endl<<flush;
DEBUGSTR<<"_orientation="<<_orientation<<endl<<flush;
DEBUGSTR<<"_numItems="<<_numItems<<endl<<flush;
DEBUGSTR<<"_slackX="<<_slackX<<endl<<flush;
DEBUGSTR<<"_slackY="<<_slackY<<endl<<flush;
DEBUGSTR<<"_dirty="<<_dirty<<endl<<flush;
DEBUGSTR<<"_valid="<<_valid<<endl<<flush;
DEBUGSTR<<endl<<flush;
}
bool operator== ( const FlowGridManager & csg1, const FlowGridManager & csg2 )
{
return csg1.gridDim()==csg2.gridDim() &&
csg1.origin()==csg2.origin() &&
csg1.gridSpacing()==csg2.gridSpacing() &&
csg1.frameSize()==csg2.frameSize();
}