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