]>
git.saurik.com Git - wxWidgets.git/blob - src/motif/spinbutt.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/motif/spinbutt.cpp 
   3 // Purpose:     wxSpinButton 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/spinbutt.h" 
  23 #include "wx/spinctrl.h" 
  26 #pragma message disable nosimpint 
  28 #include <Xm/ArrowBG.h> 
  29 #include <Xm/ArrowB.h> 
  31 #pragma message enable nosimpint 
  34 #include "wx/motif/private.h" 
  45 class wxArrowButtonTimer
; 
  48 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 static const unsigned int TICK_BEFORE_START 
= 10; 
  53 static const unsigned int TICK_BEFORE_EXPONENTIAL 
= 40; 
  54 static const unsigned int MAX_INCREMENT 
= 150; 
  55 static const unsigned int TICK_INTERVAL 
= 113; 
  57 class wxArrowButtonTimer 
: public wxTimer
 
  60     wxArrowButtonTimer( wxArrowButton
* btn
, int sign 
) 
  66     void Reset() { m_ticks 
= 0; m_increment 
= 1; } 
  69     unsigned int m_increment
; 
  71     wxArrowButton
* m_button
; 
  74 // ---------------------------------------------------------------------------- 
  76 // ---------------------------------------------------------------------------- 
  78 class wxArrowButton 
: public wxControl
 
  80     friend class wxArrowButtonTimer
; 
  82     wxArrowButton( int increment 
) 
  83         : m_increment( increment 
), 
  86     wxArrowButton( wxSpinButton
* parent
, wxWindowID id
, ArrowDirection d
, 
  87                    const wxPoint
& pos 
= wxDefaultPosition
, 
  88                    const wxSize
& size 
= wxDefaultSize
, int increment 
= 1 ) 
  90           m_increment( increment 
), 
  93         Create( parent
, id
, d
, pos
, size 
); 
  96     virtual ~wxArrowButton() 
  99     bool Create( wxSpinButton
* parent
, wxWindowID id
, ArrowDirection d
, 
 100                  const wxPoint
& pos 
= wxDefaultPosition
, 
 101                  const wxSize
& size 
= wxDefaultSize 
); 
 103     // creates a new timer object, or stops the currently running one 
 104     wxTimer
* GetFreshTimer(); 
 105     wxSpinButton
* GetSpinButton() { return (wxSpinButton
*)GetParent(); } 
 106     static void SpinButtonCallback( Widget w
, XtPointer clientData
, 
 107                                     XtPointer 
WXUNUSED(ptr
) ); 
 108     static void StartTimerCallback( Widget w
, XtPointer clientData
, 
 109                                     XtPointer 
WXUNUSED(ptr
) ); 
 111     static void  StopTimerCallback( Widget w
, XtPointer clientData
, 
 112                                     XtPointer 
WXUNUSED(ptr
) ); 
 115     wxArrowButtonTimer
* m_timer
; 
 118 // ---------------------------------------------------------------------------- 
 119 // wxArrowButtonTimer implementation 
 120 // ---------------------------------------------------------------------------- 
 122 void wxArrowButtonTimer::Notify() 
 125     if( m_ticks 
< TICK_BEFORE_START 
) return; 
 126     // increment every other tick 
 127     if( m_ticks 
<= TICK_BEFORE_EXPONENTIAL 
&& m_ticks 
& 1 ) 
 129     if( m_ticks 
> TICK_BEFORE_EXPONENTIAL 
) 
 130         m_increment 
= 2 * m_increment
; 
 131     if( m_increment 
>= MAX_INCREMENT 
) m_increment 
= MAX_INCREMENT
; 
 132     m_button
->GetSpinButton()->Increment( m_sign 
* m_increment 
); 
 135 // ---------------------------------------------------------------------------- 
 136 // wxArrowButton implementation 
 137 // ---------------------------------------------------------------------------- 
 139 wxTimer
* wxArrowButton::GetFreshTimer() 
 147         m_timer 
