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