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