Aegisub/assdraw/libpropgrid/advprops.cpp
Amar Takhar dc404a954e Add UNIX (and with luck, OS X) support to assdraw. This (unfortunatly)
includes propgrid, the build system for propgrid is brutal rather than fend of
users trying to build it themselves it's worth it to just include it with
assdraw for now.

Originally committed to SVN as r2177.
2008-04-13 06:57:09 +00:00

1883 lines
52 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: advprops.cpp
// Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.)
// Author: Jaakko Salli
// Modified by:
// Created: Sep-25-2004
// RCS-ID: $Id:
// Copyright: (c) Jaakko Salli
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "advprops.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/defs.h"
#include "wx/object.h"
#include "wx/hash.h"
#include "wx/string.h"
#include "wx/log.h"
#include "wx/event.h"
#include "wx/window.h"
#include "wx/panel.h"
#include "wx/dc.h"
#include "wx/dcclient.h"
#include "wx/button.h"
#include "wx/pen.h"
#include "wx/brush.h"
#include "wx/cursor.h"
#include "wx/dialog.h"
#include "wx/settings.h"
#include "wx/msgdlg.h"
#include "wx/choice.h"
#include "wx/stattext.h"
#include "wx/textctrl.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"
#endif
#define __wxPG_SOURCE_FILE__
#include <wx/propgrid/propgrid.h>
#if wxPG_INCLUDE_ADVPROPS
#include <wx/propgrid/propdev.h>
#include <wx/propgrid/advprops.h>
#ifdef __WXMSW__
#include <wx/msw/private.h>
#endif
// -----------------------------------------------------------------------
#if defined(__WXMSW__)
#define wxPG_CAN_DRAW_CURSOR 1
#elif defined(__WXGTK__)
#define wxPG_CAN_DRAW_CURSOR 0
#elif defined(__WXMAC__)
#define wxPG_CAN_DRAW_CURSOR 0
#else
#define wxPG_CAN_DRAW_CURSOR 0
#endif
#if !defined(wxPG_ALLOW_WXADV)
#undef wxUSE_DATEPICKCTRL
#define wxUSE_DATEPICKCTRL 0
#endif
// -----------------------------------------------------------------------
// Value type related
// -----------------------------------------------------------------------
bool operator == (const wxFont&, const wxFont&)
{
return false;
}
WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxFont,wxFontProperty,(const wxFont*)NULL)
// Implement dynamic class for type value.
IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue,wxObject)
bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b)
{
return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) );
}
WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxColourPropertyValue,wxSystemColourProperty,
(const wxColourPropertyValue*)NULL)
WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxColour,wxColourProperty,
(const wxColour*)wxBLACK)
bool operator == (const wxArrayInt& array1, const wxArrayInt& array2)
{
if ( array1.GetCount() != array2.GetCount() )
return false;
size_t i;
for ( i=0; i<array1.GetCount(); i++ )
{
if ( array1[i] != array2[i] )
return false;
}
return true;
}
WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP(wxArrayInt,
wxMultiChoiceProperty,
wxArrayInt())
#if wxUSE_DATETIME
// This macro can be used for values that have built-in support in wxVariant.
WX_PG_IMPLEMENT_VALUE_TYPE(wxDateTime,wxDateProperty,wxT("datetime"),GetDateTime,wxDateTime())
#endif
// -----------------------------------------------------------------------
// wxSpinCtrl-based property editor
// -----------------------------------------------------------------------
#if wxUSE_SPINBTN
//
// Implement an editor control that allows using wxSpinCtrl (actually,
// a combination of wxTextCtrl and wxSpinButton) to edit value of
// wxIntProperty and wxFloatProperty (and similar).
//
// Note that new editor classes needs to be registered before use.
// This can be accomplished using wxPGRegisterEditorClass macro, which
// is used for SpinCtrl in wxPropertyContainerMethods::RegisterAdditionalEditors
// (see below). Registeration can also be performed in a constructor of a
// property that is likely to require the editor in question.
//
#include <wx/spinbutt.h>
// NOTE: Regardless that this class inherits from a working editor, it has
// all necessary methods to work independently. wxTextCtrl stuff is only
// used for event handling here.
class wxPGSpinCtrlEditor : public wxPGTextCtrlEditor
{
WX_PG_DECLARE_EDITOR_CLASS()
public:
virtual ~wxPGSpinCtrlEditor();
// See below for short explanations of what these are suppposed to do.
wxPG_DECLARE_CREATECONTROLS
virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
wxWindow* wnd, wxEvent& event ) const;
};
// This macro also defines global wxPGEditor_SpinCtrl for storing
// the singleton class instance.
WX_PG_IMPLEMENT_EDITOR_CLASS(SpinCtrl,wxPGSpinCtrlEditor,wxPGEditor)
// Trivial destructor.
wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
{
}
// Create controls and initialize event handling.
#ifndef __WXPYTHON__
wxWindow* wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
const wxPoint& pos, const wxSize& sz, wxWindow** pSecondary ) const
#else
wxPGWindowPair wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
const wxPoint& pos, const wxSize& sz ) const
#endif
{
const int margin = 1;
wxSize butSz(18, sz.y);
wxSize tcSz(sz.x - butSz.x - margin, sz.y);
wxPoint butPos(pos.x + tcSz.x + margin, pos.y);
wxSpinButton* wnd2 = new wxSpinButton();
#ifdef __WXMSW__
wnd2->Hide();
#endif
wnd2->Create( propgrid, wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL );
wnd2->SetRange( INT_MIN, INT_MAX );
//wnd2->SetRange( 5, 12 );
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 );
// Let's add validator to make sure only numbers can be entered
wxString temps;
wxTextValidator validator(wxFILTER_NUMERIC, &temps);
#ifndef __WXPYTHON__
wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz, NULL );
wnd1->SetValidator(validator);
*pSecondary = wnd2;
return wnd1;
#else
wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary;
wnd1->SetValidator(validator);
return wxPGWindowPair(wnd1, wnd2);
#endif
}
// Control's events are redirected here
bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
wxWindow* wnd, wxEvent& event ) const
{
int evtType = event.GetEventType();
if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN )
{
wxString s;
// Can't use wnd since it might be clipper window
wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl);
if ( tc )
s = tc->GetValue();
else
s = property->GetValueAsString(wxPG_FULL_VALUE);
wxSpinButton* spinButton = (wxSpinButton*) propgrid->GetEditorControlSecondary();
int spinMin = spinButton->GetMin();
int spinMax = spinButton->GetMax();
if ( property->GetValueType() == wxPG_VALUETYPE(double) )
{
double v_d;
// Try double
if ( s.ToDouble(&v_d) )
{
if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += 1.0;
else v_d -= 1.0;
// Min/Max
double dSpinMin = (double) spinMin;
double dSpinMax = (double) spinMax;
if ( v_d > dSpinMax ) v_d = dSpinMax;
else if ( v_d < dSpinMin ) v_d = dSpinMin;
wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL);
}
else
{
return false;
}
}
else
{
long v_l;
// Try long
if ( s.ToLong(&v_l, 0) )
{
if ( evtType == wxEVT_SCROLL_LINEUP ) v_l++;
else v_l--;
// Min/Max
if ( v_l > spinMax ) v_l = spinMax;
else if ( v_l < spinMin ) v_l = spinMin;
s = wxString::Format(wxT("%i"),(int)v_l);
}
else
{
return false;
}
}
if ( tc )
tc->SetValue(s);
return true;
}
return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event);
}
#endif // wxUSE_SPINBTN
// -----------------------------------------------------------------------
// wxDatePickerCtrl-based property editor
// -----------------------------------------------------------------------
#if wxUSE_DATEPICKCTRL
#include <wx/datectrl.h>
#include <wx/dateevt.h>
class wxPGDatePickerCtrlEditor : public wxPGEditor
{
WX_PG_DECLARE_EDITOR_CLASS()
public:
virtual ~wxPGDatePickerCtrlEditor();
wxPG_DECLARE_CREATECONTROLS
virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const;
virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
wxWindow* wnd, wxEvent& event ) const;
virtual bool CopyValueFromControl( wxPGProperty* property, wxWindow* wnd ) const;
virtual void SetValueToUnspecified( wxWindow* wnd ) const;
};
WX_PG_IMPLEMENT_EDITOR_CLASS(DatePickerCtrl,wxPGDatePickerCtrlEditor,wxPGEditor)
wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
{
}
#ifndef __WXPYTHON__
wxWindow* wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
wxPGProperty* property,
const wxPoint& pos,
const wxSize& sz,
wxWindow** ) const
#else
wxPGWindowPair wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
wxPGProperty* property,
const wxPoint& pos,
const wxSize& sz ) const
#endif
{
wxCHECK_MSG( property->IsKindOf(WX_PG_CLASSINFO(wxDateProperty)),
NULL,
wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
wxDatePropertyClass* prop = (wxDatePropertyClass*) property;
// Use two stage creation to allow cleaner display on wxMSW
wxDatePickerCtrl* ctrl = new wxDatePickerCtrl();
#ifdef __WXMSW__
ctrl->Hide();
wxSize useSz = wxDefaultSize;
useSz.x = sz.x;
#else
wxSize useSz = sz;
#endif
ctrl->Create(propgrid,
wxPG_SUBID1,
prop->GetDateValue(),
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
return ctrl;
}
// Copies value from property to control
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( *((const wxDateTime*)property->DoGetValue().GetVoidPtr()) );
}
// Control's events are redirected here
bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid),
wxPGProperty* WXUNUSED(property),
wxWindow* WXUNUSED(wnd),
wxEvent& event ) const
{
if ( event.GetEventType() == wxEVT_DATE_CHANGED )
return true;
return false;
}
bool wxPGDatePickerCtrlEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* wnd ) const
{
wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
wxDatePropertyClass* prop = (wxDatePropertyClass*) property;
prop->SetDateValue( ctrl->GetValue() );
return true;
}
void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxWindow* WXUNUSED(wnd) ) const
{
// TODO?
//wxDateProperty* prop = (wxDateProperty*) property;
//ctrl->SetValue(?);
}
#endif // wxUSE_DATEPICKCTRL
// -----------------------------------------------------------------------
// wxFontProperty
// -----------------------------------------------------------------------
#include <wx/fontdlg.h>
#include <wx/fontenum.h>
static const wxChar* gs_fp_es_family_labels[] = {
wxT("Default"), wxT("Decorative"),
wxT("Roman"), wxT("Script"),
wxT("Swiss"), wxT("Modern"),
wxT("Teletype"),
(const wxChar*) NULL
};
static long gs_fp_es_family_values[] = {
wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE,
wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT,
wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN,
wxFONTFAMILY_TELETYPE
};
static const wxChar* gs_fp_es_style_labels[] = {
wxT("Normal"),
wxT("Slant"),
wxT("Italic"),
(const wxChar*) NULL
};
static long gs_fp_es_style_values[] = {
wxNORMAL,
wxSLANT,
wxITALIC
};
static const wxChar* gs_fp_es_weight_labels[] = {
wxT("Normal"),
wxT("Light"),
wxT("Bold"),
(const wxChar*) NULL
};
static long gs_fp_es_weight_values[] = {
wxNORMAL,
wxLIGHT,
wxBOLD
};
// Class body is in advprops.h
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxBaseParentProperty,
wxFont,const wxFont&,TextCtrlAndButton)
wxFontPropertyClass::wxFontPropertyClass( const wxString& label, const wxString& name,
const wxFont& value )
: wxPGPropertyWithChildren(label,name)
{
wxPG_INIT_REQUIRED_TYPE(wxFont)
DoSetValue( wxPGVariantCreator(value) );
// Initialize font family choices list
if ( !wxPGGlobalVars->m_fontFamilyChoices )
{
WX_PG_GLOBALS_LOCKER()
wxFontEnumerator enumerator;
enumerator.EnumerateFacenames();
#if wxMINOR_VERSION > 6
wxArrayString faceNames = enumerator.GetFacenames();
#else
wxArrayString& faceNames = *enumerator.GetFacenames();
#endif
faceNames.Sort();
wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
}
wxString emptyString(wxEmptyString);
AddChild( wxIntProperty( _("Point Size"),emptyString,m_value_wxFont.GetPointSize() ) );
AddChild( wxEnumProperty(_("Family"), emptyString,
gs_fp_es_family_labels,gs_fp_es_family_values,
m_value_wxFont.GetFamily()) );
wxString faceName = m_value_wxFont.GetFaceName();
// If font was not in there, add it now
if ( faceName.length() &&
wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
wxPGProperty* p = wxEnumProperty(_("Face Name"),emptyString,
*wxPGGlobalVars->m_fontFamilyChoices);
p->SetValueFromString(faceName,wxPG_FULL_VALUE);
AddChild( p );
AddChild( wxEnumProperty(_("Style"),emptyString,
gs_fp_es_style_labels,gs_fp_es_style_values,m_value_wxFont.GetStyle()) );
AddChild( wxEnumProperty(_("Weight"),emptyString,
gs_fp_es_weight_labels,gs_fp_es_weight_values,m_value_wxFont.GetWeight()) );
AddChild( wxBoolProperty(_("Underlined"),emptyString,
m_value_wxFont.GetUnderlined()) );
}
wxFontPropertyClass::~wxFontPropertyClass () { }
void wxFontPropertyClass::DoSetValue( wxPGVariant value )
{
const wxFont* font = wxPGVariantToWxObjectPtr(value,wxFont);
if ( font && font->Ok() )
m_value_wxFont = *font;
else
m_value_wxFont = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
RefreshChildren();
}
wxPGVariant wxFontPropertyClass::DoGetValue() const
{
return wxPGVariantCreator(m_value_wxFont);
}
wxString wxFontPropertyClass::GetValueAsString( int argFlags ) const
{
return wxPGPropertyWithChildren::GetValueAsString(argFlags);
}
bool wxFontPropertyClass::OnEvent( wxPropertyGrid* propgrid, wxWindow* primary,
wxEvent& event )
{
if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
{
// Update value from last minute changes
PrepareValueForDialogEditing(propgrid);
wxFontData data;
data.SetInitialFont(m_value_wxFont);
data.SetColour(*wxBLACK);
wxFontDialog dlg(propgrid, data);
if ( dlg.ShowModal() == wxID_OK )
{
propgrid->EditorsValueWasModified();
wxFontData retData = dlg.GetFontData();
wxFont font = retData.GetChosenFont();
DoSetValue(wxPGVariantCreator(font));
UpdateControl(primary);
return true;
}
}
return false;
}
void wxFontPropertyClass::RefreshChildren()
{
if ( !GetCount() ) return;
Item(0)->DoSetValue( (long)m_value_wxFont.GetPointSize() );
Item(1)->DoSetValue( (long)m_value_wxFont.GetFamily() );
Item(2)->SetValueFromString( m_value_wxFont.GetFaceName(), wxPG_FULL_VALUE );
Item(3)->DoSetValue( (long)m_value_wxFont.GetStyle() );
Item(4)->DoSetValue( (long)m_value_wxFont.GetWeight() );
Item(5)->DoSetValue( m_value_wxFont.GetUnderlined() );
}
void wxFontPropertyClass::ChildChanged( wxPGProperty* p )
{
wxASSERT( this == p->GetParent() );
int ind = p->GetIndexInParent();
if ( ind == 0 )
{
m_value_wxFont.SetPointSize( wxPGVariantToLong(p->DoGetValue()) );
}
else if ( ind == 1 )
{
int fam = p->DoGetValue().GetLong();
if ( fam < wxDEFAULT ||
fam > wxTELETYPE )
fam = wxDEFAULT;
m_value_wxFont.SetFamily( fam );
}
else if ( ind == 2 )
{
m_value_wxFont.SetFaceName( p->GetValueAsString(wxPG_FULL_VALUE) );
}
else if ( ind == 3 )
{
int st = wxPGVariantToLong(p->DoGetValue());
if ( st != wxFONTSTYLE_NORMAL &&
st != wxFONTSTYLE_SLANT &&
st != wxFONTSTYLE_ITALIC )
st = wxFONTWEIGHT_NORMAL;
m_value_wxFont.SetStyle( st );
}
else if ( ind == 4 )
{
int wt = wxPGVariantToLong(p->DoGetValue());
if ( wt != wxFONTWEIGHT_NORMAL &&
wt != wxFONTWEIGHT_LIGHT &&
wt != wxFONTWEIGHT_BOLD )
wt = wxFONTWEIGHT_NORMAL;
m_value_wxFont.SetWeight( wt );
}
else if ( ind == 5 )
{
m_value_wxFont.SetUnderlined( wxPGVariantToBool(p->DoGetValue())?true:false );
}
}
/*
wxSize wxFontPropertyClass::GetImageSize() const
{
return wxSize(-1,-1);
}
void wxFontPropertyClass::OnCustomPaint(wxDC& dc,
const wxRect& rect,
wxPGPaintData& paintData)
{
wxString drawFace;
if ( paintData.m_choiceItem >= 0 )
drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
else
drawFace = m_value_wxFont.GetFaceName();
if ( drawFace.length() )
{
// Draw the background
dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
//dc.SetBrush( *wxWHITE_BRUSH );
//dc.SetPen( *wxMEDIUM_GREY_PEN );
dc.DrawRectangle( rect );
wxFont oldFont = dc.GetFont();
wxFont drawFont(oldFont.GetPointSize(),
wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
dc.SetFont(drawFont);
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
dc.SetFont(oldFont);
}
else
{
// No file - just draw a white box
dc.SetBrush ( *wxWHITE_BRUSH );
dc.DrawRectangle ( rect );
}
}
*/
// -----------------------------------------------------------------------
// wxSystemColourProperty
// -----------------------------------------------------------------------
// 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>
//#define wx_cp_es_syscolours_len 25
static const wxChar* gs_cp_es_syscolour_labels[] = {
wxT("AppWorkspace"),
wxT("ActiveBorder"),
wxT("ActiveCaption"),
wxT("ButtonFace"),
wxT("ButtonHighlight"),
wxT("ButtonShadow"),
wxT("ButtonText"),
wxT("CaptionText"),
wxT("ControlDark"),
wxT("ControlLight"),
wxT("Desktop"),
wxT("GrayText"),
wxT("Highlight"),
wxT("HighlightText"),
wxT("InactiveBorder"),
wxT("InactiveCaption"),
wxT("InactiveCaptionText"),
wxT("Menu"),
wxT("Scrollbar"),
wxT("Tooltip"),
wxT("TooltipText"),
wxT("Window"),
wxT("WindowFrame"),
wxT("WindowText"),
wxT("Custom"),
(const wxChar*) NULL
};
static long gs_cp_es_syscolour_values[] = {
wxSYS_COLOUR_APPWORKSPACE,
wxSYS_COLOUR_ACTIVEBORDER,
wxSYS_COLOUR_ACTIVECAPTION,
wxSYS_COLOUR_BTNFACE,
wxSYS_COLOUR_BTNHIGHLIGHT,
wxSYS_COLOUR_BTNSHADOW,
wxSYS_COLOUR_BTNTEXT ,
wxSYS_COLOUR_CAPTIONTEXT,
wxSYS_COLOUR_3DDKSHADOW,
wxSYS_COLOUR_3DLIGHT,
wxSYS_COLOUR_BACKGROUND,
wxSYS_COLOUR_GRAYTEXT,
wxSYS_COLOUR_HIGHLIGHT,
wxSYS_COLOUR_HIGHLIGHTTEXT,
wxSYS_COLOUR_INACTIVEBORDER,
wxSYS_COLOUR_INACTIVECAPTION,
wxSYS_COLOUR_INACTIVECAPTIONTEXT,
wxSYS_COLOUR_MENU,
wxSYS_COLOUR_SCROLLBAR,
wxSYS_COLOUR_INFOBK,
wxSYS_COLOUR_INFOTEXT,
wxSYS_COLOUR_WINDOW,
wxSYS_COLOUR_WINDOWFRAME,
wxSYS_COLOUR_WINDOWTEXT,
wxPG_COLOUR_CUSTOM
};
// Class body is in advprops.h
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
wxColourPropertyValue,const wxColourPropertyValue&,Choice)
void wxSystemColourPropertyClass::Init( int type, const wxColour& colour )
{
m_value.m_type = type;
if ( colour.Ok() )
m_value.m_colour = colour;
else
m_value.m_colour = *wxWHITE;
m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
}
static wxPGChoices gs_wxSystemColourProperty_choicesCache;
wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name,
const wxColourPropertyValue& value )
: wxEnumPropertyClass( label,
name,
gs_cp_es_syscolour_labels,
gs_cp_es_syscolour_values,
&gs_wxSystemColourProperty_choicesCache )
{
wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue)
if ( &value )
Init(value.m_type,value.m_colour);
else
Init(0,*wxBLACK);
DoSetValue( &m_value );
}
wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name,
const wxChar** labels, const long* values, wxPGChoices* choicesCache,
const wxColourPropertyValue& value )
: wxEnumPropertyClass( label, name, labels, values, choicesCache )
{
if ( &value )
Init(value.m_type,value.m_colour);
else
Init(wxPG_COLOUR_CUSTOM,*wxBLACK);
}
wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name,
const wxChar** labels, const long* values, wxPGChoices* choicesCache,
const wxColour& value )
: wxEnumPropertyClass( label, name, labels, values, choicesCache )
{
Init(wxPG_COLOUR_CUSTOM,value);
}
wxSystemColourPropertyClass::~wxSystemColourPropertyClass() { }
int wxSystemColourPropertyClass::ColToInd( const wxColour& colour )
{
size_t i;
size_t i_max = m_choices.GetCount() - 1;
if ( !colour.Ok() )
return wxNOT_FOUND;
long pixval = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
const wxArrayInt& arrValues = m_choices.GetValues();
for ( i=0; i<i_max; i++ )
{
int ind = i;
if ( arrValues.GetCount() )
ind = arrValues[i];
if ( GetColour(ind) == pixval )
{
/*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
GetClassName(),GetLabel().c_str(),
(int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
(int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
return ind;
}
}
return wxNOT_FOUND;
}
static inline wxColour wxColourFromPGLong( long col )
{
return wxColour((col&0xFF),((col>>8)&0xFF),((col>>16)&0xFF));
}
void wxSystemColourPropertyClass::DoSetValue( wxPGVariant value )
{
wxColourPropertyValue* pval = wxPGVariantToWxObjectPtr(value,wxColourPropertyValue);
m_flags &= ~(wxPG_PROP_UNSPECIFIED);
if ( pval != (wxColourPropertyValue*) NULL )
{
if ( !pval->m_colour.Ok() )
{
m_flags |= wxPG_PROP_UNSPECIFIED;
m_index = wxNOT_FOUND;
m_value.Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
return;
}
else if ( pval != &m_value )
{
m_value = *pval;
}
}
else
{
m_value.Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
}
if ( m_value.m_type < wxPG_COLOUR_WEB_BASE )
{
m_value.m_colour = GetColour( m_value.m_type );
wxEnumPropertyClass::DoSetValue( (long)m_value.m_type );
}
else
{
m_index = m_choices.GetCount()-1;
}
}
long wxSystemColourPropertyClass::GetColour( int index )
{
wxColour colour = wxSystemSettings::GetColour ( (wxSystemColour)index );
return wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue());
}
wxPGVariant wxSystemColourPropertyClass::DoGetValue() const
{
return wxPGVariantCreator(&m_value);
}
wxString wxSystemColourPropertyClass::GetValueAsString( int argFlags ) const
{
// Always show custom colour for non-choice editor
// Assumes changed editor means its textctrl based...
if ( m_value.m_type == wxPG_COLOUR_CUSTOM ||
(argFlags & wxPG_PROPERTY_SPECIFIC) )
{
/*#ifdef __WXDEBUG__
// Sanity check
if ( m_value.m_type != wxPG_COLOUR_CUSTOM &&
(GetEditorClass() == wxPG_EDITOR(Choice) ||
GetEditorClass() == wxPG_EDITOR(ChoiceAndButton)) )
{
wxLogDebug(wxT("wxSystemColourPropertyClass: Assumed wrong editor type!!!"));
}
#endif*/
return wxString::Format(wxT("(%i,%i,%i)"),
(int)m_value.m_colour.Red(),
(int)m_value.m_colour.Green(),
(int)m_value.m_colour.Blue());
}
return m_choices.GetLabel(m_index);
}
wxSize wxSystemColourPropertyClass::GetImageSize() const
{
return wxSize(-1,-1);
}
bool wxSystemColourPropertyClass::QueryColourFromUser( wxPropertyGrid* propgrid, wxWindow* primary )
{
bool res = false;
m_value.m_type = wxPG_COLOUR_CUSTOM;
wxColourData data;
data.SetChooseFull(true);
data.SetColour(m_value.m_colour);
int i;
for ( i = 0; i < 16; i++)
{
wxColour colour(i*16, i*16, i*16);
data.SetCustomColour(i, colour);
}
wxColourDialog dialog(propgrid, &data);
if ( dialog.ShowModal() == wxID_OK )
{
wxColourData retData = dialog.GetColourData();
m_value.m_colour = retData.GetColour();
wxSystemColourPropertyClass::DoSetValue(&m_value);
res = true;
}
// Update text in combo box (so it is "(R,G,B)" not "Custom").
if ( primary )
GetEditorClass()->SetControlStringValue(primary,GetValueAsString(0));
return res;
}
// Need to do some extra event handling.
bool wxSystemColourPropertyClass::OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event )
{
if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
{
int index = m_index; // m_index has already been updated.
int type = wxEnumPropertyClass::DoGetValue().GetLong();
const wxArrayInt& arrValues = m_choices.GetValues();
if ( ( arrValues.GetCount() && type == wxPG_COLOUR_CUSTOM ) ||
( !arrValues.GetCount() && (index == (int)(m_choices.GetCount()-1) &&
!(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR))
)
)
{
QueryColourFromUser(propgrid,primary);
return true;
}
else
{
m_value.m_type = type;
m_value.m_colour = GetColour( type );
}
}
else if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
{
// We need to handle button click in case editor has been
// switched to one that has wxButton as well.
return QueryColourFromUser(propgrid,primary);
}
return false;
}
void wxSystemColourPropertyClass::OnCustomPaint( wxDC& dc, const wxRect& rect,
wxPGPaintData& paintdata )
{
if ( paintdata.m_choiceItem >= 0 &&
( paintdata.m_choiceItem < (int)(GetItemCount()-1) || (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR))
)
{
int colInd;
const wxArrayInt& values = m_choices.GetValues();
if ( values.GetCount() )
colInd = values[paintdata.m_choiceItem];
else
colInd = paintdata.m_choiceItem;
dc.SetBrush ( wxColour ( GetColour ( colInd ) ) );
}
else if ( !(m_flags & wxPG_PROP_UNSPECIFIED) )
dc.SetBrush ( m_value.m_colour );
else
dc.SetBrush ( *wxWHITE );
dc.DrawRectangle ( rect );
}
bool wxSystemColourPropertyClass::SetValueFromString( const wxString& text, int flags )
{
wxColourPropertyValue val;
if ( text[0] == wxT('(') )
{
// Custom colour.
val.m_type = wxPG_COLOUR_CUSTOM;
int r, g, b;
wxSscanf(text.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
val.m_colour.Set(r,g,b);
wxSystemColourPropertyClass::DoSetValue( &val );
return true;
}
else
{
// Predefined colour.
bool res = wxEnumPropertyClass::SetValueFromString(text,flags);
if ( res )
{
val.m_type = m_index;
const wxArrayInt& values = GetValues();
if ( values.GetCount() )
val.m_type = values[m_index];
// Get proper colour for type.
val.m_colour = wxColourFromPGLong(GetColour(val.m_type));
wxSystemColourPropertyClass::DoSetValue( &val );
return true;
}
}
return false;
}
void wxSystemColourPropertyClass::SetAttribute( int id, wxVariant& value )
{
if ( id == wxPG_COLOUR_ALLOW_CUSTOM )
{
int ival = value.GetLong();
SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
// Show custom choice
m_choices.Add(wxT("Custom"),wxPG_COLOUR_CUSTOM);
m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
}
else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
{
// Hide custom choice
m_choices.RemoveAt(m_choices.GetCount()-1);
m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
}
}
}
// -----------------------------------------------------------------------
// wxColourProperty
// -----------------------------------------------------------------------
static const wxChar* gs_cp_es_normcolour_labels[] = {
wxT("Black"),
wxT("Maroon"),
wxT("Navy"),
wxT("Purple"),
wxT("Teal"),
wxT("Gray"),
wxT("Green"),
wxT("Olive"),
wxT("Brown"),
wxT("Blue"),
wxT("Fuchsia"),
wxT("Red"),
wxT("Orange"),
wxT("Silver"),
wxT("Lime"),
wxT("Aqua"),
wxT("Yellow"),
wxT("White"),
wxT("Custom"),
(const wxChar*) NULL
};
static unsigned long gs_cp_es_normcolour_colours[] = {
wxPG_COLOUR(0,0,0),
wxPG_COLOUR(128,0,0),
wxPG_COLOUR(0,0,128),
wxPG_COLOUR(128,0,128),
wxPG_COLOUR(0,128,128),
wxPG_COLOUR(128,128,128),
wxPG_COLOUR(0,128,0),
wxPG_COLOUR(128,128,0),
wxPG_COLOUR(166,124,81),
wxPG_COLOUR(0,0,255),
wxPG_COLOUR(255,0,255),
wxPG_COLOUR(255,0,0),
wxPG_COLOUR(247,148,28),
wxPG_COLOUR(192,192,192),
wxPG_COLOUR(0,255,0),
wxPG_COLOUR(0,255,255),
wxPG_COLOUR(255,255,0),
wxPG_COLOUR(255,255,255),
wxPG_COLOUR(0,0,0)
};
WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(wxColourProperty,
wxColourPropertyClass,
gs_cp_es_normcolour_labels,
(const long*)NULL,
gs_cp_es_normcolour_colours,
TextCtrlAndButton)
// -----------------------------------------------------------------------
// wxCursorProperty
// -----------------------------------------------------------------------
#define wxPG_CURSOR_IMAGE_WIDTH 32
//#define wx_cp_es_syscursors_len 28
static const wxChar* gs_cp_es_syscursors_labels[] = {
wxT("Default"),
wxT("Arrow"),
wxT("Right Arrow"),
wxT("Blank"),
wxT("Bullseye"),
wxT("Character"),
wxT("Cross"),
wxT("Hand"),
wxT("I-Beam"),
wxT("Left Button"),
wxT("Magnifier"),
wxT("Middle Button"),
wxT("No Entry"),
wxT("Paint Brush"),
wxT("Pencil"),
wxT("Point Left"),
wxT("Point Right"),
wxT("Question Arrow"),
wxT("Right Button"),
wxT("Sizing NE-SW"),
wxT("Sizing N-S"),
wxT("Sizing NW-SE"),
wxT("Sizing W-E"),
wxT("Sizing"),
wxT("Spraycan"),
wxT("Wait"),
wxT("Watch"),
wxT("Wait Arrow"),
(const wxChar*) NULL
};
static long gs_cp_es_syscursors_values[] = {
wxCURSOR_NONE,
wxCURSOR_ARROW,
wxCURSOR_RIGHT_ARROW,
wxCURSOR_BLANK,
wxCURSOR_BULLSEYE,
wxCURSOR_CHAR,
wxCURSOR_CROSS,
wxCURSOR_HAND,
wxCURSOR_IBEAM,
wxCURSOR_LEFT_BUTTON,
wxCURSOR_MAGNIFIER,
wxCURSOR_MIDDLE_BUTTON,
wxCURSOR_NO_ENTRY,
wxCURSOR_PAINT_BRUSH,
wxCURSOR_PENCIL,
wxCURSOR_POINT_LEFT,
wxCURSOR_POINT_RIGHT,
wxCURSOR_QUESTION_ARROW,
wxCURSOR_RIGHT_BUTTON,
wxCURSOR_SIZENESW,
wxCURSOR_SIZENS,
wxCURSOR_SIZENWSE,
wxCURSOR_SIZEWE,
wxCURSOR_SIZING,
wxCURSOR_SPRAYCAN,
wxCURSOR_WAIT,
wxCURSOR_WATCH,
wxCURSOR_ARROWWAIT
};
WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxCursorProperty,wxEnumProperty,int)
wxCursorPropertyClass::wxCursorPropertyClass( const wxString& label, const wxString& name,
int value )
: wxEnumPropertyClass( label,
name,
gs_cp_es_syscursors_labels,
gs_cp_es_syscursors_values,
value )
{
m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
//wxEnumPropertyClass::DoSetValue ( (void*)&value, NULL );
}
wxCursorPropertyClass::~wxCursorPropertyClass()
{
}
wxSize wxCursorPropertyClass::GetImageSize() const
{
#if wxPG_CAN_DRAW_CURSOR
return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
#else
return wxSize(0,0);
#endif
}
#if wxPG_CAN_DRAW_CURSOR
void wxCursorPropertyClass::OnCustomPaint( wxDC& dc,
const wxRect& rect,
wxPGPaintData& paintdata )
{
// Background brush
dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
if ( paintdata.m_choiceItem >= 0 )
{
dc.DrawRectangle( rect );
int cursorindex = gs_cp_es_syscursors_values[paintdata.m_choiceItem];
/*
if ( cursorindex == wxPG_CURSOR_FROM_FILE )
{
wxFAIL_MSG(wxT("not implemented"));
}
else if ( cursorindex == wxPG_CURSOR_FROM_RESOURCE )
{
wxFAIL_MSG(wxT("not implemented"));
}
else
*/
{
if ( cursorindex == wxCURSOR_NONE )
cursorindex = wxCURSOR_ARROW;
wxCursor cursor( cursorindex );
#ifdef __WXMSW__
::DrawIconEx( (HDC)dc.GetHDC(),
rect.x,
rect.y,
(HICON)cursor.GetHandle(),
0,
0,
0,
NULL,
DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL
);
#endif
}
}
}
#else
void wxCursorPropertyClass::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
#endif
// -----------------------------------------------------------------------
// wxImageFileProperty
// -----------------------------------------------------------------------
#if wxUSE_IMAGE
const wxString& wxPGGetDefaultImageWildcard()
{
WX_PG_GLOBALS_LOCKER()
// Form the wildcard, if not done yet
if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
{
wxString str;
// TODO: This section may require locking (using global).
wxList& handlers = wxImage::GetHandlers();
wxList::iterator node;
// 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++ )
{
wxImageHandler *handler = (wxImageHandler*)*node;
wxString ext_lo = handler->GetExtension();
wxString ext_up = ext_lo.Upper();
str.append( ext_up );
str.append( wxT(" files (*.") );
str.append( ext_up );
str.append( wxT(")|*.") );
str.append( ext_lo );
str.append( wxT("|") );
}
str.append ( wxT("All files (*.*)|*.*") );
wxPGGlobalVars->m_pDefaultImageWildcard = str;
}
return wxPGGlobalVars->m_pDefaultImageWildcard;
}
WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxImageFileProperty,
wxFileProperty,
const wxString&)
wxImageFilePropertyClass::wxImageFilePropertyClass( const wxString& label, const wxString& name,
const wxString& value )
: wxFilePropertyClass(label,name,value)
{
m_wildcard = wxPGGetDefaultImageWildcard();
m_pImage = (wxImage*) NULL;
m_pBitmap = (wxBitmap*) NULL;
}
wxImageFilePropertyClass::~wxImageFilePropertyClass()
{
if ( m_pBitmap )
delete m_pBitmap;
if ( m_pImage )
delete m_pImage;
}
void wxImageFilePropertyClass::DoSetValue( wxPGVariant value )
{
wxFilePropertyClass::DoSetValue(value);
// Delete old image
if ( m_pImage )
{
delete m_pImage;
m_pImage = NULL;
}
if ( m_pBitmap )
{
delete m_pBitmap;
m_pBitmap = NULL;
}
// Create the image thumbnail
if ( m_filename.FileExists() )
{
m_pImage = new wxImage ( m_filename.GetFullPath() );
}
}
wxSize wxImageFilePropertyClass::GetImageSize() const
{
return wxSize(-1,-1);
}
void wxImageFilePropertyClass::OnCustomPaint( wxDC& dc,
const wxRect& rect,
wxPGPaintData& )
{
if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
{
// Draw the thumbnail
// Create the bitmap here because required size is not known in DoSetValue().
if ( !m_pBitmap )
{
m_pImage->Rescale( rect.width, rect.height );
m_pBitmap = new wxBitmap( *m_pImage );
delete m_pImage;
m_pImage = NULL;
}
dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
}
else
{
// No file - just draw a white box
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle ( rect );
}
}
#endif // wxUSE_IMAGE
// -----------------------------------------------------------------------
// wxMultiChoiceProperty
// -----------------------------------------------------------------------
#if wxUSE_CHOICEDLG
#include <wx/choicdlg.h>
#ifndef __WXPYTHON__
wxPGProperty* wxPG_CONSTFUNC(wxMultiChoiceProperty)(const wxString& label,
const wxString& name,
const wxPGChoices& choices,
const wxArrayInt& value)
{
return new wxPG_PROPCLASS(wxMultiChoiceProperty)(label,name,choices,value);
}
#endif
wxPGProperty* wxPG_CONSTFUNC(wxMultiChoiceProperty)(const wxString& label,
const wxString& name,
const wxArrayString& strings,
const wxArrayInt& value)
{
return new wxPG_PROPCLASS(wxMultiChoiceProperty)(label,name,strings,value);
}
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxBaseProperty,
wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label,
const wxString& name,
const wxPGChoices& choices,
const wxArrayInt& value)
: wxPGProperty(label,name)
{
wxPG_INIT_REQUIRED_TYPE(wxArrayInt)
m_choices.Assign(choices);
SetValueI(value);
}
wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label,
const wxString& name,
const wxArrayString& strings,
const wxArrayInt& value)
: wxPGProperty(label,name)
{
wxPG_INIT_REQUIRED_TYPE(wxArrayInt)
m_choices.Set(strings);
SetValueI(value);
}
wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label,
const wxString& name,
const wxArrayInt& WXUNUSED(value))
: wxPGProperty(label,name)
{
}
wxMultiChoicePropertyClass::~wxMultiChoicePropertyClass()
{
}
void wxMultiChoicePropertyClass::SetValueI( const wxArrayInt& arr )
{
if ( &arr )
{
m_value_wxArrayInt = arr;
GenerateValueAsString();
}
else
{
m_display = wxEmptyString;
}
}
void wxMultiChoicePropertyClass::DoSetValue( wxPGVariant value )
{
#if !wxPG_PGVARIANT_IS_VARIANT
wxArrayInt* pObj = (wxArrayInt*)wxPGVariantToVoidPtr(value);
SetValueI(*pObj);
#else
wxArrayInt arr = wxPGVariantToArrayInt(value);
SetValueI(arr);
#endif
}
wxPGVariant wxMultiChoicePropertyClass::DoGetValue() const
{
return wxPGVariantCreator(m_value_wxArrayInt);
}
wxString wxMultiChoicePropertyClass::GetValueAsString( int ) const
{
return m_display;
}
void wxMultiChoicePropertyClass::GenerateValueAsString()
{
// Allow zero-length strings list
if ( !m_choices.IsOk() || !m_choices.GetCount() )
{
m_display = wxEmptyString;
return;
}
wxString& tempStr = m_display;
wxArrayInt indices = GetValueAsIndices();
unsigned int i;
unsigned int itemCount = indices.GetCount();
tempStr.Empty();
if ( itemCount )
tempStr.append( wxT("\"") );
for ( i = 0; i < itemCount; i++ )
{
int ind = indices.Item(i);
wxCHECK_RET( ind >= 0 && ind < (int)m_choices.GetCount(),
wxT("value out of range") );
tempStr.append( m_choices.GetLabel(ind) );
tempStr.append( wxT("\"") );
if ( i < (itemCount-1) )
tempStr.append ( wxT(" \"") );
}
}
wxArrayInt wxMultiChoicePropertyClass::GetValueAsIndices() const
{
const wxArrayInt& choiceValues = m_choices.GetValues();
if ( choiceValues.GetCount() )
{
// Translate values to string indices.
wxArrayInt selections;
unsigned int i;
for ( i=0; i<m_value_wxArrayInt.GetCount(); i++ )
{
int sIndex = choiceValues.Index(m_value_wxArrayInt[i]);
if ( sIndex >= 0 )
selections.Add(sIndex);
}
return selections;
}
return m_value_wxArrayInt;
}
bool wxMultiChoicePropertyClass::OnEvent( wxPropertyGrid* propgrid,
wxWindow* primary,
wxEvent& event )
{
if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED )
{
// Update the value
PrepareValueForDialogEditing(propgrid);
// launch editor dialog
wxMultiChoiceDialog dlg( propgrid,
_("Make a selection:"),
m_label,
m_choices.GetCount(),
&m_choices.GetLabels()[0],
wxCHOICEDLG_STYLE );
dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
dlg.SetSelections(GetValueAsIndices());
if ( dlg.ShowModal() == wxID_OK )
{
wxArrayInt arrInt = dlg.GetSelections();
const wxArrayInt& choiceValues = m_choices.GetValues();
if ( choiceValues.GetCount() )
{
// Translate string indices to values.
wxArrayInt values;
unsigned int i;
for ( i=0; i<arrInt.GetCount(); i++ )
values.Add(choiceValues.Item(arrInt.Item(i)));
SetValueI( values );
}
else
{
SetValueI( arrInt );
}
UpdateControl( primary );
return true;
}
}
return false;
}
int wxMultiChoicePropertyClass::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
{
if ( choiceinfo )
{
if ( m_choices.IsOk() )
choiceinfo->m_itemCount = m_choices.GetCount();
choiceinfo->m_choices = &m_choices;
}
return -1;
}
bool wxMultiChoicePropertyClass::SetValueFromString( const wxString& text, int )
{
m_value_wxArrayInt.Empty();
const wxArrayString& strings = m_choices.GetLabels();
const wxArrayInt& values = m_choices.GetValues();
WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
int ind = strings.Index( token );
if ( ind != wxNOT_FOUND )
{
if ( values.GetCount() )
ind = values.Item(ind);
m_value_wxArrayInt.Add(ind);
}
WX_PG_TOKENIZER2_END()
GenerateValueAsString();
return true;
}
#endif // wxUSE_CHOICEDLG
// -----------------------------------------------------------------------
// wxDateProperty
// -----------------------------------------------------------------------
#if wxUSE_DATETIME
#if wxUSE_DATEPICKCTRL
#define dtCtrl DatePickerCtrl
#else
#define dtCtrl TextCtrl
#endif
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
wxBaseProperty,
wxDateTime,
const wxDateTime&,
dtCtrl)
wxString wxDatePropertyClass::ms_defaultDateFormat;
wxDatePropertyClass::wxDatePropertyClass( const wxString& label,
const wxString& name,
const wxDateTime& value )
: wxPGProperty(label,name)
{
wxPGRegisterDefaultValueType(wxDateTime)
#if wxUSE_DATEPICKCTRL
wxPGRegisterEditorClass(DatePickerCtrl);
m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
#else
m_dpStyle = 0;
#endif
DoSetValue( value );
}
wxDatePropertyClass::~wxDatePropertyClass()
{
}
void wxDatePropertyClass::DoSetValue( wxPGVariant value )
{
m_valueDateTime = wxPGVariantToDateTime(value);
}
wxPGVariant wxDatePropertyClass::DoGetValue() const
{
return wxPGVariantCreator(m_valueDateTime);
}
bool wxDatePropertyClass::SetValueFromString( const wxString& text,
int WXUNUSED(argFlags) )
{
const wxChar* c = m_valueDateTime.ParseFormat(text.c_str(),wxDefaultDateTimeFormat);
return c ? true : false;
}
wxString wxDatePropertyClass::GetValueAsString( int argFlags ) const
{
const wxChar* format = (const wxChar*) NULL;
if ( !m_valueDateTime.IsValid() )
return wxT("Invalid");
if ( !ms_defaultDateFormat.length() )
{
#if wxUSE_DATEPICKCTRL
bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
#else
bool showCentury = true;
#endif
ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
}
if ( m_format.length() &&
!(argFlags & wxPG_FULL_VALUE) )
format = m_format.c_str();
// Determine default from locale
// NB: This is really simple stuff, but can't figure anything
// better without proper support in wxLocale
if ( !format )
format = ms_defaultDateFormat.c_str();
return m_valueDateTime.Format(format);
}
wxString wxDatePropertyClass::DetermineDefaultDateFormat( bool showCentury )
{
// This code is basicly copied from datectlg.cpp's SetFormat
//
wxString format;
wxDateTime dt;
dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
wxString str(dt.Format(wxT("%x")));
const wxChar *p = str.c_str();
while ( *p )
{
int n=wxAtoi(p);
if (n == dt.GetDay())
{
format.Append(wxT("%d"));
p += 2;
}
else if (n == (int)dt.GetMonth()+1)
{
format.Append(wxT("%m"));
p += 2;
}
else if (n == dt.GetYear())
{
format.Append(wxT("%Y"));
p += 4;
}
else if (n == (dt.GetYear() % 100))
{
if (showCentury)
format.Append(wxT("%Y"));
else
format.Append(wxT("%y"));
p += 2;
}
else
format.Append(*p++);
}
return format;
}
void wxDatePropertyClass::SetAttribute( int id, wxVariant& value )
{
if ( id == wxPG_DATE_FORMAT )
{
m_format = value.GetString();
}
else if ( id == wxPG_DATE_PICKER_STYLE )
{
m_dpStyle = value.GetLong();
ms_defaultDateFormat.clear(); // This may need recalculation
}
}
#endif // wxUSE_DATETIME
// -----------------------------------------------------------------------
// wxPropertyContainerMethods
// -----------------------------------------------------------------------
void wxPropertyContainerMethods::InitAllTypeHandlers()
{
wxPG_INIT_REQUIRED_TYPE(wxColour)
wxPG_INIT_REQUIRED_TYPE(wxFont)
wxPG_INIT_REQUIRED_TYPE(wxArrayInt)
wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue)
#if wxUSE_DATETIME
wxPGRegisterDefaultValueType(wxDateTime)
#endif
}
// -----------------------------------------------------------------------
void wxPropertyContainerMethods::RegisterAdditionalEditors()
{
#if wxUSE_SPINBTN
wxPGRegisterEditorClass(SpinCtrl);
#endif
#if wxUSE_DATEPICKCTRL
wxPGRegisterEditorClass(DatePickerCtrl);
#endif
}
// -----------------------------------------------------------------------
void wxPropertyContainerMethods::RegisterAdvancedPropertyClasses()
{
wxPGRegisterPropertyClass(wxMultiChoiceProperty);
wxPGRegisterPropertyClass(wxImageFileProperty);
wxPGRegisterPropertyClass(wxColourProperty);
wxPGRegisterPropertyClass(wxFontProperty);
wxPGRegisterPropertyClass(wxSystemColourProperty);
wxPGRegisterPropertyClass(wxCursorProperty);
#if wxUSE_DATETIME
wxPGRegisterPropertyClass(wxDateProperty);
#endif
}
// -----------------------------------------------------------------------
#endif // wxPG_INCLUDE_ADVPROPS