ctkMenuButton.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Library:   CTK
00004  
00005   Copyright (c) 2010  Kitware Inc.
00006 
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at
00010 
00011       http://www.commontk.org/LICENSE
00012 
00013   Unless required by applicable law or agreed to in writing, software
00014   distributed under the License is distributed on an "AS IS" BASIS,
00015   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016   See the License for the specific language governing permissions and
00017   limitations under the License.
00018  
00019 =========================================================================*/
00020 
00021 // Qt includes
00022 #include <QApplication>
00023 #include <QCleanlooksStyle>
00024 #include <QDebug>
00025 #include <QDesktopWidget>
00026 #include <QLayout>
00027 #include <QMouseEvent>
00028 #include <QMenu>
00029 #include <QPainter>
00030 #include <QPointer>
00031 #include <QPushButton>
00032 #include <QStyle>
00033 #include <QStyleOptionButton>
00034 #include <QStylePainter>
00035 #include <QToolBar>
00036 
00037 // CTK includes
00038 #include "ctkMenuButton.h"
00039 
00040 //-----------------------------------------------------------------------------
00041 class ctkMenuButtonPrivate : public ctkPrivate<ctkMenuButton>
00042 {
00043 public:
00044   CTK_DECLARE_PUBLIC(ctkMenuButton);
00045   ctkMenuButtonPrivate();
00046 
00047   QRect indicatorRect() const;
00048   bool ShowMenu;
00049 };
00050 
00051 //-----------------------------------------------------------------------------
00052 ctkMenuButtonPrivate::ctkMenuButtonPrivate()
00053 {
00054   this->ShowMenu = false;
00055 }
00056 
00057 //-----------------------------------------------------------------------------
00058 QRect ctkMenuButtonPrivate::indicatorRect()const
00059 {
00060   CTK_P(const ctkMenuButton);
00061   
00062   QStyleOptionButton option;
00063   p->initStyleOption(&option);
00064 
00065   QRect downArrowRect = p->style()->visualRect(option.direction, option.rect, option.rect);
00066   downArrowRect.setRect(downArrowRect.right() - 13, downArrowRect.top(),
00067                         14, downArrowRect.height());
00068   downArrowRect = p->style()->visualRect(option.direction, option.rect, downArrowRect);
00069   return downArrowRect;
00070 }
00071 
00072 //-----------------------------------------------------------------------------
00073 ctkMenuButton::ctkMenuButton(QWidget* _parent)
00074   :QPushButton(_parent)
00075 {
00076   CTK_INIT_PRIVATE(ctkMenuButton);
00077 }
00078 
00079 //-----------------------------------------------------------------------------
00080 ctkMenuButton::ctkMenuButton(const QString& title, QWidget* _parent)
00081   :QPushButton(title, _parent)
00082 {
00083   CTK_INIT_PRIVATE(ctkMenuButton);
00084 }
00085 
00086 //-----------------------------------------------------------------------------
00087 ctkMenuButton::~ctkMenuButton()
00088 {
00089 }
00090 
00091 //-----------------------------------------------------------------------------
00092 QSize ctkMenuButton::minimumSizeHint()const
00093 {
00094   QSize min = QPushButton::minimumSizeHint();
00095   return QSize(min.width() + 13, min.height());
00096 }
00097 
00098 //-----------------------------------------------------------------------------
00099 QSize ctkMenuButton::sizeHint()const
00100 {
00101   QSize buttonSizeHint = QPushButton::sizeHint();
00102   return QSize(buttonSizeHint.width() + 13, buttonSizeHint.height());
00103 }
00104 
00105 //-----------------------------------------------------------------------------
00106 void ctkMenuButton::paintEvent(QPaintEvent * _event)
00107 {
00108   Q_UNUSED(_event);
00109   CTK_D(ctkMenuButton);
00110   QStylePainter painter(this);
00111   QStyleOptionButton option;
00112   initStyleOption(&option);
00113   bool drawIndicatorBackground = 
00114     option.state & QStyle::State_Sunken || 
00115     option.state & QStyle::State_On;
00116   // Draw button
00117   option.features &= ~QStyleOptionButton::HasMenu;
00118   if (this->menu() && (this->menu()->isVisible() || d->ShowMenu))
00119     {
00120     option.state &= ~QStyle::State_Sunken;
00121     option.state |= QStyle::State_Raised;
00122     }
00123   painter.drawControl(QStyle::CE_PushButtonBevel, option);
00124   // is PE_PanelButtonCommand better ?
00125   //painter.drawPrimitive(QStyle::PE_PanelButtonCommand, option);
00126   QRect downArrowRect = d->indicatorRect();
00127   if (drawIndicatorBackground)
00128     {    
00129     // if the button is down, draw the part under the indicator up
00130     QPixmap cache = QPixmap(option.rect.size());
00131     cache.fill(Qt::transparent);
00132     QPainter cachePainter(&cache);
00133     option.state &= ~QStyle::State_Sunken;
00134     option.state |= QStyle::State_Raised;
00135     option.state &= ~QStyle::State_On;
00136     option.state |= QStyle::State_Off;
00137     //option.state &= ~QStyle::State_HasFocus;
00138     option.state &= ~QStyle::State_MouseOver;
00139     this->style()->drawControl(QStyle::CE_PushButtonBevel, &option, &cachePainter, this);
00140     painter.drawItemPixmap(downArrowRect, Qt::AlignLeft | Qt::AlignTop, cache.copy(downArrowRect)); 
00141     }
00142 
00143   // Separator
00144   // Freely inspired by the painting of CC_ComboBox in qcleanlooksstyle.cpp 
00145   
00146   QColor buttonColor = this->palette().button().color();
00147   QColor darkColor;
00148   darkColor.setHsv(buttonColor.hue(),
00149                    qMin(255, (int)(buttonColor.saturation()*1.9)),
00150                    qMin(255, (int)(buttonColor.value()*0.7)));
00151   painter.setPen(buttonColor.darker(130));
00152   int borderSize = 2;
00153   painter.drawLine(QPoint(downArrowRect.left() - 1, downArrowRect.top() + borderSize),
00154                    QPoint(downArrowRect.left() - 1, downArrowRect.bottom() - borderSize));
00155   painter.setPen(this->palette().light().color());
00156   painter.drawLine(QPoint(downArrowRect.left(), downArrowRect.top() + borderSize),
00157                    QPoint(downArrowRect.left(), downArrowRect.bottom() - borderSize));
00158   // Draw arrow
00159   QStyleOption indicatorOpt;
00160   indicatorOpt.init(this);
00161   indicatorOpt.rect = downArrowRect.adjusted(borderSize, borderSize, -borderSize, -borderSize);
00162   painter.drawPrimitive(QStyle::PE_IndicatorArrowDown, indicatorOpt);
00163 
00164   // Draw Icon & Text
00165   option.rect.setRight( downArrowRect.left());
00166   painter.drawControl(QStyle::CE_PushButtonLabel, option);
00167 }
00168 
00169 //-----------------------------------------------------------------------------
00170 bool ctkMenuButton::hitButton(const QPoint & _pos)const
00171 {
00172   CTK_D(const ctkMenuButton);
00173   return !d->indicatorRect().contains(_pos) 
00174     && this->QPushButton::hitButton(_pos);
00175 }
00176 
00177 //-----------------------------------------------------------------------------
00178 void ctkMenuButton::initStyleOption(QStyleOptionButton* option)const
00179 {
00180   this->QPushButton::initStyleOption(option);
00181 }
00182 
00183 //-----------------------------------------------------------------------------
00184 void ctkMenuButton::mousePressEvent(QMouseEvent *e)
00185 {
00186   CTK_D(ctkMenuButton);
00187   // we don't want to open the menu if the mouse is clicked anywhere on
00188   // the button, only if it's clicked on the indecator
00189   this->disconnect(this,SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
00190   this->QPushButton::mousePressEvent(e);
00191   if (e->isAccepted())
00192     {
00193     return;
00194     }
00195   if (d->indicatorRect().contains(e->pos()))
00196     {
00197     d->ShowMenu = true;
00198     this->showMenu();
00199     d->ShowMenu = false;
00200     e->accept();
00201     }
00202 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated on 21 May 2010 for CTK by  doxygen 1.6.1