]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/advprops.cpp
compilation fix after wxFont changes (closes #10152)
[wxWidgets.git] / src / propgrid / advprops.cpp
CommitLineData
1c4293cb
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/propgrid/advprops.cpp
3// Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.)
4// Author: Jaakko Salli
5// Modified by:
6// Created: 2004-09-25
577972ab 7// RCS-ID: $Id$
1c4293cb
VZ
8// Copyright: (c) Jaakko Salli
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
f4bc1aa2
JS
19#if wxUSE_PROPGRID
20
1c4293cb
VZ
21#ifndef WX_PRECOMP
22 #include "wx/defs.h"
23 #include "wx/object.h"
24 #include "wx/hash.h"
25 #include "wx/string.h"
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/window.h"
29 #include "wx/panel.h"
30 #include "wx/dc.h"
31 #include "wx/dcclient.h"
32 #include "wx/button.h"
33 #include "wx/pen.h"
34 #include "wx/brush.h"
35 #include "wx/cursor.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/choice.h"
40 #include "wx/stattext.h"
41 #include "wx/textctrl.h"
42 #include "wx/scrolwin.h"
43 #include "wx/dirdlg.h"
44 #include "wx/combobox.h"
1c4293cb
VZ
45 #include "wx/sizer.h"
46 #include "wx/textdlg.h"
47 #include "wx/filedlg.h"
48 #include "wx/intl.h"
4b5d2be3 49 #include "wx/wxcrtvararg.h"
1c4293cb
VZ
50#endif
51
52#define __wxPG_SOURCE_FILE__
53
3b211af1 54#include "wx/propgrid/propgrid.h"
1c4293cb
VZ
55
56#if wxPG_INCLUDE_ADVPROPS
57
3b211af1 58#include "wx/propgrid/advprops.h"
1c4293cb
VZ
59
60#ifdef __WXMSW__
3b211af1
SC
61 #include "wx/msw/private.h"
62 #include "wx/msw/dc.h"
1c4293cb
VZ
63#endif
64
65// -----------------------------------------------------------------------
66
67#if defined(__WXMSW__)
68 #define wxPG_CAN_DRAW_CURSOR 1
69#elif defined(__WXGTK__)
70 #define wxPG_CAN_DRAW_CURSOR 0
71#elif defined(__WXMAC__)
72 #define wxPG_CAN_DRAW_CURSOR 0
73#else
74 #define wxPG_CAN_DRAW_CURSOR 0
75#endif
76
77
78// -----------------------------------------------------------------------
79// Value type related
80// -----------------------------------------------------------------------
81
82
1c4293cb
VZ
83// Implement dynamic class for type value.
84IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject)
85
86bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b)
87{
88 return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) );
89}
90
91bool operator == (const wxArrayInt& array1, const wxArrayInt& array2)
92{
93 if ( array1.size() != array2.size() )
94 return false;
95 size_t i;
96 for ( i=0; i<array1.size(); i++ )
97 {
98 if ( array1[i] != array2[i] )
99 return false;
100 }
101 return true;
102}
103
104// -----------------------------------------------------------------------
105// wxSpinCtrl-based property editor
106// -----------------------------------------------------------------------
107
108#if wxUSE_SPINBTN
109
110
52cefafe
JS
111WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl,
112 wxPGSpinCtrlEditor,
113 wxPGEditor)
1c4293cb
VZ
114
115
116// Trivial destructor.
117wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
118{
119}
120
121
122// Create controls and initialize event handling.
123wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
124 const wxPoint& pos, const wxSize& sz ) const
125{
126 const int margin = 1;
127 wxSize butSz(18, sz.y);
128 wxSize tcSz(sz.x - butSz.x - margin, sz.y);
129 wxPoint butPos(pos.x + tcSz.x + margin, pos.y);
130
131 wxSpinButton* wnd2 = new wxSpinButton();
132#ifdef __WXMSW__
133 wnd2->Hide();
134#endif
135 wnd2->Create( propgrid->GetPanel(), wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL );
136
137 wnd2->SetRange( INT_MIN, INT_MAX );
138 wnd2->SetValue( 0 );
139
60f7ea22
JS
140 wxWindowID id = wnd2->GetId();
141 wnd2->Connect( id, wxEVT_SCROLL_LINEUP,
404b9c62 142 wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
60f7ea22
JS
143 NULL, propgrid );
144 wnd2->Connect( id, wxEVT_SCROLL_LINEDOWN,
404b9c62 145 wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
60f7ea22 146 NULL, propgrid );
1c4293cb
VZ
147
148 // Let's add validator to make sure only numbers can be entered
149 wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString);
150
151 wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary;
152 wnd1->SetValidator(validator);
153
60f7ea22 154 wnd1->Connect( wnd1->GetId(), wxEVT_KEY_DOWN,
404b9c62 155 wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
60f7ea22
JS
156 NULL, propgrid );
157
1c4293cb
VZ
158 return wxPGWindowList(wnd1, wnd2);
159}
160
161// Control's events are redirected here
162bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
163 wxWindow* wnd, wxEvent& event ) const
164{
165 int evtType = event.GetEventType();
166 int keycode = -1;
167 bool bigStep = false;
168
169 if ( evtType == wxEVT_KEY_DOWN )
170 {
171 wxKeyEvent& keyEvent = (wxKeyEvent&)event;
172 keycode = keyEvent.GetKeyCode();
173
174 if ( keycode == WXK_UP )
175 evtType = wxEVT_SCROLL_LINEUP;
176 else if ( keycode == WXK_DOWN )
177 evtType = wxEVT_SCROLL_LINEDOWN;
178 else if ( keycode == WXK_PAGEUP )
179 {
180 evtType = wxEVT_SCROLL_LINEUP;
181 bigStep = true;
182 }
183 else if ( keycode == WXK_PAGEDOWN )
184 {
185 evtType = wxEVT_SCROLL_LINEDOWN;
186 bigStep = true;
187 }
188 }
189
190 if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN )
191 {
192 wxString s;
193 // Can't use wnd since it might be clipper window
194 wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl);
195
196 if ( tc )
197 s = tc->GetValue();
198 else
199 s = property->GetValueAsString(wxPG_FULL_VALUE);
200
201 int mode = wxPG_PROPERTY_VALIDATION_SATURATE;
202
203 if ( property->GetAttributeAsLong(wxT("Wrap"), 0) )
204 mode = wxPG_PROPERTY_VALIDATION_WRAP;
205
206 if ( property->GetValueType() == wxT("double") )
207 {
208 double v_d;
209 double step = property->GetAttributeAsDouble(wxT("Step"), 1.0);
210
211 // Try double
212 if ( s.ToDouble(&v_d) )
213 {
214 if ( bigStep )
215 step *= 10.0;
216
217 if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step;
218 else v_d -= step;
219
220 // Min/Max check
221 wxFloatProperty::DoValidation(property, v_d, NULL, mode);
222
223 wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL);
224 }
225 else
226 {
227 return false;
228 }
229 }
230 else
231 {
232 wxLongLong_t v_ll;
233 wxLongLong_t step = property->GetAttributeAsLong(wxT("Step"), 1);
234
235 // Try (long) long
236 if ( s.ToLongLong(&v_ll, 10) )
237 {
238 if ( bigStep )
239 step *= 10;
240
241 if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step;
242 else v_ll -= step;
243
244 // Min/Max check
245 wxIntProperty::DoValidation(property, v_ll, NULL, mode);
246
247 s = wxLongLong(v_ll).ToString();
248 }
249 else
250 {
251 return false;
252 }
253 }
254
255 if ( tc )
256 {
257 int ip = tc->GetInsertionPoint();
258 int lp = tc->GetLastPosition();
259 tc->SetValue(s);
260 tc->SetInsertionPoint(ip+(tc->GetLastPosition()-lp));
261 }
262
263 return true;
264 }
265
266 return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event);
267}
268
269#endif // wxUSE_SPINBTN
270
271
272// -----------------------------------------------------------------------
273// wxDatePickerCtrl-based property editor
274// -----------------------------------------------------------------------
275
276#if wxUSE_DATEPICKCTRL
277
278
3b211af1
SC
279#include "wx/datectrl.h"
280#include "wx/dateevt.h"
1c4293cb
VZ
281
282class wxPGDatePickerCtrlEditor : public wxPGEditor
283{
52cefafe 284 DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor)
1c4293cb
VZ
285public:
286 virtual ~wxPGDatePickerCtrlEditor();
287
52cefafe
JS
288 wxString GetName() const;
289 virtual wxPGWindowList CreateControls(wxPropertyGrid* propgrid,
290 wxPGProperty* property,
291 const wxPoint& pos,
292 const wxSize& size) const;
1c4293cb
VZ
293 virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const;
294 virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
295 wxWindow* wnd, wxEvent& event ) const;
296 virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* wnd ) const;
297 virtual void SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const;
298};
299
300
52cefafe
JS
301WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl,
302 wxPGDatePickerCtrlEditor,
303 wxPGEditor)
1c4293cb
VZ
304
305
306wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
307{
308}
309
310wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
311 wxPGProperty* property,
312 const wxPoint& pos,
313 const wxSize& sz ) const
314{
315 wxCHECK_MSG( property->IsKindOf(CLASSINFO(wxDateProperty)),
316 NULL,
317 wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
318
319 wxDateProperty* prop = (wxDateProperty*) property;
320
321 // Use two stage creation to allow cleaner display on wxMSW
322 wxDatePickerCtrl* ctrl = new wxDatePickerCtrl();
323#ifdef __WXMSW__
324 ctrl->Hide();
325 wxSize useSz = wxDefaultSize;
326 useSz.x = sz.x;
327#else
328 wxSize useSz = sz;
329#endif
330 ctrl->Create(propgrid->GetPanel(),
331 wxPG_SUBID1,
332 prop->GetDateValue(),
333 pos,
334 useSz,
335 prop->GetDatePickerStyle() | wxNO_BORDER);
336
337 // Connect all required events to grid's OnCustomEditorEvent
338 // (all relevenat wxTextCtrl, wxComboBox and wxButton events are
339 // already connected)
60f7ea22 340 ctrl->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED,
404b9c62 341 wxEventHandler(wxPropertyGrid::OnCustomEditorEvent),
60f7ea22 342 NULL, propgrid );
1c4293cb
VZ
343
344#ifdef __WXMSW__
345 ctrl->Show();
346#endif
347
348 return ctrl;
349}
350
351// Copies value from property to control
352void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* wnd ) const
353{
354 wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
355 wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
356
357 // We assume that property's data type is 'int' (or something similar),
358 // thus allowing us to get raw, unchecked value via DoGetValue.
359 ctrl->SetValue( property->GetValue().GetDateTime() );
360}
361
362// Control's events are redirected here
363bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid),
364 wxPGProperty* WXUNUSED(property),
365 wxWindow* WXUNUSED(wnd),
366 wxEvent& event ) const
367{
368 if ( event.GetEventType() == wxEVT_DATE_CHANGED )
369 return true;
370
371 return false;
372}
373
374bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const
375{
376 wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
377 wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
378
379 variant = ctrl->GetValue();
380
381 return true;
382}
383
384void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd) ) const
385{
386 // TODO?
387 //wxDateProperty* prop = (wxDateProperty*) property;
388 //ctrl->SetValue(?);
389}
390
391#endif // wxUSE_DATEPICKCTRL
392
393
394// -----------------------------------------------------------------------
395// wxFontProperty
396// -----------------------------------------------------------------------
397
3b211af1
SC
398#include "wx/fontdlg.h"
399#include "wx/fontenum.h"
1c4293cb
VZ
400
401static const wxChar* gs_fp_es_family_labels[] = {
402 wxT("Default"), wxT("Decorative"),
403 wxT("Roman"), wxT("Script"),
404 wxT("Swiss"), wxT("Modern"),
405 (const wxChar*) NULL
406};
407
408static long gs_fp_es_family_values[] = {
409 wxDEFAULT, wxDECORATIVE,
410 wxROMAN, wxSCRIPT,
411 wxSWISS, wxMODERN
412};
413
414static const wxChar* gs_fp_es_style_labels[] = {
415 wxT("Normal"),
416 wxT("Slant"),
417 wxT("Italic"),
418 (const wxChar*) NULL
419};
420
421static long gs_fp_es_style_values[] = {
422 wxNORMAL,
423 wxSLANT,
424 wxITALIC
425};
426
427static const wxChar* gs_fp_es_weight_labels[] = {
428 wxT("Normal"),
429 wxT("Light"),
430 wxT("Bold"),
431 (const wxChar*) NULL
432};
433
434static long gs_fp_es_weight_values[] = {
435 wxNORMAL,
436 wxLIGHT,
437 wxBOLD
438};
439
440// Class body is in advprops.h
441
442
443WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,
444 wxFont,const wxFont&,TextCtrlAndButton)
445
446
447wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
448 const wxFont& value )
449 : wxPGProperty(label,name)
450{
0372d42e 451 SetValue(WXVARIANT(value));
1c4293cb
VZ
452
453 // Initialize font family choices list
454 if ( !wxPGGlobalVars->m_fontFamilyChoices )
455 {
456 wxFontEnumerator enumerator;
457 enumerator.EnumerateFacenames();
458
459#if wxMINOR_VERSION > 6
460 wxArrayString faceNames = enumerator.GetFacenames();
461#else
462 wxArrayString& faceNames = *enumerator.GetFacenames();
463#endif
464
465 faceNames.Sort();
466
467 wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
468 }
469
470 wxString emptyString(wxEmptyString);
471
0372d42e
JS
472 wxFont font;
473 font << m_value;
1c4293cb 474
2fd4a524
JS
475 SetParentalType(wxPG_PROP_AGGREGATE);
476
d665918b 477 AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font.GetPointSize() ) );
1c4293cb 478
d665918b 479 AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
1c4293cb
VZ
480 gs_fp_es_family_labels,gs_fp_es_family_values,
481 font.GetFamily()) );
482
483 wxString faceName = font.GetFaceName();
484 // If font was not in there, add it now
485 if ( faceName.length() &&
486 wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
487 wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
488
d665918b 489 wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"),
1c4293cb
VZ
490 *wxPGGlobalVars->m_fontFamilyChoices);
491
492 p->SetValueFromString(faceName, wxPG_FULL_VALUE);
493
494 AddChild( p );
495
d665918b 496 AddChild( new wxEnumProperty(_("Style"), wxS("Style"),
1c4293cb
VZ
497 gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) );
498
d665918b 499 AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
1c4293cb
VZ
500 gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) );
501
d665918b 502 AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
1c4293cb
VZ
503 font.GetUnderlined()) );
504}
505
506wxFontProperty::~wxFontProperty() { }
507
508void wxFontProperty::OnSetValue()
509{
0372d42e
JS
510 wxFont font;
511 font << m_value;
1c4293cb 512
1c4293cb 513 if ( !font.Ok() )
0372d42e
JS
514 {
515 font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
516 m_value << font;
517 }
1c4293cb
VZ
518}
519
1425eca5
JS
520wxString wxFontProperty::ValueToString( wxVariant& value,
521 int argFlags ) const
1c4293cb 522{
1425eca5 523 return wxPGProperty::ValueToString(value, argFlags);
1c4293cb
VZ
524}
525
526bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
527 wxEvent& event )
528{
529 if ( propgrid->IsMainButtonEvent(event) )
530 {
531 // Update value from last minute changes
703ee9f5 532 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
533
534 wxFontData data;
0372d42e 535 wxFont font;
9b5bafcf 536 font << useValue;
0372d42e 537 data.SetInitialFont( font );
1c4293cb
VZ
538 data.SetColour(*wxBLACK);
539
540 wxFontDialog dlg(propgrid, data);
541 if ( dlg.ShowModal() == wxID_OK )
542 {
543 propgrid->EditorsValueWasModified();
544
0372d42e
JS
545 wxVariant variant;
546 variant << dlg.GetFontData().GetChosenFont();
1c4293cb
VZ
547 SetValueInEvent( variant );
548 return true;
549 }
550 }
551 return false;
552}
553
554void wxFontProperty::RefreshChildren()
555{
556 if ( !GetChildCount() ) return;
0372d42e
JS
557 wxFont font;
558 font << m_value;
1c4293cb
VZ
559 Item(0)->SetValue( (long)font.GetPointSize() );
560 Item(1)->SetValue( (long)font.GetFamily() );
561 Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
562 Item(3)->SetValue( (long)font.GetStyle() );
563 Item(4)->SetValue( (long)font.GetWeight() );
564 Item(5)->SetValue( font.GetUnderlined() );
565}
566
567void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
568{
0372d42e
JS
569 wxFont font;
570 font << thisValue;
1c4293cb
VZ
571
572 if ( ind == 0 )
573 {
574 font.SetPointSize( wxPGVariantToInt(childValue) );
575 }
576 else if ( ind == 1 )
577 {
578 int fam = childValue.GetLong();
579 if ( fam < wxDEFAULT ||
580 fam > wxTELETYPE )
581 fam = wxDEFAULT;
582 font.SetFamily( fam );
583 }
584 else if ( ind == 2 )
585 {
586 wxString faceName;
587 int faceIndex = childValue.GetLong();
588
589 if ( faceIndex >= 0 )
590 faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
591
592 font.SetFaceName( faceName );
593 }
594 else if ( ind == 3 )
595 {
596 int st = childValue.GetLong();
597 if ( st != wxFONTSTYLE_NORMAL &&
598 st != wxFONTSTYLE_SLANT &&
599 st != wxFONTSTYLE_ITALIC )
600 st = wxFONTWEIGHT_NORMAL;
601 font.SetStyle( st );
602 }
603 else if ( ind == 4 )
604 {
605 int wt = childValue.GetLong();
606 if ( wt != wxFONTWEIGHT_NORMAL &&
607 wt != wxFONTWEIGHT_LIGHT &&
608 wt != wxFONTWEIGHT_BOLD )
609 wt = wxFONTWEIGHT_NORMAL;
610 font.SetWeight( wt );
611 }
612 else if ( ind == 5 )
613 {
614 font.SetUnderlined( childValue.GetBool() );
615 }
0372d42e
JS
616
617 thisValue << font;
1c4293cb
VZ
618}
619
620/*
621wxSize wxFontProperty::OnMeasureImage() const
622{
623 return wxSize(-1,-1);
624}
625
626void wxFontProperty::OnCustomPaint(wxDC& dc,
627 const wxRect& rect,
628 wxPGPaintData& paintData)
629{
630 wxString drawFace;
631 if ( paintData.m_choiceItem >= 0 )
632 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
633 else
634 drawFace = m_value_wxFont.GetFaceName();
635
636 if ( drawFace.length() )
637 {
638 // Draw the background
639 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
640 //dc.SetBrush( *wxWHITE_BRUSH );
641 //dc.SetPen( *wxMEDIUM_GREY_PEN );
642 dc.DrawRectangle( rect );
643
644 wxFont oldFont = dc.GetFont();
645 wxFont drawFont(oldFont.GetPointSize(),
646 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
647 dc.SetFont(drawFont);
648
649 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
650 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
651
652 dc.SetFont(oldFont);
653 }
654 else
655 {
656 // No file - just draw a white box
657 dc.SetBrush ( *wxWHITE_BRUSH );
658 dc.DrawRectangle ( rect );
659 }
660}
661*/
662
663
664// -----------------------------------------------------------------------
665// wxSystemColourProperty
666// -----------------------------------------------------------------------
667
668// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
669#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
670
3b211af1 671#include "wx/colordlg.h"
1c4293cb
VZ
672
673//#define wx_cp_es_syscolours_len 25
674static const wxChar* gs_cp_es_syscolour_labels[] = {
675 wxT("AppWorkspace"),
676 wxT("ActiveBorder"),
677 wxT("ActiveCaption"),
678 wxT("ButtonFace"),
679 wxT("ButtonHighlight"),
680 wxT("ButtonShadow"),
681 wxT("ButtonText"),
682 wxT("CaptionText"),
683 wxT("ControlDark"),
684 wxT("ControlLight"),
685 wxT("Desktop"),
686 wxT("GrayText"),
687 wxT("Highlight"),
688 wxT("HighlightText"),
689 wxT("InactiveBorder"),
690 wxT("InactiveCaption"),
691 wxT("InactiveCaptionText"),
692 wxT("Menu"),
693 wxT("Scrollbar"),
694 wxT("Tooltip"),
695 wxT("TooltipText"),
696 wxT("Window"),
697 wxT("WindowFrame"),
698 wxT("WindowText"),
699 wxT("Custom"),
700 (const wxChar*) NULL
701};
702
703static long gs_cp_es_syscolour_values[] = {
704 wxSYS_COLOUR_APPWORKSPACE,
705 wxSYS_COLOUR_ACTIVEBORDER,
706 wxSYS_COLOUR_ACTIVECAPTION,
707 wxSYS_COLOUR_BTNFACE,
708 wxSYS_COLOUR_BTNHIGHLIGHT,
709 wxSYS_COLOUR_BTNSHADOW,
710 wxSYS_COLOUR_BTNTEXT ,
711 wxSYS_COLOUR_CAPTIONTEXT,
712 wxSYS_COLOUR_3DDKSHADOW,
713 wxSYS_COLOUR_3DLIGHT,
714 wxSYS_COLOUR_BACKGROUND,
715 wxSYS_COLOUR_GRAYTEXT,
716 wxSYS_COLOUR_HIGHLIGHT,
717 wxSYS_COLOUR_HIGHLIGHTTEXT,
718 wxSYS_COLOUR_INACTIVEBORDER,
719 wxSYS_COLOUR_INACTIVECAPTION,
720 wxSYS_COLOUR_INACTIVECAPTIONTEXT,
721 wxSYS_COLOUR_MENU,
722 wxSYS_COLOUR_SCROLLBAR,
723 wxSYS_COLOUR_INFOBK,
724 wxSYS_COLOUR_INFOTEXT,
725 wxSYS_COLOUR_WINDOW,
726 wxSYS_COLOUR_WINDOWFRAME,
727 wxSYS_COLOUR_WINDOWTEXT,
728 wxPG_COLOUR_CUSTOM
729};
730
731
0372d42e 732IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
1c4293cb
VZ
733
734
735// Class body is in advprops.h
736
737WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
738 wxColourPropertyValue,const wxColourPropertyValue&,Choice)
739
740
741void wxSystemColourProperty::Init( int type, const wxColour& colour )
742{
743 wxColourPropertyValue cpv;
744
745 if ( colour.Ok() )
746 cpv.Init( type, colour );
747 else
748 cpv.Init( type, *wxWHITE );
749
750 m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
751
0372d42e 752 m_value << cpv;
1c4293cb
VZ
753
754 OnSetValue();
755}
756
757
758static wxPGChoices gs_wxSystemColourProperty_choicesCache;
759
760
761wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
762 const wxColourPropertyValue& value )
763 : wxEnumProperty( label,
764 name,
765 gs_cp_es_syscolour_labels,
766 gs_cp_es_syscolour_values,
767 &gs_wxSystemColourProperty_choicesCache )
768{
769 if ( &value )
770 Init( value.m_type, value.m_colour );
771 else
772 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
773}
774
775
776wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
777 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
778 const wxColourPropertyValue& value )
779 : wxEnumProperty( label, name, labels, values, choicesCache )
780{
781 if ( &value )
782 Init( value.m_type, value.m_colour );
783 else
784 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
785}
786
787
788wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
789 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
790 const wxColour& value )
791 : wxEnumProperty( label, name, labels, values, choicesCache )
792{
793 if ( &value )
794 Init( wxPG_COLOUR_CUSTOM, value );
795 else
796 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
797}
798
799
800wxSystemColourProperty::~wxSystemColourProperty() { }
801
802
803wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
804{
805 if ( !pVariant )
806 pVariant = &m_value;
807
808 if ( pVariant->IsNull() )
809 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
810
0372d42e
JS
811 if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
812 {
813 wxColourPropertyValue v;
814 v << *pVariant;
815 return v;
816 }
1c4293cb 817
1c4293cb
VZ
818 wxColour col;
819 bool variantProcessed = true;
820
0372d42e 821 if ( pVariant->GetType() == wxS("wxColour*") )
1c4293cb 822 {
0372d42e 823 wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
1c4293cb
VZ
824 col = *pCol;
825 }
0372d42e 826 else if ( pVariant->GetType() == wxS("wxColour") )
1c4293cb 827 {
0372d42e
JS
828 col << *pVariant;
829 }
830 else if ( pVariant->GetType() == wxArrayInt_VariantType )
831 {
832 // This code is mostly needed for wxPython bindings, which
833 // may offer tuple of integers as colour value.
1c4293cb
VZ
834 wxArrayInt arr;
835 arr << *pVariant;
836
837 if ( arr.size() >= 3 )
838 {
839 int r, g, b;
840 int a = 255;
841
842 r = arr[0];
843 g = arr[1];
844 b = arr[2];
845 if ( arr.size() >= 4 )
846 a = arr[3];
847
848 col = wxColour(r, g, b, a);
849 }
850 else
851 {
852 variantProcessed = false;
853 }
854 }
1c4293cb
VZ
855 else
856 {
857 variantProcessed = false;
858 }
859
860 if ( !variantProcessed )
861 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
862
863 wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
864
865 int colInd = ColToInd(col);
866 if ( colInd != wxNOT_FOUND )
867 v2.m_type = colInd;
868
869 return v2;
870}
871
872wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
873{
0372d42e
JS
874 wxVariant variant;
875 variant << v;
876 return variant;
1c4293cb
VZ
877}
878
879int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
880{
881 size_t i;
882 size_t i_max = m_choices.GetCount() - 1;
883
884 for ( i=0; i<i_max; i++ )
885 {
886 int ind = m_choices[i].GetValue();
887
888 if ( colour == GetColour(ind) )
889 {
890 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
891 GetClassName(),GetLabel().c_str(),
892 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
893 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
894 return ind;
895 }
896 }
897 return wxNOT_FOUND;
898}
899
900
901static inline wxColour wxColourFromPGLong( long col )
902{
903 return wxColour((col&0xFF),((col>>8)&0xFF),((col>>16)&0xFF));
904}
905
906
907void wxSystemColourProperty::OnSetValue()
908{
909 // Convert from generic wxobject ptr to wxPGVariantDataColour
0372d42e 910 if ( m_value.GetType() == wxS("wxColour*") )
1c4293cb 911 {
0372d42e 912 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
1c4293cb
VZ
913 m_value << *pCol;
914 }
915
916 wxColourPropertyValue val = GetVal(&m_value);
917
918 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
919 {
920 m_value.MakeNull();
921 return;
922 }
923 else
924 {
925
926 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
927 val.m_colour = GetColour( val.m_type );
928
929 m_value = TranslateVal(val);
930 }
931
b0f0eda8 932 int ind = wxNOT_FOUND;
1c4293cb 933
0372d42e 934 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
1c4293cb 935 {
0372d42e
JS
936 wxColourPropertyValue cpv;
937 cpv << m_value;
938 wxColour col = cpv.m_colour;
1c4293cb 939
0372d42e
JS
940 if ( !col.Ok() )
941 {
942 SetValueToUnspecified();
943 SetIndex(wxNOT_FOUND);
944 return;
945 }
1c4293cb 946
0372d42e 947 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
1c4293cb 948 {
98c04633 949 ind = GetIndexForValue(cpv.m_type);
1c4293cb
VZ
950 }
951 else
952 {
0372d42e 953 cpv.m_type = wxPG_COLOUR_CUSTOM;
1c4293cb
VZ
954 ind = GetCustomColourIndex();
955 }
956 }
957 else
958 {
0372d42e
JS
959 wxColour col;
960 col << m_value;
961
962 if ( !col.Ok() )
963 {
964 SetValueToUnspecified();
965 SetIndex(wxNOT_FOUND);
966 return;
967 }
968
1c4293cb
VZ
969 ind = ColToInd(col);
970
971 if ( ind == wxNOT_FOUND )
972 ind = GetCustomColourIndex();
973 }
974
975 SetIndex(ind);
976}
977
978
979wxColour wxSystemColourProperty::GetColour( int index ) const
980{
981 return wxSystemSettings::GetColour( (wxSystemColour)index );
982}
983
984wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
985{
986 if ( index == wxNOT_FOUND )
987 return wxString::Format(wxT("(%i,%i,%i)"),
988 (int)col.Red(),
989 (int)col.Green(),
990 (int)col.Blue());
991 else
992 return m_choices.GetLabel(index);
993}
994
1425eca5 995wxString wxSystemColourProperty::ValueToString( wxVariant& value,
c9049646 996 int argFlags ) const
1c4293cb 997{
1425eca5 998 wxColourPropertyValue val = GetVal(&value);
1c4293cb 999
c9049646
JS
1000 int index;
1001
1002 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1003 {
1004 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1005 // but we should use it whenever possible.
1006 index = GetIndex();
1007
1008 // If custom colour was selected, use invalid index, so that
1009 // ColourToString() will return properly formatted colour text.
1010 if ( index == GetCustomColourIndex() )
1011 index = wxNOT_FOUND;
1012 }
1013 else
1014 {
1015 index = m_choices.Index(val.m_type);
1016 }
1017
1018 return ColourToString(val.m_colour, index);
1c4293cb
VZ
1019}
1020
1021
1022wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1023{
1024 return wxPG_DEFAULT_IMAGE_SIZE;
1025}
1026
1027
1028int wxSystemColourProperty::GetCustomColourIndex() const
1029{
1030 return m_choices.GetCount() - 1;
1031}
1032
1033
1034bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1035{
0372d42e 1036 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1c4293cb
VZ
1037 bool res = false;
1038
1039 wxPropertyGrid* propgrid = GetGrid();
1040 wxASSERT( propgrid );
1041
1042 // Must only occur when user triggers event
1043 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) )
1044 return res;
1045
1046 wxColourPropertyValue val = GetVal();
1047
1048 val.m_type = wxPG_COLOUR_CUSTOM;
1049
1050 wxColourData data;
1051 data.SetChooseFull(true);
1052 data.SetColour(val.m_colour);
1053 int i;
1054 for ( i = 0; i < 16; i++)
1055 {
1056 wxColour colour(i*16, i*16, i*16);
1057 data.SetCustomColour(i, colour);
1058 }
1059
1060 wxColourDialog dialog(propgrid, &data);
1061 if ( dialog.ShowModal() == wxID_OK )
1062 {
1063 wxColourData retData = dialog.GetColourData();
1064 val.m_colour = retData.GetColour();
1065
1066 variant = DoTranslateVal(val);
1067
1068 SetValueInEvent(variant);
1069
1070 res = true;
1071 }
1072
1073 return res;
1074}
1075
1076
1077bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1078{
1079 int index = number;
78f2d746 1080 int type = m_choices.GetValue(index);
1c4293cb 1081
98c04633 1082 if ( type == wxPG_COLOUR_CUSTOM )
1c4293cb
VZ
1083 {
1084 QueryColourFromUser(variant);
1085 }
1086 else
1087 {
1088 variant = TranslateVal( type, GetColour(type) );
1089 }
1090
1091 return true;
1092}
1093
1094// Need to do some extra event handling.
1095bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event )
1096{
1097 if ( propgrid->IsMainButtonEvent(event) )
1098 {
1099 // We need to handle button click in case editor has been
1100 // switched to one that has wxButton as well.
1101 wxVariant variant;
1102 if ( QueryColourFromUser(variant) )
1103 return true;
1104 }
1105 return false;
1106}
1107
1108/*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1109{
1110public:
1111 virtual void Render( wxDC& dc, const wxRect& rect,
1112 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1113 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1114 {
1115 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1116 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1117
1118 dc.SetPen(*wxBLACK_PEN);
1119 if ( item >= 0 &&
1120 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1121 )
1122 {
1123 int colInd;
1124 const wxArrayInt& values = prop->GetValues();
1125 if ( values.GetChildCount() )
1126 colInd = values[item];
1127 else
1128 colInd = item;
1129 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1130 }
1131 else if ( !prop->IsValueUnspecified() )
1132 dc.SetBrush( prop->GetVal().m_colour );
1133 else
1134 dc.SetBrush( *wxWHITE );
1135
1136 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1137 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1138 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1139 imageRect.width, imageRect.height );
1140
1141 wxString text;
1142 if ( item == -1 )
1143 text = property->GetValueAsString();
1144 else
1145 text = property->GetChoiceString(item);
1146 DrawText( dc, rect, imageRect.width, text );
1147 }
1148protected:
1149};
1150
1151wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1152
1153wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1154{
1155 if ( column == 1 )
1156 return &g_wxPGColourPropertyRenderer;
1157 return wxEnumProperty::GetCellRenderer(column);
1158}*/
1159
1160void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1161 wxPGPaintData& paintdata )
1162{
1163 wxColour col;
1164
1165 if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1166 paintdata.m_choiceItem != GetCustomColourIndex() )
1167 {
1168 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1169 col = GetColour( colInd );
1170 }
1171 else if ( !IsValueUnspecified() )
1172 {
1173 col = GetVal().m_colour;
1174 }
1175
1176 if ( col.Ok() )
1177 {
1178 dc.SetBrush(col);
1179 dc.DrawRectangle(rect);
1180 }
1181}
1182
1183
1184bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1185{
1186 //
1187 // Accept colour format "[Name] [(R,G,B)]"
1188 // Name takes precedence.
1189 //
1190 wxString colourName;
1191 wxString colourRGB;
1192
1193 int ppos = text.Find(wxT("("));
1194
1195 if ( ppos == wxNOT_FOUND )
1196 {
1197 colourName = text;
1198 }
1199 else
1200 {
1201 colourName = text.substr(0, ppos);
1202 colourRGB = text.substr(ppos, text.length()-ppos);
1203 }
1204
1205 // Strip spaces from extremities
1206 colourName.Trim(true);
1207 colourName.Trim(false);
1208 colourRGB.Trim(true);
1209
1210 // Validate colourRGB string - (1,1,1) is shortest allowed
1211 if ( colourRGB.length() < 7 )
1212 colourRGB.clear();
1213
1214 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
1215 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1216 {
1217 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1218 {
1219 // This really should not occurr...
1220 // wxASSERT(false);
1221 ResetNextIndex();
1222 return false;
1223 }
1224
1225 QueryColourFromUser(value);
1226 }
1227 else
1228 {
1229 wxColourPropertyValue val;
1230
1231 bool done = false;
1232
1233 if ( colourName.length() )
1234 {
1235 // Try predefined colour first
1236 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1237 if ( res && GetIndex() >= 0 )
1238 {
1239 val.m_type = GetIndex();
98c04633 1240 if ( val.m_type >= 0 && val.m_type < m_choices.GetCount() )
1c4293cb
VZ
1241 val.m_type = m_choices[val.m_type].GetValue();
1242
1243 // Get proper colour for type.
1244 val.m_colour = GetColour(val.m_type);
1245
1246 done = true;
1247 }
1248 }
1249 if ( colourRGB.length() && !done )
1250 {
1251 // Then check custom colour.
1252 val.m_type = wxPG_COLOUR_CUSTOM;
1253
1254 int r = -1, g = -1, b = -1;
1255 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1256
1257 if ( r >= 0 && r <= 255 &&
1258 g >= 0 && g <= 255 &&
1259 b >= 0 && b <= 255 )
1260 {
1261 val.m_colour.Set(r,g,b);
1262
1263 done = true;
1264 }
1265 }
1266
1267 if ( !done )
1268 {
1269 ResetNextIndex();
1270 return false;
1271 }
1272
1273 value = DoTranslateVal(val);
1274 }
1275
1276 return true;
1277}
1278
1279
1280bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1281{
1282 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1283 {
1284 int ival = wxPGVariantToInt(value);
1285
1286 SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
1287
1288 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1289 {
1290 // Show custom choice
1291 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1292 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1293 }
1294 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1295 {
1296 // Hide custom choice
1297 m_choices.RemoveAt(GetCustomColourIndex());
1298 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1299 }
1300 return true;
1301 }
1302 return false;
1303}
1304
1305
1306// -----------------------------------------------------------------------
1307// wxColourProperty
1308// -----------------------------------------------------------------------
1309
1310static const wxChar* gs_cp_es_normcolour_labels[] = {
1311 wxT("Black"),
1312 wxT("Maroon"),
1313 wxT("Navy"),
1314 wxT("Purple"),
1315 wxT("Teal"),
1316 wxT("Gray"),
1317 wxT("Green"),
1318 wxT("Olive"),
1319 wxT("Brown"),
1320 wxT("Blue"),
1321 wxT("Fuchsia"),
1322 wxT("Red"),
1323 wxT("Orange"),
1324 wxT("Silver"),
1325 wxT("Lime"),
1326 wxT("Aqua"),
1327 wxT("Yellow"),
1328 wxT("White"),
1329 wxT("Custom"),
1330 (const wxChar*) NULL
1331};
1332
1333static unsigned long gs_cp_es_normcolour_colours[] = {
1334 wxPG_COLOUR(0,0,0),
1335 wxPG_COLOUR(128,0,0),
1336 wxPG_COLOUR(0,0,128),
1337 wxPG_COLOUR(128,0,128),
1338 wxPG_COLOUR(0,128,128),
1339 wxPG_COLOUR(128,128,128),
1340 wxPG_COLOUR(0,128,0),
1341 wxPG_COLOUR(128,128,0),
1342 wxPG_COLOUR(166,124,81),
1343 wxPG_COLOUR(0,0,255),
1344 wxPG_COLOUR(255,0,255),
1345 wxPG_COLOUR(255,0,0),
1346 wxPG_COLOUR(247,148,28),
1347 wxPG_COLOUR(192,192,192),
1348 wxPG_COLOUR(0,255,0),
1349 wxPG_COLOUR(0,255,255),
1350 wxPG_COLOUR(255,255,0),
1351 wxPG_COLOUR(255,255,255),
1352 wxPG_COLOUR(0,0,0)
1353};
1354
d61d8cff
JS
1355WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1356 wxColour, const wxColour&, TextCtrlAndButton)
1357
1358static wxPGChoices gs_wxColourProperty_choicesCache;
1359
1360wxColourProperty::wxColourProperty( const wxString& label,
1361 const wxString& name,
1362 const wxColour& value )
1363 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1364 NULL,
1365 &gs_wxColourProperty_choicesCache, value )
1366{
1367 Init( value );
1368
1369 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1370}
1371
1372wxColourProperty::~wxColourProperty()
1373{
1374}
1375
1376void wxColourProperty::Init( wxColour colour )
1377{
1378 if ( !colour.Ok() )
1379 colour = *wxWHITE;
1380 wxVariant variant;
1381 variant << colour;
1382 m_value = variant;
1383 int ind = ColToInd(colour);
1384 if ( ind < 0 )
1385 ind = m_choices.GetCount() - 1;
1386 SetIndex( ind );
1387}
1388
1425eca5
JS
1389wxString wxColourProperty::ValueToString( wxVariant& value,
1390 int argFlags ) const
d61d8cff
JS
1391{
1392 const wxPGEditor* editor = GetEditorClass();
1393 if ( editor != wxPGEditor_Choice &&
1394 editor != wxPGEditor_ChoiceAndButton &&
1395 editor != wxPGEditor_ComboBox )
1396 argFlags |= wxPG_PROPERTY_SPECIFIC;
1397
1425eca5 1398 return wxSystemColourProperty::ValueToString(value, argFlags);
d61d8cff
JS
1399}
1400
1401wxColour wxColourProperty::GetColour( int index ) const
1402{
d61d8cff
JS
1403 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1404}
1405
1406wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1407{
1408 wxVariant variant;
1409 variant << v.m_colour;
1410 return variant;
1411}
1c4293cb
VZ
1412
1413// -----------------------------------------------------------------------
1414// wxCursorProperty
1415// -----------------------------------------------------------------------
1416
1417#define wxPG_CURSOR_IMAGE_WIDTH 32
1418
1419#define NUM_CURSORS 28
1420
1421//#define wx_cp_es_syscursors_len 28
1422static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1423 wxT("Default"),
1424 wxT("Arrow"),
1425 wxT("Right Arrow"),
1426 wxT("Blank"),
1427 wxT("Bullseye"),
1428 wxT("Character"),
1429 wxT("Cross"),
1430 wxT("Hand"),
1431 wxT("I-Beam"),
1432 wxT("Left Button"),
1433 wxT("Magnifier"),
1434 wxT("Middle Button"),
1435 wxT("No Entry"),
1436 wxT("Paint Brush"),
1437 wxT("Pencil"),
1438 wxT("Point Left"),
1439 wxT("Point Right"),
1440 wxT("Question Arrow"),
1441 wxT("Right Button"),
1442 wxT("Sizing NE-SW"),
1443 wxT("Sizing N-S"),
1444 wxT("Sizing NW-SE"),
1445 wxT("Sizing W-E"),
1446 wxT("Sizing"),
1447 wxT("Spraycan"),
1448 wxT("Wait"),
1449 wxT("Watch"),
1450 wxT("Wait Arrow"),
1451 (const wxChar*) NULL
1452};
1453
1454static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1455 wxCURSOR_NONE,
1456 wxCURSOR_ARROW,
1457 wxCURSOR_RIGHT_ARROW,
1458 wxCURSOR_BLANK,
1459 wxCURSOR_BULLSEYE,
1460 wxCURSOR_CHAR,
1461 wxCURSOR_CROSS,
1462 wxCURSOR_HAND,
1463 wxCURSOR_IBEAM,
1464 wxCURSOR_LEFT_BUTTON,
1465 wxCURSOR_MAGNIFIER,
1466 wxCURSOR_MIDDLE_BUTTON,
1467 wxCURSOR_NO_ENTRY,
1468 wxCURSOR_PAINT_BRUSH,
1469 wxCURSOR_PENCIL,
1470 wxCURSOR_POINT_LEFT,
1471 wxCURSOR_POINT_RIGHT,
1472 wxCURSOR_QUESTION_ARROW,
1473 wxCURSOR_RIGHT_BUTTON,
1474 wxCURSOR_SIZENESW,
1475 wxCURSOR_SIZENS,
1476 wxCURSOR_SIZENWSE,
1477 wxCURSOR_SIZEWE,
1478 wxCURSOR_SIZING,
1479 wxCURSOR_SPRAYCAN,
1480 wxCURSOR_WAIT,
1481 wxCURSOR_WATCH,
1482 wxCURSOR_ARROWWAIT
1483};
1484
1485IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1486
1487wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1488 int value )
1489 : wxEnumProperty( label,
1490 name,
1491 gs_cp_es_syscursors_labels,
1492 gs_cp_es_syscursors_values,
1493 value )
1494{
1495 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1496}
1497
1498wxCursorProperty::~wxCursorProperty()
1499{
1500}
1501
1502wxSize wxCursorProperty::OnMeasureImage( int item ) const
1503{
1504#if wxPG_CAN_DRAW_CURSOR
1505 if ( item != -1 && item < NUM_CURSORS )
1506 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1507#else
1508 wxUnusedVar(item);
1509#endif
1510 return wxSize(0,0);
1511}
1512
1513#if wxPG_CAN_DRAW_CURSOR
1514
1515void wxCursorProperty::OnCustomPaint( wxDC& dc,
1516 const wxRect& rect,
1517 wxPGPaintData& paintdata )
1518{
1519 // Background brush
1520 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1521
1522 if ( paintdata.m_choiceItem >= 0 )
1523 {
1524 dc.DrawRectangle( rect );
1525
1526 if ( paintdata.m_choiceItem < NUM_CURSORS )
1527 {
2399c87c
JS
1528 wxStockCursor cursorIndex =
1529 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1c4293cb
VZ
1530
1531 {
2399c87c
JS
1532 if ( cursorIndex == wxCURSOR_NONE )
1533 cursorIndex = wxCURSOR_ARROW;
1c4293cb 1534
2399c87c 1535 wxCursor cursor( cursorIndex );
1c4293cb
VZ
1536
1537 #ifdef __WXMSW__
1538 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1539 ::DrawIconEx( hDc,
1540 rect.x,
1541 rect.y,
1542 (HICON)cursor.GetHandle(),
1543 0,
1544 0,
1545 0,
1546 NULL,
1547 DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL
1548 );
1549 #endif
1550 }
1551 }
1552 }
1553}
1554
1555#else
1556void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1557/*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1558{
1559 return wxEnumProperty::GetCellRenderer(column);
1560}*/
1561#endif
1562
1563// -----------------------------------------------------------------------
1564// wxImageFileProperty
1565// -----------------------------------------------------------------------
1566
1567#if wxUSE_IMAGE
1568
1569const wxString& wxPGGetDefaultImageWildcard()
1570{
1571 // Form the wildcard, if not done yet
1572 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1573 {
1574
1575 wxString str;
1576
1577 // TODO: This section may require locking (using global).
1578
1579 wxList& handlers = wxImage::GetHandlers();
1580
1581 wxList::iterator node;
1582
1583 // Let's iterate over the image handler list.
1584 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1585 for ( node = handlers.begin(); node != handlers.end(); node++ )
1586 {
1587 wxImageHandler *handler = (wxImageHandler*)*node;
1588
1589 wxString ext_lo = handler->GetExtension();
1590 wxString ext_up = ext_lo.Upper();
1591
1592 str.append( ext_up );
1593 str.append( wxT(" files (*.") );
1594 str.append( ext_up );
1595 str.append( wxT(")|*.") );
1596 str.append( ext_lo );
1597 str.append( wxT("|") );
1598 }
1599
1600 str.append ( wxT("All files (*.*)|*.*") );
1601
1602 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1603 }
1604
1605 return wxPGGlobalVars->m_pDefaultImageWildcard;
1606}
1607
d53f610c 1608IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1c4293cb
VZ
1609
1610wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1611 const wxString& value )
1612 : wxFileProperty(label,name,value)
1613{
1614 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1615
1616 m_pImage = (wxImage*) NULL;
1617 m_pBitmap = (wxBitmap*) NULL;
1618}
1619
1620wxImageFileProperty::~wxImageFileProperty()
1621{
1622 if ( m_pBitmap )
1623 delete m_pBitmap;
1624 if ( m_pImage )
1625 delete m_pImage;
1626}
1627
1628void wxImageFileProperty::OnSetValue()
1629{
1630 wxFileProperty::OnSetValue();
1631
1632 // Delete old image
1633 if ( m_pImage )
1634 {
1635 delete m_pImage;
1636 m_pImage = NULL;
1637 }
1638 if ( m_pBitmap )
1639 {
1640 delete m_pBitmap;
1641 m_pBitmap = NULL;
1642 }
1643
1425eca5
JS
1644 wxFileName filename = GetFileName();
1645
1c4293cb 1646 // Create the image thumbnail
1425eca5 1647 if ( filename.FileExists() )
1c4293cb 1648 {
1425eca5 1649 m_pImage = new wxImage( filename.GetFullPath() );
1c4293cb
VZ
1650 }
1651}
1652
1653wxSize wxImageFileProperty::OnMeasureImage( int ) const
1654{
1655 return wxPG_DEFAULT_IMAGE_SIZE;
1656}
1657
1658void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1659 const wxRect& rect,
1660 wxPGPaintData& )
1661{
1662 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1663 {
1664 // Draw the thumbnail
1665
1666 // Create the bitmap here because required size is not known in OnSetValue().
1667 if ( !m_pBitmap )
1668 {
1669 m_pImage->Rescale( rect.width, rect.height );
1670 m_pBitmap = new wxBitmap( *m_pImage );
1671 delete m_pImage;
1672 m_pImage = NULL;
1673 }
1674
1675 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1676 }
1677 else
1678 {
1679 // No file - just draw a white box
1680 dc.SetBrush( *wxWHITE_BRUSH );
1681 dc.DrawRectangle ( rect );
1682 }
1683}
1684
1685#endif // wxUSE_IMAGE
1686
1687// -----------------------------------------------------------------------
1688// wxMultiChoiceProperty
1689// -----------------------------------------------------------------------
1690
1691#if wxUSE_CHOICEDLG
1692
3b211af1 1693#include "wx/choicdlg.h"
1c4293cb
VZ
1694
1695WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1696 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1697
1698wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1699 const wxString& name,
1700 const wxPGChoices& choices,
1701 const wxArrayString& value)
1702 : wxPGProperty(label,name)
1703{
1704 m_choices.Assign(choices);
1705 SetValue(value);
1706}
1707
1708wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1709 const wxString& name,
1710 const wxArrayString& strings,
1711 const wxArrayString& value)
1712 : wxPGProperty(label,name)
1713{
1714 m_choices.Set(strings);
1715 SetValue(value);
1716}
1717
1718wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1719 const wxString& name,
1720 const wxArrayString& value)
1721 : wxPGProperty(label,name)
1722{
1723 wxArrayString strings;
1724 m_choices.Set(strings);
1725 SetValue(value);
1726}
1727
1728wxMultiChoiceProperty::~wxMultiChoiceProperty()
1729{
1730}
1731
1732void wxMultiChoiceProperty::OnSetValue()
1733{
102c9a42 1734 GenerateValueAsString(m_value, &m_display);
1c4293cb
VZ
1735}
1736
1425eca5
JS
1737wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1738 int argFlags ) const
1c4293cb 1739{
1425eca5
JS
1740 // If possible, use cached string
1741 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1742 return m_display;
1743
1744 wxString s;
102c9a42 1745 GenerateValueAsString(value, &s);
1425eca5 1746 return s;
1c4293cb
VZ
1747}
1748
102c9a42
JS
1749void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1750 wxString* target ) const
1c4293cb
VZ
1751{
1752 wxArrayString strings;
1753
102c9a42
JS
1754 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1755 strings = value.GetArrayString();
1c4293cb 1756
1425eca5 1757 wxString& tempStr = *target;
1c4293cb
VZ
1758 unsigned int i;
1759 unsigned int itemCount = strings.size();
1760
1761 tempStr.Empty();
1762
1763 if ( itemCount )
1764 tempStr.append( wxT("\"") );
1765
1766 for ( i = 0; i < itemCount; i++ )
1767 {
1768 tempStr.append( strings[i] );
1769 tempStr.append( wxT("\"") );
1770 if ( i < (itemCount-1) )
1771 tempStr.append ( wxT(" \"") );
1772 }
1773}
1774
1775wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1776{
0372d42e 1777 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(GetValue());
1c4293cb
VZ
1778 unsigned int i;
1779
1780 // Translate values to string indices.
1781 wxArrayInt selections;
1782
1783 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1784 {
1785 for ( i=0; i<valueArr.size(); i++ )
1786 selections.Add(-1);
1787 }
1788 else
1789 {
1790 for ( i=0; i<valueArr.size(); i++ )
1791 {
1792 int sIndex = m_choices.Index(valueArr[i]);
1793 if ( sIndex >= 0 )
1794 selections.Add(sIndex);
1795 }
1796 }
1797
1798 return selections;
1799}
1800
1801bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1802 wxWindow* WXUNUSED(primary),
1803 wxEvent& event )
1804{
1805 if ( propgrid->IsMainButtonEvent(event) )
1806 {
1807 // Update the value
703ee9f5 1808 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
1809
1810 wxArrayString labels = m_choices.GetLabels();
1811 unsigned int choiceCount;
1812
1813 if ( m_choices.IsOk() )
1814 choiceCount = m_choices.GetCount();
1815 else
1816 choiceCount = 0;
1817
1818 // launch editor dialog
1819 wxMultiChoiceDialog dlg( propgrid,
1820 _("Make a selection:"),
1821 m_label,
1822 choiceCount,
1823 choiceCount?&labels[0]:NULL,
1824 wxCHOICEDLG_STYLE );
1825
1826 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1827
9b5bafcf 1828 wxArrayString strings = useValue.GetArrayString();
1c4293cb
VZ
1829 wxArrayString extraStrings;
1830
1831 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1832
1833 if ( dlg.ShowModal() == wxID_OK && choiceCount )
1834 {
1835 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1836
1837 wxArrayInt arrInt = dlg.GetSelections();
1838
1839 wxVariant variant;
1840
1841 // Strings that were not in list of choices
1842 wxArrayString value;
1843
1844 // Translate string indices to strings
1845
1846 unsigned int n;
1847 if ( userStringMode == 1 )
1848 {
1849 for (n=0;n<extraStrings.size();n++)
1850 value.push_back(extraStrings[n]);
1851 }
1852
1853 unsigned int i;
1854 for ( i=0; i<arrInt.size(); i++ )
1855 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1856
1857 if ( userStringMode == 2 )
1858 {
1859 for (n=0;n<extraStrings.size();n++)
1860 value.push_back(extraStrings[n]);
1861 }
1862
1863 variant = WXVARIANT(value);
1864
1865 SetValueInEvent(variant);
1866
1867 return true;
1868 }
1869 }
1870 return false;
1871}
1872
1c4293cb
VZ
1873bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1874{
1875 wxArrayString arr;
1876
1877 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1878
1879 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
1880 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
1881 arr.Add(token);
1882 WX_PG_TOKENIZER2_END()
1883
1884 wxVariant v( WXVARIANT(arr) );
1885 variant = v;
1886
1887 return true;
1888}
1889
1890#endif // wxUSE_CHOICEDLG
1891
1892
1893// -----------------------------------------------------------------------
1894// wxDateProperty
1895// -----------------------------------------------------------------------
1896
1897#if wxUSE_DATETIME
1898
1899
1900#if wxUSE_DATEPICKCTRL
1901 #define dtCtrl DatePickerCtrl
1902#else
1903 #define dtCtrl TextCtrl
1904#endif
1905
1906WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
1907 wxPGProperty,
1908 wxDateTime,
1909 const wxDateTime&,
1910 dtCtrl)
1911
1912
1913wxString wxDateProperty::ms_defaultDateFormat;
1914
1915
1916wxDateProperty::wxDateProperty( const wxString& label,
1917 const wxString& name,
1918 const wxDateTime& value )
1919 : wxPGProperty(label,name)
1920{
1921 //wxPGRegisterDefaultValueType(wxDateTime)
1922
1923#if wxUSE_DATEPICKCTRL
1924 wxPGRegisterEditorClass(DatePickerCtrl);
1925
1926 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
1927#else
1928 m_dpStyle = 0;
1929#endif
1930
1931 SetValue( value );
1932}
1933
1934wxDateProperty::~wxDateProperty()
1935{
1936}
1937
1938bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
1939 int WXUNUSED(argFlags) ) const
1940{
1941 wxDateTime dt;
1942
1943 const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
1944
1945 if ( c )
1946 {
1947 variant = dt;
1948 return true;
1949 }
1950
1951 return false;
1952}
1953
1425eca5
JS
1954wxString wxDateProperty::ValueToString( wxVariant& value,
1955 int argFlags ) const
1c4293cb
VZ
1956{
1957 const wxChar* format = (const wxChar*) NULL;
1958
1425eca5 1959 wxDateTime dateTime = value.GetDateTime();
1c4293cb
VZ
1960
1961 if ( !dateTime.IsValid() )
1962 return wxT("Invalid");
1963
1964 if ( !ms_defaultDateFormat.length() )
1965 {
1966#if wxUSE_DATEPICKCTRL
1967 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
1968#else
1969 bool showCentury = true;
1970#endif
1971 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
1972 }
1973
1974 if ( m_format.length() &&
1975 !(argFlags & wxPG_FULL_VALUE) )
1976 format = m_format.c_str();
1977
1978 // Determine default from locale
1979 // NB: This is really simple stuff, but can't figure anything
1980 // better without proper support in wxLocale
1981 if ( !format )
1982 format = ms_defaultDateFormat.c_str();
1983
1984 return dateTime.Format(format);
1985}
1986
1987wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
1988{
1989 // This code is basicly copied from datectlg.cpp's SetFormat
1990 //
1991 wxString format;
1992
1993 wxDateTime dt;
1994 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
1995 wxString str(dt.Format(wxT("%x")));
1996
1997 const wxChar *p = str.c_str();
1998 while ( *p )
1999 {
2000 int n=wxAtoi(p);
2001 if (n == dt.GetDay())
2002 {
2003 format.Append(wxT("%d"));
2004 p += 2;
2005 }
2006 else if (n == (int)dt.GetMonth()+1)
2007 {
2008 format.Append(wxT("%m"));
2009 p += 2;
2010 }
2011 else if (n == dt.GetYear())
2012 {
2013 format.Append(wxT("%Y"));
2014 p += 4;
2015 }
2016 else if (n == (dt.GetYear() % 100))
2017 {
2018 if (showCentury)
2019 format.Append(wxT("%Y"));
2020 else
2021 format.Append(wxT("%y"));
2022 p += 2;
2023 }
2024 else
2025 format.Append(*p++);
2026 }
2027
2028 return format;
2029}
2030
2031bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2032{
2033 if ( name == wxPG_DATE_FORMAT )
2034 {
2035 m_format = value.GetString();
2036 return true;
2037 }
2038 else if ( name == wxPG_DATE_PICKER_STYLE )
2039 {
2040 m_dpStyle = value.GetLong();
2041 ms_defaultDateFormat.clear(); // This may need recalculation
2042 return true;
2043 }
2044 return false;
2045}
2046
2047#endif // wxUSE_DATETIME
2048
2049
2050// -----------------------------------------------------------------------
2051// wxPropertyGridInterface
2052// -----------------------------------------------------------------------
2053
2054void wxPropertyGridInterface::InitAllTypeHandlers()
2055{
2056}
2057
2058// -----------------------------------------------------------------------
2059
2060void wxPropertyGridInterface::RegisterAdditionalEditors()
2061{
c8074be0
JS
2062 // Register editor classes, if necessary.
2063 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2064 wxPropertyGrid::RegisterDefaultEditors();
2065
1c4293cb
VZ
2066#if wxUSE_SPINBTN
2067 wxPGRegisterEditorClass(SpinCtrl);
2068#endif
2069#if wxUSE_DATEPICKCTRL
2070 wxPGRegisterEditorClass(DatePickerCtrl);
2071#endif
2072}
2073
2074// -----------------------------------------------------------------------
2075
f4bc1aa2
JS
2076#endif // wxPG_INCLUDE_ADVPROPS
2077
2078#endif // wxUSE_PROPGRID
2079