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