]> git.saurik.com Git - wxWidgets.git/blob - src/mac/toolbar.cpp
applied (slightly modified) wxToggleButton patch from John Norris and Axel Schlueter
[wxWidgets.git] / src / mac / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: AUTHOR
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHORy
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "toolbar.h"
13 #endif
14
15 #include "wx/wx.h"
16
17 #if wxUSE_TOOLBAR
18
19 #include "wx/toolbar.h"
20 #include "wx/notebook.h"
21 #include "wx/tabctrl.h"
22
23 #if !USE_SHARED_LIBRARY
24 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
25
26 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
27 EVT_MOUSE_EVENTS( wxToolBar::OnMouse )
28 EVT_PAINT( wxToolBar::OnPaint )
29 END_EVENT_TABLE()
30 #endif
31
32 #include <wx/mac/uma.h>
33
34 // ----------------------------------------------------------------------------
35 // private classes
36 // ----------------------------------------------------------------------------
37
38 class wxToolBarTool : public wxToolBarToolBase
39 {
40 public:
41 wxToolBarTool(wxToolBar *tbar,
42 int id,
43 const wxBitmap& bitmap1,
44 const wxBitmap& bitmap2,
45 bool toggle,
46 wxObject *clientData,
47 const wxString& shortHelpString,
48 const wxString& longHelpString)
49 : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle,
50 clientData, shortHelpString, longHelpString)
51 {
52 m_nSepCount = 0;
53 m_index = -1 ;
54 }
55
56 wxToolBarTool(wxToolBar *tbar, wxControl *control)
57 : wxToolBarToolBase(tbar, control)
58 {
59 m_nSepCount = 1;
60 m_index = -1 ;
61 }
62
63 // set/get the number of separators which we use to cover the space used by
64 // a control in the toolbar
65 void SetSeparatorsCount(size_t count) { m_nSepCount = count; }
66 size_t GetSeparatorsCount() const { return m_nSepCount; }
67
68 int m_index ;
69 private:
70 size_t m_nSepCount;
71 };
72
73
74 // ============================================================================
75 // implementation
76 // ============================================================================
77
78 // ----------------------------------------------------------------------------
79 // wxToolBarTool
80 // ----------------------------------------------------------------------------
81
82 const short defwidth = 24 ;
83 const short defheight = 22 ;
84
85 wxToolBarToolBase *wxToolBar::CreateTool(int id,
86 const wxBitmap& bitmap1,
87 const wxBitmap& bitmap2,
88 bool toggle,
89 wxObject *clientData,
90 const wxString& shortHelpString,
91 const wxString& longHelpString)
92 {
93 return new wxToolBarTool(this, id, bitmap1, bitmap2, toggle,
94 clientData, shortHelpString, longHelpString);
95 }
96
97 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
98 {
99 return new wxToolBarTool(this, control);
100 }
101
102 void wxToolBar::Init()
103 {
104 m_maxWidth = -1;
105 m_maxHeight = -1;
106 m_defaultWidth = defwidth;
107 m_defaultHeight = defheight;
108 // TODO
109 }
110
111 bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
112 long style, const wxString& name)
113 {
114 m_maxWidth = m_maxHeight = 0;
115
116 m_defaultWidth = defwidth;
117 m_defaultHeight = defheight;
118
119 int x = pos.x;
120 int y = pos.y;
121 int width = size.x;
122 int height = size.y;
123
124 if (width <= 0)
125 width = 100;
126 if (height <= 0)
127 height = 30;
128 if (x < 0)
129 x = 0;
130 if (y < 0)
131 y = 0;
132 #if 1
133 {
134 SetName(name);
135
136 m_windowStyle = style;
137 parent->AddChild(this);
138
139 m_backgroundColour = parent->GetBackgroundColour() ;
140 m_foregroundColour = parent->GetForegroundColour() ;
141
142 if (id == -1)
143 m_windowId = NewControlId();
144 else
145 m_windowId = id;
146
147 m_width = size.x ;
148 m_height = size.y ;
149 int x = pos.x ;
150 int y = pos.y ;
151 AdjustForParentClientOrigin(x, y, wxSIZE_USE_EXISTING);
152 m_x = x ;
153 m_y = y ;
154 }
155 #else
156 Rect bounds ;
157 Str255 title ;
158
159 MacPreControlCreate( parent , id , "" , wxPoint( x , y ) , wxSize( width , height ) ,style, wxDefaultValidator , name , &bounds , title ) ;
160
161 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
162 kControlPlacardProc , (long) this ) ;
163 MacPostControlCreate() ;
164 #endif
165 return TRUE;
166 }
167
168 wxToolBar::~wxToolBar()
169 {
170 // TODO
171 }
172
173 PicHandle MakePict(GWorldPtr wp, GWorldPtr mask ) ;
174 PicHandle MakePict(GWorldPtr wp, GWorldPtr mask )
175 {
176 CGrafPtr origPort ;
177 GDHandle origDev ;
178
179 PicHandle pict; // this is the Picture we give back
180
181 RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ;
182 RGBColor white = { 0xffff ,0xffff , 0xffff } ;
183 RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ;
184
185 unsigned char *maskimage = NULL ;
186 Rect portRect ;
187 GetPortBounds( wp , &portRect ) ;
188 int width = portRect.right - portRect.left ;
189 int height = portRect.bottom - portRect.top ;
190
191 LockPixels( GetGWorldPixMap( wp ) ) ;
192 GetGWorld( &origPort , &origDev ) ;
193
194 if ( mask )
195 {
196
197 maskimage = (unsigned char*) malloc( width * height ) ;
198 SetGWorld( mask , NULL ) ;
199 LockPixels( GetGWorldPixMap( mask ) ) ;
200 for ( int y = 0 ; y < height ; ++y )
201 {
202 for( int x = 0 ; x < width ; ++x )
203 {
204 RGBColor col ;
205
206 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
207 maskimage[y*width + x] = ( col.red == 0 ) ; // for monochrome masks
208 }
209 }
210 UnlockPixels( GetGWorldPixMap( mask ) ) ;
211 }
212
213 SetGWorld( wp , NULL ) ;
214
215 pict = OpenPicture(&portRect); // open a picture, this disables drawing
216 if(!pict)
217 return NULL;
218
219 RGBBackColor( &gray ) ;
220 RGBForeColor( &black ) ;
221 EraseRect(&portRect) ;
222 RGBBackColor( &white ) ;
223
224 if ( maskimage )
225 {
226 for ( int y = 0 ; y < height ; ++y )
227 {
228 for( int x = 0 ; x < width ; ++x )
229 {
230 if ( maskimage[y*width + x] )
231 {
232 RGBColor col ;
233
234 GetCPixel( x + portRect.left , y + portRect.top , &col ) ;
235 SetCPixel( x + portRect.left , y + portRect.top , &col ) ;
236 }
237 }
238 }
239 free( maskimage ) ;
240 maskimage = NULL ;
241 }
242 else
243 {
244 CopyBits(GetPortBitMapForCopyBits(wp), // src PixMap - we copy image over itself -
245 GetPortBitMapForCopyBits(wp), // dst PixMap - no drawing occurs -
246 &portRect, // srcRect - it will be recorded and compressed -
247 &portRect, // dstRect - into the picture that is open -
248 srcCopy,NULL); // copyMode and no clip region
249
250 }
251 ClosePicture(); // We are done recording the picture
252 UnlockPixels( GetGWorldPixMap( wp ) ) ;
253 SetGWorld( origPort , origDev ) ;
254 return pict; // return our groovy pict handle
255 }
256
257 const short kwxMacToolBarTopMargin = 2 ;
258 const short kwxMacToolBarLeftMargin = 2 ;
259
260 bool wxToolBar::Realize()
261 {
262 if (m_tools.Number() == 0)
263 return FALSE;
264
265 Rect toolbarrect = { m_y , m_x , m_y + m_height , m_x + m_width } ;
266 ControlFontStyleRec controlstyle ;
267 WindowPtr window = GetMacRootWindow() ;
268 controlstyle.flags = kControlUseFontMask ;
269 controlstyle.font = kControlFontSmallSystemFont ;
270
271 wxNode *node = m_tools.First();
272 int noButtons = 0;
273 int x = 0 ;
274 wxSize toolSize = GetToolSize() ;
275 int tw, th;
276 GetSize(& tw, & th);
277 while (node)
278 {
279 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
280 wxBitmapRefData * bmap = (wxBitmapRefData*) ( tool->GetBitmap1().GetRefData()) ;
281
282 if( !tool->IsSeparator() )
283 {
284 Rect toolrect = { toolbarrect.top + kwxMacToolBarTopMargin , toolbarrect.left + x + kwxMacToolBarLeftMargin , 0 , 0 } ;
285 toolrect.right = toolrect.left + toolSize.x ;
286 toolrect.bottom = toolrect.top + toolSize.y ;
287
288 PicHandle icon = NULL ;
289 if ( bmap )
290 {
291 if ( bmap->m_bitmapType == kMacBitmapTypePict )
292 icon = bmap->m_hPict ;
293 else if ( bmap->m_bitmapType == kMacBitmapTypeGrafWorld )
294 {
295 if ( tool->GetBitmap1().GetMask() )
296 {
297 icon = MakePict( bmap->m_hBitmap , tool->GetBitmap1().GetMask()->GetMaskBitmap() ) ;
298 }
299 else
300 {
301 icon = MakePict( bmap->m_hBitmap , NULL ) ;
302 }
303 }
304 }
305
306 ControlHandle m_macToolHandle ;
307
308 SInt16 behaviour = kControlBehaviorOffsetContents ;
309 if ( tool->CanBeToggled() )
310 behaviour += kControlBehaviorToggles ;
311
312 if ( icon )
313 {
314 m_macToolHandle = UMANewControl( window , &toolrect , "\p" , true , 0 ,
315 behaviour + kControlContentPictHandle , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ;
316 ControlButtonContentInfo info ;
317
318 info.contentType = kControlContentPictHandle ;
319 info.u.picture = icon ;
320
321 UMASetControlData( m_macToolHandle , kControlButtonPart , kControlBevelButtonContentTag , sizeof(info) , (char*) &info ) ;
322 }
323 else
324 {
325 m_macToolHandle = UMANewControl( window , &toolrect , "\p" , true , 0 ,
326 behaviour , 0 , kControlBevelButtonNormalBevelProc , (long) this ) ;
327 }
328 m_macToolHandles.Add( m_macToolHandle ) ;
329 tool->m_index = m_macToolHandles.Count() -1 ;
330 if ( !tool->IsEnabled() )
331 {
332 UMADeactivateControl( m_macToolHandle ) ;
333 }
334 if ( tool->CanBeToggled() && tool->IsToggled() )
335 {
336 ::SetControlValue( m_macToolHandle , 1 ) ;
337 }
338 UMASetControlFontStyle( m_macToolHandle , &controlstyle ) ;
339 ControlHandle container = GetParent()->MacGetContainerForEmbedding() ;
340 wxASSERT_MSG( container != NULL , "No valid mac container control" ) ;
341 UMAEmbedControl( m_macToolHandle , container ) ;
342
343 x += (int)toolSize.x;
344 noButtons ++;
345 }
346 else
347 {
348 m_macToolHandles.Add( NULL ) ;
349 x += (int)toolSize.x / 4;
350 }
351 if ( toolbarrect.left + x + kwxMacToolBarLeftMargin > m_maxWidth)
352 m_maxWidth = toolbarrect.left + x + kwxMacToolBarLeftMargin;
353 if (toolbarrect.top + kwxMacToolBarTopMargin + toolSize.y > m_maxHeight)
354 m_maxHeight = toolbarrect.top + kwxMacToolBarTopMargin ;
355
356 node = node->Next();
357 }
358
359 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
360 {
361 m_maxWidth = tw ; // +=toolSize.x;
362 m_maxHeight += toolSize.y;
363 m_maxHeight += m_yMargin;
364 }
365 else
366 {
367 m_maxHeight = th ;// += toolSize.y;
368 m_maxWidth += toolSize.x;
369 m_maxWidth += m_xMargin;
370 }
371
372 SetSize(m_maxWidth, m_maxHeight);
373
374 return TRUE;
375 }
376
377 void wxToolBar::SetToolBitmapSize(const wxSize& size)
378 {
379 m_defaultWidth = size.x; m_defaultHeight = size.y;
380 }
381
382 // The button size is bigger than the bitmap size
383 wxSize wxToolBar::GetToolSize() const
384 {
385 return wxSize(m_defaultWidth + 4, m_defaultHeight + 4);
386 }
387
388 void wxToolBar::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
389 {
390 int index = 0 ;
391 for ( index = 0 ; index < m_macToolHandles.Count() ; ++index )
392 {
393 if ( m_macToolHandles[index] == (void*) control )
394 {
395 wxToolBarTool *tool = (wxToolBarTool *)m_tools.Nth( index )->Data();
396 if ( tool->CanBeToggled() )
397 {
398 tool->Toggle( GetControlValue( control ) ) ;
399 }
400 OnLeftClick( tool->GetId() , tool -> IsToggled() ) ;
401 break ;
402 }
403 }
404 }
405
406 void wxToolBar::SetRows(int nRows)
407 {
408 if ( nRows == m_maxRows )
409 {
410 // avoid resizing the frame uselessly
411 return;
412 }
413
414 m_maxRows = nRows;
415 }
416
417 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
418 {
419 MacClientToRootWindow( &x , &y ) ;
420 Point pt = { y ,x } ;
421
422 int index = 0 ;
423 for ( index = 0 ; index < m_macToolHandles.Count() ; ++index )
424 {
425 if ( m_macToolHandles[index] )
426 {
427 Rect bounds ;
428 GetControlBounds((ControlHandle) m_macToolHandles[index], &bounds ) ;
429 if ( PtInRect( pt , &bounds ) )
430 {
431 return (wxToolBarTool*) (m_tools.Nth( index )->Data() ) ;
432 }
433 }
434 }
435
436 return (wxToolBarToolBase *)NULL;
437 }
438
439 wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
440 {
441 wxToolBarToolBase* tool = FindToolForPosition( pt.x , pt.y ) ;
442 if ( tool )
443 {
444 return tool->GetShortHelp() ;
445 }
446 return "" ;
447 }
448
449 void wxToolBar::DoEnableTool(wxToolBarToolBase *t, bool enable)
450 {
451 wxToolBarTool *tool = (wxToolBarTool *)t;
452 if ( tool->m_index < 0 )
453 return ;
454
455 ControlHandle control = (ControlHandle) m_macToolHandles[ tool->m_index ] ;
456
457 if ( enable )
458 UMAActivateControl( control ) ;
459 else
460 UMADeactivateControl( control ) ;
461 }
462
463 void wxToolBar::DoToggleTool(wxToolBarToolBase *t, bool toggle)
464 {
465 wxToolBarTool *tool = (wxToolBarTool *)t;
466 if ( tool->m_index < 0 )
467 return ;
468
469 ControlHandle control = (ControlHandle) m_macToolHandles[ tool->m_index ] ;
470 ::SetControlValue( control , toggle ) ;
471 }
472
473 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
474 wxToolBarToolBase *tool)
475 {
476 // nothing special to do here - we really create the toolbar buttons in
477 // Realize() later
478 tool->Attach(this);
479
480 return TRUE;
481 }
482
483 void wxToolBar::DoSetToggle(wxToolBarToolBase *t, bool toggle)
484 {
485 wxToolBarTool *tool = (wxToolBarTool *)t;
486 // TODO: set toggle state
487 }
488
489 bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
490 {
491 return TRUE ;
492 }
493
494 void wxToolBar::OnPaint(wxPaintEvent& event)
495 {
496 WindowRef window = GetMacRootWindow() ;
497 if ( window )
498 {
499 wxWindow* win = wxFindWinFromMacWindow( window ) ;
500 if ( win )
501 {
502 wxMacDrawingHelper help( win ) ;
503 // the mac control manager always assumes to have the origin at 0,0
504 SetOrigin( 0 , 0 ) ;
505
506 bool hasTabBehind = false ;
507 wxWindow* parent = GetParent() ;
508 while ( parent )
509 {
510 if( parent->MacGetWindowData() )
511 {
512 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
513 break ;
514 }
515
516 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
517 {
518 if ( ((wxControl*)parent)->GetMacControl() )
519 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
520 break ;
521 }
522
523 parent = parent->GetParent() ;
524 }
525 Rect toolbarrect = { m_y , m_x , m_y + m_height , m_x + m_width } ;
526
527 UMADrawThemePlacard( &toolbarrect , IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
528 {
529 int index = 0 ;
530 for ( index = 0 ; index < m_macToolHandles.Count() ; ++index )
531 {
532 if ( m_macToolHandles[index] )
533 {
534 UMADrawControl( (ControlHandle) m_macToolHandles[index] ) ;
535 }
536 }
537 }
538 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
539 }
540 }
541 }
542 void wxToolBar::OnMouse( wxMouseEvent &event )
543 {
544
545 if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK )
546 {
547
548 int x = event.m_x ;
549 int y = event.m_y ;
550
551 MacClientToRootWindow( &x , &y ) ;
552
553 ControlHandle control ;
554 Point localwhere ;
555 GrafPtr port ;
556 SInt16 controlpart ;
557 WindowRef window = GetMacRootWindow() ;
558
559 localwhere.h = x ;
560 localwhere.v = y ;
561
562 short modifiers = 0;
563
564 if ( !event.m_leftDown && !event.m_rightDown )
565 modifiers |= btnState ;
566
567 if ( event.m_shiftDown )
568 modifiers |= shiftKey ;
569
570 if ( event.m_controlDown )
571 modifiers |= controlKey ;
572
573 if ( event.m_altDown )
574 modifiers |= optionKey ;
575
576 if ( event.m_metaDown )
577 modifiers |= cmdKey ;
578
579 controlpart = FindControl( localwhere , window , &control ) ;
580 {
581 if ( AcceptsFocus() && FindFocus() != this )
582 {
583 SetFocus() ;
584 }
585 if ( control && UMAIsControlActive( control ) )
586 {
587 {
588 if ( controlpart == kControlIndicatorPart && !UMAHasAppearance() )
589 controlpart = UMAHandleControlClick( control , localwhere , modifiers , (ControlActionUPP) NULL ) ;
590 else
591 controlpart = UMAHandleControlClick( control , localwhere , modifiers , (ControlActionUPP) -1 ) ;
592 wxTheApp->s_lastMouseDown = 0 ;
593 if ( controlpart && ! ( ( UMAHasAppearance() || (controlpart != kControlIndicatorPart) )
594 && (IsKindOf( CLASSINFO( wxScrollBar ) ) ) ) ) // otherwise we will get the event twice
595 {
596 MacHandleControlClick( control , controlpart ) ;
597 }
598 }
599 }
600 }
601 }
602 }
603
604 #endif // wxUSE_TOOLBAR
605