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