Browse Source

ENH: Add alignment properties to ctkCollapsibleButton

Julien Finet 15 years ago
parent
commit
a6a7dfff98
2 changed files with 139 additions and 16 deletions
  1. 120 12
      Libs/Widgets/ctkCollapsibleButton.cpp
  2. 19 4
      Libs/Widgets/ctkCollapsibleButton.h

+ 120 - 12
Libs/Widgets/ctkCollapsibleButton.cpp

@@ -53,6 +53,10 @@ public:
   bool     LookOffWhenChecked;
 
   int      MaximumHeight;  // use carefully
+
+  // Tuning of the button look&feel
+  Qt::Alignment TextAlignment;
+  Qt::Alignment IndicatorAlignment;
 };
 
 //-----------------------------------------------------------------------------
@@ -76,6 +80,9 @@ void ctkCollapsibleButtonPrivate::init()
   
   this->MaximumHeight = p->maximumHeight();
 
+  this->TextAlignment = Qt::AlignLeft | Qt::AlignVCenter;
+  this->IndicatorAlignment = Qt::AlignLeft | Qt::AlignVCenter;
+
   p->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,
                                QSizePolicy::Preferred, 
                                QSizePolicy::DefaultType));
@@ -278,6 +285,36 @@ void ctkCollapsibleButton::setContentsMidLineWidth(int w)
 }
 
 //-----------------------------------------------------------------------------
+void ctkCollapsibleButton::setButtonTextAlignment(Qt::Alignment textAlignment)
+{
+  CTK_D(ctkCollapsibleButton);
+  d->TextAlignment = textAlignment;
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+Qt::Alignment ctkCollapsibleButton::buttonTextAlignment()const
+{
+  CTK_D(const ctkCollapsibleButton);
+  return d->TextAlignment;
+}
+
+//-----------------------------------------------------------------------------
+void ctkCollapsibleButton::setIndicatorAlignment(Qt::Alignment indicatorAlignment)
+{
+  CTK_D(ctkCollapsibleButton);
+  d->IndicatorAlignment = indicatorAlignment;
+  this->update();
+}
+
+//-----------------------------------------------------------------------------
+Qt::Alignment ctkCollapsibleButton::indicatorAlignment()const
+{
+  CTK_D(const ctkCollapsibleButton);
+  return d->IndicatorAlignment;
+}
+
+//-----------------------------------------------------------------------------
 QSize ctkCollapsibleButton::buttonSizeHint()const
 {
   int w = 0, h = 0;
@@ -400,16 +437,58 @@ void ctkCollapsibleButton::paintEvent(QPaintEvent * _event)
                               style()->pixelMetric(QStyle::PM_IndicatorHeight, &opt, this));
   opt.iconSize = indicatorSize;
   style()->drawControl(QStyle::CE_PushButtonBevel, &opt, &p, this);
-  // is PE_PanelButtonCommand better ?
+  // TBD is PE_PanelButtonCommand better ?
   //style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, &p, this);
   int buttonHeight = opt.rect.height();
-
+  uint tf = d->TextAlignment;
+  if (this->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
+    {
+    tf |= Qt::TextShowMnemonic;
+    }
+  else
+    {
+    tf |= Qt::TextHideMnemonic;
+    }
+  int textWidth = opt.fontMetrics.boundingRect(opt.rect, tf, opt.text).width();
+  int indicatorSpacing = this->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, this);
+  int buttonMargin = this->style()->pixelMetric(QStyle::PM_ButtonMargin, &opt, this);
   // Draw Indicator
   QStyleOption indicatorOpt;
   indicatorOpt.init(this);
-  indicatorOpt.rect = QRect((buttonHeight - indicatorSize.width()) / 2, 
-                            (buttonHeight - indicatorSize.height()) / 2,
-                            indicatorSize.width(), indicatorSize.height());
+  if (d->IndicatorAlignment & Qt::AlignLeft)
+    {
+    indicatorOpt.rect = QRect((buttonHeight - indicatorSize.width()) / 2,
+                              (buttonHeight - indicatorSize.height()) / 2,
+                              indicatorSize.width(), indicatorSize.height());
+    }
+  else if (d->IndicatorAlignment & Qt::AlignHCenter)
+    {
+    int w = indicatorSize.width();
+    if (!opt.text.isEmpty() && (d->TextAlignment & Qt::AlignHCenter))
+      {
+      w += textWidth + indicatorSpacing;
+      }
+    indicatorOpt.rect = QRect(opt.rect.x()+ opt.rect.width() /2 - w / 2,
+                              (buttonHeight - indicatorSize.height()) / 2,
+                              indicatorSize.width(), indicatorSize.height());
+    if (d->TextAlignment & Qt::AlignLeft &&
+        indicatorOpt.rect.left() < opt.rect.x() + buttonMargin + textWidth)
+      {
+      indicatorOpt.rect.moveLeft(opt.rect.x() + buttonMargin + textWidth);
+      }
+    else if (d->TextAlignment & Qt::AlignRight &&
+             indicatorOpt.rect.right() > opt.rect.right() - buttonMargin - textWidth)
+      {
+      indicatorOpt.rect.moveRight(opt.rect.right() - buttonMargin - textWidth);
+      }
+    }
+  else if (d->IndicatorAlignment & Qt::AlignRight)
+    {
+    indicatorOpt.rect = QRect(opt.rect.width() - (buttonHeight - indicatorSize.width()) / 2
+                                - indicatorSize.width(),
+                              (buttonHeight - indicatorSize.height()) / 2,
+                              indicatorSize.width(), indicatorSize.height());
+    }
   if (d->Collapsed)
     {
     style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &indicatorOpt, &p, this);
@@ -420,17 +499,46 @@ void ctkCollapsibleButton::paintEvent(QPaintEvent * _event)
     }
 
   // Draw Text
