lib

tktoolbarbutton.cpp

00001 /*
00002  * Kivio - Visual Modelling and Flowcharting
00003  * Copyright (C) 2000 theKompany.com
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 #include <tktoolbarbutton.h>
00021 
00022 #include <qtimer.h>
00023 #include <qtooltip.h>
00024 #include <qpopupmenu.h>
00025 #include <qcursor.h>
00026 #include <qpainter.h>
00027 #include <qdrawutil.h>
00028 #include <qstyle.h>
00029 
00030 #include <kdeversion.h>
00031 #include <kapplication.h>
00032 #include <kiconeffect.h>
00033 #include <kiconloader.h>
00034 #include <kglobalsettings.h>
00035 
00036 // Delay in ms before delayed popup pops up
00037 #define POPUP_DELAY 500
00038 
00039 class TKToolBarButton::TKToolBarButtonPrivate
00040 {
00041 public:
00042   TKToolBarButtonPrivate()
00043   {
00044     m_iconMode     = TK::IconOnly;
00045     m_isPopup      = false;
00046     m_isToggle     = false;
00047     m_isOn         = false;
00048     m_isRaised     = false;
00049     m_autoRaised   = true;
00050     ignoreNextMousePress = false;
00051 
00052     m_text         = QString::null;
00053     m_iconName     = QString::null;
00054     m_arrowPressed = false;
00055     m_delayTimer   = 0L;
00056     m_popup        = 0L;
00057 
00058     m_disabledIconName = QString::null;
00059     m_defaultIconName  = QString::null;
00060 
00061     m_instance = KGlobal::instance();
00062   }
00063 
00064   ~TKToolBarButtonPrivate()
00065   {
00066     delete m_delayTimer;
00067     m_delayTimer = 0;
00068   }
00069 
00070   bool    m_isPopup;
00071   bool    m_isToggle;
00072   bool    m_isOn;
00073   bool    m_isRaised;
00074   bool    m_autoRaised;
00075   bool    m_arrowPressed;
00076   bool    ignoreNextMousePress;
00077 
00078   QString m_text;
00079   QString m_iconName;
00080   QString m_disabledIconName;
00081   QString m_defaultIconName;
00082 
00083   TK::IconMode m_iconMode;
00084 
00085   QTimer     *m_delayTimer;
00086   QPopupMenu *m_popup;
00087 
00088   KInstance  *m_instance;
00089 };
00090 
00091 TKToolBarButton::TKToolBarButton( const QString& icon, const QString& txt,
00092                                         QWidget* parent, const char* name,
00093                                         KInstance *instance )
00094 : QToolButton(parent,name)
00095 {
00096   d = new TKToolBarButtonPrivate;
00097   d->m_text = txt;
00098   d->m_instance = instance;
00099 
00100   setFocusPolicy( NoFocus );
00101 
00102   connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
00103   connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
00104   connect(this, SIGNAL(released()), SLOT(slotReleased()) );
00105 
00106   installEventFilter(this);
00107 
00108   setIcon(icon);
00109   modeChange();
00110 }
00111 
00112 TKToolBarButton::TKToolBarButton( const QPixmap& pixmap, const QString& txt, QWidget* parent, const char* name )
00113 : QToolButton(parent,name )
00114 {
00115   d = new TKToolBarButtonPrivate;
00116   d->m_text = txt;
00117 
00118   setFocusPolicy( NoFocus );
00119 
00120   connect(this, SIGNAL(clicked()), SLOT(slotClicked()) );
00121   connect(this, SIGNAL(pressed()), SLOT(slotPressed()) );
00122   connect(this, SIGNAL(released()), SLOT(slotReleased()) );
00123 
00124   installEventFilter(this);
00125 
00126   setPixmap(pixmap);
00127   modeChange();
00128 }
00129 
00130 TKToolBarButton::~TKToolBarButton()
00131 {
00132   delete d;
00133 }
00134 
00135 QString TKToolBarButton::text()
00136 {
00137   return d->m_text;
00138 }
00139 
00140 void TKToolBarButton::modeChange()
00141 {
00142   QToolTip::add(this,d->m_text);
00143 
00144   int border = 3;
00145   int w = 2*border;
00146   int h = 2*border;
00147 
00148   if (pixmap()) {
00149     w += pixmap()->width();
00150     h = QMAX(h,pixmap()->height()+2*border);
00151     if (d->m_iconMode == TK::IconAndText && !d->m_text.isEmpty())
00152       w += border;
00153   }
00154 
00155   if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty())
00156   {
00157     QFont tmp_font = KGlobalSettings::toolBarFont();
00158     QFontMetrics fm(tmp_font);
00159 
00160     h = QMAX(h,fm.lineSpacing()+2*border);
00161     w += fm.width(d->m_text);
00162   }
00163 
00164   if (d->m_popup && !d->m_isToggle)
00165     w += 11;
00166 
00167   QSize size(w,h);
00168   setMinimumSize(size);
00169 
00170   updateGeometry();
00171 }
00172 
00173 void TKToolBarButton::setEnabled( bool enabled )
00174 {
00175   if (isEnabled()==enabled)
00176     return;
00177 
00178   QToolButton::setPixmap( (enabled ? defaultPixmap : disabledPixmap) );
00179   QToolButton::setEnabled( enabled );
00180 }
00181 
00182 void TKToolBarButton::setText( const QString& text)
00183 {
00184   d->m_text = text;
00185   repaint(false);
00186 }
00187 
00188 void TKToolBarButton::setIcon( const QString& icon )
00189 {
00190   d->m_iconName = icon;
00191   int iconSize = 16;
00192 
00193   setPixmap( BarIcon(icon, iconSize, KIcon::ActiveState, d->m_instance), false );
00194   setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
00195   setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
00196 }
00197 
00198 void TKToolBarButton::setDisabledIcon( const QString &icon )
00199 {
00200   d->m_disabledIconName = icon;
00201   int iconSize = 16;
00202   setDisabledPixmap( BarIcon(icon, iconSize, KIcon::DisabledState, d->m_instance) );
00203 }
00204 
00205 void TKToolBarButton::setDefaultIcon( const QString &icon )
00206 {
00207   d->m_defaultIconName = icon;
00208   int iconSize = 16;
00209   setDefaultPixmap( BarIcon(icon, iconSize, KIcon::DefaultState, d->m_instance) );
00210 }
00211 
00212 QPixmap TKToolBarButton::getActivePixmap() const
00213 {
00214   return activePixmap;
00215 }
00216 
00217 void TKToolBarButton::setPixmap( const QPixmap &pixmap )
00218 {
00219   setPixmap( pixmap, true );
00220 }
00221 
00222 void TKToolBarButton::setPixmap( const QPixmap &pixmap, bool generate )
00223 {
00224   activePixmap = pixmap;
00225 
00226   if ( generate )
00227   {
00228     makeDefaultPixmap();
00229     makeDisabledPixmap();
00230   }
00231   else
00232   {
00233     if (defaultPixmap.isNull())
00234       defaultPixmap = activePixmap;
00235     if (disabledPixmap.isNull())
00236       disabledPixmap = activePixmap;
00237   }
00238 
00239   QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00240 }
00241 
00242 void TKToolBarButton::setDefaultPixmap( const QPixmap &pixmap )
00243 {
00244   defaultPixmap = pixmap;
00245   QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00246 }
00247 
00248 void TKToolBarButton::setDisabledPixmap( const QPixmap &pixmap )
00249 {
00250   disabledPixmap = pixmap;
00251   QToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
00252 }
00253 
00254 void TKToolBarButton::setPopup(QPopupMenu *p)
00255 {
00256   d->m_popup = p;
00257   d->m_popup->setFont(KGlobalSettings::toolBarFont());
00258   p->installEventFilter(this);
00259 
00260   modeChange();
00261 }
00262 
00263 QPopupMenu *TKToolBarButton::popup()
00264 {
00265   return d->m_popup;
00266 }
00267 
00268 void TKToolBarButton::setDelayedPopup (QPopupMenu *p, bool toggle )
00269 {
00270   d->m_isPopup = true;
00271   setToggle(toggle);
00272 
00273   if (!d->m_delayTimer) {
00274     d->m_delayTimer = new QTimer(this);
00275     connect(d->m_delayTimer, SIGNAL(timeout()), this, SLOT(slotDelayTimeout()));
00276   }
00277 
00278   setPopup(p);
00279 }
00280 
00281 void TKToolBarButton::setRaised(bool f)
00282 {
00283   d->m_isRaised = f;
00284   repaint(false);
00285 }
00286 
00287 void TKToolBarButton::setAutoRaised(bool f)
00288 {
00289   d->m_autoRaised = f;
00290 }
00291 
00292 void TKToolBarButton::leaveEvent(QEvent *)
00293 {
00294   if (!d->m_isToggle && !(d->m_popup && d->m_popup->isVisible()) ) {
00295     QToolButton::setPixmap(isEnabled() ? defaultPixmap : disabledPixmap);
00296     if (d->m_autoRaised)
00297       setRaised(false);
00298   }
00299 }
00300 
00301 void TKToolBarButton::enterEvent(QEvent *)
00302 {
00303   if (!d->m_isToggle) {
00304     if (isEnabled()) {
00305       QToolButton::setPixmap(activePixmap);
00306       if (d->m_autoRaised)
00307         setRaised(true);
00308     } else {
00309       QToolButton::setPixmap(disabledPixmap);
00310     }
00311     repaint(false);
00312   }
00313 }
00314 
00315 bool TKToolBarButton::eventFilter(QObject *o, QEvent *ev)
00316 {
00317   if ( o == this )
00318     if (ev->type() == QEvent::MouseButtonPress && d->m_popup && d->m_isPopup ) {
00319       if (!d->m_isToggle) {
00320         d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
00321       } else {
00322         d->m_delayTimer->start(POPUP_DELAY);
00323       }
00324     }
00325 
00326   if ( o == d->m_popup) {
00327     switch (ev->type())
00328     {
00329       case QEvent::Show:
00330         on(true);
00331         return false;
00332       case QEvent::Hide:
00333         on(false);
00334         setDown(false);
00335         if ( !geometry().contains(parentWidget()->mapFromGlobal(QCursor::pos())) )
00336           leaveEvent(0L);
00337         return false;
00338         break;
00339       case QEvent::MouseButtonPress: {
00340         d->m_arrowPressed = arrowPressed( mapFromGlobal(QCursor::pos()) );
00341         d->ignoreNextMousePress = d->m_arrowPressed;
00342         break;
00343       }
00344       default:
00345         break;
00346     }
00347   }
00348   return false;
00349 }
00350 
00351 void TKToolBarButton::drawButton( QPainter* p )
00352 {
00353 #define DRAW_PIXMAP_AND_TEXT \
00354   int x = 3;\
00355   if (pixmap()) {\
00356     style().drawItem( p, QRect( x, 0, pixmap()->width(), height() ), AlignCenter, colorGroup(), isEnabled(), pixmap(), QString::null );\
00357     if (d->m_iconMode==TK::IconAndText && !d->m_text.isEmpty()) {\
00358       x += pixmap()->width() + 3;\
00359     }\
00360   }\
00361   if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) {\
00362     QFontMetrics fm(KGlobalSettings::toolBarFont());\
00363     style().drawItem( p, QRect( x, 0, fm.width(d->m_text), height() ), AlignCenter, colorGroup(), isEnabled(), 0, d->m_text );\
00364   }
00365 
00366   const char* arrow[] = {
00367   "7 4 2 1",
00368   "# c Black",
00369   ". c None",
00370   "#######",
00371   ".#####.",
00372   "..###..",
00373   "...#..."};
00374   QPixmap arrow_pix(arrow);
00375   bool f = d->m_isOn || isDown();
00376 
00377     if (d->m_popup && !d->m_isToggle)
00378     {
00379         if (d->m_isPopup)
00380         {
00381             QStyle::SFlags flags   = QStyle::Style_Default;
00382             if (isEnabled())    flags |= QStyle::Style_Enabled;
00383             if (isOn())         flags |= QStyle::Style_On;
00384             if (d->m_isRaised)  flags |= QStyle::Style_Raised;
00385             if (hasFocus()) flags |= QStyle::Style_HasFocus;
00386 
00387             style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( 0, 0, width()-12, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
00388             style().drawComplexControl( QStyle::CC_ToolButton, p, this, QRect( width()-13, 0, 13, height() ), colorGroup(), flags, QStyle::SC_ToolButton );
00389             style().drawItem( p, QRect( width()-13, 0, 13, height() ), AlignCenter, colorGroup(), isEnabled(), &arrow_pix, QString::null );
00390             if ( d->m_isRaised )
00391                 qDrawShadeLine( p, width()-12, 0, width()-12, height(), colorGroup(), true );
00392             DRAW_PIXMAP_AND_TEXT
00393         } else {
00394             style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
00395             DRAW_PIXMAP_AND_TEXT
00396             int z = f ? 1:0;
00397             p->drawPixmap(width()-11+z,(height()-4)/2+z ,arrow_pix);
00398         }
00399     } else {
00400         style().drawControl( QStyle::CE_PushButton, p, this, QRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
00401         DRAW_PIXMAP_AND_TEXT
00402     }
00403 }
00404 
00405 void TKToolBarButton::paletteChange(const QPalette &)
00406 {
00407   makeDisabledPixmap();
00408   if ( !isEnabled() )
00409     QToolButton::setPixmap( disabledPixmap );
00410   else
00411     QToolButton::setPixmap( defaultPixmap );
00412   repaint(false);
00413 }
00414 
00415 void TKToolBarButton::makeDefaultPixmap()
00416 {
00417   if (activePixmap.isNull())
00418     return;
00419 
00420   KIconEffect effect;
00421   defaultPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DefaultState);
00422 }
00423 
00424 void TKToolBarButton::makeDisabledPixmap()
00425 {
00426   if (activePixmap.isNull())
00427     return;
00428 
00429   KIconEffect effect;
00430   disabledPixmap = effect.apply(activePixmap, KIcon::Toolbar, KIcon::DisabledState);
00431 }
00432 
00433 QSize TKToolBarButton::sizeHint() const
00434 {
00435     return minimumSize();
00436 }
00437 
00438 QSize TKToolBarButton::minimumSizeHint() const
00439 {
00440     return minimumSize();
00441 }
00442 
00443 void TKToolBarButton::showMenu()
00444 {
00445   QPoint p ( mapToGlobal( QPoint( 0, 0 ) ) );
00446   const int deskHeight = KGlobalSettings::desktopGeometry(this).height();
00447   if ( p.y() + height() + d->m_popup->height() > deskHeight )
00448       p.setY( p.y() - d->m_popup->height() );
00449   else
00450       p.setY( p.y() + height( ));
00451 
00452   d->m_popup->popup(p);
00453 }
00454 
00455 void TKToolBarButton::slotDelayTimeout()
00456 {
00457   d->m_delayTimer->stop();
00458   showMenu();
00459 }
00460 
00461 void TKToolBarButton::slotClicked()
00462 {
00463   if ( d->ignoreNextMousePress ) {
00464     d->ignoreNextMousePress=false;
00465     return;
00466   }
00467 
00468   if (d->m_popup && !d->m_isPopup)
00469     showMenu();
00470   else
00471     emit buttonClicked();
00472 }
00473 
00474 void TKToolBarButton::slotPressed()
00475 {
00476   if ( d->ignoreNextMousePress )
00477     return;
00478 
00479   if (d->m_popup) {
00480     if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed)
00481       showMenu();
00482   }
00483   else
00484     emit buttonPressed();
00485 
00486   d->ignoreNextMousePress = false;
00487 }
00488 
00489 void TKToolBarButton::slotReleased()
00490 {
00491   if (d->m_popup && d->m_isPopup)
00492     d->m_delayTimer->stop();
00493 
00494   emit buttonReleased();
00495 }
00496 
00497 void TKToolBarButton::slotToggled()
00498 {
00499   emit buttonToggled();
00500 }
00501 
00502 void TKToolBarButton::on(bool flag)
00503 {
00504   d->m_isOn = flag;
00505   repaint();
00506 }
00507 
00508 void TKToolBarButton::toggle()
00509 {
00510   on(!d->m_isOn);
00511 }
00512 
00513 void TKToolBarButton::setToggle(bool flag)
00514 {
00515   d->m_isToggle = flag;
00516   if (flag == true)
00517     connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00518   else
00519     disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
00520 
00521   modeChange();
00522   repaint();
00523 }
00524 
00525 void TKToolBarButton::setIconMode( TK::IconMode m )
00526 {
00527   d->m_iconMode = m;
00528   modeChange();
00529   repaint();
00530 }
00531 
00532 #include <tktoolbarbutton.moc>
KDE Home | KDE Accessibility Home | Description of Access Keys