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
:
71 wxControl
* wx
= (wxControl
*) GetControlReference( iControl
) ;
72 if ( wx
!= NULL
&& wx
->IsKindOf( CLASSINFO( wxControl
) ) )
74 wxDC::MacSetupBackgroundForCurrentPort( wx
->MacGetBackgroundBrush() ) ;
75 // SetThemeBackground( iDepth , iIsColor ) ;
89 wxControl::wxControl()
92 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
93 m_macVerticalBorder
= 0 ;
94 m_backgroundColour
= *wxWHITE
;
95 m_foregroundColour
= *wxBLACK
;
96 #if WXWIN_COMPATIBILITY
98 #endif // WXWIN_COMPATIBILITY
100 if ( wxMacLiveScrollbarActionUPP
== NULL
)
102 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
103 wxMacLiveScrollbarActionUPP
= NewControlActionUPP( wxMacLiveScrollbarActionProc
);
105 wxMacLiveScrollbarActionUPP
= NewControlActionProc( wxMacLiveScrollbarActionProc
) ;
110 bool wxControl::Create(wxWindow
*parent
, wxWindowID id
,
112 const wxSize
& size
, long style
,
113 const wxValidator
& validator
,
114 const wxString
& name
)
116 m_macControl
= NULL
;
117 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
118 m_macVerticalBorder
= 0 ;
119 bool rval
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
122 SetValidator(validator
);
128 wxControl::~wxControl()
130 m_isBeingDeleted
= TRUE
;
131 // If we delete an item, we should initialize the parent panel,
132 // because it could now be invalid.
133 wxWindow
*parent
= GetParent() ;
136 if (parent
->GetDefaultItem() == (wxButton
*) this)
137 parent
->SetDefaultItem(NULL
);
139 if ( (ControlHandle
) m_macControl
)
141 ::DisposeControl( (ControlHandle
) m_macControl
) ;
142 m_macControl
= NULL
;
146 void wxControl::SetLabel(const wxString
& title
)
150 if ( (ControlHandle
) m_macControl
)
155 if( wxApp::s_macDefaultEncodingIsPC
)
156 label
= wxMacMakeMacStringFromPC( title
) ;
161 c2pstrcpy( (StringPtr
) maclabel
, label
) ;
163 strcpy( (char *) maclabel
, label
) ;
164 c2pstr( (char *) maclabel
) ;
166 ::SetControlTitle( (ControlHandle
) m_macControl
, maclabel
) ;
171 wxSize
wxControl::DoGetBestSize() const
173 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
174 short baselineoffset
;
175 int bestWidth
, bestHeight
;
176 ::GetBestControlRect( (ControlHandle
) m_macControl
, &bestsize
, &baselineoffset
) ;
178 if ( EmptyRect( &bestsize
) )
181 bestsize
.left
= bestsize
.top
= 0 ;
182 bestsize
.right
= 16 ;
183 bestsize
.bottom
= 16 ;
184 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
186 bestsize
.bottom
= 16 ;
188 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
190 bestsize
.bottom
= 24 ;
194 if ( IsKindOf( CLASSINFO( wxButton
) ) )
196 bestWidth
= m_label
.Length() * 8 + 12 ;
197 if ( bestWidth
< 70 )
200 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
202 bestWidth
= m_label
.Length() * 8 ;
205 bestWidth
= bestsize
.right
- bestsize
.left
;
207 bestWidth
+= 2 * m_macHorizontalBorder
;
209 bestHeight
= bestsize
.bottom
- bestsize
.top
;
210 if ( bestHeight
< 10 )
213 bestHeight
+= 2 * m_macVerticalBorder
;
216 return wxSize(bestWidth
, bestHeight
);
219 bool wxControl::ProcessCommand (wxCommandEvent
& event
)
222 // 1) A callback function (to become obsolete)
223 // 2) OnCommand, starting at this window and working up parent hierarchy
224 // 3) OnCommand then calls ProcessEvent to search the event tables.
225 #if WXWIN_COMPATIBILITY
228 (void)(*m_callback
)(this, event
);
233 #endif // WXWIN_COMPATIBILITY
235 return GetEventHandler()->ProcessEvent(event
);
239 // ------------------------
240 wxList
*wxWinMacControlList
= NULL
;
241 wxControl
*wxFindControlFromMacControl(ControlHandle inControl
)
243 wxNode
*node
= wxWinMacControlList
->Find((long)inControl
);
246 return (wxControl
*)node
->Data();
249 void wxAssociateControlWithMacControl(ControlHandle inControl
, wxControl
*control
)
251 // adding NULL WindowRef is (first) surely a result of an error and
252 // (secondly) breaks menu command processing
253 wxCHECK_RET( inControl
!= (ControlHandle
) NULL
, "attempt to add a NULL WindowRef to window list" );
255 if ( !wxWinMacControlList
->Find((long)inControl
) )
256 wxWinMacControlList
->Append((long)inControl
, control
);
259 void wxRemoveMacControlAssociation(wxControl
*control
)
261 wxWinMacControlList
->DeleteObject(control
);
264 void wxControl::MacPreControlCreate( wxWindow
*parent
, wxWindowID id
, wxString label
,
266 const wxSize
& size
, long style
,
267 const wxValidator
& validator
,
268 const wxString
& name
, WXRECTPTR outBounds
, unsigned char* maclabel
)
273 SetValidator(validator
);
275 m_windowStyle
= style
;
276 parent
->AddChild(this);
278 m_backgroundColour
= parent
->GetBackgroundColour() ;
279 m_foregroundColour
= parent
->GetForegroundColour() ;
282 m_windowId
= NewControlId();
286 // These sizes will be adjusted in MacPostControlCreate
293 ((Rect
*)outBounds
)->top
= -10;
294 ((Rect
*)outBounds
)->left
= -10;
295 ((Rect
*)outBounds
)->bottom
= 0;
296 ((Rect
*)outBounds
)->right
= 0;
299 strcpy( c_text
, label
) ;
300 if( wxApp::s_macDefaultEncodingIsPC
)
302 wxMacConvertFromPCForControls( c_text
) ;
306 c2pstrcpy( (StringPtr
) maclabel
, c_text
) ;
308 strcpy( (char *) maclabel
, c_text
) ;
309 c2pstr( (char *) maclabel
) ;
313 void wxControl::MacPostControlCreate()
315 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, "No valid mac control" ) ;
317 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
321 else if ( !UMAHasAquaLayout() && (IsKindOf( CLASSINFO( wxStaticBox
) ) || IsKindOf( CLASSINFO( wxRadioBox
) ) || IsKindOf( CLASSINFO( wxButton
) ) ) )
323 ControlFontStyleRec controlstyle
;
324 controlstyle
.flags
= kControlUseFontMask
;
325 controlstyle
.font
= kControlFontSmallBoldSystemFont
;
327 ::SetControlFontStyle( (ControlHandle
) m_macControl
, &controlstyle
) ;
331 ControlFontStyleRec controlstyle
;
332 controlstyle
.flags
= kControlUseFontMask
;
333 controlstyle
.font
= kControlFontSmallSystemFont
;
335 ::SetControlFontStyle( (ControlHandle
) m_macControl
, &controlstyle
) ;
337 ControlHandle container
= (ControlHandle
) GetParent()->MacGetContainerForEmbedding() ;
338 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
339 ::EmbedControl( (ControlHandle
) m_macControl
, container
) ;
340 m_macControlIsShown
= true ;
342 wxAssociateControlWithMacControl( (ControlHandle
) m_macControl
, this ) ;
344 if ( wxMacSetupControlBackgroundUPP
== NULL
)
346 wxMacSetupControlBackgroundUPP
= NewControlColorUPP( wxMacSetupControlBackground
) ;
348 SetControlColorProc( (ControlHandle
) m_macControl
, wxMacSetupControlBackgroundUPP
) ;
350 // Adjust the controls size and position
351 wxPoint
pos(m_x
, m_y
);
352 wxSize
best_size( DoGetBestSize() );
353 wxSize
new_size( m_width
, m_height
);
355 m_x
= m_y
= m_width
= m_height
= -1; // Forces SetSize to move/size the control
357 if (new_size
.x
== -1) {
358 new_size
.x
= best_size
.x
;
360 if (new_size
.y
== -1) {
361 new_size
.y
= best_size
.y
;
364 SetSize(pos
.x
, pos
.y
, new_size
.x
, new_size
.y
);
366 UMAShowControl( (ControlHandle
) m_macControl
) ;
370 void wxControl::MacAdjustControlRect()
372 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, wxT("No valid mac control") ) ;
373 if ( m_width
== -1 || m_height
== -1 )
375 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
376 short baselineoffset
;
378 ::GetBestControlRect( (ControlHandle
) m_macControl
, &bestsize
, &baselineoffset
) ;
380 if ( EmptyRect( &bestsize
) )
383 bestsize
.left
= bestsize
.top
= 0 ;
384 bestsize
.right
= 16 ;
385 bestsize
.bottom
= 16 ;
386 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
388 bestsize
.bottom
= 16 ;
390 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
392 bestsize
.bottom
= 24 ;
398 if ( IsKindOf( CLASSINFO( wxButton
) ) )
400 m_width
= m_label
.Length() * 8 + 12 ;
404 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
406 m_width
= m_label
.Length() * 8 ;
409 m_width
= bestsize
.right
- bestsize
.left
;
411 m_width
+= 2 * m_macHorizontalBorder
;
413 if ( m_height
== -1 )
415 m_height
= bestsize
.bottom
- bestsize
.top
;
419 m_height
+= 2 * m_macVerticalBorder
;
422 UMASizeControl( (ControlHandle
) m_macControl
, m_width
- 2 * m_macHorizontalBorder
, m_height
- 2 * m_macVerticalBorder
) ;
426 WXWidget
wxControl::MacGetContainerForEmbedding()
429 return m_macControl
;
431 return wxWindow::MacGetContainerForEmbedding() ;
434 void wxControl::MacSuperChangedPosition()
436 if ( (ControlHandle
) m_macControl
)
439 GetControlBounds( (ControlHandle
) m_macControl
, &contrlRect
) ;
440 int former_mac_x
= contrlRect
.left
;
441 int former_mac_y
= contrlRect
.top
;
444 GetParent()->MacWindowToRootWindow( & mac_x
, & mac_y
) ;
446 WindowRef rootwindow
= (WindowRef
) MacGetRootWindow() ;
448 if ( mac_x
+ m_macHorizontalBorder
!= former_mac_x
||
449 mac_y
+ m_macVerticalBorder
!= former_mac_y
)
452 Rect inval
= { former_mac_y
, former_mac_x
, former_mac_y
+ m_height
, former_mac_x
+ m_width
} ;
453 InvalWindowRect( rootwindow
, &inval
) ;
455 UMAMoveControl( (ControlHandle
) m_macControl
, mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
) ;
457 Rect inval
= { mac_y
, mac_x
, mac_y
+ m_height
, mac_x
+ m_width
} ;
458 InvalWindowRect( rootwindow
, &inval
) ;
463 wxWindow::MacSuperChangedPosition() ;
466 void wxControl::MacSuperEnabled( bool enabled
)
469 wxWindow::MacSuperEnabled( enabled
) ;
472 void wxControl::MacSuperShown( bool show
)
474 if ( (ControlHandle
) m_macControl
)
478 if ( m_macControlIsShown
)
480 ::UMAHideControl( (ControlHandle
) m_macControl
) ;
481 m_macControlIsShown
= false ;
486 if ( MacIsReallyShown() && !m_macControlIsShown
)
488 ::UMAShowControl( (ControlHandle
) m_macControl
) ;
489 m_macControlIsShown
= true ;
494 wxWindow::MacSuperShown( show
) ;
497 void wxControl::DoSetSize(int x
, int y
,
498 int width
, int height
,
501 if ( (ControlHandle
) m_macControl
== NULL
)
503 wxWindow::DoSetSize( x
, y
,width
, height
,sizeFlags
) ;
508 int new_x
, new_y
, new_width
, new_height
;
514 new_height
= m_height
;
516 if (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
)
525 if (x
!= -1) new_x
= x
;
526 if (y
!= -1) new_y
= y
;
527 if (width
!= -1) new_width
= width
;
528 if (height
!= -1) new_height
= height
;
531 if(sizeFlags
& wxSIZE_AUTO
)
533 wxSize size
= GetBestSize();
534 if (sizeFlags
& wxSIZE_AUTO_WIDTH
)
536 if (width
== -1) new_width
= size
.x
;
538 if (sizeFlags
& wxSIZE_AUTO_HEIGHT
)
540 if (height
== -1) new_height
= size
.y
;
543 AdjustForParentClientOrigin(new_x
, new_y
, sizeFlags
);
548 GetParent()->MacWindowToRootWindow(&mac_x
, &mac_y
);
550 GetControlBounds( (ControlHandle
) m_macControl
, &oldbounds
);
551 oldbounds
.right
= oldbounds
.left
+ m_width
;
552 oldbounds
.bottom
= oldbounds
.top
+ m_height
;
555 bool doResize
= false;
557 if ( mac_x
!= (oldbounds
.left
- m_macHorizontalBorder
) ||
558 mac_y
!= (oldbounds
.top
- m_macVerticalBorder
) )
562 if ( new_width
!= oldbounds
.right
- oldbounds
.left
- 2 * m_macHorizontalBorder
||
563 new_height
!= oldbounds
.bottom
- oldbounds
.top
- 2 * m_macVerticalBorder
)
568 if ( doMove
|| doResize
)
572 // Ensure resize is within constraints
573 if ((m_minWidth
!= -1) && (new_width
< m_minWidth
)) {
574 new_width
= m_minWidth
;
576 if ((m_minHeight
!= -1) && (new_height
< m_minHeight
)) {
577 new_height
= m_minHeight
;
579 if ((m_maxWidth
!= -1) && (new_width
> m_maxWidth
)) {
580 new_width
= m_maxWidth
;
582 if ((m_maxHeight
!= -1) && (new_height
> m_maxHeight
)) {
583 new_height
= m_maxHeight
;
591 UMAMoveControl( (ControlHandle
) m_macControl
,
592 mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
);
594 wxMoveEvent
event(wxPoint(m_x
, m_y
), m_windowId
);
595 event
.SetEventObject(this);
596 GetEventHandler()->ProcessEvent(event
) ;
601 m_height
= new_height
;
603 UMASizeControl( (ControlHandle
) m_macControl
,
604 m_width
- 2 * m_macHorizontalBorder
,
605 m_height
- 2 * m_macVerticalBorder
) ;
608 wxSizeEvent
event(wxSize(m_width
, m_height
), m_windowId
);
609 event
.SetEventObject(this);
610 GetEventHandler()->ProcessEvent(event
);
617 bool wxControl::Show(bool show
)
619 if ( !wxWindow::Show( show
) )
622 if ( (ControlHandle
) m_macControl
)
626 if ( m_macControlIsShown
)
628 ::UMAHideControl( (ControlHandle
) m_macControl
) ;
629 m_macControlIsShown
= false ;
634 if ( MacIsReallyShown() && !m_macControlIsShown
)
636 ::UMAShowControl( (ControlHandle
) m_macControl
) ;
637 m_macControlIsShown
= true ;
644 bool wxControl::Enable(bool enable
)
646 if ( !wxWindow::Enable(enable
) )
649 if ( (ControlHandle
) m_macControl
)
652 UMAActivateControl( (ControlHandle
) m_macControl
) ;
654 UMADeactivateControl( (ControlHandle
) m_macControl
) ;
659 void wxControl::Refresh(bool eraseBack
, const wxRect
*rect
)
661 wxWindow::Refresh( eraseBack
, rect
) ;
664 void wxControl::MacRedrawControl()
666 if ( (ControlHandle
) m_macControl
&& MacGetRootWindow() )
668 wxClientDC
dc(this) ;
669 wxMacPortSetter
helper(&dc
) ;
671 // the controls sometimes draw outside their boundaries, this
672 // should be resolved differently but is not trivial (e.g. drop shadows)
673 // since adding them to the border would yield in enormous gaps between
675 Rect r
= { 0 , 0 , 32000 , 32000 } ;
677 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
678 UMADrawControl( (ControlHandle
) m_macControl
) ;
682 void wxControl::OnPaint(wxPaintEvent
& event
)
684 if ( (ControlHandle
) m_macControl
)
687 wxMacPortSetter
helper(&dc
) ;
688 // the controls sometimes draw outside their boundaries, this
689 // should be resolved differently but is not trivial (e.g. drop shadows)
690 // since adding them to the border would yield in enormous gaps between
692 Rect r
= { 0 , 0 , 32000 , 32000 } ;
695 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
696 UMADrawControl( (ControlHandle
) m_macControl
) ;
703 void wxControl::OnEraseBackground(wxEraseEvent
& event
)
705 wxWindow::OnEraseBackground( event
) ;
709 void wxControl::OnKeyDown( wxKeyEvent
&event
)
711 if ( (ControlHandle
) m_macControl
== NULL
)
714 EventRecord
*ev
= (EventRecord
*) wxTheApp
->MacGetCurrentEvent() ;
717 keychar
= short(ev
->message
& charCodeMask
);
718 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
720 ::HandleControlKey( (ControlHandle
) m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
723 void wxControl::OnMouseEvent( wxMouseEvent
&event
)
725 if ( (ControlHandle
) m_macControl
== NULL
)
731 if (event
.GetEventType() == wxEVT_LEFT_DOWN
|| event
.GetEventType() == wxEVT_LEFT_DCLICK
)
737 MacClientToRootWindow( &x
, &y
) ;
739 ControlHandle control
;
742 WindowRef window
= (WindowRef
) MacGetRootWindow() ;
749 if ( !event
.m_leftDown
&& !event
.m_rightDown
)
750 modifiers
|= btnState
;
752 if ( event
.m_shiftDown
)
753 modifiers
|= shiftKey
;
755 if ( event
.m_controlDown
)
756 modifiers
|= controlKey
;
758 if ( event
.m_altDown
)
759 modifiers
|= optionKey
;
761 if ( event
.m_metaDown
)
762 modifiers
|= cmdKey
;
765 control = FindControlUnderMouse( localwhere , window , &controlpart ) ;
767 controlpart = FindControl( localwhere , window , &control ) ;
772 if ( AcceptsFocus() && FindFocus() != this )
777 control
= (ControlHandle
) m_macControl
;
778 if ( control
&& ::IsControlActive( control
) )
781 controlpart
= ::HandleControlClick( control
, localwhere
, modifiers
, (ControlActionUPP
) -1 ) ;
782 wxTheApp
->s_lastMouseDown
= 0 ;
783 if ( control
&& controlpart
!= kControlNoPart
&&
784 ! IsKindOf( CLASSINFO( wxScrollBar
) )
785 ) // otherwise we will get the event twice for scrollbar
787 MacHandleControlClick( control
, controlpart
) ;
795 bool wxControl::MacCanFocus() const
797 { if ( (ControlHandle
) m_macControl
== NULL
)
804 void wxControl::MacHandleControlClick( WXWidget control
, wxInt16 controlpart
)
806 wxASSERT_MSG( (ControlHandle
) m_macControl
!= NULL
, "No valid mac control" ) ;