= new wxArrowButtonTimer( this, m_increment 
); 
 152 void wxArrowButton::SpinButtonCallback( Widget w
, XtPointer clientData
, 
 153                                         XtPointer 
WXUNUSED(ptr
) ) 
 155     if( !wxGetWindowFromTable( w 
) ) 
 156         // Widget has been deleted! 
 159     wxArrowButton
* btn 
= (wxArrowButton
*)clientData
; 
 161     btn
->GetSpinButton()->Increment( btn
->m_increment 
); 
 164 void wxArrowButton::StartTimerCallback( Widget w
, XtPointer clientData
, 
 165                                         XtPointer 
WXUNUSED(ptr
) ) 
 167     if( !wxGetWindowFromTable( w 
) ) 
 168         // Widget has been deleted! 
 171     wxArrowButton
* btn 
= (wxArrowButton
*)clientData
; 
 172     btn
->GetFreshTimer()->Start( TICK_INTERVAL 
); 
 175 void wxArrowButton::StopTimerCallback( Widget w
, XtPointer clientData
, 
 176                                        XtPointer 
WXUNUSED(ptr
) ) 
 178     if( !wxGetWindowFromTable( w 
) ) 
 179         // Widget has been deleted! 
 182     wxArrowButton
* btn 
= (wxArrowButton
*)clientData
; 
 187 bool wxArrowButton::Create( wxSpinButton
* parent
, 
 188                             wxWindowID 
WXUNUSED(id
), 
 190                             const wxPoint
& pos
, const wxSize
& size 
) 
 192     wxCHECK_MSG( parent
, false, _T("must have a valid parent") ); 
 194     int arrow_dir 
= XmARROW_UP
; 
 199         arrow_dir 
= XmARROW_UP
; 
 202         arrow_dir 
= XmARROW_DOWN
; 
 205         arrow_dir 
= XmARROW_LEFT
; 
 208         arrow_dir 
= XmARROW_RIGHT
; 
 212     parent
->AddChild( this ); 
 215     Widget parentWidget 
= (Widget
) parent
->GetClientWidget(); 
 216     m_mainWidget 
