]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/dyntbar.cpp
194271339eec547fad7615a638af7f78405c646b
[wxWidgets.git] / contrib / src / fl / dyntbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dyntbar.cpp
3 // Purpose: wxDynamicToolBar implementation
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: ??/10/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dyntbar.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/utils.h" // import wxMin,wxMax macros
28
29 #include "wx/fl/dyntbar.h"
30 #include "wx/fl/newbmpbtn.h"
31
32 IMPLEMENT_DYNAMIC_CLASS(wxDynamicToolBar, wxControl )
33
34 BEGIN_EVENT_TABLE( wxDynamicToolBar, wxControl )
35
36 EVT_SIZE ( wxDynamicToolBar::OnSize )
37 EVT_PAINT( wxDynamicToolBar::OnPaint )
38 //EVT_ERASE_BACKGROUND( wxDynamicToolBar::OnEraseBackground )
39
40 END_EVENT_TABLE()
41
42 /***** Implementation for class wxDynToolInfo *****/
43
44 IMPLEMENT_DYNAMIC_CLASS(wxDynToolInfo, wxToolLayoutItem)
45
46 /***** Implementation for class wxDynamicToolBar *****/
47
48 wxDynamicToolBar::wxDynamicToolBar()
49 : mpLayoutMan( NULL ),
50 mSepartorSize( 8 ),
51 mVertGap ( 0 ),
52 mHorizGap( 0 )
53 {
54 }
55
56 wxDynamicToolBar::wxDynamicToolBar(wxWindow *parent, const wxWindowID id,
57 const wxPoint& pos, const wxSize& size,
58 const long style, const int orientation,
59 const int RowsOrColumns, const wxString& name )
60 : mpLayoutMan( NULL ),
61 mSepartorSize( 8 ),
62 mVertGap ( 0 ),
63 mHorizGap( 0 )
64 {
65 Create(parent, id, pos, size, style, orientation, RowsOrColumns, name);
66
67 SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE) );
68 }
69
70 bool wxDynamicToolBar::Create(wxWindow *parent, const wxWindowID id,
71 const wxPoint& pos,
72 const wxSize& size,
73 const long style,
74 const int orientation, const int RowsOrColumns,
75 const wxString& name)
76 {
77 // cut&pasted from wxtbatsmpl.h
78
79 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
80 return FALSE;
81
82 SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE ));
83
84 return TRUE;
85 }
86
87 bool wxDynamicToolBar::Realize(void)
88 {
89 // FOR NOW:: nothing
90 return TRUE;
91 }
92
93 wxDynamicToolBar::~wxDynamicToolBar(void)
94 {
95 if ( mpLayoutMan )
96 delete mpLayoutMan;
97
98 size_t i;
99 for( i = 0; i != mTools.Count(); ++i )
100 {
101 delete mTools[i];
102 }
103 }
104
105 void wxDynamicToolBar::AddTool( int toolIndex,
106 wxWindow* pToolWindow,
107 const wxSize& size
108 )
109 {
110 wxDynToolInfo* pInfo = new wxDynToolInfo();
111
112 pInfo->mpToolWnd = pToolWindow;
113 pInfo->mIndex = toolIndex;
114 pInfo->mIsSeparator = FALSE;
115
116 int x,y;
117 pToolWindow->GetSize( &x, &y );
118 pInfo->mRealSize.x = x;
119 pInfo->mRealSize.y = y;
120 pInfo->mRect.width = x;
121 pInfo->mRect.height = y;
122
123 mTools.Add( pInfo );
124 }
125
126 void wxDynamicToolBar::AddTool( int toolIndex,
127 const wxString& imageFileName,
128 wxBitmapType imageFileType,
129 const wxString& labelText, bool alignTextRight,
130 bool isFlat )
131 {
132 wxNewBitmapButton* pBtn =
133
134 new wxNewBitmapButton( imageFileName, imageFileType,
135 labelText,
136 ( alignTextRight )
137 ? NB_ALIGN_TEXT_RIGHT
138 : NB_ALIGN_TEXT_BOTTOM,
139 isFlat
140 );
141
142 pBtn->Create( this, toolIndex );
143
144 pBtn->Reshape();
145
146 AddTool( toolIndex, pBtn );
147 }
148 void wxDynamicToolBar::AddTool( int toolIndex, wxBitmap labelBmp,
149 const wxString& labelText, bool alignTextRight,
150 bool isFlat )
151 {
152 wxNewBitmapButton* pBtn =
153
154 new wxNewBitmapButton( labelBmp,
155 labelText,
156 ( alignTextRight )
157 ? NB_ALIGN_TEXT_RIGHT
158 : NB_ALIGN_TEXT_BOTTOM,
159 isFlat
160 );
161
162 pBtn->Create( this, toolIndex );
163
164 pBtn->Reshape();
165
166 AddTool( toolIndex, pBtn );
167 }
168
169
170 wxToolBarToolBase*
171 wxDynamicToolBar::AddTool(const int toolIndex, const wxBitmap& bitmap,
172 const wxBitmap& pushedBitmap,
173 const bool toggle, const long xPos,
174 const long yPos, wxObject *clientData,
175 const wxString& helpString1, const wxString& helpString2)
176 {
177 wxNewBitmapButton* pBmpBtn = new wxNewBitmapButton( bitmap );
178
179 pBmpBtn->Create( this, toolIndex );
180
181 pBmpBtn->Reshape();
182
183 AddTool( toolIndex, pBmpBtn );
184
185 return NULL;
186 }
187
188
189 wxDynToolInfo* wxDynamicToolBar::GetToolInfo( int toolIndex )
190 {
191 size_t i;
192 for( i = 0; i != mTools.Count(); ++i )
193 {
194 if ( mTools[i]->mIndex == toolIndex )
195 return mTools[i];
196 }
197
198 return NULL;
199 }
200
201 void wxDynamicToolBar::RemveTool( int toolIndex )
202 {
203 size_t i;
204 for( i = 0; i != mTools.Count(); ++i )
205 {
206 if ( mTools[i]->mIndex == toolIndex )
207 {
208 if ( mTools[i]->mpToolWnd )
209 {
210 mTools[i]->mpToolWnd->Destroy();
211 }
212 delete mTools[i]; // HVL To be tested!!!
213 #if wxCHECK_VERSION(2,3,2)
214 mTools.RemoveAt(i);
215 #else
216 mTools.Remove(i);
217 #endif
218 Layout();
219
220 return;
221 }
222 }
223 // TODO:: if not found, should it be an assertion?
224 }
225
226 void wxDynamicToolBar::AddSeparator( wxWindow* pSepartorWnd )
227 {
228 wxDynToolInfo* pInfo = new wxDynToolInfo();
229
230 pInfo->mpToolWnd = pSepartorWnd;
231 pInfo->mIndex = -1;
232 pInfo->mIsSeparator = TRUE;
233
234 // Do we draw a separator or is a other object?
235 if ( pSepartorWnd )
236 {
237 // hvl => Is there a way to know if it was already created?
238 // hvl => shouldn't the pSepartorWnd be created? (like one should expect?)
239 // pSepartorWnd->Create( this, -1 );
240
241 int x,y;
242 pSepartorWnd->GetSize( &x, &y );
243 pInfo->mRealSize.x = x;
244 pInfo->mRealSize.y = y;
245
246 pInfo->mRect.width = x;
247 pInfo->mRect.height = y;
248 }
249 else
250 {
251 // Init x and y to the default.
252 pInfo->mRealSize.x = 0;
253 pInfo->mRealSize.y = 0;
254
255 // Init height and width to the normal size of a separator.
256 pInfo->mRect.width = mSepartorSize;
257 pInfo->mRect.height = mSepartorSize;
258 }
259
260 mTools.Add( pInfo );
261 }
262
263 void wxDynamicToolBar::OnEraseBackground( wxEraseEvent& event )
264 {
265 // FOR NOW:: nothing
266 }
267
268 void wxDynamicToolBar::OnSize( wxSizeEvent& event )
269 {
270 //SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE ) );
271
272 Layout();
273 }
274
275 void wxDynamicToolBar::DrawSeparator( wxDynToolInfo& info, wxDC& dc )
276 {
277 // check the orientation of separator
278 if ( info.mRect.width < info.mRect.height )
279 {
280 int midX = info.mRect.x + info.mRect.width/2 - 1;
281
282 dc.SetPen( *wxGREY_PEN );
283 dc.DrawLine( midX, info.mRect.y,
284 midX, info.mRect.y + info.mRect.height+1 );
285
286 dc.SetPen( *wxWHITE_PEN );
287 dc.DrawLine( midX+1, info.mRect.y,
288 midX+1, info.mRect.y + info.mRect.height+1 );
289 }
290 else
291 {
292 int midY = info.mRect.y + info.mRect.height/2 - 1;
293
294 dc.SetPen( *wxGREY_PEN );
295 dc.DrawLine( info.mRect.x, midY,
296 info.mRect.x + info.mRect.width+1, midY );
297
298 dc.SetPen( *wxWHITE_PEN );
299 dc.DrawLine( info.mRect.x, midY + 1,
300 info.mRect.x + info.mRect.width+1, midY + 1 );
301 }
302 }
303
304 void wxDynamicToolBar::OnPaint( wxPaintEvent& event )
305 {
306 // draw separators if any
307 wxPaintDC dc(this);
308
309 size_t i;
310 for( i = 0; i != mTools.Count(); ++i )
311 {
312 if ( mTools[i]->mIsSeparator )
313 {
314 // check if separator doesn't have it's own window
315 // if so, then draw it using built-in drawing method
316 if ( !mTools[i]->mpToolWnd )
317 DrawSeparator( *mTools[i], dc );
318 }
319 }
320 }
321
322 // FOR NOW:: quick fix
323 #include "wx/choice.h"
324
325 void wxDynamicToolBar::SizeToolWindows()
326 {
327 bool bStateCheckDone = FALSE;
328 bool bHorzSeparator = FALSE;
329 int maxWidth = 0;
330 int maxHeight = 0;
331
332 size_t i;
333 for( i = 0; i != mTools.Count(); ++i )
334 {
335 wxDynToolInfo& info = *mTools[i];
336
337 if ( !info.mIsSeparator )
338 {
339 // center real rectangle within the rectangle
340 // provided by the layout manager
341
342 int x = info.mRect.x;
343 int y = info.mRect.y + (info.mRect.height - info.mRealSize.y)/2;
344
345 // FOR NOW FOR NOW:: quick & dirty fix
346 if ( info.mpToolWnd->IsKindOf( CLASSINFO( wxChoice ) ) )
347 {
348 info.mpToolWnd->SetSize( x, y,
349 info.mRealSize.x - 3,
350 info.mRealSize.y);
351 }
352 else
353 {
354 info.mpToolWnd->SetSize( x, y,
355 info.mRealSize.x,
356 info.mRealSize.y );
357 }
358 }
359 else
360 {
361 // We performer this code here, so we only execute it when we have
362 // separators and we do it only once (all to do with performance...)
363 if (!bStateCheckDone)
364 {
365 bStateCheckDone = TRUE;
366
367 size_t j;
368 wxDynToolInfo *pInfo = NULL;
369 wxDynToolInfo *pPrevInfo = NULL;
370 int nVertSeparators = 0;
371
372 for( j = 0; j != mTools.Count(); ++j )
373 {
374 pInfo = mTools[j];
375
376 // Count all Vert Separators.
377 if ( pInfo->mIsSeparator )
378 nVertSeparators++;
379
380 // Check if the new row starts with a Separator.
381 if ( pPrevInfo && pInfo->mIsSeparator &&
382 // pPrevInfo->mRect.x >= pInfo->mRect.x &&
383 pPrevInfo->mRect.y < pInfo->mRect.y)
384 {
385 // If the Separator is shown on the next row and it's
386 // the only object on the row it would mean that the
387 // Separator should be shown as Horizontal one.
388 if (j+1 != mTools.Count())
389 {
390 if (pInfo->mRect.y < mTools[j+1]->mRect.y)
391 nVertSeparators--;
392 }
393 else
394 {
395 nVertSeparators--;
396 }
397 }
398
399 pPrevInfo = pInfo;
400
401 maxWidth = wxMax(pInfo->mRect.width, maxWidth);
402 maxHeight = wxMax(pInfo->mRect.height, maxHeight);
403 }
404
405 bHorzSeparator = nVertSeparators == 0;
406 }
407
408 // Check if we should draw Horz or Vert...
409 if ( !bHorzSeparator )
410 {
411 info.mRect.width = mSepartorSize;
412 info.mRect.height = maxHeight;
413 }
414 else
415 {
416 info.mRect.width = maxWidth;
417 info.mRect.height = mSepartorSize;
418 }
419
420 // Do we need to set a new size to a seperator object?
421 if ( info.mpToolWnd )
422 {
423 info.mpToolWnd->SetSize( info.mRect.x,
424 info.mRect.y,
425 info.mRect.width,
426 info.mRect.height);
427 }
428
429 }
430 }
431 }
432
433 bool wxDynamicToolBar::Layout()
434 {
435 int x,y;
436 GetSize( &x, &y );
437 wxSize wndDim(x,y);
438 wxSize result;
439 size_t i;
440 wxDynToolInfo *pInfo;
441
442 // Reset the size of separators...
443 for( i = 0; i != mTools.Count(); ++i )
444 {
445 pInfo = mTools[i];
446
447 if ( pInfo->mIsSeparator )
448 {
449 pInfo->mRect.width = mSepartorSize;
450 pInfo->mRect.height = mSepartorSize;
451 }
452 }
453
454 // Calc and set the best layout
455 GetPreferredDim( wndDim, result );
456
457 SizeToolWindows();
458 return TRUE;
459 }
460
461 void wxDynamicToolBar::GetPreferredDim( const wxSize& givenDim, wxSize& prefDim )
462 {
463 if ( !mpLayoutMan )
464 mpLayoutMan = CreateDefaultLayout();
465
466 wxLayoutItemArrayT items;
467
468 // safe conversion
469 size_t i;
470 for( i = 0; i != mTools.Count(); ++i )
471 items.Add( mTools[i] );
472
473 mpLayoutMan->Layout( givenDim, prefDim, items, mVertGap, mHorizGap );
474 }
475
476 void wxDynamicToolBar::SetLayout( LayoutManagerBase* pLayout )
477 {
478 if ( mpLayoutMan )
479 delete mpLayoutMan;
480
481 mpLayoutMan = pLayout;
482
483 Layout();
484 }
485
486 void wxDynamicToolBar::EnableTool(const int toolIndex, const bool enable )
487 {
488 wxDynToolInfo* pInfo = GetToolInfo( toolIndex );
489
490 if ( !pInfo )
491 return;
492
493 if ( pInfo->mIsSeparator || !pInfo->mpToolWnd )
494 return;
495
496 pInfo->mpToolWnd->Enable( enable );
497 }
498
499 /***** Implementation for class BagLayout *****/
500
501 void BagLayout::Layout( const wxSize& parentDim,
502 wxSize& resultingDim,
503 wxLayoutItemArrayT& items,
504 int horizGap,
505 int vertGap
506 )
507 {
508 int maxWidth = 0;
509 int curY = 0;
510 int nRows = 0;
511
512 size_t i = 0;
513
514 while( i < items.Count() )
515 {
516 int curX = 0;
517 int height = 0;
518 // int nItems = 0;
519
520 // int firstItem = i;
521 int itemsInRow = 0;
522
523 if ( nRows > 0 )
524 curY += vertGap;
525
526 // step #1 - arrange horizontal positions of items in the row
527
528 do
529 {
530 if ( itemsInRow > 0 )
531 curX += horizGap;
532
533 wxRect& r = items[i]->mRect;
534
535 if ( curX + r.width > parentDim.x )
536 {
537 if ( itemsInRow > 0 )
538 break;
539 }
540 r.x = curX;
541 r.y = curY;
542
543 curX += r.width;
544
545 height = wxMax( height, r.height );
546
547 ++itemsInRow;
548 ++i;
549
550 } while( i < items.Count() );
551
552 curY += height;
553
554 maxWidth = wxMax( maxWidth, curX );
555 }
556
557 resultingDim.x = maxWidth;
558 resultingDim.y = curY;
559 }
560
561 //////// stuff from 2.1.15 ///////////
562
563 wxToolBarToolBase* wxDynamicToolBar::FindToolForPosition( wxCoord x, wxCoord y ) const
564 {
565 return NULL;
566 }
567
568 bool wxDynamicToolBar::DoInsertTool( size_t pos, wxToolBarToolBase* tool )
569 {
570 return TRUE;
571 }
572
573 bool wxDynamicToolBar::DoDeleteTool( size_t pos, wxToolBarToolBase* tool )
574 {
575 return TRUE;
576 }
577
578 void wxDynamicToolBar::DoEnableTool( wxToolBarToolBase* tool, bool enable )
579 {
580 }
581
582 void wxDynamicToolBar::DoToggleTool( wxToolBarToolBase* tool, bool toggle )
583 {
584 }
585
586 void wxDynamicToolBar::DoSetToggle( wxToolBarToolBase* tool, bool toggle )
587 {
588 }
589
590 wxToolBarToolBase* wxDynamicToolBar::CreateTool( int id, const wxBitmap& bitmap1, const wxBitmap& bitmap2, bool toggle, wxObject* clientData, const wxString& shortHelpString, const wxString& longHelpString )
591 {
592 return NULL;
593 }
594
595 wxToolBarToolBase* wxDynamicToolBar::CreateTool( wxControl* control )
596 {
597 return NULL;
598 }
599