]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/advprops.cpp
Add wxGrid::RefreshAttr() method to force attribute refresh.
[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 8// Copyright: (c) Jaakko Salli
526954c5 9// Licence: wxWindows licence
1c4293cb
VZ
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 557
30fad74e
JS
558//
559// NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar*
560//
561
a243da29 562static const wxChar* const gs_fp_es_family_labels[] = {
30fad74e
JS
563 wxT("Default"), wxT("Decorative"),
564 wxT("Roman"), wxT("Script"),
565 wxT("Swiss"), wxT("Modern"),
566 wxT("Teletype"), wxT("Unknown"),
1c4293cb
VZ
567 (const wxChar*) NULL
568};
569
a243da29 570static const long gs_fp_es_family_values[] = {
9867e3e4
JS
571 wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE,
572 wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT,
573 wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN,
574 wxFONTFAMILY_TELETYPE, wxFONTFAMILY_UNKNOWN
1c4293cb
VZ
575};
576
a243da29 577static const wxChar* const gs_fp_es_style_labels[] = {
1c4293cb
VZ
578 wxT("Normal"),
579 wxT("Slant"),
580 wxT("Italic"),
581 (const wxChar*) NULL
582};
583
a243da29 584static const long gs_fp_es_style_values[] = {
1c4293cb
VZ
585 wxNORMAL,
586 wxSLANT,
587 wxITALIC
588};
589
a243da29 590static const wxChar* const gs_fp_es_weight_labels[] = {
1c4293cb
VZ
591 wxT("Normal"),
592 wxT("Light"),
593 wxT("Bold"),
594 (const wxChar*) NULL
595};
596
a243da29 597static const long gs_fp_es_weight_values[] = {
1c4293cb
VZ
598 wxNORMAL,
599 wxLIGHT,
600 wxBOLD
601};
602
603// Class body is in advprops.h
604
605
606WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,
607 wxFont,const wxFont&,TextCtrlAndButton)
608
609
610wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
611 const wxFont& value )
612 : wxPGProperty(label,name)
613{
0372d42e 614 SetValue(WXVARIANT(value));
1c4293cb
VZ
615
616 // Initialize font family choices list
617 if ( !wxPGGlobalVars->m_fontFamilyChoices )
618 {
b7bc9d80 619 wxArrayString faceNames = wxFontEnumerator::GetFacenames();
1c4293cb
VZ
620
621 faceNames.Sort();
622
623 wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
624 }
625
626 wxString emptyString(wxEmptyString);
627
0372d42e
JS
628 wxFont font;
629 font << m_value;
1c4293cb 630
48a32cf6
JS
631 AddPrivateChild( new wxIntProperty( _("Point Size"),
632 wxS("Point Size"),(long)font.GetPointSize() ) );
2fd4a524 633
1c4293cb
VZ
634 wxString faceName = font.GetFaceName();
635 // If font was not in there, add it now
636 if ( faceName.length() &&
637 wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
638 wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
639
d665918b 640 wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"),
1c4293cb
VZ
641 *wxPGGlobalVars->m_fontFamilyChoices);
642
643 p->SetValueFromString(faceName, wxPG_FULL_VALUE);
644
48a32cf6 645 AddPrivateChild( p );
1c4293cb 646
48a32cf6
JS
647 AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
648 gs_fp_es_style_labels,gs_fp_es_style_values,
649 font.GetStyle()) );
1c4293cb 650
48a32cf6
JS
651 AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
652 gs_fp_es_weight_labels,gs_fp_es_weight_values,
653 font.GetWeight()) );
1c4293cb 654
48a32cf6
JS
655 AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
656 font.GetUnderlined()) );
9867e3e4
JS
657
658 AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
659 gs_fp_es_family_labels,gs_fp_es_family_values,
660 font.GetFamily()) );
1c4293cb
VZ
661}
662
663wxFontProperty::~wxFontProperty() { }
664
665void wxFontProperty::OnSetValue()
666{
0372d42e
JS
667 wxFont font;
668 font << m_value;
1c4293cb 669
1c4293cb 670 if ( !font.Ok() )
0372d42e 671 {
9a1eabd4 672 m_value << *wxNORMAL_FONT;
0372d42e 673 }
1c4293cb
VZ
674}
675
1425eca5
JS
676wxString wxFontProperty::ValueToString( wxVariant& value,
677 int argFlags ) const
1c4293cb 678{
1425eca5 679 return wxPGProperty::ValueToString(value, argFlags);
1c4293cb
VZ
680}
681
682bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
683 wxEvent& event )
684{
685 if ( propgrid->IsMainButtonEvent(event) )
686 {
687 // Update value from last minute changes
703ee9f5 688 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
689
690 wxFontData data;
0372d42e 691 wxFont font;
47450ed1
JS
692
693 if ( useValue.GetType() == wxS("wxFont") )
694 font << useValue;
695
0372d42e 696 data.SetInitialFont( font );
1c4293cb
VZ
697 data.SetColour(*wxBLACK);
698
699 wxFontDialog dlg(propgrid, data);
700 if ( dlg.ShowModal() == wxID_OK )
701 {
702 propgrid->EditorsValueWasModified();
703
0372d42e
JS
704 wxVariant variant;
705 variant << dlg.GetFontData().GetChosenFont();
1c4293cb
VZ
706 SetValueInEvent( variant );
707 return true;
708 }
709 }
710 return false;
711}
712
713void wxFontProperty::RefreshChildren()
714{
715 if ( !GetChildCount() ) return;
0372d42e
JS
716 wxFont font;
717 font << m_value;
1c4293cb 718 Item(0)->SetValue( (long)font.GetPointSize() );
9867e3e4
JS
719 Item(1)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
720 Item(2)->SetValue( (long)font.GetStyle() );
721 Item(3)->SetValue( (long)font.GetWeight() );
722 Item(4)->SetValue( font.GetUnderlined() );
723 Item(5)->SetValue( (long)font.GetFamily() );
1c4293cb
VZ
724}
725
b8b1ff48
JS
726wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue,
727 int ind,
728 wxVariant& childValue ) const
1c4293cb 729{
0372d42e
JS
730 wxFont font;
731 font << thisValue;
1c4293cb
VZ
732
733 if ( ind == 0 )
734 {
4e00b908 735 font.SetPointSize( childValue.GetLong() );
1c4293cb
VZ
736 }
737 else if ( ind == 1 )
1c4293cb
VZ
738 {
739 wxString faceName;
740 int faceIndex = childValue.GetLong();
741
742 if ( faceIndex >= 0 )
743 faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
744
745 font.SetFaceName( faceName );
746 }
9867e3e4 747 else if ( ind == 2 )
1c4293cb
VZ
748 {
749 int st = childValue.GetLong();
750 if ( st != wxFONTSTYLE_NORMAL &&
751 st != wxFONTSTYLE_SLANT &&
752 st != wxFONTSTYLE_ITALIC )
753 st = wxFONTWEIGHT_NORMAL;
754 font.SetStyle( st );
755 }
9867e3e4 756 else if ( ind == 3 )
1c4293cb
VZ
757 {
758 int wt = childValue.GetLong();
759 if ( wt != wxFONTWEIGHT_NORMAL &&
760 wt != wxFONTWEIGHT_LIGHT &&
761 wt != wxFONTWEIGHT_BOLD )
762 wt = wxFONTWEIGHT_NORMAL;
763 font.SetWeight( wt );
764 }
9867e3e4 765 else if ( ind == 4 )
1c4293cb
VZ
766 {
767 font.SetUnderlined( childValue.GetBool() );
768 }
9867e3e4
JS
769 else if ( ind == 5 )
770 {
771 int fam = childValue.GetLong();
772 if ( fam < wxDEFAULT ||
773 fam > wxTELETYPE )
774 fam = wxDEFAULT;
775 font.SetFamily( fam );
776 }
0372d42e 777
b8b1ff48
JS
778 wxVariant newVariant;
779 newVariant << font;
780 return newVariant;
1c4293cb
VZ
781}
782
783/*
784wxSize wxFontProperty::OnMeasureImage() const
785{
786 return wxSize(-1,-1);
787}
788
789void wxFontProperty::OnCustomPaint(wxDC& dc,
790 const wxRect& rect,
791 wxPGPaintData& paintData)
792{
793 wxString drawFace;
794 if ( paintData.m_choiceItem >= 0 )
795 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
796 else
797 drawFace = m_value_wxFont.GetFaceName();
798
799 if ( drawFace.length() )
800 {
801 // Draw the background
802 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
803 //dc.SetBrush( *wxWHITE_BRUSH );
804 //dc.SetPen( *wxMEDIUM_GREY_PEN );
805 dc.DrawRectangle( rect );
806
807 wxFont oldFont = dc.GetFont();
808 wxFont drawFont(oldFont.GetPointSize(),
809 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
810 dc.SetFont(drawFont);
811
812 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
813 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
814
815 dc.SetFont(oldFont);
816 }
817 else
818 {
819 // No file - just draw a white box
820 dc.SetBrush ( *wxWHITE_BRUSH );
821 dc.DrawRectangle ( rect );
822 }
823}
824*/
825
826
827// -----------------------------------------------------------------------
828// wxSystemColourProperty
829// -----------------------------------------------------------------------
830
831// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
832#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
833
3b211af1 834#include "wx/colordlg.h"
1c4293cb
VZ
835
836//#define wx_cp_es_syscolours_len 25
a243da29 837static const wxChar* const gs_cp_es_syscolour_labels[] = {
1c4293cb
VZ
838 wxT("AppWorkspace"),
839 wxT("ActiveBorder"),
840 wxT("ActiveCaption"),
841 wxT("ButtonFace"),
842 wxT("ButtonHighlight"),
843 wxT("ButtonShadow"),
844 wxT("ButtonText"),
845 wxT("CaptionText"),
846 wxT("ControlDark"),
847 wxT("ControlLight"),
848 wxT("Desktop"),
849 wxT("GrayText"),
850 wxT("Highlight"),
851 wxT("HighlightText"),
852 wxT("InactiveBorder"),
853 wxT("InactiveCaption"),
854 wxT("InactiveCaptionText"),
855 wxT("Menu"),
856 wxT("Scrollbar"),
857 wxT("Tooltip"),
858 wxT("TooltipText"),
859 wxT("Window"),
860 wxT("WindowFrame"),
861 wxT("WindowText"),
862 wxT("Custom"),
863 (const wxChar*) NULL
864};
865
a243da29 866static const long gs_cp_es_syscolour_values[] = {
1c4293cb
VZ
867 wxSYS_COLOUR_APPWORKSPACE,
868 wxSYS_COLOUR_ACTIVEBORDER,
869 wxSYS_COLOUR_ACTIVECAPTION,
870 wxSYS_COLOUR_BTNFACE,
871 wxSYS_COLOUR_BTNHIGHLIGHT,
872 wxSYS_COLOUR_BTNSHADOW,
873 wxSYS_COLOUR_BTNTEXT ,
874 wxSYS_COLOUR_CAPTIONTEXT,
875 wxSYS_COLOUR_3DDKSHADOW,
876 wxSYS_COLOUR_3DLIGHT,
877 wxSYS_COLOUR_BACKGROUND,
878 wxSYS_COLOUR_GRAYTEXT,
879 wxSYS_COLOUR_HIGHLIGHT,
880 wxSYS_COLOUR_HIGHLIGHTTEXT,
881 wxSYS_COLOUR_INACTIVEBORDER,
882 wxSYS_COLOUR_INACTIVECAPTION,
883 wxSYS_COLOUR_INACTIVECAPTIONTEXT,
884 wxSYS_COLOUR_MENU,
885 wxSYS_COLOUR_SCROLLBAR,
886 wxSYS_COLOUR_INFOBK,
887 wxSYS_COLOUR_INFOTEXT,
888 wxSYS_COLOUR_WINDOW,
889 wxSYS_COLOUR_WINDOWFRAME,
890 wxSYS_COLOUR_WINDOWTEXT,
891 wxPG_COLOUR_CUSTOM
892};
893
894
0372d42e 895IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
1c4293cb
VZ
896
897
898// Class body is in advprops.h
899
900WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
901 wxColourPropertyValue,const wxColourPropertyValue&,Choice)
902
903
904void wxSystemColourProperty::Init( int type, const wxColour& colour )
905{
906 wxColourPropertyValue cpv;
907
908 if ( colour.Ok() )
909 cpv.Init( type, colour );
910 else
911 cpv.Init( type, *wxWHITE );
912
913 m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
914
0372d42e 915 m_value << cpv;
1c4293cb
VZ
916
917 OnSetValue();
918}
919
920
921static wxPGChoices gs_wxSystemColourProperty_choicesCache;
922
923
924wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
925 const wxColourPropertyValue& value )
926 : wxEnumProperty( label,
927 name,
928 gs_cp_es_syscolour_labels,
929 gs_cp_es_syscolour_values,
930 &gs_wxSystemColourProperty_choicesCache )
931{
932 if ( &value )
933 Init( value.m_type, value.m_colour );
934 else
935 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
936}
937
938
939wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
a243da29 940 const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
1c4293cb
VZ
941 const wxColourPropertyValue& value )
942 : wxEnumProperty( label, name, labels, values, choicesCache )
943{
944 if ( &value )
945 Init( value.m_type, value.m_colour );
946 else
947 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
948}
949
950
951wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
a243da29 952 const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
1c4293cb
VZ
953 const wxColour& value )
954 : wxEnumProperty( label, name, labels, values, choicesCache )
955{
956 if ( &value )
957 Init( wxPG_COLOUR_CUSTOM, value );
958 else
959 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
960}
961
962
963wxSystemColourProperty::~wxSystemColourProperty() { }
964
965
966wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
967{
968 if ( !pVariant )
969 pVariant = &m_value;
970
971 if ( pVariant->IsNull() )
972 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
973
0372d42e
JS
974 if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
975 {
976 wxColourPropertyValue v;
977 v << *pVariant;
978 return v;
979 }
1c4293cb 980
1c4293cb
VZ
981 wxColour col;
982 bool variantProcessed = true;
983
0372d42e 984 if ( pVariant->GetType() == wxS("wxColour*") )
1c4293cb 985 {
0372d42e 986 wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
1c4293cb
VZ
987 col = *pCol;
988 }
0372d42e 989 else if ( pVariant->GetType() == wxS("wxColour") )
1c4293cb 990 {
0372d42e
JS
991 col << *pVariant;
992 }
993 else if ( pVariant->GetType() == wxArrayInt_VariantType )
994 {
995 // This code is mostly needed for wxPython bindings, which
996 // may offer tuple of integers as colour value.
1c4293cb
VZ
997 wxArrayInt arr;
998 arr << *pVariant;
999
1000 if ( arr.size() >= 3 )
1001 {
1002 int r, g, b;
1003 int a = 255;
1004
1005 r = arr[0];
1006 g = arr[1];
1007 b = arr[2];
1008 if ( arr.size() >= 4 )
1009 a = arr[3];
1010
1011 col = wxColour(r, g, b, a);
1012 }
1013 else
1014 {
1015 variantProcessed = false;
1016 }
1017 }
1c4293cb
VZ
1018 else
1019 {
1020 variantProcessed = false;
1021 }
1022
1023 if ( !variantProcessed )
1024 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
1025
1026 wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
1027
1028 int colInd = ColToInd(col);
1029 if ( colInd != wxNOT_FOUND )
1030 v2.m_type = colInd;
1031
1032 return v2;
1033}
1034
1035wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1036{
0372d42e
JS
1037 wxVariant variant;
1038 variant << v;
1039 return variant;
1c4293cb
VZ
1040}
1041
1042int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
1043{
1044 size_t i;
5f7c24e2
JS
1045 size_t i_max = m_choices.GetCount();
1046
1047 if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1048 i_max -= 1;
1c4293cb
VZ
1049
1050 for ( i=0; i<i_max; i++ )
1051 {
1052 int ind = m_choices[i].GetValue();
1053
1054 if ( colour == GetColour(ind) )
1055 {
1056 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1057 GetClassName(),GetLabel().c_str(),
1058 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1059 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1060 return ind;
1061 }
1062 }
1063 return wxNOT_FOUND;
1064}
1065
1c4293cb
VZ
1066void wxSystemColourProperty::OnSetValue()
1067{
1068 // Convert from generic wxobject ptr to wxPGVariantDataColour
0372d42e 1069 if ( m_value.GetType() == wxS("wxColour*") )
1c4293cb 1070 {
0372d42e 1071 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
1c4293cb
VZ
1072 m_value << *pCol;
1073 }
1074
1075 wxColourPropertyValue val = GetVal(&m_value);
1076
1077 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
1078 {
1079 m_value.MakeNull();
1080 return;
1081 }
1082 else
1083 {
1084
1085 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
1086 val.m_colour = GetColour( val.m_type );
1087
1088 m_value = TranslateVal(val);
1089 }
1090
b0f0eda8 1091 int ind = wxNOT_FOUND;
1c4293cb 1092
0372d42e 1093 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
1c4293cb 1094 {
0372d42e
JS
1095 wxColourPropertyValue cpv;
1096 cpv << m_value;
1097 wxColour col = cpv.m_colour;
1c4293cb 1098
0372d42e
JS
1099 if ( !col.Ok() )
1100 {
1101 SetValueToUnspecified();
1102 SetIndex(wxNOT_FOUND);
1103 return;
1104 }
1c4293cb 1105
5f7c24e2
JS
1106 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ||
1107 (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb 1108 {
98c04633 1109 ind = GetIndexForValue(cpv.m_type);
1c4293cb
VZ
1110 }
1111 else
1112 {
0372d42e 1113 cpv.m_type = wxPG_COLOUR_CUSTOM;
1c4293cb
VZ
1114 ind = GetCustomColourIndex();
1115 }
1116 }
1117 else
1118 {
0372d42e
JS
1119 wxColour col;
1120 col << m_value;
1121
1122 if ( !col.Ok() )
1123 {
1124 SetValueToUnspecified();
1125 SetIndex(wxNOT_FOUND);
1126 return;
1127 }
1128
1c4293cb
VZ
1129 ind = ColToInd(col);
1130
5f7c24e2
JS
1131 if ( ind == wxNOT_FOUND &&
1132 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb
VZ
1133 ind = GetCustomColourIndex();
1134 }
1135
1136 SetIndex(ind);
1137}
1138
1139
1140wxColour wxSystemColourProperty::GetColour( int index ) const
1141{
1142 return wxSystemSettings::GetColour( (wxSystemColour)index );
1143}
1144
1145wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
1146{
1147 if ( index == wxNOT_FOUND )
1148 return wxString::Format(wxT("(%i,%i,%i)"),
1149 (int)col.Red(),
1150 (int)col.Green(),
1151 (int)col.Blue());
1152 else
1153 return m_choices.GetLabel(index);
1154}
1155
1425eca5 1156wxString wxSystemColourProperty::ValueToString( wxVariant& value,
c9049646 1157 int argFlags ) const
1c4293cb 1158{
1425eca5 1159 wxColourPropertyValue val = GetVal(&value);
1c4293cb 1160
c9049646
JS
1161 int index;
1162
1163 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1164 {
1165 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1166 // but we should use it whenever possible.
1167 index = GetIndex();
1168
1169 // If custom colour was selected, use invalid index, so that
1170 // ColourToString() will return properly formatted colour text.
5f7c24e2
JS
1171 if ( index == GetCustomColourIndex() &&
1172 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
c9049646
JS
1173 index = wxNOT_FOUND;
1174 }
1175 else
1176 {
1177 index = m_choices.Index(val.m_type);
1178 }
1179
1180 return ColourToString(val.m_colour, index);
1c4293cb
VZ
1181}
1182
1183
1184wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1185{
1186 return wxPG_DEFAULT_IMAGE_SIZE;
1187}
1188
1189
1190int wxSystemColourProperty::GetCustomColourIndex() const
1191{
1192 return m_choices.GetCount() - 1;
1193}
1194
1195
1196bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1197{
0372d42e 1198 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1c4293cb
VZ
1199 bool res = false;
1200
1201 wxPropertyGrid* propgrid = GetGrid();
1202 wxASSERT( propgrid );
1203
1204 // Must only occur when user triggers event
b0996c3d 1205 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
1c4293cb
VZ
1206 return res;
1207
1208 wxColourPropertyValue val = GetVal();
1209
1210 val.m_type = wxPG_COLOUR_CUSTOM;
1211
1212 wxColourData data;
1213 data.SetChooseFull(true);
1214 data.SetColour(val.m_colour);
1215 int i;
1216 for ( i = 0; i < 16; i++)
1217 {
1218 wxColour colour(i*16, i*16, i*16);
1219 data.SetCustomColour(i, colour);
1220 }
1221
1222 wxColourDialog dialog(propgrid, &data);
1223 if ( dialog.ShowModal() == wxID_OK )
1224 {
1225 wxColourData retData = dialog.GetColourData();
1226 val.m_colour = retData.GetColour();
1227
1228 variant = DoTranslateVal(val);
1229
1230 SetValueInEvent(variant);
1231
1232 res = true;
1233 }
1234
1235 return res;
1236}
1237
1238
1239bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1240{
1241 int index = number;
78f2d746 1242 int type = m_choices.GetValue(index);
1c4293cb 1243
98c04633 1244 if ( type == wxPG_COLOUR_CUSTOM )
1c4293cb
VZ
1245 {
1246 QueryColourFromUser(variant);
1247 }
1248 else
1249 {
1250 variant = TranslateVal( type, GetColour(type) );
1251 }
1252
1253 return true;
1254}
1255
1256// Need to do some extra event handling.
858102d7
JS
1257bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid,
1258 wxWindow* WXUNUSED(primary),
1259 wxEvent& event )
1c4293cb 1260{
858102d7
JS
1261 bool askColour = false;
1262
1c4293cb 1263 if ( propgrid->IsMainButtonEvent(event) )
858102d7 1264 {
fbbde249
JS
1265 // We need to handle button click in case editor has been
1266 // switched to one that has wxButton as well.
858102d7
JS
1267 askColour = true;
1268 }
1269 else if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
1270 {
03647350
VZ
1271 // Must override index detection since at this point GetIndex()
1272 // will return old value.
1273 wxOwnerDrawnComboBox* cb =
1274 static_cast<wxOwnerDrawnComboBox*>(propgrid->GetEditorControl());
1275
1276 if ( cb )
1277 {
1278 int index = cb->GetSelection();
1279
1280 if ( index == GetCustomColourIndex() &&
1281 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1282 askColour = true;
1283 }
858102d7
JS
1284 }
1285
eddcc4b4 1286 if ( askColour && !propgrid->WasValueChangedInEvent() )
1c4293cb 1287 {
1c4293cb
VZ
1288 wxVariant variant;
1289 if ( QueryColourFromUser(variant) )
1290 return true;
1291 }
1292 return false;
1293}
1294
1295/*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1296{
1297public:
1298 virtual void Render( wxDC& dc, const wxRect& rect,
1299 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1300 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1301 {
1302 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1303 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1304
1305 dc.SetPen(*wxBLACK_PEN);
1306 if ( item >= 0 &&
1307 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1308 )
1309 {
1310 int colInd;
1311 const wxArrayInt& values = prop->GetValues();
1312 if ( values.GetChildCount() )
1313 colInd = values[item];
1314 else
1315 colInd = item;
1316 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1317 }
1318 else if ( !prop->IsValueUnspecified() )
1319 dc.SetBrush( prop->GetVal().m_colour );
1320 else
1321 dc.SetBrush( *wxWHITE );
1322
1323 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1324 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1325 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1326 imageRect.width, imageRect.height );
1327
1328 wxString text;
1329 if ( item == -1 )
1330 text = property->GetValueAsString();
1331 else
1332 text = property->GetChoiceString(item);
1333 DrawText( dc, rect, imageRect.width, text );
1334 }
1335protected:
1336};
1337
1338wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1339
1340wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1341{
1342 if ( column == 1 )
1343 return &g_wxPGColourPropertyRenderer;
1344 return wxEnumProperty::GetCellRenderer(column);
1345}*/
1346
1347void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1348 wxPGPaintData& paintdata )
1349{
1350 wxColour col;
1351
a4c605ce
JS
1352 if ( paintdata.m_choiceItem >= 0 &&
1353 paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1354 (paintdata.m_choiceItem != GetCustomColourIndex() ||
1355 m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb
VZ
1356 {
1357 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1358 col = GetColour( colInd );
1359 }
1360 else if ( !IsValueUnspecified() )
1361 {
1362 col = GetVal().m_colour;
1363 }
1364
1365 if ( col.Ok() )
1366 {
1367 dc.SetBrush(col);
1368 dc.DrawRectangle(rect);
1369 }
1370}
1371
1372
1373bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1374{
1375 //
1376 // Accept colour format "[Name] [(R,G,B)]"
1377 // Name takes precedence.
1378 //
1379 wxString colourName;
1380 wxString colourRGB;
1381
1382 int ppos = text.Find(wxT("("));
1383
1384 if ( ppos == wxNOT_FOUND )
1385 {
1386 colourName = text;
1387 }
1388 else
1389 {
1390 colourName = text.substr(0, ppos);
1391 colourRGB = text.substr(ppos, text.length()-ppos);
1392 }
1393
1394 // Strip spaces from extremities
1395 colourName.Trim(true);
1396 colourName.Trim(false);
1397 colourRGB.Trim(true);
1398
1399 // Validate colourRGB string - (1,1,1) is shortest allowed
1400 if ( colourRGB.length() < 7 )
1401 colourRGB.clear();
1402
1403 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
5f7c24e2 1404 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) &&
1c4293cb
VZ
1405 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1406 {
1407 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1408 {
1409 // This really should not occurr...
1410 // wxASSERT(false);
1411 ResetNextIndex();
1412 return false;
1413 }
1414
1415 QueryColourFromUser(value);
1416 }
1417 else
1418 {
1419 wxColourPropertyValue val;
1420
1421 bool done = false;
1422
1423 if ( colourName.length() )
1424 {
1425 // Try predefined colour first
1426 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1427 if ( res && GetIndex() >= 0 )
1428 {
1429 val.m_type = GetIndex();
9e996d8c 1430 if ( val.m_type < m_choices.GetCount() )
1c4293cb
VZ
1431 val.m_type = m_choices[val.m_type].GetValue();
1432
1433 // Get proper colour for type.
1434 val.m_colour = GetColour(val.m_type);
1435
1436 done = true;
1437 }
1438 }
1439 if ( colourRGB.length() && !done )
1440 {
1441 // Then check custom colour.
1442 val.m_type = wxPG_COLOUR_CUSTOM;
1443
1444 int r = -1, g = -1, b = -1;
1445 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1446
1447 if ( r >= 0 && r <= 255 &&
1448 g >= 0 && g <= 255 &&
1449 b >= 0 && b <= 255 )
1450 {
1451 val.m_colour.Set(r,g,b);
1452
1453 done = true;
1454 }
1455 }
1456
1457 if ( !done )
1458 {
1459 ResetNextIndex();
1460 return false;
1461 }
1462
1463 value = DoTranslateVal(val);
1464 }
1465
1466 return true;
1467}
1468
1469
1470bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1471{
1472 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1473 {
4e00b908 1474 int ival = value.GetLong();
1c4293cb 1475
1c4293cb
VZ
1476 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1477 {
1478 // Show custom choice
1479 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1480 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1481 }
1482 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1483 {
1484 // Hide custom choice
1485 m_choices.RemoveAt(GetCustomColourIndex());
1486 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1487 }
1488 return true;
1489 }
1490 return false;
1491}
1492
1493
1494// -----------------------------------------------------------------------
1495// wxColourProperty
1496// -----------------------------------------------------------------------
1497
a243da29 1498static const wxChar* const gs_cp_es_normcolour_labels[] = {
1c4293cb
VZ
1499 wxT("Black"),
1500 wxT("Maroon"),
1501 wxT("Navy"),
1502 wxT("Purple"),
1503 wxT("Teal"),
1504 wxT("Gray"),
1505 wxT("Green"),
1506 wxT("Olive"),
1507 wxT("Brown"),
1508 wxT("Blue"),
1509 wxT("Fuchsia"),
1510 wxT("Red"),
1511 wxT("Orange"),
1512 wxT("Silver"),
1513 wxT("Lime"),
1514 wxT("Aqua"),
1515 wxT("Yellow"),
1516 wxT("White"),
1517 wxT("Custom"),
1518 (const wxChar*) NULL
1519};
1520
a243da29 1521static const unsigned long gs_cp_es_normcolour_colours[] = {
1c4293cb
VZ
1522 wxPG_COLOUR(0,0,0),
1523 wxPG_COLOUR(128,0,0),
1524 wxPG_COLOUR(0,0,128),
1525 wxPG_COLOUR(128,0,128),
1526 wxPG_COLOUR(0,128,128),
1527 wxPG_COLOUR(128,128,128),
1528 wxPG_COLOUR(0,128,0),
1529 wxPG_COLOUR(128,128,0),
1530 wxPG_COLOUR(166,124,81),
1531 wxPG_COLOUR(0,0,255),
1532 wxPG_COLOUR(255,0,255),
1533 wxPG_COLOUR(255,0,0),
1534 wxPG_COLOUR(247,148,28),
1535 wxPG_COLOUR(192,192,192),
1536 wxPG_COLOUR(0,255,0),
1537 wxPG_COLOUR(0,255,255),
1538 wxPG_COLOUR(255,255,0),
1539 wxPG_COLOUR(255,255,255),
1540 wxPG_COLOUR(0,0,0)
1541};
1542
d61d8cff
JS
1543WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1544 wxColour, const wxColour&, TextCtrlAndButton)
1545
1546static wxPGChoices gs_wxColourProperty_choicesCache;
1547
1548wxColourProperty::wxColourProperty( const wxString& label,
1549 const wxString& name,
1550 const wxColour& value )
1551 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1552 NULL,
1553 &gs_wxColourProperty_choicesCache, value )
1554{
1555 Init( value );
1556
1557 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1558}
1559
1560wxColourProperty::~wxColourProperty()
1561{
1562}
1563
1564void wxColourProperty::Init( wxColour colour )
1565{
1566 if ( !colour.Ok() )
1567 colour = *wxWHITE;
1568 wxVariant variant;
1569 variant << colour;
1570 m_value = variant;
1571 int ind = ColToInd(colour);
1572 if ( ind < 0 )
1573 ind = m_choices.GetCount() - 1;
1574 SetIndex( ind );
1575}
1576
1425eca5
JS
1577wxString wxColourProperty::ValueToString( wxVariant& value,
1578 int argFlags ) const
d61d8cff
JS
1579{
1580 const wxPGEditor* editor = GetEditorClass();
1581 if ( editor != wxPGEditor_Choice &&
1582 editor != wxPGEditor_ChoiceAndButton &&
1583 editor != wxPGEditor_ComboBox )
1584 argFlags |= wxPG_PROPERTY_SPECIFIC;
1585
1425eca5 1586 return wxSystemColourProperty::ValueToString(value, argFlags);
d61d8cff
JS
1587}
1588
1589wxColour wxColourProperty::GetColour( int index ) const
1590{
d61d8cff
JS
1591 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1592}
1593
1594wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1595{
1596 wxVariant variant;
1597 variant << v.m_colour;
1598 return variant;
1599}
1c4293cb
VZ
1600
1601// -----------------------------------------------------------------------
1602// wxCursorProperty
1603// -----------------------------------------------------------------------
1604
1605#define wxPG_CURSOR_IMAGE_WIDTH 32
1606
1607#define NUM_CURSORS 28
1608
1609//#define wx_cp_es_syscursors_len 28
a243da29 1610static const wxChar* const gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1c4293cb
VZ
1611 wxT("Default"),
1612 wxT("Arrow"),
1613 wxT("Right Arrow"),
1614 wxT("Blank"),
1615 wxT("Bullseye"),
1616 wxT("Character"),
1617 wxT("Cross"),
1618 wxT("Hand"),
1619 wxT("I-Beam"),
1620 wxT("Left Button"),
1621 wxT("Magnifier"),
1622 wxT("Middle Button"),
1623 wxT("No Entry"),
1624 wxT("Paint Brush"),
1625 wxT("Pencil"),
1626 wxT("Point Left"),
1627 wxT("Point Right"),
1628 wxT("Question Arrow"),
1629 wxT("Right Button"),
1630 wxT("Sizing NE-SW"),
1631 wxT("Sizing N-S"),
1632 wxT("Sizing NW-SE"),
1633 wxT("Sizing W-E"),
1634 wxT("Sizing"),
1635 wxT("Spraycan"),
1636 wxT("Wait"),
1637 wxT("Watch"),
1638 wxT("Wait Arrow"),
1639 (const wxChar*) NULL
1640};
1641
a243da29 1642static const long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1c4293cb
VZ
1643 wxCURSOR_NONE,
1644 wxCURSOR_ARROW,
1645 wxCURSOR_RIGHT_ARROW,
1646 wxCURSOR_BLANK,
1647 wxCURSOR_BULLSEYE,
1648 wxCURSOR_CHAR,
1649 wxCURSOR_CROSS,
1650 wxCURSOR_HAND,
1651 wxCURSOR_IBEAM,
1652 wxCURSOR_LEFT_BUTTON,
1653 wxCURSOR_MAGNIFIER,
1654 wxCURSOR_MIDDLE_BUTTON,
1655 wxCURSOR_NO_ENTRY,
1656 wxCURSOR_PAINT_BRUSH,
1657 wxCURSOR_PENCIL,
1658 wxCURSOR_POINT_LEFT,
1659 wxCURSOR_POINT_RIGHT,
1660 wxCURSOR_QUESTION_ARROW,
1661 wxCURSOR_RIGHT_BUTTON,
1662 wxCURSOR_SIZENESW,
1663 wxCURSOR_SIZENS,
1664 wxCURSOR_SIZENWSE,
1665 wxCURSOR_SIZEWE,
1666 wxCURSOR_SIZING,
1667 wxCURSOR_SPRAYCAN,
1668 wxCURSOR_WAIT,
1669 wxCURSOR_WATCH,
1670 wxCURSOR_ARROWWAIT
1671};
1672
1673IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1674
1675wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1676 int value )
1677 : wxEnumProperty( label,
1678 name,
1679 gs_cp_es_syscursors_labels,
1680 gs_cp_es_syscursors_values,
1681 value )
1682{
1683 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1684}
1685
1686wxCursorProperty::~wxCursorProperty()
1687{
1688}
1689
1690wxSize wxCursorProperty::OnMeasureImage( int item ) const
1691{
1692#if wxPG_CAN_DRAW_CURSOR
1693 if ( item != -1 && item < NUM_CURSORS )
1694 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1695#else
1696 wxUnusedVar(item);
1697#endif
1698 return wxSize(0,0);
1699}
1700
1701#if wxPG_CAN_DRAW_CURSOR
1702
1703void wxCursorProperty::OnCustomPaint( wxDC& dc,
1704 const wxRect& rect,
1705 wxPGPaintData& paintdata )
1706{
1707 // Background brush
1708 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1709
1710 if ( paintdata.m_choiceItem >= 0 )
1711 {
1712 dc.DrawRectangle( rect );
1713
1714 if ( paintdata.m_choiceItem < NUM_CURSORS )
1715 {
2399c87c
JS
1716 wxStockCursor cursorIndex =
1717 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1c4293cb
VZ
1718
1719 {
2399c87c
JS
1720 if ( cursorIndex == wxCURSOR_NONE )
1721 cursorIndex = wxCURSOR_ARROW;
1c4293cb 1722
2399c87c 1723 wxCursor cursor( cursorIndex );
1c4293cb
VZ
1724
1725 #ifdef __WXMSW__
1726 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1727 ::DrawIconEx( hDc,
1728 rect.x,
1729 rect.y,
1730 (HICON)cursor.GetHandle(),
1731 0,
1732 0,
1733 0,
1734 NULL,
591df136
JS
1735 #if !defined(__WXWINCE__)
1736 DI_COMPAT | DI_DEFAULTSIZE |
1737 #endif
1738 DI_NORMAL
1c4293cb
VZ
1739 );
1740 #endif
1741 }
1742 }
1743 }
1744}
1745
1746#else
1747void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1748/*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1749{
1750 return wxEnumProperty::GetCellRenderer(column);
1751}*/
1752#endif
1753
1754// -----------------------------------------------------------------------
1755// wxImageFileProperty
1756// -----------------------------------------------------------------------
1757
1758#if wxUSE_IMAGE
1759
1760const wxString& wxPGGetDefaultImageWildcard()
1761{
1762 // Form the wildcard, if not done yet
1763 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1764 {
1765
1766 wxString str;
1767
1768 // TODO: This section may require locking (using global).
1769
1770 wxList& handlers = wxImage::GetHandlers();
1771
1772 wxList::iterator node;
1773
1774 // Let's iterate over the image handler list.
1775 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
b7bc9d80 1776 for ( node = handlers.begin(); node != handlers.end(); ++node )
1c4293cb
VZ
1777 {
1778 wxImageHandler *handler = (wxImageHandler*)*node;
1779
1780 wxString ext_lo = handler->GetExtension();
1781 wxString ext_up = ext_lo.Upper();
1782
1783 str.append( ext_up );
1784 str.append( wxT(" files (*.") );
1785 str.append( ext_up );
1786 str.append( wxT(")|*.") );
1787 str.append( ext_lo );
1788 str.append( wxT("|") );
1789 }
1790
1791 str.append ( wxT("All files (*.*)|*.*") );
1792
1793 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1794 }
1795
1796 return wxPGGlobalVars->m_pDefaultImageWildcard;
1797}
1798
d53f610c 1799IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1c4293cb
VZ
1800
1801wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1802 const wxString& value )
1803 : wxFileProperty(label,name,value)
1804{
1805 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1806
d3b9f782
VZ
1807 m_pImage = NULL;
1808 m_pBitmap = NULL;
1c4293cb
VZ
1809}
1810
1811wxImageFileProperty::~wxImageFileProperty()
1812{
1813 if ( m_pBitmap )
1814 delete m_pBitmap;
1815 if ( m_pImage )
1816 delete m_pImage;
1817}
1818
1819void wxImageFileProperty::OnSetValue()
1820{
1821 wxFileProperty::OnSetValue();
1822
1823 // Delete old image
5276b0a5
VZ
1824 wxDELETE(m_pImage);
1825 wxDELETE(m_pBitmap);
1c4293cb 1826
1425eca5
JS
1827 wxFileName filename = GetFileName();
1828
1c4293cb 1829 // Create the image thumbnail
1425eca5 1830 if ( filename.FileExists() )
1c4293cb 1831 {
1425eca5 1832 m_pImage = new wxImage( filename.GetFullPath() );
1c4293cb
VZ
1833 }
1834}
1835
1836wxSize wxImageFileProperty::OnMeasureImage( int ) const
1837{
1838 return wxPG_DEFAULT_IMAGE_SIZE;
1839}
1840
1841void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1842 const wxRect& rect,
1843 wxPGPaintData& )
1844{
1845 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1846 {
1847 // Draw the thumbnail
1848
1849 // Create the bitmap here because required size is not known in OnSetValue().
1850 if ( !m_pBitmap )
1851 {
1852 m_pImage->Rescale( rect.width, rect.height );
1853 m_pBitmap = new wxBitmap( *m_pImage );
5276b0a5 1854 wxDELETE(m_pImage);
1c4293cb
VZ
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