625 lines
18 KiB
Text
625 lines
18 KiB
Text
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Name: spinctld.h
|
||
|
// Author: John Labenski
|
||
|
// Created: 11/05/02
|
||
|
// Copyright: John Labenski, 2002
|
||
|
// License: wxWidgets
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
|
||
|
#pragma implementation "spinctld.h"
|
||
|
#endif
|
||
|
|
||
|
// For compilers that support precompilation, includes "wx/wx.h".
|
||
|
#include "wx/wxprec.h"
|
||
|
|
||
|
#ifdef __BORLANDC__
|
||
|
#pragma hdrstop
|
||
|
#endif
|
||
|
|
||
|
#ifndef WX_PRECOMP
|
||
|
#include "wx/valtext.h" // for wxTextValidator
|
||
|
#include "wx/textctrl.h"
|
||
|
#endif // WX_PRECOMP
|
||
|
|
||
|
#include "wx/things/spinctld.h"
|
||
|
#include <math.h>
|
||
|
|
||
|
#if wxCHECK_VERSION(2,5,0)
|
||
|
#include "wx/math.h"
|
||
|
#else
|
||
|
#if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
|
||
|
#include <float.h>
|
||
|
#define wxFinite(x) _finite(x)
|
||
|
#elif defined(__GNUG__)||defined(__GNUWIN32__)||defined(__DJGPP__)|| \
|
||
|
defined(__SGI_CC__)||defined(__SUNCC__)||defined(__XLC__)|| \
|
||
|
defined(__HPUX__)||defined(__MWERKS__)
|
||
|
#define wxFinite(x) finite(x)
|
||
|
#else
|
||
|
#define wxFinite(x) ((x) == (x))
|
||
|
#endif
|
||
|
#endif // wxCHECK_VERSION(2,5,0)
|
||
|
|
||
|
// NOTES : if the textctrl is focused and the program is ending, a killfocus
|
||
|
// event is sent in MSW, this is why m_textCtrl is set to NULL in it's
|
||
|
// destructor and there's so many checks for it not being NULL
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// wxSpinCtrlDbl
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
// the textctrl used for the wxSpinCtrlDbl, needed for keypresses
|
||
|
class wxSpinCtrlDblTextCtrl : public wxTextCtrl
|
||
|
{
|
||
|
public:
|
||
|
wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id,
|
||
|
const wxString &value = wxEmptyString,
|
||
|
const wxPoint &pos = wxDefaultPosition,
|
||
|
const wxSize &size = wxDefaultSize,
|
||
|
long style = 0,
|
||
|
const wxValidator& validator = wxDefaultValidator,
|
||
|
const wxString &name = wxTextCtrlNameStr);
|
||
|
|
||
|
// MSW sends extra kill focus event
|
||
|
virtual ~wxSpinCtrlDblTextCtrl()
|
||
|
{
|
||
|
if (m_parent) m_parent->m_textCtrl = NULL;
|
||
|
m_parent = NULL;
|
||
|
}
|
||
|
|
||
|
wxSpinCtrlDbl *m_parent;
|
||
|
|
||
|
void OnChar( wxKeyEvent &event ); // pass chars to wxSpinCtrlDbl
|
||
|
void OnKillFocus( wxFocusEvent &event ); // sync the spin to textctrl
|
||
|
|
||
|
private:
|
||
|
DECLARE_EVENT_TABLE()
|
||
|
};
|
||
|
|
||
|
BEGIN_EVENT_TABLE(wxSpinCtrlDblTextCtrl,wxTextCtrl)
|
||
|
// EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextEnter ) // get them from spinctrldbl
|
||
|
// EVT_TEXT( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextUpdate ) // get them from spinctrldbl
|
||
|
EVT_CHAR( wxSpinCtrlDblTextCtrl::OnChar )
|
||
|
EVT_KILL_FOCUS( wxSpinCtrlDblTextCtrl::OnKillFocus )
|
||
|
END_EVENT_TABLE()
|
||
|
|
||
|
wxSpinCtrlDblTextCtrl::wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id,
|
||
|
const wxString &value,
|
||
|
const wxPoint &pos, const wxSize &size,
|
||
|
long style,
|
||
|
const wxValidator& validator,
|
||
|
const wxString &name)
|
||
|
:wxTextCtrl( parent, id, value, pos, size, style,
|
||
|
validator, name)
|
||
|
{
|
||
|
m_parent = (wxSpinCtrlDbl*)parent;
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDblTextCtrl::OnChar( wxKeyEvent &event )
|
||
|
{
|
||
|
if (m_parent) m_parent->OnChar( event );
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDblTextCtrl::OnKillFocus( wxFocusEvent &event )
|
||
|
{
|
||
|
if (m_parent) m_parent->SyncSpinToText(true);
|
||
|
event.Skip();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// wxSpinCtrlDbl
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
IMPLEMENT_DYNAMIC_CLASS( wxSpinCtrlDbl, wxControl )
|
||
|
|
||
|
BEGIN_EVENT_TABLE(wxSpinCtrlDbl,wxControl)
|
||
|
EVT_SPIN_UP ( wxID_ANY, wxSpinCtrlDbl::OnSpinUp )
|
||
|
EVT_SPIN_DOWN ( wxID_ANY, wxSpinCtrlDbl::OnSpinDown )
|
||
|
EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDbl::OnTextEnter )
|
||
|
//EVT_TEXT ( wxID_ANY, wxSpinCtrlDbl::OnText )
|
||
|
EVT_SET_FOCUS ( wxSpinCtrlDbl::OnFocus )
|
||
|
EVT_KILL_FOCUS( wxSpinCtrlDbl::OnKillFocus )
|
||
|
END_EVENT_TABLE()
|
||
|
|
||
|
void wxSpinCtrlDbl::Init()
|
||
|
{
|
||
|
m_min = 0;
|
||
|
m_max = 100;
|
||
|
m_value = 0;
|
||
|
m_default_value = 0;
|
||
|
m_increment = 1;
|
||
|
m_digits = wxSPINCTRLDBL_AUTODIGITS;
|
||
|
m_snap_ticks = false;
|
||
|
m_spinButton = NULL;
|
||
|
m_textCtrl = NULL;
|
||
|
}
|
||
|
|
||
|
bool wxSpinCtrlDbl::Create( wxWindow *parent, wxWindowID id,
|
||
|
const wxString& value,
|
||
|
const wxPoint& pos, const wxSize& size,
|
||
|
long style,
|
||
|
double min, double max,
|
||
|
double initial,
|
||
|
double increment, int digits,
|
||
|
const wxString& name)
|
||
|
{
|
||
|
if (!wxControl::Create(parent, id, pos, size, style|wxNO_BORDER,
|
||
|
wxDefaultValidator, name))
|
||
|
return false;
|
||
|
|
||
|
wxControl::SetLabel(name);
|
||
|
wxControl::SetBackgroundColour(parent->GetBackgroundColour());
|
||
|
wxControl::SetForegroundColour(parent->GetForegroundColour());
|
||
|
|
||
|
int width = size.GetWidth(), height = size.GetHeight();
|
||
|
|
||
|
wxSize best_size( DoGetBestSize() );
|
||
|
if (width == -1) width = best_size.GetWidth();
|
||
|
if (height == -1) height = best_size.GetHeight();
|
||
|
|
||
|
// Create a validator for numbers, +-, and eE for exponential
|
||
|
wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST);
|
||
|
|
||
|
#if wxCHECK_VERSION(2, 5, 4)
|
||
|
wxArrayString list;
|
||
|
|
||
|
wxString valid_chars(wxT(" 0123456789+-.eE"));
|
||
|
size_t len = valid_chars.Length();
|
||
|
for (size_t i=0; i<len; i++)
|
||
|
list.Add(wxString(valid_chars.GetChar(i)));
|
||
|
|
||
|
validator.SetIncludes(list);
|
||
|
#else
|
||
|
wxStringList list;
|
||
|
|
||
|
wxString valid_chars(wxT(" 0123456789+-.eE"));
|
||
|
size_t len = valid_chars.Length();
|
||
|
for (size_t i=0; i<len; i++)
|
||
|
list.Add(wxString(valid_chars.GetChar(i)));
|
||
|
|
||
|
validator.SetIncludeList(list);
|
||
|
#endif // wxCHECK_VER(2, 5, 4)
|
||
|
|
||
|
m_spinButton = new wxSpinButton( this, id, wxPoint(0,0), wxSize(-1, height),
|
||
|
wxSP_ARROW_KEYS|wxSP_VERTICAL|wxSP_WRAP);
|
||
|
m_textCtrl = new wxSpinCtrlDblTextCtrl( this, id, value,
|
||
|
wxPoint(0,0),
|
||
|
wxSize(width-m_spinButton->GetSize().GetWidth(), height),
|
||
|
wxTE_NOHIDESEL|wxTE_PROCESS_ENTER, validator);
|
||
|
|
||
|
DoSetSize( pos.x, pos.y, width, height );
|
||
|
SetBestSize(wxSize(width, height));
|
||
|
|
||
|
m_min = min;
|
||
|
m_max = max;
|
||
|
m_value = initial;
|
||
|
m_default_value = initial;
|
||
|
m_increment = increment;
|
||
|
SetDigits( digits );
|
||
|
|
||
|
// set the value here without generating an event
|
||
|
if (!value.IsEmpty())
|
||
|
m_textCtrl->SetValue(value);
|
||
|
else
|
||
|
m_textCtrl->SetValue(wxString::Format(m_textFormat.c_str(), initial));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
wxSpinCtrlDbl::~wxSpinCtrlDbl()
|
||
|
{
|
||
|
if (m_textCtrl) // null this since MSW sends KILL_FOCUS on deletion
|
||
|
{
|
||
|
m_textCtrl->m_parent = NULL;
|
||
|
|
||
|
wxSpinCtrlDblTextCtrl *text = m_textCtrl;
|
||
|
m_textCtrl = NULL;
|
||
|
delete text;
|
||
|
}
|
||
|
|
||
|
delete m_spinButton;
|
||
|
m_spinButton = NULL;
|
||
|
}
|
||
|
|
||
|
#define wxSPINCTRLDBL_SPIN_WIDTH 15
|
||
|
#define wxSPINCTRLDBL_SPIN_HEIGHT 22
|
||
|
|
||
|
void wxSpinCtrlDbl::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||
|
{
|
||
|
//wxPrintf(wxT("DoSetSize %d, %d %d %d %d %d\n"), GetId(), x, y, width, height, sizeFlags);
|
||
|
|
||
|
wxSize bestSize( DoGetBestSize() );
|
||
|
if (width < 0) width = bestSize.GetWidth();
|
||
|
if (height < 0) height = bestSize.GetHeight();
|
||
|
|
||
|
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||
|
|
||
|
int spinwidth = wxSPINCTRLDBL_SPIN_WIDTH;
|
||
|
int spinheight = wxSPINCTRLDBL_SPIN_HEIGHT;
|
||
|
if (m_spinButton)
|
||
|
m_spinButton->GetSize( &spinwidth, &spinheight );
|
||
|
|
||
|
#ifdef __WIN95__ // humm... these used to be different
|
||
|
if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height );
|
||
|
if (m_spinButton) m_spinButton->SetSize( width-spinwidth-2, 0, -1, height );
|
||
|
//m_textCtrl->SetSize( -3, -3, width - spinwidth, height ); // old wxWin < 2.3.2
|
||
|
//m_spinButton->SetSize( width-spinwidth-4, -3, -1, height-1 );
|
||
|
#else
|
||
|
if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height );
|
||
|
if (m_spinButton) m_spinButton->SetSize( width-spinwidth, 0, -1, height );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static wxSize s_spinctrl_bestSize(-999,-999);
|
||
|
|
||
|
wxSize wxSpinCtrlDbl::DoGetBestSize() const
|
||
|
{
|
||
|
//wxPrintf(wxT("GetBestSize %d\n"), GetId());
|
||
|
if (s_spinctrl_bestSize.x == -999)
|
||
|
{
|
||
|
wxSpinCtrl spin((wxWindow*)this, wxID_ANY);
|
||
|
s_spinctrl_bestSize = spin.GetBestSize();
|
||
|
// oops something went wrong, set to reasonable value
|
||
|
if (s_spinctrl_bestSize.GetWidth() < 20)
|
||
|
s_spinctrl_bestSize.SetWidth(95);
|
||
|
if (s_spinctrl_bestSize.GetHeight() < 10)
|
||
|
s_spinctrl_bestSize.SetHeight(wxSPINCTRLDBL_SPIN_HEIGHT);
|
||
|
}
|
||
|
|
||
|
return s_spinctrl_bestSize;
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::DoSendEvent()
|
||
|
{
|
||
|
wxCommandEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, GetId() );
|
||
|
event.SetEventObject( this );
|
||
|
event.SetInt( (int)(m_value+0.5) );
|
||
|
if (m_textCtrl) event.SetString( m_textCtrl->GetValue() );
|
||
|
GetEventHandler()->ProcessEvent( event );
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnSpinUp( wxSpinEvent &WXUNUSED(event) )
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified() )
|
||
|
SyncSpinToText(false);
|
||
|
|
||
|
if ( InRange(m_value + m_increment) )
|
||
|
{
|
||
|
m_value += m_increment;
|
||
|
SetValue( m_value );
|
||
|
DoSendEvent();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnSpinDown( wxSpinEvent &WXUNUSED(event) )
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified() )
|
||
|
SyncSpinToText(false);
|
||
|
|
||
|
if ( InRange(m_value - m_increment) )
|
||
|
{
|
||
|
m_value -= m_increment;
|
||
|
SetValue( m_value );
|
||
|
DoSendEvent();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnTextEnter( wxCommandEvent &event )
|
||
|
{
|
||
|
SyncSpinToText(true);
|
||
|
event.Skip();
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnText( wxCommandEvent &event )
|
||
|
{
|
||
|
//wxPrintf(wxT("Text '%s'\n"), event.GetString()); fflush(stdout);
|
||
|
event.Skip();
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnChar( wxKeyEvent &event )
|
||
|
{
|
||
|
double modifier = 1.0;
|
||
|
if ( event.m_shiftDown ) modifier = 2.0;
|
||
|
if ( event.m_controlDown ) modifier *= 10.0;
|
||
|
if ( event.m_altDown ) modifier *= 100.0;
|
||
|
|
||
|
switch ( event.GetKeyCode() )
|
||
|
{
|
||
|
case WXK_UP :
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false);
|
||
|
SetValue( m_value + m_increment * modifier );
|
||
|
DoSendEvent();
|
||
|
break;
|
||
|
}
|
||
|
case WXK_DOWN :
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false);
|
||
|
SetValue( m_value - m_increment * modifier );
|
||
|
DoSendEvent();
|
||
|
break;
|
||
|
}
|
||
|
case WXK_PRIOR : // pg-up
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false);
|
||
|
SetValue( m_value + m_increment * 10.0 * modifier );
|
||
|
DoSendEvent();
|
||
|
break;
|
||
|
}
|
||
|
case WXK_NEXT : // pg-down
|
||
|
{
|
||
|
if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false);
|
||
|
SetValue( m_value - m_increment * 10.0 * modifier );
|
||
|
DoSendEvent();
|
||
|
break;
|
||
|
}
|
||
|
case WXK_SPACE :
|
||
|
{
|
||
|
SetValue(m_value);
|
||
|
event.Skip(false);
|
||
|
break;
|
||
|
}
|
||
|
case WXK_ESCAPE :
|
||
|
{
|
||
|
SetDefaultValue();
|
||
|
DoSendEvent();
|
||
|
break;
|
||
|
}
|
||
|
case WXK_TAB :
|
||
|
{
|
||
|
wxNavigationKeyEvent new_event;
|
||
|
new_event.SetEventObject( GetParent() );
|
||
|
new_event.SetDirection( !event.ShiftDown() );
|
||
|
// CTRL-TAB changes the (parent) window, i.e. switch notebook page
|
||
|
new_event.SetWindowChange( event.ControlDown() );
|
||
|
new_event.SetCurrentFocus( this );
|
||
|
GetParent()->GetEventHandler()->ProcessEvent( new_event );
|
||
|
break;
|
||
|
}
|
||
|
default : event.Skip(); break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetValue( double value )
|
||
|
{
|
||
|
if (!m_textCtrl || !InRange(value))
|
||
|
return;
|
||
|
|
||
|
if ( m_snap_ticks && (m_increment != 0) )
|
||
|
{
|
||
|
double snap_value = (value - m_default_value) / m_increment;
|
||
|
|
||
|
if (wxFinite(snap_value)) // FIXME what to do about a failure?
|
||
|
{
|
||
|
if (snap_value - floor(snap_value) < ceil(snap_value) - snap_value)
|
||
|
value = m_default_value + floor(snap_value) * m_increment;
|
||
|
else
|
||
|
value = m_default_value + ceil(snap_value) * m_increment;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wxString str(wxString::Format(m_textFormat.c_str(), value));
|
||
|
|
||
|
if ((value != m_value) || (str != m_textCtrl->GetValue()))
|
||
|
{
|
||
|
m_textCtrl->SetValue( str );
|
||
|
m_textCtrl->DiscardEdits();
|
||
|
m_value = value;
|
||
|
str.ToDouble( &m_value ); // wysiwyg for textctrl
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetValue( const wxString& text, bool force )
|
||
|
{
|
||
|
if (!m_textCtrl) return;
|
||
|
|
||
|
double value;
|
||
|
if ( text.ToDouble(&value) )
|
||
|
SetValue( value );
|
||
|
else if (force)
|
||
|
{
|
||
|
m_textCtrl->SetValue( text );
|
||
|
m_textCtrl->DiscardEdits();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetRange( double min_val, double max_val )
|
||
|
{
|
||
|
//wxCHECK_RET(max_val > min_val, wxT("invalid spinctrl range"));
|
||
|
m_min = min_val;
|
||
|
m_max = max_val;
|
||
|
|
||
|
if (HasRange())
|
||
|
{
|
||
|
if (m_value > m_max)
|
||
|
SetValue(m_max);
|
||
|
else if (m_value < m_min)
|
||
|
SetValue(m_min);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetIncrement( double increment )
|
||
|
{
|
||
|
m_increment = increment;
|
||
|
SetValue(m_value);
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetDigits( int digits, formatType fmt )
|
||
|
{
|
||
|
wxCHECK_RET(digits >= -1, wxT("invalid spinctrl format"));
|
||
|
|
||
|
if ((digits == wxSPINCTRLDBL_AUTODIGITS) && (fmt != lg_fmt))
|
||
|
{
|
||
|
wxString wxstr;
|
||
|
int lastplace = -1, extra_digits = 0;
|
||
|
if (fmt == le_fmt)
|
||
|
{
|
||
|
wxstr.Printf(wxT("%le"), m_increment );
|
||
|
wxstr.LowerCase();
|
||
|
lastplace = wxstr.Find(wxT('e')) - 2;
|
||
|
long places;
|
||
|
if (wxstr.AfterFirst(wxT('e')).ToLong(&places))
|
||
|
extra_digits = int(labs(places));
|
||
|
}
|
||
|
else if (fmt == lf_fmt)
|
||
|
{
|
||
|
wxstr.Printf(wxT("%lf"), m_increment );
|
||
|
lastplace = wxstr.Len()-1;
|
||
|
}
|
||
|
|
||
|
int decimalplace = wxstr.Find(wxT('.'));
|
||
|
|
||
|
int i = 0;
|
||
|
|
||
|
for ( i=lastplace; i>decimalplace; i-- )
|
||
|
{
|
||
|
if ( wxstr.GetChar(i) != wxT('0') )
|
||
|
{
|
||
|
m_digits = extra_digits + i-decimalplace;
|
||
|
switch (fmt)
|
||
|
{
|
||
|
case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break;
|
||
|
case lf_fmt :
|
||
|
default : m_textFormat.Printf(wxT("%%.%dlg"), m_digits ); break;
|
||
|
}
|
||
|
|
||
|
SetValue(m_value);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_digits = 0; // no digits, I guess
|
||
|
}
|
||
|
else
|
||
|
m_digits = digits;
|
||
|
|
||
|
switch (fmt)
|
||
|
{
|
||
|
case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break;
|
||
|
case lg_fmt :
|
||
|
{
|
||
|
if (m_digits == -1)
|
||
|
m_textFormat.Printf(wxT("%%lg") );
|
||
|
else
|
||
|
m_textFormat.Printf(wxT("%%.%dlg"), m_digits );
|
||
|
break;
|
||
|
}
|
||
|
case lf_fmt :
|
||
|
default : m_textFormat.Printf(wxT("%%.%dlf"), m_digits ); break;
|
||
|
}
|
||
|
|
||
|
SetValue(m_value);
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetFormat( const wxString& format )
|
||
|
{
|
||
|
wxString wxstr;
|
||
|
if ( wxstr.Printf(format.c_str(), 123456.123456) > 0 )
|
||
|
m_textFormat = format;
|
||
|
|
||
|
SetValue(m_value);
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetDefaultValue( double default_value )
|
||
|
{
|
||
|
if ( InRange(default_value) )
|
||
|
{
|
||
|
m_default_value = default_value;
|
||
|
SetDefaultValue();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SetSnapToTicks(bool forceTicks)
|
||
|
{
|
||
|
if (m_snap_ticks != forceTicks)
|
||
|
{
|
||
|
m_snap_ticks = forceTicks;
|
||
|
SetValue( m_value );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnFocus( wxFocusEvent &event )
|
||
|
{
|
||
|
if (m_textCtrl)
|
||
|
m_textCtrl->SetFocus(); // this is to pass TAB navigation
|
||
|
|
||
|
event.Skip();
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::OnKillFocus( wxFocusEvent &event )
|
||
|
{
|
||
|
SyncSpinToText(true);
|
||
|
event.Skip();
|
||
|
}
|
||
|
|
||
|
void wxSpinCtrlDbl::SyncSpinToText(bool send_event, bool force_valid)
|
||
|
{
|
||
|
if (!m_textCtrl)
|
||
|
return;
|
||
|
|
||
|
double txt_value;
|
||
|
if ( m_textCtrl->GetValue().ToDouble( &txt_value ) )
|
||
|
{
|
||
|
if ( force_valid || !HasRange() || InRange(txt_value) )
|
||
|
{
|
||
|
if (force_valid && HasRange())
|
||
|
{
|
||
|
if (txt_value > GetMax())
|
||
|
txt_value = GetMax();
|
||
|
else if (txt_value < GetMin())
|
||
|
txt_value = GetMin();
|
||
|
}
|
||
|
|
||
|
if (m_value != txt_value)
|
||
|
{
|
||
|
SetValue( txt_value );
|
||
|
if (send_event) DoSendEvent();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (force_valid)
|
||
|
{
|
||
|
// textctrl is out of sync, discard and reset
|
||
|
SetValue(GetValue());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool wxSpinCtrlDbl::SetFont( const wxFont &font )
|
||
|
{
|
||
|
if (!m_textCtrl) return false;
|
||
|
return m_textCtrl->SetFont( font );
|
||
|
}
|
||
|
wxFont wxSpinCtrlDbl::GetFont() const
|
||
|
{
|
||
|
if (!m_textCtrl) return GetFont();
|
||
|
return m_textCtrl->GetFont();
|
||
|
}
|
||
|
|
||
|
bool wxSpinCtrlDbl::SetBackgroundColour(const wxColour& colour)
|
||
|
{
|
||
|
if (!m_textCtrl) return wxControl::SetBackgroundColour(colour);
|
||
|
bool ret = false;
|
||
|
ret = m_textCtrl->SetBackgroundColour(colour);
|
||
|
m_textCtrl->Refresh(); // FIXME is this necessary in GTK/OSX
|
||
|
return ret;
|
||
|
}
|
||
|
wxColour wxSpinCtrlDbl::GetBackgroundColour() const
|
||
|
{
|
||
|
if (!m_textCtrl) return wxControl::GetBackgroundColour();
|
||
|
return m_textCtrl->GetBackgroundColour();
|
||
|
}
|
||
|
|
||
|
bool wxSpinCtrlDbl::SetForegroundColour(const wxColour& colour)
|
||
|
{
|
||
|
if (!m_textCtrl) return wxControl::SetForegroundColour(colour);
|
||
|
bool ret = false;
|
||
|
ret = m_textCtrl->SetForegroundColour(colour);
|
||
|
m_textCtrl->Refresh();
|
||
|
return ret;
|
||
|
}
|
||
|
wxColour wxSpinCtrlDbl::GetForegroundColour() const
|
||
|
{
|
||
|
if (!m_textCtrl) return wxControl::GetForegroundColour();
|
||
|
return m_textCtrl->GetForegroundColour();
|
||
|
}
|