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