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