]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/advprops.cpp
reset the tooltip text before changing it, this apparently prevents a spurious redraw...
[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
1c4293cb
VZ
1426 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1427 {
1428 // Show custom choice
1429 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1430 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1431 }
1432 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1433 {
1434 // Hide custom choice
1435 m_choices.RemoveAt(GetCustomColourIndex());
1436 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1437 }
1438 return true;
1439 }
1440 return false;
1441}
1442
1443
1444// -----------------------------------------------------------------------
1445// wxColourProperty
1446// -----------------------------------------------------------------------
1447
1448static const wxChar* gs_cp_es_normcolour_labels[] = {
1449 wxT("Black"),
1450 wxT("Maroon"),
1451 wxT("Navy"),
1452 wxT("Purple"),
1453 wxT("Teal"),
1454 wxT("Gray"),
1455 wxT("Green"),
1456 wxT("Olive"),
1457 wxT("Brown"),
1458 wxT("Blue"),
1459 wxT("Fuchsia"),
1460 wxT("Red"),
1461 wxT("Orange"),
1462 wxT("Silver"),
1463 wxT("Lime"),
1464 wxT("Aqua"),
1465 wxT("Yellow"),
1466 wxT("White"),
1467 wxT("Custom"),
1468 (const wxChar*) NULL
1469};
1470
1471static unsigned long gs_cp_es_normcolour_colours[] = {
1472 wxPG_COLOUR(0,0,0),
1473 wxPG_COLOUR(128,0,0),
1474 wxPG_COLOUR(0,0,128),
1475 wxPG_COLOUR(128,0,128),
1476 wxPG_COLOUR(0,128,128),
1477 wxPG_COLOUR(128,128,128),
1478 wxPG_COLOUR(0,128,0),
1479 wxPG_COLOUR(128,128,0),
1480 wxPG_COLOUR(166,124,81),
1481 wxPG_COLOUR(0,0,255),
1482 wxPG_COLOUR(255,0,255),
1483 wxPG_COLOUR(255,0,0),
1484 wxPG_COLOUR(247,148,28),
1485 wxPG_COLOUR(192,192,192),
1486 wxPG_COLOUR(0,255,0),
1487 wxPG_COLOUR(0,255,255),
1488 wxPG_COLOUR(255,255,0),
1489 wxPG_COLOUR(255,255,255),
1490 wxPG_COLOUR(0,0,0)
1491};
1492
d61d8cff
JS
1493WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1494 wxColour, const wxColour&, TextCtrlAndButton)
1495
1496static wxPGChoices gs_wxColourProperty_choicesCache;
1497
1498wxColourProperty::wxColourProperty( const wxString& label,
1499 const wxString& name,
1500 const wxColour& value )
1501 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1502 NULL,
1503 &gs_wxColourProperty_choicesCache, value )
1504{
1505 Init( value );
1506
1507 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1508}
1509
1510wxColourProperty::~wxColourProperty()
1511{
1512}
1513
1514void wxColourProperty::Init( wxColour colour )
1515{
1516 if ( !colour.Ok() )
1517 colour = *wxWHITE;
1518 wxVariant variant;
1519 variant << colour;
1520 m_value = variant;
1521 int ind = ColToInd(colour);
1522 if ( ind < 0 )
1523 ind = m_choices.GetCount() - 1;
1524 SetIndex( ind );
1525}
1526
1425eca5
JS
1527wxString wxColourProperty::ValueToString( wxVariant& value,
1528 int argFlags ) const
d61d8cff
JS
1529{
1530 const wxPGEditor* editor = GetEditorClass();
1531 if ( editor != wxPGEditor_Choice &&
1532 editor != wxPGEditor_ChoiceAndButton &&
1533 editor != wxPGEditor_ComboBox )
1534 argFlags |= wxPG_PROPERTY_SPECIFIC;
1535
1425eca5 1536 return wxSystemColourProperty::ValueToString(value, argFlags);
d61d8cff
JS
1537}
1538
1539wxColour wxColourProperty::GetColour( int index ) const
1540{
d61d8cff
JS
1541 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1542}
1543
1544wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1545{
1546 wxVariant variant;
1547 variant << v.m_colour;
1548 return variant;
1549}
1c4293cb
VZ
1550
1551// -----------------------------------------------------------------------
1552// wxCursorProperty
1553// -----------------------------------------------------------------------
1554
1555#define wxPG_CURSOR_IMAGE_WIDTH 32
1556
1557#define NUM_CURSORS 28
1558
1559//#define wx_cp_es_syscursors_len 28
1560static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1561 wxT("Default"),
1562 wxT("Arrow"),
1563 wxT("Right Arrow"),
1564 wxT("Blank"),
1565 wxT("Bullseye"),
1566 wxT("Character"),
1567 wxT("Cross"),
1568 wxT("Hand"),
1569 wxT("I-Beam"),
1570 wxT("Left Button"),
1571 wxT("Magnifier"),
1572 wxT("Middle Button"),
1573 wxT("No Entry"),
1574 wxT("Paint Brush"),
1575 wxT("Pencil"),
1576 wxT("Point Left"),
1577 wxT("Point Right"),
1578 wxT("Question Arrow"),
1579 wxT("Right Button"),
1580 wxT("Sizing NE-SW"),
1581 wxT("Sizing N-S"),
1582 wxT("Sizing NW-SE"),
1583 wxT("Sizing W-E"),
1584 wxT("Sizing"),
1585 wxT("Spraycan"),
1586 wxT("Wait"),
1587 wxT("Watch"),
1588 wxT("Wait Arrow"),
1589 (const wxChar*) NULL
1590};
1591
1592static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1593 wxCURSOR_NONE,
1594 wxCURSOR_ARROW,
1595 wxCURSOR_RIGHT_ARROW,
1596 wxCURSOR_BLANK,
1597 wxCURSOR_BULLSEYE,
1598 wxCURSOR_CHAR,
1599 wxCURSOR_CROSS,
1600 wxCURSOR_HAND,
1601 wxCURSOR_IBEAM,
1602 wxCURSOR_LEFT_BUTTON,
1603 wxCURSOR_MAGNIFIER,
1604 wxCURSOR_MIDDLE_BUTTON,
1605 wxCURSOR_NO_ENTRY,
1606 wxCURSOR_PAINT_BRUSH,
1607 wxCURSOR_PENCIL,
1608 wxCURSOR_POINT_LEFT,
1609 wxCURSOR_POINT_RIGHT,
1610 wxCURSOR_QUESTION_ARROW,
1611 wxCURSOR_RIGHT_BUTTON,
1612 wxCURSOR_SIZENESW,
1613 wxCURSOR_SIZENS,
1614 wxCURSOR_SIZENWSE,
1615 wxCURSOR_SIZEWE,
1616 wxCURSOR_SIZING,
1617 wxCURSOR_SPRAYCAN,
1618 wxCURSOR_WAIT,
1619 wxCURSOR_WATCH,
1620 wxCURSOR_ARROWWAIT
1621};
1622
1623IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1624
1625wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1626 int value )
1627 : wxEnumProperty( label,
1628 name,
1629 gs_cp_es_syscursors_labels,
1630 gs_cp_es_syscursors_values,
1631 value )
1632{
1633 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1634}
1635
1636wxCursorProperty::~wxCursorProperty()
1637{
1638}
1639
1640wxSize wxCursorProperty::OnMeasureImage( int item ) const
1641{
1642#if wxPG_CAN_DRAW_CURSOR
1643 if ( item != -1 && item < NUM_CURSORS )
1644 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1645#else
1646 wxUnusedVar(item);
1647#endif
1648 return wxSize(0,0);
1649}
1650
1651#if wxPG_CAN_DRAW_CURSOR
1652
1653void wxCursorProperty::OnCustomPaint( wxDC& dc,
1654 const wxRect& rect,
1655 wxPGPaintData& paintdata )
1656{
1657 // Background brush
1658 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1659
1660 if ( paintdata.m_choiceItem >= 0 )
1661 {
1662 dc.DrawRectangle( rect );
1663
1664 if ( paintdata.m_choiceItem < NUM_CURSORS )
1665 {
2399c87c
JS
1666 wxStockCursor cursorIndex =
1667 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1c4293cb
VZ
1668
1669 {
2399c87c
JS
1670 if ( cursorIndex == wxCURSOR_NONE )
1671 cursorIndex = wxCURSOR_ARROW;
1c4293cb 1672
2399c87c 1673 wxCursor cursor( cursorIndex );
1c4293cb
VZ
1674
1675 #ifdef __WXMSW__
1676 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1677 ::DrawIconEx( hDc,
1678 rect.x,
1679 rect.y,
1680 (HICON)cursor.GetHandle(),
1681 0,
1682 0,
1683 0,
1684 NULL,
591df136
JS
1685 #if !defined(__WXWINCE__)
1686 DI_COMPAT | DI_DEFAULTSIZE |
1687 #endif
1688 DI_NORMAL
1c4293cb
VZ
1689 );
1690 #endif
1691 }
1692 }
1693 }
1694}
1695
1696#else
1697void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1698/*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1699{
1700 return wxEnumProperty::GetCellRenderer(column);
1701}*/
1702#endif
1703
1704// -----------------------------------------------------------------------
1705// wxImageFileProperty
1706// -----------------------------------------------------------------------
1707
1708#if wxUSE_IMAGE
1709
1710const wxString& wxPGGetDefaultImageWildcard()
1711{
1712 // Form the wildcard, if not done yet
1713 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1714 {
1715
1716 wxString str;
1717
1718 // TODO: This section may require locking (using global).
1719
1720 wxList& handlers = wxImage::GetHandlers();
1721
1722 wxList::iterator node;
1723
1724 // Let's iterate over the image handler list.
1725 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
b7bc9d80 1726 for ( node = handlers.begin(); node != handlers.end(); ++node )
1c4293cb
VZ
1727 {
1728 wxImageHandler *handler = (wxImageHandler*)*node;
1729
1730 wxString ext_lo = handler->GetExtension();
1731 wxString ext_up = ext_lo.Upper();
1732
1733 str.append( ext_up );
1734 str.append( wxT(" files (*.") );
1735 str.append( ext_up );
1736 str.append( wxT(")|*.") );
1737 str.append( ext_lo );
1738 str.append( wxT("|") );
1739 }
1740
1741 str.append ( wxT("All files (*.*)|*.*") );
1742
1743 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1744 }
1745
1746 return wxPGGlobalVars->m_pDefaultImageWildcard;
1747}
1748
d53f610c 1749IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1c4293cb
VZ
1750
1751wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1752 const wxString& value )
1753 : wxFileProperty(label,name,value)
1754{
1755 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1756
d3b9f782
VZ
1757 m_pImage = NULL;
1758 m_pBitmap = NULL;
1c4293cb
VZ
1759}
1760
1761wxImageFileProperty::~wxImageFileProperty()
1762{
1763 if ( m_pBitmap )
1764 delete m_pBitmap;
1765 if ( m_pImage )
1766 delete m_pImage;
1767}
1768
1769void wxImageFileProperty::OnSetValue()
1770{
1771 wxFileProperty::OnSetValue();
1772
1773 // Delete old image
1774 if ( m_pImage )
1775 {
1776 delete m_pImage;
1777 m_pImage = NULL;
1778 }
1779 if ( m_pBitmap )
1780 {
1781 delete m_pBitmap;
1782 m_pBitmap = NULL;
1783 }
1784
1425eca5
JS
1785 wxFileName filename = GetFileName();
1786
1c4293cb 1787 // Create the image thumbnail
1425eca5 1788 if ( filename.FileExists() )
1c4293cb 1789 {
1425eca5 1790 m_pImage = new wxImage( filename.GetFullPath() );
1c4293cb
VZ
1791 }
1792}
1793
1794wxSize wxImageFileProperty::OnMeasureImage( int ) const
1795{
1796 return wxPG_DEFAULT_IMAGE_SIZE;
1797}
1798
1799void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1800 const wxRect& rect,
1801 wxPGPaintData& )
1802{
1803 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1804 {
1805 // Draw the thumbnail
1806
1807 // Create the bitmap here because required size is not known in OnSetValue().
1808 if ( !m_pBitmap )
1809 {
1810 m_pImage->Rescale( rect.width, rect.height );
1811 m_pBitmap = new wxBitmap( *m_pImage );
1812 delete m_pImage;
1813 m_pImage = NULL;
1814 }
1815
1816 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1817 }
1818 else
1819 {
1820 // No file - just draw a white box
1821 dc.SetBrush( *wxWHITE_BRUSH );
1822 dc.DrawRectangle ( rect );
1823 }
1824}
1825
1826#endif // wxUSE_IMAGE
1827
1828// -----------------------------------------------------------------------
1829// wxMultiChoiceProperty
1830// -----------------------------------------------------------------------
1831
1832#if wxUSE_CHOICEDLG
1833
3b211af1 1834#include "wx/choicdlg.h"
1c4293cb
VZ
1835
1836WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1837 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1838
1839wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1840 const wxString& name,
1841 const wxPGChoices& choices,
1842 const wxArrayString& value)
1843 : wxPGProperty(label,name)
1844{
1845 m_choices.Assign(choices);
1846 SetValue(value);
1847}
1848
1849wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1850 const wxString& name,
1851 const wxArrayString& strings,
1852 const wxArrayString& value)
1853 : wxPGProperty(label,name)
1854{
1855 m_choices.Set(strings);
1856 SetValue(value);
1857}
1858
1859wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1860 const wxString& name,
1861 const wxArrayString& value)
1862 : wxPGProperty(label,name)
1863{
1864 wxArrayString strings;
1865 m_choices.Set(strings);
1866 SetValue(value);
1867}
1868
1869wxMultiChoiceProperty::~wxMultiChoiceProperty()
1870{
1871}
1872
1873void wxMultiChoiceProperty::OnSetValue()
1874{
102c9a42 1875 GenerateValueAsString(m_value, &m_display);
1c4293cb
VZ
1876}
1877
1425eca5
JS
1878wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1879 int argFlags ) const
1c4293cb 1880{
1425eca5
JS
1881 // If possible, use cached string
1882 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1883 return m_display;
1884
1885 wxString s;
102c9a42 1886 GenerateValueAsString(value, &s);
1425eca5 1887 return s;
1c4293cb
VZ
1888}
1889
102c9a42
JS
1890void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1891 wxString* target ) const
1c4293cb
VZ
1892{
1893 wxArrayString strings;
1894
102c9a42
JS
1895 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1896 strings = value.GetArrayString();
1c4293cb 1897
1425eca5 1898 wxString& tempStr = *target;
1c4293cb
VZ
1899 unsigned int i;
1900 unsigned int itemCount = strings.size();
1901
1902 tempStr.Empty();
1903
1904 if ( itemCount )
1905 tempStr.append( wxT("\"") );
1906
1907 for ( i = 0; i < itemCount; i++ )
1908 {
1909 tempStr.append( strings[i] );
1910 tempStr.append( wxT("\"") );
1911 if ( i < (itemCount-1) )
1912 tempStr.append ( wxT(" \"") );
1913 }
1914}
1915
1916wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1917{
bfad4a15
JS
1918 wxVariant variant = GetValue();
1919 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant);
1c4293cb
VZ
1920 unsigned int i;
1921
1922 // Translate values to string indices.
1923 wxArrayInt selections;
1924
1925 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1926 {
1927 for ( i=0; i<valueArr.size(); i++ )
1928 selections.Add(-1);
1929 }
1930 else
1931 {
1932 for ( i=0; i<valueArr.size(); i++ )
1933 {
1934 int sIndex = m_choices.Index(valueArr[i]);
1935 if ( sIndex >= 0 )
1936 selections.Add(sIndex);
1937 }
1938 }
1939
1940 return selections;
1941}
1942
1943bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1944 wxWindow* WXUNUSED(primary),
1945 wxEvent& event )
1946{
1947 if ( propgrid->IsMainButtonEvent(event) )
1948 {
1949 // Update the value
703ee9f5 1950 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
1951
1952 wxArrayString labels = m_choices.GetLabels();
1953 unsigned int choiceCount;
1954
1955 if ( m_choices.IsOk() )
1956 choiceCount = m_choices.GetCount();
1957 else
1958 choiceCount = 0;
1959
1960 // launch editor dialog
1961 wxMultiChoiceDialog dlg( propgrid,
1962 _("Make a selection:"),
1963 m_label,
1964 choiceCount,
1965 choiceCount?&labels[0]:NULL,
1966 wxCHOICEDLG_STYLE );
1967
1968 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1969
9b5bafcf 1970 wxArrayString strings = useValue.GetArrayString();
1c4293cb
VZ
1971 wxArrayString extraStrings;
1972
1973 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1974
1975 if ( dlg.ShowModal() == wxID_OK && choiceCount )
1976 {
1977 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1978
1979 wxArrayInt arrInt = dlg.GetSelections();
1980
1981 wxVariant variant;
1982
1983 // Strings that were not in list of choices
1984 wxArrayString value;
1985
1986 // Translate string indices to strings
1987
1988 unsigned int n;
1989 if ( userStringMode == 1 )
1990 {
1991 for (n=0;n<extraStrings.size();n++)
1992 value.push_back(extraStrings[n]);
1993 }
1994
1995 unsigned int i;
1996 for ( i=0; i<arrInt.size(); i++ )
1997 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1998
1999 if ( userStringMode == 2 )
2000 {
2001 for (n=0;n<extraStrings.size();n++)
2002 value.push_back(extraStrings[n]);
2003 }
2004
2005 variant = WXVARIANT(value);
2006
2007 SetValueInEvent(variant);
2008
2009 return true;
2010 }
2011 }
2012 return false;
2013}
2014
1c4293cb
VZ
2015bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2016{
2017 wxArrayString arr;
2018
2019 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
2020
2021 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
2022 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
2023 arr.Add(token);
2024 WX_PG_TOKENIZER2_END()
2025
2026 wxVariant v( WXVARIANT(arr) );
2027 variant = v;
2028
2029 return true;
2030}
2031
2032#endif // wxUSE_CHOICEDLG
2033
2034
2035// -----------------------------------------------------------------------
2036// wxDateProperty
2037// -----------------------------------------------------------------------
2038
2039#if wxUSE_DATETIME
2040
2041
2042#if wxUSE_DATEPICKCTRL
2043 #define dtCtrl DatePickerCtrl
2044#else
2045 #define dtCtrl TextCtrl
2046#endif
2047
2048WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
2049 wxPGProperty,
2050 wxDateTime,
2051 const wxDateTime&,
2052 dtCtrl)
2053
2054
2055wxString wxDateProperty::ms_defaultDateFormat;
2056
2057
2058wxDateProperty::wxDateProperty( const wxString& label,
2059 const wxString& name,
2060 const wxDateTime& value )
2061 : wxPGProperty(label,name)
2062{
2063 //wxPGRegisterDefaultValueType(wxDateTime)
2064
2065#if wxUSE_DATEPICKCTRL
2066 wxPGRegisterEditorClass(DatePickerCtrl);
2067
2068 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
2069#else
2070 m_dpStyle = 0;
2071#endif
2072
2073 SetValue( value );
2074}
2075
2076wxDateProperty::~wxDateProperty()
2077{
2078}
2079
b6fd0b42
JS
2080void wxDateProperty::OnSetValue()
2081{
2082 //
2083 // Convert invalid dates to unspecified value
2084 if ( m_value.GetType() == wxT("datetime") )
2085 {
2086 if ( !m_value.GetDateTime().IsValid() )
2087 m_value.MakeNull();
2088 }
2089}
2090
1c4293cb
VZ
2091bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
2092 int WXUNUSED(argFlags) ) const
2093{
2094 wxDateTime dt;
2095
2096 const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
2097
2098 if ( c )
2099 {
2100 variant = dt;
2101 return true;
2102 }
2103
2104 return false;
2105}
2106
1425eca5
JS
2107wxString wxDateProperty::ValueToString( wxVariant& value,
2108 int argFlags ) const
1c4293cb
VZ
2109{
2110 const wxChar* format = (const wxChar*) NULL;
2111
1425eca5 2112 wxDateTime dateTime = value.GetDateTime();
1c4293cb
VZ
2113
2114 if ( !dateTime.IsValid() )
2115 return wxT("Invalid");
2116
2117 if ( !ms_defaultDateFormat.length() )
2118 {
2119#if wxUSE_DATEPICKCTRL
2120 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
2121#else
2122 bool showCentury = true;
2123#endif
2124 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
2125 }
2126
2127 if ( m_format.length() &&
2128 !(argFlags & wxPG_FULL_VALUE) )
2129 format = m_format.c_str();
2130
2131 // Determine default from locale
2132 // NB: This is really simple stuff, but can't figure anything
2133 // better without proper support in wxLocale
2134 if ( !format )
2135 format = ms_defaultDateFormat.c_str();
2136
2137 return dateTime.Format(format);
2138}
2139
2140wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
2141{
2142 // This code is basicly copied from datectlg.cpp's SetFormat
2143 //
2144 wxString format;
2145
2146 wxDateTime dt;
2147 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2148 wxString str(dt.Format(wxT("%x")));
2149
2150 const wxChar *p = str.c_str();
2151 while ( *p )
2152 {
2153 int n=wxAtoi(p);
2154 if (n == dt.GetDay())
2155 {
2156 format.Append(wxT("%d"));
2157 p += 2;
2158 }
2159 else if (n == (int)dt.GetMonth()+1)
2160 {
2161 format.Append(wxT("%m"));
2162 p += 2;
2163 }
2164 else if (n == dt.GetYear())
2165 {
2166 format.Append(wxT("%Y"));
2167 p += 4;
2168 }
2169 else if (n == (dt.GetYear() % 100))
2170 {
2171 if (showCentury)
2172 format.Append(wxT("%Y"));
2173 else
2174 format.Append(wxT("%y"));
2175 p += 2;
2176 }
2177 else
2178 format.Append(*p++);
2179 }
2180
2181 return format;
2182}
2183
2184bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2185{
2186 if ( name == wxPG_DATE_FORMAT )
2187 {
2188 m_format = value.GetString();
2189 return true;
2190 }
2191 else if ( name == wxPG_DATE_PICKER_STYLE )
2192 {
2193 m_dpStyle = value.GetLong();
2194 ms_defaultDateFormat.clear(); // This may need recalculation
2195 return true;
2196 }
2197 return false;
2198}
2199
2200#endif // wxUSE_DATETIME
2201
2202
2203// -----------------------------------------------------------------------
2204// wxPropertyGridInterface
2205// -----------------------------------------------------------------------
2206
2207void wxPropertyGridInterface::InitAllTypeHandlers()
2208{
2209}
2210
2211// -----------------------------------------------------------------------
2212
2213void wxPropertyGridInterface::RegisterAdditionalEditors()
2214{
c8074be0
JS
2215 // Register editor classes, if necessary.
2216 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2217 wxPropertyGrid::RegisterDefaultEditors();
2218
1c4293cb
VZ
2219#if wxUSE_SPINBTN
2220 wxPGRegisterEditorClass(SpinCtrl);
2221#endif
2222#if wxUSE_DATEPICKCTRL
2223 wxPGRegisterEditorClass(DatePickerCtrl);
2224#endif
2225}
2226
2227// -----------------------------------------------------------------------
2228
f4bc1aa2
JS
2229#endif // wxPG_INCLUDE_ADVPROPS
2230
2231#endif // wxUSE_PROPGRID
2232