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