KoKoolBar.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <KoKoolBar.h>
21#include <kiconloader.h>
22
23#include <tqpainter.h>
24#include <tqpushbutton.h>
25
26static int g_koKoolBarId = 0;
27
28KoKoolBar::KoKoolBar( TQWidget *_parent, const char *_name ) :
29 TQWidget( _parent, _name ), m_iActiveGroup( -1 )
30{
31 m_mapGroups.setAutoDelete( true );
32 m_pBox = new KoKoolBarBox( this );
33}
34
35int KoKoolBar::insertGroup( const TQString& _text )
36{
37 KoKoolBarGroup *p = new KoKoolBarGroup( this, _text );
38 m_mapGroups.insert( p->id(), p );
39
40 if ( m_iActiveGroup == -1 )
41 setActiveGroup( p->id() );
42 else
43 resizeEvent( 0L );
44 return p->id();
45}
46
47int KoKoolBar::insertItem( int _grp, const TQPixmap& _pix, const TQString& _text,
48 TQObject *_obj, const char *_slot )
49{
50 KoKoolBarGroup* g = m_mapGroups[ _grp ];
51 if ( !g )
52 return -1;
53 KoKoolBarItem *item = new KoKoolBarItem( g, _pix, _text );
54
55 if ( _obj != 0L && _slot != 0L )
56 connect( item, TQ_SIGNAL( pressed( int, int ) ), _obj, _slot );
57 g->append( item );
58
59 if ( g->id() == m_iActiveGroup )
60 m_pBox->update();
61
62 return item->id();
63}
64
65void KoKoolBar::removeGroup( int _grp )
66{
67 KoKoolBarGroup* g = m_mapGroups[ _grp ];
68 if ( !g )
69 return;
70
71 m_mapGroups.remove( _grp );
72
73 if ( _grp == m_iActiveGroup )
74 {
75 if ( m_mapGroups.count() == 0 )
76 {
77 m_iActiveGroup = -1;
78 m_pBox->setActiveGroup( 0L );
79 }
80 else
81 {
82 TQIntDictIterator<KoKoolBarGroup> it( m_mapGroups );
83 g = it.current();
84 m_iActiveGroup = g->id();
85 m_pBox->setActiveGroup( g );
86 }
87 }
88
89 resizeEvent( 0L );
90}
91
92void KoKoolBar::removeItem( int _grp, int _id )
93{
94 KoKoolBarGroup* g = m_mapGroups[ _grp ];
95 if ( !g )
96 return;
97
98 g->remove( _id );
99
100 if ( g->id() == m_iActiveGroup )
101 m_pBox->update();
102}
103
104void KoKoolBar::renameItem( int _grp, int _id, const TQString & _text )
105{
106 KoKoolBarGroup* g = m_mapGroups[ _grp ];
107 if ( !g )
108 return;
109
110 KoKoolBarItem * item = g->item( _id );
111 if ( !item )
112 return;
113
114 item->setText( _text );
115
116 if ( g->id() == m_iActiveGroup )
117 m_pBox->update();
118}
119
120void KoKoolBar::setActiveGroup( int _grp )
121{
122 KoKoolBarGroup* g = m_mapGroups[ _grp ];
123 if ( !g )
124 return;
125
126 m_iActiveGroup = g->id();
127 m_pBox->setActiveGroup( g );
128
129 resizeEvent( 0L );
130}
131
132void KoKoolBar::resizeEvent( TQResizeEvent * ev )
133{
134 if ( m_iActiveGroup == -1 )
135 return;
136
137 int buttonheight = fontMetrics().height() + 4;
138
139 KoKoolBarGroup *g = m_mapGroups[ m_iActiveGroup ];
140 if ( !g )
141 return;
142
143 // Go behind g
144 TQIntDictIterator<KoKoolBarGroup> it( m_mapGroups );
145 while( it.current() != g )
146 ++it;
147 // Position of g
148 TQIntDictIterator<KoKoolBarGroup> pos = it;
149 ++it;
150
151 // How many left ?
152 int result = 0;
153 TQIntDictIterator<KoKoolBarGroup> i = it;
154 while( i.current() )
155 {
156 ++result;
157 ++i;
158 }
159
160 int y = height() - buttonheight * result;
161 for( ; it.current(); ++it )
162 {
163 it.current()->button()->setGeometry( 0, y, width(), buttonheight );
164 it.current()->button()->show();
165 y += buttonheight;
166 }
167
168 int y2 = 0;
169 it.toFirst();
170 ++pos;
171 while( it.current() != pos.current() )
172 {
173 it.current()->button()->setGeometry( 0, y2, width(), buttonheight );
174 it.current()->button()->show();
175 ++it;
176 y2 += buttonheight;
177 }
178
179 if ( height() - y2 - result * buttonheight >= 0 )
180 {
181 m_pBox->show();
182 m_pBox->setGeometry( 0, y2, width(), height() - y2 - result * buttonheight );
183 if ( !ev ) // fake event
184 m_pBox->sizeChanged();
185 }
186 else
187 m_pBox->hide();
188
189}
190
191void KoKoolBar::enableItem( int _grp, int _id, bool _enable )
192{
193 KoKoolBarGroup* g = m_mapGroups[ _grp ];
194 if ( !g )
195 return;
196 KoKoolBarItem *item = g->item( _id );
197 if ( !item )
198 return;
199 item->setEnabled( _enable );
200}
201
202void KoKoolBar::enableGroup( int _grp, bool _enable )
203{
204 KoKoolBarGroup* g = m_mapGroups[ _grp ];
205 if ( !g )
206 return;
207 g->setEnabled( _enable );
208}
209
210KoKoolBarBox::KoKoolBarBox( KoKoolBar *_bar ) :
211 TQFrame( _bar ), m_pBar( _bar ),
212 m_pButtonUp( 0L ), m_pButtonDown( 0L )
213{
214 m_iYOffset = 0;
215 m_iYIcon = 0;
216 m_pGroup = 0L;
217
218 setFrameShape( StyledPanel );
219 setFrameShadow( Sunken );
220 // setBackgroundMode( PaletteBase );
221 setBackgroundColor( colorGroup().background() );
222}
223
224void KoKoolBarBox::setActiveGroup( KoKoolBarGroup *_grp )
225{
226 m_pGroup = _grp;
227 m_iYOffset = 0;
228 m_iYIcon = 0;
229 update();
230}
231
232bool KoKoolBarBox::needsScrolling() const
233{
234 if ( m_pGroup == 0L )
235 return false;
236
237 return ( maxHeight() > height() );
238}
239
240void KoKoolBarBox::resizeEvent( TQResizeEvent * )
241{
242 if ( needsScrolling() )
243 {
244 if ( m_pButtonUp == 0L )
245 {
246 m_pButtonUp = new TQPushButton( this );
247 m_pButtonUp->setPixmap( TQPixmap( UserIcon( "koKoolBarUp" ) ) );
248 connect( m_pButtonUp, TQ_SIGNAL( clicked() ), this, TQ_SLOT( scrollUp() ) );
249 }
250 if ( m_pButtonDown == 0L )
251 {
252 m_pButtonDown = new TQPushButton( this );
253 m_pButtonDown->setPixmap( TQPixmap( UserIcon( "koKoolBarDown" ) ) );
254 connect( m_pButtonDown, TQ_SIGNAL( clicked() ), this, TQ_SLOT( scrollDown() ) );
255 }
256 m_pButtonUp->show();
257 m_pButtonUp->raise();
258 m_pButtonDown->show();
259 m_pButtonDown->raise();
260 updateScrollButtons();
261 }
262 else
263 {
264 if ( m_pButtonUp )
265 m_pButtonUp->hide();
266 if ( m_pButtonDown )
267 m_pButtonDown->hide();
268 }
269}
270
271KoKoolBarItem* KoKoolBarBox::findByPos( int _abs_y ) const
272{
273 if ( m_pGroup == 0L )
274 return 0L;
275
276 int y = 0;
277
278 TQIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator();
279 for ( ; it.current(); ++it )
280 {
281 int dy = it.current()->height();
282 if ( y <= _abs_y && _abs_y <= y + dy )
283 return it.current();
284 y += dy;
285 }
286
287 return 0L;
288}
289
290int KoKoolBarBox::maxHeight() const
291{
292 int y = 0;
293
294 TQIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator();
295 for ( ; it.current(); ++it )
296 y += it.current()->height();
297
298 return y;
299}
300
301bool KoKoolBarBox::isAtTop() const
302{
303 return ( m_iYIcon == 0 );
304}
305
306bool KoKoolBarBox::isAtBottom() const
307{
308 if ( m_pGroup->items() == 0 )
309 return true;
310 int h = maxHeight();
311 if ( height() + m_iYOffset >= h )
312 return true;
313 if ( m_pGroup->items() - 1 == m_iYIcon )
314 return true;
315 return false;
316}
317
318void KoKoolBarBox::scrollUp()
319{
320 if ( isAtTop() )
321 return;
322
323 int y = 0;
324 int i = 0;
325 m_iYIcon--;
326
327 TQIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator();
328 for ( ; i < m_iYIcon && it.current(); ++it )
329 {
330 y += it.current()->height();
331 ++i;
332 }
333
334 int old = m_iYOffset;
335 m_iYOffset = y;
336
337 TQWidget::scroll( 0, old - m_iYOffset, contentsRect() );
338 updateScrollButtons();
339}
340
341void KoKoolBarBox::scrollDown()
342{
343 if ( isAtBottom() )
344 return;
345
346 int y = 0;
347 int i = 0;
348 m_iYIcon++;
349
350 TQIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator();
351 for ( ; i < m_iYIcon && it.current(); ++it )
352 {
353 y += it.current()->height();
354 i++;
355 }
356 int h = maxHeight();
357 if ( y + height() > h ) // Don't go after last item
358 y = h - height();
359
360 int old = m_iYOffset;
361 m_iYOffset = y;
362
363 TQWidget::scroll( 0, old - m_iYOffset, contentsRect() );
364 updateScrollButtons();
365}
366
367void KoKoolBarBox::updateScrollButtons()
368{
369 if ( isAtTop() )
370 m_pButtonUp->setEnabled( false );
371 else
372 m_pButtonUp->setEnabled( true );
373
374 if ( isAtBottom() )
375 m_pButtonDown->setEnabled( false );
376 else
377 m_pButtonDown->setEnabled( true );
378
379 const int bs = 14; // buttonSize
380 m_pButtonUp->setGeometry( width() - bs, height() - 2 * bs, bs, bs );
381 m_pButtonDown->setGeometry( width() - bs, height() - bs, bs, bs );
382}
383
384void KoKoolBarBox::drawContents( TQPainter * painter )
385{
386 if ( m_pGroup == 0L )
387 return;
388
389 int y = -m_iYOffset;
390
391 TQIntDictIterator<KoKoolBarItem> it = m_pGroup->iterator();
392 for ( ; it.current(); ++it )
393 {
394 if ( y + it.current()->height() >= 0 && y <= height() ) // visible ?
395 {
396 painter->drawPixmap( ( width() - it.current()->pixmap().width() ) / 2, y, it.current()->pixmap() );
397 if ( !it.current()->text().isEmpty() )
398 {
399 int y2 = y + it.current()->pixmap().height() + 2;
400 painter->drawText( ( width() - painter->fontMetrics().width( it.current()->text() ) ) / 2,
401 y2 + painter->fontMetrics().ascent(), it.current()->text() );
402 }
403 }
404
405 y += it.current()->height();
406 }
407}
408
409KoKoolBarGroup::KoKoolBarGroup( KoKoolBar *_bar, const TQString& _text ) :
410 m_pBar( _bar )
411{
412 m_mapItems.setAutoDelete( true );
413
414 m_pButton = new TQPushButton( _text, _bar );
415
416 m_bEnabled = true;
417
418 connect( m_pButton, TQ_SIGNAL( clicked() ), this, TQ_SLOT( pressed() ) );
419 m_id = g_koKoolBarId++;
420}
421
422KoKoolBarGroup::~KoKoolBarGroup()
423{
424 delete m_pButton;
425}
426
427void KoKoolBarGroup::remove( int _id )
428{
429 m_mapItems.remove( _id );
430}
431
432void KoKoolBarGroup::pressed()
433{
434 m_pBar->setActiveGroup( m_id );
435}
436
437KoKoolBarItem::KoKoolBarItem( KoKoolBarGroup *_grp, const TQPixmap& _pix, const TQString&_text )
438 : m_pGroup( _grp )
439{
440 m_pixmap = _pix;
441 m_strText = _text;
442 m_bEnabled = true;
443 m_id = g_koKoolBarId++;
444 calc( _grp->bar() );
445}
446
447void KoKoolBarItem::calc( TQWidget *_widget )
448{
449 m_iHeight = pixmap().height() + 8;
450
451 if ( !m_strText.isEmpty() )
452 m_iHeight += _widget->fontMetrics().height() + 2;
453}
454
455void KoKoolBarItem::press()
456{
457 emit pressed();
458 emit pressed( m_pGroup->id(), m_id );
459}
460
461/*
462
463int main( int argc, char **argv )
464{
465 TDEApplication app( argc, argv );
466 KoKoolBar bar;
467 int file = bar.insertGroup("File");
468 TQPixmap pix;
469 pix.load( "/opt/kde/share/icons/image.xpm" );
470 bar.insertItem( file, pix );
471 pix.load( "/opt/kde/share/icons/html.xpm" );
472 bar.insertItem( file, pix );
473 pix.load( "/opt/kde/share/icons/txt.xpm" );
474 bar.insertItem( file, pix );
475 pix.load( "/opt/kde/share/icons/kfm.xpm" );
476 bar.insertItem( file, pix );
477
478 bar.insertGroup("Edit");
479 bar.insertGroup("View");
480 bar.insertGroup("Layout");
481 bar.insertGroup("Help");
482 bar.setGeometry( 100, 100, 80, 300 );
483 bar.show();
484
485 app.exec();
486}
487*/
488
489#include <KoKoolBar.moc>