X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b0f0eda8ce631577cf4176d2d17785daddc9b5bc..55410bb4f67febe1ca20654f078ea4fb9a6223ae:/src/propgrid/advprops.cpp diff --git a/src/propgrid/advprops.cpp b/src/propgrid/advprops.cpp index c93ca5fdcf..1b9fa5ee16 100644 --- a/src/propgrid/advprops.cpp +++ b/src/propgrid/advprops.cpp @@ -108,6 +108,131 @@ bool operator == (const wxArrayInt& array1, const wxArrayInt& array2) #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) @@ -128,7 +253,19 @@ wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxP 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 @@ -137,24 +274,12 @@ wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxP 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); } @@ -164,6 +289,7 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper { int evtType = event.GetEventType(); int keycode = -1; + int spins = 1; bool bigStep = false; if ( evtType == wxEVT_KEY_DOWN ) @@ -189,6 +315,17 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper 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); @@ -214,6 +351,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10.0; + step *= (double) spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step; else v_d -= step; @@ -238,6 +377,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10; + step *= spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step; else v_ll -= step; @@ -316,7 +457,7 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri 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(); @@ -327,20 +468,20 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri #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 @@ -349,14 +490,18 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri } // 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 @@ -381,11 +526,20 @@ bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProp 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 @@ -453,14 +607,7 @@ wxFontProperty::wxFontProperty( const wxString& label, const wxString& name, // 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(); @@ -897,13 +1044,6 @@ int wxSystemColourProperty::ColToInd( const wxColour& colour ) const 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 @@ -1040,7 +1180,7 @@ bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const 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(); @@ -1237,7 +1377,7 @@ bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& te 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. @@ -1283,8 +1423,6 @@ bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& va { 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 @@ -1544,7 +1682,10 @@ void wxCursorProperty::OnCustomPaint( wxDC& dc, 0, 0, NULL, - DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL + #if !defined(__WXWINCE__) + DI_COMPAT | DI_DEFAULTSIZE | + #endif + DI_NORMAL ); #endif } @@ -1582,7 +1723,7 @@ const wxString& wxPGGetDefaultImageWildcard() // 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; @@ -1613,8 +1754,8 @@ wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& { SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() ); - m_pImage = (wxImage*) NULL; - m_pBitmap = (wxBitmap*) NULL; + m_pImage = NULL; + m_pBitmap = NULL; } wxImageFileProperty::~wxImageFileProperty() @@ -1774,7 +1915,8 @@ void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value, 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. @@ -1935,6 +2077,17 @@ wxDateProperty::~wxDateProperty() { } +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 {