// Author: Jaakko Salli
// Modified by:
// Created: 2004-09-25
-// RCS-ID: $Id:
+// RCS-ID: $Id$
// Copyright: (c) Jaakko Salli
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#include "wx/scrolwin.h"
#include "wx/dirdlg.h"
#include "wx/combobox.h"
- #include "wx/layout.h"
#include "wx/sizer.h"
#include "wx/textdlg.h"
#include "wx/filedlg.h"
#include "wx/intl.h"
+ #include "wx/wxcrtvararg.h"
#endif
#define __wxPG_SOURCE_FILE__
-#include <wx/propgrid/propgrid.h>
+#include "wx/propgrid/propgrid.h"
#if wxPG_INCLUDE_ADVPROPS
-#include <wx/propgrid/advprops.h>
+#include "wx/propgrid/advprops.h"
#ifdef __WXMSW__
- #include <wx/msw/private.h>
- #include <wx/msw/dc.h>
+ #include "wx/msw/private.h"
+ #include "wx/msw/dc.h"
#endif
-#include <typeinfo>
-
// -----------------------------------------------------------------------
#if defined(__WXMSW__)
// -----------------------------------------------------------------------
-bool operator == (const wxFont&, const wxFont&)
-{
- return false;
-}
-
// Implement dynamic class for type value.
IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject)
#if wxUSE_SPINBTN
-// This macro also defines global wxPGEditor_SpinCtrl for storing
-// the singleton class instance.
-WX_PG_IMPLEMENT_EDITOR_CLASS(SpinCtrl,wxPGSpinCtrlEditor,wxPGEditor)
+#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)
// Trivial destructor.
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 );
- propgrid->Connect( wxPG_SUBID2, wxEVT_SCROLL_LINEUP,
- (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
- &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid );
- propgrid->Connect( wxPG_SUBID2, wxEVT_SCROLL_LINEDOWN,
- (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
- &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid );
- propgrid->Connect( wxPG_SUBID1, wxEVT_KEY_DOWN,
- (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
- &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid );
-
// Let's add validator to make sure only numbers can be entered
wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString);
{
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;
#if wxUSE_DATEPICKCTRL
-#include <wx/datectrl.h>
-#include <wx/dateevt.h>
+#include "wx/datectrl.h"
+#include "wx/dateevt.h"
class wxPGDatePickerCtrlEditor : public wxPGEditor
{
- WX_PG_DECLARE_EDITOR_CLASS(wxPGDatePickerCtrlEditor)
+ DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor)
public:
virtual ~wxPGDatePickerCtrlEditor();
- wxPG_DECLARE_CREATECONTROLS
-
+ wxString GetName() const;
+ virtual wxPGWindowList CreateControls(wxPropertyGrid* propgrid,
+ wxPGProperty* property,
+ const wxPoint& pos,
+ const wxSize& size) const;
virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const;
virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
wxWindow* wnd, wxEvent& event ) const;
};
-WX_PG_IMPLEMENT_EDITOR_CLASS(DatePickerCtrl,wxPGDatePickerCtrlEditor,wxPGEditor)
+WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl,
+ wxPGDatePickerCtrlEditor,
+ wxPGEditor)
wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
#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)
- propgrid->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED,
- (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
- &wxPropertyGrid::OnCustomEditorEvent );
-
#ifdef __WXMSW__
ctrl->Show();
#endif
// wxFontProperty
// -----------------------------------------------------------------------
-#include <wx/fontdlg.h>
-#include <wx/fontenum.h>
+#include "wx/fontdlg.h"
+#include "wx/fontenum.h"
static const wxChar* gs_fp_es_family_labels[] = {
wxT("Default"), wxT("Decorative"),
// 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() ) );
AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
}
}
-wxString wxFontProperty::GetValueAsString( int argFlags ) const
+wxString wxFontProperty::ValueToString( wxVariant& value,
+ int argFlags ) const
{
- return wxPGProperty::GetValueAsString(argFlags);
+ return wxPGProperty::ValueToString(value, argFlags);
}
bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
if ( propgrid->IsMainButtonEvent(event) )
{
// Update value from last minute changes
- PrepareValueForDialogEditing(propgrid);
+ wxVariant useValue = propgrid->GetUncommittedPropertyValue();
wxFontData data;
wxFont font;
- font << m_value;
+ font << useValue;
data.SetInitialFont( font );
data.SetColour(*wxBLACK);
// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
-#include <wx/colordlg.h>
+#include "wx/colordlg.h"
//#define wx_cp_es_syscolours_len 25
static const wxChar* gs_cp_es_syscolour_labels[] = {
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") )
{
if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
{
- if ( m_choices.HasValues() )
- ind = GetIndexForValue(cpv.m_type);
- else
- ind = ColToInd(col);
+ ind = GetIndexForValue(cpv.m_type);
}
else
{
return m_choices.GetLabel(index);
}
-wxString wxSystemColourProperty::GetValueAsString( int argFlags ) const
+wxString wxSystemColourProperty::ValueToString( wxVariant& value,
+ int argFlags ) const
{
- wxColourPropertyValue val = GetVal();
+ wxColourPropertyValue val = GetVal(&value);
- int ind = GetIndex();
+ int index;
- // Always show custom colour for textctrl-editor
- if ( val.m_type == wxPG_COLOUR_CUSTOM ||
- ind == GetCustomColourIndex() ||
- (argFlags & wxPG_PROPERTY_SPECIFIC) )
+ if ( argFlags & wxPG_VALUE_IS_CURRENT )
{
- return ColourToString(val.m_colour, wxNOT_FOUND);
+ // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
+ // but we should use it whenever possible.
+ index = GetIndex();
+
+ // If custom colour was selected, use invalid index, so that
+ // ColourToString() will return properly formatted colour text.
+ if ( index == GetCustomColourIndex() )
+ index = wxNOT_FOUND;
+ }
+ else
+ {
+ index = m_choices.Index(val.m_type);
}
- if ( ind == -1 )
- return wxEmptyString;
-
- return ColourToString(val.m_colour, ind);
+ return ColourToString(val.m_colour, index);
}
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();
bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
{
int index = number;
- int type = GetValueForIndex(index);
- bool hasValue = m_choices[index].HasValue();
+ int type = m_choices.GetValue(index);
- if ( ( hasValue && type == wxPG_COLOUR_CUSTOM ) ||
- ( !hasValue && (index == (int)GetCustomColourIndex() &&
- !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR))
- )
- )
+ if ( type == wxPG_COLOUR_CUSTOM )
{
QueryColourFromUser(variant);
}
if ( res && GetIndex() >= 0 )
{
val.m_type = GetIndex();
- if ( val.m_type >= 0 && val.m_type < m_choices.GetCount() && m_choices[val.m_type].HasValue() )
+ if ( val.m_type < m_choices.GetCount() )
val.m_type = m_choices[val.m_type].GetValue();
// Get proper colour for type.
wxPG_COLOUR(0,0,0)
};
-WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(wxColourProperty,
- gs_cp_es_normcolour_labels,
- (const long*)NULL,
- gs_cp_es_normcolour_colours,
- TextCtrlAndButton)
+WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
+ wxColour, const wxColour&, TextCtrlAndButton)
+
+static wxPGChoices gs_wxColourProperty_choicesCache;
+
+wxColourProperty::wxColourProperty( const wxString& label,
+ const wxString& name,
+ const wxColour& value )
+ : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
+ NULL,
+ &gs_wxColourProperty_choicesCache, value )
+{
+ Init( value );
+
+ m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
+}
+
+wxColourProperty::~wxColourProperty()
+{
+}
+
+void wxColourProperty::Init( wxColour colour )
+{
+ if ( !colour.Ok() )
+ colour = *wxWHITE;
+ wxVariant variant;
+ variant << colour;
+ m_value = variant;
+ int ind = ColToInd(colour);
+ if ( ind < 0 )
+ ind = m_choices.GetCount() - 1;
+ SetIndex( ind );
+}
+
+wxString wxColourProperty::ValueToString( wxVariant& value,
+ int argFlags ) const
+{
+ const wxPGEditor* editor = GetEditorClass();
+ if ( editor != wxPGEditor_Choice &&
+ editor != wxPGEditor_ChoiceAndButton &&
+ editor != wxPGEditor_ComboBox )
+ argFlags |= wxPG_PROPERTY_SPECIFIC;
+
+ return wxSystemColourProperty::ValueToString(value, argFlags);
+}
+
+wxColour wxColourProperty::GetColour( int index ) const
+{
+ return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
+}
+
+wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
+{
+ wxVariant variant;
+ variant << v.m_colour;
+ return variant;
+}
// -----------------------------------------------------------------------
// wxCursorProperty
if ( paintdata.m_choiceItem < NUM_CURSORS )
{
- int cursorindex = gs_cp_es_syscursors_values[paintdata.m_choiceItem];
+ wxStockCursor cursorIndex =
+ (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
{
- if ( cursorindex == wxCURSOR_NONE )
- cursorindex = wxCURSOR_ARROW;
+ if ( cursorIndex == wxCURSOR_NONE )
+ cursorIndex = wxCURSOR_ARROW;
- wxCursor cursor( cursorindex );
+ wxCursor cursor( cursorIndex );
#ifdef __WXMSW__
HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
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;
return wxPGGlobalVars->m_pDefaultImageWildcard;
}
-WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxImageFileProperty,
- wxFileProperty,
- const wxString&)
+IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
const wxString& value )
m_pBitmap = NULL;
}
+ wxFileName filename = GetFileName();
+
// Create the image thumbnail
- if ( m_filename.FileExists() )
+ if ( filename.FileExists() )
{
- m_pImage = new wxImage( m_filename.GetFullPath() );
+ m_pImage = new wxImage( filename.GetFullPath() );
}
}
#if wxUSE_CHOICEDLG
-#include <wx/choicdlg.h>
+#include "wx/choicdlg.h"
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
void wxMultiChoiceProperty::OnSetValue()
{
- GenerateValueAsString();
+ GenerateValueAsString(m_value, &m_display);
}
-wxString wxMultiChoiceProperty::GetValueAsString( int ) const
+wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
+ int argFlags ) const
{
- return m_display;
+ // If possible, use cached string
+ if ( argFlags & wxPG_VALUE_IS_CURRENT )
+ return m_display;
+
+ wxString s;
+ GenerateValueAsString(value, &s);
+ return s;
}
-void wxMultiChoiceProperty::GenerateValueAsString()
+void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
+ wxString* target ) const
{
wxArrayString strings;
- if ( m_value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
- strings = m_value.GetArrayString();
+ if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
+ strings = value.GetArrayString();
- wxString& tempStr = m_display;
+ wxString& tempStr = *target;
unsigned int i;
unsigned int itemCount = strings.size();
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.
if ( propgrid->IsMainButtonEvent(event) )
{
// Update the value
- PrepareValueForDialogEditing(propgrid);
+ wxVariant useValue = propgrid->GetUncommittedPropertyValue();
wxArrayString labels = m_choices.GetLabels();
unsigned int choiceCount;
dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
- wxArrayString strings = m_value.GetArrayString();
+ wxArrayString strings = useValue.GetArrayString();
wxArrayString extraStrings;
dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
return false;
}
-wxString wxDateProperty::GetValueAsString( int argFlags ) const
+wxString wxDateProperty::ValueToString( wxVariant& value,
+ int argFlags ) const
{
const wxChar* format = (const wxChar*) NULL;
- wxDateTime dateTime = m_value.GetDateTime();
+ wxDateTime dateTime = value.GetDateTime();
if ( !dateTime.IsValid() )
return wxT("Invalid");
void wxPropertyGridInterface::RegisterAdditionalEditors()
{
+ // Register editor classes, if necessary.
+ if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
+ wxPropertyGrid::RegisterDefaultEditors();
+
#if wxUSE_SPINBTN
wxPGRegisterEditorClass(SpinCtrl);
#endif