1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxControl class
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "control.h"
18 #include "wx/control.h"
22 #include "wx/dcclient.h"
23 #include "wx/notebook.h"
24 #include "wx/tabctrl.h"
25 #include "wx/radiobox.h"
26 #include "wx/spinbutt.h"
27 #include "wx/scrolbar.h"
28 #include "wx/button.h"
29 #include "wx/dialog.h"
30 #include "wx/statbox.h"
32 #include "wx/stattext.h"
34 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_ABSTRACT_CLASS(wxControl
, wxWindow
)
37 BEGIN_EVENT_TABLE(wxControl
, wxWindow
)
38 EVT_MOUSE_EVENTS( wxControl::OnMouseEvent
)
39 // EVT_CHAR( wxControl::OnKeyDown )
40 EVT_PAINT( wxControl::OnPaint
)
44 #include "wx/mac/uma.h"
48 ControlActionUPP wxMacLiveScrollbarActionUPP
= NULL
;
50 pascal void wxMacLiveScrollbarActionProc( ControlHandle control
, ControlPartCode partCode
) ;
51 pascal void wxMacLiveScrollbarActionProc( ControlHandle control
, ControlPartCode partCode
)
55 wxControl
* wx
= (wxControl
*) GetControlReference( control
) ;
58 wx
->MacHandleControlClick( control
, partCode
) ;
63 ControlColorUPP wxMacSetupControlBackgroundUPP
= NULL
;
65 pascal OSStatus
wxMacSetupControlBackground( ControlRef iControl
, SInt16 iMessage
, SInt16 iDepth
, Boolean iIsColor
)
67 OSStatus status
= noErr
;
70 case kControlMsgSetUpBackground
:
72 wxControl
* wx
= (wxControl
*) GetControlReference( iControl
) ;
73 if ( wx
!= NULL
&& wx
->IsKindOf( CLASSINFO( wxControl
) ) )
75 wxDC::MacSetupBackgroundForCurrentPort( wx
->MacGetBackgroundBrush() ) ;
76 // SetThemeBackground( iDepth , iIsColor ) ;
91 wxControl::wxControl()
94 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
95 m_macVerticalBorder
= 0 ;
96 m_backgroundColour
= *wxWHITE
;
97 m_foregroundColour
= *wxBLACK
;
98 #if WXWIN_COMPATIBILITY
100 #endif // WXWIN_COMPATIBILITY
102 if ( wxMacLiveScrollbarActionUPP
== NULL
)
104 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
105 wxMacLiveScrollbarActionUPP
= NewControlActionUPP( wxMacLiveScrollbarActionProc
);
107 wxMacLiveScrollbarActionUPP
= NewControlActionProc( wxMacLiveScrollbarActionProc
) ;
112 bool wxControl::Create(wxWindow
*parent
, wxWindowID id
,
114 const wxSize
& size
, long style
,
115 const wxValidator
& validator
,
116 const wxString
& name
)
118 m_macControl
= NULL
;
119 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
120 m_macVerticalBorder
= 0 ;
121 bool rval
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
124 SetValidator(validator
);
130 wxControl::~wxControl()
132 m_isBeingDeleted
= TRUE
;
133 // If we delete an item, we should initialize the parent panel,
134 // because it could now be invalid.
135 wxWindow
*parent
= GetParent() ;
138 if (parent
->GetDefaultItem() == (wxButton
*) this)
139 parent
->SetDefaultItem(NULL
);
141 if ( (ControlHandle
) m_macControl
)
143 ::DisposeControl( (ControlHandle
) m_macControl
) ;
144 m_macControl
= NULL
;
148 void wxControl::SetLabel(const wxString
& title
)
152 if ( (ControlHandle
) m_macControl
)
157 if( wxApp::s_macDefaultEncodingIsPC
)
158 label
= wxMacMakeMacStringFromPC( title
) ;
163 c2pstrcpy( (StringPtr
) maclabel
, label
) ;
165 strcpy( (char *) maclabel
, label
) ;
166 c2pstr( (char *) maclabel
) ;
168 ::SetControlTitle( (ControlHandle
) m_macControl
, maclabel
) ;
173 wxSize
wxControl::DoGetBestSize() const
175 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
176 short baselineoffset
;
177 int bestWidth
, bestHeight
;
178 ::GetBestControlRect( (ControlHandle
) m_macControl
, &bestsize
, &baselineoffset
) ;
180 if ( EmptyRect( &bestsize
) )
183 bestsize
.left
= bestsize
.top
= 0 ;
184 bestsize
.right
= 16 ;
185 bestsize
.bottom
= 16 ;
186 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
188 bestsize
.bottom
= 16 ;
190 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
192 bestsize
.bottom
= 24 ;
196 if ( IsKindOf( CLASSINFO( wxButton
) ) )
198 bestWidth
= m_label
.Length() * 8 + 12 ;
199 if ( bestWidth
< 70 )
202 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
204 bestWidth
= m_label
.Length() * 8 ;
207 bestWidth
= bestsize
.right
- bestsize
.left
;
209 bestWidth
+= 2 * m_macHorizontalBorder
;
211 bestHeight
= bestsize
.bottom
- bestsize
.top
;
212 if ( bestHeight
< 10 )
215 bestHeight
+= 2 * m_macVerticalBorder
;
218 return wxSize(bestWidth
, bestHeight
);
221 bool wxControl::ProcessCommand (wxCommandEvent
& event
)
224 // 1) A callback function (to become obsolete)
225 // 2) OnCommand, starting at this window and working up parent hierarchy
226 // 3) OnCommand then calls ProcessEvent to search the event tables.
227 #if WXWIN_COMPATIBILITY
230 (void)(*m_callback
)(this, event
);
235 #endif // WXWIN_COMPATIBILITY
237 return GetEventHandler()->ProcessEvent(event
);
241 // ------------------------
242 wxList
*wxWinMacControlList
= NULL
;
243 wxControl
*wxFindControlFromMacControl(ControlHandle inControl
)
245 wxNode
*node
= wxWinMacControlList
->Find((long)inControl
);
248 return (wxControl
*)node
->Data();
251 void wxAssociateControlWithMacControl(ControlHandle inControl
, wxControl
*control
)
253 // adding NULL WindowRef is (first) surely a result of an error and
254 // (secondly) breaks menu command processing
255 wxCHECK_RET( inControl
!= (ControlHandle
) NULL
, "attempt to add a NULL WindowRef to window list" );
257 if ( !wxWinMacControlList
->Find((long)inControl
) )
258 wxWinMacControlList
->Append((long)inControl
, control
);
261 void wxRemoveMacControlAssociation(wxControl
*control
)
263 wxWinMacControlList
->DeleteObject(control
);
266 void wxControl::MacPreControlCreate( wxWindow
*parent
, wxWindowID id
, wxString label
,
268 const wxSize
& size
, long style
,
269 const wxValidator
& validator
,
270 const wxString
& name
, WXRECTPTR outBounds
, unsigned char* maclabel
)
275 SetValidator(validator
);
277 m_windowStyle
= style
;
278 parent
->AddChild(this);
280 m_backgroundColour
= parent
->GetBackgroundColour() ;
281 m_foregroundColour
= parent
->GetForegroundColour() ;
284 m_windowId
= NewControlId();
288 // These sizes will be adjusted in MacPostControlCreate
295 ((Rect
*)outBounds
)->top
= -10;
296 ((Rect
*)outBounds
)->left
= -10;
297 ((Rect
*)outBounds
)->bottom
= 0;
298 ((Rect
*)outBounds
)->right
= 0;
301 strcpy( c_text
, label
) ;
302 if( wxApp::s_macDefaultEncodingIsPC
)
304 wxMacConvertFromPCForControls( c_text
) ;
308 c2pstrcpy( (StringPtr
) maclabel
, c_text
) ;
310 strcpy( (char *) maclabel
, c_text
) ;
311 c2pstr( (char *) maclabel
) ;
315 void wxControl::MacPostControlCreate()
317 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, "No valid mac control" ) ;
319 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
323 else if ( !UMAHasAquaLayout() && (IsKindOf( CLASSINFO( wxStaticBox
) ) || IsKindOf( CLASSINFO( wxRadioBox
) ) || IsKindOf( CLASSINFO( wxButton
) ) ) )
325 ControlFontStyleRec controlstyle
;
326 controlstyle
.flags
= kControlUseFontMask
;
327 controlstyle
.font
= kControlFontSmallBoldSystemFont
;
329 ::SetControlFontStyle( (ControlHandle
) m_macControl
, &controlstyle
) ;
333 ControlFontStyleRec controlstyle
;
334 controlstyle
.flags
= kControlUseFontMask
;
335 controlstyle
.font
= kControlFontSmallSystemFont
;
337 ::SetControlFontStyle( (ControlHandle
) m_macControl
, &controlstyle
) ;
339 ControlHandle container
= (ControlHandle
) GetParent()->MacGetContainerForEmbedding() ;
340 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
341 ::EmbedControl( (ControlHandle
) m_macControl
, container
) ;
342 m_macControlIsShown
= true ;
344 wxAssociateControlWithMacControl( (ControlHandle
) m_macControl
, this ) ;
346 if ( wxMacSetupControlBackgroundUPP
== NULL
)
348 wxMacSetupControlBackgroundUPP
= NewControlColorUPP( wxMacSetupControlBackground
) ;
350 SetControlColorProc( (ControlHandle
) m_macControl
, wxMacSetupControlBackgroundUPP
) ;
352 // Adjust the controls size and position
353 wxPoint
pos(m_x
, m_y
);
354 wxSize
best_size( DoGetBestSize() );
355 wxSize
new_size( m_width
, m_height
);
357 m_x
= m_y
= m_width
= m_height
= -1; // Forces SetSize to move/size the control
359 if (new_size
.x
== -1) {
360 new_size
.x
= best_size
.x
;
362 if (new_size
.y
== -1) {
363 new_size
.y
= best_size
.y
;
366 SetSize(pos
.x
, pos
.y
, new_size
.x
, new_size
.y
);
368 UMAShowControl( (ControlHandle
) m_macControl
) ;
372 void wxControl::MacAdjustControlRect()
374 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, wxT("No valid mac control") ) ;
375 if ( m_width
== -1 || m_height
== -1 )
377 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
378 short baselineoffset
;
380 ::GetBestControlRect( (ControlHandle
) m_macControl
, &bestsize
, &baselineoffset
) ;
382 if ( EmptyRect( &bestsize
) )
385 bestsize
.left
= bestsize
.top
= 0 ;
386 bestsize
.right
= 16 ;
387 bestsize
.bottom
= 16 ;
388 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
390 bestsize
.bottom
= 16 ;
392 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
394 bestsize
.bottom
= 24 ;
400 if ( IsKindOf( CLASSINFO( wxButton
) ) )
402 m_width
= m_label
.Length() * 8 + 12 ;
406 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
408 m_width
= m_label
.Length() * 8 ;
411 m_width
= bestsize
.right
- bestsize
.left
;
413 m_width
+= 2 * m_macHorizontalBorder
;
415 if ( m_height
== -1 )
417 m_height
= bestsize
.bottom
- bestsize
.top
;
421 m_height
+= 2 * m_macVerticalBorder
;
424 UMASizeControl( (ControlHandle
) m_macControl
, m_width
- 2 * m_macHorizontalBorder
, m_height
- 2 * m_macVerticalBorder
) ;
428 WXWidget
wxControl::MacGetContainerForEmbedding()
431 return m_macControl
;
433 return wxWindow::MacGetContainerForEmbedding() ;
436 void wxControl::MacSuperChangedPosition()
438 if ( (ControlHandle
) m_macControl
)
441 GetControlBounds( (ControlHandle
) m_macControl
, &contrlRect
) ;
442 int former_mac_x
= contrlRect
.left
;
443 int former_mac_y
= contrlRect
.top
;
446 GetParent()->MacWindowToRootWindow( & mac_x
, & mac_y
) ;
448 WindowRef rootwindow
= (WindowRef
) MacGetRootWindow() ;
450 if ( mac_x
+ m_macHorizontalBorder
!= former_mac_x
||
451 mac_y
+ m_macVerticalBorder
!= former_mac_y
)
454 Rect inval
= { former_mac_y
, former_mac_x
, former_mac_y
+ m_height
, former_mac_x
+ m_width
} ;
455 InvalWindowRect( rootwindow
, &inval
) ;
457 UMAMoveControl( (ControlHandle
) m_macControl
, mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
) ;
459 Rect inval
= { mac_y
, mac_x
, mac_y
+ m_height
, mac_x
+ m_width
} ;
460 InvalWindowRect( rootwindow
, &inval
) ;
465 wxWindow::MacSuperChangedPosition() ;
468 void wxControl::MacSuperEnabled( bool enabled
)
471 wxWindow::MacSuperEnabled( enabled
) ;
474 void wxControl::MacSuperShown( bool show
)
476 if ( (ControlHandle
) m_macControl
)
480 if ( m_macControlIsShown
)
482 ::UMAHideControl( (ControlHandle
) m_macControl
) ;
483 m_macControlIsShown
= false ;
488 if ( MacIsReallyShown() && !m_macControlIsShown
)
490 ::UMAShowControl( (ControlHandle
) m_macControl
) ;
491 m_macControlIsShown
= true ;
496 wxWindow::MacSuperShown( show
) ;
499 void wxControl::DoSetSize(int x
, int y
,
500 int width
, int height
,
503 if ( (ControlHandle
) m_macControl
== NULL
)
505 wxWindow::DoSetSize( x
, y
,width
, height
,sizeFlags
) ;
510 int new_x
, new_y
, new_width
, new_height
;
516 new_height
= m_height
;
518 if (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
)
527 if (x
!= -1) new_x
= x
;
528 if (y
!= -1) new_y
= y
;
529 if (width
!= -1) new_width
= width
;
530 if (height
!= -1) new_height
= height
;
533 if(sizeFlags
& wxSIZE_AUTO
)
535 wxSize size
= GetBestSize();
536 if (sizeFlags
& wxSIZE_AUTO_WIDTH
)
538 if (width
== -1) new_width
= size
.x
;
540 if (sizeFlags
& wxSIZE_AUTO_HEIGHT
)
542 if (height
== -1) new_height
= size
.y
;
545 AdjustForParentClientOrigin(new_x
, new_y
, sizeFlags
);
550 GetParent()->MacWindowToRootWindow(&mac_x
, &mac_y
);
552 GetControlBounds( (ControlHandle
) m_macControl
, &oldbounds
);
553 oldbounds
.right
= oldbounds
.left
+ m_width
;
554 oldbounds
.bottom
= oldbounds
.top
+ m_height
;
557 bool doResize
= false;
559 if ( mac_x
!= (oldbounds
.left
- m_macHorizontalBorder
) ||
560 mac_y
!= (oldbounds
.top
- m_macVerticalBorder
) )
564 if ( new_width
!= oldbounds
.right
- oldbounds
.left
- 2 * m_macHorizontalBorder
||
565 new_height
!= oldbounds
.bottom
- oldbounds
.top
- 2 * m_macVerticalBorder
)
570 if ( doMove
|| doResize
)
574 // Ensure resize is within constraints
575 if ((m_minWidth
!= -1) && (new_width
< m_minWidth
)) {
576 new_width
= m_minWidth
;
578 if ((m_minHeight
!= -1) && (new_height
< m_minHeight
)) {
579 new_height
= m_minHeight
;
581 if ((m_maxWidth
!= -1) && (new_width
> m_maxWidth
)) {
582 new_width
= m_maxWidth
;
584 if ((m_maxHeight
!= -1) && (new_height
> m_maxHeight
)) {
585 new_height
= m_maxHeight
;
593 UMAMoveControl( (ControlHandle
) m_macControl
,
594 mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
);
596 wxMoveEvent
event(wxPoint(m_x
, m_y
), m_windowId
);
597 event
.SetEventObject(this);
598 GetEventHandler()->ProcessEvent(event
) ;
603 m_height
= new_height
;
605 UMASizeControl( (ControlHandle
) m_macControl
,
606 m_width
- 2 * m_macHorizontalBorder
,
607 m_height
- 2 * m_macVerticalBorder
) ;
610 wxSizeEvent
event(wxSize(m_width
, m_height
), m_windowId
);
611 event
.SetEventObject(this);
612 GetEventHandler()->ProcessEvent(event
);
619 bool wxControl::Show(bool show
)
621 if ( !wxWindow::Show( show
) )
624 if ( (ControlHandle
) m_macControl
)
628 if ( m_macControlIsShown
)
630 ::UMAHideControl( (ControlHandle
) m_macControl
) ;
631 m_macControlIsShown
= false ;
636 if ( MacIsReallyShown() && !m_macControlIsShown
)
638 ::UMAShowControl( (ControlHandle
) m_macControl
) ;
639 m_macControlIsShown
= true ;
646 bool wxControl::Enable(bool enable
)
648 if ( !wxWindow::Enable(enable
) )
651 if ( (ControlHandle
) m_macControl
)
654 UMAActivateControl( (ControlHandle
) m_macControl
) ;
656 UMADeactivateControl( (ControlHandle
) m_macControl
) ;
661 void wxControl::Refresh(bool eraseBack
, const wxRect
*rect
)
663 wxWindow::Refresh( eraseBack
, rect
) ;
666 void wxControl::MacRedrawControl()
668 if ( (ControlHandle
) m_macControl
&& MacGetRootWindow() )
670 wxClientDC
dc(this) ;
671 wxMacPortSetter
helper(&dc
) ;
673 // the controls sometimes draw outside their boundaries, this
674 // should be resolved differently but is not trivial (e.g. drop shadows)
675 // since adding them to the border would yield in enormous gaps between
677 Rect r
= { 0 , 0 , 32000 , 32000 } ;
679 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
680 UMADrawControl( (ControlHandle
) m_macControl
) ;
684 void wxControl::OnPaint(wxPaintEvent
& event
)
686 if ( (ControlHandle
) m_macControl
)
689 wxMacPortSetter
helper(&dc
) ;
690 // the controls sometimes draw outside their boundaries, this
691 // should be resolved differently but is not trivial (e.g. drop shadows)
692 // since adding them to the border would yield in enormous gaps between
694 Rect r
= { 0 , 0 , 32000 , 32000 } ;
697 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
698 UMADrawControl( (ControlHandle
) m_macControl
) ;
705 void wxControl::OnEraseBackground(wxEraseEvent
& event
)
707 wxWindow::OnEraseBackground( event
) ;
711 void wxControl::OnKeyDown( wxKeyEvent
&event
)
713 if ( (ControlHandle
) m_macControl
== NULL
)
716 EventRecord
*ev
= (EventRecord
*) wxTheApp
->MacGetCurrentEvent() ;
719 keychar
= short(ev
->message
& charCodeMask
);
720 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
722 ::HandleControlKey( (ControlHandle
) m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
725 void wxControl::OnMouseEvent( wxMouseEvent
&event
)
727 if ( (ControlHandle
) m_macControl
== NULL
)
733 if (event
.GetEventType() == wxEVT_LEFT_DOWN
|| event
.GetEventType() == wxEVT_LEFT_DCLICK
)
739 MacClientToRootWindow( &x
, &y
) ;
741 ControlHandle control
;
744 WindowRef window
= (WindowRef
) MacGetRootWindow() ;
751 if ( !event
.m_leftDown
&& !event
.m_rightDown
)
752 modifiers
|= btnState
;
754 if ( event
.m_shiftDown
)
755 modifiers
|= shiftKey
;
757 if ( event
.m_controlDown
)
758 modifiers
|= controlKey
;
760 if ( event
.m_altDown
)
761 modifiers
|= optionKey
;
763 if ( event
.m_metaDown
)
764 modifiers
|= cmdKey
;
767 control = FindControlUnderMouse( localwhere , window , &controlpart ) ;
769 controlpart = FindControl( localwhere , window , &control ) ;
774 if ( AcceptsFocus() && FindFocus() != this )
779 control
= (ControlHandle
) m_macControl
;
780 if ( control
&& ::IsControlActive( control
) )
783 controlpart
= ::HandleControlClick( control
, localwhere
, modifiers
, (ControlActionUPP
) -1 ) ;
784 wxTheApp
->s_lastMouseDown
= 0 ;
785 if ( control
&& controlpart
!= kControlNoPart
&&
786 ! IsKindOf( CLASSINFO( wxScrollBar
) )
787 ) // otherwise we will get the event twice for scrollbar
789 MacHandleControlClick( control
, controlpart
) ;
797 bool wxControl::MacCanFocus() const
799 { if ( (ControlHandle
) m_macControl
== NULL
)
806 void wxControl::MacHandleControlClick( WXWidget control
, wxInt16 controlpart
)
808 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, "No valid mac control" ) ;