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