-  int indicatorSpacing = style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, this);
-  opt.rect.setLeft( indicatorOpt.rect.right() + indicatorSpacing);
-  uint tf = Qt::AlignVCenter | Qt::AlignLeft;
-  if (this->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
+  if (d->TextAlignment & Qt::AlignLeft)
     {
-    tf |= Qt::TextShowMnemonic;
+    if (d->IndicatorAlignment & Qt::AlignLeft)
+      {
+      opt.rect.setLeft(indicatorOpt.rect.right() + indicatorSpacing);
+      }
+    else
+      {
+      opt.rect.setLeft(opt.rect.x() + buttonMargin);
+      }
     }
-  else
+  else if (d->TextAlignment & Qt::AlignHCenter)
     {
-    tf |= Qt::TextHideMnemonic;
+    if (d->IndicatorAlignment & Qt::AlignHCenter)
+      {
+      opt.rect.setLeft(indicatorOpt.rect.right() + indicatorSpacing);
+      }
+    else
+      {
+      opt.rect.setLeft(opt.rect.x() + opt.rect.width() / 2 - textWidth / 2);
+      if (d->IndicatorAlignment & Qt::AlignLeft)
+        {
+        opt.rect.setLeft( qMin(indicatorOpt.rect.left() + indicatorSpacing, opt.rect.left()) );
+        }
+      }
+    }
+  else if (d->TextAlignment & Qt::AlignRight)
+    {
+    if (d->IndicatorAlignment & Qt::AlignRight)
+      {
+      opt.rect.setLeft(indicatorOpt.rect.left() - indicatorSpacing - textWidth);
+      }
+    else
+      {
+      opt.rect.setLeft(opt.rect.right() - buttonMargin - textWidth);
+      }
     }
+  // all the computations have been made infering the text would be left oriented
+  tf &= ~Qt::AlignHCenter & ~Qt::AlignRight;
+  tf |= Qt::AlignLeft;
   style()->drawItemText(&p, opt.rect, tf, opt.palette, (opt.state & QStyle::State_Enabled),
                         opt.text, QPalette::ButtonText);
 

+ 19 - 4
Libs/Widgets/ctkCollapsibleButton.h

@@ -35,10 +35,10 @@ class QStyleOptionButton;
 /// Description
 /// A Collapsible widget that show/hide its children depending on its checked/collapsed properties
 /// Warning: As ctkCollapsibleButton forces the Visiblity of its children to
-/// true when it get expanded, any Visibility property is lost. All the widgets
-/// will be visible. To avoid this behavior, use an intermediate widget that
-/// contains all the children (they would become grandchildren and their
-/// will remain relative to their parent: ctkCollapsibleButton's unique child.
+/// true when it get expanded, any child Visibility property is lost. All the widgets
+/// will then be visible. To avoid this behavior, use an intermediate widget that
+/// contains all the children (they would become grandchildren and their Visibility property
+/// will remain relative to their parent, ctkCollapsibleButton's unique child widget.
 class CTK_WIDGETS_EXPORT ctkCollapsibleButton : public QAbstractButton
 {
   Q_OBJECT
@@ -50,6 +50,9 @@ class CTK_WIDGETS_EXPORT ctkCollapsibleButton : public QAbstractButton
   Q_PROPERTY(int contentsLineWidth READ contentsLineWidth WRITE setContentsLineWidth)
   Q_PROPERTY(int contentsMidLineWidth READ contentsMidLineWidth WRITE setContentsMidLineWidth)
 
+  Q_PROPERTY(Qt::Alignment buttonTextAlignment READ buttonTextAlignment WRITE setButtonTextAlignment)
+  Q_PROPERTY(Qt::Alignment indicatorAlignment READ indicatorAlignment WRITE setIndicatorAlignment)
+
 public:
   ctkCollapsibleButton(QWidget *parent = 0);
   ctkCollapsibleButton(const QString& text, QWidget *parent = 0);
@@ -89,6 +92,18 @@ public:
   int contentsMidLineWidth() const;
   void setContentsMidLineWidth(int);
 
+  ///
+  /// Set the alignment of the text on the button,
+  /// Qt::Left|Qt::VCenter by default.
+  void setButtonTextAlignment(Qt::Alignment textAlignment);
+  Qt::Alignment buttonTextAlignment()const;
+
+  ///
+  /// Set the alignment of the indicator (arrow) on the button,
+  /// Qt::Left|Qt::VCenter by default.
+  void setIndicatorAlignment(Qt::Alignment indicatorAlignment);
+  Qt::Alignment indicatorAlignment()const;
+
   /// 
   /// Reimplement for internal reasons
   virtual QSize minimumSizeHint()const;