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.
483 lines
11 KiB
483 lines
11 KiB
/* This file is part of the KDE project
|
|
Copyright (c) 1999 Carsten Pfeiffer (pfeiffer@kde.org)
|
|
Copyright (c) 2002 Igor Jansen (rm@kde.org)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <kdebug.h>
|
|
#include <koIconChooser.h>
|
|
#include <tdeglobal.h>
|
|
|
|
#include <tqpainter.h>
|
|
#include <tqcursor.h>
|
|
#include <tqapplication.h>
|
|
#include <tqhbox.h>
|
|
#include <tqlayout.h>
|
|
#include <kdebug.h>
|
|
|
|
KoPixmapWidget::KoPixmapWidget(const TQPixmap &aPixmap, TQWidget *parent, const char *name):
|
|
TQFrame(parent, name, WType_Popup)
|
|
{
|
|
kdDebug() << "Popup created: " << name << "\n";
|
|
setFrameStyle(TQFrame::WinPanel | TQFrame::Raised);
|
|
mPixmap = aPixmap;
|
|
int w = mPixmap.width() + 2 * lineWidth();
|
|
int h = mPixmap.height() + 2 * lineWidth();
|
|
resize(w, h);
|
|
|
|
}
|
|
|
|
KoPixmapWidget::~KoPixmapWidget()
|
|
{
|
|
}
|
|
|
|
// paint the centered pixmap; don't overpaint the frame
|
|
void KoPixmapWidget::paintEvent(TQPaintEvent *e)
|
|
{
|
|
TQFrame::paintEvent(e);
|
|
TQPainter p(this);
|
|
p.setClipRect(e->rect());
|
|
p.drawPixmap(lineWidth(), lineWidth(), mPixmap);
|
|
}
|
|
|
|
|
|
void KoPixmapWidget::mouseReleaseEvent(TQMouseEvent *)
|
|
{
|
|
hide();
|
|
}
|
|
|
|
|
|
KoIconChooser::KoIconChooser(TQSize aIconSize, TQWidget *parent, const char *name, bool sort):
|
|
TQGridView(parent, name)
|
|
{
|
|
TQGridView::setBackgroundColor(TQt::white);
|
|
|
|
mMargin = 2;
|
|
setCellWidth(aIconSize.width() + 2 * mMargin);
|
|
setCellHeight(aIconSize.height() + 2 * mMargin);
|
|
|
|
mIconList.clear();
|
|
mPixmapWidget = 0L;
|
|
mNCols = 0;
|
|
mCurRow = 0;
|
|
mCurCol = 0;
|
|
mItemCount = 0;
|
|
mItemWidth = aIconSize.width();
|
|
mItemHeight = aIconSize.height();
|
|
mMouseButtonDown = false;
|
|
mDragEnabled = false;
|
|
mSort = sort;
|
|
}
|
|
|
|
KoIconChooser::~KoIconChooser()
|
|
{
|
|
mIconList.clear();
|
|
if(mPixmapWidget)
|
|
delete mPixmapWidget;
|
|
}
|
|
|
|
void KoIconChooser::addItem(KoIconItem *item)
|
|
{
|
|
TQ_INT32 n = mItemCount;
|
|
KoIconItem *current = currentItem();
|
|
|
|
Q_ASSERT(item);
|
|
|
|
int i;
|
|
|
|
if (mSort)
|
|
{
|
|
i = sortInsertionIndex(item);
|
|
}
|
|
else
|
|
{
|
|
i = mItemCount;
|
|
}
|
|
|
|
mIconList.insert(i, item);
|
|
mItemCount++;
|
|
calculateCells();
|
|
|
|
if (mSort)
|
|
{
|
|
setCurrentItem(current);
|
|
updateContents();
|
|
}
|
|
else
|
|
{
|
|
updateCell(n / numCols(), n - (n / numCols()) * numCols());
|
|
}
|
|
}
|
|
|
|
bool KoIconChooser::removeItem(KoIconItem *item)
|
|
{
|
|
int index = mIconList.find(item);
|
|
bool ok = mIconList.remove(item);
|
|
if( ok )
|
|
{
|
|
mItemCount--;
|
|
// select same cell as deleted cell, or new last cell if we deleted
|
|
// last cell.
|
|
setCurrentItem(itemAt(kMin(index, mItemCount - 1)));
|
|
calculateCells();
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void KoIconChooser::clear()
|
|
{
|
|
mItemCount = 0;
|
|
mIconList.clear();
|
|
calculateCells();
|
|
}
|
|
|
|
// return 0L if there is no current item
|
|
KoIconItem *KoIconChooser::currentItem()
|
|
{
|
|
return itemAt(mCurRow, mCurCol);
|
|
}
|
|
|
|
// sets the current item to item
|
|
// does NOT emit selected() (should it?)
|
|
void KoIconChooser::setCurrentItem(KoIconItem *item)
|
|
{
|
|
int index = mIconList.find(item);
|
|
|
|
// item is available
|
|
if(index != -1 && mNCols > 0)
|
|
{
|
|
int oldRow = mCurRow;
|
|
int oldCol = mCurCol;
|
|
|
|
mCurRow = index / mNCols;
|
|
mCurCol = index % mNCols;
|
|
|
|
// repaint the old and the new item
|
|
repaintCell(oldRow, oldCol);
|
|
repaintCell(mCurRow, mCurCol);
|
|
|
|
ensureCellVisible(mCurRow, mCurCol);
|
|
}
|
|
}
|
|
|
|
// eventually select the item, clicked on
|
|
void KoIconChooser::mousePressEvent(TQMouseEvent *e)
|
|
{
|
|
TQGridView::mousePressEvent(e);
|
|
}
|
|
|
|
void KoIconChooser::mouseMoveEvent(TQMouseEvent *e)
|
|
{
|
|
if(mMouseButtonDown && mDragEnabled )
|
|
{
|
|
#if 0
|
|
if(mPixmapWidget)
|
|
{
|
|
delete mPixmapWidget;
|
|
mPixmapWidget = 0L;
|
|
}
|
|
#endif
|
|
if( ( mDragStartPos - e->pos() ).manhattanLength() > TQApplication::startDragDistance() )
|
|
startDrag();
|
|
}
|
|
}
|
|
|
|
void
|
|
KoIconChooser::startDrag()
|
|
{
|
|
mMouseButtonDown = false;
|
|
}
|
|
|
|
void KoIconChooser::mouseReleaseEvent(TQMouseEvent * e)
|
|
{
|
|
mMouseButtonDown = true;
|
|
if(e->button() == TQt::LeftButton)
|
|
{
|
|
TQPoint p = e->pos();
|
|
mDragStartPos = p;
|
|
int x = contentsX() + p.x();
|
|
int y = contentsY() + p.y();
|
|
TQSize gridExtent = gridSize();
|
|
|
|
if (x < gridExtent.width() && y < gridExtent.height())
|
|
{
|
|
int row = rowAt(y);
|
|
int col = columnAt(x);
|
|
|
|
KoIconItem *item = itemAt(row, col);
|
|
if(item)
|
|
{
|
|
const TQPixmap &pix = item->pixmap();
|
|
if(pix.width() > mItemWidth || pix.height() > mItemHeight)
|
|
showFullPixmap(pix, p);
|
|
|
|
setCurrentItem(item);
|
|
emit selected( item );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// FIXME: implement keyboard navigation
|
|
void KoIconChooser::keyPressEvent(TQKeyEvent *e)
|
|
{
|
|
TQGridView::keyPressEvent(e);
|
|
}
|
|
|
|
// recalculate the number of items that fit into one row
|
|
// set the current item again after calculating the new grid
|
|
void KoIconChooser::resizeEvent(TQResizeEvent *e)
|
|
{
|
|
TQGridView::resizeEvent(e);
|
|
|
|
KoIconItem *item = currentItem();
|
|
int oldNCols = mNCols;
|
|
|
|
if (cellWidth() != 0)
|
|
{
|
|
mNCols = e -> size().width() / cellWidth();
|
|
}
|
|
|
|
if(mNCols != oldNCols)
|
|
{
|
|
setNumCols(mNCols);
|
|
calculateCells();
|
|
setCurrentItem(item);
|
|
updateContents();
|
|
}
|
|
}
|
|
|
|
// paint one cell
|
|
// mark the current item and center items smaller than the cellSize
|
|
// TODO: scale down big pixmaps and paint the size as text into the pixmap
|
|
void KoIconChooser::paintCell(TQPainter *p, int row, int col)
|
|
{
|
|
KoIconItem *item = itemAt(row, col);
|
|
|
|
if(item)
|
|
{
|
|
const TQPixmap &pix = item->pixmap();
|
|
|
|
int x = mMargin;
|
|
int y = mMargin;
|
|
int pw = pix.width();
|
|
int ph = pix.height();
|
|
int cw = cellWidth();
|
|
int ch = cellHeight();
|
|
|
|
// center small pixmaps
|
|
if(pw < mItemWidth)
|
|
x = (cw - pw) / 2;
|
|
if(ph < mItemHeight)
|
|
y = (cw - ph) / 2;
|
|
|
|
if((!item->hasValidThumb()) || (pw <= mItemWidth && ph <= mItemHeight))
|
|
p->drawPixmap(x, y, pix, 0, 0, mItemWidth, mItemHeight);
|
|
else
|
|
{
|
|
const TQPixmap &thumbpix = item->thumbPixmap();
|
|
x = mMargin;
|
|
y = mMargin;
|
|
pw = thumbpix.width();
|
|
ph = thumbpix.height();
|
|
cw = cellWidth();
|
|
ch = cellHeight();
|
|
|
|
// center small pixmaps
|
|
if(pw < mItemWidth)
|
|
x = (cw - pw) / 2;
|
|
if(ph < mItemHeight)
|
|
y = (cw - ph) / 2;
|
|
p->drawPixmap(x, y, thumbpix, 0, 0, mItemWidth, mItemHeight);
|
|
}
|
|
|
|
// highlight current item
|
|
if(row == mCurRow && col == mCurCol)
|
|
{
|
|
p->setPen(blue);
|
|
p->drawRect(0, 0, cw, ch);
|
|
}
|
|
else
|
|
{
|
|
p->setPen(gray);
|
|
//p->drawRect(0, 0, cw, ch);
|
|
p->drawLine(cw-1, 0, cw-1, ch-1);
|
|
p->drawLine(0, ch-1, cw-1, ch-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// empty cell
|
|
p->fillRect(0, 0, cellWidth(), cellHeight(), TQBrush(TQt::white));
|
|
}
|
|
}
|
|
|
|
// return the pointer of the item at (row,col) - beware, resizing disturbs
|
|
// rows and cols!
|
|
// return 0L if item is not found
|
|
KoIconItem *KoIconChooser::itemAt(int row, int col)
|
|
{
|
|
return itemAt(cellIndex(row, col));
|
|
}
|
|
|
|
// return the pointer of the item at position index
|
|
// return 0L if item is not found
|
|
KoIconItem *KoIconChooser::itemAt(int index)
|
|
{
|
|
if(index < 0)
|
|
return 0L;
|
|
return mIconList.count() > uint(index) ? mIconList.at(index) : 0;
|
|
}
|
|
|
|
// return the index of a cell, given row and column position
|
|
// maps directly to the position in the itemlist
|
|
// return -1 on failure
|
|
int KoIconChooser::cellIndex(int row, int col)
|
|
{
|
|
if(row < 0 || col < 0)
|
|
return -1;
|
|
else
|
|
return((row * mNCols) + col);
|
|
}
|
|
|
|
// calculate the grid and set the number of rows and columns
|
|
// reorder all items approrpriately
|
|
void KoIconChooser::calculateCells()
|
|
{
|
|
if(mNCols == 0)
|
|
return;
|
|
bool update = isUpdatesEnabled();
|
|
int rows = mItemCount / mNCols;
|
|
setUpdatesEnabled(false);
|
|
if((rows * mNCols) < mItemCount)
|
|
rows++;
|
|
setNumRows(rows);
|
|
setUpdatesEnabled(update);
|
|
updateContents();
|
|
}
|
|
|
|
// show the full pixmap of a large item in an extra widget
|
|
void KoIconChooser::showFullPixmap(const TQPixmap &pix, const TQPoint &/*p*/)
|
|
{
|
|
//delete mPixmapWidget;
|
|
mPixmapWidget = new KoPixmapWidget(pix, this);
|
|
|
|
// center widget under mouse cursor
|
|
TQPoint p = TQCursor::pos();
|
|
int w = mPixmapWidget->width();
|
|
int h = mPixmapWidget->height();
|
|
mPixmapWidget->move(p.x() - w / 2, p.y() - h / 2);
|
|
mPixmapWidget->show();
|
|
}
|
|
|
|
int KoIconChooser::sortInsertionIndex(const KoIconItem *item)
|
|
{
|
|
int index = 0;
|
|
|
|
if (!mIconList.isEmpty())
|
|
{
|
|
// Binary insertion
|
|
int first = 0;
|
|
int last = mIconList.count() - 1;
|
|
|
|
while (first != last)
|
|
{
|
|
int middle = (first + last) / 2;
|
|
|
|
if (item -> compare(mIconList.at(middle)) < 0)
|
|
{
|
|
last = middle - 1;
|
|
|
|
if (last < first)
|
|
{
|
|
last = first;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
first = middle + 1;
|
|
|
|
if (first > last)
|
|
{
|
|
first = last;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (item -> compare(mIconList.at(first)) < 0)
|
|
{
|
|
index = first;
|
|
}
|
|
else
|
|
{
|
|
index = first + 1;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
KoPatternChooser::KoPatternChooser( const TQPtrList<KoIconItem> &list, TQWidget *parent, const char *name )
|
|
: TQWidget( parent, name )
|
|
{
|
|
// only serves as beautifier for the iconchooser
|
|
//frame = new TQHBox( this );
|
|
//frame->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
|
|
chooser = new KoIconChooser( TQSize(30,30), this, "pattern chooser" );
|
|
|
|
TQObject::connect( chooser, TQ_SIGNAL(selected( KoIconItem * ) ),
|
|
this, TQ_SIGNAL( selected( KoIconItem * )));
|
|
|
|
TQPtrListIterator<KoIconItem> itr( list );
|
|
for( itr.toFirst(); itr.current(); ++itr )
|
|
chooser->addItem( itr.current() );
|
|
|
|
TQVBoxLayout *mainLayout = new TQVBoxLayout( this, 1, -1, "main layout" );
|
|
mainLayout->addWidget( chooser, 10 );
|
|
}
|
|
|
|
|
|
KoPatternChooser::~KoPatternChooser()
|
|
{
|
|
delete chooser;
|
|
//delete frame;
|
|
}
|
|
|
|
// set the active pattern in the chooser - does NOT emit selected() (should it?)
|
|
void KoPatternChooser::setCurrentPattern( KoIconItem *pattern )
|
|
{
|
|
chooser->setCurrentItem( pattern );
|
|
}
|
|
|
|
void KoPatternChooser::addPattern( KoIconItem *pattern )
|
|
{
|
|
chooser->addItem( pattern );
|
|
}
|
|
|
|
// return the active pattern
|
|
KoIconItem *KoPatternChooser::currentPattern()
|
|
{
|
|
return chooser->currentItem();
|
|
}
|
|
|
|
void KoPatternChooser::removePattern( KoIconItem *pattern )
|
|
{
|
|
chooser->removeItem( pattern );
|
|
}
|
|
|
|
#include "koIconChooser.moc"
|