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.
koffice/lib/kofficeui/tktoolbarbutton.cpp

533 lines
13 KiB

/*
* Kivio - Visual Modelling and Flowcharting
* Copyright (C) 2000 theKompany.com
*
* 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 <tktoolbarbutton.h>
#include <qtimer.h>
#include <qtooltip.h>
#include <qpopupmenu.h>
#include <qcursor.h>
#include <qpainter.h>
#include <qdrawutil.h>
#include <qstyle.h>
#include <kdeversion.h>
#include <kapplication.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <kglobalsettings.h>
// Delay in ms before delayed popup pops up
#define POPUP_DELAY 500
class TKToolBarButton::TKToolBarButtonPrivate
{
public:
TKToolBarButtonPrivate()
{
m_iconMode = TK::IconOnly;
m_isPopup = false;
m_isToggle = false;
m_isOn = false;
m_isRaised = false;
m_autoRaised = true;
ignoreNextMousePress = false;
m_text = QString::null;
m_iconName = QString::null;
m_arrowPressed = false;
m_delayTimer = 0L;
m_popup = 0L;
m_disabledIconName = QString::null;
m_defaultIconName = QString::null;
m_instance = KGlobal::instance();
}
~TKToolBarButtonPrivate()
{
delete m_delayTimer;
m_delayTimer = 0;
}
bool m_isPopup;
bool m_isToggle;
bool m_isOn;
bool m_isRaised;
bool m_autoRaised;
bool m_arrowPressed;
bool ignoreNextMousePress;
QString m_text;
QString m_iconName;
QString m_disabledIconName;
QString m_defaultIconName;
TK::IconMode m_iconMode;
QTimer *m_delayTimer;
QPopupMenu *m_popup;
KInstance *m_instance;
};
TKToolBarButton::TKToolBarButton( const QString& icon, const QString& txt,
QWidget* parent, const char* name,
KInstance *instance )
: QToolButton(parent,name)
{
d = new TKToolBarButtonPrivate;
d->m_text = txt;
d->m_instance = instance;
setFocusPolicy( NoFocus );
connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
connect(this, SIGNAL(released()), SLOT(slotReleased()) );
installEventFilter(this);
setIcon(icon);
modeChange();
}
TKToolBarButton::TKToolBarButton( const QPixmap& pixmap, const QString& txt, QWidget* parent, const char* name )
: QToolButton(parent,name )
{
d = new TKToolBarButtonPrivate;
d->m_text = txt;
setFocusPolicy( NoFocus );
connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
connect(this, SIGNAL(released()), SLOT(slotReleased()) );
installEventFilter(this);
setPixmap(pixmap);
modeChange();
}
TKToolBarButton::~TKToolBarButton()
{
delete d;
}
QString TKToolBarButton::text()
{
return d->m_text;
}
void TKToolBarButton::modeChange()
{
QToolTip::add(this,d->m_text);
int border = 3;
int w = 2*border;
int h = 2*border;
if (pixmap()) {
w += pixmap()->width();
h = QMAX(h,pixmap()->height()+2*border);
if (d->m_iconMode == TK::IconAndText && !d->m_text.isEmpty())
w += border;
}
if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty())
{
QFont tmp_font = KGlobalSettings::toolBarFont();
QFontMetrics fm(tmp_font);
h = QMAX(h,fm.lineSpacing()+2*border);
w += fm.width(d->m_text);
}
if (d->m_popup && !d->m_isToggle)
w += 11;
QSize size(w,h);
setMinimumSize(size);
updateGeometry();
}
void TKToolBarButton::setEnabled( bool enabled )
{
if (isEnabled()==enabled)
return;
QToolButton::setPixmap( (enabled ? defaultPixmap : disabledPixmap) );
QToolButton::setEnabled( enabled );
}
void TKToolBarButton::setText( const QString& text)
{
d->m_text = text;
repaint(false);
}
void TKToolBarButton::setIcon( const QString& icon )
{
d->m_iconName = icon;
int iconSize = 16;
setPixmap( BarIcon(icon, iconSize, KIcon::ActiveState, d->m_instance), false );
setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
}
void TKToolBarButton::setDisabledIcon( const QString &icon )
{
d->m_disabledIconName = icon;
int iconSize = 16;
setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
}
void TKToolBarButton::setDefaultIcon( const QString &icon )
{
d->m_defaultIconName = icon;
int iconSize = 16;
setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
}
QPixmap TKToolBarButton::getActivePixmap() const
{
return activePixmap;
}
void TKToolBarButton::setPixmap( const QPixmap &pixmap )
{
setPixmap( pixmap, true );
}
void TKToolBarButton::setPixmap( const QPixmap &pixmap, bool generate )
{
activePixmap = pixmap;
if ( generate )
{
makeDefaultPixmap();
makeDisabledPixmap();
}
else
{
if (defaultPixmap.isNull())
defaultPixmap = activePixmap;
if (disabledPixmap.isNull())
disabledPixmap = activePixmap;
}
QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}
void TKToolBarButton::setDefaultPixmap( const QPixmap &pixmap )
{
defaultPixmap = pixmap;
QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}
void TKToolBarButton::setDisabledPixmap( const QPixmap &pixmap )
{
disabledPixmap = pixmap;
QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}
void TKToolBarButton::setPopup(QPopupMenu *p)
{
d->m_popup = p;
d->m_popup->setFont(KGlobalSettings::toolBarFont());
p->installEventFilter(this);
modeChange();
}
QPopupMenu *TKToolBarButton::popup()
{
return d->m_popup;
}
void TKToolBarButton::setDelayedPopup (QPopupMenu *p, bool toggle )
{
d->m_isPopup = true;
setToggle(toggle);
if (!d->m_delayTimer) {
d->m_delayTimer = new QTimer(this);
connect(d->m_delayTimer, SIGNAL(timeout()), this, SLOT(slotDelayTimeout()));
}
setPopup(p);
}
void TKToolBarButton::setRaised(bool f)
{
d->m_isRaised = f;
repaint(false);
}
void TKToolBarButton::setAutoRaised(bool f)
{
d->m_autoRaised = f;
}
void TKToolBarButton::leaveEvent(QEvent *)
{
if (!d->m_isToggle && !(d->m_popup && d->m_popup->isVisible()) ) {
QToolButton::setPixmap(isEnabled() ? defaultPixmap : disabledPixmap);
if (d->m_autoRaised)
setRaised(false);
}
}
void TKToolBarButton::enterEvent(QEvent *)
{
if (!d->m_isToggle) {
if (isEnabled()) {
QToolButton::setPixmap(activePixmap);
if (d->m_autoRaised)
setRaised(true);
} else {
QToolButton::setPixmap(disabledPixmap);
}
repaint(false);
}
}
bool TKToolBarButton::eventFilter(QObject *o, QEvent *ev)
{
if ( o == this )
if (ev->type() == QEvent::MouseButtonPress && d->m_popup && d->m_isPopup ) {
if (!d->m_isToggle) {
d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
} else {
d->m_delayTimer->start(POPUP_DELAY);
}
}
if ( o == d->m_popup) {
switch (ev->type())
{
case QEvent::Show:
on(true);
return false;
case QEvent::Hide:
on(false);
setDown(false);
if ( !geometry().contains(parentWidget()->mapFromGlobal(QCursor::pos())) )
leaveEvent(0L);
return false;
break;
case QEvent::MouseButtonPress: {
d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
d->ignoreNextMousePress = d->m_arrowPressed;
break;
}
default:
break;
}
}
return false;
}
void TKToolBarButton::drawButton( QPainter* p )
{
#define DRAW_PIXMAP_AND_TEXT \
int x = 3;\
if (pixmap()) {\
style().drawItem( p, QRect( x, 0, pixmap()->width(), height() ), AlignCenter, colorGroup(), isEnabled(), pixmap(), QString::null );\
if (d->m_iconMode==TK::IconAndText && !d->m_text.isEmpty()) {\
x += pixmap()->width() + 3;\
}\
}\
if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) {\
QFontMetrics fm(KGlobalSettings::toolBarFont());\
style().drawItem( p, QRect( x, 0, fm.width(d->m_text), height() ), AlignCenter, colorGroup(), isEnabled(), 0, d->m_text );\
}
const char* arrow[] = {
"7 4 2 1",
"# c Black",
". c None",
"#######",
".#####.",
"..###..",
"...#..."};
QPixmap arrow_pix(arrow);
bool f = d->m_isOn || isDown();
if (d->m_popup && !d->m_isToggle)
{
if (d->m_isPopup)
{
QStyle::SFlags flags = QStyle::Style_Default;
if (isEnabled()) flags |= QStyle::Style_Enabled;
if (isOn()) flags |= QStyle::Style_On;
if (d->m_isRaised) flags |= QStyle::Style_Raised;
if (hasFocus()) flags |= QStyle::Style_HasFocus;
style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( 0, 0, width()-12, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( width()-13, 0, 13, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
style().drawItem( p, QRect( width()-13, 0, 13, height() ), AlignCenter, colorGroup(), isEnabled(), &arrow_pix, QString::null );
if ( d->m_isRaised )
qDrawShadeLine( p, width()-12, 0, width()-12, height(), colorGroup(), true );
DRAW_PIXMAP_AND_TEXT
} else {
style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
DRAW_PIXMAP_AND_TEXT
int z = f ? 1:0;
p->drawPixmap(width()-11+z,(height()-4)/2+z ,arrow_pix);
}
} else {
style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
DRAW_PIXMAP_AND_TEXT
}
}
void TKToolBarButton::paletteChange(const QPalette &)
{
makeDisabledPixmap();
if ( !isEnabled() )
QToolButton::setPixmap( disabledPixmap );
else
QToolButton::setPixmap( defaultPixmap );
repaint(false);
}
void TKToolBarButton::makeDefaultPixmap()
{
if (activePixmap.isNull())
return;
KIconEffect effect;
defaultPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DefaultState);
}
void TKToolBarButton::makeDisabledPixmap()
{
if (activePixmap.isNull())
return;
KIconEffect effect;
disabledPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DisabledState);
}
QSize TKToolBarButton::sizeHint() const
{
return minimumSize();
}
QSize TKToolBarButton::minimumSizeHint() const
{
return minimumSize();
}
void TKToolBarButton::showMenu()
{
QPoint p ( mapToGlobal( QPoint( 0, 0 ) ) );
const int deskHeight = KGlobalSettings::desktopGeometry(this).height();
if ( p.y() + height() + d->m_popup->height() > deskHeight )
p.setY( p.y() - d->m_popup->height() );
else
p.setY( p.y() + height( ));
d->m_popup->popup(p);
}
void TKToolBarButton::slotDelayTimeout()
{
d->m_delayTimer->stop();
showMenu();
}
void TKToolBarButton::slotClicked()
{
if ( d->ignoreNextMousePress ) {
d->ignoreNextMousePress=false;
return;
}
if (d->m_popup && !d->m_isPopup)
showMenu();
else
emit buttonClicked();
}
void TKToolBarButton::slotPressed()
{
if ( d->ignoreNextMousePress )
return;
if (d->m_popup) {
if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed)
showMenu();
}
else
emit buttonPressed();
d->ignoreNextMousePress = false;
}
void TKToolBarButton::slotReleased()
{
if (d->m_popup && d->m_isPopup)
d->m_delayTimer->stop();
emit buttonReleased();
}
void TKToolBarButton::slotToggled()
{
emit buttonToggled();
}
void TKToolBarButton::on(bool flag)
{
d->m_isOn = flag;
repaint();
}
void TKToolBarButton::toggle()
{
on(!d->m_isOn);
}
void TKToolBarButton::setToggle(bool flag)
{
d->m_isToggle = flag;
if (flag == true)
connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
else
disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
modeChange();
repaint();
}
void TKToolBarButton::setIconMode( TK::IconMode m )
{
d->m_iconMode = m;
modeChange();
repaint();
}
#include <tktoolbarbutton.moc>