]> git.saurik.com Git - wxWidgets.git/blob - src/mac/control.cpp
fixed menu accelerators
[wxWidgets.git] / src / mac / control.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: control.cpp
3 // Purpose: wxControl class
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "control.h"
14 #endif
15
16 #include "wx/control.h"
17 #include "wx/notebook.h"
18 #include "wx/tabctrl.h"
19 #include "wx/spinbutt.h"
20
21 #if !USE_SHARED_LIBRARY
22 IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
23
24 BEGIN_EVENT_TABLE(wxControl, wxWindow)
25 EVT_MOUSE_EVENTS( wxControl::OnMouseEvent )
26 EVT_CHAR( wxControl::OnKeyDown )
27 EVT_PAINT( wxControl::OnPaint )
28 END_EVENT_TABLE()
29 #endif
30
31 #include <wx/mac/uma.h>
32
33 // Item members
34
35 ControlActionUPP wxMacLiveScrollbarActionUPP = NULL ;
36
37 pascal void wxMacLiveScrollbarActionProc( ControlHandle control , ControlPartCode partCode )
38 {
39 if ( partCode != 0)
40 {
41 wxControl* wx = (wxControl*) GetControlReference( control ) ;
42 if ( wx )
43 {
44 wx->MacHandleControlClick( control , partCode ) ;
45 }
46 }
47 }
48
49 wxControl::wxControl()
50 {
51 m_macControl = NULL ;
52 m_macHorizontalBorder = 0 ; // additional pixels around the real control
53 m_macVerticalBorder = 0 ;
54 m_backgroundColour = *wxWHITE;
55 m_foregroundColour = *wxBLACK;
56 m_callback = 0;
57
58 if ( wxMacLiveScrollbarActionUPP == NULL )
59 {
60 wxMacLiveScrollbarActionUPP = NewControlActionProc( wxMacLiveScrollbarActionProc ) ;
61 }
62 }
63
64 wxControl::~wxControl()
65 {
66 // If we delete an item, we should initialize the parent panel,
67 // because it could now be invalid.
68 wxWindow *parent = (wxWindow *)GetParent();
69 if (parent)
70 {
71 if (parent->GetDefaultItem() == (wxButton*) this)
72 parent->SetDefaultItem(NULL);
73 }
74 if ( m_macControl )
75 {
76 UMADisposeControl( m_macControl ) ;
77 m_macControl = NULL ;
78 }
79 }
80
81 void wxControl::SetLabel(const wxString& label)
82 {
83 m_label = label ;
84
85 if ( m_macControl )
86 {
87 Str255 maclabel ;
88
89 strcpy( (char*) maclabel , label ) ;
90 c2pstr( (char*) maclabel ) ;
91
92 ::SetControlTitle( m_macControl , maclabel ) ;
93 }
94 }
95
96 wxString wxControl::GetLabel() const
97 {
98 return m_label ;
99 }
100
101 void wxControl::ProcessCommand (wxCommandEvent & event)
102 {
103 // Tries:
104 // 1) A callback function (to become obsolete)
105 // 2) OnCommand, starting at this window and working up parent hierarchy
106 // 3) OnCommand then calls ProcessEvent to search the event tables.
107 if (m_callback)
108 {
109 (void) (*(m_callback)) (*this, event);
110 }
111 else
112 {
113 GetEventHandler()->OnCommand(*this, event);
114 }
115 }
116
117 void wxControl::Centre (int direction)
118 {
119 int x, y, width, height, panel_width, panel_height, new_x, new_y;
120
121 wxWindow *parent = (wxWindow *) GetParent ();
122 if (!parent)
123 return;
124
125 parent->GetClientSize (&panel_width, &panel_height);
126 GetSize (&width, &height);
127 GetPosition (&x, &y);
128
129 new_x = x;
130 new_y = y;
131
132 if (direction & wxHORIZONTAL)
133 new_x = (int) ((panel_width - width) / 2);
134
135 if (direction & wxVERTICAL)
136 new_y = (int) ((panel_height - height) / 2);
137
138 SetSize (new_x, new_y, width, height);
139 }
140
141 void wxControl::SetClientSize (int width, int height)
142 {
143 SetSize (-1, -1, width, height);
144 }
145
146 // ------------------------
147 wxList *wxWinMacControlList = NULL;
148 wxControl *wxFindControlFromMacControl(ControlHandle inControl )
149 {
150 wxNode *node = wxWinMacControlList->Find((long)inControl);
151 if (!node)
152 return NULL;
153 return (wxControl *)node->Data();
154 }
155
156 void wxAssociateControlWithMacControl(ControlHandle inControl, wxControl *control)
157 {
158 // adding NULL WindowRef is (first) surely a result of an error and
159 // (secondly) breaks menu command processing
160 wxCHECK_RET( inControl != (ControlHandle) NULL, "attempt to add a NULL WindowRef to window list" );
161
162 if ( !wxWinMacControlList->Find((long)inControl) )
163 wxWinMacControlList->Append((long)inControl, control);
164 }
165
166 void wxRemoveMacControlAssociation(wxControl *control)
167 {
168 wxWinMacControlList->DeleteObject(control);
169 }
170
171 void wxControl::MacPreControlCreate( wxWindow *parent, wxWindowID id, wxString label ,
172 const wxPoint& pos,
173 const wxSize& size, long style,
174 const wxValidator& validator,
175 const wxString& name , Rect *outBounds , StringPtr maclabel )
176 {
177 m_label = label ;
178 SetName(name);
179 if ( &validator )
180 SetValidator(validator);
181
182 m_windowStyle = style;
183 parent->AddChild((wxButton *)this);
184
185 m_backgroundColour = parent->GetBackgroundColour() ;
186 m_foregroundColour = parent->GetForegroundColour() ;
187
188 if (id == -1)
189 m_windowId = NewControlId();
190 else
191 m_windowId = id;
192
193 m_width = size.x ;
194 m_height = size.y ;
195 int x = pos.x ;
196 int y = pos.y ;
197 AdjustForParentClientOrigin(x, y, wxSIZE_USE_EXISTING);
198 m_x = x ;
199 m_y = y ;
200
201
202 Point localOrigin ;
203 Rect clipRect ;
204
205 parent->MacClientToRootWindow( &x , &y ) ;
206 outBounds->top = y + m_macVerticalBorder ;
207 outBounds->left = x + m_macHorizontalBorder ;
208 outBounds->bottom = outBounds->top + m_height - 2 * m_macVerticalBorder;
209 outBounds->right = outBounds->left + m_width - 2 * m_macHorizontalBorder ;
210
211 strcpy( (char*) maclabel , label ) ;
212 if( wxApp::s_macDefaultEncodingIsPC )
213 {
214 wxMacConvertFromPCForControls( (char*) maclabel ) ;
215 }
216
217 c2pstr( (char*) maclabel ) ;
218 }
219
220 void wxControl::MacPostControlCreate()
221 {
222 wxASSERT_MSG( m_macControl != NULL , "No valid mac control" ) ;
223
224 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
225 {
226 // no font
227 }
228 else if ( IsKindOf( CLASSINFO( wxStaticBox ) ) )
229 {
230 ControlFontStyleRec controlstyle ;
231 controlstyle.flags = kControlUseFontMask ;
232 controlstyle.font = kControlFontSmallBoldSystemFont ;
233
234 ::UMASetControlFontStyle( m_macControl , &controlstyle ) ;
235 }
236 else
237 {
238 ControlFontStyleRec controlstyle ;
239 controlstyle.flags = kControlUseFontMask ;
240 controlstyle.font = kControlFontSmallSystemFont ;
241
242 ::UMASetControlFontStyle( m_macControl , &controlstyle ) ;
243 }
244 ControlHandle container = GetParent()->MacGetContainerForEmbedding() ;
245 wxASSERT_MSG( container != NULL , "No valid mac container control" ) ;
246 ::UMAEmbedControl( m_macControl , container ) ;
247 MacAdjustControlRect() ;
248 wxAssociateControlWithMacControl( m_macControl , this ) ;
249 }
250
251 void wxControl::MacAdjustControlRect()
252 {
253 wxASSERT_MSG( m_macControl != NULL , "No valid mac control" ) ;
254 if ( m_width == -1 || m_height == -1 )
255 {
256 Rect bestsize = { 0 , 0 , 0 , 0 } ;
257 short baselineoffset ;
258
259 UMAGetBestControlRect( m_macControl , &bestsize , &baselineoffset ) ;
260
261 if ( EmptyRect( &bestsize ) )
262 {
263 baselineoffset = 0;
264 bestsize.left = bestsize.top = 0 ;
265 bestsize.right = 16 ;
266 bestsize.bottom = 16 ;
267 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
268 {
269 bestsize.bottom = 16 ;
270 }
271 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
272 {
273 bestsize.bottom = 24 ;
274 }
275 }
276
277 if ( m_width == -1 )
278 {
279 if ( IsKindOf( CLASSINFO( wxButton ) ) )
280 {
281 m_width = m_label.Length() * 8 + 12 + 2 * m_macHorizontalBorder;
282 }
283 else if ( IsKindOf( CLASSINFO( wxStaticText ) ) )
284 {
285 m_width = m_label.Length() * 8 ;
286 }
287 else
288 m_width = bestsize.right - bestsize.left + 2 * m_macHorizontalBorder;
289 }
290 if ( m_height == -1 )
291 {
292 m_height = bestsize.bottom - bestsize.top ;
293 if ( m_height < 10 )
294 m_height = 13 ;
295
296 m_height += 2 * m_macVerticalBorder;
297 }
298
299 wxMacDrawingHelper helper ( wxFindWinFromMacWindow( GetMacRootWindow() ) ) ;
300 if ( helper.Ok() )
301 {
302 UMASizeControl( m_macControl , m_width - 2 * m_macHorizontalBorder, m_height - 2 * m_macVerticalBorder ) ;
303 }
304 }
305 }
306 ControlHandle wxControl::MacGetContainerForEmbedding()
307 {
308 if ( m_macControl )
309 return m_macControl ;
310
311 return wxWindow::MacGetContainerForEmbedding() ;
312 }
313
314 void wxControl::MacSuperChangedPosition()
315 {
316 if ( m_macControl )
317 {
318 int former_mac_x = (**m_macControl).contrlRect.left ;
319 int former_mac_y = (**m_macControl).contrlRect.top ;
320 int mac_x = m_x ;
321 int mac_y = m_y ;
322 GetParent()->MacClientToRootWindow( & mac_x , & mac_y ) ;
323
324 WindowRef rootwindow = GetMacRootWindow() ;
325 wxWindow* wxrootwindow = wxFindWinFromMacWindow( rootwindow ) ;
326 UMASetThemeWindowBackground( rootwindow , kThemeBrushDialogBackgroundActive , false ) ;
327 wxMacDrawingHelper focus( wxrootwindow ) ;
328
329 if ( mac_x != former_mac_x || mac_y != former_mac_y )
330 {
331 {
332 Rect inval = { former_mac_y , former_mac_x , former_mac_y + m_height , former_mac_x + m_width } ;
333 InvalRect( &inval ) ;
334 }
335 UMAMoveControl( m_macControl , mac_x + m_macHorizontalBorder , mac_y + m_macVerticalBorder ) ;
336 {
337 Rect inval = { mac_y , mac_x , mac_y + m_height , mac_x + m_width } ;
338 InvalRect( &inval ) ;
339 }
340 }
341 if ( wxrootwindow->IsKindOf( CLASSINFO( wxDialog ) ) )
342 {
343 }
344 else
345 {
346 UMASetThemeWindowBackground( rootwindow , kThemeBrushDocumentWindowBackground , false ) ;
347 }
348 }
349
350 wxWindow::MacSuperChangedPosition() ;
351 }
352
353 void wxControl::MacSuperEnabled( bool enabled )
354 {
355 if ( m_macControl )
356 {
357 if ( UMAHasAppearance() )
358 {
359 if ( !enabled )
360 {
361 ::DeactivateControl( m_macControl ) ;
362 }
363 else
364 {
365 if ( m_macEnabled )
366 ::ActivateControl( m_macControl ) ;
367 }
368 }
369 else
370 {
371 if ( !enabled )
372 {
373 ::HiliteControl( m_macControl , 255 ) ;
374 }
375 else
376 {
377 if ( m_macEnabled )
378 ::HiliteControl( m_macControl , 0 ) ;
379 }
380 }
381 }
382 wxWindow::MacSuperEnabled( enabled ) ;
383 }
384
385 void wxControl::MacSuperShown( bool show )
386 {
387 if ( m_macControl )
388 {
389 if ( !show )
390 {
391 ::UMAHideControl( m_macControl ) ;
392 }
393 else
394 {
395 if ( m_macShown )
396 ::UMAShowControl( m_macControl ) ;
397 }
398 }
399
400 wxWindow::MacSuperShown( show ) ;
401 }
402
403 void wxControl::DoSetSize(int x, int y,
404 int width, int height,
405 int sizeFlags )
406 {
407 if ( m_macControl == NULL )
408 {
409 wxWindow::DoSetSize( x , y ,width , height ,sizeFlags ) ;
410 return ;
411 }
412
413 WindowRef rootwindow = GetMacRootWindow() ;
414 wxWindow* wxrootwindow = wxFindWinFromMacWindow( rootwindow ) ;
415 UMASetThemeWindowBackground( rootwindow , kThemeBrushDialogBackgroundActive , false ) ;
416
417 int former_x = m_x ;
418 int former_y = m_y ;
419 int former_w = m_width ;
420 int former_h = m_height ;
421
422 int former_mac_x = (**m_macControl).contrlRect.left ;
423 int former_mac_y = (**m_macControl).contrlRect.top ;
424
425 int currentX, currentY;
426 GetPosition(&currentX, &currentY);
427 int currentW,currentH;
428 GetSize(&currentW, &currentH);
429
430 int actualWidth = width;
431 int actualHeight = height;
432 int actualX = x;
433 int actualY = y;
434 if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
435 actualX = currentX;
436 if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
437 actualY = currentY;
438 if (width == -1)
439 actualWidth = currentW ;
440 if (height == -1)
441 actualHeight = currentH ;
442
443 if ( actualX == currentX && actualY == currentY && actualWidth == currentW && actualHeight == currentH)
444 return ;
445
446 AdjustForParentClientOrigin(actualX, actualY, sizeFlags);
447 wxMacDrawingHelper focus( wxFindWinFromMacWindow( GetMacRootWindow() ) ) ;
448
449 int mac_x = actualX ;
450 int mac_y = actualY ;
451 GetParent()->MacClientToRootWindow( & mac_x , & mac_y ) ;
452
453 if ( mac_x != former_mac_x || mac_y != former_mac_y )
454 {
455 {
456 Rect inval = { former_mac_y , former_mac_x , former_mac_y + m_height , former_mac_x + m_width } ;
457 InvalRect( &inval ) ;
458 }
459 UMAMoveControl( m_macControl , mac_x + m_macHorizontalBorder , mac_y + m_macVerticalBorder ) ;
460 {
461 Rect inval = { mac_y , mac_x , mac_y + m_height , mac_x + m_width } ;
462 InvalRect( &inval ) ;
463 }
464 }
465
466 if ( actualX != former_x || actualY != former_y )
467 {
468 m_x = actualX ;
469 m_y = actualY ;
470
471 MacRepositionScrollBars() ;
472 // To consider -> should the parameters be the effective or the virtual coordinates (AdjustForParent..)
473 wxMoveEvent event(wxPoint(m_x, m_y), m_windowId);
474 event.SetEventObject(this);
475 GetEventHandler()->ProcessEvent(event);
476 }
477 if ( actualWidth != former_w || actualHeight != former_h )
478 {
479 {
480 Rect inval = { mac_y , mac_x , mac_y + former_h , mac_x + former_w } ;
481 InvalRect( &inval ) ;
482 }
483 m_width = actualWidth ;
484 m_height = actualHeight ;
485
486 UMASizeControl( m_macControl , m_width - 2 * m_macHorizontalBorder, m_height - 2 * m_macVerticalBorder ) ;
487 {
488 Rect inval = { mac_y , mac_x , mac_y + m_height , mac_x + m_width } ;
489 InvalRect( &inval ) ;
490 }
491
492 MacRepositionScrollBars() ;
493 wxSizeEvent event(wxSize(m_width, m_height), m_windowId);
494 event.SetEventObject(this);
495 GetEventHandler()->ProcessEvent(event);
496 }
497 if ( wxrootwindow->IsKindOf( CLASSINFO( wxDialog ) ) )
498 {
499 }
500 else
501 {
502 UMASetThemeWindowBackground( rootwindow , kThemeBrushDocumentWindowBackground , false ) ;
503 }
504 }
505
506 void wxControl::DoSetClientSize(int width, int height)
507 {
508 DoSetSize( -1 , -1 , width , height ) ;
509 }
510
511 bool wxControl::Show(bool show)
512 {
513 if ( m_macControl == NULL )
514 return wxWindow::Show( show ) ;
515
516 if ( m_macShown == show )
517 return TRUE ;
518
519 if ( show )
520 ::UMAShowControl( m_macControl ) ;
521 else
522 ::UMAHideControl( m_macControl ) ;
523
524 return wxWindow::Show( show ) ;
525 }
526
527 void wxControl::Enable(bool enable)
528 {
529 if ( m_macControl == NULL )
530 return wxWindow::Enable( enable ) ;
531
532 if ( m_macEnabled == enable )
533 return ;
534
535 if ( UMAHasAppearance() )
536 {
537 if ( enable )
538 ::ActivateControl( m_macControl ) ;
539 else
540 ::DeactivateControl( m_macControl ) ;
541 }
542 else
543 {
544 if ( enable )
545 ::HiliteControl( m_macControl , 0 ) ;
546 else
547 ::HiliteControl( m_macControl , 255 ) ;
548 }
549
550 return wxWindow::Enable( enable ) ;
551 }
552
553 void wxControl::Refresh(bool eraseBack, const wxRect *rect)
554 {
555 if ( m_macControl )
556 {
557 wxWindow::Refresh( eraseBack , rect ) ;
558 }
559 else
560 {
561 wxWindow::Refresh( eraseBack , rect ) ;
562 }
563 }
564
565 void wxControl::OnPaint(wxPaintEvent& event)
566 {
567 if ( m_macControl )
568 {
569 WindowRef window = GetMacRootWindow() ;
570 if ( window )
571 {
572 wxWindow* win = wxFindWinFromMacWindow( window ) ;
573 if ( win )
574 {
575 wxMacDrawingHelper help( win ) ;
576 SetOrigin( 0 , 0 ) ;
577
578 bool hasTabBehind = false ;
579 wxWindow* parent = GetParent() ;
580 while ( parent )
581 {
582 if( parent->m_macWindowData )
583 {
584 UMASetThemeWindowBackground( win->m_macWindowData->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
585 break ;
586 }
587
588 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
589 {
590 if ( ((wxControl*)parent)->m_macControl )
591 SetUpControlBackground( ((wxControl*)parent)->m_macControl , -1 , true ) ;
592 break ;
593 }
594
595 parent = parent->GetParent() ;
596 }
597
598 UMADrawControl( m_macControl ) ;
599 UMASetThemeWindowBackground( win->m_macWindowData->m_macWindow , win->m_macWindowData->m_macWindowBackgroundTheme , false ) ;
600 }
601 }
602 }
603 else
604 {
605 wxWindow::OnPaint( event ) ;
606 }
607 }
608
609 void wxControl::OnKeyDown( wxKeyEvent &event )
610 {
611 if ( m_macControl == NULL )
612 return ;
613
614 EventRecord *ev = wxTheApp->MacGetCurrentEvent() ;
615 short keycode ;
616 short keychar ;
617 keychar = short(ev->message & charCodeMask);
618 keycode = short(ev->message & keyCodeMask) >> 8 ;
619
620 UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ;
621 }
622
623 void wxControl::OnMouseEvent( wxMouseEvent &event )
624 {
625 if ( m_macControl == NULL )
626 {
627 event.Skip() ;
628 return ;
629 }
630
631 if (event.GetEventType() == wxEVT_LEFT_DOWN )
632 {
633
634 int x = event.m_x ;
635 int y = event.m_y ;
636
637 MacClientToRootWindow( &x , &y ) ;
638
639 ControlHandle control ;
640 Point localwhere ;
641 GrafPtr port ;
642 SInt16 controlpart ;
643 WindowRef window = GetMacRootWindow() ;
644
645 localwhere.h = x ;
646 localwhere.v = y ;
647
648 short modifiers = 0;
649
650 if ( !event.m_leftDown && !event.m_rightDown )
651 modifiers |= btnState ;
652
653 if ( event.m_shiftDown )
654 modifiers |= shiftKey ;
655
656 if ( event.m_controlDown )
657 modifiers |= controlKey ;
658
659 if ( event.m_altDown )
660 modifiers |= optionKey ;
661
662 if ( event.m_metaDown )
663 modifiers |= cmdKey ;
664
665 controlpart = FindControl( localwhere , window , &control ) ;
666 {
667 if ( AcceptsFocus() && FindFocus() != this )
668 {
669 SetFocus() ;
670 }
671 if ( control && UMAIsControlActive( control ) )
672 {
673 {
674 if ( controlpart == kControlIndicatorPart && !UMAHasAppearance() )
675 controlpart = UMAHandleControlClick( control , localwhere , modifiers , (ControlActionUPP) NULL ) ;
676 else
677 controlpart = UMAHandleControlClick( control , localwhere , modifiers , (ControlActionUPP) -1 ) ;
678 wxTheApp->s_lastMouseDown = 0 ;
679 if ( controlpart && ! ( ( UMAHasAppearance() || (controlpart != kControlIndicatorPart) )
680 && (IsKindOf( CLASSINFO( wxScrollBar ) ) ) ) ) // otherwise we will get the event twice
681 {
682 MacHandleControlClick( control , controlpart ) ;
683 }
684 }
685 }
686 }
687 }
688 }
689
690 bool wxControl::MacCanFocus() const
691 {
692 { if ( m_macControl == NULL )
693 return true ;
694 else
695 return false ;
696 }
697 }
698
699 void wxControl::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
700 {
701 wxASSERT_MSG( m_macControl != NULL , "No valid mac control" ) ;
702 }
703