]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/advprops.cpp
no changes, just fixed typo in an error message
[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
48a32cf6
JS
622 AddPrivateChild( new wxIntProperty( _("Point Size"),
623 wxS("Point Size"),(long)font.GetPointSize() ) );
2fd4a524 624
48a32cf6
JS
625 AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
626 gs_fp_es_family_labels,gs_fp_es_family_values,
627 font.GetFamily()) );
1c4293cb
VZ
628
629 wxString faceName = font.GetFaceName();
630 // If font was not in there, add it now
631 if ( faceName.length() &&
632 wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
633 wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
634
d665918b 635 wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"),
1c4293cb
VZ
636 *wxPGGlobalVars->m_fontFamilyChoices);
637
638 p->SetValueFromString(faceName, wxPG_FULL_VALUE);
639
48a32cf6 640 AddPrivateChild( p );
1c4293cb 641
48a32cf6
JS
642 AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
643 gs_fp_es_style_labels,gs_fp_es_style_values,
644 font.GetStyle()) );
1c4293cb 645
48a32cf6
JS
646 AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
647 gs_fp_es_weight_labels,gs_fp_es_weight_values,
648 font.GetWeight()) );
1c4293cb 649
48a32cf6
JS
650 AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
651 font.GetUnderlined()) );
1c4293cb
VZ
652}
653
654wxFontProperty::~wxFontProperty() { }
655
656void wxFontProperty::OnSetValue()
657{
0372d42e
JS
658 wxFont font;
659 font << m_value;
1c4293cb 660
1c4293cb 661 if ( !font.Ok() )
0372d42e
JS
662 {
663 font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
664 m_value << font;
665 }
1c4293cb
VZ
666}
667
1425eca5
JS
668wxString wxFontProperty::ValueToString( wxVariant& value,
669 int argFlags ) const
1c4293cb 670{
1425eca5 671 return wxPGProperty::ValueToString(value, argFlags);
1c4293cb
VZ
672}
673
674bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
675 wxEvent& event )
676{
677 if ( propgrid->IsMainButtonEvent(event) )
678 {
679 // Update value from last minute changes
703ee9f5 680 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
681
682 wxFontData data;
0372d42e 683 wxFont font;
9b5bafcf 684 font << useValue;
0372d42e 685 data.SetInitialFont( font );
1c4293cb
VZ
686 data.SetColour(*wxBLACK);
687
688 wxFontDialog dlg(propgrid, data);
689 if ( dlg.ShowModal() == wxID_OK )
690 {
691 propgrid->EditorsValueWasModified();
692
0372d42e
JS
693 wxVariant variant;
694 variant << dlg.GetFontData().GetChosenFont();
1c4293cb
VZ
695 SetValueInEvent( variant );
696 return true;
697 }
698 }
699 return false;
700}
701
702void wxFontProperty::RefreshChildren()
703{
704 if ( !GetChildCount() ) return;
0372d42e
JS
705 wxFont font;
706 font << m_value;
1c4293cb
VZ
707 Item(0)->SetValue( (long)font.GetPointSize() );
708 Item(1)->SetValue( (long)font.GetFamily() );
709 Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
710 Item(3)->SetValue( (long)font.GetStyle() );
711 Item(4)->SetValue( (long)font.GetWeight() );
712 Item(5)->SetValue( font.GetUnderlined() );
713}
714
715void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
716{
0372d42e
JS
717 wxFont font;
718 font << thisValue;
1c4293cb
VZ
719
720 if ( ind == 0 )
721 {
722 font.SetPointSize( wxPGVariantToInt(childValue) );
723 }
724 else if ( ind == 1 )
725 {
726 int fam = childValue.GetLong();
727 if ( fam < wxDEFAULT ||
728 fam > wxTELETYPE )
729 fam = wxDEFAULT;
730 font.SetFamily( fam );
731 }
732 else if ( ind == 2 )
733 {
734 wxString faceName;
735 int faceIndex = childValue.GetLong();
736
737 if ( faceIndex >= 0 )
738 faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
739
740 font.SetFaceName( faceName );
741 }
742 else if ( ind == 3 )
743 {
744 int st = childValue.GetLong();
745 if ( st != wxFONTSTYLE_NORMAL &&
746 st != wxFONTSTYLE_SLANT &&
747 st != wxFONTSTYLE_ITALIC )
748 st = wxFONTWEIGHT_NORMAL;
749 font.SetStyle( st );
750 }
751 else if ( ind == 4 )
752 {
753 int wt = childValue.GetLong();
754 if ( wt != wxFONTWEIGHT_NORMAL &&
755 wt != wxFONTWEIGHT_LIGHT &&
756 wt != wxFONTWEIGHT_BOLD )
757 wt = wxFONTWEIGHT_NORMAL;
758 font.SetWeight( wt );
759 }
760 else if ( ind == 5 )
761 {
762 font.SetUnderlined( childValue.GetBool() );
763 }
0372d42e
JS
764
765 thisValue << font;
1c4293cb
VZ
766}
767
768/*
769wxSize wxFontProperty::OnMeasureImage() const
770{
771 return wxSize(-1,-1);
772}
773
774void wxFontProperty::OnCustomPaint(wxDC& dc,
775 const wxRect& rect,
776 wxPGPaintData& paintData)
777{
778 wxString drawFace;
779 if ( paintData.m_choiceItem >= 0 )
780 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
781 else
782 drawFace = m_value_wxFont.GetFaceName();
783
784 if ( drawFace.length() )
785 {
786 // Draw the background
787 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
788 //dc.SetBrush( *wxWHITE_BRUSH );
789 //dc.SetPen( *wxMEDIUM_GREY_PEN );
790 dc.DrawRectangle( rect );
791
792 wxFont oldFont = dc.GetFont();
793 wxFont drawFont(oldFont.GetPointSize(),
794 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
795 dc.SetFont(drawFont);
796
797 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
798 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
799
800 dc.SetFont(oldFont);
801 }
802 else
803 {
804 // No file - just draw a white box
805 dc.SetBrush ( *wxWHITE_BRUSH );
806 dc.DrawRectangle ( rect );
807 }
808}
809*/
810
811
812// -----------------------------------------------------------------------
813// wxSystemColourProperty
814// -----------------------------------------------------------------------
815
816// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
817#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
818
3b211af1 819#include "wx/colordlg.h"
1c4293cb
VZ
820
821//#define wx_cp_es_syscolours_len 25
822static const wxChar* gs_cp_es_syscolour_labels[] = {
823 wxT("AppWorkspace"),
824 wxT("ActiveBorder"),
825 wxT("ActiveCaption"),
826 wxT("ButtonFace"),
827 wxT("ButtonHighlight"),
828 wxT("ButtonShadow"),
829 wxT("ButtonText"),
830 wxT("CaptionText"),
831 wxT("ControlDark"),
832 wxT("ControlLight"),
833 wxT("Desktop"),
834 wxT("GrayText"),
835 wxT("Highlight"),
836 wxT("HighlightText"),
837 wxT("InactiveBorder"),
838 wxT("InactiveCaption"),
839 wxT("InactiveCaptionText"),
840 wxT("Menu"),
841 wxT("Scrollbar"),
842 wxT("Tooltip"),
843 wxT("TooltipText"),
844 wxT("Window"),
845 wxT("WindowFrame"),
846 wxT("WindowText"),
847 wxT("Custom"),
848 (const wxChar*) NULL
849};
850
851static long gs_cp_es_syscolour_values[] = {
852 wxSYS_COLOUR_APPWORKSPACE,
853 wxSYS_COLOUR_ACTIVEBORDER,
854 wxSYS_COLOUR_ACTIVECAPTION,
855 wxSYS_COLOUR_BTNFACE,
856 wxSYS_COLOUR_BTNHIGHLIGHT,
857 wxSYS_COLOUR_BTNSHADOW,
858 wxSYS_COLOUR_BTNTEXT ,
859 wxSYS_COLOUR_CAPTIONTEXT,
860 wxSYS_COLOUR_3DDKSHADOW,
861 wxSYS_COLOUR_3DLIGHT,
862 wxSYS_COLOUR_BACKGROUND,
863 wxSYS_COLOUR_GRAYTEXT,
864 wxSYS_COLOUR_HIGHLIGHT,
865 wxSYS_COLOUR_HIGHLIGHTTEXT,
866 wxSYS_COLOUR_INACTIVEBORDER,
867 wxSYS_COLOUR_INACTIVECAPTION,
868 wxSYS_COLOUR_INACTIVECAPTIONTEXT,
869 wxSYS_COLOUR_MENU,
870 wxSYS_COLOUR_SCROLLBAR,
871 wxSYS_COLOUR_INFOBK,
872 wxSYS_COLOUR_INFOTEXT,
873 wxSYS_COLOUR_WINDOW,
874 wxSYS_COLOUR_WINDOWFRAME,
875 wxSYS_COLOUR_WINDOWTEXT,
876 wxPG_COLOUR_CUSTOM
877};
878
879
0372d42e 880IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
1c4293cb
VZ
881
882
883// Class body is in advprops.h
884
885WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
886 wxColourPropertyValue,const wxColourPropertyValue&,Choice)
887
888
889void wxSystemColourProperty::Init( int type, const wxColour& colour )
890{
891 wxColourPropertyValue cpv;
892
893 if ( colour.Ok() )
894 cpv.Init( type, colour );
895 else
896 cpv.Init( type, *wxWHITE );
897
898 m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
899
0372d42e 900 m_value << cpv;
1c4293cb
VZ
901
902 OnSetValue();
903}
904
905
906static wxPGChoices gs_wxSystemColourProperty_choicesCache;
907
908
909wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
910 const wxColourPropertyValue& value )
911 : wxEnumProperty( label,
912 name,
913 gs_cp_es_syscolour_labels,
914 gs_cp_es_syscolour_values,
915 &gs_wxSystemColourProperty_choicesCache )
916{
917 if ( &value )
918 Init( value.m_type, value.m_colour );
919 else
920 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
921}
922
923
924wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
925 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
926 const wxColourPropertyValue& value )
927 : wxEnumProperty( label, name, labels, values, choicesCache )
928{
929 if ( &value )
930 Init( value.m_type, value.m_colour );
931 else
932 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
933}
934
935
936wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
937 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
938 const wxColour& value )
939 : wxEnumProperty( label, name, labels, values, choicesCache )
940{
941 if ( &value )
942 Init( wxPG_COLOUR_CUSTOM, value );
943 else
944 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
945}
946
947
948wxSystemColourProperty::~wxSystemColourProperty() { }
949
950
951wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
952{
953 if ( !pVariant )
954 pVariant = &m_value;
955
956 if ( pVariant->IsNull() )
957 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
958
0372d42e
JS
959 if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
960 {
961 wxColourPropertyValue v;
962 v << *pVariant;
963 return v;
964 }
1c4293cb 965
1c4293cb
VZ
966 wxColour col;
967 bool variantProcessed = true;
968
0372d42e 969 if ( pVariant->GetType() == wxS("wxColour*") )
1c4293cb 970 {
0372d42e 971 wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
1c4293cb
VZ
972 col = *pCol;
973 }
0372d42e 974 else if ( pVariant->GetType() == wxS("wxColour") )
1c4293cb 975 {
0372d42e
JS
976 col << *pVariant;
977 }
978 else if ( pVariant->GetType() == wxArrayInt_VariantType )
979 {
980 // This code is mostly needed for wxPython bindings, which
981 // may offer tuple of integers as colour value.
1c4293cb
VZ
982 wxArrayInt arr;
983 arr << *pVariant;
984
985 if ( arr.size() >= 3 )
986 {
987 int r, g, b;
988 int a = 255;
989
990 r = arr[0];
991 g = arr[1];
992 b = arr[2];
993 if ( arr.size() >= 4 )
994 a = arr[3];
995
996 col = wxColour(r, g, b, a);
997 }
998 else
999 {
1000 variantProcessed = false;
1001 }
1002 }
1c4293cb
VZ
1003 else
1004 {
1005 variantProcessed = false;
1006 }
1007
1008 if ( !variantProcessed )
1009 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
1010
1011 wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
1012
1013 int colInd = ColToInd(col);
1014 if ( colInd != wxNOT_FOUND )
1015 v2.m_type = colInd;
1016
1017 return v2;
1018}
1019
1020wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1021{
0372d42e
JS
1022 wxVariant variant;
1023 variant << v;
1024 return variant;
1c4293cb
VZ
1025}
1026
1027int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
1028{
1029 size_t i;
1030 size_t i_max = m_choices.GetCount() - 1;
1031
1032 for ( i=0; i<i_max; i++ )
1033 {
1034 int ind = m_choices[i].GetValue();
1035
1036 if ( colour == GetColour(ind) )
1037 {
1038 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1039 GetClassName(),GetLabel().c_str(),
1040 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1041 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1042 return ind;
1043 }
1044 }
1045 return wxNOT_FOUND;
1046}
1047
1c4293cb
VZ
1048void wxSystemColourProperty::OnSetValue()
1049{
1050 // Convert from generic wxobject ptr to wxPGVariantDataColour
0372d42e 1051 if ( m_value.GetType() == wxS("wxColour*") )
1c4293cb 1052 {
0372d42e 1053 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
1c4293cb
VZ
1054 m_value << *pCol;
1055 }
1056
1057 wxColourPropertyValue val = GetVal(&m_value);
1058
1059 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
1060 {
1061 m_value.MakeNull();
1062 return;
1063 }
1064 else
1065 {
1066
1067 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
1068 val.m_colour = GetColour( val.m_type );
1069
1070 m_value = TranslateVal(val);
1071 }
1072
b0f0eda8 1073 int ind = wxNOT_FOUND;
1c4293cb 1074
0372d42e 1075 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
1c4293cb 1076 {
0372d42e
JS
1077 wxColourPropertyValue cpv;
1078 cpv << m_value;
1079 wxColour col = cpv.m_colour;
1c4293cb 1080
0372d42e
JS
1081 if ( !col.Ok() )
1082 {
1083 SetValueToUnspecified();
1084 SetIndex(wxNOT_FOUND);
1085 return;
1086 }
1c4293cb 1087
0372d42e 1088 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
1c4293cb 1089 {
98c04633 1090 ind = GetIndexForValue(cpv.m_type);
1c4293cb
VZ
1091 }
1092 else
1093 {
0372d42e 1094 cpv.m_type = wxPG_COLOUR_CUSTOM;
1c4293cb
VZ
1095 ind = GetCustomColourIndex();
1096 }
1097 }
1098 else
1099 {
0372d42e
JS
1100 wxColour col;
1101 col << m_value;
1102
1103 if ( !col.Ok() )
1104 {
1105 SetValueToUnspecified();
1106 SetIndex(wxNOT_FOUND);
1107 return;
1108 }
1109
1c4293cb
VZ
1110 ind = ColToInd(col);
1111
1112 if ( ind == wxNOT_FOUND )
1113 ind = GetCustomColourIndex();
1114 }
1115
1116 SetIndex(ind);
1117}
1118
1119
1120wxColour wxSystemColourProperty::GetColour( int index ) const
1121{
1122 return wxSystemSettings::GetColour( (wxSystemColour)index );
1123}
1124
1125wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
1126{
1127 if ( index == wxNOT_FOUND )
1128 return wxString::Format(wxT("(%i,%i,%i)"),
1129 (int)col.Red(),
1130 (int)col.Green(),
1131 (int)col.Blue());
1132 else
1133 return m_choices.GetLabel(index);
1134}
1135
1425eca5 1136wxString wxSystemColourProperty::ValueToString( wxVariant& value,
c9049646 1137 int argFlags ) const
1c4293cb 1138{
1425eca5 1139 wxColourPropertyValue val = GetVal(&value);
1c4293cb 1140
c9049646
JS
1141 int index;
1142
1143 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1144 {
1145 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1146 // but we should use it whenever possible.
1147 index = GetIndex();
1148
1149 // If custom colour was selected, use invalid index, so that
1150 // ColourToString() will return properly formatted colour text.
1151 if ( index == GetCustomColourIndex() )
1152 index = wxNOT_FOUND;
1153 }
1154 else
1155 {
1156 index = m_choices.Index(val.m_type);
1157 }
1158
1159 return ColourToString(val.m_colour, index);
1c4293cb
VZ
1160}
1161
1162
1163wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1164{
1165 return wxPG_DEFAULT_IMAGE_SIZE;
1166}
1167
1168
1169int wxSystemColourProperty::GetCustomColourIndex() const
1170{
1171 return m_choices.GetCount() - 1;
1172}
1173
1174
1175bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1176{
0372d42e 1177 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1c4293cb
VZ
1178 bool res = false;
1179
1180 wxPropertyGrid* propgrid = GetGrid();
1181 wxASSERT( propgrid );
1182
1183 // Must only occur when user triggers event
b0996c3d 1184 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
1c4293cb
VZ
1185 return res;
1186
1187 wxColourPropertyValue val = GetVal();
1188
1189 val.m_type = wxPG_COLOUR_CUSTOM;
1190
1191 wxColourData data;
1192 data.SetChooseFull(true);
1193 data.SetColour(val.m_colour);
1194 int i;
1195 for ( i = 0; i < 16; i++)
1196 {
1197 wxColour colour(i*16, i*16, i*16);
1198 data.SetCustomColour(i, colour);
1199 }
1200
1201 wxColourDialog dialog(propgrid, &data);
1202 if ( dialog.ShowModal() == wxID_OK )
1203 {
1204 wxColourData retData = dialog.GetColourData();
1205 val.m_colour = retData.GetColour();
1206
1207 variant = DoTranslateVal(val);
1208
1209 SetValueInEvent(variant);
1210
1211 res = true;
1212 }
1213
1214 return res;
1215}
1216
1217
1218bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1219{
1220 int index = number;
78f2d746 1221 int type = m_choices.GetValue(index);
1c4293cb 1222
98c04633 1223 if ( type == wxPG_COLOUR_CUSTOM )
1c4293cb
VZ
1224 {
1225 QueryColourFromUser(variant);
1226 }
1227 else
1228 {
1229 variant = TranslateVal( type, GetColour(type) );
1230 }
1231
1232 return true;
1233}
1234
1235// Need to do some extra event handling.
1236bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event )
1237{
1238 if ( propgrid->IsMainButtonEvent(event) )
1239 {
1240 // We need to handle button click in case editor has been
1241 // switched to one that has wxButton as well.
1242 wxVariant variant;
1243 if ( QueryColourFromUser(variant) )
1244 return true;
1245 }
1246 return false;
1247}
1248
1249/*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1250{
1251public:
1252 virtual void Render( wxDC& dc, const wxRect& rect,
1253 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1254 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1255 {
1256 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1257 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1258
1259 dc.SetPen(*wxBLACK_PEN);
1260 if ( item >= 0 &&
1261 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1262 )
1263 {
1264 int colInd;
1265 const wxArrayInt& values = prop->GetValues();
1266 if ( values.GetChildCount() )
1267 colInd = values[item];
1268 else
1269 colInd = item;
1270 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1271 }
1272 else if ( !prop->IsValueUnspecified() )
1273 dc.SetBrush( prop->GetVal().m_colour );
1274 else
1275 dc.SetBrush( *wxWHITE );
1276
1277 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1278 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1279 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1280 imageRect.width, imageRect.height );
1281
1282 wxString text;
1283 if ( item == -1 )
1284 text = property->GetValueAsString();
1285 else
1286 text = property->GetChoiceString(item);
1287 DrawText( dc, rect, imageRect.width, text );
1288 }
1289protected:
1290};
1291
1292wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1293
1294wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1295{
1296 if ( column == 1 )
1297 return &g_wxPGColourPropertyRenderer;
1298 return wxEnumProperty::GetCellRenderer(column);
1299}*/
1300
1301void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1302 wxPGPaintData& paintdata )
1303{
1304 wxColour col;
1305
1306 if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1307 paintdata.m_choiceItem != GetCustomColourIndex() )
1308 {
1309 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1310 col = GetColour( colInd );
1311 }
1312 else if ( !IsValueUnspecified() )
1313 {
1314 col = GetVal().m_colour;
1315 }
1316
1317 if ( col.Ok() )
1318 {
1319 dc.SetBrush(col);
1320 dc.DrawRectangle(rect);
1321 }
1322}
1323
1324
1325bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1326{
1327 //
1328 // Accept colour format "[Name] [(R,G,B)]"
1329 // Name takes precedence.
1330 //
1331 wxString colourName;
1332 wxString colourRGB;
1333
1334 int ppos = text.Find(wxT("("));
1335
1336 if ( ppos == wxNOT_FOUND )
1337 {
1338 colourName = text;
1339 }
1340 else
1341 {
1342 colourName = text.substr(0, ppos);
1343 colourRGB = text.substr(ppos, text.length()-ppos);
1344 }
1345
1346 // Strip spaces from extremities
1347 colourName.Trim(true);
1348 colourName.Trim(false);
1349 colourRGB.Trim(true);
1350
1351 // Validate colourRGB string - (1,1,1) is shortest allowed
1352 if ( colourRGB.length() < 7 )
1353 colourRGB.clear();
1354
1355 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
1356 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1357 {
1358 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1359 {
1360 // This really should not occurr...
1361 // wxASSERT(false);
1362 ResetNextIndex();
1363 return false;
1364 }
1365
1366 QueryColourFromUser(value);
1367 }
1368 else
1369 {
1370 wxColourPropertyValue val;
1371
1372 bool done = false;
1373
1374 if ( colourName.length() )
1375 {
1376 // Try predefined colour first
1377 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1378 if ( res && GetIndex() >= 0 )
1379 {
1380 val.m_type = GetIndex();
9e996d8c 1381 if ( val.m_type < m_choices.GetCount() )
1c4293cb
VZ
1382 val.m_type = m_choices[val.m_type].GetValue();
1383
1384 // Get proper colour for type.
1385 val.m_colour = GetColour(val.m_type);
1386
1387 done = true;
1388 }
1389 }
1390 if ( colourRGB.length() && !done )
1391 {
1392 // Then check custom colour.
1393 val.m_type = wxPG_COLOUR_CUSTOM;
1394
1395 int r = -1, g = -1, b = -1;
1396 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1397
1398 if ( r >= 0 && r <= 255 &&
1399 g >= 0 && g <= 255 &&
1400 b >= 0 && b <= 255 )
1401 {
1402 val.m_colour.Set(r,g,b);
1403
1404 done = true;
1405 }
1406 }
1407
1408 if ( !done )
1409 {
1410 ResetNextIndex();
1411 return false;
1412 }
1413
1414 value = DoTranslateVal(val);
1415 }
1416
1417 return true;
1418}
1419
1420
1421bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1422{
1423 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1424 {
1425 int ival = wxPGVariantToInt(value);
1426
1c4293cb
VZ
1427 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1428 {
1429 // Show custom choice
1430 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1431 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1432 }
1433 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1434 {
1435 // Hide custom choice
1436 m_choices.RemoveAt(GetCustomColourIndex());
1437 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1438 }
1439 return true;
1440 }
1441 return false;
1442}
1443
1444
1445// -----------------------------------------------------------------------
1446// wxColourProperty
1447// -----------------------------------------------------------------------
1448
1449static const wxChar* gs_cp_es_normcolour_labels[] = {
1450 wxT("Black"),
1451 wxT("Maroon"),
1452 wxT("Navy"),
1453 wxT("Purple"),
1454 wxT("Teal"),
1455 wxT("Gray"),
1456 wxT("Green"),
1457 wxT("Olive"),
1458 wxT("Brown"),
1459 wxT("Blue"),
1460 wxT("Fuchsia"),
1461 wxT("Red"),
1462 wxT("Orange"),
1463 wxT("Silver"),
1464 wxT("Lime"),
1465 wxT("Aqua"),
1466 wxT("Yellow"),
1467 wxT("White"),
1468 wxT("Custom"),
1469 (const wxChar*) NULL
1470};
1471
1472static unsigned long gs_cp_es_normcolour_colours[] = {
1473 wxPG_COLOUR(0,0,0),
1474 wxPG_COLOUR(128,0,0),
1475 wxPG_COLOUR(0,0,128),
1476 wxPG_COLOUR(128,0,128),
1477 wxPG_COLOUR(0,128,128),
1478 wxPG_COLOUR(128,128,128),
1479 wxPG_COLOUR(0,128,0),
1480 wxPG_COLOUR(128,128,0),
1481 wxPG_COLOUR(166,124,81),
1482 wxPG_COLOUR(0,0,255),
1483 wxPG_COLOUR(255,0,255),
1484 wxPG_COLOUR(255,0,0),
1485 wxPG_COLOUR(247,148,28),
1486 wxPG_COLOUR(192,192,192),
1487 wxPG_COLOUR(0,255,0),
1488 wxPG_COLOUR(0,255,255),
1489 wxPG_COLOUR(255,255,0),
1490 wxPG_COLOUR(255,255,255),
1491 wxPG_COLOUR(0,0,0)
1492};
1493
d61d8cff
JS
1494WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1495 wxColour, const wxColour&, TextCtrlAndButton)
1496
1497static wxPGChoices gs_wxColourProperty_choicesCache;
1498
1499wxColourProperty::wxColourProperty( const wxString& label,
1500 const wxString& name,
1501 const wxColour& value )
1502 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1503 NULL,
1504 &gs_wxColourProperty_choicesCache, value )
1505{
1506 Init( value );
1507
1508 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1509}
1510
1511wxColourProperty::~wxColourProperty()
1512{
1513}
1514
1515void wxColourProperty::Init( wxColour colour )
1516{
1517 if ( !colour.Ok() )
1518 colour = *wxWHITE;
1519 wxVariant variant;
1520 variant << colour;
1521 m_value = variant;
1522 int ind = ColToInd(colour);
1523 if ( ind < 0 )
1524 ind = m_choices.GetCount() - 1;
1525 SetIndex( ind );
1526}
1527
1425eca5
JS
1528wxString wxColourProperty::ValueToString( wxVariant& value,
1529 int argFlags ) const
d61d8cff
JS
1530{
1531 const wxPGEditor* editor = GetEditorClass();
1532 if ( editor != wxPGEditor_Choice &&
1533 editor != wxPGEditor_ChoiceAndButton &&
1534 editor != wxPGEditor_ComboBox )
1535 argFlags |= wxPG_PROPERTY_SPECIFIC;
1536
1425eca5 1537 return wxSystemColourProperty::ValueToString(value, argFlags);
d61d8cff
JS
1538}
1539
1540wxColour wxColourProperty::GetColour( int index ) const
1541{
d61d8cff
JS
1542 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1543}
1544
1545wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1546{
1547 wxVariant variant;
1548 variant << v.m_colour;
1549 return variant;
1550}
1c4293cb
VZ
1551
1552// -----------------------------------------------------------------------
1553// wxCursorProperty
1554// -----------------------------------------------------------------------
1555
1556#define wxPG_CURSOR_IMAGE_WIDTH 32
1557
1558#define NUM_CURSORS 28
1559
1560//#define wx_cp_es_syscursors_len 28
1561static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1562 wxT("Default"),
1563 wxT("Arrow"),
1564 wxT("Right Arrow"),
1565 wxT("Blank"),
1566 wxT("Bullseye"),
1567 wxT("Character"),
1568 wxT("Cross"),
1569 wxT("Hand"),
1570 wxT("I-Beam"),
1571 wxT("Left Button"),
1572 wxT("Magnifier"),
1573 wxT("Middle Button"),
1574 wxT("No Entry"),
1575 wxT("Paint Brush"),
1576 wxT("Pencil"),
1577 wxT("Point Left"),
1578 wxT("Point Right"),
1579 wxT("Question Arrow"),
1580 wxT("Right Button"),
1581 wxT("Sizing NE-SW"),
1582 wxT("Sizing N-S"),
1583 wxT("Sizing NW-SE"),
1584 wxT("Sizing W-E"),
1585 wxT("Sizing"),
1586 wxT("Spraycan"),
1587 wxT("Wait"),
1588 wxT("Watch"),
1589 wxT("Wait Arrow"),
1590 (const wxChar*) NULL
1591};
1592
1593static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1594 wxCURSOR_NONE,
1595 wxCURSOR_ARROW,
1596 wxCURSOR_RIGHT_ARROW,
1597 wxCURSOR_BLANK,
1598 wxCURSOR_BULLSEYE,
1599 wxCURSOR_CHAR,
1600 wxCURSOR_CROSS,
1601 wxCURSOR_HAND,
1602 wxCURSOR_IBEAM,
1603 wxCURSOR_LEFT_BUTTON,
1604 wxCURSOR_MAGNIFIER,
1605 wxCURSOR_MIDDLE_BUTTON,
1606 wxCURSOR_NO_ENTRY,
1607 wxCURSOR_PAINT_BRUSH,
1608 wxCURSOR_PENCIL,
1609 wxCURSOR_POINT_LEFT,
1610 wxCURSOR_POINT_RIGHT,
1611 wxCURSOR_QUESTION_ARROW,
1612 wxCURSOR_RIGHT_BUTTON,
1613 wxCURSOR_SIZENESW,
1614 wxCURSOR_SIZENS,
1615 wxCURSOR_SIZENWSE,
1616 wxCURSOR_SIZEWE,
1617 wxCURSOR_SIZING,
1618 wxCURSOR_SPRAYCAN,
1619 wxCURSOR_WAIT,
1620 wxCURSOR_WATCH,
1621 wxCURSOR_ARROWWAIT
1622};
1623
1624IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1625
1626wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1627 int value )
1628 : wxEnumProperty( label,
1629 name,
1630 gs_cp_es_syscursors_labels,
1631 gs_cp_es_syscursors_values,
1632 value )
1633{
1634 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1635}
1636
1637wxCursorProperty::~wxCursorProperty()
1638{
1639}
1640
1641wxSize wxCursorProperty::OnMeasureImage( int item ) const
1642{
1643#if wxPG_CAN_DRAW_CURSOR
1644 if ( item != -1 && item < NUM_CURSORS )
1645 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1646#else
1647 wxUnusedVar(item);
1648#endif
1649 return wxSize(0,0);
1650}
1651
1652#if wxPG_CAN_DRAW_CURSOR
1653
1654void wxCursorProperty::OnCustomPaint( wxDC& dc,
1655 const wxRect& rect,
1656 wxPGPaintData& paintdata )
1657{
1658 // Background brush
1659 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1660
1661 if ( paintdata.m_choiceItem >= 0 )
1662 {
1663 dc.DrawRectangle( rect );
1664
1665 if ( paintdata.m_choiceItem < NUM_CURSORS )
1666 {
2399c87c
JS
1667 wxStockCursor cursorIndex =
1668 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1c4293cb
VZ
1669
1670 {
2399c87c
JS
1671 if ( cursorIndex == wxCURSOR_NONE )
1672 cursorIndex = wxCURSOR_ARROW;
1c4293cb 1673
2399c87c 1674 wxCursor cursor( cursorIndex );
1c4293cb
VZ
1675
1676 #ifdef __WXMSW__
1677 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1678 ::DrawIconEx( hDc,
1679 rect.x,
1680 rect.y,
1681 (HICON)cursor.GetHandle(),
1682 0,
1683 0,
1684 0,
1685 NULL,
591df136
JS
1686 #if !defined(__WXWINCE__)
1687 DI_COMPAT | DI_DEFAULTSIZE |
1688 #endif
1689 DI_NORMAL
1c4293cb
VZ
1690 );
1691 #endif
1692 }
1693 }
1694 }
1695}
1696
1697#else
1698void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1699/*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1700{
1701 return wxEnumProperty::GetCellRenderer(column);
1702}*/
1703#endif
1704
1705// -----------------------------------------------------------------------
1706// wxImageFileProperty
1707// -----------------------------------------------------------------------
1708
1709#if wxUSE_IMAGE
1710
1711const wxString& wxPGGetDefaultImageWildcard()
1712{
1713 // Form the wildcard, if not done yet
1714 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1715 {
1716
1717 wxString str;
1718
1719 // TODO: This section may require locking (using global).
1720
1721 wxList& handlers = wxImage::GetHandlers();
1722
1723 wxList::iterator node;
1724
1725 // Let's iterate over the image handler list.
1726 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
b7bc9d80 1727 for ( node = handlers.begin(); node != handlers.end(); ++node )
1c4293cb
VZ
1728 {
1729 wxImageHandler *handler = (wxImageHandler*)*node;
1730
1731 wxString ext_lo = handler->GetExtension();
1732 wxString ext_up = ext_lo.Upper();
1733
1734 str.append( ext_up );
1735 str.append( wxT(" files (*.") );
1736 str.append( ext_up );
1737 str.append( wxT(")|*.") );
1738 str.append( ext_lo );
1739 str.append( wxT("|") );
1740 }
1741
1742 str.append ( wxT("All files (*.*)|*.*") );
1743
1744 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1745 }
1746
1747 return wxPGGlobalVars->m_pDefaultImageWildcard;
1748}
1749
d53f610c 1750IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1c4293cb
VZ
1751
1752wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1753 const wxString& value )
1754 : wxFileProperty(label,name,value)
1755{
1756 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1757
d3b9f782
VZ
1758 m_pImage = NULL;
1759 m_pBitmap = NULL;
1c4293cb
VZ
1760}
1761
1762wxImageFileProperty::~wxImageFileProperty()
1763{
1764 if ( m_pBitmap )
1765 delete m_pBitmap;
1766 if ( m_pImage )
1767 delete m_pImage;
1768}
1769
1770void wxImageFileProperty::OnSetValue()
1771{
1772 wxFileProperty::OnSetValue();
1773
1774 // Delete old image
1775 if ( m_pImage )
1776 {
1777 delete m_pImage;
1778 m_pImage = NULL;
1779 }
1780 if ( m_pBitmap )
1781 {
1782 delete m_pBitmap;
1783 m_pBitmap = NULL;
1784 }
1785
1425eca5
JS
1786 wxFileName filename = GetFileName();
1787
1c4293cb 1788 // Create the image thumbnail
1425eca5 1789 if ( filename.FileExists() )
1c4293cb 1790 {
1425eca5 1791 m_pImage = new wxImage( filename.GetFullPath() );
1c4293cb
VZ
1792 }
1793}
1794
1795wxSize wxImageFileProperty::OnMeasureImage( int ) const
1796{
1797 return wxPG_DEFAULT_IMAGE_SIZE;
1798}
1799
1800void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1801 const wxRect& rect,
1802 wxPGPaintData& )
1803{
1804 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1805 {
1806 // Draw the thumbnail
1807
1808 // Create the bitmap here because required size is not known in OnSetValue().
1809 if ( !m_pBitmap )
1810 {
1811 m_pImage->Rescale( rect.width, rect.height );
1812 m_pBitmap = new wxBitmap( *m_pImage );
1813 delete m_pImage;
1814 m_pImage = NULL;
1815 }
1816
1817 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1818 }
1819 else
1820 {
1821 // No file - just draw a white box
1822 dc.SetBrush( *wxWHITE_BRUSH );
1823 dc.DrawRectangle ( rect );
1824 }
1825}
1826
1827#endif // wxUSE_IMAGE
1828
1829// -----------------------------------------------------------------------
1830// wxMultiChoiceProperty
1831// -----------------------------------------------------------------------
1832
1833#if wxUSE_CHOICEDLG
1834
3b211af1 1835#include "wx/choicdlg.h"
1c4293cb
VZ
1836
1837WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1838 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1839
1840wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1841 const wxString& name,
1842 const wxPGChoices& choices,
1843 const wxArrayString& value)
1844 : wxPGProperty(label,name)
1845{
1846 m_choices.Assign(choices);
1847 SetValue(value);
1848}
1849
1850wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1851 const wxString& name,
1852 const wxArrayString& strings,
1853 const wxArrayString& value)
1854 : wxPGProperty(label,name)
1855{
1856 m_choices.Set(strings);
1857 SetValue(value);
1858}
1859
1860wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1861 const wxString& name,
1862 const wxArrayString& value)
1863 : wxPGProperty(label,name)
1864{
1865 wxArrayString strings;
1866 m_choices.Set(strings);
1867 SetValue(value);
1868}
1869
1870wxMultiChoiceProperty::~wxMultiChoiceProperty()
1871{
1872}
1873
1874void wxMultiChoiceProperty::OnSetValue()
1875{
102c9a42 1876 GenerateValueAsString(m_value, &m_display);
1c4293cb
VZ
1877}
1878
1425eca5
JS
1879wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1880 int argFlags ) const
1c4293cb 1881{
1425eca5
JS
1882 // If possible, use cached string
1883 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1884 return m_display;
1885
1886 wxString s;
102c9a42 1887 GenerateValueAsString(value, &s);
1425eca5 1888 return s;
1c4293cb
VZ
1889}
1890
102c9a42
JS
1891void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1892 wxString* target ) const
1c4293cb
VZ
1893{
1894 wxArrayString strings;
1895
102c9a42
JS
1896 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1897 strings = value.GetArrayString();
1c4293cb 1898
1425eca5 1899 wxString& tempStr = *target;
1c4293cb
VZ
1900 unsigned int i;
1901 unsigned int itemCount = strings.size();
1902
1903 tempStr.Empty();
1904
1905 if ( itemCount )
1906 tempStr.append( wxT("\"") );
1907
1908 for ( i = 0; i < itemCount; i++ )
1909 {
1910 tempStr.append( strings[i] );
1911 tempStr.append( wxT("\"") );
1912 if ( i < (itemCount-1) )
1913 tempStr.append ( wxT(" \"") );
1914 }
1915}
1916
1917wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1918{
bfad4a15
JS
1919 wxVariant variant = GetValue();
1920 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant);
1c4293cb
VZ
1921 unsigned int i;
1922
1923 // Translate values to string indices.
1924 wxArrayInt selections;
1925
1926 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1927 {
1928 for ( i=0; i<valueArr.size(); i++ )
1929 selections.Add(-1);
1930 }
1931 else
1932 {
1933 for ( i=0; i<valueArr.size(); i++ )
1934 {
1935 int sIndex = m_choices.Index(valueArr[i]);
1936 if ( sIndex >= 0 )
1937 selections.Add(sIndex);
1938 }
1939 }
1940
1941 return selections;
1942}
1943
1944bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1945 wxWindow* WXUNUSED(primary),
1946 wxEvent& event )
1947{
1948 if ( propgrid->IsMainButtonEvent(event) )
1949 {
1950 // Update the value
703ee9f5 1951 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
1952
1953 wxArrayString labels = m_choices.GetLabels();
1954 unsigned int choiceCount;
1955
1956 if ( m_choices.IsOk() )
1957 choiceCount = m_choices.GetCount();
1958 else
1959 choiceCount = 0;
1960
1961 // launch editor dialog
1962 wxMultiChoiceDialog dlg( propgrid,
1963 _("Make a selection:"),
1964 m_label,
1965 choiceCount,
1966 choiceCount?&labels[0]:NULL,
1967 wxCHOICEDLG_STYLE );
1968
1969 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1970
9b5bafcf 1971 wxArrayString strings = useValue.GetArrayString();
1c4293cb
VZ
1972 wxArrayString extraStrings;
1973
1974 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1975
1976 if ( dlg.ShowModal() == wxID_OK && choiceCount )
1977 {
1978 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1979
1980 wxArrayInt arrInt = dlg.GetSelections();
1981
1982 wxVariant variant;
1983
1984 // Strings that were not in list of choices
1985 wxArrayString value;
1986
1987 // Translate string indices to strings
1988
1989 unsigned int n;
1990 if ( userStringMode == 1 )
1991 {
1992 for (n=0;n<extraStrings.size();n++)
1993 value.push_back(extraStrings[n]);
1994 }
1995
1996 unsigned int i;
1997 for ( i=0; i<arrInt.size(); i++ )
1998 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1999
2000 if ( userStringMode == 2 )
2001 {
2002 for (n=0;n<extraStrings.size();n++)
2003 value.push_back(extraStrings[n]);
2004 }
2005
2006 variant = WXVARIANT(value);
2007
2008 SetValueInEvent(variant);
2009
2010 return true;
2011 }
2012 }
2013 return false;
2014}
2015
1c4293cb
VZ
2016bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2017{
2018 wxArrayString arr;
2019
2020 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
2021
2022 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
2023 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
2024 arr.Add(token);
2025 WX_PG_TOKENIZER2_END()
2026
2027 wxVariant v( WXVARIANT(arr) );
2028 variant = v;
2029
2030 return true;
2031}
2032
2033#endif // wxUSE_CHOICEDLG
2034
2035
2036// -----------------------------------------------------------------------
2037// wxDateProperty
2038// -----------------------------------------------------------------------
2039
2040#if wxUSE_DATETIME
2041
2042
2043#if wxUSE_DATEPICKCTRL
2044 #define dtCtrl DatePickerCtrl
2045#else
2046 #define dtCtrl TextCtrl
2047#endif
2048
2049WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
2050 wxPGProperty,
2051 wxDateTime,
2052 const wxDateTime&,
2053 dtCtrl)
2054
2055
2056wxString wxDateProperty::ms_defaultDateFormat;
2057
2058
2059wxDateProperty::wxDateProperty( const wxString& label,
2060 const wxString& name,
2061 const wxDateTime& value )
2062 : wxPGProperty(label,name)
2063{
2064 //wxPGRegisterDefaultValueType(wxDateTime)
2065
2066#if wxUSE_DATEPICKCTRL
2067 wxPGRegisterEditorClass(DatePickerCtrl);
2068
2069 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
2070#else
2071 m_dpStyle = 0;
2072#endif
2073
2074 SetValue( value );
2075}
2076
2077wxDateProperty::~wxDateProperty()
2078{
2079}
2080
b6fd0b42
JS
2081void wxDateProperty::OnSetValue()
2082{
2083 //
2084 // Convert invalid dates to unspecified value
2085 if ( m_value.GetType() == wxT("datetime") )
2086 {
2087 if ( !m_value.GetDateTime().IsValid() )
2088 m_value.MakeNull();
2089 }
2090}
2091
1c4293cb
VZ
2092bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
2093 int WXUNUSED(argFlags) ) const
2094{
2095 wxDateTime dt;
2096
09777a5b
VZ
2097 // FIXME: do we really want to return true from here if only part of the
2098 // string was parsed?
2099 const char* c = dt.ParseFormat(text);
1c4293cb
VZ
2100
2101 if ( c )
2102 {
2103 variant = dt;
2104 return true;
2105 }
2106
2107 return false;
2108}
2109
1425eca5
JS
2110wxString wxDateProperty::ValueToString( wxVariant& value,
2111 int argFlags ) const
1c4293cb
VZ
2112{
2113 const wxChar* format = (const wxChar*) NULL;
2114
1425eca5 2115 wxDateTime dateTime = value.GetDateTime();
1c4293cb
VZ
2116
2117 if ( !dateTime.IsValid() )
2118 return wxT("Invalid");
2119
2120 if ( !ms_defaultDateFormat.length() )
2121 {
2122#if wxUSE_DATEPICKCTRL
2123 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
2124#else
2125 bool showCentury = true;
2126#endif
2127 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
2128 }
2129
2130 if ( m_format.length() &&
2131 !(argFlags & wxPG_FULL_VALUE) )
2132 format = m_format.c_str();
2133
2134 // Determine default from locale
2135 // NB: This is really simple stuff, but can't figure anything
2136 // better without proper support in wxLocale
2137 if ( !format )
2138 format = ms_defaultDateFormat.c_str();
2139
2140 return dateTime.Format(format);
2141}
2142
2143wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
2144{
2145 // This code is basicly copied from datectlg.cpp's SetFormat
2146 //
2147 wxString format;
2148
2149 wxDateTime dt;
2150 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2151 wxString str(dt.Format(wxT("%x")));
2152
2153 const wxChar *p = str.c_str();
2154 while ( *p )
2155 {
2156 int n=wxAtoi(p);
2157 if (n == dt.GetDay())
2158 {
2159 format.Append(wxT("%d"));
2160 p += 2;
2161 }
2162 else if (n == (int)dt.GetMonth()+1)
2163 {
2164 format.Append(wxT("%m"));
2165 p += 2;
2166 }
2167 else if (n == dt.GetYear())
2168 {
2169 format.Append(wxT("%Y"));
2170 p += 4;
2171 }
2172 else if (n == (dt.GetYear() % 100))
2173 {
2174 if (showCentury)
2175 format.Append(wxT("%Y"));
2176 else
2177 format.Append(wxT("%y"));
2178 p += 2;
2179 }
2180 else
2181 format.Append(*p++);
2182 }
2183
2184 return format;
2185}
2186
2187bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2188{
2189 if ( name == wxPG_DATE_FORMAT )
2190 {
2191 m_format = value.GetString();
2192 return true;
2193 }
2194 else if ( name == wxPG_DATE_PICKER_STYLE )
2195 {
2196 m_dpStyle = value.GetLong();
2197 ms_defaultDateFormat.clear(); // This may need recalculation
2198 return true;
2199 }
2200 return false;
2201}
2202
2203#endif // wxUSE_DATETIME
2204
2205
2206// -----------------------------------------------------------------------
2207// wxPropertyGridInterface
2208// -----------------------------------------------------------------------
2209
2210void wxPropertyGridInterface::InitAllTypeHandlers()
2211{
2212}
2213
2214// -----------------------------------------------------------------------
2215
2216void wxPropertyGridInterface::RegisterAdditionalEditors()
2217{
c8074be0
JS
2218 // Register editor classes, if necessary.
2219 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2220 wxPropertyGrid::RegisterDefaultEditors();
2221
1c4293cb
VZ
2222#if wxUSE_SPINBTN
2223 wxPGRegisterEditorClass(SpinCtrl);
2224#endif
2225#if wxUSE_DATEPICKCTRL
2226 wxPGRegisterEditorClass(DatePickerCtrl);
2227#endif
2228}
2229
2230// -----------------------------------------------------------------------
2231
f4bc1aa2
JS
2232#endif // wxPG_INCLUDE_ADVPROPS
2233
2234#endif // wxUSE_PROPGRID
2235