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