]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/toolbar.mm
using backward compatible calls for HitTest hack
[wxWidgets.git] / src / cocoa / toolbar.mm
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: wxWidgets 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
44 // ========================================================================
45 // wxToolBarTool
46 // ========================================================================
47 class wxToolBarTool : public wxToolBarToolBase
48 {
49 public:
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; }
83 protected:
84 void Init();
85 NSButtonCell *m_cocoaNSButtonCell;
86 NSRect m_frameRect;
87 };
88
89 // ========================================================================
90 // wxToolBarTool
91 // ========================================================================
92 void wxToolBarTool::Init()
93 {
94 m_cocoaNSButtonCell = NULL;
95 m_frameRect = NSZeroRect;
96 }
97
98 void 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
106 wxToolBarTool::~wxToolBarTool()
107 {
108 [m_cocoaNSButtonCell release];
109 }
110
111 bool wxToolBarTool::CreateButtonCell()
112 {
113 wxAutoNSAutoreleasePool pool;
114
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];
152 return true;
153 }
154
155 void wxToolBarTool::DrawTool(NSView *nsview)
156 {
157 [m_cocoaNSButtonCell drawWithFrame:m_frameRect inView:nsview];
158 }
159
160 // ========================================================================
161 // wxToolBar
162 // ========================================================================
163 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
164
165 //-----------------------------------------------------------------------------
166 // wxToolBar construction
167 //-----------------------------------------------------------------------------
168
169 void wxToolBar::Init()
170 {
171 m_owningFrame = NULL;
172 m_mouseDownTool = NULL;
173 }
174
175 wxToolBar::~wxToolBar()
176 {
177 }
178
179 bool 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
190 wxToolBarToolBase *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
203 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
204 {
205 return new wxToolBarTool(this, control);
206 }
207
208 void wxToolBar::SetWindowStyleFlag( long style )
209 {
210 wxToolBarBase::SetWindowStyleFlag(style);
211 }
212
213 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
214 {
215 return true;
216 }
217
218 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *toolBase)
219 {
220 Realize();
221 return true;
222 }
223
224 bool wxToolBar::Cocoa_acceptsFirstMouse(bool &acceptsFirstMouse, WX_NSEvent theEvent)
225 {
226 acceptsFirstMouse = true; return true;
227 }
228
229 bool wxToolBar::Cocoa_drawRect(const NSRect &rect)
230 {
231 wxToolBarToolsList::compatibility_iterator node;
232 for(node = m_tools.GetFirst(); node; node = node->GetNext())
233 {
234 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
235 tool->DrawTool(m_cocoaNSView);
236 }
237 return wxToolBarBase::Cocoa_drawRect(rect);
238 }
239
240 static const NSSize toolPadding = { 4.0, 4.0 };
241
242 static NSRect AddToolPadding(NSRect toolRect)
243 {
244 toolRect.origin.x -= toolPadding.width;
245 toolRect.size.width += 2.0*toolPadding.width;
246 toolRect.origin.y -= toolPadding.height;
247 toolRect.size.height += 2.0*toolPadding.height;
248 return toolRect;
249 }
250
251 bool wxToolBar::Cocoa_mouseDragged(WX_NSEvent theEvent)
252 {
253 if(m_mouseDownTool && [m_cocoaNSView
254 mouse:[m_cocoaNSView convertPoint:[theEvent locationInWindow]
255 fromView:nil]
256 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect())])
257 {
258 NSButtonCell *buttonCell = m_mouseDownTool->GetNSButtonCell();
259 if(buttonCell)
260 {
261 [buttonCell retain];
262 [buttonCell setHighlighted: YES];
263 if([buttonCell trackMouse: theEvent
264 inRect:AddToolPadding(m_mouseDownTool->GetFrameRect()) ofView:m_cocoaNSView
265 untilMouseUp:NO])
266 {
267 CocoaToolClickEnded();
268 m_mouseDownTool = NULL;
269 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked after drag!"));
270 }
271 [buttonCell setHighlighted: NO];
272 [buttonCell release];
273 }
274 }
275 return wxToolBarBase::Cocoa_mouseDragged(theEvent);
276 }
277
278 bool wxToolBar::Cocoa_mouseDown(WX_NSEvent theEvent)
279 {
280 wxToolBarTool *tool = CocoaFindToolForPosition([m_cocoaNSView convertPoint:[theEvent locationInWindow] fromView:nil]);
281 if(tool)
282 {
283 NSButtonCell *buttonCell = tool->GetNSButtonCell();
284 if(buttonCell)
285 {
286 [buttonCell retain];
287 m_mouseDownTool = tool;
288 [buttonCell setHighlighted: YES];
289 if([buttonCell trackMouse: theEvent
290 inRect:AddToolPadding(tool->GetFrameRect()) ofView:m_cocoaNSView
291 untilMouseUp:NO])
292 {
293 CocoaToolClickEnded();
294 m_mouseDownTool = NULL;
295 wxLogTrace(wxTRACE_COCOA,wxT("Button was clicked!"));
296 }
297 [buttonCell setHighlighted: NO];
298 [buttonCell release];
299 }
300 }
301 return wxToolBarBase::Cocoa_mouseDown(theEvent);
302 }
303
304 bool wxToolBar::Realize()
305 {
306 wxAutoNSAutoreleasePool pool;
307
308 wxToolBarToolsList::compatibility_iterator node;
309 NSSize totalSize = NSZeroSize;
310 // This is for horizontal, TODO: vertical
311 for(node = m_tools.GetFirst(); node; node = node->GetNext())
312 {
313 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
314 if(tool->IsControl())
315 {
316 totalSize.width = ceil(totalSize.width);
317 wxControl *control = tool->GetControl();
318 wxSize controlSize = control->GetSize();
319 control->SetPosition(wxPoint((wxCoord)totalSize.width,0));
320 totalSize.width += controlSize.x;
321 if(controlSize.y > totalSize.height)
322 totalSize.height = controlSize.y;
323 }
324 else if(tool->IsSeparator())
325 {
326 totalSize.width += 2.0;
327 }
328 else
329 {
330 NSButtonCell *buttonCell = tool->GetNSButtonCell();
331 NSSize toolSize = [buttonCell cellSize];
332 tool->SetFrameRect(NSMakeRect(totalSize.width+toolPadding.width,toolPadding.height,toolSize.width,toolSize.height));
333 toolSize.width += 2.0*toolPadding.width;
334 toolSize.height += 2.0*toolPadding.height;
335 totalSize.width += toolSize.width;
336 if(toolSize.height > totalSize.height)
337 totalSize.height = toolSize.height;
338 }
339 }
340 m_bestSize = wxSize((wxCoord)ceil(totalSize.width),(wxCoord)ceil(totalSize.height));
341 if(m_owningFrame)
342 m_owningFrame->UpdateFrameNSView();
343 return true;
344 }
345
346 wxSize wxToolBar::DoGetBestSize() const
347 {
348 return m_bestSize;
349 }
350
351 // ----------------------------------------------------------------------------
352 // wxToolBar tools state
353 // ----------------------------------------------------------------------------
354
355 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
356 {
357 }
358
359 void wxToolBar::DoToggleTool( wxToolBarToolBase *toolBase, bool toggle )
360 {
361 }
362
363 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
364 bool WXUNUSED(toggle))
365 {
366 }
367
368 // ----------------------------------------------------------------------------
369 // wxToolBar geometry
370 // ----------------------------------------------------------------------------
371
372 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
373 {
374 return NULL;
375 }
376
377 wxToolBarTool *wxToolBar::CocoaFindToolForPosition(const NSPoint& pos) const
378 {
379 wxToolBarToolsList::compatibility_iterator node;
380 for(node = m_tools.GetFirst(); node; node = node->GetNext())
381 {
382 wxToolBarTool *tool = static_cast<wxToolBarTool*>(node->GetData());
383 if(tool->IsControl())
384 {
385 // TODO
386 }
387 else if(tool->IsSeparator())
388 { // Do nothing
389 }
390 else
391 {
392 if([m_cocoaNSView mouse:pos inRect:AddToolPadding(tool->GetFrameRect())])
393 return tool;
394 }
395 }
396 return NULL;
397 }
398
399 void wxToolBar::SetMargins( int x, int y )
400 {
401 }
402
403 void wxToolBar::SetToolSeparation( int separation )
404 {
405 m_toolSeparation = separation;
406 }
407
408 void wxToolBar::SetToolShortHelp( int id, const wxString& helpString )
409 {
410 }
411
412 // ----------------------------------------------------------------------------
413 // wxToolBar idle handling
414 // ----------------------------------------------------------------------------
415
416 void wxToolBar::OnInternalIdle()
417 {
418 }
419
420 #endif // wxUSE_TOOLBAR_NATIVE