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