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