]> git.saurik.com Git - wxWidgets.git/blob - utils/framelayout/src/dyntbar.cpp
don't crash when invalid colour is set as fg/bg colour
[wxWidgets.git] / utils / framelayout / src / dyntbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
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.cpp"
14 #pragma interface "dyntbar.cpp"
15 #endif
16
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
19
20 /*
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24 */
25
26 #ifndef WX_PRECOMP
27 #include "wx/wx.h"
28 #endif
29
30 #include "wx/utils.h" // import wxMin,wxMax macros
31
32 #include "dyntbar.h"
33 #include "newbmpbtn.h"
34
35 IMPLEMENT_DYNAMIC_CLASS(wxDynamicToolBar, wxToolBarBase)
36
37 BEGIN_EVENT_TABLE( wxDynamicToolBar, wxToolBarBase )
38
39 EVT_SIZE ( wxDynamicToolBar::OnSize )
40 EVT_PAINT( wxDynamicToolBar::OnPaint )
41 //EVT_ERASE_BACKGROUND( wxDynamicToolBar::OnEraseBackground )
42
43 END_EVENT_TABLE()
44
45 /***** Implementation for class wxDynToolInfo *****/
46
47 IMPLEMENT_DYNAMIC_CLASS(wxDynToolInfo, wxToolLayoutItem)
48
49 /***** Implementation for class wxDynamicToolBar *****/
50
51 wxDynamicToolBar::wxDynamicToolBar()
52 : mpLayoutMan( NULL ),
53 mSepartorSize( 8 ),
54 mVertGap ( 0 ),
55 mHorizGap( 0 )
56 {
57 }
58
59 wxDynamicToolBar::wxDynamicToolBar(wxWindow *parent, const wxWindowID id,
60 const wxPoint& pos, const wxSize& size,
61 const long style, const int orientation,
62 const int RowsOrColumns, const wxString& name )
63 : mpLayoutMan( NULL ),
64 mSepartorSize( 8 ),
65 mVertGap ( 0 ),
66 mHorizGap( 0 )
67 {
68 Create(parent, id, pos, size, style, orientation, RowsOrColumns, name);
69
70 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE) );
71 }
72
73 bool wxDynamicToolBar::Create(wxWindow *parent, const wxWindowID id,
74 const wxPoint& pos,
75 const wxSize& size,
76 const long style,
77 const int orientation, const int RowsOrColumns,
78 const wxString& name)
79 {
80 // cut&pasted from wxtbatsmpl.h
81
82 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
83 return FALSE;
84
85 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE ));
86
87 return TRUE;
88 }
89
90 bool wxDynamicToolBar::Realize(void)
91 {
92 // FOR NOW:: nothing
93 return TRUE;
94 }
95
96 wxDynamicToolBar::~wxDynamicToolBar(void)
97 {
98 if ( mpLayoutMan ) delete mpLayoutMan;
99
100 for( size_t i = 0; i != mTools.Count(); ++i )
101
102 delete mTools[i];
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 int 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 wxToolBarTool*
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 for( size_t i = 0; i != mTools.Count(); ++i )
192
193 if ( mTools[i]->mIndex == toolIndex ) return mTools[i];
194
195 return NULL;
196 }
197
198 void wxDynamicToolBar::RemveTool( int toolIndex )
199 {
200 for( size_t i = 0; i != mTools.Count(); ++i )
201
202 if ( mTools[i]->mIndex == toolIndex )
203 {
204 if ( mTools[i]->mpToolWnd )
205
206 mTools[i]->mpToolWnd->Destroy();
207
208 mTools.Remove( i );
209
210 Layout();
211
212 return;
213 }
214
215 // TODO:: if not found, should it be an assertion?
216 }
217
218 void wxDynamicToolBar::AddSeparator( wxWindow* pSepartorWnd )
219 {
220 wxDynToolInfo* pInfo = new wxDynToolInfo();
221
222 pInfo->mpToolWnd = pSepartorWnd;
223 pInfo->mIndex = -1;
224 pInfo->mIsSeparator = TRUE;
225
226 if ( pSepartorWnd )
227 {
228 pSepartorWnd->Create( this, -1 );
229
230 int x,y;
231 pSepartorWnd->GetSize( &x, &y );
232 pInfo->mRealSize.x = x;
233 pInfo->mRealSize.y = y;
234
235 pInfo->mRect.width = x;
236 pInfo->mRect.height = y;
237 }
238 else
239 {
240 pInfo->mRealSize.x = mSepartorSize;
241 pInfo->mRealSize.y = 0;
242
243 pInfo->mRect.width = mSepartorSize;
244 pInfo->mRect.height = 0;
245 }
246
247 mTools.Add( pInfo );
248 }
249
250 void wxDynamicToolBar::OnEraseBackground( wxEraseEvent& event )
251 {
252 // FOR NOW:: nothing
253 }
254
255 void wxDynamicToolBar::OnSize( wxSizeEvent& event )
256 {
257 //SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE ) );
258
259 Layout();
260 }
261
262 void wxDynamicToolBar::DrawSeparator( wxDynToolInfo& info, wxDC& dc )
263 {
264 // check the orientation of separator
265 if ( info.mRect.width < info.mRect.height )
266 {
267 int midX = info.mRect.x + info.mRect.width/2 - 1;
268
269 dc.SetPen( *wxGREY_PEN );
270 dc.DrawLine( midX, info.mRect.y,
271 midX, info.mRect.y + info.mRect.height+1 );
272
273 dc.SetPen( *wxWHITE_PEN );
274 dc.DrawLine( midX+1, info.mRect.y,
275 midX+1, info.mRect.y + info.mRect.height+1 );
276 }
277 else
278 {
279 int midY = info.mRect.y + info.mRect.height/2 - 1;
280
281 dc.SetPen( *wxGREY_PEN );
282 dc.DrawLine( info.mRect.x, midY,
283 info.mRect.x + info.mRect.width+1, midY );
284
285 dc.SetPen( *wxWHITE_PEN );
286 dc.DrawLine( info.mRect.x, midY + 1,
287 info.mRect.x + info.mRect.width+1, midY + 1 );
288 }
289 }
290
291 void wxDynamicToolBar::OnPaint( wxPaintEvent& event )
292 {
293 // draw separators if any
294
295 wxPaintDC dc(this);
296
297 for( size_t i = 0; i != mTools.Count(); ++i )
298
299 if ( mTools[i]->mIsSeparator )
300 {
301 // check if separator doesn't have it's own window
302 // if so, then draw it using built-in drawing method
303
304 if ( !mTools[i]->mpToolWnd )
305
306 DrawSeparator( *mTools[i], dc );
307 }
308 }
309
310 // FOR NOW:: quick fix
311 #include "wx/choice.h"
312
313 void wxDynamicToolBar::SizeToolWindows()
314 {
315 for( size_t i = 0; i != mTools.Count(); ++i )
316 {
317 wxDynToolInfo& info = *mTools[i];
318
319 if ( !info.mIsSeparator )
320 {
321
322 // center real rectangle within the rectangle
323 // provided by the layout manager
324
325 int x = info.mRect.x;
326 int y = info.mRect.y + (info.mRect.height - info.mRealSize.y)/2;
327
328 // FOR NOW FOR NOW:: quick & dirty fix
329 if ( info.mpToolWnd->IsKindOf( CLASSINFO( wxChoice ) ) )
330 {
331 info.mpToolWnd->SetSize( x,y,
332 info.mRealSize.x - 3,
333 info.mRealSize.y);
334 }
335 else
336 info.mpToolWnd->SetSize( x,y,
337 info.mRealSize.x,
338 info.mRealSize.y );
339 }
340
341 // TBD:: size separator window if present
342 }
343 }
344
345 bool wxDynamicToolBar::Layout()
346 {
347 if ( !mpLayoutMan ) mpLayoutMan = CreateDefaulLayout();
348
349 int x,y;
350 GetSize( &x, &y );
351 wxSize wndDim(x,y);
352 wxSize result;
353
354 wxLayoutItemArrayT items;
355
356 // safe conversion
357 for( size_t i = 0; i != mTools.Count(); ++i ) items.Add( mTools[i] );
358
359 mpLayoutMan->Layout( wndDim, result, items, mVertGap, mHorizGap );;
360
361 SizeToolWindows();
362 return TRUE;
363 }
364
365 void wxDynamicToolBar::GetPreferredDim( const wxSize& givenDim, wxSize& prefDim )
366 {
367 if ( !mpLayoutMan ) mpLayoutMan = CreateDefaulLayout();
368
369 wxLayoutItemArrayT items;
370
371 // safe conversion
372 for( size_t i = 0; i != mTools.Count(); ++i ) items.Add( mTools[i] );
373
374 mpLayoutMan->Layout( givenDim, prefDim, items, mVertGap, mHorizGap );;
375 }
376
377 void wxDynamicToolBar::SetLayout( LayoutManagerBase* pLayout )
378 {
379 if ( mpLayoutMan ) delete mpLayoutMan;
380
381 mpLayoutMan = pLayout;
382
383 Layout();
384 }
385
386 void wxDynamicToolBar::EnableTool(const int toolIndex, const bool enable )
387 {
388 wxDynToolInfo* pInfo = GetToolInfo( toolIndex );
389
390 if ( !pInfo ) return;
391
392 if ( pInfo->mIsSeparator || !pInfo->mpToolWnd ) return;
393
394 pInfo->mpToolWnd->Enable( enable );
395 }
396
397 /***** Implementation for class BagLayout *****/
398
399 void BagLayout::Layout( const wxSize& parentDim,
400 wxSize& resultingDim,
401 wxLayoutItemArrayT& items,
402 int horizGap,
403 int vertGap
404 )
405 {
406 int maxWidth = 0;
407 int curY = 0;
408 int nRows = 0;
409
410 size_t i = 0;
411
412 while( i < items.Count() )
413 {
414 int curX = 0;
415 int height = 0;
416 int nItems = 0;
417
418 int firstItem = i;
419 int itemsInRow = 0;
420
421 if ( nRows > 0 ) curY += vertGap;
422
423 // step #1 - arrange horizontal positions of items in the row
424
425 do
426 {
427 if ( itemsInRow > 0 ) curX += horizGap;
428
429 wxRect& r = items[i]->mRect;
430
431 if ( curX + r.width > parentDim.x )
432
433 if ( itemsInRow > 0 ) break;
434
435 r.x = curX;
436 r.y = curY;
437
438 curX += r.width;
439
440 height = wxMax( height, r.height );
441
442 ++itemsInRow;
443 ++i;
444
445 } while( i < items.Count() );
446
447 curY += height;
448
449 maxWidth = wxMax( maxWidth, curX );
450 }
451
452 resultingDim.x = maxWidth;
453 resultingDim.y = curY;
454 }