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