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.
485 lines
15 KiB
485 lines
15 KiB
/*************************************************************************** |
|
* Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> * |
|
* * |
|
* 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. * |
|
***************************************************************************/ |
|
|
|
// qt/kde includes |
|
#include <qbitmap.h> |
|
#include <qpixmap.h> |
|
#include <qimage.h> |
|
#include <qpainter.h> |
|
#include <qtimer.h> |
|
#include <qtooltip.h> |
|
#include <kiconloader.h> |
|
#include <kimageeffect.h> |
|
#include <klocale.h> |
|
#include <kdeversion.h> |
|
#include <kaccelmanager.h> |
|
#include <kdebug.h> |
|
|
|
// system includes |
|
#include <math.h> |
|
|
|
// local includes |
|
#include "pageviewtoolbox.h" |
|
#include "conf/settings.h" |
|
|
|
/** ToolboxButton **/ |
|
|
|
static const int ToolboxButtonIcon = 32; |
|
static const int ToolboxButtonSize = 40; |
|
|
|
// a flat button that enlights on hover and has an ID |
|
class ToolboxButton : public QPushButton |
|
{ |
|
public: |
|
ToolboxButton( QWidget * parent, const ToolboxItem & item, const QPixmap & backPixmap ); |
|
int toolboxID() const; |
|
|
|
protected: |
|
void mouseMoveEvent( QMouseEvent * e ); |
|
void mouseReleaseEvent( QMouseEvent * e ); |
|
void paintEvent( QPaintEvent * e ); |
|
|
|
private: |
|
int m_id; |
|
bool m_hovering; |
|
const QPixmap & m_background; |
|
}; |
|
|
|
ToolboxButton::ToolboxButton( QWidget * parent, const ToolboxItem & item, const QPixmap & pix ) |
|
: QPushButton( parent ), m_id( item.id ), m_hovering( false ), m_background( pix ) |
|
{ |
|
setMouseTracking( true ); |
|
setToggleButton( true ); |
|
resize( ToolboxButtonSize, ToolboxButtonSize ); |
|
setPixmap( DesktopIcon( item.pixmap, ToolboxButtonIcon ) ); |
|
QToolTip::add( this, item.text ); |
|
setWFlags( Qt::WNoAutoErase ); |
|
#if KDE_IS_VERSION(3,3,90) |
|
KAcceleratorManager::setNoAccel( this ); |
|
#endif |
|
} |
|
|
|
int ToolboxButton::toolboxID() const |
|
{ |
|
return m_id; |
|
} |
|
|
|
void ToolboxButton::mouseMoveEvent( QMouseEvent * e ) |
|
{ |
|
// check for mouse hovering |
|
const QRect myGeom( 0,0, width(), height() ); |
|
bool hover = myGeom.contains( e->pos() ); |
|
|
|
// if hover state changed update gfx |
|
if ( m_hovering != hover ) |
|
{ |
|
m_hovering = hover; |
|
update(); |
|
} |
|
} |
|
|
|
void ToolboxButton::mouseReleaseEvent( QMouseEvent * e ) |
|
{ |
|
// call default handler |
|
QPushButton::mouseReleaseEvent( e ); |
|
|
|
// reset hover state when clicking |
|
m_hovering = false; |
|
update(); |
|
} |
|
|
|
void ToolboxButton::paintEvent( QPaintEvent * e ) |
|
{ |
|
// always not hovering in disabled state |
|
if ( !isEnabled() ) |
|
m_hovering = false; |
|
|
|
// paint button in different flavours |
|
if ( isOn() || m_hovering ) |
|
{ |
|
// if the button is pressed or we're hovering it, use QPushButton style |
|
QPushButton::paintEvent( e ); |
|
} |
|
else |
|
{ |
|
// else draw button's pixmap over the parent's background (fake transparency) |
|
QPainter p( this ); |
|
QRect backRect = e->rect(); |
|
backRect.moveBy( x(), y() ); |
|
p.drawPixmap( e->rect().topLeft(), m_background, backRect ); |
|
drawButtonLabel( &p ); |
|
} |
|
} |
|
|
|
|
|
/** PageViewToolbox **/ |
|
|
|
static const int ToolboxGridSize = 40; |
|
static const int AnchorRBMargin = 2; |
|
|
|
PageViewToolbox::PageViewToolbox( QWidget * parent, QWidget * anchorWidget ) |
|
: QWidget( parent, "", Qt::WNoAutoErase ), m_anchor( anchorWidget ), |
|
m_side( Left ), m_timerID( 0 ), m_hiding( false ) |
|
{ |
|
} |
|
|
|
void PageViewToolbox::showItems( Side side, const QValueList<ToolboxItem> & items ) |
|
{ |
|
// cache side |
|
m_side = side; |
|
|
|
// delete buttons if already present |
|
if ( !m_buttons.isEmpty() ) |
|
{ |
|
QValueList< ToolboxButton * >::iterator it = m_buttons.begin(), end = m_buttons.end(); |
|
for ( ; it != end; ++it ) |
|
delete *it; |
|
m_buttons.clear(); |
|
} |
|
|
|
// create new buttons for given items |
|
QValueList<ToolboxItem>::const_iterator it = items.begin(), end = items.end(); |
|
for ( ; it != end; ++it ) |
|
{ |
|
ToolboxButton * button = new ToolboxButton( this, *it, m_pixmap ); |
|
connect( button, SIGNAL( clicked() ), this, SLOT( slotButtonClicked() ) ); |
|
m_buttons.append( button ); |
|
} |
|
|
|
// rebuild pixmap and mask |
|
buildGfx(); |
|
QWidget::show(); |
|
|
|
// set scroll parameters |
|
m_hiding = false; |
|
m_currentPosition = getStartPoint(); |
|
m_endPosition = getEndPoint(); |
|
move( m_currentPosition ); |
|
|
|
// start scrolling in |
|
if ( m_timerID ) |
|
killTimer( m_timerID ); |
|
m_timerID = startTimer( 20 ); |
|
} |
|
|
|
void PageViewToolbox::hideAndDestroy() |
|
{ |
|
// set scroll parameters |
|
m_hiding = true; |
|
m_endPosition = getStartPoint(); |
|
|
|
// start scrolling out |
|
if ( m_timerID ) |
|
killTimer( m_timerID ); |
|
m_timerID = startTimer( 10 ); |
|
} |
|
|
|
void PageViewToolbox::anchorChanged() |
|
{ |
|
// stop timer |
|
if ( m_timerID ) |
|
{ |
|
killTimer( m_timerID ); |
|
m_timerID = 0; |
|
} |
|
// if was hiding delete this |
|
if ( m_hiding ) |
|
delete this; |
|
else |
|
showFinal(); |
|
} |
|
|
|
|
|
void PageViewToolbox::mousePressEvent( QMouseEvent * e ) |
|
{ |
|
// set 'dragging' cursor |
|
if ( e->button() == Qt::LeftButton ) |
|
setCursor( sizeAllCursor ); |
|
} |
|
|
|
void PageViewToolbox::mouseMoveEvent( QMouseEvent * e ) |
|
{ |
|
if ( e->state() != Qt::LeftButton ) |
|
return; |
|
|
|
// compute the nearest side |
|
QPoint parentPos = mapToParent( e->pos() ); |
|
float nX = (float)parentPos.x() / (float)m_anchor->width(), |
|
nY = (float)parentPos.y() / (float)m_anchor->height(); |
|
if ( nX > 0.3 && nX < 0.7 && nY > 0.3 && nY < 0.7 ) |
|
return; |
|
bool LT = nX < (1.0 - nY); |
|
bool LB = nX < (nY); |
|
Side side = LT ? ( LB ? Left : Top ) : ( LB ? Bottom : Right ); |
|
|
|
// if side changed, update stuff |
|
if ( side != m_side ) |
|
{ |
|
// inform subclasses about orientation change |
|
orientationChanged( m_side = side ); |
|
|
|
// rebuild and display the widget |
|
showFinal(); |
|
} |
|
} |
|
|
|
void PageViewToolbox::mouseReleaseEvent( QMouseEvent * e ) |
|
{ |
|
// set normal cursor |
|
if ( e->button() == Qt::LeftButton ) |
|
setCursor( arrowCursor ); |
|
} |
|
|
|
void PageViewToolbox::paintEvent( QPaintEvent * e ) |
|
{ |
|
// paint the internal pixmap over the widget |
|
bitBlt( this, e->rect().topLeft(), &m_pixmap, e->rect() ); |
|
} |
|
|
|
void PageViewToolbox::timerEvent( QTimerEvent * ) |
|
{ |
|
// move currentPosition towards endPosition |
|
int dX = m_endPosition.x() - m_currentPosition.x(), |
|
dY = m_endPosition.y() - m_currentPosition.y(); |
|
dX = dX / 6 + QMAX( -1, QMIN( 1, dX) ); |
|
dY = dY / 6 + QMAX( -1, QMIN( 1, dY) ); |
|
m_currentPosition.setX( m_currentPosition.x() + dX ); |
|
m_currentPosition.setY( m_currentPosition.y() + dY ); |
|
|
|
// move the widget |
|
move( m_currentPosition ); |
|
|
|
// handle arrival to the end |
|
if ( m_currentPosition == m_endPosition ) |
|
{ |
|
killTimer( m_timerID ); |
|
m_timerID = 0; |
|
if ( m_hiding ) |
|
delete this; |
|
} |
|
} |
|
|
|
|
|
void PageViewToolbox::showFinal() |
|
{ |
|
// the following gives a better gfx result on repositioning, but ends |
|
// drag operation |
|
//QWidget::hide(); |
|
|
|
// rebuild widget and move it to its final place |
|
buildGfx(); |
|
m_currentPosition = getEndPoint(); |
|
move( m_currentPosition ); |
|
|
|
// repaint all buttons (to update background) |
|
QValueList< ToolboxButton * >::iterator it = m_buttons.begin(), end = m_buttons.end(); |
|
for ( ; it != end; ++it ) |
|
(*it)->update(); |
|
|
|
//QWidget::show(); |
|
} |
|
|
|
void PageViewToolbox::buildGfx() |
|
{ |
|
int buttonsNumber = m_buttons.count(), |
|
parentWidth = m_anchor->width(), |
|
parentHeight = m_anchor->height(), |
|
myCols = 1, |
|
myRows = 1; |
|
|
|
// 1. find out columns and rows we're going to use |
|
bool m_vertical = m_side == Left || m_side == Right; |
|
if ( m_vertical ) |
|
{ |
|
myCols = 1 + (buttonsNumber * ToolboxGridSize) / |
|
(parentHeight - ToolboxGridSize); |
|
myRows = (int)ceilf( (float)buttonsNumber / (float)myCols ); |
|
} |
|
else |
|
{ |
|
myRows = 1 + (buttonsNumber * ToolboxGridSize) / |
|
(parentWidth - ToolboxGridSize); |
|
myCols = (int)ceilf( (float)buttonsNumber / (float)myRows ); |
|
} |
|
|
|
// 2. compute widget size (from rows/cols) |
|
int myWidth = myCols * ToolboxGridSize, |
|
myHeight = myRows * ToolboxGridSize, |
|
xOffset = (ToolboxGridSize - ToolboxButtonSize) / 2, |
|
yOffset = (ToolboxGridSize - ToolboxButtonSize) / 2; |
|
|
|
if ( m_vertical ) |
|
{ |
|
myHeight += 16; |
|
myWidth += 4; |
|
yOffset += 12; |
|
if ( m_side == Right ) |
|
xOffset += 4; |
|
} |
|
else |
|
{ |
|
myWidth += 16; |
|
myHeight += 4; |
|
xOffset += 12; |
|
if ( m_side == Bottom ) |
|
yOffset += 4; |
|
} |
|
|
|
// 3. resize pixmap, mask and widget |
|
static QBitmap mask; |
|
mask.resize( myWidth, myHeight ); |
|
m_pixmap.resize( myWidth, myHeight ); |
|
resize( myWidth, myHeight ); |
|
|
|
// 4. create and set transparency mask |
|
QPainter maskPainter( &mask); |
|
mask.fill( Qt::black ); |
|
maskPainter.setBrush( Qt::white ); |
|
if ( m_side == Left ) |
|
maskPainter.drawRoundRect( -10, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight ); |
|
else if ( m_side == Top ) |
|
maskPainter.drawRoundRect( 0, -10, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10) ); |
|
else if ( m_side == Right ) |
|
maskPainter.drawRoundRect( 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight ); |
|
else // ( m_side == Bottom ) |
|
maskPainter.drawRoundRect( 0, 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10) ); |
|
setMask( mask ); |
|
|
|
// 5. draw background |
|
QPainter bufferPainter( &m_pixmap ); |
|
QPixmap gradientPattern; |
|
// 5.1. draw horizontal/vertical gradient |
|
if ( m_side == Left ) |
|
gradientPattern = KImageEffect::gradient( QSize( myWidth, 1), |
|
palette().active().button(), palette().active().light(), |
|
KImageEffect::HorizontalGradient ); |
|
else if ( m_side == Top ) |
|
gradientPattern = KImageEffect::gradient( QSize( 1, myHeight ), |
|
palette().active().button(), palette().active().light(), |
|
KImageEffect::VerticalGradient ); |
|
else if ( m_side == Right ) |
|
gradientPattern = KImageEffect::gradient( QSize( myWidth, 1), |
|
palette().active().light(), palette().active().button(), |
|
KImageEffect::HorizontalGradient ); |
|
else // ( m_side == Bottom ) |
|
gradientPattern = KImageEffect::gradient( QSize( 1, myHeight ), |
|
palette().active().light(), palette().active().button(), |
|
KImageEffect::VerticalGradient ); |
|
bufferPainter.drawTiledPixmap( 0, 0, myWidth, myHeight, gradientPattern ); |
|
// 5.2. draw rounded border |
|
bufferPainter.setPen( palette().active().dark() ); |
|
if ( m_side == Left ) |
|
bufferPainter.drawRoundRect( -10, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight ); |
|
else if ( m_side == Top ) |
|
bufferPainter.drawRoundRect( 0, -10, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10) ); |
|
else if ( m_side == Right ) |
|
bufferPainter.drawRoundRect( 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight ); |
|
else // ( m_side == Bottom ) |
|
bufferPainter.drawRoundRect( 0, 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10) ); |
|
// 5.3. draw handle |
|
bufferPainter.setPen( palette().active().mid() ); |
|
if ( m_vertical ) |
|
{ |
|
int dx = m_side == Left ? 2 : 4; |
|
bufferPainter.drawLine( dx, 6, dx + myWidth - 8, 6 ); |
|
bufferPainter.drawLine( dx, 9, dx + myWidth - 8, 9 ); |
|
bufferPainter.setPen( palette().active().light() ); |
|
bufferPainter.drawLine( dx + 1, 7, dx + myWidth - 7, 7 ); |
|
bufferPainter.drawLine( dx + 1, 10, dx + myWidth - 7, 10 ); |
|
} |
|
else |
|
{ |
|
int dy = m_side == Top ? 2 : 4; |
|
bufferPainter.drawLine( 6, dy, 6, dy + myHeight - 8 ); |
|
bufferPainter.drawLine( 9, dy, 9, dy + myHeight - 8 ); |
|
bufferPainter.setPen( palette().active().light() ); |
|
bufferPainter.drawLine( 7, dy + 1, 7, dy + myHeight - 7 ); |
|
bufferPainter.drawLine( 10, dy + 1, 10, dy + myHeight - 7 ); |
|
} |
|
|
|
// 6. reposition buttons (in rows/col grid) |
|
int gridX = 0, |
|
gridY = 0; |
|
QValueList< ToolboxButton * >::iterator it = m_buttons.begin(), end = m_buttons.end(); |
|
for ( ; it != end; ++it ) |
|
{ |
|
ToolboxButton * button = *it; |
|
button->move( gridX * ToolboxGridSize + xOffset, |
|
gridY * ToolboxGridSize + yOffset ); |
|
if ( ++gridX == myCols ) |
|
{ |
|
gridX = 0; |
|
gridY++; |
|
} |
|
} |
|
} |
|
|
|
QPoint PageViewToolbox::getEndPoint() |
|
{ |
|
// returns the final position of the widget |
|
if ( m_side == Left ) |
|
return QPoint( 0, (m_anchor->height() - height()) / 2 ); |
|
if ( m_side == Top ) |
|
return QPoint( (m_anchor->width() - width()) / 2, 0 ); |
|
if ( m_side == Right ) |
|
return QPoint( m_anchor->width() - width() + AnchorRBMargin, (m_anchor->height() - height()) / 2 ); |
|
return QPoint( (m_anchor->width() - width()) / 2, m_anchor->height() - height() + AnchorRBMargin ); |
|
} |
|
|
|
QPoint PageViewToolbox::getStartPoint() |
|
{ |
|
// returns the point from which the transition starts |
|
if ( m_side == Left ) |
|
return QPoint( -width(), (m_anchor->height() - height()) / 2 ); |
|
if ( m_side == Top ) |
|
return QPoint( (m_anchor->width() - width()) / 2, -height() ); |
|
if ( m_side == Right ) |
|
return QPoint( m_anchor->width() + AnchorRBMargin, (m_anchor->height() - height()) / 2 ); |
|
return QPoint( (m_anchor->width() - width()) / 2, m_anchor->height() + AnchorRBMargin ); |
|
} |
|
|
|
void PageViewToolbox::slotButtonClicked() |
|
{ |
|
ToolboxButton * button = (ToolboxButton *)sender(); |
|
if ( button ) |
|
{ |
|
// deselect other buttons |
|
QValueList< ToolboxButton * >::iterator it = m_buttons.begin(), end = m_buttons.end(); |
|
for ( ; it != end; ++it ) |
|
if ( *it != button ) |
|
(*it)->setOn( false ); |
|
// emit signal (-1 if button has been unselected) |
|
emit toolSelected( button->isOn() ? button->toolboxID() : -1 ); |
|
} |
|
} |
|
|
|
|
|
/** PageViewEditTools **/ |
|
|
|
PageViewEditTools::PageViewEditTools( QWidget * parent, QWidget * anchorWidget ) |
|
: PageViewToolbox( parent, anchorWidget ) |
|
{ |
|
// create the ToolboxItems and show it on last place |
|
QValueList<ToolboxItem> items; |
|
items.push_back( ToolboxItem( 1, i18n("Text"), "pinnote" ) ); |
|
items.push_back( ToolboxItem( 2, i18n("Yellow Highlighter"), "highlight_yellow" ) ); |
|
items.push_back( ToolboxItem( 3, i18n("Orange Highlighter"), "highlight_orange" ) ); |
|
items.push_back( ToolboxItem( 4, i18n("Green Highlighter"), "highlight_green" ) ); |
|
items.push_back( ToolboxItem( 5, i18n("Pencil"), "pencil" ) ); |
|
items.push_back( ToolboxItem( 6, i18n("sbiancante"), "coprex-white" ) ); |
|
showItems( (Side)Settings::editToolboxPlacement(), items ); |
|
} |
|
|
|
void PageViewEditTools::orientationChanged( Side side ) |
|
{ |
|
// save position to the conficuration file |
|
Settings::setEditToolboxPlacement( (int)side ); |
|
} |
|
|
|
#include "pageviewtoolbox.moc"
|
|
|