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