1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/toolbar.mm
4 // Author: David Elliott
7 // Copyright: (c) 2003 David Elliott
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #if wxUSE_TOOLBAR_NATIVE
24 #include "wx/toolbar.h"
31 #include "wx/cocoa/string.h"
32 #include "wx/cocoa/autorelease.h"
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>
45 // ========================================================================
47 // ========================================================================
48 class wxToolBarTool : public wxToolBarToolBase
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)
62 wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
63 : wxToolBarToolBase(tbar, control, label)
69 bool CreateButtonCell();
71 // is this a radio button?
73 // unlike GetKind(), can be called for any kind of tools, not just buttons
74 bool IsRadio() const { return IsButton() && GetKind() == wxITEM_RADIO; }
77 { return m_frameRect; }
78 void SetFrameRect(NSRect frameRect)
79 { m_frameRect = frameRect; }
80 void DrawTool(NSView *nsview);
82 NSButtonCell *GetNSButtonCell()
83 { return m_cocoaNSButtonCell; }
86 NSButtonCell *m_cocoaNSButtonCell;
90 // ========================================================================
92 // ========================================================================
93 void wxToolBarTool::Init()
95 m_cocoaNSButtonCell = NULL;
96 m_frameRect = NSZeroRect;
99 void wxToolBar::CocoaToolClickEnded()
101 wxASSERT(m_mouseDownTool);
102 wxCommandEvent event(wxEVT_MENU, m_mouseDownTool->GetId());
103 InitCommandEvent(event);
107 wxToolBarTool::~wxToolBarTool()
109 [m_cocoaNSButtonCell release];
112 bool wxToolBarTool::CreateButtonCell()
114 wxAutoNSAutoreleasePool pool;
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]];
123 // Create an alternate image in the style of NSToolBar
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];
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];
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];
156 void wxToolBarTool::DrawTool(NSView *nsview)
158 [m_cocoaNSButtonCell drawWithFrame:m_frameRect inView:nsview];
161 // ========================================================================
163 // ========================================================================
164 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
166 //-----------------------------------------------------------------------------
167 // wxToolBar construction
168 //-----------------------------------------------------------------------------
170 void wxToolBar::Init()
172 m_owningFrame = NULL;
173 m_mouseDownTool = NULL;
176 wxToolBar::~wxToolBar()
180 bool wxToolBar::Create( wxWindow *parent,
185 const wxString& name )
187 // Call wxControl::Create so we get a wxNonControlNSControl
188 if ( !wxToolBarBase::Create(parent, winid, pos, size, style,
189 wxDefaultValidator, name) )
197 wxToolBarToolBase *wxToolBar::CreateTool(int toolid,
198 const wxString& text,
199 const wxBitmap& bitmap1,
200 const wxBitmap& bitmap2,
202 wxObject *clientData,
203 const wxString& shortHelpString,
204 const wxString& longHelpString)
206 return new wxToolBarTool(this, toolid, text, bitmap1, bitmap2, kind,
207 clientData, shortHelpString, longHelpString);
211 wxToolBar::CreateTool(wxControl *control, const wxString& label)
213 return new wxToolBarTool(this, control, label);
216 void wxToolBar::SetWindowStyleFlag( long style )
218 wxToolBarBase::SetWindowStyleFlag(style);
221 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
226 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
232 bool wxToolBar::Cocoa_acceptsFirstMouse(bool &acceptsFirstMouse, WX_NSEvent theEvent)
234 acceptsFirstMouse = true; return true;
237 bool wxToolBar::Cocoa_drawRect(const NSRect &rect)
239 wxToolBarToolsList::compatibility_iterator node;
240 for(node = m_tools.GetFirst(); node; node = node->GetNext())
242 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
243 tool->DrawTool(m_cocoaNSView);
245 return wxToolBarBase::Cocoa_drawRect(rect);
248 static const NSSize toolPadding = { 4.0, 4.0 };
250 static NSRect AddToolPadding(NSRect toolRect)
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;
259 bool wxToolBar::Cocoa_mouseDragged(WX_NSEvent theEvent)
261 if(m_mouseDownTool && [m_cocoaNSView
262 mouse:[m_cocoaNSView convertPoint:[theEvent locationInWindow]
264 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect())])
266 NSButtonCell *buttonCell = m_mouseDownTool->GetNSButtonCell();
270 [buttonCell setHighlighted: YES];
271 if([buttonCell trackMouse: theEvent
272 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect()) ofView:m_cocoaNSView
275 CocoaToolClickEnded();
276 m_mouseDownTool = NULL;
277 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked after drag!"));
279 [buttonCell setHighlighted: NO];
280 [buttonCell release];
283 return wxToolBarBase::Cocoa_mouseDragged(theEvent);
286 bool wxToolBar::Cocoa_mouseDown(WX_NSEvent theEvent)
288 wxToolBarTool *tool = CocoaFindToolForPosition([m_cocoaNSView convertPoint:[theEvent locationInWindow] fromView:nil]);
291 NSButtonCell *buttonCell = tool->GetNSButtonCell();
295 m_mouseDownTool = tool;
296 [buttonCell setHighlighted: YES];
297 if([buttonCell trackMouse: theEvent
298 inRect:AddToolPadding(tool->GetFrameRect()) ofView:m_cocoaNSView
301 CocoaToolClickEnded();
302 m_mouseDownTool = NULL;
303 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked!"));
305 [buttonCell setHighlighted: NO];
306 [buttonCell release];
309 return wxToolBarBase::Cocoa_mouseDown(theEvent);
312 bool wxToolBar::Realize()
314 wxAutoNSAutoreleasePool pool;
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())
321 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
322 if(tool->IsControl())
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;
332 else if(tool->IsSeparator())
334 totalSize.width += 2.0;
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;
348 m_bestSize = wxSize((wxCoord)ceil(totalSize.width),(wxCoord)ceil(totalSize.height));
350 m_owningFrame->UpdateFrameNSView();
354 wxSize wxToolBar::DoGetBestSize() const
359 // ----------------------------------------------------------------------------
360 // wxToolBar tools state
361 // ----------------------------------------------------------------------------
363 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
367 void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
371 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
372 bool WXUNUSED(toggle))
376 // ----------------------------------------------------------------------------
377 // wxToolBar geometry
378 // ----------------------------------------------------------------------------
380 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
385 wxToolBarTool *wxToolBar::CocoaFindToolForPosition(const NSPoint& pos) const
387 wxToolBarToolsList::compatibility_iterator node;
388 for(node = m_tools.GetFirst(); node; node = node->GetNext())
390 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
391 if(tool->IsControl())
395 else if(tool->IsSeparator())
400 if([m_cocoaNSView mouse:pos inRect:AddToolPadding(tool->GetFrameRect())])
407 void wxToolBar::SetMargins( int x, int y )
411 void wxToolBar::SetToolSeparation( int separation )
413 m_toolSeparation = separation;
416 void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
420 // ----------------------------------------------------------------------------
421 // wxToolBar idle handling
422 // ----------------------------------------------------------------------------
424 void wxToolBar::OnInternalIdle()
428 #endif // wxUSE_TOOLBAR_NATIVE