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 wxControl::wxControl()
66 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
67 m_macVerticalBorder
= 0 ;
68 m_backgroundColour
= *wxWHITE
;
69 m_foregroundColour
= *wxBLACK
;
70 #if WXWIN_COMPATIBILITY
72 #endif // WXWIN_COMPATIBILITY
74 if ( wxMacLiveScrollbarActionUPP
== NULL
)
76 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
77 wxMacLiveScrollbarActionUPP
= NewControlActionUPP( wxMacLiveScrollbarActionProc
);
79 wxMacLiveScrollbarActionUPP
= NewControlActionProc( wxMacLiveScrollbarActionProc
) ;
84 bool wxControl::Create(wxWindow
*parent
, wxWindowID id
,
86 const wxSize
& size
, long style
,
87 const wxValidator
& validator
,
91 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
92 m_macVerticalBorder
= 0 ;
93 bool rval
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
96 SetValidator(validator
);
102 wxControl::~wxControl()
104 m_isBeingDeleted
= TRUE
;
105 // If we delete an item, we should initialize the parent panel,
106 // because it could now be invalid.
107 wxWindow
*parent
= GetParent() ;
110 if (parent
->GetDefaultItem() == (wxButton
*) this)
111 parent
->SetDefaultItem(NULL
);
115 ::DisposeControl( m_macControl
) ;
116 m_macControl
= NULL
;
120 void wxControl::SetLabel(const wxString
& title
)
129 if( wxApp::s_macDefaultEncodingIsPC
)
130 label
= wxMacMakeMacStringFromPC( title
) ;
135 c2pstrcpy( (StringPtr
) maclabel
, label
) ;
137 strcpy( (char *) maclabel
, label
) ;
138 c2pstr( (char *) maclabel
) ;
140 ::SetControlTitle( m_macControl
, maclabel
) ;
145 wxSize
wxControl::DoGetBestSize() const
147 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
148 short baselineoffset
;
149 int bestWidth
, bestHeight
;
150 ::GetBestControlRect( m_macControl
, &bestsize
, &baselineoffset
) ;
152 if ( EmptyRect( &bestsize
) )
155 bestsize
.left
= bestsize
.top
= 0 ;
156 bestsize
.right
= 16 ;
157 bestsize
.bottom
= 16 ;
158 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
160 bestsize
.bottom
= 16 ;
162 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
164 bestsize
.bottom
= 24 ;
168 if ( IsKindOf( CLASSINFO( wxButton
) ) )
170 bestWidth
= m_label
.Length() * 8 + 12 ;
171 if ( bestWidth
< 70 )
174 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
176 bestWidth
= m_label
.Length() * 8 ;
179 bestWidth
= bestsize
.right
- bestsize
.left
;
181 bestWidth
+= 2 * m_macHorizontalBorder
;
183 bestHeight
= bestsize
.bottom
- bestsize
.top
;
184 if ( bestHeight
< 10 )
187 bestHeight
+= 2 * m_macVerticalBorder
;
190 return wxSize(bestWidth
, bestHeight
);
193 bool wxControl::ProcessCommand (wxCommandEvent
& event
)
196 // 1) A callback function (to become obsolete)
197 // 2) OnCommand, starting at this window and working up parent hierarchy
198 // 3) OnCommand then calls ProcessEvent to search the event tables.
199 #if WXWIN_COMPATIBILITY
202 (void)(*m_callback
)(this, event
);
207 #endif // WXWIN_COMPATIBILITY
209 return GetEventHandler()->ProcessEvent(event
);
213 // ------------------------
214 wxList
*wxWinMacControlList
= NULL
;
215 wxControl
*wxFindControlFromMacControl(ControlHandle inControl
)
217 wxNode
*node
= wxWinMacControlList
->Find((long)inControl
);
220 return (wxControl
*)node
->Data();
223 void wxAssociateControlWithMacControl(ControlHandle inControl
, wxControl
*control
)
225 // adding NULL WindowRef is (first) surely a result of an error and
226 // (secondly) breaks menu command processing
227 wxCHECK_RET( inControl
!= (ControlHandle
) NULL
, "attempt to add a NULL WindowRef to window list" );
229 if ( !wxWinMacControlList
->Find((long)inControl
) )
230 wxWinMacControlList
->Append((long)inControl
, control
);
233 void wxRemoveMacControlAssociation(wxControl
*control
)
235 wxWinMacControlList
->DeleteObject(control
);
238 void wxControl::MacPreControlCreate( wxWindow
*parent
, wxWindowID id
, wxString label
,
240 const wxSize
& size
, long style
,
241 const wxValidator
& validator
,
242 const wxString
& name
, Rect
*outBounds
, StringPtr maclabel
)
247 SetValidator(validator
);
249 m_windowStyle
= style
;
250 parent
->AddChild(this);
252 m_backgroundColour
= parent
->GetBackgroundColour() ;
253 m_foregroundColour
= parent
->GetForegroundColour() ;
256 m_windowId
= NewControlId();
260 // These sizes will be adjusted in MacPostControlCreate
267 outBounds
->top
= -10;
268 outBounds
->left
= -10;
269 outBounds
->bottom
= 0;
270 outBounds
->right
= 0;
273 strcpy( c_text
, label
) ;
274 if( wxApp::s_macDefaultEncodingIsPC
)
276 wxMacConvertFromPCForControls( c_text
) ;
280 c2pstrcpy( (StringPtr
) maclabel
, c_text
) ;
282 strcpy( (char *) maclabel
, c_text
) ;
283 c2pstr( (char *) maclabel
) ;
287 void wxControl::MacPostControlCreate()
289 wxASSERT_MSG( m_macControl
!= NULL
, "No valid mac control" ) ;
291 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
295 else if ( IsKindOf( CLASSINFO( wxStaticBox
) ) || IsKindOf( CLASSINFO( wxRadioBox
) ) || IsKindOf( CLASSINFO( wxButton
) ) )
297 ControlFontStyleRec controlstyle
;
298 controlstyle
.flags
= kControlUseFontMask
;
299 controlstyle
.font
= kControlFontSmallBoldSystemFont
;
301 ::SetControlFontStyle( m_macControl
, &controlstyle
) ;
305 ControlFontStyleRec controlstyle
;
306 controlstyle
.flags
= kControlUseFontMask
;
307 controlstyle
.font
= kControlFontSmallSystemFont
;
309 ::SetControlFontStyle( m_macControl
, &controlstyle
) ;
311 ControlHandle container
= GetParent()->MacGetContainerForEmbedding() ;
312 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
313 ::EmbedControl( m_macControl
, container
) ;
314 m_macControlIsShown
= true ;
316 wxAssociateControlWithMacControl( m_macControl
, this ) ;
319 // Adjust the controls size and position
320 wxPoint
pos(m_x
, m_y
);
321 wxSize
best_size( DoGetBestSize() );
322 wxSize
new_size( m_width
, m_height
);
324 m_x
= m_y
= m_width
= m_height
= -1; // Forces SetSize to move/size the control
326 if (new_size
.x
== -1) {
327 new_size
.x
= best_size
.x
;
329 if (new_size
.y
== -1) {
330 new_size
.y
= best_size
.y
;
333 SetSize(pos
.x
, pos
.y
, new_size
.x
, new_size
.y
);
335 UMAShowControl( m_macControl
) ;
339 void wxControl::MacAdjustControlRect()
341 wxASSERT_MSG( m_macControl
!= NULL
, wxT("No valid mac control") ) ;
342 if ( m_width
== -1 || m_height
== -1 )
344 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
345 short baselineoffset
;
347 ::GetBestControlRect( m_macControl
, &bestsize
, &baselineoffset
) ;
349 if ( EmptyRect( &bestsize
) )
352 bestsize
.left
= bestsize
.top
= 0 ;
353 bestsize
.right
= 16 ;
354 bestsize
.bottom
= 16 ;
355 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
357 bestsize
.bottom
= 16 ;
359 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
361 bestsize
.bottom
= 24 ;
367 if ( IsKindOf( CLASSINFO( wxButton
) ) )
369 m_width
= m_label
.Length() * 8 + 12 ;
373 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
375 m_width
= m_label
.Length() * 8 ;
378 m_width
= bestsize
.right
- bestsize
.left
;
380 m_width
+= 2 * m_macHorizontalBorder
;
382 if ( m_height
== -1 )
384 m_height
= bestsize
.bottom
- bestsize
.top
;
388 m_height
+= 2 * m_macVerticalBorder
;
391 UMASizeControl( m_macControl
, m_width
- 2 * m_macHorizontalBorder
, m_height
- 2 * m_macVerticalBorder
) ;
394 ControlHandle
wxControl::MacGetContainerForEmbedding()
397 return m_macControl
;
399 return wxWindow::MacGetContainerForEmbedding() ;
402 void wxControl::MacSuperChangedPosition()
407 GetControlBounds( m_macControl
, &contrlRect
) ;
408 int former_mac_x
= contrlRect
.left
;
409 int former_mac_y
= contrlRect
.top
;
412 GetParent()->MacWindowToRootWindow( & mac_x
, & mac_y
) ;
414 WindowRef rootwindow
= MacGetRootWindow() ;
416 if ( mac_x
+ m_macHorizontalBorder
!= former_mac_x
||
417 mac_y
+ m_macVerticalBorder
!= former_mac_y
)
420 Rect inval
= { former_mac_y
, former_mac_x
, former_mac_y
+ m_height
, former_mac_x
+ m_width
} ;
421 InvalWindowRect( rootwindow
, &inval
) ;
423 UMAMoveControl( m_macControl
, mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
) ;
425 Rect inval
= { mac_y
, mac_x
, mac_y
+ m_height
, mac_x
+ m_width
} ;
426 InvalWindowRect( rootwindow
, &inval
) ;
431 wxWindow::MacSuperChangedPosition() ;
434 void wxControl::MacSuperEnabled( bool enabled
)
437 wxWindow::MacSuperEnabled( enabled
) ;
440 void wxControl::MacSuperShown( bool show
)
446 if ( m_macControlIsShown
)
448 ::UMAHideControl( m_macControl
) ;
449 m_macControlIsShown
= false ;
454 if ( MacIsReallyShown() && !m_macControlIsShown
)
456 ::UMAShowControl( m_macControl
) ;
457 m_macControlIsShown
= true ;
462 wxWindow::MacSuperShown( show
) ;
465 void wxControl::DoSetSize(int x
, int y
,
466 int width
, int height
,
469 if ( m_macControl
== NULL
)
471 wxWindow::DoSetSize( x
, y
,width
, height
,sizeFlags
) ;
475 Rect oldbounds
, newbounds
;
476 int new_x
, new_y
, new_width
, new_height
;
482 new_height
= m_height
;
484 if (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
)
493 if (x
!= -1) new_x
= x
;
494 if (y
!= -1) new_y
= y
;
495 if (width
!= -1) new_width
= width
;
496 if (height
!= -1) new_height
= height
;
499 if(sizeFlags
& wxSIZE_AUTO
)
501 wxSize size
= GetBestSize();
502 if (sizeFlags
& wxSIZE_AUTO_WIDTH
)
504 if (width
== -1) new_width
= size
.x
;
506 if (sizeFlags
& wxSIZE_AUTO_HEIGHT
)
508 if (height
== -1) new_height
= size
.y
;
511 AdjustForParentClientOrigin(new_x
, new_y
, sizeFlags
);
516 GetParent()->MacWindowToRootWindow(&mac_x
, &mac_y
);
518 GetControlBounds(m_macControl
, &oldbounds
);
519 oldbounds
.right
= oldbounds
.left
+ m_width
;
520 oldbounds
.bottom
= oldbounds
.top
+ m_height
;
523 bool doResize
= false;
525 if ( mac_x
!= (oldbounds
.left
- m_macHorizontalBorder
) ||
526 mac_y
!= (oldbounds
.top
- m_macVerticalBorder
) )
530 if ( new_width
!= oldbounds
.right
- oldbounds
.left
- 2 * m_macHorizontalBorder
||
531 new_height
!= oldbounds
.bottom
- oldbounds
.top
- 2 * m_macVerticalBorder
)
536 if ( doMove
|| doResize
)
540 // Ensure resize is within constraints
541 if ((m_minWidth
!= -1) && (new_width
< m_minWidth
)) {
542 new_width
= m_minWidth
;
544 if ((m_minHeight
!= -1) && (new_height
< m_minHeight
)) {
545 new_height
= m_minHeight
;
547 if ((m_maxWidth
!= -1) && (new_width
> m_maxWidth
)) {
548 new_width
= m_maxWidth
;
550 if ((m_maxHeight
!= -1) && (new_height
> m_maxHeight
)) {
551 new_height
= m_maxHeight
;
559 UMAMoveControl(m_macControl
,
560 mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
);
562 wxMoveEvent
event(wxPoint(m_x
, m_y
), m_windowId
);
563 event
.SetEventObject(this);
564 GetEventHandler()->ProcessEvent(event
) ;
569 m_height
= new_height
;
571 UMASizeControl( m_macControl
,
572 m_width
- 2 * m_macHorizontalBorder
,
573 m_height
- 2 * m_macVerticalBorder
) ;
576 wxSizeEvent
event(wxSize(m_width
, m_height
), m_windowId
);
577 event
.SetEventObject(this);
578 GetEventHandler()->ProcessEvent(event
);
585 bool wxControl::Show(bool show
)
587 if ( !wxWindow::Show( show
) )
594 if ( m_macControlIsShown
)
596 ::UMAHideControl( m_macControl
) ;
597 m_macControlIsShown
= false ;
602 if ( MacIsReallyShown() && !m_macControlIsShown
)
604 ::UMAShowControl( m_macControl
) ;
605 m_macControlIsShown
= true ;
612 bool wxControl::Enable(bool enable
)
614 if ( !wxWindow::Enable(enable
) )
620 UMAActivateControl( m_macControl
) ;
622 UMADeactivateControl( m_macControl
) ;
627 void wxControl::Refresh(bool eraseBack
, const wxRect
*rect
)
629 wxWindow::Refresh( eraseBack
, rect
) ;
632 void wxControl::MacRedrawControl()
634 if ( m_macControl
&& MacGetRootWindow() )
636 wxClientDC
dc(this) ;
637 wxMacPortSetter
helper(&dc
) ;
639 // the controls sometimes draw outside their boundaries, this
640 // should be resolved differently but is not trivial (e.g. drop shadows)
641 // since adding them to the border would yield in enormous gaps between
643 Rect r
= { 0 , 0 , 32000 , 32000 } ;
645 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
646 UMADrawControl( m_macControl
) ;
650 void wxControl::OnPaint(wxPaintEvent
& event
)
655 wxMacPortSetter
helper(&dc
) ;
656 // the controls sometimes draw outside their boundaries, this
657 // should be resolved differently but is not trivial (e.g. drop shadows)
658 // since adding them to the border would yield in enormous gaps between
660 Rect r
= { 0 , 0 , 32000 , 32000 } ;
663 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
664 UMADrawControl( m_macControl
) ;
671 void wxControl::OnEraseBackground(wxEraseEvent
& event
)
673 wxWindow::OnEraseBackground( event
) ;
677 void wxControl::OnKeyDown( wxKeyEvent
&event
)
679 if ( m_macControl
== NULL
)
682 EventRecord
*ev
= wxTheApp
->MacGetCurrentEvent() ;
685 keychar
= short(ev
->message
& charCodeMask
);
686 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
688 ::HandleControlKey( m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
691 void wxControl::OnMouseEvent( wxMouseEvent
&event
)
693 if ( m_macControl
== NULL
)
699 if (event
.GetEventType() == wxEVT_LEFT_DOWN
|| event
.GetEventType() == wxEVT_LEFT_DCLICK
)
705 MacClientToRootWindow( &x
, &y
) ;
707 ControlHandle control
;
710 WindowRef window
= MacGetRootWindow() ;
717 if ( !event
.m_leftDown
&& !event
.m_rightDown
)
718 modifiers
|= btnState
;
720 if ( event
.m_shiftDown
)
721 modifiers
|= shiftKey
;
723 if ( event
.m_controlDown
)
724 modifiers
|= controlKey
;
726 if ( event
.m_altDown
)
727 modifiers
|= optionKey
;
729 if ( event
.m_metaDown
)
730 modifiers
|= cmdKey
;
733 control = FindControlUnderMouse( localwhere , window , &controlpart ) ;
735 controlpart = FindControl( localwhere , window , &control ) ;
740 if ( AcceptsFocus() && FindFocus() != this )
745 control
= m_macControl
;
746 if ( control
&& ::IsControlActive( control
) )
749 controlpart
= ::HandleControlClick( control
, localwhere
, modifiers
, (ControlActionUPP
) -1 ) ;
750 wxTheApp
->s_lastMouseDown
= 0 ;
751 if ( control
&& controlpart
!= kControlNoPart
&&
752 ! IsKindOf( CLASSINFO( wxScrollBar
) )
753 ) // otherwise we will get the event twice for scrollbar
755 MacHandleControlClick( control
, controlpart
) ;
763 bool wxControl::MacCanFocus() const
765 { if ( m_macControl
== NULL
)
772 void wxControl::MacHandleControlClick( ControlHandle control
, SInt16 controlpart
)
774 wxASSERT_MSG( m_macControl
!= NULL
, "No valid mac control" ) ;