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