]> git.saurik.com Git - wxWidgets.git/blob - src/propgrid/advprops.cpp
remove unused static wxColourFromPGLong function
[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 void wxSystemColourProperty::OnSetValue()
902 {
903 // Convert from generic wxobject ptr to wxPGVariantDataColour
904 if ( m_value.GetType() == wxS("wxColour*") )
905 {
906 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
907 m_value << *pCol;
908 }
909
910 wxColourPropertyValue val = GetVal(&m_value);
911
912 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
913 {
914 m_value.MakeNull();
915 return;
916 }
917 else
918 {
919
920 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
921 val.m_colour = GetColour( val.m_type );
922
923 m_value = TranslateVal(val);
924 }
925
926 int ind = wxNOT_FOUND;
927
928 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
929 {
930 wxColourPropertyValue cpv;
931 cpv << m_value;
932 wxColour col = cpv.m_colour;
933
934 if ( !col.Ok() )
935 {
936 SetValueToUnspecified();
937 SetIndex(wxNOT_FOUND);
938 return;
939 }
940
941 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
942 {
943 ind = GetIndexForValue(cpv.m_type);
944 }
945 else
946 {
947 cpv.m_type = wxPG_COLOUR_CUSTOM;
948 ind = GetCustomColourIndex();
949 }
950 }
951 else
952 {
953 wxColour col;
954 col << m_value;
955
956 if ( !col.Ok() )
957 {
958 SetValueToUnspecified();
959 SetIndex(wxNOT_FOUND);
960 return;
961 }
962
963 ind = ColToInd(col);
964
965 if ( ind == wxNOT_FOUND )
966 ind = GetCustomColourIndex();
967 }
968
969 SetIndex(ind);
970 }
971
972
973 wxColour wxSystemColourProperty::GetColour( int index ) const
974 {
975 return wxSystemSettings::GetColour( (wxSystemColour)index );
976 }
977
978 wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
979 {
980 if ( index == wxNOT_FOUND )
981 return wxString::Format(wxT("(%i,%i,%i)"),
982 (int)col.Red(),
983 (int)col.Green(),
984 (int)col.Blue());
985 else
986 return m_choices.GetLabel(index);
987 }
988
989 wxString wxSystemColourProperty::ValueToString( wxVariant& value,
990 int argFlags ) const
991 {
992 wxColourPropertyValue val = GetVal(&value);
993
994 int index;
995
996 if ( argFlags & wxPG_VALUE_IS_CURRENT )
997 {
998 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
999 // but we should use it whenever possible.
1000 index = GetIndex();
1001
1002 // If custom colour was selected, use invalid index, so that
1003 // ColourToString() will return properly formatted colour text.
1004 if ( index == GetCustomColourIndex() )
1005 index = wxNOT_FOUND;
1006 }
1007 else
1008 {
1009 index = m_choices.Index(val.m_type);
1010 }
1011
1012 return ColourToString(val.m_colour, index);
1013 }
1014
1015
1016 wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1017 {
1018 return wxPG_DEFAULT_IMAGE_SIZE;
1019 }
1020
1021
1022 int wxSystemColourProperty::GetCustomColourIndex() const
1023 {
1024 return m_choices.GetCount() - 1;
1025 }
1026
1027
1028 bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1029 {
1030 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1031 bool res = false;
1032
1033 wxPropertyGrid* propgrid = GetGrid();
1034 wxASSERT( propgrid );
1035
1036 // Must only occur when user triggers event
1037 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) )
1038 return res;
1039
1040 wxColourPropertyValue val = GetVal();
1041
1042 val.m_type = wxPG_COLOUR_CUSTOM;
1043
1044 wxColourData data;
1045 data.SetChooseFull(true);
1046 data.SetColour(val.m_colour);
1047 int i;
1048 for ( i = 0; i < 16; i++)
1049 {
1050 wxColour colour(i*16, i*16, i*16);
1051 data.SetCustomColour(i, colour);
1052 }
1053
1054 wxColourDialog dialog(propgrid, &data);
1055 if ( dialog.ShowModal() == wxID_OK )
1056 {
1057 wxColourData retData = dialog.GetColourData();
1058 val.m_colour = retData.GetColour();
1059
1060 variant = DoTranslateVal(val);
1061
1062 SetValueInEvent(variant);
1063
1064 res = true;
1065 }
1066
1067 return res;
1068 }
1069
1070
1071 bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1072 {
1073 int index = number;
1074 int type = m_choices.GetValue(index);
1075
1076 if ( type == wxPG_COLOUR_CUSTOM )
1077 {
1078 QueryColourFromUser(variant);
1079 }
1080 else
1081 {
1082 variant = TranslateVal( type, GetColour(type) );
1083 }
1084
1085 return true;
1086 }
1087
1088 // Need to do some extra event handling.
1089 bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event )
1090 {
1091 if ( propgrid->IsMainButtonEvent(event) )
1092 {
1093 // We need to handle button click in case editor has been
1094 // switched to one that has wxButton as well.
1095 wxVariant variant;
1096 if ( QueryColourFromUser(variant) )
1097 return true;
1098 }
1099 return false;
1100 }
1101
1102 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1103 {
1104 public:
1105 virtual void Render( wxDC& dc, const wxRect& rect,
1106 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1107 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1108 {
1109 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1110 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1111
1112 dc.SetPen(*wxBLACK_PEN);
1113 if ( item >= 0 &&
1114 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1115 )
1116 {
1117 int colInd;
1118 const wxArrayInt& values = prop->GetValues();
1119 if ( values.GetChildCount() )
1120 colInd = values[item];
1121 else
1122 colInd = item;
1123 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1124 }
1125 else if ( !prop->IsValueUnspecified() )
1126 dc.SetBrush( prop->GetVal().m_colour );
1127 else
1128 dc.SetBrush( *wxWHITE );
1129
1130 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1131 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1132 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1133 imageRect.width, imageRect.height );
1134
1135 wxString text;
1136 if ( item == -1 )
1137 text = property->GetValueAsString();
1138 else
1139 text = property->GetChoiceString(item);
1140 DrawText( dc, rect, imageRect.width, text );
1141 }
1142 protected:
1143 };
1144
1145 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1146
1147 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1148 {
1149 if ( column == 1 )
1150 return &g_wxPGColourPropertyRenderer;
1151 return wxEnumProperty::GetCellRenderer(column);
1152 }*/
1153
1154 void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1155 wxPGPaintData& paintdata )
1156 {
1157 wxColour col;
1158
1159 if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1160 paintdata.m_choiceItem != GetCustomColourIndex() )
1161 {
1162 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1163 col = GetColour( colInd );
1164 }
1165 else if ( !IsValueUnspecified() )
1166 {
1167 col = GetVal().m_colour;
1168 }
1169
1170 if ( col.Ok() )
1171 {
1172 dc.SetBrush(col);
1173 dc.DrawRectangle(rect);
1174 }
1175 }
1176
1177
1178 bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1179 {
1180 //
1181 // Accept colour format "[Name] [(R,G,B)]"
1182 // Name takes precedence.
1183 //
1184 wxString colourName;
1185 wxString colourRGB;
1186
1187 int ppos = text.Find(wxT("("));
1188
1189 if ( ppos == wxNOT_FOUND )
1190 {
1191 colourName = text;
1192 }
1193 else
1194 {
1195 colourName = text.substr(0, ppos);
1196 colourRGB = text.substr(ppos, text.length()-ppos);
1197 }
1198
1199 // Strip spaces from extremities
1200 colourName.Trim(true);
1201 colourName.Trim(false);
1202 colourRGB.Trim(true);
1203
1204 // Validate colourRGB string - (1,1,1) is shortest allowed
1205 if ( colourRGB.length() < 7 )
1206 colourRGB.clear();
1207
1208 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
1209 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1210 {
1211 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1212 {
1213 // This really should not occurr...
1214 // wxASSERT(false);
1215 ResetNextIndex();
1216 return false;
1217 }
1218
1219 QueryColourFromUser(value);
1220 }
1221 else
1222 {
1223 wxColourPropertyValue val;
1224
1225 bool done = false;
1226
1227 if ( colourName.length() )
1228 {
1229 // Try predefined colour first
1230 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1231 if ( res && GetIndex() >= 0 )
1232 {
1233 val.m_type = GetIndex();
1234 if ( val.m_type < m_choices.GetCount() )
1235 val.m_type = m_choices[val.m_type].GetValue();
1236
1237 // Get proper colour for type.
1238 val.m_colour = GetColour(val.m_type);
1239
1240 done = true;
1241 }
1242 }
1243 if ( colourRGB.length() && !done )
1244 {
1245 // Then check custom colour.
1246 val.m_type = wxPG_COLOUR_CUSTOM;
1247
1248 int r = -1, g = -1, b = -1;
1249 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1250
1251 if ( r >= 0 && r <= 255 &&
1252 g >= 0 && g <= 255 &&
1253 b >= 0 && b <= 255 )
1254 {
1255 val.m_colour.Set(r,g,b);
1256
1257 done = true;
1258 }
1259 }
1260
1261 if ( !done )
1262 {
1263 ResetNextIndex();
1264 return false;
1265 }
1266
1267 value = DoTranslateVal(val);
1268 }
1269
1270 return true;
1271 }
1272
1273
1274 bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1275 {
1276 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1277 {
1278 int ival = wxPGVariantToInt(value);
1279
1280 SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
1281
1282 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1283 {
1284 // Show custom choice
1285 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1286 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1287 }
1288 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1289 {
1290 // Hide custom choice
1291 m_choices.RemoveAt(GetCustomColourIndex());
1292 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1293 }
1294 return true;
1295 }
1296 return false;
1297 }
1298
1299
1300 // -----------------------------------------------------------------------
1301 // wxColourProperty
1302 // -----------------------------------------------------------------------
1303
1304 static const wxChar* gs_cp_es_normcolour_labels[] = {
1305 wxT("Black"),
1306 wxT("Maroon"),
1307 wxT("Navy"),
1308 wxT("Purple"),
1309 wxT("Teal"),
1310 wxT("Gray"),
1311 wxT("Green"),
1312 wxT("Olive"),
1313 wxT("Brown"),
1314 wxT("Blue"),
1315 wxT("Fuchsia"),
1316 wxT("Red"),
1317 wxT("Orange"),
1318 wxT("Silver"),
1319 wxT("Lime"),
1320 wxT("Aqua"),
1321 wxT("Yellow"),
1322 wxT("White"),
1323 wxT("Custom"),
1324 (const wxChar*) NULL
1325 };
1326
1327 static unsigned long gs_cp_es_normcolour_colours[] = {
1328 wxPG_COLOUR(0,0,0),
1329 wxPG_COLOUR(128,0,0),
1330 wxPG_COLOUR(0,0,128),
1331 wxPG_COLOUR(128,0,128),
1332 wxPG_COLOUR(0,128,128),
1333 wxPG_COLOUR(128,128,128),
1334 wxPG_COLOUR(0,128,0),
1335 wxPG_COLOUR(128,128,0),
1336 wxPG_COLOUR(166,124,81),
1337 wxPG_COLOUR(0,0,255),
1338 wxPG_COLOUR(255,0,255),
1339 wxPG_COLOUR(255,0,0),
1340 wxPG_COLOUR(247,148,28),
1341 wxPG_COLOUR(192,192,192),
1342 wxPG_COLOUR(0,255,0),
1343 wxPG_COLOUR(0,255,255),
1344 wxPG_COLOUR(255,255,0),
1345 wxPG_COLOUR(255,255,255),
1346 wxPG_COLOUR(0,0,0)
1347 };
1348
1349 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1350 wxColour, const wxColour&, TextCtrlAndButton)
1351
1352 static wxPGChoices gs_wxColourProperty_choicesCache;
1353
1354 wxColourProperty::wxColourProperty( const wxString& label,
1355 const wxString& name,
1356 const wxColour& value )
1357 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1358 NULL,
1359 &gs_wxColourProperty_choicesCache, value )
1360 {
1361 Init( value );
1362
1363 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1364 }
1365
1366 wxColourProperty::~wxColourProperty()
1367 {
1368 }
1369
1370 void wxColourProperty::Init( wxColour colour )
1371 {
1372 if ( !colour.Ok() )
1373 colour = *wxWHITE;
1374 wxVariant variant;
1375 variant << colour;
1376 m_value = variant;
1377 int ind = ColToInd(colour);
1378 if ( ind < 0 )
1379 ind = m_choices.GetCount() - 1;
1380 SetIndex( ind );
1381 }
1382
1383 wxString wxColourProperty::ValueToString( wxVariant& value,
1384 int argFlags ) const
1385 {
1386 const wxPGEditor* editor = GetEditorClass();
1387 if ( editor != wxPGEditor_Choice &&
1388 editor != wxPGEditor_ChoiceAndButton &&
1389 editor != wxPGEditor_ComboBox )
1390 argFlags |= wxPG_PROPERTY_SPECIFIC;
1391
1392 return wxSystemColourProperty::ValueToString(value, argFlags);
1393 }
1394
1395 wxColour wxColourProperty::GetColour( int index ) const
1396 {
1397 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1398 }
1399
1400 wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1401 {
1402 wxVariant variant;
1403 variant << v.m_colour;
1404 return variant;
1405 }
1406
1407 // -----------------------------------------------------------------------
1408 // wxCursorProperty
1409 // -----------------------------------------------------------------------
1410
1411 #define wxPG_CURSOR_IMAGE_WIDTH 32
1412
1413 #define NUM_CURSORS 28
1414
1415 //#define wx_cp_es_syscursors_len 28
1416 static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1417 wxT("Default"),
1418 wxT("Arrow"),
1419 wxT("Right Arrow"),
1420 wxT("Blank"),
1421 wxT("Bullseye"),
1422 wxT("Character"),
1423 wxT("Cross"),
1424 wxT("Hand"),
1425 wxT("I-Beam"),
1426 wxT("Left Button"),
1427 wxT("Magnifier"),
1428 wxT("Middle Button"),
1429 wxT("No Entry"),
1430 wxT("Paint Brush"),
1431 wxT("Pencil"),
1432 wxT("Point Left"),
1433 wxT("Point Right"),
1434 wxT("Question Arrow"),
1435 wxT("Right Button"),
1436 wxT("Sizing NE-SW"),
1437 wxT("Sizing N-S"),
1438 wxT("Sizing NW-SE"),
1439 wxT("Sizing W-E"),
1440 wxT("Sizing"),
1441 wxT("Spraycan"),
1442 wxT("Wait"),
1443 wxT("Watch"),
1444 wxT("Wait Arrow"),
1445 (const wxChar*) NULL
1446 };
1447
1448 static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1449 wxCURSOR_NONE,
1450 wxCURSOR_ARROW,
1451 wxCURSOR_RIGHT_ARROW,
1452 wxCURSOR_BLANK,
1453 wxCURSOR_BULLSEYE,
1454 wxCURSOR_CHAR,
1455 wxCURSOR_CROSS,
1456 wxCURSOR_HAND,
1457 wxCURSOR_IBEAM,
1458 wxCURSOR_LEFT_BUTTON,
1459 wxCURSOR_MAGNIFIER,
1460 wxCURSOR_MIDDLE_BUTTON,
1461 wxCURSOR_NO_ENTRY,
1462 wxCURSOR_PAINT_BRUSH,
1463 wxCURSOR_PENCIL,
1464 wxCURSOR_POINT_LEFT,
1465 wxCURSOR_POINT_RIGHT,
1466 wxCURSOR_QUESTION_ARROW,
1467 wxCURSOR_RIGHT_BUTTON,
1468 wxCURSOR_SIZENESW,
1469 wxCURSOR_SIZENS,
1470 wxCURSOR_SIZENWSE,
1471 wxCURSOR_SIZEWE,
1472 wxCURSOR_SIZING,
1473 wxCURSOR_SPRAYCAN,
1474 wxCURSOR_WAIT,
1475 wxCURSOR_WATCH,
1476 wxCURSOR_ARROWWAIT
1477 };
1478
1479 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1480
1481 wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1482 int value )
1483 : wxEnumProperty( label,
1484 name,
1485 gs_cp_es_syscursors_labels,
1486 gs_cp_es_syscursors_values,
1487 value )
1488 {
1489 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1490 }
1491
1492 wxCursorProperty::~wxCursorProperty()
1493 {
1494 }
1495
1496 wxSize wxCursorProperty::OnMeasureImage( int item ) const
1497 {
1498 #if wxPG_CAN_DRAW_CURSOR
1499 if ( item != -1 && item < NUM_CURSORS )
1500 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1501 #else
1502 wxUnusedVar(item);
1503 #endif
1504 return wxSize(0,0);
1505 }
1506
1507 #if wxPG_CAN_DRAW_CURSOR
1508
1509 void wxCursorProperty::OnCustomPaint( wxDC& dc,
1510 const wxRect& rect,
1511 wxPGPaintData& paintdata )
1512 {
1513 // Background brush
1514 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1515
1516 if ( paintdata.m_choiceItem >= 0 )
1517 {
1518 dc.DrawRectangle( rect );
1519
1520 if ( paintdata.m_choiceItem < NUM_CURSORS )
1521 {
1522 wxStockCursor cursorIndex =
1523 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1524
1525 {
1526 if ( cursorIndex == wxCURSOR_NONE )
1527 cursorIndex = wxCURSOR_ARROW;
1528
1529 wxCursor cursor( cursorIndex );
1530
1531 #ifdef __WXMSW__
1532 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1533 ::DrawIconEx( hDc,
1534 rect.x,
1535 rect.y,
1536 (HICON)cursor.GetHandle(),
1537 0,
1538 0,
1539 0,
1540 NULL,
1541 DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL
1542 );
1543 #endif
1544 }
1545 }
1546 }
1547 }
1548
1549 #else
1550 void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1551 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1552 {
1553 return wxEnumProperty::GetCellRenderer(column);
1554 }*/
1555 #endif
1556
1557 // -----------------------------------------------------------------------
1558 // wxImageFileProperty
1559 // -----------------------------------------------------------------------
1560
1561 #if wxUSE_IMAGE
1562
1563 const wxString& wxPGGetDefaultImageWildcard()
1564 {
1565 // Form the wildcard, if not done yet
1566 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1567 {
1568
1569 wxString str;
1570
1571 // TODO: This section may require locking (using global).
1572
1573 wxList& handlers = wxImage::GetHandlers();
1574
1575 wxList::iterator node;
1576
1577 // Let's iterate over the image handler list.
1578 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1579 for ( node = handlers.begin(); node != handlers.end(); node++ )
1580 {
1581 wxImageHandler *handler = (wxImageHandler*)*node;
1582
1583 wxString ext_lo = handler->GetExtension();
1584 wxString ext_up = ext_lo.Upper();
1585
1586 str.append( ext_up );
1587 str.append( wxT(" files (*.") );
1588 str.append( ext_up );
1589 str.append( wxT(")|*.") );
1590 str.append( ext_lo );
1591 str.append( wxT("|") );
1592 }
1593
1594 str.append ( wxT("All files (*.*)|*.*") );
1595
1596 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1597 }
1598
1599 return wxPGGlobalVars->m_pDefaultImageWildcard;
1600 }
1601
1602 IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1603
1604 wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1605 const wxString& value )
1606 : wxFileProperty(label,name,value)
1607 {
1608 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1609
1610 m_pImage = (wxImage*) NULL;
1611 m_pBitmap = (wxBitmap*) NULL;
1612 }
1613
1614 wxImageFileProperty::~wxImageFileProperty()
1615 {
1616 if ( m_pBitmap )
1617 delete m_pBitmap;
1618 if ( m_pImage )
1619 delete m_pImage;
1620 }
1621
1622 void wxImageFileProperty::OnSetValue()
1623 {
1624 wxFileProperty::OnSetValue();
1625
1626 // Delete old image
1627 if ( m_pImage )
1628 {
1629 delete m_pImage;
1630 m_pImage = NULL;
1631 }
1632 if ( m_pBitmap )
1633 {
1634 delete m_pBitmap;
1635 m_pBitmap = NULL;
1636 }
1637
1638 wxFileName filename = GetFileName();
1639
1640 // Create the image thumbnail
1641 if ( filename.FileExists() )
1642 {
1643 m_pImage = new wxImage( filename.GetFullPath() );
1644 }
1645 }
1646
1647 wxSize wxImageFileProperty::OnMeasureImage( int ) const
1648 {
1649 return wxPG_DEFAULT_IMAGE_SIZE;
1650 }
1651
1652 void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1653 const wxRect& rect,
1654 wxPGPaintData& )
1655 {
1656 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1657 {
1658 // Draw the thumbnail
1659
1660 // Create the bitmap here because required size is not known in OnSetValue().
1661 if ( !m_pBitmap )
1662 {
1663 m_pImage->Rescale( rect.width, rect.height );
1664 m_pBitmap = new wxBitmap( *m_pImage );
1665 delete m_pImage;
1666 m_pImage = NULL;
1667 }
1668
1669 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1670 }
1671 else
1672 {
1673 // No file - just draw a white box
1674 dc.SetBrush( *wxWHITE_BRUSH );
1675 dc.DrawRectangle ( rect );
1676 }
1677 }
1678
1679 #endif // wxUSE_IMAGE
1680
1681 // -----------------------------------------------------------------------
1682 // wxMultiChoiceProperty
1683 // -----------------------------------------------------------------------
1684
1685 #if wxUSE_CHOICEDLG
1686
1687 #include "wx/choicdlg.h"
1688
1689 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1690 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1691
1692 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1693 const wxString& name,
1694 const wxPGChoices& choices,
1695 const wxArrayString& value)
1696 : wxPGProperty(label,name)
1697 {
1698 m_choices.Assign(choices);
1699 SetValue(value);
1700 }
1701
1702 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1703 const wxString& name,
1704 const wxArrayString& strings,
1705 const wxArrayString& value)
1706 : wxPGProperty(label,name)
1707 {
1708 m_choices.Set(strings);
1709 SetValue(value);
1710 }
1711
1712 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1713 const wxString& name,
1714 const wxArrayString& value)
1715 : wxPGProperty(label,name)
1716 {
1717 wxArrayString strings;
1718 m_choices.Set(strings);
1719 SetValue(value);
1720 }
1721
1722 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1723 {
1724 }
1725
1726 void wxMultiChoiceProperty::OnSetValue()
1727 {
1728 GenerateValueAsString(m_value, &m_display);
1729 }
1730
1731 wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1732 int argFlags ) const
1733 {
1734 // If possible, use cached string
1735 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1736 return m_display;
1737
1738 wxString s;
1739 GenerateValueAsString(value, &s);
1740 return s;
1741 }
1742
1743 void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1744 wxString* target ) const
1745 {
1746 wxArrayString strings;
1747
1748 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1749 strings = value.GetArrayString();
1750
1751 wxString& tempStr = *target;
1752 unsigned int i;
1753 unsigned int itemCount = strings.size();
1754
1755 tempStr.Empty();
1756
1757 if ( itemCount )
1758 tempStr.append( wxT("\"") );
1759
1760 for ( i = 0; i < itemCount; i++ )
1761 {
1762 tempStr.append( strings[i] );
1763 tempStr.append( wxT("\"") );
1764 if ( i < (itemCount-1) )
1765 tempStr.append ( wxT(" \"") );
1766 }
1767 }
1768
1769 wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1770 {
1771 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(GetValue());
1772 unsigned int i;
1773
1774 // Translate values to string indices.
1775 wxArrayInt selections;
1776
1777 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1778 {
1779 for ( i=0; i<valueArr.size(); i++ )
1780 selections.Add(-1);
1781 }
1782 else
1783 {
1784 for ( i=0; i<valueArr.size(); i++ )
1785 {
1786 int sIndex = m_choices.Index(valueArr[i]);
1787 if ( sIndex >= 0 )
1788 selections.Add(sIndex);
1789 }
1790 }
1791
1792 return selections;
1793 }
1794
1795 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1796 wxWindow* WXUNUSED(primary),
1797 wxEvent& event )
1798 {
1799 if ( propgrid->IsMainButtonEvent(event) )
1800 {
1801 // Update the value
1802 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1803
1804 wxArrayString labels = m_choices.GetLabels();
1805 unsigned int choiceCount;
1806
1807 if ( m_choices.IsOk() )
1808 choiceCount = m_choices.GetCount();
1809 else
1810 choiceCount = 0;
1811
1812 // launch editor dialog
1813 wxMultiChoiceDialog dlg( propgrid,
1814 _("Make a selection:"),
1815 m_label,
1816 choiceCount,
1817 choiceCount?&labels[0]:NULL,
1818 wxCHOICEDLG_STYLE );
1819
1820 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1821
1822 wxArrayString strings = useValue.GetArrayString();
1823 wxArrayString extraStrings;
1824
1825 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1826
1827 if ( dlg.ShowModal() == wxID_OK && choiceCount )
1828 {
1829 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1830
1831 wxArrayInt arrInt = dlg.GetSelections();
1832
1833 wxVariant variant;
1834
1835 // Strings that were not in list of choices
1836 wxArrayString value;
1837
1838 // Translate string indices to strings
1839
1840 unsigned int n;
1841 if ( userStringMode == 1 )
1842 {
1843 for (n=0;n<extraStrings.size();n++)
1844 value.push_back(extraStrings[n]);
1845 }
1846
1847 unsigned int i;
1848 for ( i=0; i<arrInt.size(); i++ )
1849 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1850
1851 if ( userStringMode == 2 )
1852 {
1853 for (n=0;n<extraStrings.size();n++)
1854 value.push_back(extraStrings[n]);
1855 }
1856
1857 variant = WXVARIANT(value);
1858
1859 SetValueInEvent(variant);
1860
1861 return true;
1862 }
1863 }
1864 return false;
1865 }
1866
1867 bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1868 {
1869 wxArrayString arr;
1870
1871 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1872
1873 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
1874 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
1875 arr.Add(token);
1876 WX_PG_TOKENIZER2_END()
1877
1878 wxVariant v( WXVARIANT(arr) );
1879 variant = v;
1880
1881 return true;
1882 }
1883
1884 #endif // wxUSE_CHOICEDLG
1885
1886
1887 // -----------------------------------------------------------------------
1888 // wxDateProperty
1889 // -----------------------------------------------------------------------
1890
1891 #if wxUSE_DATETIME
1892
1893
1894 #if wxUSE_DATEPICKCTRL
1895 #define dtCtrl DatePickerCtrl
1896 #else
1897 #define dtCtrl TextCtrl
1898 #endif
1899
1900 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
1901 wxPGProperty,
1902 wxDateTime,
1903 const wxDateTime&,
1904 dtCtrl)
1905
1906
1907 wxString wxDateProperty::ms_defaultDateFormat;
1908
1909
1910 wxDateProperty::wxDateProperty( const wxString& label,
1911 const wxString& name,
1912 const wxDateTime& value )
1913 : wxPGProperty(label,name)
1914 {
1915 //wxPGRegisterDefaultValueType(wxDateTime)
1916
1917 #if wxUSE_DATEPICKCTRL
1918 wxPGRegisterEditorClass(DatePickerCtrl);
1919
1920 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
1921 #else
1922 m_dpStyle = 0;
1923 #endif
1924
1925 SetValue( value );
1926 }
1927
1928 wxDateProperty::~wxDateProperty()
1929 {
1930 }
1931
1932 bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
1933 int WXUNUSED(argFlags) ) const
1934 {
1935 wxDateTime dt;
1936
1937 const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
1938
1939 if ( c )
1940 {
1941 variant = dt;
1942 return true;
1943 }
1944
1945 return false;
1946 }
1947
1948 wxString wxDateProperty::ValueToString( wxVariant& value,
1949 int argFlags ) const
1950 {
1951 const wxChar* format = (const wxChar*) NULL;
1952
1953 wxDateTime dateTime = value.GetDateTime();
1954
1955 if ( !dateTime.IsValid() )
1956 return wxT("Invalid");
1957
1958 if ( !ms_defaultDateFormat.length() )
1959 {
1960 #if wxUSE_DATEPICKCTRL
1961 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
1962 #else
1963 bool showCentury = true;
1964 #endif
1965 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
1966 }
1967
1968 if ( m_format.length() &&
1969 !(argFlags & wxPG_FULL_VALUE) )
1970 format = m_format.c_str();
1971
1972 // Determine default from locale
1973 // NB: This is really simple stuff, but can't figure anything
1974 // better without proper support in wxLocale
1975 if ( !format )
1976 format = ms_defaultDateFormat.c_str();
1977
1978 return dateTime.Format(format);
1979 }
1980
1981 wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
1982 {
1983 // This code is basicly copied from datectlg.cpp's SetFormat
1984 //
1985 wxString format;
1986
1987 wxDateTime dt;
1988 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
1989 wxString str(dt.Format(wxT("%x")));
1990
1991 const wxChar *p = str.c_str();
1992 while ( *p )
1993 {
1994 int n=wxAtoi(p);
1995 if (n == dt.GetDay())
1996 {
1997 format.Append(wxT("%d"));
1998 p += 2;
1999 }
2000 else if (n == (int)dt.GetMonth()+1)
2001 {
2002 format.Append(wxT("%m"));
2003 p += 2;
2004 }
2005 else if (n == dt.GetYear())
2006 {
2007 format.Append(wxT("%Y"));
2008 p += 4;
2009 }
2010 else if (n == (dt.GetYear() % 100))
2011 {
2012 if (showCentury)
2013 format.Append(wxT("%Y"));
2014 else
2015 format.Append(wxT("%y"));
2016 p += 2;
2017 }
2018 else
2019 format.Append(*p++);
2020 }
2021
2022 return format;
2023 }
2024
2025 bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2026 {
2027 if ( name == wxPG_DATE_FORMAT )
2028 {
2029 m_format = value.GetString();
2030 return true;
2031 }
2032 else if ( name == wxPG_DATE_PICKER_STYLE )
2033 {
2034 m_dpStyle = value.GetLong();
2035 ms_defaultDateFormat.clear(); // This may need recalculation
2036 return true;
2037 }
2038 return false;
2039 }
2040
2041 #endif // wxUSE_DATETIME
2042
2043
2044 // -----------------------------------------------------------------------
2045 // wxPropertyGridInterface
2046 // -----------------------------------------------------------------------
2047
2048 void wxPropertyGridInterface::InitAllTypeHandlers()
2049 {
2050 }
2051
2052 // -----------------------------------------------------------------------
2053
2054 void wxPropertyGridInterface::RegisterAdditionalEditors()
2055 {
2056 // Register editor classes, if necessary.
2057 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2058 wxPropertyGrid::RegisterDefaultEditors();
2059
2060 #if wxUSE_SPINBTN
2061 wxPGRegisterEditorClass(SpinCtrl);
2062 #endif
2063 #if wxUSE_DATEPICKCTRL
2064 wxPGRegisterEditorClass(DatePickerCtrl);
2065 #endif
2066 }
2067
2068 // -----------------------------------------------------------------------
2069
2070 #endif // wxPG_INCLUDE_ADVPROPS
2071
2072 #endif // wxUSE_PROPGRID
2073