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/notebook.h"
23 #include "wx/tabctrl.h"
24 #include "wx/radiobox.h"
25 #include "wx/spinbutt.h"
26 #include "wx/scrolbar.h"
27 #include "wx/button.h"
28 #include "wx/dialog.h"
29 #include "wx/statbox.h"
31 #include "wx/stattext.h"
33 #if !USE_SHARED_LIBRARY
34 IMPLEMENT_ABSTRACT_CLASS(wxControl
, wxWindow
)
36 BEGIN_EVENT_TABLE(wxControl
, wxWindow
)
37 EVT_MOUSE_EVENTS( wxControl::OnMouseEvent
)
38 EVT_CHAR( wxControl::OnKeyDown
)
39 EVT_PAINT( wxControl::OnPaint
)
43 #include "wx/mac/uma.h"
47 ControlActionUPP wxMacLiveScrollbarActionUPP
= NULL
;
49 pascal void wxMacLiveScrollbarActionProc( ControlHandle control
, ControlPartCode partCode
) ;
50 pascal void wxMacLiveScrollbarActionProc( ControlHandle control
, ControlPartCode partCode
)
54 wxControl
* wx
= (wxControl
*) GetControlReference( control
) ;
57 wx
->MacHandleControlClick( control
, partCode
) ;
62 wxControl::wxControl()
65 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
66 m_macVerticalBorder
= 0 ;
67 m_backgroundColour
= *wxWHITE
;
68 m_foregroundColour
= *wxBLACK
;
69 #if WXWIN_COMPATIBILITY
71 #endif // WXWIN_COMPATIBILITY
73 if ( wxMacLiveScrollbarActionUPP
== NULL
)
75 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
76 wxMacLiveScrollbarActionUPP
= NewControlActionUPP( wxMacLiveScrollbarActionProc
);
78 wxMacLiveScrollbarActionUPP
= NewControlActionProc( wxMacLiveScrollbarActionProc
) ;
83 bool wxControl::Create(wxWindow
*parent
, wxWindowID id
,
85 const wxSize
& size
, long style
,
86 const wxValidator
& validator
,
90 m_macHorizontalBorder
= 0 ; // additional pixels around the real control
91 m_macVerticalBorder
= 0 ;
92 bool rval
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
95 SetValidator(validator
);
101 wxControl::~wxControl()
103 m_isBeingDeleted
= TRUE
;
104 // If we delete an item, we should initialize the parent panel,
105 // because it could now be invalid.
106 wxPanel
*panel
= wxDynamicCast(GetParent(), wxPanel
);
109 if (panel
->GetDefaultItem() == (wxButton
*) this)
110 panel
->SetDefaultItem(NULL
);
114 ::DisposeControl( m_macControl
) ;
115 m_macControl
= NULL
;
119 void wxControl::SetLabel(const wxString
& title
)
128 if( wxApp::s_macDefaultEncodingIsPC
)
129 label
= wxMacMakeMacStringFromPC( title
) ;
134 c2pstrcpy( (StringPtr
) maclabel
, label
) ;
136 strcpy( (char *) maclabel
, label
) ;
137 c2pstr( (char *) maclabel
) ;
139 ::SetControlTitle( m_macControl
, maclabel
) ;
144 wxSize
wxControl::DoGetBestSize() const
146 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
147 short baselineoffset
;
148 int bestWidth
, bestHeight
;
149 ::GetBestControlRect( m_macControl
, &bestsize
, &baselineoffset
) ;
151 if ( EmptyRect( &bestsize
) )
154 bestsize
.left
= bestsize
.top
= 0 ;
155 bestsize
.right
= 16 ;
156 bestsize
.bottom
= 16 ;
157 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
159 bestsize
.bottom
= 16 ;
161 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
163 bestsize
.bottom
= 24 ;
167 if ( IsKindOf( CLASSINFO( wxButton
) ) )
169 bestWidth
= m_label
.Length() * 8 + 12 ;
170 if ( bestWidth
< 70 )
173 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
175 bestWidth
= m_label
.Length() * 8 ;
178 bestWidth
= bestsize
.right
- bestsize
.left
;
180 bestWidth
+= 2 * m_macHorizontalBorder
;
182 bestHeight
= bestsize
.bottom
- bestsize
.top
;
183 if ( bestHeight
< 10 )
186 bestHeight
+= 2 * m_macVerticalBorder
;
189 return wxSize(bestWidth
, bestHeight
);
192 bool wxControl::ProcessCommand (wxCommandEvent
& event
)
195 // 1) A callback function (to become obsolete)
196 // 2) OnCommand, starting at this window and working up parent hierarchy
197 // 3) OnCommand then calls ProcessEvent to search the event tables.
198 #if WXWIN_COMPATIBILITY
201 (void)(*m_callback
)(this, event
);
206 #endif // WXWIN_COMPATIBILITY
208 return GetEventHandler()->ProcessEvent(event
);
212 // ------------------------
213 wxList
*wxWinMacControlList
= NULL
;
214 wxControl
*wxFindControlFromMacControl(ControlHandle inControl
)
216 wxNode
*node
= wxWinMacControlList
->Find((long)inControl
);
219 return (wxControl
*)node
->Data();
222 void wxAssociateControlWithMacControl(ControlHandle inControl
, wxControl
*control
)
224 // adding NULL WindowRef is (first) surely a result of an error and
225 // (secondly) breaks menu command processing
226 wxCHECK_RET( inControl
!= (ControlHandle
) NULL
, "attempt to add a NULL WindowRef to window list" );
228 if ( !wxWinMacControlList
->Find((long)inControl
) )
229 wxWinMacControlList
->Append((long)inControl
, control
);
232 void wxRemoveMacControlAssociation(wxControl
*control
)
234 wxWinMacControlList
->DeleteObject(control
);
237 void wxControl::MacPreControlCreate( wxWindow
*parent
, wxWindowID id
, wxString label
,
239 const wxSize
& size
, long style
,
240 const wxValidator
& validator
,
241 const wxString
& name
, Rect
*outBounds
, StringPtr maclabel
)
246 SetValidator(validator
);
248 m_windowStyle
= style
;
249 parent
->AddChild(this);
251 m_backgroundColour
= parent
->GetBackgroundColour() ;
252 m_foregroundColour
= parent
->GetForegroundColour() ;
255 m_windowId
= NewControlId();
259 // These sizes will be adjusted in MacPostControlCreate
266 outBounds
->top
= -10;
267 outBounds
->left
= -10;
268 outBounds
->bottom
= 0;
269 outBounds
->right
= 0;
272 strcpy( c_text
, label
) ;
273 if( wxApp::s_macDefaultEncodingIsPC
)
275 wxMacConvertFromPCForControls( c_text
) ;
279 c2pstrcpy( (StringPtr
) maclabel
, c_text
) ;
281 strcpy( (char *) maclabel
, c_text
) ;
282 c2pstr( (char *) maclabel
) ;
286 void wxControl::MacPostControlCreate()
288 wxASSERT_MSG( m_macControl
!= NULL
, "No valid mac control" ) ;
290 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
294 else if ( IsKindOf( CLASSINFO( wxStaticBox
) ) || IsKindOf( CLASSINFO( wxRadioBox
) ) || IsKindOf( CLASSINFO( wxButton
) ) )
296 ControlFontStyleRec controlstyle
;
297 controlstyle
.flags
= kControlUseFontMask
;
298 controlstyle
.font
= kControlFontSmallBoldSystemFont
;
300 ::SetControlFontStyle( m_macControl
, &controlstyle
) ;
304 ControlFontStyleRec controlstyle
;
305 controlstyle
.flags
= kControlUseFontMask
;
306 controlstyle
.font
= kControlFontSmallSystemFont
;
308 ::SetControlFontStyle( m_macControl
, &controlstyle
) ;
310 ControlHandle container
= GetParent()->MacGetContainerForEmbedding() ;
311 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
312 ::EmbedControl( m_macControl
, container
) ;
313 m_macControlIsShown
= true ;
315 wxAssociateControlWithMacControl( m_macControl
, this ) ;
318 // Adjust the controls size and position
319 wxPoint
pos(m_x
, m_y
);
320 wxSize
best_size( DoGetBestSize() );
321 wxSize
new_size( m_width
, m_height
);
323 m_x
= m_y
= m_width
= m_height
= -1; // Forces SetSize to move/size the control
325 if (new_size
.x
== -1) {
326 new_size
.x
= best_size
.x
;
328 if (new_size
.y
== -1) {
329 new_size
.y
= best_size
.y
;
332 SetSize(pos
.x
, pos
.y
, new_size
.x
, new_size
.y
);
334 UMAShowControl( m_macControl
) ;
337 void wxControl::MacAdjustControlRect()
339 wxASSERT_MSG( m_macControl
!= NULL
, wxT("No valid mac control") ) ;
340 if ( m_width
== -1 || m_height
== -1 )
342 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
343 short baselineoffset
;
345 ::GetBestControlRect( m_macControl
, &bestsize
, &baselineoffset
) ;
347 if ( EmptyRect( &bestsize
) )
350 bestsize
.left
= bestsize
.top
= 0 ;
351 bestsize
.right
= 16 ;
352 bestsize
.bottom
= 16 ;
353 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
355 bestsize
.bottom
= 16 ;
357 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
359 bestsize
.bottom
= 24 ;
365 if ( IsKindOf( CLASSINFO( wxButton
) ) )
367 m_width
= m_label
.Length() * 8 + 12 ;
371 else if ( IsKindOf( CLASSINFO( wxStaticText
) ) )
373 m_width
= m_label
.Length() * 8 ;
376 m_width
= bestsize
.right
- bestsize
.left
;
378 m_width
+= 2 * m_macHorizontalBorder
;
380 if ( m_height
== -1 )
382 m_height
= bestsize
.bottom
- bestsize
.top
;
386 m_height
+= 2 * m_macVerticalBorder
;
389 wxMacDrawingHelper
helper ( wxFindWinFromMacWindow( GetMacRootWindow() ) ) ;
392 UMASizeControl( m_macControl
, m_width
- 2 * m_macHorizontalBorder
, m_height
- 2 * m_macVerticalBorder
) ;
396 ControlHandle
wxControl::MacGetContainerForEmbedding()
399 return m_macControl
;
401 return wxWindow::MacGetContainerForEmbedding() ;
404 void wxControl::MacSuperChangedPosition()
409 GetControlBounds( m_macControl
, &contrlRect
) ;
410 int former_mac_x
= contrlRect
.left
;
411 int former_mac_y
= contrlRect
.top
;
414 GetParent()->MacClientToRootWindow( & mac_x
, & mac_y
) ;
416 WindowRef rootwindow
= GetMacRootWindow() ;
417 wxWindow
* wxrootwindow
= wxFindWinFromMacWindow( rootwindow
) ;
418 ::SetThemeWindowBackground( rootwindow
, kThemeBrushDialogBackgroundActive
, false ) ;
419 wxMacDrawingHelper
focus( wxrootwindow
) ;
421 if ( mac_x
!= former_mac_x
|| mac_y
!= former_mac_y
)
424 Rect inval
= { former_mac_y
, former_mac_x
, former_mac_y
+ m_height
, former_mac_x
+ m_width
} ;
425 InvalWindowRect( rootwindow
, &inval
) ;
427 UMAMoveControl( m_macControl
, mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
) ;
429 Rect inval
= { mac_y
, mac_x
, mac_y
+ m_height
, mac_x
+ m_width
} ;
430 InvalWindowRect( rootwindow
, &inval
) ;
433 if ( wxrootwindow
->IsKindOf( CLASSINFO( wxDialog
) ) )
438 ::SetThemeWindowBackground( rootwindow
, kThemeBrushDocumentWindowBackground
, false ) ;
442 wxWindow::MacSuperChangedPosition() ;
445 void wxControl::MacSuperEnabled( bool enabled
)
450 if ( UMAHasAppearance() )
454 ::DeactivateControl( m_macControl ) ;
459 ::ActivateControl( m_macControl ) ;
466 ::HiliteControl( m_macControl , 255 ) ;
471 ::HiliteControl( m_macControl , 0 ) ;
475 wxWindow::MacSuperEnabled( enabled ) ;
479 void wxControl::MacSuperShown( bool show
)
485 if ( m_macControlIsShown
)
487 ::HideControl( m_macControl
) ;
488 m_macControlIsShown
= false ;
493 if ( MacIsReallyShown() && !m_macControlIsShown
)
495 ::UMAShowControl( m_macControl
) ;
496 m_macControlIsShown
= true ;
501 wxWindow::MacSuperShown( show
) ;
504 void wxControl::DoSetSize(int x
, int y
,
505 int width
, int height
,
508 if ( m_macControl
== NULL
)
510 wxWindow::DoSetSize( x
, y
,width
, height
,sizeFlags
) ;
514 Rect oldbounds
, newbounds
;
515 int new_x
, new_y
, new_width
, new_height
;
521 new_height
= m_height
;
523 if (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
)
532 if (x
!= -1) new_x
= x
;
533 if (y
!= -1) new_y
= y
;
534 if (width
!= -1) new_width
= width
;
535 if (height
!= -1) new_height
= height
;
538 if(sizeFlags
& wxSIZE_AUTO
)
540 wxSize size
= GetBestSize();
541 if (sizeFlags
& wxSIZE_AUTO_WIDTH
)
543 if (width
== -1) new_width
= size
.x
;
545 if (sizeFlags
& wxSIZE_AUTO_HEIGHT
)
547 if (height
== -1) new_height
= size
.y
;
550 AdjustForParentClientOrigin(new_x
, new_y
, sizeFlags
);
555 GetParent()->MacClientToRootWindow(&mac_x
, &mac_y
);
557 GetControlBounds(m_macControl
, &oldbounds
);
558 oldbounds
.right
= oldbounds
.left
+ m_width
;
559 oldbounds
.bottom
= oldbounds
.top
+ m_height
;
562 bool doResize
= false;
564 if ( mac_x
!= (oldbounds
.left
- m_macHorizontalBorder
) ||
565 mac_y
!= (oldbounds
.top
- m_macVerticalBorder
) )
569 if ( new_width
!= oldbounds
.right
- oldbounds
.left
- 2 * m_macHorizontalBorder
||
570 new_height
!= oldbounds
.bottom
- oldbounds
.top
- 2 * m_macVerticalBorder
)
575 if ( doMove
|| doResize
)
577 // Ensure resize is within constraints
578 if ((m_minWidth
!= -1) && (new_width
< m_minWidth
)) {
579 new_width
= m_minWidth
;
581 if ((m_minHeight
!= -1) && (new_height
< m_minHeight
)) {
582 new_height
= m_minHeight
;
584 if ((m_maxWidth
!= -1) && (new_width
> m_maxWidth
)) {
585 new_width
= m_maxWidth
;
587 if ((m_maxHeight
!= -1) && (new_height
> m_maxHeight
)) {
588 new_height
= m_maxHeight
;
596 UMAMoveControl(m_macControl
,
597 mac_x
+ m_macHorizontalBorder
, mac_y
+ m_macVerticalBorder
);
599 wxMoveEvent
event(wxPoint(m_x
, m_y
), m_windowId
);
600 event
.SetEventObject(this);
601 GetEventHandler()->ProcessEvent(event
) ;
606 m_height
= new_height
;
608 UMASizeControl( m_macControl
,
609 m_width
- 2 * m_macHorizontalBorder
,
610 m_height
- 2 * m_macVerticalBorder
) ;
612 wxSizeEvent
event(wxSize(m_width
, m_height
), m_windowId
);
613 event
.SetEventObject(this);
614 GetEventHandler()->ProcessEvent(event
);
618 WindowRef rootwindow
= GetMacRootWindow() ;
619 wxWindow
* wxrootwindow
= wxFindWinFromMacWindow( rootwindow
) ;
620 wxMacDrawingHelper
focus( wxrootwindow
);
622 ::SetThemeWindowBackground( rootwindow
, kThemeBrushDialogBackgroundActive
, false ) ;
623 // Update window at old and new positions
624 SetRect(&newbounds
, m_x
, m_y
, m_x
+ m_width
, m_y
+ m_height
);
625 InvalWindowRect( rootwindow
, &oldbounds
);
626 InvalWindowRect( rootwindow
, &newbounds
);
628 MacRepositionScrollBars() ;
630 if ( !wxrootwindow
->IsKindOf( CLASSINFO( wxDialog
) ) )
632 ::SetThemeWindowBackground( rootwindow
, kThemeBrushDocumentWindowBackground
, false );
637 bool wxControl::Show(bool show
)
639 if ( !wxWindow::Show( show
) )
646 if ( m_macControlIsShown
)
648 ::HideControl( m_macControl
) ;
649 m_macControlIsShown
= false ;
654 if ( MacIsReallyShown() && !m_macControlIsShown
)
656 ::UMAShowControl( m_macControl
) ;
657 m_macControlIsShown
= true ;
664 bool wxControl::Enable(bool enable
)
666 if ( !wxWindow::Enable(enable
) )
672 UMAActivateControl( m_macControl
) ;
674 UMADeactivateControl( m_macControl
) ;
679 void wxControl::Refresh(bool eraseBack
, const wxRect
*rect
)
683 wxWindow::Refresh( eraseBack
, rect
) ;
687 wxWindow::Refresh( eraseBack
, rect
) ;
691 void wxControl::MacRedrawControl()
695 WindowRef window
= GetMacRootWindow() ;
698 wxWindow
* win
= wxFindWinFromMacWindow( window
) ;
701 wxMacDrawingHelper
help( win
) ;
702 // the mac control manager always assumes to have the origin at 0,0
705 wxWindow
* parent
= GetParent() ;
708 if( parent
->MacGetWindowData() )
710 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow
, kThemeBrushDialogBackgroundActive
, false ) ;
714 if( parent
->IsKindOf( CLASSINFO( wxNotebook
) ) || parent
->IsKindOf( CLASSINFO( wxTabCtrl
) ))
716 if ( ((wxControl
*)parent
)->m_macControl
)
717 SetUpControlBackground( ((wxControl
*)parent
)->m_macControl
, -1 , true ) ;
721 parent
= parent
->GetParent() ;
724 UMADrawControl( m_macControl
) ;
725 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow
, win
->MacGetWindowData()->m_macWindowBackgroundTheme
, false ) ;
731 void wxControl::OnPaint(wxPaintEvent
& event
)
735 WindowRef window
= GetMacRootWindow() ;
738 wxWindow
* win
= wxFindWinFromMacWindow( window
) ;
741 wxMacDrawingHelper
help( win
) ;
742 // the mac control manager always assumes to have the origin at 0,0
745 wxWindow
* parent
= GetParent() ;
748 if( parent
->MacGetWindowData() )
750 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow
, kThemeBrushDialogBackgroundActive
, false ) ;
754 if( parent
->IsKindOf( CLASSINFO( wxNotebook
) ) || parent
->IsKindOf( CLASSINFO( wxTabCtrl
) ))
756 if ( ((wxControl
*)parent
)->m_macControl
)
757 SetUpControlBackground( ((wxControl
*)parent
)->m_macControl
, -1 , true ) ;
761 parent
= parent
->GetParent() ;
764 UMADrawControl( m_macControl
) ;
765 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow
, win
->MacGetWindowData()->m_macWindowBackgroundTheme
, false ) ;
771 // wxWindow::OnPaint( event ) ;
774 void wxControl::OnEraseBackground(wxEraseEvent
& event
)
776 // In general, you don't want to erase the background of a control,
777 // or you'll get a flicker.
778 // TODO: move this 'null' function into each control that
783 void wxControl::OnKeyDown( wxKeyEvent
&event
)
785 if ( m_macControl
== NULL
)
788 EventRecord
*ev
= wxTheApp
->MacGetCurrentEvent() ;
791 keychar
= short(ev
->message
& charCodeMask
);
792 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
794 ::HandleControlKey( m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
797 void wxControl::OnMouseEvent( wxMouseEvent
&event
)
799 if ( m_macControl
== NULL
)
805 if (event
.GetEventType() == wxEVT_LEFT_DOWN
|| event
.GetEventType() == wxEVT_LEFT_DCLICK
)
811 MacClientToRootWindow( &x
, &y
) ;
813 ControlHandle control
;
816 WindowRef window
= GetMacRootWindow() ;
823 if ( !event
.m_leftDown
&& !event
.m_rightDown
)
824 modifiers
|= btnState
;
826 if ( event
.m_shiftDown
)
827 modifiers
|= shiftKey
;
829 if ( event
.m_controlDown
)
830 modifiers
|= controlKey
;
832 if ( event
.m_altDown
)
833 modifiers
|= optionKey
;
835 if ( event
.m_metaDown
)
836 modifiers
|= cmdKey
;
839 control
= FindControlUnderMouse( localwhere
, window
, &controlpart
) ;
841 // control = FindControlUnderMouse( localwhere , window , &controlpart ) ;
842 controlpart
= FindControl( localwhere
, window
, &control
) ;
846 if ( AcceptsFocus() && FindFocus() != this )
851 if ( control
&& ::IsControlActive( control
) )
854 if ( controlpart
== kControlIndicatorPart
&& !UMAHasAppearance() )
855 controlpart
= ::HandleControlClick( control
, localwhere
, modifiers
, (ControlActionUPP
) NULL
) ;
857 controlpart
= ::HandleControlClick( control
, localwhere
, modifiers
, (ControlActionUPP
) -1 ) ;
858 wxTheApp
->s_lastMouseDown
= 0 ;
859 if ( control
&& ! ( ( UMAHasAppearance() || (controlpart
!= kControlIndicatorPart
) )
860 && (IsKindOf( CLASSINFO( wxScrollBar
) ) ) ) ) // otherwise we will get the event twice
862 MacHandleControlClick( control
, controlpart
) ;
870 bool wxControl::MacCanFocus() const
872 { if ( m_macControl
== NULL
)
879 void wxControl::MacHandleControlClick( ControlHandle control
, SInt16 controlpart
)
881 wxASSERT_MSG( m_macControl
!= NULL
, "No valid mac control" ) ;