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