= (WXWidget
) XtVaCreateManagedWidget( "XmArrowButton", 
 217         xmArrowButtonWidgetClass
, 
 219         XmNarrowDirection
, arrow_dir
, 
 221         XmNshadowThickness
, 0, 
 224     XtAddCallback( (Widget
) m_mainWidget
, 
 225                    XmNactivateCallback
, (XtCallbackProc
) SpinButtonCallback
, 
 227     XtAddCallback( (Widget
) m_mainWidget
, 
 228                    XmNarmCallback
, (XtCallbackProc
) StartTimerCallback
, 
 230     XtAddCallback( (Widget
) m_mainWidget
, 
 231                    XmNactivateCallback
, (XtCallbackProc
) StopTimerCallback
, 
 235     AttachWidget( parent
, m_mainWidget
, (WXWidget
) NULL
, 
 236                   pos
.x
, pos
.y
, size
.x
, size
.y 
); 
 241 // ---------------------------------------------------------------------------- 
 243 // ---------------------------------------------------------------------------- 
 245 IMPLEMENT_DYNAMIC_CLASS(wxSpinButton
, wxControl
) 
 246 IMPLEMENT_DYNAMIC_CLASS(wxSpinEvent
, wxNotifyEvent
) 
 248 static void CalcSizes( const wxPoint
& pt
, const wxSize
& sz
, 
 249                        wxPoint
& pt1
, wxSize
& sz1
, 
 250                        wxPoint
& pt2
, wxSize
& sz2
, 
 253     typedef int wxSize::* CDPTR1
; 
 254     typedef int wxPoint::* CDPTR2
; 
 259     CDPTR1 szm 
= isVertical 
? &wxSize::y 
: &wxSize::x
; 
 260     CDPTR2 ptm 
= isVertical 
? &wxPoint::y 
: &wxPoint::x
; 
 261     int dim 
= sz
.*szm
, half 
= dim
/2; 
 264     sz2
.*szm 
= dim 
- half
; 
 265     pt2
.*ptm 
+= half 
+ 1; 
 268 bool wxSpinButton::Create( wxWindow 
*parent
, wxWindowID id
, 
 269                            const wxPoint
& pos
, const wxSize
& size
, 
 270                            long style
, const wxString
& name 
) 
 272     m_windowStyle 
= style
; 
 274     wxSize newSize 
= GetBestSize(); 
 275     if( size
.x 
!= -1 ) newSize
.x 
= size
.x
; 
 276     if( size
.y 
!= -1 ) newSize
.y 
= size
.y
; 
 278     if( !wxControl::Create( parent
, id
, pos
, newSize
, style 
) ) 
 285     m_windowId 
= ( id 
== wxID_ANY 
) ? NewControlId() : id
; 
 287     bool isVert 
= IsVertical(); 
 290     CalcSizes( wxPoint(0,0), newSize
, pt1
, sz1
, pt2
, sz2
, isVert 
); 
 291     m_up 
= new wxArrowButton( this, -1, isVert 
? wxARROW_UP 
: wxARROW_RIGHT
, 
 293     m_down 
= new wxArrowButton( this, -1, 
 294                                 isVert 
? wxARROW_DOWN 
: wxARROW_LEFT
, 
 300 wxSpinButton::~wxSpinButton() 
 304 void wxSpinButton::DoMoveWindow(int x
, int y
, int width
, int height
) 
 306     wxControl::DoMoveWindow( x
, y
, width
, height 
); 
 311     CalcSizes( wxPoint(0,0), wxSize(width
,height
), pt1
, 
 312                sz1
, pt2
, sz2
, IsVertical() ); 
 313     m_up
->SetSize( pt1
.x
, pt1
.y
, sz1
.x
, sz1
.y 
); 
 314     m_down
->SetSize( pt2
.x
, pt2
.y
, sz2
.x
, sz2
.y 
); 
 317 void wxSpinButton::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 319     if ( (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) && width 
== -1 ) 
 321     if ( (sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) && height 
== -1 ) 
 322         height 
= GetSize().y
; 
 324     wxControl::DoSetSize(x
, y
, width
, height
, 0); 
 327 void wxSpinButton::Increment( int delta 
) 
 329     if( m_pos 
< m_min 
) m_pos 
= m_min
; 
 330     if( m_pos 
> m_max 
) m_pos 
= m_max
; 
 332     int npos 
= m_pos 
+ delta
; 
 336         if( GetWindowStyle() & wxSP_WRAP 
) 
 343         if( GetWindowStyle() & wxSP_WRAP 
) 
 348     if( npos 
== m_pos 
) return; 
 350     wxSpinEvent 
event( delta 
> 0 ? wxEVT_SCROLL_LINEUP 
: wxEVT_SCROLL_LINEDOWN
, 
 352     event
.SetPosition( npos 
); 
 353     event
.SetEventObject( this ); 
 355     HandleWindowEvent( event 
); 
 357     if( event
.IsAllowed() ) 
 360         event
.SetEventType( wxEVT_SCROLL_THUMBTRACK 
); 
 361         event
.SetPosition( m_pos 
); 
 363         HandleWindowEvent( event 
); 
 367 wxSize 
wxSpinButton::DoGetBestSize() const 
 369     return IsVertical() ? wxSize( 20, 30 ) : wxSize( 30, 20 ); 
 373 //////////////////////////////////////////////////////////////////////////// 
 375 int wxSpinButton::GetValue() const 
 380 void wxSpinButton::SetValue(int val
) 
 385 void wxSpinButton::SetRange(int minVal
, int maxVal
) 
 387     wxSpinButtonBase::SetRange(minVal
, maxVal
); 
 390 void wxSpinButton::ChangeFont(bool WXUNUSED(keepOriginalSize
)) 
 395 void wxSpinButton::ChangeBackgroundColour() 
 397     wxControl::ChangeBackgroundColour(); 
 400 void wxSpinButton::ChangeForegroundColour() 
 405 #endif // wxUSE_SPINBTN