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.
370 lines
9.5 KiB
370 lines
9.5 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2001-2002 Matthias Kretz <kretz@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
//$Id$
|
|
|
|
#include <assert.h>
|
|
|
|
#include <tqcolor.h>
|
|
#include <tqwidget.h>
|
|
#include <tqimage.h>
|
|
#include <tqpainter.h>
|
|
#include <tqpen.h>
|
|
#include <tqmovie.h>
|
|
#include <tqpixmap.h>
|
|
|
|
#include <kpixmap.h>
|
|
#include <kdebug.h>
|
|
|
|
#include "kimageholder.h"
|
|
|
|
KImageHolder::KImageHolder( TQWidget * parent, const char * name )
|
|
: TQWidget( parent, name, TQt::WResizeNoErase | TQt::WRepaintNoErase )
|
|
, m_selected( false )
|
|
, m_bSelecting( false )
|
|
, m_scrollTimerId( 0 )
|
|
, m_xOffset( 0 )
|
|
, m_yOffset( 0 )
|
|
, m_pen( new TQPen( TQColor( 255, 255, 255 ), 0, DashLine ) )
|
|
, m_pPixmap( 0 )
|
|
, m_pDoubleBuffer( 0 )
|
|
, m_pCheckboardPixmap( 0 )
|
|
{
|
|
setBackgroundMode( TQWidget::NoBackground );
|
|
}
|
|
|
|
KImageHolder::~KImageHolder()
|
|
{
|
|
delete m_pen;
|
|
delete m_pPixmap;
|
|
delete m_pDoubleBuffer;
|
|
delete m_pCheckboardPixmap;
|
|
m_pen = 0;
|
|
m_pPixmap = 0;
|
|
m_pDoubleBuffer = 0;
|
|
m_pCheckboardPixmap = 0;
|
|
}
|
|
|
|
void KImageHolder::mousePressEvent( TQMouseEvent *ev )
|
|
{
|
|
//kdDebug( 4620 ) << k_funcinfo << " ev->state() = " << ev->state() << endl;
|
|
// if the right mouse button is pressed emit the contextPress signal
|
|
if ( ev->button() == Qt::RightButton )
|
|
{
|
|
emit contextPress( mapToGlobal( ev->pos() ) );
|
|
return;
|
|
}
|
|
|
|
if( m_pPixmap == 0 )
|
|
return;
|
|
|
|
if( ev->button() == Qt::LeftButton || ev->button() == Qt::MidButton )
|
|
{
|
|
m_scrollpos = ev->globalPos();
|
|
m_selectionStartPoint = ev->pos();
|
|
}
|
|
}
|
|
|
|
void KImageHolder::mouseMoveEvent( TQMouseEvent *ev )
|
|
{
|
|
//FIXME: when scrolling the cursorpos shouldn't change
|
|
if( TQT_TQRECT_OBJECT(this->rect()).contains( ev->pos(), false ) )
|
|
emit cursorPos( ev->pos() );
|
|
//kdDebug( 4620 ) << k_funcinfo << " ev->state() = " << ev->state() << endl;
|
|
if( ev->state() & Qt::LeftButton || ev->state() & Qt::MidButton )
|
|
{
|
|
// scroll when a modifier and left button or the middle button is pressed
|
|
if( ev->state() & AltButton || ev->state() & ControlButton || ev->state() & ShiftButton || ev->state() & Qt::MidButton )
|
|
{
|
|
TQPoint difference = m_scrollpos - ev->globalPos();
|
|
emit wannaScroll( difference.x(), difference.y() );
|
|
}
|
|
else // create a selection
|
|
{
|
|
TQWidget * parentwidget = ( TQWidget* )parent();
|
|
if( ! m_bSelecting )
|
|
{
|
|
m_bSelecting = true;
|
|
if( m_selected ) {
|
|
// remove old rubberband
|
|
eraseSelect();
|
|
m_selected = false;
|
|
}
|
|
|
|
m_selection.setLeft( m_selectionStartPoint.x() );
|
|
m_selection.setRight( m_selectionStartPoint.x() );
|
|
m_selection.setTop( m_selectionStartPoint.y() );
|
|
m_selection.setBottom( m_selectionStartPoint.y() );
|
|
}
|
|
// currently called only on drag,
|
|
// so assume a selection has been started
|
|
bool erase = m_selected;
|
|
|
|
if( !m_selected )
|
|
m_selected = true;
|
|
|
|
// Autoscrolling:
|
|
// For every pixel the mouse leaves the image canvas the canvas
|
|
// should scroll faster. The scrolling should be independent from
|
|
// the mouse movement. Therefor I need a timer to do the scroll
|
|
// movement:
|
|
// e.g.: m_xOffset=-1 => scroll to the left 1 px per 50ms
|
|
// -2 => scroll to the left 2 px per 50ms
|
|
// 2 => scroll to the right 2 px per 50ms
|
|
// ...
|
|
m_xOffset = mapTo( parentwidget, ev->pos() ).x();
|
|
m_yOffset = mapTo( parentwidget, ev->pos() ).y();
|
|
if( m_xOffset > 0 )
|
|
{
|
|
m_xOffset -= parentwidget->width();
|
|
if( m_xOffset < 0 )
|
|
m_xOffset = 0;
|
|
}
|
|
if( m_yOffset > 0 )
|
|
{
|
|
m_yOffset -= parentwidget->height();
|
|
if( m_yOffset < 0 )
|
|
m_yOffset = 0;
|
|
}
|
|
if( m_scrollTimerId != 0 && m_xOffset == 0 && m_yOffset == 0 )
|
|
{
|
|
killTimer( m_scrollTimerId );
|
|
m_scrollTimerId = 0;
|
|
}
|
|
else if( m_scrollTimerId == 0 && ( m_xOffset != 0 || m_yOffset != 0 ) )
|
|
m_scrollTimerId = startTimer( 50 );
|
|
|
|
int r = ev->x() < width() ? ( ev->x() < 0 ? 0 : ev->x() ) : width() - 1;
|
|
int b = ev->y() < height() ? ( ev->y() < 0 ? 0 : ev->y() ) : height() - 1;
|
|
|
|
if( r != m_selection.right() || b != m_selection.bottom() )
|
|
{
|
|
if( erase )
|
|
eraseSelect();
|
|
|
|
m_selection.setRight( r );
|
|
m_selection.setBottom( b );
|
|
emit selected( m_selection.normalize() );
|
|
|
|
TQPainter painter( this );
|
|
drawSelect( painter );
|
|
}
|
|
}
|
|
m_scrollpos = ev->globalPos();
|
|
m_selectionStartPoint = ev->pos();
|
|
}
|
|
}
|
|
|
|
void KImageHolder::mouseReleaseEvent( TQMouseEvent * ev )
|
|
{
|
|
if( m_bSelecting )
|
|
{
|
|
m_xOffset = m_yOffset = 0;
|
|
if( m_scrollTimerId != 0 )
|
|
{
|
|
killTimer( m_scrollTimerId );
|
|
m_scrollTimerId = 0;
|
|
}
|
|
}
|
|
if( ev->state() & Qt::LeftButton || ev->state() & Qt::MidButton )
|
|
if( m_bSelecting )
|
|
m_bSelecting = false;
|
|
else
|
|
clearSelection();
|
|
}
|
|
|
|
void KImageHolder::drawSelect( TQPainter & painter )
|
|
{
|
|
painter.save();
|
|
painter.setRasterOp( XorROP );
|
|
painter.setPen( *m_pen );
|
|
painter.drawRect( m_selection.normalize() );
|
|
painter.restore();
|
|
}
|
|
|
|
void KImageHolder::eraseSelect()
|
|
{
|
|
TQRegion r( m_selection.normalize() );
|
|
TQRect inner = m_selection.normalize();
|
|
inner.rLeft() += 1;
|
|
inner.rTop() += 1;
|
|
inner.rRight() -= 1;
|
|
inner.rBottom() -= 1;
|
|
r -= inner;
|
|
|
|
TQMemArray<TQRect> rects = r.rects();
|
|
|
|
if( m_pDoubleBuffer )
|
|
for( unsigned int i = 0; i < rects.size(); ++i )
|
|
bitBlt( this, rects[ i ].topLeft(), m_pDoubleBuffer, rects[ i ], CopyROP );
|
|
else
|
|
for( unsigned int i = 0; i < rects.size(); ++i )
|
|
bitBlt( this, rects[ i ].topLeft(), m_pPixmap, rects[ i ], CopyROP );
|
|
}
|
|
|
|
void KImageHolder::clearSelection()
|
|
{
|
|
if( m_selected )
|
|
{
|
|
eraseSelect();
|
|
m_selected = false;
|
|
}
|
|
m_selection.setSize( TQSize( 0, 0 ) );
|
|
emit selected( m_selection );
|
|
}
|
|
|
|
void KImageHolder::setImage( const KPixmap & pix )
|
|
{
|
|
clearSelection();
|
|
|
|
setPixmap( pix );
|
|
}
|
|
|
|
void KImageHolder::setImage( const TQImage & image )
|
|
{
|
|
clearSelection();
|
|
kdDebug( 4620 ) << "converting Image to Pixmap" << endl;
|
|
KPixmap pix( image );
|
|
|
|
setPixmap( pix );
|
|
}
|
|
|
|
void KImageHolder::setImage( const TQMovie & /*movie*/ )
|
|
{
|
|
clearSelection();
|
|
//setMovie( movie );
|
|
kdWarning( 4620 ) << "setImage( TQMovie ) not implemented" << endl;
|
|
}
|
|
|
|
void KImageHolder::clear()
|
|
{
|
|
delete m_pPixmap;
|
|
m_pPixmap = 0;
|
|
delete m_pDoubleBuffer;
|
|
m_pDoubleBuffer = 0;
|
|
hide();
|
|
clearSelection();
|
|
}
|
|
|
|
TQRect KImageHolder::selection() const
|
|
{
|
|
if( m_selected )
|
|
return m_selection.normalize();
|
|
else
|
|
return TQRect();
|
|
}
|
|
|
|
TQSize KImageHolder::sizeHint() const
|
|
{
|
|
if( m_pPixmap )
|
|
return m_pPixmap->size();
|
|
return TQSize( 0, 0 );
|
|
}
|
|
|
|
void KImageHolder::paintEvent( TQPaintEvent *ev )
|
|
{
|
|
TQPainter painter( this );
|
|
painter.setClipRegion( ev->region().intersect( m_drawRect ) );
|
|
if( m_pPixmap )
|
|
{
|
|
if( m_pPixmap->mask() )
|
|
{
|
|
if( ! m_pDoubleBuffer )
|
|
{
|
|
m_pDoubleBuffer = new KPixmap( m_pPixmap->size() );
|
|
TQPainter p( m_pDoubleBuffer );
|
|
p.drawTiledPixmap( m_pDoubleBuffer->rect(), checkboardPixmap() );
|
|
p.end();
|
|
bitBlt( m_pDoubleBuffer, TQPoint( 0, 0 ), m_pPixmap, m_pPixmap->rect() );
|
|
}
|
|
painter.drawPixmap( 0, 0, *m_pDoubleBuffer );
|
|
}
|
|
else
|
|
painter.drawPixmap( 0, 0, *m_pPixmap );
|
|
}
|
|
if( m_selected )
|
|
drawSelect( painter );
|
|
}
|
|
|
|
void KImageHolder::timerEvent( TQTimerEvent * ev )
|
|
{
|
|
if( ev->timerId() != m_scrollTimerId )
|
|
return;
|
|
|
|
emit wannaScroll( m_xOffset, m_yOffset );
|
|
}
|
|
|
|
void KImageHolder::setPixmap( const KPixmap & pixmap )
|
|
{
|
|
kdDebug( 4620 ) << k_funcinfo << " " << pixmap.width() << 'x' << pixmap.height() << endl;
|
|
delete m_pPixmap;
|
|
delete m_pDoubleBuffer;
|
|
m_pDoubleBuffer = 0;
|
|
m_pPixmap = new KPixmap( pixmap );
|
|
m_drawRect = m_pPixmap->rect();
|
|
show();
|
|
}
|
|
|
|
const KPixmap & KImageHolder::checkboardPixmap()
|
|
{
|
|
if( ! m_pCheckboardPixmap )
|
|
{
|
|
const char * xpm[] = {
|
|
"32 32 2 1",
|
|
" c #666666",
|
|
"X c #999999",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
" XXXXXXXXXXXXXXXX",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
"XXXXXXXXXXXXXXXX ",
|
|
};
|
|
m_pCheckboardPixmap = new KPixmap( xpm );
|
|
}
|
|
return *m_pCheckboardPixmap;
|
|
}
|
|
|
|
#include "kimageholder.moc"
|