#if wxUSE_SPINBTN
+#ifdef __WXMSW__
+ #define IS_MOTION_SPIN_SUPPORTED 1
+#else
+ #define IS_MOTION_SPIN_SUPPORTED 0
+#endif
+
+#if IS_MOTION_SPIN_SUPPORTED
+
+//
+// This class implements ability to rapidly change "spin" value
+// by moving mouse when one of the spin buttons is depressed.
+class wxPGSpinButton : public wxSpinButton
+{
+public:
+ wxPGSpinButton() : wxSpinButton()
+ {
+ m_bLeftDown = false;
+ m_hasCapture = false;
+ m_spins = 1;
+
+ Connect( wxEVT_LEFT_DOWN,
+ wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
+ Connect( wxEVT_LEFT_UP,
+ wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
+ Connect( wxEVT_MOTION,
+ wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) );
+ Connect( wxEVT_MOUSE_CAPTURE_LOST,
+ wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost) );
+ }
+
+ int GetSpins() const
+ {
+ return m_spins;
+ }
+
+private:
+ wxPoint m_ptPosition;
+
+ // Having a separate spins variable allows us to handle validation etc. for
+ // multiple spin events at once (with quick mouse movements there could be
+ // hundreds of 'spins' being done at once). Technically things like this
+ // should be stored in event (wxSpinEvent in this case), but there probably
+ // isn't anything there that can be reliably reused.
+ int m_spins;
+
+ bool m_bLeftDown;
+
+ // SpinButton seems to be a special for mouse capture, so we may need track
+ // privately whether mouse is actually captured.
+ bool m_hasCapture;
+
+ void Capture()
+ {
+ if ( !m_hasCapture )
+ {
+ CaptureMouse();
+ m_hasCapture = true;
+ }
+
+ SetCursor(wxCURSOR_SIZENS);
+ }
+ void Release()
+ {
+ m_bLeftDown = false;
+
+ if ( m_hasCapture )
+ {
+ ReleaseMouse();
+ m_hasCapture = false;
+ }
+
+ wxWindow *parent = GetParent();
+ if ( parent )
+ SetCursor(parent->GetCursor());
+ else
+ SetCursor(wxNullCursor);
+ }
+
+ void OnMouseEvent(wxMouseEvent& event)
+ {
+ if ( event.GetEventType() == wxEVT_LEFT_DOWN )
+ {
+ m_bLeftDown = true;
+ m_ptPosition = event.GetPosition();
+ }
+ else if ( event.GetEventType() == wxEVT_LEFT_UP )
+ {
+ Release();
+ m_bLeftDown = false;
+ }
+ else if ( event.GetEventType() == wxEVT_MOTION )
+ {
+ if ( m_bLeftDown )
+ {
+ int dy = m_ptPosition.y - event.GetPosition().y;
+ if ( dy )
+ {
+ Capture();
+ m_ptPosition = event.GetPosition();
+
+ wxSpinEvent evtscroll( (dy >= 0) ? wxEVT_SCROLL_LINEUP :
+ wxEVT_SCROLL_LINEDOWN,
+ GetId() );
+ evtscroll.SetEventObject(this);
+
+ wxASSERT( m_spins == 1 );
+
+ m_spins = abs(dy);
+ GetEventHandler()->ProcessEvent(evtscroll);
+ m_spins = 1;
+ }
+ }
+ }
+
+ event.Skip();
+ }
+ void OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+ {
+ Release();
+ }
+};
+
+#endif // IS_MOTION_SPIN_SUPPORTED
+
+
WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl,
wxPGSpinCtrlEditor,
wxPGEditor)
wxSize tcSz(sz.x - butSz.x - margin, sz.y);
wxPoint butPos(pos.x + tcSz.x + margin, pos.y);
- wxSpinButton* wnd2 = new wxSpinButton();
+ wxSpinButton* wnd2;
+
+#if IS_MOTION_SPIN_SUPPORTED
+ if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
+ {
+ wnd2 = new wxPGSpinButton();
+ }
+ else
+#endif
+ {
+ wnd2 = new wxSpinButton();
+ }
+
#ifdef __WXMSW__
wnd2->Hide();
#endif
wnd2->SetRange( INT_MIN, INT_MAX );
wnd2->SetValue( 0 );
- wxWindowID id = wnd2->GetId();
- wnd2->Connect( id, wxEVT_SCROLL_LINEUP,
- wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
- NULL, propgrid );
- wnd2->Connect( id, wxEVT_SCROLL_LINEDOWN,
- wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
- NULL, propgrid );
-
// Let's add validator to make sure only numbers can be entered
wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString);
wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary;
wnd1->SetValidator(validator);
- wnd1->Connect( wnd1->GetId(), wxEVT_KEY_DOWN,
- wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
- NULL, propgrid );
-
return wxPGWindowList(wnd1, wnd2);
}
{
int evtType = event.GetEventType();
int keycode = -1;
+ int spins = 1;
bool bigStep = false;
if ( evtType == wxEVT_KEY_DOWN )
if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN )
{
+ #if IS_MOTION_SPIN_SUPPORTED
+ if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
+ {
+ wxPGSpinButton* spinButton =
+ (wxPGSpinButton*) propgrid->GetEditorControlSecondary();
+
+ if ( spinButton )
+ spins = spinButton->GetSpins();
+ }
+ #endif
+
wxString s;
// Can't use wnd since it might be clipper window
wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl);
if ( bigStep )
step *= 10.0;
+ step *= (double) spins;
+
if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step;
else v_d -= step;
if ( bigStep )
step *= 10;
+ step *= spins;
+
if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step;
else v_ll -= step;
NULL,
wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
- wxDateProperty* prop = (wxDateProperty*) property;
+ wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
// Use two stage creation to allow cleaner display on wxMSW
wxDatePickerCtrl* ctrl = new wxDatePickerCtrl();
#else
wxSize useSz = sz;
#endif
+
+ wxDateTime dateValue(wxInvalidDateTime);
+
+ wxVariant value = prop->GetValue();
+ if ( value.GetType() == wxT("datetime") )
+ dateValue = value.GetDateTime();
+
ctrl->Create(propgrid->GetPanel(),
wxPG_SUBID1,
- prop->GetDateValue(),
+ dateValue,
pos,
useSz,
prop->GetDatePickerStyle() | wxNO_BORDER);
- // Connect all required events to grid's OnCustomEditorEvent
- // (all relevenat wxTextCtrl, wxComboBox and wxButton events are
- // already connected)
- ctrl->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED,
- wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
- NULL, propgrid );
-
#ifdef __WXMSW__
ctrl->Show();
#endif
}
// Copies value from property to control
-void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* wnd ) const
+void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property,
+ wxWindow* wnd ) const
{
wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
- // We assume that property's data type is 'int' (or something similar),
- // thus allowing us to get raw, unchecked value via DoGetValue.
- ctrl->SetValue( property->GetValue().GetDateTime() );
+ wxDateTime dateValue(wxInvalidDateTime);
+ wxVariant v(property->GetValue());
+ if ( v.GetType() == wxT("datetime") )
+ dateValue = v.GetDateTime();
+
+ ctrl->SetValue( dateValue );
}
// Control's events are redirected here
return true;
}
-void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd) ) const
+void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* property,
+ wxWindow* wnd ) const
{
- // TODO?
- //wxDateProperty* prop = (wxDateProperty*) property;
- //ctrl->SetValue(?);
+ wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
+ wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
+
+ wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
+
+ if ( prop )
+ {
+ int datePickerStyle = prop->GetDatePickerStyle();
+ if ( datePickerStyle & wxDP_ALLOWNONE )
+ ctrl->SetValue(wxInvalidDateTime);
+ }
}
#endif // wxUSE_DATEPICKCTRL
// Initialize font family choices list
if ( !wxPGGlobalVars->m_fontFamilyChoices )
{
- wxFontEnumerator enumerator;
- enumerator.EnumerateFacenames();
-
-#if wxMINOR_VERSION > 6
- wxArrayString faceNames = enumerator.GetFacenames();
-#else
- wxArrayString& faceNames = *enumerator.GetFacenames();
-#endif
+ wxArrayString faceNames = wxFontEnumerator::GetFacenames();
faceNames.Sort();
wxFont font;
font << m_value;
- SetParentalType(wxPG_PROP_AGGREGATE);
-
- AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font.GetPointSize() ) );
+ AddPrivateChild( new wxIntProperty( _("Point Size"),
+ wxS("Point Size"),(long)font.GetPointSize() ) );
- AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
- gs_fp_es_family_labels,gs_fp_es_family_values,
- font.GetFamily()) );
+ AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
+ gs_fp_es_family_labels,gs_fp_es_family_values,
+ font.GetFamily()) );
wxString faceName = font.GetFaceName();
// If font was not in there, add it now
p->SetValueFromString(faceName, wxPG_FULL_VALUE);
- AddChild( p );
+ AddPrivateChild( p );
- AddChild( new wxEnumProperty(_("Style"), wxS("Style"),
- gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) );
+ AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
+ gs_fp_es_style_labels,gs_fp_es_style_values,
+ font.GetStyle()) );
- AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
- gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) );
+ AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
+ gs_fp_es_weight_labels,gs_fp_es_weight_values,
+ font.GetWeight()) );
- AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
- font.GetUnderlined()) );
+ AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
+ font.GetUnderlined()) );
}
wxFontProperty::~wxFontProperty() { }
if ( !font.Ok() )
{
- font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
- m_value << font;
+ m_value << *wxNORMAL_FONT;
}
}
Item(5)->SetValue( font.GetUnderlined() );
}
-void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
+wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue,
+ int ind,
+ wxVariant& childValue ) const
{
wxFont font;
font << thisValue;
font.SetUnderlined( childValue.GetBool() );
}
- thisValue << font;
+ wxVariant newVariant;
+ newVariant << font;
+ return newVariant;
}
/*
return wxNOT_FOUND;
}
-
-static inline wxColour wxColourFromPGLong( long col )
-{
- return wxColour((col&0xFF),((col>>8)&0xFF),((col>>16)&0xFF));
-}
-
-
void wxSystemColourProperty::OnSetValue()
{
// Convert from generic wxobject ptr to wxPGVariantDataColour
m_value = TranslateVal(val);
}
- int ind;
+ int ind = wxNOT_FOUND;
if ( m_value.GetType() == wxS("wxColourPropertyValue") )
{
wxASSERT( propgrid );
// Must only occur when user triggers event
- if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) )
+ if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
return res;
wxColourPropertyValue val = GetVal();
if ( res && GetIndex() >= 0 )
{
val.m_type = GetIndex();
- if ( val.m_type >= 0 && val.m_type < m_choices.GetCount() )
+ if ( val.m_type < m_choices.GetCount() )
val.m_type = m_choices[val.m_type].GetValue();
// Get proper colour for type.
{
int ival = wxPGVariantToInt(value);
- SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
-
if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
// Show custom choice
0,
0,
NULL,
- DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL
+ #if !defined(__WXWINCE__)
+ DI_COMPAT | DI_DEFAULTSIZE |
+ #endif
+ DI_NORMAL
);
#endif
}
// Let's iterate over the image handler list.
//for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
- for ( node = handlers.begin(); node != handlers.end(); node++ )
+ for ( node = handlers.begin(); node != handlers.end(); ++node )
{
wxImageHandler *handler = (wxImageHandler*)*node;
{
SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
- m_pImage = (wxImage*) NULL;
- m_pBitmap = (wxBitmap*) NULL;
+ m_pImage = NULL;
+ m_pBitmap = NULL;
}
wxImageFileProperty::~wxImageFileProperty()
wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
{
- const wxArrayInt& valueArr = wxArrayIntRefFromVariant(GetValue());
+ wxVariant variant = GetValue();
+ const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant);
unsigned int i;
// Translate values to string indices.
{
}
+void wxDateProperty::OnSetValue()
+{
+ //
+ // Convert invalid dates to unspecified value
+ if ( m_value.GetType() == wxT("datetime") )
+ {
+ if ( !m_value.GetDateTime().IsValid() )
+ m_value.MakeNull();
+ }
+}
+
bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
int WXUNUSED(argFlags) ) const
{
wxDateTime dt;
- const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
+ // FIXME: do we really want to return true from here if only part of the
+ // string was parsed?
+ const char* c = dt.ParseFormat(text);
if ( c )
{