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