PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/osx/carbon/toolbar.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1625 lines | 1273 code | 267 blank | 85 comment | 246 complexity | 45d084c541478fc31ba47f5f0b56fea1 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/osx/carbon/toolbar.cpp
  3. // Purpose: wxToolBar
  4. // Author: Stefan Csomor
  5. // Modified by:
  6. // Created: 04/01/98
  7. // RCS-ID: $Id$
  8. // Copyright: (c) Stefan Csomor
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include "wx/wxprec.h"
  12. #if wxUSE_TOOLBAR
  13. #include "wx/toolbar.h"
  14. #ifndef WX_PRECOMP
  15. #include "wx/wx.h"
  16. #endif
  17. #include "wx/app.h"
  18. #include "wx/osx/private.h"
  19. #include "wx/geometry.h"
  20. #include "wx/sysopt.h"
  21. const short kwxMacToolBarToolDefaultWidth = 16;
  22. const short kwxMacToolBarToolDefaultHeight = 16;
  23. const short kwxMacToolBarTopMargin = 4;
  24. const short kwxMacToolBarLeftMargin = 4;
  25. const short kwxMacToolBorder = 0;
  26. const short kwxMacToolSpacing = 6;
  27. BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
  28. EVT_PAINT( wxToolBar::OnPaint )
  29. END_EVENT_TABLE()
  30. #pragma mark -
  31. #pragma mark Tool Implementation
  32. // ----------------------------------------------------------------------------
  33. // private classes
  34. // ----------------------------------------------------------------------------
  35. // We have a dual implementation for each tool, ControlRef and HIToolbarItemRef
  36. // when embedding native controls in the native toolbar we must make sure the
  37. // control does not get deleted behind our backs, so the retain count gets increased
  38. // (after creation it is 1), first be the creation of the custom HIToolbarItem wrapper
  39. // object, and second by the code 'creating' the custom HIView (which is the same as the
  40. // already existing native control, therefore we just increase the ref count)
  41. // when this view is removed from the native toolbar its count gets decremented again
  42. // and when the HITooolbarItem wrapper object gets destroyed it is decremented as well
  43. // so in the end the control lives with a refcount of one and can be disposed of by the
  44. // wxControl code. For embedded controls on a non-native toolbar this ref count is less
  45. // so we can only test against a range, not a specific value of the refcount.
  46. class wxToolBarTool : public wxToolBarToolBase
  47. {
  48. public:
  49. wxToolBarTool(
  50. wxToolBar *tbar,
  51. int id,
  52. const wxString& label,
  53. const wxBitmap& bmpNormal,
  54. const wxBitmap& bmpDisabled,
  55. wxItemKind kind,
  56. wxObject *clientData,
  57. const wxString& shortHelp,
  58. const wxString& longHelp );
  59. wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
  60. : wxToolBarToolBase(tbar, control, label)
  61. {
  62. Init();
  63. if (control != NULL)
  64. SetControlHandle( (ControlRef) control->GetHandle() );
  65. }
  66. virtual ~wxToolBarTool()
  67. {
  68. ClearControl();
  69. }
  70. WXWidget GetControlHandle()
  71. {
  72. return (WXWidget) m_controlHandle;
  73. }
  74. void SetControlHandle( ControlRef handle )
  75. {
  76. m_controlHandle = handle;
  77. }
  78. void SetPosition( const wxPoint& position );
  79. void ClearControl()
  80. {
  81. if ( m_controlHandle )
  82. {
  83. if ( !IsControl() )
  84. DisposeControl( m_controlHandle );
  85. else
  86. {
  87. // the embedded control is not under the responsibility of the tool, it gets disposed of in the
  88. // proper wxControl destructor
  89. }
  90. m_controlHandle = NULL ;
  91. }
  92. #if wxOSX_USE_NATIVE_TOOLBAR
  93. if ( m_toolbarItemRef )
  94. {
  95. CFIndex count = CFGetRetainCount( m_toolbarItemRef ) ;
  96. // different behaviour under Leopard
  97. if ( UMAGetSystemVersion() < 0x1050 )
  98. {
  99. if ( count != 1 )
  100. {
  101. wxFAIL_MSG("Reference count of native tool was not 1 in wxToolBarTool destructor");
  102. }
  103. }
  104. wxTheApp->MacAddToAutorelease(m_toolbarItemRef);
  105. CFRelease(m_toolbarItemRef);
  106. m_toolbarItemRef = NULL;
  107. }
  108. #endif // wxOSX_USE_NATIVE_TOOLBAR
  109. }
  110. wxSize GetSize() const
  111. {
  112. wxSize curSize;
  113. if ( IsControl() )
  114. {
  115. curSize = GetControl()->GetSize();
  116. }
  117. else if ( IsButton() )
  118. {
  119. curSize = GetToolBar()->GetToolSize();
  120. }
  121. else
  122. {
  123. // separator size
  124. curSize = GetToolBar()->GetToolSize();
  125. if ( GetToolBar()->GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) )
  126. curSize.y /= 4;
  127. else
  128. curSize.x /= 4;
  129. }
  130. return curSize;
  131. }
  132. wxPoint GetPosition() const
  133. {
  134. return wxPoint( m_x, m_y );
  135. }
  136. virtual bool Enable( bool enable );
  137. void UpdateToggleImage( bool toggle );
  138. virtual bool Toggle(bool toggle)
  139. {
  140. if ( wxToolBarToolBase::Toggle( toggle ) == false )
  141. return false;
  142. UpdateToggleImage(toggle);
  143. return true;
  144. }
  145. void UpdateHelpStrings()
  146. {
  147. #if wxOSX_USE_NATIVE_TOOLBAR
  148. if ( m_toolbarItemRef )
  149. {
  150. wxFontEncoding enc = GetToolBarFontEncoding();
  151. HIToolbarItemSetHelpText(
  152. m_toolbarItemRef,
  153. wxCFStringRef( GetShortHelp(), enc ),
  154. wxCFStringRef( GetLongHelp(), enc ) );
  155. }
  156. #endif
  157. }
  158. virtual bool SetShortHelp(const wxString& help)
  159. {
  160. if ( wxToolBarToolBase::SetShortHelp( help ) == false )
  161. return false;
  162. UpdateHelpStrings();
  163. return true;
  164. }
  165. virtual bool SetLongHelp(const wxString& help)
  166. {
  167. if ( wxToolBarToolBase::SetLongHelp( help ) == false )
  168. return false;
  169. UpdateHelpStrings();
  170. return true;
  171. }
  172. virtual void SetNormalBitmap(const wxBitmap& bmp)
  173. {
  174. wxToolBarToolBase::SetNormalBitmap(bmp);
  175. UpdateToggleImage(CanBeToggled() && IsToggled());
  176. }
  177. virtual void SetLabel(const wxString& label)
  178. {
  179. wxToolBarToolBase::SetLabel(label);
  180. #if wxOSX_USE_NATIVE_TOOLBAR
  181. if ( m_toolbarItemRef )
  182. {
  183. // strip mnemonics from the label for compatibility with the usual
  184. // labels in wxStaticText sense
  185. wxString labelStr = wxStripMenuCodes(label);
  186. HIToolbarItemSetLabel(
  187. m_toolbarItemRef,
  188. wxCFStringRef(labelStr, GetToolBarFontEncoding()) );
  189. }
  190. #endif
  191. }
  192. #if wxOSX_USE_NATIVE_TOOLBAR
  193. void SetToolbarItemRef( HIToolbarItemRef ref )
  194. {
  195. if ( m_controlHandle )
  196. HideControl( m_controlHandle );
  197. if ( m_toolbarItemRef )
  198. CFRelease( m_toolbarItemRef );
  199. m_toolbarItemRef = ref;
  200. UpdateHelpStrings();
  201. }
  202. HIToolbarItemRef GetToolbarItemRef() const
  203. {
  204. return m_toolbarItemRef;
  205. }
  206. void SetIndex( CFIndex idx )
  207. {
  208. m_index = idx;
  209. }
  210. CFIndex GetIndex() const
  211. {
  212. return m_index;
  213. }
  214. #endif // wxOSX_USE_NATIVE_TOOLBAR
  215. private:
  216. #if wxOSX_USE_NATIVE_TOOLBAR
  217. wxFontEncoding GetToolBarFontEncoding() const
  218. {
  219. wxFont f;
  220. if ( GetToolBar() )
  221. f = GetToolBar()->GetFont();
  222. return f.IsOk() ? f.GetEncoding() : wxFont::GetDefaultEncoding();
  223. }
  224. #endif // wxOSX_USE_NATIVE_TOOLBAR
  225. void Init()
  226. {
  227. m_controlHandle = NULL;
  228. #if wxOSX_USE_NATIVE_TOOLBAR
  229. m_toolbarItemRef = NULL;
  230. m_index = -1;
  231. #endif
  232. }
  233. ControlRef m_controlHandle;
  234. wxCoord m_x;
  235. wxCoord m_y;
  236. #if wxOSX_USE_NATIVE_TOOLBAR
  237. HIToolbarItemRef m_toolbarItemRef;
  238. // position in its toolbar, -1 means not inserted
  239. CFIndex m_index;
  240. #endif
  241. };
  242. static const EventTypeSpec eventList[] =
  243. {
  244. { kEventClassControl, kEventControlHit },
  245. { kEventClassControl, kEventControlHitTest },
  246. };
  247. static pascal OSStatus wxMacToolBarToolControlEventHandler( EventHandlerCallRef WXUNUSED(handler), EventRef event, void *data )
  248. {
  249. OSStatus result = eventNotHandledErr;
  250. ControlRef controlRef;
  251. wxMacCarbonEvent cEvent( event );
  252. cEvent.GetParameter( kEventParamDirectObject, &controlRef );
  253. switch ( GetEventKind( event ) )
  254. {
  255. case kEventControlHit:
  256. {
  257. wxToolBarTool *tbartool = (wxToolBarTool*)data;
  258. wxToolBar *tbar = tbartool != NULL ? (wxToolBar*) (tbartool->GetToolBar()) : NULL;
  259. if ((tbartool != NULL) && tbartool->CanBeToggled())
  260. {
  261. bool shouldToggle;
  262. shouldToggle = !tbartool->IsToggled();
  263. tbar->ToggleTool( tbartool->GetId(), shouldToggle );
  264. }
  265. if (tbartool != NULL)
  266. tbar->OnLeftClick( tbartool->GetId(), tbartool->IsToggled() );
  267. result = noErr;
  268. }
  269. break;
  270. case kEventControlHitTest:
  271. {
  272. HIPoint pt = cEvent.GetParameter<HIPoint>(kEventParamMouseLocation);
  273. HIRect rect;
  274. HIViewGetBounds( controlRef, &rect );
  275. ControlPartCode pc = kControlNoPart;
  276. if ( CGRectContainsPoint( rect, pt ) )
  277. pc = kControlIconPart;
  278. cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, pc );
  279. result = noErr;
  280. }
  281. break;
  282. default:
  283. break;
  284. }
  285. return result;
  286. }
  287. static pascal OSStatus wxMacToolBarToolEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
  288. {
  289. OSStatus result = eventNotHandledErr;
  290. switch ( GetEventClass( event ) )
  291. {
  292. case kEventClassControl:
  293. result = wxMacToolBarToolControlEventHandler( handler, event, data );
  294. break;
  295. default:
  296. break;
  297. }
  298. return result;
  299. }
  300. DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarToolEventHandler )
  301. #if wxOSX_USE_NATIVE_TOOLBAR
  302. static const EventTypeSpec toolBarEventList[] =
  303. {
  304. { kEventClassToolbarItem, kEventToolbarItemPerformAction },
  305. };
  306. static pascal OSStatus wxMacToolBarCommandEventHandler( EventHandlerCallRef WXUNUSED(handler), EventRef event, void *data )
  307. {
  308. OSStatus result = eventNotHandledErr;
  309. switch ( GetEventKind( event ) )
  310. {
  311. case kEventToolbarItemPerformAction:
  312. {
  313. wxToolBarTool* tbartool = (wxToolBarTool*) data;
  314. if ( tbartool != NULL )
  315. {
  316. wxToolBar *tbar = (wxToolBar*)(tbartool->GetToolBar());
  317. int toolID = tbartool->GetId();
  318. if ( tbartool->CanBeToggled() )
  319. {
  320. if ( tbar != NULL )
  321. tbar->ToggleTool(toolID, !tbartool->IsToggled() );
  322. }
  323. if ( tbar != NULL )
  324. tbar->OnLeftClick( toolID, tbartool->IsToggled() );
  325. result = noErr;
  326. }
  327. }
  328. break;
  329. default:
  330. break;
  331. }
  332. return result;
  333. }
  334. static pascal OSStatus wxMacToolBarEventHandler( EventHandlerCallRef handler, EventRef event, void *data )
  335. {
  336. OSStatus result = eventNotHandledErr;
  337. switch ( GetEventClass( event ) )
  338. {
  339. case kEventClassToolbarItem:
  340. result = wxMacToolBarCommandEventHandler( handler, event, data );
  341. break;
  342. default:
  343. break;
  344. }
  345. return result;
  346. }
  347. DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacToolBarEventHandler )
  348. #endif
  349. bool wxToolBarTool::Enable( bool enable )
  350. {
  351. if ( wxToolBarToolBase::Enable( enable ) == false )
  352. return false;
  353. if ( IsControl() )
  354. {
  355. GetControl()->Enable( enable );
  356. }
  357. else if ( IsButton() )
  358. {
  359. #if wxOSX_USE_NATIVE_TOOLBAR
  360. if ( m_toolbarItemRef != NULL )
  361. HIToolbarItemSetEnabled( m_toolbarItemRef, enable );
  362. #endif
  363. if ( m_controlHandle != NULL )
  364. {
  365. if ( enable )
  366. EnableControl( m_controlHandle );
  367. else
  368. DisableControl( m_controlHandle );
  369. }
  370. }
  371. return true;
  372. }
  373. void wxToolBarTool::SetPosition( const wxPoint& position )
  374. {
  375. m_x = position.x;
  376. m_y = position.y;
  377. int mac_x = position.x;
  378. int mac_y = position.y;
  379. if ( IsButton() )
  380. {
  381. Rect contrlRect;
  382. GetControlBounds( m_controlHandle, &contrlRect );
  383. int former_mac_x = contrlRect.left;
  384. int former_mac_y = contrlRect.top;
  385. GetToolBar()->GetToolSize();
  386. if ( mac_x != former_mac_x || mac_y != former_mac_y )
  387. {
  388. ::MoveControl( m_controlHandle, mac_x, mac_y );
  389. }
  390. }
  391. else if ( IsControl() )
  392. {
  393. // embedded native controls are moved by the OS
  394. #if wxOSX_USE_NATIVE_TOOLBAR
  395. if ( ((wxToolBar*)GetToolBar())->MacWantsNativeToolbar() == false )
  396. #endif
  397. {
  398. GetControl()->Move( position );
  399. }
  400. }
  401. else
  402. {
  403. // separator
  404. Rect contrlRect;
  405. GetControlBounds( m_controlHandle, &contrlRect );
  406. int former_mac_x = contrlRect.left;
  407. int former_mac_y = contrlRect.top;
  408. if ( mac_x != former_mac_x || mac_y != former_mac_y )
  409. ::MoveControl( m_controlHandle, mac_x, mac_y );
  410. }
  411. }
  412. void wxToolBarTool::UpdateToggleImage( bool toggle )
  413. {
  414. if ( toggle )
  415. {
  416. int w = m_bmpNormal.GetWidth() + 6;
  417. int h = m_bmpNormal.GetHeight() + 6;
  418. wxBitmap bmp( w, h );
  419. wxMemoryDC dc;
  420. dc.SelectObject( bmp );
  421. wxColour mid_grey_75 = wxColour(128, 128, 128, 196);
  422. wxColour light_grey_75 = wxColour(196, 196, 196, 196);
  423. dc.GradientFillLinear( wxRect(1, 1, w - 1, h-1),
  424. light_grey_75, mid_grey_75, wxNORTH);
  425. wxColour black_50 = wxColour(0, 0, 0, 127);
  426. dc.SetPen( wxPen(black_50) );
  427. dc.DrawRoundedRectangle( 0, 0, w, h, 1.5 );
  428. dc.DrawBitmap( m_bmpNormal, 3, 3, true );
  429. dc.SelectObject( wxNullBitmap );
  430. ControlButtonContentInfo info;
  431. wxMacCreateBitmapButton( &info, bmp );
  432. SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
  433. #if wxOSX_USE_NATIVE_TOOLBAR
  434. if (m_toolbarItemRef != NULL)
  435. {
  436. ControlButtonContentInfo info2;
  437. wxMacCreateBitmapButton( &info2, bmp, kControlContentCGImageRef);
  438. HIToolbarItemSetImage( m_toolbarItemRef, info2.u.imageRef );
  439. wxMacReleaseBitmapButton( &info2 );
  440. }
  441. #endif
  442. wxMacReleaseBitmapButton( &info );
  443. }
  444. else
  445. {
  446. ControlButtonContentInfo info;
  447. wxMacCreateBitmapButton( &info, m_bmpNormal );
  448. SetControlData( m_controlHandle, 0, kControlIconContentTag, sizeof(info), (Ptr)&info );
  449. #if wxOSX_USE_NATIVE_TOOLBAR
  450. if (m_toolbarItemRef != NULL)
  451. {
  452. ControlButtonContentInfo info2;
  453. wxMacCreateBitmapButton( &info2, m_bmpNormal, kControlContentCGImageRef);
  454. HIToolbarItemSetImage( m_toolbarItemRef, info2.u.imageRef );
  455. wxMacReleaseBitmapButton( &info2 );
  456. }
  457. #endif
  458. wxMacReleaseBitmapButton( &info );
  459. }
  460. IconTransformType transform = toggle ? kTransformSelected : kTransformNone;
  461. SetControlData(
  462. m_controlHandle, 0, kControlIconTransformTag,
  463. sizeof(transform), (Ptr)&transform );
  464. HIViewSetNeedsDisplay( m_controlHandle, true );
  465. }
  466. wxToolBarTool::wxToolBarTool(
  467. wxToolBar *tbar,
  468. int id,
  469. const wxString& label,
  470. const wxBitmap& bmpNormal,
  471. const wxBitmap& bmpDisabled,
  472. wxItemKind kind,
  473. wxObject *clientData,
  474. const wxString& shortHelp,
  475. const wxString& longHelp )
  476. :
  477. wxToolBarToolBase(
  478. tbar, id, label, bmpNormal, bmpDisabled, kind,
  479. clientData, shortHelp, longHelp )
  480. {
  481. Init();
  482. }
  483. #pragma mark -
  484. #pragma mark Toolbar Implementation
  485. wxToolBarToolBase *wxToolBar::CreateTool(
  486. int id,
  487. const wxString& label,
  488. const wxBitmap& bmpNormal,
  489. const wxBitmap& bmpDisabled,
  490. wxItemKind kind,
  491. wxObject *clientData,
  492. const wxString& shortHelp,
  493. const wxString& longHelp )
  494. {
  495. return new wxToolBarTool(
  496. this, id, label, bmpNormal, bmpDisabled, kind,
  497. clientData, shortHelp, longHelp );
  498. }
  499. wxToolBarToolBase *
  500. wxToolBar::CreateTool(wxControl *control, const wxString& label)
  501. {
  502. return new wxToolBarTool(this, control, label);
  503. }
  504. void wxToolBar::Init()
  505. {
  506. m_maxWidth = -1;
  507. m_maxHeight = -1;
  508. m_defaultWidth = kwxMacToolBarToolDefaultWidth;
  509. m_defaultHeight = kwxMacToolBarToolDefaultHeight;
  510. #if wxOSX_USE_NATIVE_TOOLBAR
  511. m_macToolbar = NULL;
  512. m_macUsesNativeToolbar = false;
  513. #endif
  514. }
  515. #define kControlToolbarItemClassID CFSTR( "org.wxwidgets.controltoolbaritem" )
  516. const EventTypeSpec kEvents[] =
  517. {
  518. { kEventClassHIObject, kEventHIObjectConstruct },
  519. { kEventClassHIObject, kEventHIObjectInitialize },
  520. { kEventClassHIObject, kEventHIObjectDestruct },
  521. { kEventClassToolbarItem, kEventToolbarItemCreateCustomView }
  522. };
  523. const EventTypeSpec kViewEvents[] =
  524. {
  525. { kEventClassControl, kEventControlGetSizeConstraints }
  526. };
  527. struct ControlToolbarItem
  528. {
  529. HIToolbarItemRef toolbarItem;
  530. HIViewRef viewRef;
  531. wxSize lastValidSize ;
  532. };
  533. static pascal OSStatus ControlToolbarItemHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
  534. {
  535. OSStatus result = eventNotHandledErr;
  536. ControlToolbarItem* object = (ControlToolbarItem*)inUserData;
  537. switch ( GetEventClass( inEvent ) )
  538. {
  539. case kEventClassHIObject:
  540. switch ( GetEventKind( inEvent ) )
  541. {
  542. case kEventHIObjectConstruct:
  543. {
  544. HIObjectRef toolbarItem;
  545. ControlToolbarItem* item;
  546. GetEventParameter( inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL,
  547. sizeof( HIObjectRef ), NULL, &toolbarItem );
  548. item = (ControlToolbarItem*) malloc(sizeof(ControlToolbarItem)) ;
  549. item->toolbarItem = toolbarItem ;
  550. item->lastValidSize = wxSize(-1,-1);
  551. item->viewRef = NULL ;
  552. SetEventParameter( inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof( void * ), &item );
  553. result = noErr ;
  554. }
  555. break;
  556. case kEventHIObjectInitialize:
  557. result = CallNextEventHandler( inCallRef, inEvent );
  558. if ( result == noErr )
  559. {
  560. CFDataRef data;
  561. GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
  562. sizeof( CFTypeRef ), NULL, &data );
  563. HIViewRef viewRef ;
  564. wxASSERT_MSG( CFDataGetLength( data ) == sizeof( viewRef ) , wxT("Illegal Data passed") ) ;
  565. memcpy( &viewRef , CFDataGetBytePtr( data ) , sizeof( viewRef ) ) ;
  566. object->viewRef = (HIViewRef) viewRef ;
  567. // make sure we keep that control during our lifetime
  568. CFRetain( object->viewRef ) ;
  569. verify_noerr(InstallEventHandler( GetControlEventTarget( viewRef ), ControlToolbarItemHandler,
  570. GetEventTypeCount( kViewEvents ), kViewEvents, object, NULL ));
  571. result = noErr ;
  572. }
  573. break;
  574. case kEventHIObjectDestruct:
  575. {
  576. HIViewRef viewRef = object->viewRef ;
  577. if( viewRef && IsValidControlHandle( viewRef) )
  578. {
  579. // depending whether the wxControl corresponding to this HIView has already been destroyed or
  580. // not, ref counts differ, so we cannot assert a special value
  581. CFIndex count = CFGetRetainCount( viewRef ) ;
  582. if ( count >= 1 )
  583. {
  584. CFRelease( viewRef ) ;
  585. }
  586. }
  587. free( object ) ;
  588. result = noErr;
  589. }
  590. break;
  591. }
  592. break;
  593. case kEventClassToolbarItem:
  594. switch ( GetEventKind( inEvent ) )
  595. {
  596. case kEventToolbarItemCreateCustomView:
  597. {
  598. HIViewRef viewRef = object->viewRef ;
  599. HIViewRemoveFromSuperview( viewRef ) ;
  600. HIViewSetVisible(viewRef, true) ;
  601. CFRetain( viewRef ) ;
  602. result = SetEventParameter( inEvent, kEventParamControlRef, typeControlRef, sizeof( HIViewRef ), &viewRef );
  603. }
  604. break;
  605. }
  606. break;
  607. case kEventClassControl:
  608. switch ( GetEventKind( inEvent ) )
  609. {
  610. case kEventControlGetSizeConstraints:
  611. {
  612. wxWindow* wxwindow = wxFindWindowFromWXWidget( (WXWidget) object->viewRef ) ;
  613. if ( wxwindow )
  614. {
  615. // during toolbar layout the native window sometimes gets negative sizes,
  616. // sometimes it just gets shrunk behind our back, so in order to avoid
  617. // ever shrinking more, once a valid size is captured, we keep it
  618. wxSize sz = object->lastValidSize;
  619. if ( sz.x <= 0 || sz.y <= 0 )
  620. {
  621. sz = wxwindow->GetSize() ;
  622. sz.x -= wxwindow->MacGetLeftBorderSize() + wxwindow->MacGetRightBorderSize();
  623. sz.y -= wxwindow->MacGetTopBorderSize() + wxwindow->MacGetBottomBorderSize();
  624. if ( sz.x > 0 && sz.y > 0 )
  625. object->lastValidSize = sz ;
  626. else
  627. sz = wxSize(0,0) ;
  628. }
  629. // Extra width to avoid edge of combobox being cut off
  630. sz.x += 3;
  631. HISize min, max;
  632. min.width = max.width = sz.x ;
  633. min.height = max.height = sz.y ;
  634. result = SetEventParameter( inEvent, kEventParamMinimumSize, typeHISize,
  635. sizeof( HISize ), &min );
  636. result = SetEventParameter( inEvent, kEventParamMaximumSize, typeHISize,
  637. sizeof( HISize ), &max );
  638. result = noErr ;
  639. }
  640. }
  641. break;
  642. }
  643. break;
  644. }
  645. return result;
  646. }
  647. void RegisterControlToolbarItemClass()
  648. {
  649. static bool sRegistered;
  650. if ( !sRegistered )
  651. {
  652. HIObjectRegisterSubclass( kControlToolbarItemClassID, kHIToolbarItemClassID, 0,
  653. ControlToolbarItemHandler, GetEventTypeCount( kEvents ), kEvents, 0, NULL );
  654. sRegistered = true;
  655. }
  656. }
  657. HIToolbarItemRef CreateControlToolbarItem(CFStringRef inIdentifier, CFTypeRef inConfigData)
  658. {
  659. RegisterControlToolbarItemClass();
  660. OSStatus err;
  661. EventRef event;
  662. UInt32 options = kHIToolbarItemAllowDuplicates;
  663. HIToolbarItemRef result = NULL;
  664. err = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), 0, &event );
  665. require_noerr( err, CantCreateEvent );
  666. SetEventParameter( event, kEventParamAttributes, typeUInt32, sizeof( UInt32 ), &options );
  667. SetEventParameter( event, kEventParamToolbarItemIdentifier, typeCFStringRef, sizeof( CFStringRef ), &inIdentifier );
  668. if ( inConfigData )
  669. SetEventParameter( event, kEventParamToolbarItemConfigData, typeCFTypeRef, sizeof( CFTypeRef ), &inConfigData );
  670. err = HIObjectCreate( kControlToolbarItemClassID, event, (HIObjectRef*)&result );
  671. check_noerr( err );
  672. ReleaseEvent( event );
  673. CantCreateEvent :
  674. return result ;
  675. }
  676. #if wxOSX_USE_NATIVE_TOOLBAR
  677. static const EventTypeSpec kToolbarEvents[] =
  678. {
  679. { kEventClassToolbar, kEventToolbarGetDefaultIdentifiers },
  680. { kEventClassToolbar, kEventToolbarGetAllowedIdentifiers },
  681. { kEventClassToolbar, kEventToolbarCreateItemWithIdentifier },
  682. };
  683. static OSStatus ToolbarDelegateHandler(EventHandlerCallRef WXUNUSED(inCallRef),
  684. EventRef inEvent,
  685. void* WXUNUSED(inUserData))
  686. {
  687. OSStatus result = eventNotHandledErr;
  688. // Not yet needed
  689. // wxToolBar* toolbar = (wxToolBar*) inUserData ;
  690. CFMutableArrayRef array;
  691. switch ( GetEventKind( inEvent ) )
  692. {
  693. case kEventToolbarGetDefaultIdentifiers:
  694. {
  695. GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
  696. sizeof( CFMutableArrayRef ), NULL, &array );
  697. // not implemented yet
  698. // GetToolbarDefaultItems( array );
  699. result = noErr;
  700. }
  701. break;
  702. case kEventToolbarGetAllowedIdentifiers:
  703. {
  704. GetEventParameter( inEvent, kEventParamMutableArray, typeCFMutableArrayRef, NULL,
  705. sizeof( CFMutableArrayRef ), NULL, &array );
  706. // not implemented yet
  707. // GetToolbarAllowedItems( array );
  708. result = noErr;
  709. }
  710. break;
  711. case kEventToolbarCreateItemWithIdentifier:
  712. {
  713. HIToolbarItemRef item = NULL;
  714. CFTypeRef data = NULL;
  715. CFStringRef identifier = NULL ;
  716. GetEventParameter( inEvent, kEventParamToolbarItemIdentifier, typeCFStringRef, NULL,
  717. sizeof( CFStringRef ), NULL, &identifier );
  718. GetEventParameter( inEvent, kEventParamToolbarItemConfigData, typeCFTypeRef, NULL,
  719. sizeof( CFTypeRef ), NULL, &data );
  720. if ( CFStringCompare( kControlToolbarItemClassID, identifier, kCFCompareBackwards ) == kCFCompareEqualTo )
  721. {
  722. item = CreateControlToolbarItem( kControlToolbarItemClassID, data );
  723. if ( item )
  724. {
  725. SetEventParameter( inEvent, kEventParamToolbarItem, typeHIToolbarItemRef,
  726. sizeof( HIToolbarItemRef ), &item );
  727. result = noErr;
  728. }
  729. }
  730. }
  731. break;
  732. }
  733. return result ;
  734. }
  735. #endif // wxOSX_USE_NATIVE_TOOLBAR
  736. // also for the toolbar we have the dual implementation:
  737. // only when MacInstallNativeToolbar is called is the native toolbar set as the window toolbar
  738. bool wxToolBar::Create(
  739. wxWindow *parent,
  740. wxWindowID id,
  741. const wxPoint& pos,
  742. const wxSize& size,
  743. long style,
  744. const wxString& name )
  745. {
  746. if ( !wxToolBarBase::Create( parent, id, pos, size, style, wxDefaultValidator, name ) )
  747. return false;
  748. FixupStyle();
  749. OSStatus err = noErr;
  750. #if wxOSX_USE_NATIVE_TOOLBAR
  751. if (parent->IsKindOf(CLASSINFO(wxFrame)) && wxSystemOptions::GetOptionInt(wxT("mac.toolbar.no-native")) != 1)
  752. {
  753. wxString labelStr = wxString::Format( wxT("%p"), this );
  754. err = HIToolbarCreate(
  755. wxCFStringRef( labelStr, wxFont::GetDefaultEncoding() ), 0,
  756. (HIToolbarRef*) &m_macToolbar );
  757. if (m_macToolbar != NULL)
  758. {
  759. InstallEventHandler( HIObjectGetEventTarget((HIToolbarRef)m_macToolbar ), ToolbarDelegateHandler,
  760. GetEventTypeCount( kToolbarEvents ), kToolbarEvents, this, NULL );
  761. HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
  762. HIToolbarDisplaySize displaySize = kHIToolbarDisplaySizeSmall;
  763. if ( style & wxTB_NOICONS )
  764. mode = kHIToolbarDisplayModeLabelOnly;
  765. else if ( style & wxTB_TEXT )
  766. mode = kHIToolbarDisplayModeIconAndLabel;
  767. else
  768. mode = kHIToolbarDisplayModeIconOnly;
  769. HIToolbarSetDisplayMode( (HIToolbarRef) m_macToolbar, mode );
  770. HIToolbarSetDisplaySize( (HIToolbarRef) m_macToolbar, displaySize );
  771. }
  772. }
  773. #endif // wxOSX_USE_NATIVE_TOOLBAR
  774. return (err == noErr);
  775. }
  776. wxToolBar::~wxToolBar()
  777. {
  778. #if wxOSX_USE_NATIVE_TOOLBAR
  779. // We could be not using a native tool bar at all, this happens when we're
  780. // created with something other than the frame as parent for example.
  781. if ( !m_macToolbar )
  782. return;
  783. CFIndex count = CFGetRetainCount( m_macToolbar ) ;
  784. // Leopard seems to have one refcount more, so we cannot check reliably at the moment
  785. if ( UMAGetSystemVersion() < 0x1050 )
  786. {
  787. if ( count != 1 )
  788. {
  789. wxFAIL_MSG("Reference count of native control was not 1 in wxToolBar destructor");
  790. }
  791. }
  792. CFRelease( (HIToolbarRef)m_macToolbar );
  793. m_macToolbar = NULL;
  794. #endif // wxOSX_USE_NATIVE_TOOLBAR
  795. }
  796. bool wxToolBar::Show( bool show )
  797. {
  798. WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
  799. bool bResult = (tlw != NULL);
  800. if (bResult)
  801. {
  802. #if wxOSX_USE_NATIVE_TOOLBAR
  803. bool ownToolbarInstalled = false;
  804. MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
  805. if (ownToolbarInstalled)
  806. {
  807. bResult = (IsWindowToolbarVisible( tlw ) != show);
  808. if ( bResult )
  809. ShowHideWindowToolbar( tlw, show, false );
  810. }
  811. else
  812. bResult = wxToolBarBase::Show( show );
  813. #else
  814. bResult = wxToolBarBase::Show( show );
  815. #endif
  816. }
  817. return bResult;
  818. }
  819. bool wxToolBar::IsShown() const
  820. {
  821. bool bResult;
  822. #if wxOSX_USE_NATIVE_TOOLBAR
  823. bool ownToolbarInstalled;
  824. MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
  825. if (ownToolbarInstalled)
  826. {
  827. WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
  828. bResult = IsWindowToolbarVisible( tlw );
  829. }
  830. else
  831. bResult = wxToolBarBase::IsShown();
  832. #else
  833. bResult = wxToolBarBase::IsShown();
  834. #endif
  835. return bResult;
  836. }
  837. void wxToolBar::DoGetSize( int *width, int *height ) const
  838. {
  839. #if wxOSX_USE_NATIVE_TOOLBAR
  840. Rect boundsR;
  841. bool ownToolbarInstalled;
  842. MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
  843. if ( ownToolbarInstalled )
  844. {
  845. // TODO: is this really a control ?
  846. GetControlBounds( (ControlRef) m_macToolbar, &boundsR );
  847. if ( width != NULL )
  848. *width = boundsR.right - boundsR.left;
  849. if ( height != NULL )
  850. *height = boundsR.bottom - boundsR.top;
  851. }
  852. else
  853. wxToolBarBase::DoGetSize( width, height );
  854. #else
  855. wxToolBarBase::DoGetSize( width, height );
  856. #endif
  857. }
  858. wxSize wxToolBar::DoGetBestSize() const
  859. {
  860. int width, height;
  861. DoGetSize( &width, &height );
  862. return wxSize( width, height );
  863. }
  864. void wxToolBar::SetWindowStyleFlag( long style )
  865. {
  866. wxToolBarBase::SetWindowStyleFlag( style );
  867. #if wxOSX_USE_NATIVE_TOOLBAR
  868. if (m_macToolbar != NULL)
  869. {
  870. HIToolbarDisplayMode mode = kHIToolbarDisplayModeDefault;
  871. if ( style & wxTB_NOICONS )
  872. mode = kHIToolbarDisplayModeLabelOnly;
  873. else if ( style & wxTB_TEXT )
  874. mode = kHIToolbarDisplayModeIconAndLabel;
  875. else
  876. mode = kHIToolbarDisplayModeIconOnly;
  877. HIToolbarSetDisplayMode( (HIToolbarRef) m_macToolbar, mode );
  878. }
  879. #endif
  880. }
  881. #if wxOSX_USE_NATIVE_TOOLBAR
  882. bool wxToolBar::MacWantsNativeToolbar()
  883. {
  884. return m_macUsesNativeToolbar;
  885. }
  886. bool wxToolBar::MacTopLevelHasNativeToolbar(bool *ownToolbarInstalled) const
  887. {
  888. bool bResultV = false;
  889. if (ownToolbarInstalled != NULL)
  890. *ownToolbarInstalled = false;
  891. WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
  892. if (tlw != NULL)
  893. {
  894. HIToolbarRef curToolbarRef = NULL;
  895. OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
  896. bResultV = ((err == noErr) && (curToolbarRef != NULL));
  897. if (bResultV && (ownToolbarInstalled != NULL))
  898. *ownToolbarInstalled = (curToolbarRef == m_macToolbar);
  899. }
  900. return bResultV;
  901. }
  902. bool wxToolBar::MacInstallNativeToolbar(bool usesNative)
  903. {
  904. bool bResult = false;
  905. if (usesNative && (m_macToolbar == NULL))
  906. return bResult;
  907. if (usesNative && ((GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT|wxTB_BOTTOM)) != 0))
  908. return bResult;
  909. WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
  910. if (tlw == NULL)
  911. return bResult;
  912. // check the existing toolbar
  913. HIToolbarRef curToolbarRef = NULL;
  914. OSStatus err = GetWindowToolbar( tlw, &curToolbarRef );
  915. if (err != noErr)
  916. curToolbarRef = NULL;
  917. m_macUsesNativeToolbar = usesNative;
  918. if (m_macUsesNativeToolbar)
  919. {
  920. // only install toolbar if there isn't one installed already
  921. if (curToolbarRef == NULL)
  922. {
  923. bResult = true;
  924. SetWindowToolbar( tlw, (HIToolbarRef) m_macToolbar );
  925. // ShowHideWindowToolbar will make the wxFrame grow
  926. // which we don't want in this case
  927. wxSize sz = GetParent()->GetSize();
  928. ShowHideWindowToolbar( tlw, true, false );
  929. // Restore the orginal size
  930. GetParent()->SetSize( sz );
  931. ChangeWindowAttributes( tlw, kWindowToolbarButtonAttribute, 0 );
  932. SetAutomaticControlDragTrackingEnabledForWindow( tlw, true );
  933. GetPeer()->Move(0,0,0,0 );
  934. SetSize( wxSIZE_AUTO_WIDTH, 0 );
  935. GetPeer()->SetVisibility( false );
  936. wxToolBarBase::Show( false );
  937. }
  938. }
  939. else
  940. {
  941. // only deinstall toolbar if this is the installed one
  942. if (m_macToolbar == curToolbarRef)
  943. {
  944. bResult = true;
  945. ShowHideWindowToolbar( tlw, false, false );
  946. ChangeWindowAttributes( tlw, 0, kWindowToolbarButtonAttribute );
  947. MacUninstallNativeToolbar();
  948. GetPeer()->SetVisibility( true );
  949. }
  950. }
  951. if (bResult)
  952. InvalidateBestSize();
  953. // wxLogDebug( wxT(" --> [%lx] - result [%s]"), (long)this, bResult ? wxT("T") : wxT("F") );
  954. return bResult;
  955. }
  956. void wxToolBar::MacUninstallNativeToolbar()
  957. {
  958. if (!m_macToolbar)
  959. return;
  960. WindowRef tlw = MAC_WXHWND(MacGetTopLevelWindowRef());
  961. if (tlw)
  962. SetWindowToolbar( tlw, NULL );
  963. }
  964. #endif
  965. bool wxToolBar::Realize()
  966. {
  967. if ( !wxToolBarBase::Realize() )
  968. return false;
  969. wxSize tlw_sz = GetParent()->GetSize();
  970. int maxWidth = 0;
  971. int maxHeight = 0;
  972. int maxToolWidth = 0;
  973. int maxToolHeight = 0;
  974. int x = m_xMargin + kwxMacToolBarLeftMargin;
  975. int y = m_yMargin + kwxMacToolBarTopMargin;
  976. int tw, th;
  977. GetSize( &tw, &th );
  978. // find the maximum tool width and height
  979. wxToolBarTool *tool;
  980. wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
  981. while ( node )
  982. {
  983. tool = (wxToolBarTool *) node->GetData();
  984. if ( tool != NULL )
  985. {
  986. wxSize sz = tool->GetSize();
  987. if ( sz.x > maxToolWidth )
  988. maxToolWidth = sz.x;
  989. if ( sz.y > maxToolHeight )
  990. maxToolHeight = sz.y;
  991. }
  992. node = node->GetNext();
  993. }
  994. bool lastIsRadio = false;
  995. bool curIsRadio = false;
  996. #if wxOSX_USE_NATIVE_TOOLBAR
  997. CFIndex currentPosition = 0;
  998. bool insertAll = false;
  999. HIToolbarRef refTB = (HIToolbarRef)m_macToolbar;
  1000. wxFont f;
  1001. wxFontEncoding enc;
  1002. f = GetFont();
  1003. if ( f.IsOk() )
  1004. enc = f.GetEncoding();
  1005. else
  1006. enc = wxFont::GetDefaultEncoding();
  1007. #endif
  1008. node = m_tools.GetFirst();
  1009. while ( node )
  1010. {
  1011. tool = (wxToolBarTool*) node->GetData();
  1012. if ( tool == NULL )
  1013. {
  1014. node = node->GetNext();
  1015. continue;
  1016. }
  1017. // set tool position:
  1018. // for the moment just perform a single row/column alignment
  1019. wxSize cursize = tool->GetSize();
  1020. if ( x + cursize.x > maxWidth )
  1021. maxWidth = x + cursize.x;
  1022. if ( y + cursize.y > maxHeight )
  1023. maxHeight = y + cursize.y;
  1024. if ( GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) )
  1025. {
  1026. int x1 = x + ( maxToolWidth - cursize.x ) / 2;
  1027. tool->SetPosition( wxPoint(x1, y) );
  1028. }
  1029. else
  1030. {
  1031. int y1 = y + ( maxToolHeight - cursize.y ) / 2;
  1032. tool->SetPosition( wxPoint(x, y1) );
  1033. }
  1034. // update the item positioning state
  1035. if ( GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) )
  1036. y += cursize.y + kwxMacToolSpacing;
  1037. else
  1038. x += cursize.x + kwxMacToolSpacing;
  1039. #if wxOSX_USE_NATIVE_TOOLBAR
  1040. // install in native HIToolbar
  1041. if ( refTB )
  1042. {
  1043. HIToolbarItemRef hiItemRef = tool->GetToolbarItemRef();
  1044. if ( hiItemRef != NULL )
  1045. {
  1046. // since setting the help texts is non-virtual we have to update
  1047. // the strings now
  1048. if ( insertAll || (tool->GetIndex() != currentPosition) )
  1049. {
  1050. OSStatus err = noErr;
  1051. if ( !insertAll )
  1052. {
  1053. insertAll = true;
  1054. // if this is the first tool that gets newly inserted or repositioned
  1055. // first remove all 'old' tools from here to the right, because of this
  1056. // all following tools will have to be reinserted (insertAll).
  1057. for ( wxToolBarToolsList::compatibility_iterator node2 = m_tools.GetLast();
  1058. node2 != node;
  1059. node2 = node2->GetPrevious() )
  1060. {
  1061. wxToolBarTool *tool2 = (wxToolBarTool*) node2->GetData();
  1062. const long idx = tool2->GetIndex();
  1063. if ( idx != -1 )
  1064. {
  1065. if ( tool2->IsControl() )
  1066. {
  1067. CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
  1068. if ( count != 3 && count != 2 )
  1069. {
  1070. wxFAIL_MSG("Reference count of native tool was illegal before removal");
  1071. }
  1072. wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
  1073. }
  1074. err = HIToolbarRemoveItemAtIndex(refTB, idx);
  1075. if ( err != noErr )
  1076. {
  1077. wxLogDebug(wxT("HIToolbarRemoveItemAtIndex(%ld) failed [%ld]"),
  1078. idx, (long)err);
  1079. }
  1080. if ( tool2->IsControl() )
  1081. {
  1082. CFIndex count = CFGetRetainCount( tool2->GetControl()->GetPeer()->GetControlRef() ) ;
  1083. if ( count != 2 )
  1084. {
  1085. wxFAIL_MSG("Reference count of native tool was not 2 after removal");
  1086. }
  1087. wxASSERT( IsValidControlHandle(tool2->GetControl()->GetPeer()->GetControlRef() )) ;
  1088. }
  1089. tool2->SetIndex(-1);
  1090. }
  1091. }
  1092. }
  1093. err = HIToolbarInsertItemAtIndex( refTB, hiItemRef, currentPosition );
  1094. if (err != noErr)
  1095. {
  1096. wxLogDebug( wxT("HIToolbarInsertItemAtIndex failed [%ld]"), (long)err );
  1097. }
  1098. tool->SetIndex( currentPosition );
  1099. if ( tool->IsControl() )
  1100. {
  1101. CFIndex count = CFGetRetainCount( tool->GetControl()->GetPeer()->GetControlRef() ) ;
  1102. if ( count != 3 && count != 2 )
  1103. {
  1104. wxFAIL_MSG("Reference count of native tool was illegal before removal");
  1105. }
  1106. wxASSERT( IsValidControlHandle(tool->GetControl()->GetPeer()->GetControlRef() )) ;
  1107. wxString label = tool->GetLabel();
  1108. if ( !label.empty() )
  1109. HIToolbarItemSetLabel( hiItemRef, wxCFStringRef(label, GetFont().GetEncoding()) );
  1110. }
  1111. }
  1112. currentPosition++;
  1113. }
  1114. }
  1115. #endif
  1116. // update radio button (and group) state
  1117. lastIsRadio = curIsRadio;
  1118. curIsRadio = ( tool->IsButton() && (tool->GetKind() == wxITEM_RADIO) );
  1119. if ( !curIsRadio )
  1120. {
  1121. if ( tool->IsToggled() )
  1122. DoToggleTool( tool, true );
  1123. }
  1124. else
  1125. {
  1126. if ( !lastIsRadio )
  1127. {
  1128. if ( tool->Toggle( true ) )
  1129. {
  1130. DoToggleTool( tool, true );
  1131. }
  1132. }
  1133. else if ( tool->IsToggled() )
  1134. {
  1135. if ( tool->IsToggled() )
  1136. DoToggleTool( tool, true );
  1137. wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
  1138. while ( nodePrev )
  1139. {
  1140. wxToolBarToolBase *toggleTool = nodePrev->GetData();
  1141. if ( (toggleTool == NULL) || !toggleTool->IsButton() || (toggleTool->GetKind() != wxITEM_RADIO) )
  1142. break;
  1143. if ( toggleTool->Toggle( false ) )
  1144. DoToggleTool( toggleTool, false );
  1145. nodePrev = nodePrev->GetPrevious();
  1146. }
  1147. }
  1148. }
  1149. node = node->GetNext();
  1150. }
  1151. if (m_macUsesNativeToolbar)
  1152. GetParent()->SetSize( tlw_sz );
  1153. if ( GetWindowStyleFlag() & (wxTB_TOP|wxTB_BOTTOM) )
  1154. {
  1155. // if not set yet, only one row
  1156. if ( m_maxRows <= 0 )
  1157. SetRows( 1 );
  1158. m_minWidth = maxWidth;
  1159. maxHeight += m_yMargin + kwxMacToolBarTopMargin;
  1160. m_minHeight = m_maxHeight = maxHeight;
  1161. }
  1162. else
  1163. {
  1164. // if not set yet, have one column
  1165. if ( (GetToolsCount() > 0) && (m_maxRows <= 0) )
  1166. SetRows( GetToolsCount() );
  1167. m_minHeight = maxHeight;
  1168. maxWidth += m_xMargin + kwxMacToolBarLeftMargin;
  1169. m_minWidth = m_maxWidth = maxWidth;
  1170. }
  1171. #if 0
  1172. // FIXME: should this be OSX-only?
  1173. {
  1174. bool wantNativeToolbar, ownToolbarInstalled;
  1175. // attempt to install the native toolbar
  1176. wantNativeToolbar = ((GetWindowStyleFlag() & (wxTB_LEFT|wxTB_BOTTOM|wxTB_RIGHT)) == 0);
  1177. MacInstallNativeToolbar( wantNativeToolbar );
  1178. (void)MacTopLevelHasNativeToolbar( &ownToolbarInstalled );
  1179. if (!ownToolbarInstalled)
  1180. {
  1181. SetSize( maxWidth, maxHeight );
  1182. InvalidateBestSize();
  1183. }
  1184. }
  1185. #else
  1186. SetSize( maxWidth, maxHeight );
  1187. InvalidateBestSize();
  1188. #endif
  1189. SetInitialSize();
  1190. return true;
  1191. }
  1192. void wxToolBar::DoLayout()
  1193. {
  1194. // TODO port back osx_cocoa layout solution
  1195. }
  1196. void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
  1197. {
  1198. wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
  1199. DoLayout();
  1200. }
  1201. void wxToolBar::SetToolBitmapSize(const wxSize& size)
  1202. {
  1203. m_defaultWidth = size.x + kwxMacToolBorder;
  1204. m_defaultHeight = size.y + kwxMacToolBorder;
  1205. #if wxOSX_USE_NATIVE_TOOLBAR
  1206. if (m_macToolbar != NULL)
  1207. {
  1208. int maxs = wxMax( size.x, size.y );
  1209. HIToolbarDisplaySize sizeSpec;
  1210. if ( maxs > 32 )
  1211. sizeSpec = kHIToolbarDisplaySizeNormal;
  1212. else if ( maxs > 24 )
  1213. sizeSpec = kHIToolbarDisplaySizeDefault;
  1214. else
  1215. sizeSpec = kHIToolbarDisplaySizeSmall;
  1216. HIToolbarSetDisplaySize( (HIToolbarRef) m_macToolbar, sizeSpec );
  1217. }
  1218. #endif
  1219. }
  1220. // The button size is bigger than the bitmap size
  1221. wxSize wxToolBar::GetToolSize() const
  1222. {
  1223. return wxSize(m_defaultWidth + kwxMacToolBorder, m_defaultHeight + kwxMacToolBorder);
  1224. }
  1225. void wxToolBar::SetRows(int nRows)
  1226. {
  1227. // avoid resizing the frame uselessly
  1228. if ( nRows != m_maxRows )
  1229. m_maxRows = nRows;
  1230. }
  1231. void wxToolBar::MacSuperChangedPosition()
  1232. {
  1233. wxWindow::MacSuperChangedPosition();
  1234. #if wxOSX_USE_NATIVE_TOOLBAR
  1235. if (! m_macUsesNativeToolbar )
  1236. Realize();
  1237. #else
  1238. Realize();
  1239. #endif
  1240. }
  1241. void wxToolBar::SetToolNormalBitmap( int id, const wxBitmap& bitmap )
  1242. {
  1243. wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
  1244. if ( tool )
  1245. {
  1246. wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
  1247. tool->SetNormalBitmap(bitmap);
  1248. // a side-effect of the UpdateToggleImage function is that it always changes the bitmap used on the button.
  1249. tool->UpdateToggleImage( tool->CanBeToggled() && tool->IsToggled() );
  1250. }
  1251. }
  1252. void wxToolBar::SetToolDisabledBitmap( int id, const wxBitmap& bitmap )
  1253. {
  1254. wxToolBarTool* tool = static_cast<wxToolBarTool*>(FindById(id));
  1255. if ( tool )
  1256. {
  1257. wxCHECK_RET( tool->IsButton(), wxT("Can only set bitmap on button tools."));
  1258. tool->SetDisabledBitmap(bitmap);
  1259. // TODO: what to do for this one?
  1260. }
  1261. }
  1262. wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
  1263. {
  1264. wxToolBarTool *tool;
  1265. wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
  1266. while ( node )
  1267. {
  1268. tool = (wxToolBarTool *)node->GetData();
  1269. if (tool != NULL)
  1270. {
  1271. wxRect2DInt r( tool->GetPosition(), tool->GetSize() );
  1272. if ( r.Contains( wxPoint( x, y ) ) )
  1273. return tool;
  1274. }
  1275. node = node->GetNext();
  1276. }
  1277. return NULL;
  1278. }
  1279. wxString wxToolBar::MacGetToolTipString( wxPoint &pt )
  1280. {
  1281. wxToolBarToolBase *tool = FindToolForPosition( pt.x, pt.y );
  1282. if ( tool != NULL )
  1283. return tool->GetShortHelp();
  1284. return wxEmptyString;
  1285. }
  1286. void wxToolBar::DoEnableTool(wxToolBarToolBase *WXUNUSED(t), bool WXUNUSED(enable))
  1287. {
  1288. // everything already done in the tool's implementation
  1289. }
  1290. void wxToolBar::DoToggleTool(wxToolBarToolBase *WXUNUSED(t), bool WXUNUSED(toggle))
  1291. {
  1292. // everything already done in the tool's implementation
  1293. }
  1294. bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
  1295. {
  1296. wxToolBarTool *tool = static_cast< wxToolBarTool*>(toolBase );
  1297. if (tool == NULL)
  1298. return false;
  1299. WindowRef window = (WindowRef) MacGetTopLevelWindowRef();
  1300. wxSize toolSize = GetToolSize();
  1301. Rect toolrect = { 0, 0, toolSize.y, toolSize.x };
  1302. ControlRef controlHandle = NULL;
  1303. OSStatus err = 0;
  1304. #if wxOSX_USE_NATIVE_TOOLBAR
  1305. wxString label = tool->GetLabel();
  1306. if (m_macToolbar && !label.empty() )
  1307. {
  1308. // strip mnemonics from the label for compatibility
  1309. // with the usual labels in wxStaticText sense
  1310. label = wxStripMenuCodes(label);
  1311. }
  1312. #endif // wxOSX_USE_NATIVE_TOOLBAR
  1313. switch (tool->GetStyle())
  1314. {
  1315. case wxTOOL_STYLE_SEPARATOR:
  1316. {
  1317. wxASSERT( tool->GetControlHandle() == NULL );
  1318. toolSize.x /= 4;
  1319. toolSize.y /= 4;
  1320. if ( GetWindowStyleFlag() & (wxTB_LEFT|wxTB_RIGHT) )
  1321. toolrect.bottom = toolSize.y;
  1322. else
  1323. toolrect.right = toolSize.x;
  1324. // in flat style we need a visual separator
  1325. #if wxOSX_USE_NATIVE_TOOLBAR
  1326. if (m_macToolbar != NULL)
  1327. {
  1328. HIToolbarItemRef item;
  1329. err = HIToolbarItemCreate(
  1330. kHIToolbarSeparatorIdentifier,
  1331. kHIToolbarItemCantBeRemoved | kHIToolbarItemIsSeparator | kHIToolbarItemAllowDuplicates,
  1332. &item );
  1333. if (err == noErr)
  1334. tool->SetToolbarItemRef( item );
  1335. }
  1336. else
  1337. err = noErr;
  1338. #endif // wxOSX_USE_NATIVE_TOOLBAR
  1339. CreateSeparatorControl( window, &toolrect, &controlHandle );
  1340. tool->SetControlHandle( controlHandle );
  1341. }
  1342. break;
  1343. case wxTOOL_STYLE_BUTTON:
  1344. {
  1345. wxASSERT( tool->GetControlHandle() == NULL );
  1346. ControlButtonContentInfo info;
  1347. wxMacCreateBitmapButton( &info, tool->GetNormalBitmap() );
  1348. if ( UMAGetSystemVersion() >= 0x1000)
  1349. {
  1350. // contrary to the docs this control only works with iconrefs
  1351. ControlButtonContentInfo info;
  1352. wxMacCreateBitmapButton( &info, tool->GetNormalBitmap(), kControlContentIconRef );
  1353. CreateIconControl( window, &toolrect, &info, false, &controlHandle );
  1354. wxMacReleaseBitmapButton( &info );
  1355. }
  1356. else
  1357. {
  1358. SInt16 behaviour = kControlBehaviorOffsetContents;