1///////////////////////////////////////////////////////////////////////////// 2// Name: src/cocoa/toolbar.mm 3// Purpose: wxToolBar 4// Author: David Elliott 5// Modified by: 6// Created: 2003/08/17 7// Copyright: (c) 2003 David Elliott 8// Licence: wxWindows licence 9///////////////////////////////////////////////////////////////////////////// 10 11// ============================================================================ 12// declarations 13// ============================================================================ 14 15// ---------------------------------------------------------------------------- 16// headers 17// ---------------------------------------------------------------------------- 18 19// For compilers that support precompilation, includes "wx.h". 20#include "wx/wxprec.h" 21 22#if wxUSE_TOOLBAR_NATIVE 23 24#include "wx/toolbar.h" 25 26#ifndef WX_PRECOMP 27 #include "wx/frame.h" 28 #include "wx/log.h" 29#endif // WX_PRECOMP 30 31#include "wx/cocoa/string.h" 32#include "wx/cocoa/autorelease.h" 33 34#import <AppKit/NSView.h> 35#import <AppKit/NSButtonCell.h> 36#import <AppKit/NSMatrix.h> 37#import <AppKit/NSImage.h> 38#import <AppKit/NSEvent.h> 39#import <AppKit/NSColor.h> 40#import <AppKit/NSAttributedString.h> 41#import <AppKit/NSFont.h> 42 43#include <math.h> 44 45// ======================================================================== 46// wxToolBarTool 47// ======================================================================== 48class wxToolBarTool : public wxToolBarToolBase 49{ 50public: 51 wxToolBarTool(wxToolBar *tbar, int toolid, const wxString& label, 52 const wxBitmap& bitmap1, const wxBitmap& bitmap2, 53 wxItemKind kind, wxObject *clientData, 54 const wxString& shortHelpString, const wxString& longHelpString) 55 : wxToolBarToolBase(tbar, toolid, label, bitmap1, bitmap2, kind, 56 clientData, shortHelpString, longHelpString) 57 { 58 Init(); 59 CreateButtonCell(); 60 } 61 62 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label) 63 : wxToolBarToolBase(tbar, control, label) 64 { 65 Init(); 66 } 67 ~wxToolBarTool(); 68 69 bool CreateButtonCell(); 70 71 // is this a radio button? 72 // 73 // unlike GetKind(), can be called for any kind of tools, not just buttons 74 bool IsRadio() const { return IsButton() && GetKind() == wxITEM_RADIO; } 75 76 NSRect GetFrameRect() 77 { return m_frameRect; } 78 void SetFrameRect(NSRect frameRect) 79 { m_frameRect = frameRect; } 80 void DrawTool(NSView *nsview); 81 82 NSButtonCell *GetNSButtonCell() 83 { return m_cocoaNSButtonCell; } 84protected: 85 void Init(); 86 NSButtonCell *m_cocoaNSButtonCell; 87 NSRect m_frameRect; 88}; 89 90// ======================================================================== 91// wxToolBarTool 92// ======================================================================== 93void wxToolBarTool::Init() 94{ 95 m_cocoaNSButtonCell = NULL; 96 m_frameRect = NSZeroRect; 97} 98 99void wxToolBar::CocoaToolClickEnded() 100{ 101 wxASSERT(m_mouseDownTool); 102 wxCommandEvent event(wxEVT_MENU, m_mouseDownTool->GetId()); 103 InitCommandEvent(event); 104 Command(event); 105} 106 107wxToolBarTool::~wxToolBarTool() 108{ 109 [m_cocoaNSButtonCell release]; 110} 111 112bool wxToolBarTool::CreateButtonCell() 113{ 114 wxAutoNSAutoreleasePool pool; 115 116 NSImage *nsimage = [m_bmpNormal.GetNSImage(true) retain]; 117 m_cocoaNSButtonCell = [[NSButtonCell alloc] initTextCell:nil]; 118 [m_cocoaNSButtonCell setImage:nsimage]; 119 NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:wxNSStringWithWxString(m_label) attributes:[NSDictionary dictionaryWithObject:[NSFont labelFontOfSize:0.0] forKey:NSFontAttributeName]]; 120// [m_cocoaNSButtonCell setTitle:wxNSStringWithWxString(m_label)]; 121 [m_cocoaNSButtonCell setAttributedTitle:[attributedTitle autorelease]]; 122 123 // Create an alternate image in the style of NSToolBar 124 if(nsimage) 125 { 126 NSImage *alternateImage = [[NSImage alloc] initWithSize:[nsimage size]]; 127 [alternateImage lockFocus]; 128 // Paint the entire image with solid black at 50% transparency 129 NSRect imageRect = NSZeroRect; 130 imageRect.size = [alternateImage size]; 131 [[NSColor colorWithCalibratedWhite:0.0 alpha:0.5] set]; 132 NSRectFill(imageRect); 133 // Composite the original image with the alternate image 134 [nsimage compositeToPoint:NSZeroPoint operation:NSCompositeDestinationAtop]; 135 [alternateImage unlockFocus]; 136 [m_cocoaNSButtonCell setAlternateImage:alternateImage]; 137 [alternateImage release]; 138 } 139 [nsimage release]; 140 141 NSMutableAttributedString *alternateTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[m_cocoaNSButtonCell attributedTitle]]; 142 [alternateTitle applyFontTraits:NSBoldFontMask range:NSMakeRange(0,[alternateTitle length])]; 143 [m_cocoaNSButtonCell setAttributedAlternateTitle:alternateTitle]; 144 [alternateTitle release]; 145 146 // ---- 147 [m_cocoaNSButtonCell setImagePosition:NSImageBelow]; 148// [m_cocoaNSButtonCell setBezeled:NO]; 149 [m_cocoaNSButtonCell setButtonType:NSMomentaryChangeButton]; 150 [m_cocoaNSButtonCell setBordered:NO]; 151// [m_cocoaNSButtonCell setHighlightsBy:NSContentsCellMask|NSPushInCellMask]; 152// [m_cocoaNSButtonCell setShowsStateBy:NSContentsCellMask|NSPushInCellMask]; 153 return true; 154} 155 156void wxToolBarTool::DrawTool(NSView *nsview) 157{ 158 [m_cocoaNSButtonCell drawWithFrame:m_frameRect inView:nsview]; 159} 160 161// ======================================================================== 162// wxToolBar 163// ======================================================================== 164IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) 165 166//----------------------------------------------------------------------------- 167// wxToolBar construction 168//----------------------------------------------------------------------------- 169 170void wxToolBar::Init() 171{ 172 m_owningFrame = NULL; 173 m_mouseDownTool = NULL; 174} 175 176wxToolBar::~wxToolBar() 177{ 178} 179 180bool wxToolBar::Create( wxWindow *parent, 181 wxWindowID winid, 182 const wxPoint& pos, 183 const wxSize& size, 184 long style, 185 const wxString& name ) 186{ 187 // Call wxControl::Create so we get a wxNonControlNSControl 188 if ( !wxToolBarBase::Create(parent, winid, pos, size, style, 189 wxDefaultValidator, name) ) 190 return false; 191 192 FixupStyle(); 193 194 return true; 195} 196 197wxToolBarToolBase *wxToolBar::CreateTool(int toolid, 198 const wxString& text, 199 const wxBitmap& bitmap1, 200 const wxBitmap& bitmap2, 201 wxItemKind kind, 202 wxObject *clientData, 203 const wxString& shortHelpString, 204 const wxString& longHelpString) 205{ 206 return new wxToolBarTool(this, toolid, text, bitmap1, bitmap2, kind, 207 clientData, shortHelpString, longHelpString); 208} 209 210wxToolBarToolBase * 211wxToolBar::CreateTool(wxControl *control, const wxString& label) 212{ 213 return new wxToolBarTool(this, control, label); 214} 215 216void wxToolBar::SetWindowStyleFlag( long style ) 217{ 218 wxToolBarBase::SetWindowStyleFlag(style); 219} 220 221bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) 222{ 223 return true; 224} 225 226bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase) 227{ 228 Realize(); 229 return true; 230} 231 232bool wxToolBar::Cocoa_acceptsFirstMouse(bool &acceptsFirstMouse, WX_NSEvent theEvent) 233{ 234 acceptsFirstMouse = true; return true; 235} 236 237bool wxToolBar::Cocoa_drawRect(const NSRect &rect) 238{ 239 wxToolBarToolsList::compatibility_iterator node; 240 for(node = m_tools.GetFirst(); node; node = node->GetNext()) 241 { 242 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData()); 243 tool->DrawTool(m_cocoaNSView); 244 } 245 return wxToolBarBase::Cocoa_drawRect(rect); 246} 247 248static const NSSize toolPadding = { 4.0, 4.0 }; 249 250static NSRect AddToolPadding(NSRect toolRect) 251{ 252 toolRect.origin.x -= toolPadding.width; 253 toolRect.size.width += 2.0*toolPadding.width; 254 toolRect.origin.y -= toolPadding.height; 255 toolRect.size.height += 2.0*toolPadding.height; 256 return toolRect; 257} 258 259bool wxToolBar::Cocoa_mouseDragged(WX_NSEvent theEvent) 260{ 261 if(m_mouseDownTool && [m_cocoaNSView 262 mouse:[m_cocoaNSView convertPoint:[theEvent locationInWindow] 263 fromView:nil] 264 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect())]) 265 { 266 NSButtonCell *buttonCell = m_mouseDownTool->GetNSButtonCell(); 267 if(buttonCell) 268 { 269 [buttonCell retain]; 270 [buttonCell setHighlighted: YES]; 271 if([buttonCell trackMouse: theEvent 272 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect()) ofView:m_cocoaNSView 273 untilMouseUp:NO]) 274 { 275 CocoaToolClickEnded(); 276 m_mouseDownTool = NULL; 277 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked after drag!")); 278 } 279 [buttonCell setHighlighted: NO]; 280 [buttonCell release]; 281 } 282 } 283 return wxToolBarBase::Cocoa_mouseDragged(theEvent); 284} 285 286bool wxToolBar::Cocoa_mouseDown(WX_NSEvent theEvent) 287{ 288 wxToolBarTool *tool = CocoaFindToolForPosition([m_cocoaNSView convertPoint:[theEvent locationInWindow] fromView:nil]); 289 if(tool) 290 { 291 NSButtonCell *buttonCell = tool->GetNSButtonCell(); 292 if(buttonCell) 293 { 294 [buttonCell retain]; 295 m_mouseDownTool = tool; 296 [buttonCell setHighlighted: YES]; 297 if([buttonCell trackMouse: theEvent 298 inRect:AddToolPadding(tool->GetFrameRect()) ofView:m_cocoaNSView 299 untilMouseUp:NO]) 300 { 301 CocoaToolClickEnded(); 302 m_mouseDownTool = NULL; 303 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked!")); 304 } 305 [buttonCell setHighlighted: NO]; 306 [buttonCell release]; 307 } 308 } 309 return wxToolBarBase::Cocoa_mouseDown(theEvent); 310} 311 312bool wxToolBar::Realize() 313{ 314 wxAutoNSAutoreleasePool pool; 315 316 wxToolBarToolsList::compatibility_iterator node; 317 NSSize totalSize = NSZeroSize; 318 // This is for horizontal, TODO: vertical 319 for(node = m_tools.GetFirst(); node; node = node->GetNext()) 320 { 321 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData()); 322 if(tool->IsControl()) 323 { 324 totalSize.width = ceil(totalSize.width); 325 wxControl *control = tool->GetControl(); 326 wxSize controlSize = control->GetSize(); 327 control->SetPosition(wxPoint((wxCoord)totalSize.width,0)); 328 totalSize.width += controlSize.x; 329 if(controlSize.y > totalSize.height) 330 totalSize.height = controlSize.y; 331 } 332 else if(tool->IsSeparator()) 333 { 334 totalSize.width += 2.0; 335 } 336 else 337 { 338 NSButtonCell *buttonCell = tool->GetNSButtonCell(); 339 NSSize toolSize = [buttonCell cellSize]; 340 tool->SetFrameRect(NSMakeRect(totalSize.width+toolPadding.width,toolPadding.height,toolSize.width,toolSize.height)); 341 toolSize.width += 2.0*toolPadding.width; 342 toolSize.height += 2.0*toolPadding.height; 343 totalSize.width += toolSize.width; 344 if(toolSize.height > totalSize.height) 345 totalSize.height = toolSize.height; 346 } 347 } 348 m_bestSize = wxSize((wxCoord)ceil(totalSize.width),(wxCoord)ceil(totalSize.height)); 349 if(m_owningFrame) 350 m_owningFrame->UpdateFrameNSView(); 351 return true; 352} 353 354wxSize wxToolBar::DoGetBestSize() const 355{ 356 return m_bestSize; 357} 358 359// ---------------------------------------------------------------------------- 360// wxToolBar tools state 361// ---------------------------------------------------------------------------- 362 363void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable) 364{ 365} 366 367void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle ) 368{ 369} 370 371void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool), 372 bool WXUNUSED(toggle)) 373{ 374} 375 376// ---------------------------------------------------------------------------- 377// wxToolBar geometry 378// ---------------------------------------------------------------------------- 379 380wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const 381{ 382 return NULL; 383} 384 385wxToolBarTool *wxToolBar::CocoaFindToolForPosition(const NSPoint& pos) const 386{ 387 wxToolBarToolsList::compatibility_iterator node; 388 for(node = m_tools.GetFirst(); node; node = node->GetNext()) 389 { 390 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData()); 391 if(tool->IsControl()) 392 { 393 // TODO 394 } 395 else if(tool->IsSeparator()) 396 { // Do nothing 397 } 398 else 399 { 400 if([m_cocoaNSView mouse:pos inRect:AddToolPadding(tool->GetFrameRect())]) 401 return tool; 402 } 403 } 404 return NULL; 405} 406 407void wxToolBar::SetMargins( int x, int y ) 408{ 409} 410 411void wxToolBar::SetToolSeparation( int separation ) 412{ 413 m_toolSeparation = separation; 414} 415 416void wxToolBar::SetToolShortHelp( int id, const wxString& helpString ) 417{ 418} 419 420// ---------------------------------------------------------------------------- 421// wxToolBar idle handling 422// ---------------------------------------------------------------------------- 423 424void wxToolBar::OnInternalIdle() 425{ 426} 427 428#endif // wxUSE_TOOLBAR_NATIVE 429