// Author: Jaakko Salli
// Modified by:
// Created: 2004-09-25
-// RCS-ID: $Id:
// Copyright: (c) Jaakko Salli
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
#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 "wx/odcombo.h"
+
// -----------------------------------------------------------------------
#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.
+// Destructor. It is useful to reset the global pointer in it.
wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
{
+ wxPG_EDITOR(SpinCtrl) = NULL;
}
-
// Create controls and initialize event handling.
wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
const wxPoint& pos, const wxSize& sz ) const
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 );
-
+ wxWindow* wnd1 = wxPGTextCtrlEditor::CreateControls(propgrid, property, pos, tcSz).m_primary;
+#if wxUSE_VALIDATORS
// 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);
+#endif
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;
#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()
{
+ wxPG_EDITOR(DatePickerCtrl) = NULL;
}
wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
const wxPoint& pos,
const wxSize& sz ) const
{
- wxCHECK_MSG( property->IsKindOf(CLASSINFO(wxDateProperty)),
+ wxCHECK_MSG( wxDynamicCast(property, wxDateProperty),
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)
- propgrid->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED,
- (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
- &wxPropertyGrid::OnCustomEditorEvent );
-
#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)) );
+ wxASSERT( wxDynamicCast(ctrl, 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
bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const
{
wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
- wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
+ wxASSERT( wxDynamicCast(ctrl, wxDatePickerCtrl) );
variant = ctrl->GetValue();
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( wxDynamicCast(ctrl, wxDatePickerCtrl) );
+
+ wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
+
+ if ( prop )
+ {
+ int datePickerStyle = prop->GetDatePickerStyle();
+ if ( datePickerStyle & wxDP_ALLOWNONE )
+ ctrl->SetValue(wxInvalidDateTime);
+ }
}
#endif // wxUSE_DATEPICKCTRL
// wxFontProperty
// -----------------------------------------------------------------------
-#include <wx/fontdlg.h>
-#include <wx/fontenum.h>
+#include "wx/fontdlg.h"
+#include "wx/fontenum.h"
+
+//
+// NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar*
+//
-static const wxChar* gs_fp_es_family_labels[] = {
+static const wxChar* const gs_fp_es_family_labels[] = {
wxT("Default"), wxT("Decorative"),
wxT("Roman"), wxT("Script"),
wxT("Swiss"), wxT("Modern"),
+ wxT("Teletype"), wxT("Unknown"),
(const wxChar*) NULL
};
-static long gs_fp_es_family_values[] = {
- wxDEFAULT, wxDECORATIVE,
- wxROMAN, wxSCRIPT,
- wxSWISS, wxMODERN
+static const long gs_fp_es_family_values[] = {
+ wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE,
+ wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT,
+ wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN,
+ wxFONTFAMILY_TELETYPE, wxFONTFAMILY_UNKNOWN
};
-static const wxChar* gs_fp_es_style_labels[] = {
+static const wxChar* const gs_fp_es_style_labels[] = {
wxT("Normal"),
wxT("Slant"),
wxT("Italic"),
(const wxChar*) NULL
};
-static long gs_fp_es_style_values[] = {
+static const long gs_fp_es_style_values[] = {
wxNORMAL,
wxSLANT,
wxITALIC
};
-static const wxChar* gs_fp_es_weight_labels[] = {
+static const wxChar* const gs_fp_es_weight_labels[] = {
wxT("Normal"),
wxT("Light"),
wxT("Bold"),
(const wxChar*) NULL
};
-static long gs_fp_es_weight_values[] = {
+static const long gs_fp_es_weight_values[] = {
wxNORMAL,
wxLIGHT,
wxBOLD
// 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;
- AddChild( 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 wxIntProperty( _("Point Size"),
+ wxS("Point Size"),(long)font.GetPointSize() ) );
wxString faceName = font.GetFaceName();
// If font was not in there, add it now
- if ( faceName.length() &&
+ if ( !faceName.empty() &&
wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
p->SetValueFromString(faceName, wxPG_FULL_VALUE);
- AddChild( p );
+ AddPrivateChild( p );
+
+ AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
+ gs_fp_es_style_labels,gs_fp_es_style_values,
+ font.GetStyle()) );
- AddChild( new wxEnumProperty(_("Style"), wxS("Style"),
- gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) );
+ AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
+ gs_fp_es_weight_labels,gs_fp_es_weight_values,
+ font.GetWeight()) );
- AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
- gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) );
+ AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
+ font.GetUnderlined()) );
- AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
- font.GetUnderlined()) );
+ AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
+ gs_fp_es_family_labels,gs_fp_es_family_values,
+ font.GetFamily()) );
}
wxFontProperty::~wxFontProperty() { }
wxFont font;
font << m_value;
- if ( !font.Ok() )
+ if ( !font.IsOk() )
{
- font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
- m_value << font;
+ m_value << *wxNORMAL_FONT;
}
}
-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;
+
+ if ( useValue.GetType() == wxS("wxFont") )
+ font << useValue;
+
data.SetInitialFont( font );
data.SetColour(*wxBLACK);
wxFont font;
font << m_value;
Item(0)->SetValue( (long)font.GetPointSize() );
- Item(1)->SetValue( (long)font.GetFamily() );
- Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
- Item(3)->SetValue( (long)font.GetStyle() );
- Item(4)->SetValue( (long)font.GetWeight() );
- Item(5)->SetValue( font.GetUnderlined() );
+ Item(1)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
+ Item(2)->SetValue( (long)font.GetStyle() );
+ Item(3)->SetValue( (long)font.GetWeight() );
+ Item(4)->SetValue( font.GetUnderlined() );
+ Item(5)->SetValue( (long)font.GetFamily() );
}
-void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
+wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue,
+ int ind,
+ wxVariant& childValue ) const
{
wxFont font;
font << thisValue;
if ( ind == 0 )
{
- font.SetPointSize( wxPGVariantToInt(childValue) );
+ font.SetPointSize( childValue.GetLong() );
}
else if ( ind == 1 )
- {
- int fam = childValue.GetLong();
- if ( fam < wxDEFAULT ||
- fam > wxTELETYPE )
- fam = wxDEFAULT;
- font.SetFamily( fam );
- }
- else if ( ind == 2 )
{
wxString faceName;
int faceIndex = childValue.GetLong();
font.SetFaceName( faceName );
}
- else if ( ind == 3 )
+ else if ( ind == 2 )
{
int st = childValue.GetLong();
if ( st != wxFONTSTYLE_NORMAL &&
st = wxFONTWEIGHT_NORMAL;
font.SetStyle( st );
}
- else if ( ind == 4 )
+ else if ( ind == 3 )
{
int wt = childValue.GetLong();
if ( wt != wxFONTWEIGHT_NORMAL &&
wt = wxFONTWEIGHT_NORMAL;
font.SetWeight( wt );
}
- else if ( ind == 5 )
+ else if ( ind == 4 )
{
font.SetUnderlined( childValue.GetBool() );
}
+ else if ( ind == 5 )
+ {
+ int fam = childValue.GetLong();
+ if ( fam < wxDEFAULT ||
+ fam > wxTELETYPE )
+ fam = wxDEFAULT;
+ font.SetFamily( fam );
+ }
- thisValue << font;
+ wxVariant newVariant;
+ newVariant << font;
+ return newVariant;
}
/*
else
drawFace = m_value_wxFont.GetFaceName();
- if ( drawFace.length() )
+ if ( !drawFace.empty() )
{
// Draw the background
dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
// 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[] = {
+static const wxChar* const gs_cp_es_syscolour_labels[] = {
wxT("AppWorkspace"),
wxT("ActiveBorder"),
wxT("ActiveCaption"),
(const wxChar*) NULL
};
-static long gs_cp_es_syscolour_values[] = {
+static const long gs_cp_es_syscolour_values[] = {
wxSYS_COLOUR_APPWORKSPACE,
wxSYS_COLOUR_ACTIVEBORDER,
wxSYS_COLOUR_ACTIVECAPTION,
{
wxColourPropertyValue cpv;
- if ( colour.Ok() )
+ if ( colour.IsOk() )
cpv.Init( type, colour );
else
cpv.Init( type, *wxWHITE );
wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
- const wxChar** labels, const long* values, wxPGChoices* choicesCache,
+ const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
const wxColourPropertyValue& value )
: wxEnumProperty( label, name, labels, values, choicesCache )
{
wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
- const wxChar** labels, const long* values, wxPGChoices* choicesCache,
+ const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
const wxColour& value )
: wxEnumProperty( label, name, labels, values, choicesCache )
{
int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
{
size_t i;
- size_t i_max = m_choices.GetCount() - 1;
+ size_t i_max = m_choices.GetCount();
+
+ if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
+ i_max -= 1;
for ( i=0; i<i_max; i++ )
{
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") )
{
cpv << m_value;
wxColour col = cpv.m_colour;
- if ( !col.Ok() )
+ if ( !col.IsOk() )
{
SetValueToUnspecified();
SetIndex(wxNOT_FOUND);
return;
}
- if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
+ if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ||
+ (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
- if ( m_choices.HasValues() )
- ind = GetIndexForValue(cpv.m_type);
- else
- ind = ColToInd(col);
+ ind = GetIndexForValue(cpv.m_type);
}
else
{
wxColour col;
col << m_value;
- if ( !col.Ok() )
+ if ( !col.IsOk() )
{
SetValueToUnspecified();
SetIndex(wxNOT_FOUND);
ind = ColToInd(col);
- if ( ind == wxNOT_FOUND )
+ if ( ind == wxNOT_FOUND &&
+ !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
ind = GetCustomColourIndex();
}
return wxSystemSettings::GetColour( (wxSystemColour)index );
}
-wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
+wxString wxSystemColourProperty::ColourToString( const wxColour& col,
+ int index,
+ int argFlags ) const
{
+
if ( index == wxNOT_FOUND )
- return wxString::Format(wxT("(%i,%i,%i)"),
- (int)col.Red(),
- (int)col.Green(),
- (int)col.Blue());
+ {
+
+ if ( (argFlags & wxPG_FULL_VALUE) ||
+ GetAttributeAsLong(wxPG_COLOUR_HAS_ALPHA, 0) )
+ {
+ return wxString::Format(wxS("(%i,%i,%i,%i)"),
+ (int)col.Red(),
+ (int)col.Green(),
+ (int)col.Blue(),
+ (int)col.Alpha());
+ }
+ else
+ {
+ return wxString::Format(wxS("(%i,%i,%i)"),
+ (int)col.Red(),
+ (int)col.Green(),
+ (int)col.Blue());
+ }
+ }
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() &&
+ !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
+ 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, argFlags);
}
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);
}
}
// Need to do some extra event handling.
-bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event )
+bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid,
+ wxWindow* WXUNUSED(primary),
+ wxEvent& event )
{
+ bool askColour = false;
+
if ( propgrid->IsMainButtonEvent(event) )
{
// We need to handle button click in case editor has been
// switched to one that has wxButton as well.
+ askColour = true;
+ }
+ else if ( event.GetEventType() == wxEVT_COMBOBOX )
+ {
+ // Must override index detection since at this point GetIndex()
+ // will return old value.
+ wxOwnerDrawnComboBox* cb =
+ static_cast<wxOwnerDrawnComboBox*>(propgrid->GetEditorControl());
+
+ if ( cb )
+ {
+ int index = cb->GetSelection();
+
+ if ( index == GetCustomColourIndex() &&
+ !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
+ askColour = true;
+ }
+ }
+
+ if ( askColour && !propgrid->WasValueChangedInEvent() )
+ {
wxVariant variant;
if ( QueryColourFromUser(variant) )
return true;
const wxPropertyGrid* propertyGrid, wxPGProperty* property,
int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
{
- wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
+ wxASSERT( wxDynamicCast(property, wxSystemColourProperty) );
wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
dc.SetPen(*wxBLACK_PEN);
{
wxColour col;
- if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() &&
- paintdata.m_choiceItem != GetCustomColourIndex() )
+ if ( paintdata.m_choiceItem >= 0 &&
+ paintdata.m_choiceItem < (int)m_choices.GetCount() &&
+ (paintdata.m_choiceItem != GetCustomColourIndex() ||
+ m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
int colInd = m_choices[paintdata.m_choiceItem].GetValue();
col = GetColour( colInd );
col = GetVal().m_colour;
}
- if ( col.Ok() )
+ if ( col.IsOk() )
{
dc.SetBrush(col);
dc.DrawRectangle(rect);
bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
{
- //
- // Accept colour format "[Name] [(R,G,B)]"
- // Name takes precedence.
- //
- wxString colourName;
- wxString colourRGB;
+ wxString custColName(m_choices.GetLabel(GetCustomColourIndex()));
+ wxString colStr(text);
+ colStr.Trim(true);
+ colStr.Trim(false);
- int ppos = text.Find(wxT("("));
+ wxColour customColour;
+ bool conversionSuccess = false;
- if ( ppos == wxNOT_FOUND )
+ if ( colStr != custColName )
{
- colourName = text;
- }
- else
- {
- colourName = text.substr(0, ppos);
- colourRGB = text.substr(ppos, text.length()-ppos);
- }
+ if ( colStr.Find(wxS("(")) == 0 )
+ {
+ // Eliminate whitespace
+ colStr.Replace(wxS(" "), wxEmptyString);
- // Strip spaces from extremities
- colourName.Trim(true);
- colourName.Trim(false);
- colourRGB.Trim(true);
+ int commaCount = colStr.Freq(wxS(','));
+ if ( commaCount == 2 )
+ {
+ // Convert (R,G,B) to rgb(R,G,B)
+ colStr = wxS("rgb") + colStr;
+ }
+ else if ( commaCount == 3 )
+ {
+ // We have int alpha, CSS format that wxColour takes as
+ // input processes float alpha. So, let's parse the colour
+ // ourselves instead of trying to convert it to a format
+ // that wxColour::FromString() understands.
+ int r = -1, g = -1, b = -1, a = -1;
+ wxSscanf(colStr, wxS("(%i,%i,%i,%i)"), &r, &g, &b, &a);
+ customColour.Set(r, g, b, a);
+ conversionSuccess = customColour.IsOk();
+ }
+ }
- // Validate colourRGB string - (1,1,1) is shortest allowed
- if ( colourRGB.length() < 7 )
- colourRGB.clear();
+ if ( !conversionSuccess )
+ conversionSuccess = customColour.Set(colStr);
+ }
- if ( colourRGB.length() == 0 && m_choices.GetCount() &&
- colourName == m_choices.GetLabel(GetCustomColourIndex()) )
+ if ( !conversionSuccess && m_choices.GetCount() &&
+ !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) &&
+ colStr == custColName )
{
if ( !(argFlags & wxPG_EDITABLE_VALUE ))
{
- // This really should not occurr...
+ // This really should not occur...
// wxASSERT(false);
ResetNextIndex();
return false;
bool done = false;
- if ( colourName.length() )
+ if ( !conversionSuccess )
{
// Try predefined colour first
- bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
+ bool res = wxEnumProperty::StringToValue(value,
+ colStr,
+ argFlags);
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.
done = true;
}
}
- if ( colourRGB.length() && !done )
+ else
{
- // Then check custom colour.
val.m_type = wxPG_COLOUR_CUSTOM;
-
- int r = -1, g = -1, b = -1;
- wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
-
- if ( r >= 0 && r <= 255 &&
- g >= 0 && g <= 255 &&
- b >= 0 && b <= 255 )
- {
- val.m_colour.Set(r,g,b);
-
- done = true;
- }
+ val.m_colour = customColour;
+ done = true;
}
if ( !done )
{
if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
{
- int ival = wxPGVariantToInt(value);
-
- SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
+ int ival = value.GetLong();
if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
// wxColourProperty
// -----------------------------------------------------------------------
-static const wxChar* gs_cp_es_normcolour_labels[] = {
+static const wxChar* const gs_cp_es_normcolour_labels[] = {
wxT("Black"),
wxT("Maroon"),
wxT("Navy"),
(const wxChar*) NULL
};
-static unsigned long gs_cp_es_normcolour_colours[] = {
+static const unsigned long gs_cp_es_normcolour_colours[] = {
wxPG_COLOUR(0,0,0),
wxPG_COLOUR(128,0,0),
wxPG_COLOUR(0,0,128),
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.IsOk() )
+ 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
#define NUM_CURSORS 28
//#define wx_cp_es_syscursors_len 28
-static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
+static const wxChar* const gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
wxT("Default"),
wxT("Arrow"),
wxT("Right Arrow"),
(const wxChar*) NULL
};
-static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
+static const long gs_cp_es_syscursors_values[NUM_CURSORS] = {
wxCURSOR_NONE,
wxCURSOR_ARROW,
wxCURSOR_RIGHT_ARROW,
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
}
const wxString& wxPGGetDefaultImageWildcard()
{
// Form the wildcard, if not done yet
- if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
+ if ( wxPGGlobalVars->m_pDefaultImageWildcard.empty() )
{
wxString str;
// 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()
wxFileProperty::OnSetValue();
// Delete old image
- if ( m_pImage )
- {
- delete m_pImage;
- m_pImage = NULL;
- }
- if ( m_pBitmap )
- {
- delete m_pBitmap;
- m_pBitmap = NULL;
- }
+ wxDELETE(m_pImage);
+ wxDELETE(m_pBitmap);
+
+ 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() );
}
}
const wxRect& rect,
wxPGPaintData& )
{
- if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
+ if ( m_pBitmap || (m_pImage && m_pImage->IsOk() ) )
{
// Draw the thumbnail
{
m_pImage->Rescale( rect.width, rect.height );
m_pBitmap = new wxBitmap( *m_pImage );
- delete m_pImage;
- m_pImage = NULL;
+ wxDELETE(m_pImage);
}
dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
#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));
{
}
+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 )
{
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");
- if ( !ms_defaultDateFormat.length() )
+ if ( ms_defaultDateFormat.empty() )
{
#if wxUSE_DATEPICKCTRL
bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
}
- if ( m_format.length() &&
+ if ( !m_format.empty() &&
!(argFlags & wxPG_FULL_VALUE) )
format = m_format.c_str();
wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
{
- // This code is basicly copied from datectlg.cpp's SetFormat
+ // This code is basically copied from datectlg.cpp's SetFormat
//
wxString format;
void wxPropertyGridInterface::RegisterAdditionalEditors()
{
+ // Register editor classes, if necessary.
+ if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
+ wxPropertyGrid::RegisterDefaultEditors();
+
#if wxUSE_SPINBTN
wxPGRegisterEditorClass(SpinCtrl);
#endif