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