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