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