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