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