Salome HOME
Property "isOpen" property added.
[modules/gui.git] / src / Qtx / QtxMenuButton.cxx
1 // File:      QtxMenuButton.cxx
2 // Author:    Sergey TELKOV
3
4 #include "QtxMenuButton.h"
5
6 #include <qstyle.h>
7 #include <qpainter.h>
8 #include <qpopupmenu.h>
9 #include <qpointarray.h>
10 #include <qapplication.h>
11
12 class QtxMenuButton::PopupMenu : public QPopupMenu
13 {
14 public:
15     PopupMenu( QtxMenuButton* mb ) : QPopupMenu( mb ), myMenuButton( mb ) {};
16     virtual ~PopupMenu() {};
17
18     virtual void setMinimumSize( int, int );
19
20 private:
21     QtxMenuButton* myMenuButton;
22 };
23
24 void QtxMenuButton::PopupMenu::setMinimumSize( int w, int h )
25 {
26     if ( myMenuButton->isAlignWidth() &&
27          ( myMenuButton->position() == Top || myMenuButton->position() == Bottom ) )
28         w = QMAX( w, myMenuButton->width() );
29
30     QPopupMenu::setMinimumSize( w, h );
31 }
32
33
34 QtxMenuButton::QtxMenuButton( int pos, QWidget* parent, const char* name )
35 : QPushButton( parent, name ),
36 myPos( pos )
37 {
38         initialize();
39 }
40
41 QtxMenuButton::QtxMenuButton( const QString& text, QWidget* parent, const char* name )
42 : QPushButton( parent, name ),
43 myPos( Bottom )
44 {
45         setText( text );
46         initialize();
47 }
48
49 QtxMenuButton::QtxMenuButton( int pos, const QString& text, QWidget* parent, const char* name )
50 : QPushButton( parent, name ),
51 myPos( pos )
52 {
53         setText( text );
54         initialize();
55 }
56
57 QtxMenuButton::QtxMenuButton( QWidget* parent, const char* name )
58 : QPushButton( parent, name ),
59 myPos( Bottom )
60 {
61         initialize();
62 }
63
64 QtxMenuButton::~QtxMenuButton()
65 {
66 }
67
68 void QtxMenuButton::initialize()
69 {
70         myArrow = true;
71     myAlign = true;
72
73         setAutoDefault( false );
74         myPopup = new PopupMenu( this );
75     myPopup->hide();
76
77         connect( myPopup, SIGNAL( activated( int ) ), this, SIGNAL( activated( int ) ) );
78         connect( this, SIGNAL( clicked() ), this, SLOT( onShowPopup() ) );
79 }
80
81 int QtxMenuButton::position() const
82 {
83         return myPos;
84 }
85
86 bool QtxMenuButton::isAlignWidth() const
87 {
88     return myAlign;
89 }
90
91 bool QtxMenuButton::isArrowEnabled() const
92 {
93         return myArrow;
94 }
95
96 void QtxMenuButton::setPosition( const int pos )
97 {
98         if ( myPos == pos )
99                 return;
100
101     myPos = pos;
102     if ( myPopup->isVisible() )
103         onShowPopup();
104 }
105
106 void QtxMenuButton::setAlignWidth( const bool on )
107 {
108     if ( myAlign == on )
109         return;
110
111     myAlign = on;
112     updateGeometry();
113 }
114
115 void QtxMenuButton::setArrowEnabled( const bool on )
116 {
117         if ( myArrow == on )
118                 return;
119
120     myArrow = on;
121     repaint();
122 }
123
124 void QtxMenuButton::clear()
125 {
126         if ( myPopup )
127                 myPopup->clear();
128         onShowPopup();
129         updateGeometry();
130 }
131
132 void QtxMenuButton::removeItem( int id )
133 {
134         if ( myPopup )
135                 removeItem( id );
136         updateGeometry();
137 }
138
139 int QtxMenuButton::insertSeparator( int id )
140 {
141         int res = -1;
142         if ( myPopup )
143                 res = myPopup->insertSeparator( id );
144     return res;
145 }
146
147 int QtxMenuButton::insertItem( const QString& t, int id, int index )
148 {
149         int resId = -1;
150         if ( myPopup )
151                 resId = myPopup->insertItem( t, id, index );
152
153         if ( resId != -1 )
154                 updateGeometry();
155
156         return resId;
157 }
158
159 int QtxMenuButton::insertItem( const QIconSet& is, const QString& t, int id, int index )
160 {
161         int resId = -1;
162         if ( myPopup )
163                 resId = myPopup->insertItem( is, t, id, index );
164
165         if ( resId != -1 )
166                 updateGeometry();
167
168         return resId;
169 }
170
171 void QtxMenuButton::onShowPopup()
172 {
173         if ( !myPopup || !myPopup->count() )
174         {
175                 myPopup->hide();
176                 return;
177         }
178
179         QPoint p = mapToGlobal( QPoint( 0, 0 ) );
180         int x = p.x();
181         int y = p.y() + 1;
182         int margin = 0;
183         int xoffset = 0;
184         int yoffset = 0;
185         switch ( position() )
186         {
187         case Left:
188                 xoffset = -1 * ( myPopup->sizeHint().width() + margin );
189                 break;
190         case Right:
191                 xoffset = width() + margin;
192                 break;
193         case Top:
194                 yoffset = -1 * ( myPopup->sizeHint().height() + margin );
195                 break;
196         case Bottom:
197         default:
198                 yoffset = height() + margin;
199                 break;
200         }
201         int dw = QApplication::desktop()->width();
202         int dh = QApplication::desktop()->height();
203         x = QMIN( QMAX( x + xoffset, 0 ), dw );
204         y = QMIN( QMAX( y + yoffset, 0 ), dh );
205
206         myPopup->exec( QPoint( x, y ) );
207 }
208
209 bool QtxMenuButton::event( QEvent* e )
210 {
211         if ( e->type() == QEvent::MouseButtonPress ||
212                  e->type() == QEvent::MouseButtonDblClick ||
213                  e->type() == QEvent::MouseButtonRelease )
214         {
215                 onShowPopup();
216                 return false;
217         }
218
219         return QPushButton::event( e );
220 }
221
222 QSize QtxMenuButton::sizeHint() const
223 {
224         QSize sz = QPushButton::sizeHint();
225         if ( ( position() == Top || position() == Bottom ) && myPopup && myAlign )
226                 sz = QSize( QMAX( sz.width(), myPopup->sizeHint().width() ), sz.height() );
227
228         return sz;
229 }
230
231 QSize QtxMenuButton::minimumSizeHint() const
232 {
233         QSize sz = QPushButton::minimumSizeHint();
234         if ( ( position() == Top || position() == Bottom ) && myPopup && myAlign )
235                 sz = QSize( QMAX( sz.width(), myPopup->sizeHint().width() ), sz.height() );
236
237         return sz;
238 }
239
240 void QtxMenuButton::resizeEvent( QResizeEvent* re )
241 {
242         if ( re )
243                 QPushButton::resizeEvent( re );
244
245         if ( ( position() == Top || position() == Bottom ) && myPopup && myAlign )
246         myPopup->setMinimumWidth( re ? re->size().width() : width() );
247 }
248
249 QPopupMenu* QtxMenuButton::popup() const
250 {
251     return myPopup;
252 }
253
254 void QtxMenuButton::drawButtonLabel( QPainter* p )
255 {
256     QPushButton::drawButtonLabel( p );
257 /*
258         QStyle::SFlags flags = QStyle::Style_Default;
259         if ( isEnabled() )
260                 flags |= QStyle::Style_Enabled;
261         if ( hasFocus() )
262                 flags |= QStyle::Style_HasFocus;
263 */
264 #if QT_VER < 3
265     QRect r = rect();
266 #else
267         QRect r = style().subRect( QStyle::SR_PushButtonContents, this );
268 #endif
269
270         if ( myArrow && myPopup && myPopup->count() )
271         {
272                 int w = 7;
273                 int h = 7;
274                 int margin = 5;
275
276                 QRect ar( 0, 0, w, h );
277                 if ( position() == Left || position() == Top )
278                         r.moveBy( ar.width() + 2 * margin, 0 );
279                 else
280                         ar.moveBy( r.width() - ar.width() - 2 * margin, 0 );
281
282                 r.setWidth( r.width() - ar.width() - 2 * margin );
283     
284                 ar.moveBy( margin, ( height() - h ) / 2 );
285
286                 QPointArray arrow( 3 );
287                 switch ( position() )
288                 {
289                 case Left:
290                         arrow.putPoints( 0, 3, ar.left(), ar.top() + ar.height() / 2, ar.right(), ar.top(), ar.right(), ar.bottom() );
291                         break;
292                 case Right:
293                         arrow.putPoints( 0, 3, ar.left(), ar.top(), ar.left(), ar.bottom(), ar.right(), ar.top() + ar.height() / 2 );
294                         break;
295                 case Top:
296                         arrow.putPoints( 0, 3, ar.left(), ar.bottom(), ar.right(), ar.bottom(), ar.left() + ar.width() / 2, ar.top() );
297                         break;
298                 case Bottom:
299                 default:
300                         arrow.putPoints( 0, 3, ar.left(), ar.top(), ar.right(), ar.top(), ar.left() + ar.width() / 2, ar.bottom() );
301                         break;
302                 }
303
304                 p->setPen( colorGroup().text() );
305                 p->setBrush( colorGroup().text() );
306                 p->drawPolygon( arrow, true );
307         }
308
309 //      style().drawControl( QStyle::CE_PushButtonLabel, p, this, r, colorGroup(), flags );
310 }