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