]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/advprops.cpp
Refactor wxTranslationsLoader API.
[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 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;
9b5bafcf 692 font << useValue;
0372d42e 693 data.SetInitialFont( font );
1c4293cb
VZ
694 data.SetColour(*wxBLACK);
695
696 wxFontDialog dlg(propgrid, data);
697 if ( dlg.ShowModal() == wxID_OK )
698 {
699 propgrid->EditorsValueWasModified();
700
0372d42e
JS
701 wxVariant variant;
702 variant << dlg.GetFontData().GetChosenFont();
1c4293cb
VZ
703 SetValueInEvent( variant );
704 return true;
705 }
706 }
707 return false;
708}
709
710void wxFontProperty::RefreshChildren()
711{
712 if ( !GetChildCount() ) return;
0372d42e
JS
713 wxFont font;
714 font << m_value;
1c4293cb 715 Item(0)->SetValue( (long)font.GetPointSize() );
9867e3e4
JS
716 Item(1)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
717 Item(2)->SetValue( (long)font.GetStyle() );
718 Item(3)->SetValue( (long)font.GetWeight() );
719 Item(4)->SetValue( font.GetUnderlined() );
720 Item(5)->SetValue( (long)font.GetFamily() );
1c4293cb
VZ
721}
722
b8b1ff48
JS
723wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue,
724 int ind,
725 wxVariant& childValue ) const
1c4293cb 726{
0372d42e
JS
727 wxFont font;
728 font << thisValue;
1c4293cb
VZ
729
730 if ( ind == 0 )
731 {
4e00b908 732 font.SetPointSize( childValue.GetLong() );
1c4293cb
VZ
733 }
734 else if ( ind == 1 )
1c4293cb
VZ
735 {
736 wxString faceName;
737 int faceIndex = childValue.GetLong();
738
739 if ( faceIndex >= 0 )
740 faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
741
742 font.SetFaceName( faceName );
743 }
9867e3e4 744 else if ( ind == 2 )
1c4293cb
VZ
745 {
746 int st = childValue.GetLong();
747 if ( st != wxFONTSTYLE_NORMAL &&
748 st != wxFONTSTYLE_SLANT &&
749 st != wxFONTSTYLE_ITALIC )
750 st = wxFONTWEIGHT_NORMAL;
751 font.SetStyle( st );
752 }
9867e3e4 753 else if ( ind == 3 )
1c4293cb
VZ
754 {
755 int wt = childValue.GetLong();
756 if ( wt != wxFONTWEIGHT_NORMAL &&
757 wt != wxFONTWEIGHT_LIGHT &&
758 wt != wxFONTWEIGHT_BOLD )
759 wt = wxFONTWEIGHT_NORMAL;
760 font.SetWeight( wt );
761 }
9867e3e4 762 else if ( ind == 4 )
1c4293cb
VZ
763 {
764 font.SetUnderlined( childValue.GetBool() );
765 }
9867e3e4
JS
766 else if ( ind == 5 )
767 {
768 int fam = childValue.GetLong();
769 if ( fam < wxDEFAULT ||
770 fam > wxTELETYPE )
771 fam = wxDEFAULT;
772 font.SetFamily( fam );
773 }
0372d42e 774
b8b1ff48
JS
775 wxVariant newVariant;
776 newVariant << font;
777 return newVariant;
1c4293cb
VZ
778}
779
780/*
781wxSize wxFontProperty::OnMeasureImage() const
782{
783 return wxSize(-1,-1);
784}
785
786void wxFontProperty::OnCustomPaint(wxDC& dc,
787 const wxRect& rect,
788 wxPGPaintData& paintData)
789{
790 wxString drawFace;
791 if ( paintData.m_choiceItem >= 0 )
792 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
793 else
794 drawFace = m_value_wxFont.GetFaceName();
795
796 if ( drawFace.length() )
797 {
798 // Draw the background
799 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
800 //dc.SetBrush( *wxWHITE_BRUSH );
801 //dc.SetPen( *wxMEDIUM_GREY_PEN );
802 dc.DrawRectangle( rect );
803
804 wxFont oldFont = dc.GetFont();
805 wxFont drawFont(oldFont.GetPointSize(),
806 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
807 dc.SetFont(drawFont);
808
809 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
810 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
811
812 dc.SetFont(oldFont);
813 }
814 else
815 {
816 // No file - just draw a white box
817 dc.SetBrush ( *wxWHITE_BRUSH );
818 dc.DrawRectangle ( rect );
819 }
820}
821*/
822
823
824// -----------------------------------------------------------------------
825// wxSystemColourProperty
826// -----------------------------------------------------------------------
827
828// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
829#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
830
3b211af1 831#include "wx/colordlg.h"
1c4293cb
VZ
832
833//#define wx_cp_es_syscolours_len 25
a243da29 834static const wxChar* const gs_cp_es_syscolour_labels[] = {
1c4293cb
VZ
835 wxT("AppWorkspace"),
836 wxT("ActiveBorder"),
837 wxT("ActiveCaption"),
838 wxT("ButtonFace"),
839 wxT("ButtonHighlight"),
840 wxT("ButtonShadow"),
841 wxT("ButtonText"),
842 wxT("CaptionText"),
843 wxT("ControlDark"),
844 wxT("ControlLight"),
845 wxT("Desktop"),
846 wxT("GrayText"),
847 wxT("Highlight"),
848 wxT("HighlightText"),
849 wxT("InactiveBorder"),
850 wxT("InactiveCaption"),
851 wxT("InactiveCaptionText"),
852 wxT("Menu"),
853 wxT("Scrollbar"),
854 wxT("Tooltip"),
855 wxT("TooltipText"),
856 wxT("Window"),
857 wxT("WindowFrame"),
858 wxT("WindowText"),
859 wxT("Custom"),
860 (const wxChar*) NULL
861};
862
a243da29 863static const long gs_cp_es_syscolour_values[] = {
1c4293cb
VZ
864 wxSYS_COLOUR_APPWORKSPACE,
865 wxSYS_COLOUR_ACTIVEBORDER,
866 wxSYS_COLOUR_ACTIVECAPTION,
867 wxSYS_COLOUR_BTNFACE,
868 wxSYS_COLOUR_BTNHIGHLIGHT,
869 wxSYS_COLOUR_BTNSHADOW,
870 wxSYS_COLOUR_BTNTEXT ,
871 wxSYS_COLOUR_CAPTIONTEXT,
872 wxSYS_COLOUR_3DDKSHADOW,
873 wxSYS_COLOUR_3DLIGHT,
874 wxSYS_COLOUR_BACKGROUND,
875 wxSYS_COLOUR_GRAYTEXT,
876 wxSYS_COLOUR_HIGHLIGHT,
877 wxSYS_COLOUR_HIGHLIGHTTEXT,
878 wxSYS_COLOUR_INACTIVEBORDER,
879 wxSYS_COLOUR_INACTIVECAPTION,
880 wxSYS_COLOUR_INACTIVECAPTIONTEXT,
881 wxSYS_COLOUR_MENU,
882 wxSYS_COLOUR_SCROLLBAR,
883 wxSYS_COLOUR_INFOBK,
884 wxSYS_COLOUR_INFOTEXT,
885 wxSYS_COLOUR_WINDOW,
886 wxSYS_COLOUR_WINDOWFRAME,
887 wxSYS_COLOUR_WINDOWTEXT,
888 wxPG_COLOUR_CUSTOM
889};
890
891
0372d42e 892IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
1c4293cb
VZ
893
894
895// Class body is in advprops.h
896
897WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
898 wxColourPropertyValue,const wxColourPropertyValue&,Choice)
899
900
901void wxSystemColourProperty::Init( int type, const wxColour& colour )
902{
903 wxColourPropertyValue cpv;
904
905 if ( colour.Ok() )
906 cpv.Init( type, colour );
907 else
908 cpv.Init( type, *wxWHITE );
909
910 m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
911
0372d42e 912 m_value << cpv;
1c4293cb
VZ
913
914 OnSetValue();
915}
916
917
918static wxPGChoices gs_wxSystemColourProperty_choicesCache;
919
920
921wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
922 const wxColourPropertyValue& value )
923 : wxEnumProperty( label,
924 name,
925 gs_cp_es_syscolour_labels,
926 gs_cp_es_syscolour_values,
927 &gs_wxSystemColourProperty_choicesCache )
928{
929 if ( &value )
930 Init( value.m_type, value.m_colour );
931 else
932 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
933}
934
935
936wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
a243da29 937 const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
1c4293cb
VZ
938 const wxColourPropertyValue& value )
939 : wxEnumProperty( label, name, labels, values, choicesCache )
940{
941 if ( &value )
942 Init( value.m_type, value.m_colour );
943 else
944 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
945}
946
947
948wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
a243da29 949 const wxChar* const* labels, const long* values, wxPGChoices* choicesCache,
1c4293cb
VZ
950 const wxColour& value )
951 : wxEnumProperty( label, name, labels, values, choicesCache )
952{
953 if ( &value )
954 Init( wxPG_COLOUR_CUSTOM, value );
955 else
956 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
957}
958
959
960wxSystemColourProperty::~wxSystemColourProperty() { }
961
962
963wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
964{
965 if ( !pVariant )
966 pVariant = &m_value;
967
968 if ( pVariant->IsNull() )
969 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
970
0372d42e
JS
971 if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
972 {
973 wxColourPropertyValue v;
974 v << *pVariant;
975 return v;
976 }
1c4293cb 977
1c4293cb
VZ
978 wxColour col;
979 bool variantProcessed = true;
980
0372d42e 981 if ( pVariant->GetType() == wxS("wxColour*") )
1c4293cb 982 {
0372d42e 983 wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
1c4293cb
VZ
984 col = *pCol;
985 }
0372d42e 986 else if ( pVariant->GetType() == wxS("wxColour") )
1c4293cb 987 {
0372d42e
JS
988 col << *pVariant;
989 }
990 else if ( pVariant->GetType() == wxArrayInt_VariantType )
991 {
992 // This code is mostly needed for wxPython bindings, which
993 // may offer tuple of integers as colour value.
1c4293cb
VZ
994 wxArrayInt arr;
995 arr << *pVariant;
996
997 if ( arr.size() >= 3 )
998 {
999 int r, g, b;
1000 int a = 255;
1001
1002 r = arr[0];
1003 g = arr[1];
1004 b = arr[2];
1005 if ( arr.size() >= 4 )
1006 a = arr[3];
1007
1008 col = wxColour(r, g, b, a);
1009 }
1010 else
1011 {
1012 variantProcessed = false;
1013 }
1014 }
1c4293cb
VZ
1015 else
1016 {
1017 variantProcessed = false;
1018 }
1019
1020 if ( !variantProcessed )
1021 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
1022
1023 wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
1024
1025 int colInd = ColToInd(col);
1026 if ( colInd != wxNOT_FOUND )
1027 v2.m_type = colInd;
1028
1029 return v2;
1030}
1031
1032wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1033{
0372d42e
JS
1034 wxVariant variant;
1035 variant << v;
1036 return variant;
1c4293cb
VZ
1037}
1038
1039int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
1040{
1041 size_t i;
5f7c24e2
JS
1042 size_t i_max = m_choices.GetCount();
1043
1044 if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1045 i_max -= 1;
1c4293cb
VZ
1046
1047 for ( i=0; i<i_max; i++ )
1048 {
1049 int ind = m_choices[i].GetValue();
1050
1051 if ( colour == GetColour(ind) )
1052 {
1053 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1054 GetClassName(),GetLabel().c_str(),
1055 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1056 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1057 return ind;
1058 }
1059 }
1060 return wxNOT_FOUND;
1061}
1062
1c4293cb
VZ
1063void wxSystemColourProperty::OnSetValue()
1064{
1065 // Convert from generic wxobject ptr to wxPGVariantDataColour
0372d42e 1066 if ( m_value.GetType() == wxS("wxColour*") )
1c4293cb 1067 {
0372d42e 1068 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
1c4293cb
VZ
1069 m_value << *pCol;
1070 }
1071
1072 wxColourPropertyValue val = GetVal(&m_value);
1073
1074 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
1075 {
1076 m_value.MakeNull();
1077 return;
1078 }
1079 else
1080 {
1081
1082 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
1083 val.m_colour = GetColour( val.m_type );
1084
1085 m_value = TranslateVal(val);
1086 }
1087
b0f0eda8 1088 int ind = wxNOT_FOUND;
1c4293cb 1089
0372d42e 1090 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
1c4293cb 1091 {
0372d42e
JS
1092 wxColourPropertyValue cpv;
1093 cpv << m_value;
1094 wxColour col = cpv.m_colour;
1c4293cb 1095
0372d42e
JS
1096 if ( !col.Ok() )
1097 {
1098 SetValueToUnspecified();
1099 SetIndex(wxNOT_FOUND);
1100 return;
1101 }
1c4293cb 1102
5f7c24e2
JS
1103 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ||
1104 (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb 1105 {
98c04633 1106 ind = GetIndexForValue(cpv.m_type);
1c4293cb
VZ
1107 }
1108 else
1109 {
0372d42e 1110 cpv.m_type = wxPG_COLOUR_CUSTOM;
1c4293cb
VZ
1111 ind = GetCustomColourIndex();
1112 }
1113 }
1114 else
1115 {
0372d42e
JS
1116 wxColour col;
1117 col << m_value;
1118
1119 if ( !col.Ok() )
1120 {
1121 SetValueToUnspecified();
1122 SetIndex(wxNOT_FOUND);
1123 return;
1124 }
1125
1c4293cb
VZ
1126 ind = ColToInd(col);
1127
5f7c24e2
JS
1128 if ( ind == wxNOT_FOUND &&
1129 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb
VZ
1130 ind = GetCustomColourIndex();
1131 }
1132
1133 SetIndex(ind);
1134}
1135
1136
1137wxColour wxSystemColourProperty::GetColour( int index ) const
1138{
1139 return wxSystemSettings::GetColour( (wxSystemColour)index );
1140}
1141
1142wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
1143{
1144 if ( index == wxNOT_FOUND )
1145 return wxString::Format(wxT("(%i,%i,%i)"),
1146 (int)col.Red(),
1147 (int)col.Green(),
1148 (int)col.Blue());
1149 else
1150 return m_choices.GetLabel(index);
1151}
1152
1425eca5 1153wxString wxSystemColourProperty::ValueToString( wxVariant& value,
c9049646 1154 int argFlags ) const
1c4293cb 1155{
1425eca5 1156 wxColourPropertyValue val = GetVal(&value);
1c4293cb 1157
c9049646
JS
1158 int index;
1159
1160 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1161 {
1162 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1163 // but we should use it whenever possible.
1164 index = GetIndex();
1165
1166 // If custom colour was selected, use invalid index, so that
1167 // ColourToString() will return properly formatted colour text.
5f7c24e2
JS
1168 if ( index == GetCustomColourIndex() &&
1169 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
c9049646
JS
1170 index = wxNOT_FOUND;
1171 }
1172 else
1173 {
1174 index = m_choices.Index(val.m_type);
1175 }
1176
1177 return ColourToString(val.m_colour, index);
1c4293cb
VZ
1178}
1179
1180
1181wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1182{
1183 return wxPG_DEFAULT_IMAGE_SIZE;
1184}
1185
1186
1187int wxSystemColourProperty::GetCustomColourIndex() const
1188{
1189 return m_choices.GetCount() - 1;
1190}
1191
1192
1193bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1194{
0372d42e 1195 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1c4293cb
VZ
1196 bool res = false;
1197
1198 wxPropertyGrid* propgrid = GetGrid();
1199 wxASSERT( propgrid );
1200
1201 // Must only occur when user triggers event
b0996c3d 1202 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
1c4293cb
VZ
1203 return res;
1204
1205 wxColourPropertyValue val = GetVal();
1206
1207 val.m_type = wxPG_COLOUR_CUSTOM;
1208
1209 wxColourData data;
1210 data.SetChooseFull(true);
1211 data.SetColour(val.m_colour);
1212 int i;
1213 for ( i = 0; i < 16; i++)
1214 {
1215 wxColour colour(i*16, i*16, i*16);
1216 data.SetCustomColour(i, colour);
1217 }
1218
1219 wxColourDialog dialog(propgrid, &data);
1220 if ( dialog.ShowModal() == wxID_OK )
1221 {
1222 wxColourData retData = dialog.GetColourData();
1223 val.m_colour = retData.GetColour();
1224
1225 variant = DoTranslateVal(val);
1226
1227 SetValueInEvent(variant);
1228
1229 res = true;
1230 }
1231
1232 return res;
1233}
1234
1235
1236bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1237{
1238 int index = number;
78f2d746 1239 int type = m_choices.GetValue(index);
1c4293cb 1240
98c04633 1241 if ( type == wxPG_COLOUR_CUSTOM )
1c4293cb
VZ
1242 {
1243 QueryColourFromUser(variant);
1244 }
1245 else
1246 {
1247 variant = TranslateVal( type, GetColour(type) );
1248 }
1249
1250 return true;
1251}
1252
1253// Need to do some extra event handling.
858102d7
JS
1254bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid,
1255 wxWindow* WXUNUSED(primary),
1256 wxEvent& event )
1c4293cb 1257{
858102d7
JS
1258 bool askColour = false;
1259
1c4293cb 1260 if ( propgrid->IsMainButtonEvent(event) )
858102d7 1261 {
fbbde249
JS
1262 // We need to handle button click in case editor has been
1263 // switched to one that has wxButton as well.
858102d7
JS
1264 askColour = true;
1265 }
1266 else if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
1267 {
03647350
VZ
1268 // Must override index detection since at this point GetIndex()
1269 // will return old value.
1270 wxOwnerDrawnComboBox* cb =
1271 static_cast<wxOwnerDrawnComboBox*>(propgrid->GetEditorControl());
1272
1273 if ( cb )
1274 {
1275 int index = cb->GetSelection();
1276
1277 if ( index == GetCustomColourIndex() &&
1278 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1279 askColour = true;
1280 }
858102d7
JS
1281 }
1282
eddcc4b4 1283 if ( askColour && !propgrid->WasValueChangedInEvent() )
1c4293cb 1284 {
1c4293cb
VZ
1285 wxVariant variant;
1286 if ( QueryColourFromUser(variant) )
1287 return true;
1288 }
1289 return false;
1290}
1291
1292/*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1293{
1294public:
1295 virtual void Render( wxDC& dc, const wxRect& rect,
1296 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1297 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1298 {
1299 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1300 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1301
1302 dc.SetPen(*wxBLACK_PEN);
1303 if ( item >= 0 &&
1304 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1305 )
1306 {
1307 int colInd;
1308 const wxArrayInt& values = prop->GetValues();
1309 if ( values.GetChildCount() )
1310 colInd = values[item];
1311 else
1312 colInd = item;
1313 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1314 }
1315 else if ( !prop->IsValueUnspecified() )
1316 dc.SetBrush( prop->GetVal().m_colour );
1317 else
1318 dc.SetBrush( *wxWHITE );
1319
1320 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1321 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1322 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1323 imageRect.width, imageRect.height );
1324
1325 wxString text;
1326 if ( item == -1 )
1327 text = property->GetValueAsString();
1328 else
1329 text = property->GetChoiceString(item);
1330 DrawText( dc, rect, imageRect.width, text );
1331 }
1332protected:
1333};
1334
1335wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1336
1337wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1338{
1339 if ( column == 1 )
1340 return &g_wxPGColourPropertyRenderer;
1341 return wxEnumProperty::GetCellRenderer(column);
1342}*/
1343
1344void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1345 wxPGPaintData& paintdata )
1346{
1347 wxColour col;
1348
a4c605ce
JS
1349 if ( paintdata.m_choiceItem >= 0 &&
1350 paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1351 (paintdata.m_choiceItem != GetCustomColourIndex() ||
1352 m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1c4293cb
VZ
1353 {
1354 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1355 col = GetColour( colInd );
1356 }
1357 else if ( !IsValueUnspecified() )
1358 {
1359 col = GetVal().m_colour;
1360 }
1361
1362 if ( col.Ok() )
1363 {
1364 dc.SetBrush(col);
1365 dc.DrawRectangle(rect);
1366 }
1367}
1368
1369
1370bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1371{
1372 //
1373 // Accept colour format "[Name] [(R,G,B)]"
1374 // Name takes precedence.
1375 //
1376 wxString colourName;
1377 wxString colourRGB;
1378
1379 int ppos = text.Find(wxT("("));
1380
1381 if ( ppos == wxNOT_FOUND )
1382 {
1383 colourName = text;
1384 }
1385 else
1386 {
1387 colourName = text.substr(0, ppos);
1388 colourRGB = text.substr(ppos, text.length()-ppos);
1389 }
1390
1391 // Strip spaces from extremities
1392 colourName.Trim(true);
1393 colourName.Trim(false);
1394 colourRGB.Trim(true);
1395
1396 // Validate colourRGB string - (1,1,1) is shortest allowed
1397 if ( colourRGB.length() < 7 )
1398 colourRGB.clear();
1399
1400 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
5f7c24e2 1401 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) &&
1c4293cb
VZ
1402 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1403 {
1404 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1405 {
1406 // This really should not occurr...
1407 // wxASSERT(false);
1408 ResetNextIndex();
1409 return false;
1410 }
1411
1412 QueryColourFromUser(value);
1413 }
1414 else
1415 {
1416 wxColourPropertyValue val;
1417
1418 bool done = false;
1419
1420 if ( colourName.length() )
1421 {
1422 // Try predefined colour first
1423 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1424 if ( res && GetIndex() >= 0 )
1425 {
1426 val.m_type = GetIndex();
9e996d8c 1427 if ( val.m_type < m_choices.GetCount() )
1c4293cb
VZ
1428 val.m_type = m_choices[val.m_type].GetValue();
1429
1430 // Get proper colour for type.
1431 val.m_colour = GetColour(val.m_type);
1432
1433 done = true;
1434 }
1435 }
1436 if ( colourRGB.length() && !done )
1437 {
1438 // Then check custom colour.
1439 val.m_type = wxPG_COLOUR_CUSTOM;
1440
1441 int r = -1, g = -1, b = -1;
1442 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1443
1444 if ( r >= 0 && r <= 255 &&
1445 g >= 0 && g <= 255 &&
1446 b >= 0 && b <= 255 )
1447 {
1448 val.m_colour.Set(r,g,b);
1449
1450 done = true;
1451 }
1452 }
1453
1454 if ( !done )
1455 {
1456 ResetNextIndex();
1457 return false;
1458 }
1459
1460 value = DoTranslateVal(val);
1461 }
1462
1463 return true;
1464}
1465
1466
1467bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1468{
1469 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1470 {
4e00b908 1471 int ival = value.GetLong();
1c4293cb 1472
1c4293cb
VZ
1473 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1474 {
1475 // Show custom choice
1476 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1477 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1478 }
1479 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1480 {
1481 // Hide custom choice
1482 m_choices.RemoveAt(GetCustomColourIndex());
1483 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1484 }
1485 return true;
1486 }
1487 return false;
1488}
1489
1490
1491// -----------------------------------------------------------------------
1492// wxColourProperty
1493// -----------------------------------------------------------------------
1494
a243da29 1495static const wxChar* const gs_cp_es_normcolour_labels[] = {
1c4293cb
VZ
1496 wxT("Black"),
1497 wxT("Maroon"),
1498 wxT("Navy"),
1499 wxT("Purple"),
1500 wxT("Teal"),
1501 wxT("Gray"),
1502 wxT("Green"),
1503 wxT("Olive"),
1504 wxT("Brown"),
1505 wxT("Blue"),
1506 wxT("Fuchsia"),
1507 wxT("Red"),
1508 wxT("Orange"),
1509 wxT("Silver"),
1510 wxT("Lime"),
1511 wxT("Aqua"),
1512 wxT("Yellow"),
1513 wxT("White"),
1514 wxT("Custom"),
1515 (const wxChar*) NULL
1516};
1517
a243da29 1518static const unsigned long gs_cp_es_normcolour_colours[] = {
1c4293cb
VZ
1519 wxPG_COLOUR(0,0,0),
1520 wxPG_COLOUR(128,0,0),
1521 wxPG_COLOUR(0,0,128),
1522 wxPG_COLOUR(128,0,128),
1523 wxPG_COLOUR(0,128,128),
1524 wxPG_COLOUR(128,128,128),
1525 wxPG_COLOUR(0,128,0),
1526 wxPG_COLOUR(128,128,0),
1527 wxPG_COLOUR(166,124,81),
1528 wxPG_COLOUR(0,0,255),
1529 wxPG_COLOUR(255,0,255),
1530 wxPG_COLOUR(255,0,0),
1531 wxPG_COLOUR(247,148,28),
1532 wxPG_COLOUR(192,192,192),
1533 wxPG_COLOUR(0,255,0),
1534 wxPG_COLOUR(0,255,255),
1535 wxPG_COLOUR(255,255,0),
1536 wxPG_COLOUR(255,255,255),
1537 wxPG_COLOUR(0,0,0)
1538};
1539
d61d8cff
JS
1540WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1541 wxColour, const wxColour&, TextCtrlAndButton)
1542
1543static wxPGChoices gs_wxColourProperty_choicesCache;
1544
1545wxColourProperty::wxColourProperty( const wxString& label,
1546 const wxString& name,
1547 const wxColour& value )
1548 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1549 NULL,
1550 &gs_wxColourProperty_choicesCache, value )
1551{
1552 Init( value );
1553
1554 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1555}
1556
1557wxColourProperty::~wxColourProperty()
1558{
1559}
1560
1561void wxColourProperty::Init( wxColour colour )
1562{
1563 if ( !colour.Ok() )
1564 colour = *wxWHITE;
1565 wxVariant variant;
1566 variant << colour;
1567 m_value = variant;
1568 int ind = ColToInd(colour);
1569 if ( ind < 0 )
1570 ind = m_choices.GetCount() - 1;
1571 SetIndex( ind );
1572}
1573
1425eca5
JS
1574wxString wxColourProperty::ValueToString( wxVariant& value,
1575 int argFlags ) const
d61d8cff
JS
1576{
1577 const wxPGEditor* editor = GetEditorClass();
1578 if ( editor != wxPGEditor_Choice &&
1579 editor != wxPGEditor_ChoiceAndButton &&
1580 editor != wxPGEditor_ComboBox )
1581 argFlags |= wxPG_PROPERTY_SPECIFIC;
1582
1425eca5 1583 return wxSystemColourProperty::ValueToString(value, argFlags);
d61d8cff
JS
1584}
1585
1586wxColour wxColourProperty::GetColour( int index ) const
1587{
d61d8cff
JS
1588 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1589}
1590
1591wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1592{
1593 wxVariant variant;
1594 variant << v.m_colour;
1595 return variant;
1596}
1c4293cb
VZ
1597
1598// -----------------------------------------------------------------------
1599// wxCursorProperty
1600// -----------------------------------------------------------------------
1601
1602#define wxPG_CURSOR_IMAGE_WIDTH 32
1603
1604#define NUM_CURSORS 28
1605
1606//#define wx_cp_es_syscursors_len 28
a243da29 1607static const wxChar* const gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1c4293cb
VZ
1608 wxT("Default"),
1609 wxT("Arrow"),
1610 wxT("Right Arrow"),
1611 wxT("Blank"),
1612 wxT("Bullseye"),
1613 wxT("Character"),
1614 wxT("Cross"),
1615 wxT("Hand"),
1616 wxT("I-Beam"),
1617 wxT("Left Button"),
1618 wxT("Magnifier"),
1619 wxT("Middle Button"),
1620 wxT("No Entry"),
1621 wxT("Paint Brush"),
1622 wxT("Pencil"),
1623 wxT("Point Left"),
1624 wxT("Point Right"),
1625 wxT("Question Arrow"),
1626 wxT("Right Button"),
1627 wxT("Sizing NE-SW"),
1628 wxT("Sizing N-S"),
1629 wxT("Sizing NW-SE"),
1630 wxT("Sizing W-E"),
1631 wxT("Sizing"),
1632 wxT("Spraycan"),
1633 wxT("Wait"),
1634 wxT("Watch"),
1635 wxT("Wait Arrow"),
1636 (const wxChar*) NULL
1637};
1638
a243da29 1639static const long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1c4293cb
VZ
1640 wxCURSOR_NONE,
1641 wxCURSOR_ARROW,
1642 wxCURSOR_RIGHT_ARROW,
1643 wxCURSOR_BLANK,
1644 wxCURSOR_BULLSEYE,
1645 wxCURSOR_CHAR,
1646 wxCURSOR_CROSS,
1647 wxCURSOR_HAND,
1648 wxCURSOR_IBEAM,
1649 wxCURSOR_LEFT_BUTTON,
1650 wxCURSOR_MAGNIFIER,
1651 wxCURSOR_MIDDLE_BUTTON,
1652 wxCURSOR_NO_ENTRY,
1653 wxCURSOR_PAINT_BRUSH,
1654 wxCURSOR_PENCIL,
1655 wxCURSOR_POINT_LEFT,
1656 wxCURSOR_POINT_RIGHT,
1657 wxCURSOR_QUESTION_ARROW,
1658 wxCURSOR_RIGHT_BUTTON,
1659 wxCURSOR_SIZENESW,
1660 wxCURSOR_SIZENS,
1661 wxCURSOR_SIZENWSE,
1662 wxCURSOR_SIZEWE,
1663 wxCURSOR_SIZING,
1664 wxCURSOR_SPRAYCAN,
1665 wxCURSOR_WAIT,
1666 wxCURSOR_WATCH,
1667 wxCURSOR_ARROWWAIT
1668};
1669
1670IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1671
1672wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1673 int value )
1674 : wxEnumProperty( label,
1675 name,
1676 gs_cp_es_syscursors_labels,
1677 gs_cp_es_syscursors_values,
1678 value )
1679{
1680 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1681}
1682
1683wxCursorProperty::~wxCursorProperty()
1684{
1685}
1686
1687wxSize wxCursorProperty::OnMeasureImage( int item ) const
1688{
1689#if wxPG_CAN_DRAW_CURSOR
1690 if ( item != -1 && item < NUM_CURSORS )
1691 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1692#else
1693 wxUnusedVar(item);
1694#endif
1695 return wxSize(0,0);
1696}
1697
1698#if wxPG_CAN_DRAW_CURSOR
1699
1700void wxCursorProperty::OnCustomPaint( wxDC& dc,
1701 const wxRect& rect,
1702 wxPGPaintData& paintdata )
1703{
1704 // Background brush
1705 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1706
1707 if ( paintdata.m_choiceItem >= 0 )
1708 {
1709 dc.DrawRectangle( rect );
1710
1711 if ( paintdata.m_choiceItem < NUM_CURSORS )
1712 {
2399c87c
JS
1713 wxStockCursor cursorIndex =
1714 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1c4293cb
VZ
1715
1716 {
2399c87c
JS
1717 if ( cursorIndex == wxCURSOR_NONE )
1718 cursorIndex = wxCURSOR_ARROW;
1c4293cb 1719
2399c87c 1720 wxCursor cursor( cursorIndex );
1c4293cb
VZ
1721
1722 #ifdef __WXMSW__
1723 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1724 ::DrawIconEx( hDc,
1725 rect.x,
1726 rect.y,
1727 (HICON)cursor.GetHandle(),
1728 0,
1729 0,
1730 0,
1731 NULL,
591df136
JS
1732 #if !defined(__WXWINCE__)
1733 DI_COMPAT | DI_DEFAULTSIZE |
1734 #endif
1735 DI_NORMAL
1c4293cb
VZ
1736 );
1737 #endif
1738 }
1739 }
1740 }
1741}
1742
1743#else
1744void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1745/*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1746{
1747 return wxEnumProperty::GetCellRenderer(column);
1748}*/
1749#endif
1750
1751// -----------------------------------------------------------------------
1752// wxImageFileProperty
1753// -----------------------------------------------------------------------
1754
1755#if wxUSE_IMAGE
1756
1757const wxString& wxPGGetDefaultImageWildcard()
1758{
1759 // Form the wildcard, if not done yet
1760 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1761 {
1762
1763 wxString str;
1764
1765 // TODO: This section may require locking (using global).
1766
1767 wxList& handlers = wxImage::GetHandlers();
1768
1769 wxList::iterator node;
1770
1771 // Let's iterate over the image handler list.
1772 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
b7bc9d80 1773 for ( node = handlers.begin(); node != handlers.end(); ++node )
1c4293cb
VZ
1774 {
1775 wxImageHandler *handler = (wxImageHandler*)*node;
1776
1777 wxString ext_lo = handler->GetExtension();
1778 wxString ext_up = ext_lo.Upper();
1779
1780 str.append( ext_up );
1781 str.append( wxT(" files (*.") );
1782 str.append( ext_up );
1783 str.append( wxT(")|*.") );
1784 str.append( ext_lo );
1785 str.append( wxT("|") );
1786 }
1787
1788 str.append ( wxT("All files (*.*)|*.*") );
1789
1790 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1791 }
1792
1793 return wxPGGlobalVars->m_pDefaultImageWildcard;
1794}
1795
d53f610c 1796IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1c4293cb
VZ
1797
1798wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1799 const wxString& value )
1800 : wxFileProperty(label,name,value)
1801{
1802 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1803
d3b9f782
VZ
1804 m_pImage = NULL;
1805 m_pBitmap = NULL;
1c4293cb
VZ
1806}
1807
1808wxImageFileProperty::~wxImageFileProperty()
1809{
1810 if ( m_pBitmap )
1811 delete m_pBitmap;
1812 if ( m_pImage )
1813 delete m_pImage;
1814}
1815
1816void wxImageFileProperty::OnSetValue()
1817{
1818 wxFileProperty::OnSetValue();
1819
1820 // Delete old image
1821 if ( m_pImage )
1822 {
1823 delete m_pImage;
1824 m_pImage = NULL;
1825 }
1826 if ( m_pBitmap )
1827 {
1828 delete m_pBitmap;
1829 m_pBitmap = NULL;
1830 }
1831
1425eca5
JS
1832 wxFileName filename = GetFileName();
1833
1c4293cb 1834 // Create the image thumbnail
1425eca5 1835 if ( filename.FileExists() )
1c4293cb 1836 {
1425eca5 1837 m_pImage = new wxImage( filename.GetFullPath() );
1c4293cb
VZ
1838 }
1839}
1840
1841wxSize wxImageFileProperty::OnMeasureImage( int ) const
1842{
1843 return wxPG_DEFAULT_IMAGE_SIZE;
1844}
1845
1846void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1847 const wxRect& rect,
1848 wxPGPaintData& )
1849{
1850 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1851 {
1852 // Draw the thumbnail
1853
1854 // Create the bitmap here because required size is not known in OnSetValue().
1855 if ( !m_pBitmap )
1856 {
1857 m_pImage->Rescale( rect.width, rect.height );
1858 m_pBitmap = new wxBitmap( *m_pImage );
1859 delete m_pImage;
1860 m_pImage = NULL;
1861 }
1862
1863 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1864 }
1865 else
1866 {
1867 // No file - just draw a white box
1868 dc.SetBrush( *wxWHITE_BRUSH );
1869 dc.DrawRectangle ( rect );
1870 }
1871}
1872
1873#endif // wxUSE_IMAGE
1874
1875// -----------------------------------------------------------------------
1876// wxMultiChoiceProperty
1877// -----------------------------------------------------------------------
1878
1879#if wxUSE_CHOICEDLG
1880
3b211af1 1881#include "wx/choicdlg.h"
1c4293cb
VZ
1882
1883WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1884 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1885
1886wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1887 const wxString& name,
1888 const wxPGChoices& choices,
1889 const wxArrayString& value)
1890 : wxPGProperty(label,name)
1891{
1892 m_choices.Assign(choices);
1893 SetValue(value);
1894}
1895
1896wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1897 const wxString& name,
1898 const wxArrayString& strings,
1899 const wxArrayString& value)
1900 : wxPGProperty(label,name)
1901{
1902 m_choices.Set(strings);
1903 SetValue(value);
1904}
1905
1906wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1907 const wxString& name,
1908 const wxArrayString& value)
1909 : wxPGProperty(label,name)
1910{
1911 wxArrayString strings;
1912 m_choices.Set(strings);
1913 SetValue(value);
1914}
1915
1916wxMultiChoiceProperty::~wxMultiChoiceProperty()
1917{
1918}
1919
1920void wxMultiChoiceProperty::OnSetValue()
1921{
102c9a42 1922 GenerateValueAsString(m_value, &m_display);
1c4293cb
VZ
1923}
1924
1425eca5
JS
1925wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1926 int argFlags ) const
1c4293cb 1927{
1425eca5
JS
1928 // If possible, use cached string
1929 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1930 return m_display;
1931
1932 wxString s;
102c9a42 1933 GenerateValueAsString(value, &s);
1425eca5 1934 return s;
1c4293cb
VZ
1935}
1936
102c9a42
JS
1937void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1938 wxString* target ) const
1c4293cb
VZ
1939{
1940 wxArrayString strings;
1941
102c9a42
JS
1942 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1943 strings = value.GetArrayString();
1c4293cb 1944
1425eca5 1945 wxString& tempStr = *target;
1c4293cb
VZ
1946 unsigned int i;
1947 unsigned int itemCount = strings.size();
1948
1949 tempStr.Empty();
1950
1951 if ( itemCount )
1952 tempStr.append( wxT("\"") );
1953
1954 for ( i = 0; i < itemCount; i++ )
1955 {
1956 tempStr.append( strings[i] );
1957 tempStr.append( wxT("\"") );
1958 if ( i < (itemCount-1) )
1959 tempStr.append ( wxT(" \"") );
1960 }
1961}
1962
1963wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1964{
bfad4a15
JS
1965 wxVariant variant = GetValue();
1966 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant);
1c4293cb
VZ
1967 unsigned int i;
1968
1969 // Translate values to string indices.
1970 wxArrayInt selections;
1971
1972 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1973 {
1974 for ( i=0; i<valueArr.size(); i++ )
1975 selections.Add(-1);
1976 }
1977 else
1978 {
1979 for ( i=0; i<valueArr.size(); i++ )
1980 {
1981 int sIndex = m_choices.Index(valueArr[i]);
1982 if ( sIndex >= 0 )
1983 selections.Add(sIndex);
1984 }
1985 }
1986
1987 return selections;
1988}
1989
1990bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1991 wxWindow* WXUNUSED(primary),
1992 wxEvent& event )
1993{
1994 if ( propgrid->IsMainButtonEvent(event) )
1995 {
1996 // Update the value
703ee9f5 1997 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb
VZ
1998
1999 wxArrayString labels = m_choices.GetLabels();
2000 unsigned int choiceCount;
2001
2002 if ( m_choices.IsOk() )
2003 choiceCount = m_choices.GetCount();
2004 else
2005 choiceCount = 0;
2006
2007 // launch editor dialog
2008 wxMultiChoiceDialog dlg( propgrid,
2009 _("Make a selection:"),
2010 m_label,
2011 choiceCount,
2012 choiceCount?&labels[0]:NULL,
2013 wxCHOICEDLG_STYLE );
2014
2015 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
2016
9b5bafcf 2017 wxArrayString strings = useValue.GetArrayString();
1c4293cb
VZ
2018 wxArrayString extraStrings;
2019
2020 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
2021
2022 if ( dlg.ShowModal() == wxID_OK && choiceCount )
2023 {
2024 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
2025
2026 wxArrayInt arrInt = dlg.GetSelections();
2027
2028 wxVariant variant;
2029
2030 // Strings that were not in list of choices
2031 wxArrayString value;
2032
2033 // Translate string indices to strings
2034
2035 unsigned int n;
2036 if ( userStringMode == 1 )
2037 {
2038 for (n=0;n<extraStrings.size();n++)
2039 value.push_back(extraStrings[n]);
2040 }
2041
2042 unsigned int i;
2043 for ( i=0; i<arrInt.size(); i++ )
2044 value.Add(m_choices.GetLabel(arrInt.Item(i)));
2045
2046 if ( userStringMode == 2 )
2047 {
2048 for (n=0;n<extraStrings.size();n++)
2049 value.push_back(extraStrings[n]);
2050 }
2051
2052 variant = WXVARIANT(value);
2053
2054 SetValueInEvent(variant);
2055
2056 return true;
2057 }
2058 }
2059 return false;
2060}
2061
1c4293cb
VZ
2062bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2063{
2064 wxArrayString arr;
2065
2066 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
2067
2068 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
2069 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
2070 arr.Add(token);
2071 WX_PG_TOKENIZER2_END()
2072
2073 wxVariant v( WXVARIANT(arr) );
2074 variant = v;
2075
2076 return true;
2077}
2078
2079#endif // wxUSE_CHOICEDLG
2080
2081
2082// -----------------------------------------------------------------------
2083// wxDateProperty
2084// -----------------------------------------------------------------------
2085
2086#if wxUSE_DATETIME
2087
2088
2089#if wxUSE_DATEPICKCTRL
2090 #define dtCtrl DatePickerCtrl
2091#else
2092 #define dtCtrl TextCtrl
2093#endif
2094
2095WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
2096 wxPGProperty,
2097 wxDateTime,
2098 const wxDateTime&,
2099 dtCtrl)
2100
2101
2102wxString wxDateProperty::ms_defaultDateFormat;
2103
2104
2105wxDateProperty::wxDateProperty( const wxString& label,
2106 const wxString& name,
2107 const wxDateTime& value )
2108 : wxPGProperty(label,name)
2109{
2110 //wxPGRegisterDefaultValueType(wxDateTime)
2111
2112#if wxUSE_DATEPICKCTRL
2113 wxPGRegisterEditorClass(DatePickerCtrl);
2114
2115 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
2116#else
2117 m_dpStyle = 0;
2118#endif
2119
2120 SetValue( value );
2121}
2122
2123wxDateProperty::~wxDateProperty()
2124{
2125}
2126
b6fd0b42
JS
2127void wxDateProperty::OnSetValue()
2128{
2129 //
2130 // Convert invalid dates to unspecified value
2131 if ( m_value.GetType() == wxT("datetime") )
2132 {
2133 if ( !m_value.GetDateTime().IsValid() )
2134 m_value.MakeNull();
2135 }
2136}
2137
1c4293cb
VZ
2138bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
2139 int WXUNUSED(argFlags) ) const
2140{
2141 wxDateTime dt;
2142
09777a5b
VZ
2143 // FIXME: do we really want to return true from here if only part of the
2144 // string was parsed?
2145 const char* c = dt.ParseFormat(text);
1c4293cb
VZ
2146
2147 if ( c )
2148 {
2149 variant = dt;
2150 return true;
2151 }
2152
2153 return false;
2154}
2155
1425eca5
JS
2156wxString wxDateProperty::ValueToString( wxVariant& value,
2157 int argFlags ) const
1c4293cb
VZ
2158{
2159 const wxChar* format = (const wxChar*) NULL;
2160
1425eca5 2161 wxDateTime dateTime = value.GetDateTime();
1c4293cb
VZ
2162
2163 if ( !dateTime.IsValid() )
2164 return wxT("Invalid");
2165
2166 if ( !ms_defaultDateFormat.length() )
2167 {
2168#if wxUSE_DATEPICKCTRL
2169 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
2170#else
2171 bool showCentury = true;
2172#endif
2173 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
2174 }
2175
2176 if ( m_format.length() &&
2177 !(argFlags & wxPG_FULL_VALUE) )
2178 format = m_format.c_str();
2179
2180 // Determine default from locale
2181 // NB: This is really simple stuff, but can't figure anything
2182 // better without proper support in wxLocale
2183 if ( !format )
2184 format = ms_defaultDateFormat.c_str();
2185
2186 return dateTime.Format(format);
2187}
2188
2189wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
2190{
2191 // This code is basicly copied from datectlg.cpp's SetFormat
2192 //
2193 wxString format;
2194
2195 wxDateTime dt;
2196 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2197 wxString str(dt.Format(wxT("%x")));
2198
2199 const wxChar *p = str.c_str();
2200 while ( *p )
2201 {
2202 int n=wxAtoi(p);
2203 if (n == dt.GetDay())
2204 {
2205 format.Append(wxT("%d"));
2206 p += 2;
2207 }
2208 else if (n == (int)dt.GetMonth()+1)
2209 {
2210 format.Append(wxT("%m"));
2211 p += 2;
2212 }
2213 else if (n == dt.GetYear())
2214 {
2215 format.Append(wxT("%Y"));
2216 p += 4;
2217 }
2218 else if (n == (dt.GetYear() % 100))
2219 {
2220 if (showCentury)
2221 format.Append(wxT("%Y"));
2222 else
2223 format.Append(wxT("%y"));
2224 p += 2;
2225 }
2226 else
2227 format.Append(*p++);
2228 }
2229
2230 return format;
2231}
2232
2233bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2234{
2235 if ( name == wxPG_DATE_FORMAT )
2236 {
2237 m_format = value.GetString();
2238 return true;
2239 }
2240 else if ( name == wxPG_DATE_PICKER_STYLE )
2241 {
2242 m_dpStyle = value.GetLong();
2243 ms_defaultDateFormat.clear(); // This may need recalculation
2244 return true;
2245 }
2246 return false;
2247}
2248
2249#endif // wxUSE_DATETIME
2250
2251
2252// -----------------------------------------------------------------------
2253// wxPropertyGridInterface
2254// -----------------------------------------------------------------------
2255
2256void wxPropertyGridInterface::InitAllTypeHandlers()
2257{
2258}
2259
2260// -----------------------------------------------------------------------
2261
2262void wxPropertyGridInterface::RegisterAdditionalEditors()
2263{
c8074be0
JS
2264 // Register editor classes, if necessary.
2265 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2266 wxPropertyGrid::RegisterDefaultEditors();
2267
1c4293cb
VZ
2268#if wxUSE_SPINBTN
2269 wxPGRegisterEditorClass(SpinCtrl);
2270#endif
2271#if wxUSE_DATEPICKCTRL
2272 wxPGRegisterEditorClass(DatePickerCtrl);
2273#endif
2274}
2275
2276// -----------------------------------------------------------------------
2277
f4bc1aa2
JS
2278#endif // wxPG_INCLUDE_ADVPROPS
2279
2280#endif // wxUSE_PROPGRID
2281