]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/props.cpp
Adding compiling (but not yet working) taskbar implementation for OS X Cocoa, mostly...
[wxWidgets.git] / src / propgrid / props.cpp
CommitLineData
1c4293cb
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/propgrid/props.cpp
3// Purpose: Basic Property Classes
4// Author: Jaakko Salli
5// Modified by:
6// Created: 2005-05-14
7// RCS-ID: $Id:
8// Copyright: (c) Jaakko Salli
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
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/dcmemory.h"
33 #include "wx/button.h"
34 #include "wx/pen.h"
35 #include "wx/brush.h"
36 #include "wx/cursor.h"
37 #include "wx/dialog.h"
38 #include "wx/settings.h"
39 #include "wx/msgdlg.h"
40 #include "wx/choice.h"
41 #include "wx/stattext.h"
42 #include "wx/scrolwin.h"
43 #include "wx/dirdlg.h"
44 #include "wx/combobox.h"
45 #include "wx/layout.h"
46 #include "wx/sizer.h"
47 #include "wx/textdlg.h"
48 #include "wx/filedlg.h"
1c4293cb
VZ
49 #include "wx/intl.h"
50#endif
51
52#include <wx/filename.h>
53
54#include <wx/propgrid/propgrid.h>
55
56#define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
57
58
59// -----------------------------------------------------------------------
60// wxStringProperty
61// -----------------------------------------------------------------------
62
63WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty,wxPGProperty,
64 wxString,const wxString&,TextCtrl)
65
66wxStringProperty::wxStringProperty( const wxString& label,
67 const wxString& name,
68 const wxString& value )
69 : wxPGProperty(label,name)
70{
71 SetValue(value);
72}
73
74void wxStringProperty::OnSetValue()
75{
76 if ( !m_value.IsNull() && m_value.GetString() == wxS("<composed>") )
77 SetFlag(wxPG_PROP_COMPOSED_VALUE);
78
79 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE) )
80 {
81 wxString s;
82 GenerateComposedValue(s, 0);
83 m_value = s;
84 }
85}
86
87wxStringProperty::~wxStringProperty() { }
88
89wxString wxStringProperty::GetValueAsString( int argFlags ) const
90{
91 wxString s = m_value.GetString();
92
93 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) )
94 {
95 // Value stored in m_value is non-editable, non-full value
96 if ( (argFlags & wxPG_FULL_VALUE) || (argFlags & wxPG_EDITABLE_VALUE) )
97 GenerateComposedValue(s, argFlags);
98
99 return s;
100 }
101
102 // If string is password and value is for visual purposes,
103 // then return asterisks instead the actual string.
104 if ( (m_flags & wxPG_PROP_PASSWORD) && !(argFlags & (wxPG_FULL_VALUE|wxPG_EDITABLE_VALUE)) )
105 return wxString(wxChar('*'), s.Length());
106
107 return s;
108}
109
110bool wxStringProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
111{
112 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) )
113 return wxPGProperty::StringToValue(variant, text, argFlags);
114
115 if ( m_value.GetString() != text )
116 {
117 variant = text;
118 return true;
119 }
120
121 return false;
122}
123
124bool wxStringProperty::DoSetAttribute( const wxString& name, wxVariant& value )
125{
126 if ( name == wxPG_STRING_PASSWORD )
127 {
128 m_flags &= ~(wxPG_PROP_PASSWORD);
129 if ( wxPGVariantToInt(value) ) m_flags |= wxPG_PROP_PASSWORD;
130 RecreateEditor();
131 return false;
132 }
133 return true;
134}
135
136// -----------------------------------------------------------------------
137// wxIntProperty
138// -----------------------------------------------------------------------
139
140WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty,wxPGProperty,
141 long,long,TextCtrl)
142
143wxIntProperty::wxIntProperty( const wxString& label, const wxString& name,
144 long value ) : wxPGProperty(label,name)
145{
146 SetValue(value);
147}
148
149wxIntProperty::wxIntProperty( const wxString& label, const wxString& name,
150 const wxLongLong& value ) : wxPGProperty(label,name)
151{
0372d42e 152 SetValue(WXVARIANT(value));
1c4293cb
VZ
153}
154
155wxIntProperty::~wxIntProperty() { }
156
157wxString wxIntProperty::GetValueAsString( int ) const
158{
0372d42e
JS
159 if ( m_value.GetType() == wxPG_VARIANT_TYPE_LONG )
160 {
1c4293cb 161 return wxString::Format(wxS("%li"),m_value.GetLong());
0372d42e
JS
162 }
163 else if ( m_value.GetType() == wxLongLong_VariantType )
164 {
165 wxLongLong ll;
166 ll << m_value;
167 return ll.ToString();
168 }
1c4293cb 169
0372d42e 170 return wxEmptyString;
1c4293cb
VZ
171}
172
173bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
174{
175 wxString s;
176 long value32;
177
178 if ( text.length() == 0 )
179 {
180 variant.MakeNull();
181 return true;
182 }
183
184 // We know it is a number, but let's still check
185 // the return value.
186 if ( text.IsNumber() )
187 {
188 // Remove leading zeroes, so that the number is not interpreted as octal
189 wxString::const_iterator i = text.begin();
190 wxString::const_iterator iMax = text.end() - 1; // Let's allow one, last zero though
191
192 int firstNonZeroPos = 0;
193
194 for ( ; i != iMax; i++ )
195 {
196 wxChar c = *i;
197 if ( c != wxS('0') && c != wxS(' ') )
198 break;
199 firstNonZeroPos++;
200 }
201
202 wxString useText = text.substr(firstNonZeroPos, text.length() - firstNonZeroPos);
203
0372d42e
JS
204 wxString variantType = variant.GetType();
205 bool isPrevLong = variantType == wxPG_VARIANT_TYPE_LONG;
1c4293cb
VZ
206
207 wxLongLong_t value64 = 0;
208
209 if ( useText.ToLongLong(&value64, 10) &&
210 ( value64 >= INT_MAX || value64 <= INT_MIN )
211 )
212 {
0372d42e
JS
213 bool doChangeValue = isPrevLong;
214
215 if ( !isPrevLong && variantType == wxLongLong_VariantType )
216 {
217 wxLongLong oldValue;
218 oldValue << variant;
219 if ( oldValue.GetValue() != value64 )
220 doChangeValue = true;
221 }
222
223 if ( doChangeValue )
1c4293cb 224 {
0372d42e
JS
225 wxLongLong ll(value64);
226 variant << ll;
1c4293cb
VZ
227 return true;
228 }
229 }
230
231 if ( useText.ToLong( &value32, 0 ) )
232 {
233 if ( !isPrevLong || m_value.GetLong() != value32 )
234 {
235 variant = value32;
236 return true;
237 }
238 }
239 }
240 else if ( argFlags & wxPG_REPORT_ERROR )
241 {
242 }
243 return false;
244}
245
246bool wxIntProperty::IntToValue( wxVariant& variant, int value, int WXUNUSED(argFlags) ) const
247{
0372d42e 248 if ( variant.GetType() != wxPG_VARIANT_TYPE_LONG || variant.GetLong() != value )
1c4293cb
VZ
249 {
250 variant = (long)value;
251 return true;
252 }
253 return false;
254}
255
256bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& value, wxPGValidationInfo* pValidationInfo, int mode )
257{
258 // Check for min/max
259 wxLongLong_t min = wxINT64_MIN;
260 wxLongLong_t max = wxINT64_MAX;
261 wxVariant variant;
262 bool minOk = false;
263 bool maxOk = false;
264
265 variant = property->GetAttribute(wxPGGlobalVars->m_strMin);
266 if ( !variant.IsNull() )
267 {
268 wxPGVariantToLongLong(variant, &min);
269 minOk = true;
270 }
271
272 variant = property->GetAttribute(wxPGGlobalVars->m_strMax);
273 if ( !variant.IsNull() )
274 {
275 wxPGVariantToLongLong(variant, &max);
276 maxOk = true;
277 }
278
279 if ( minOk )
280 {
281 if ( value < min )
282 {
283 if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
284 pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min);
285 else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
286 value = min;
287 else
288 value = max - (min - value);
289 return false;
290 }
291 }
292
293 if ( maxOk )
294 {
295 if ( value > max )
296 {
297 if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
298 pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min);
299 else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
300 value = max;
301 else
302 value = min + (value - max);
303 return false;
304 }
305 }
306 return true;
307}
308
309bool wxIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
310{
311 wxLongLong_t ll;
312 if ( wxPGVariantToLongLong(value, &ll) )
313 return DoValidation(this, ll, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE);
314 return true;
315}
316
317wxValidator* wxIntProperty::GetClassValidator()
318{
319#if wxUSE_VALIDATORS
320 WX_PG_DOGETVALIDATOR_ENTRY()
321
322 // Atleast wxPython 2.6.2.1 required that the string argument is given
323 static wxString v;
324 wxTextValidator* validator = new wxTextValidator(wxFILTER_NUMERIC,&v);
325
326 WX_PG_DOGETVALIDATOR_EXIT(validator)
327#else
328 return NULL;
329#endif
330}
331
332wxValidator* wxIntProperty::DoGetValidator() const
333{
334 return GetClassValidator();
335}
336
337// -----------------------------------------------------------------------
338// wxUIntProperty
339// -----------------------------------------------------------------------
340
341
342#define wxPG_UINT_TEMPLATE_MAX 8
343
344static const wxChar* gs_uintTemplates32[wxPG_UINT_TEMPLATE_MAX] = {
345 wxT("%x"),wxT("0x%x"),wxT("$%x"),
346 wxT("%X"),wxT("0x%X"),wxT("$%X"),
347 wxT("%u"),wxT("%o")
348};
349
350static const wxChar* gs_uintTemplates64[wxPG_UINT_TEMPLATE_MAX] = {
351 wxT("%") wxLongLongFmtSpec wxT("x"),
352 wxT("0x%") wxLongLongFmtSpec wxT("x"),
353 wxT("$%") wxLongLongFmtSpec wxT("x"),
354 wxT("%") wxLongLongFmtSpec wxT("X"),
355 wxT("0x%") wxLongLongFmtSpec wxT("X"),
356 wxT("$%") wxLongLongFmtSpec wxT("X"),
357 wxT("%") wxLongLongFmtSpec wxT("u"),
358 wxT("%") wxLongLongFmtSpec wxT("o")
359};
360
361WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty,wxPGProperty,
362 long,unsigned long,TextCtrl)
363
364void wxUIntProperty::Init()
365{
366 m_base = 6; // This is magic number for dec base (must be same as in setattribute)
367 m_realBase = 10;
368 m_prefix = wxPG_PREFIX_NONE;
369}
370
371wxUIntProperty::wxUIntProperty( const wxString& label, const wxString& name,
372 unsigned long value ) : wxPGProperty(label,name)
373{
374 Init();
375 SetValue((long)value);
376}
377
378wxUIntProperty::wxUIntProperty( const wxString& label, const wxString& name,
379 const wxULongLong& value ) : wxPGProperty(label,name)
380{
381 Init();
0372d42e 382 SetValue(WXVARIANT(value));
1c4293cb
VZ
383}
384
385wxUIntProperty::~wxUIntProperty() { }
386
387wxString wxUIntProperty::GetValueAsString( int ) const
388{
389 size_t index = m_base + m_prefix;
390 if ( index >= wxPG_UINT_TEMPLATE_MAX )
391 index = wxPG_BASE_DEC;
392
0372d42e
JS
393 if ( m_value.GetType() == wxPG_VARIANT_TYPE_LONG )
394 {
395 return wxString::Format(gs_uintTemplates32[index], (unsigned long)m_value.GetLong());
396 }
397
398 wxULongLong ull;
399 ull << m_value;
400
401 return wxString::Format(gs_uintTemplates64[index], ull.GetValue());
1c4293cb
VZ
402}
403
404bool wxUIntProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const
405{
0372d42e
JS
406 wxString variantType = variant.GetType();
407 bool isPrevLong = variantType == wxPG_VARIANT_TYPE_LONG;
1c4293cb
VZ
408
409 if ( text.length() == 0 )
410 {
411 variant.MakeNull();
412 return true;
413 }
414
415 size_t start = 0;
416 if ( text[0] == wxS('$') )
417 start++;
418
419 wxULongLong_t value64 = 0;
420 wxString s = text.substr(start, text.length() - start);
421
422 if ( s.ToULongLong(&value64, (unsigned int)m_realBase) )
423 {
424 if ( value64 >= LONG_MAX )
425 {
0372d42e
JS
426 bool doChangeValue = isPrevLong;
427
428 if ( !isPrevLong && variantType == wxULongLong_VariantType )
1c4293cb 429 {
0372d42e
JS
430 wxULongLong oldValue;
431 oldValue << variant;
432 if ( oldValue.GetValue() != value64 )
433 doChangeValue = true;
434 }
435
436 if ( doChangeValue )
437 {
438 wxULongLong ull(value64);
439 variant << ull;
1c4293cb
VZ
440 return true;
441 }
442 }
443 else
444 {
445 unsigned long value32 = wxLongLong(value64).GetLo();
446 if ( !isPrevLong || m_value.GetLong() != (long)value32 )
447 {
448 variant = (long)value32;
449 return true;
450 }
451 }
452
453 }
454 return false;
455}
456
457bool wxUIntProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
458{
459 if ( m_value != (long)number )
460 {
461 variant = (long)number;
462 return true;
463 }
464 return false;
465}
466
467#ifdef ULLONG_MAX
468 #define wxUINT64_MAX ULLONG_MAX
469 #define wxUINT64_MIN wxULL(0)
470#else
471 #define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF)
472 #define wxUINT64_MIN wxULL(0)
473#endif
474
475bool wxUIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
476{
477 // Check for min/max
478 wxULongLong_t ll;
479 if ( wxPGVariantToULongLong(value, &ll) )
480 {
481 wxULongLong_t min = wxUINT64_MIN;
482 wxULongLong_t max = wxUINT64_MAX;
483 wxVariant variant;
484
485 variant = GetAttribute(wxPGGlobalVars->m_strMin);
486 if ( !variant.IsNull() )
487 {
488 wxPGVariantToULongLong(variant, &min);
489 if ( ll < min )
490 {
491 validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or higher"),min);
492 return false;
493 }
494 }
495 variant = GetAttribute(wxPGGlobalVars->m_strMax);
496 if ( !variant.IsNull() )
497 {
498 wxPGVariantToULongLong(variant, &max);
499 if ( ll > max )
500 {
501 validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or less"),max);
502 return false;
503 }
504 }
505 }
506 return true;
507}
508
509bool wxUIntProperty::DoSetAttribute( const wxString& name, wxVariant& value )
510{
511 if ( name == wxPG_UINT_BASE )
512 {
513 int val = value.GetLong();
514
515 m_realBase = (wxByte) val;
516 if ( m_realBase > 16 )
517 m_realBase = 16;
518
519 //
520 // Translate logical base to a template array index
521 m_base = 7; // oct
522 if ( val == wxPG_BASE_HEX )
523 m_base = 3;
524 else if ( val == wxPG_BASE_DEC )
525 m_base = 6;
526 else if ( val == wxPG_BASE_HEXL )
527 m_base = 0;
528 return true;
529 }
530 else if ( name == wxPG_UINT_PREFIX )
531 {
532 m_prefix = (wxByte) value.GetLong();
533 return true;
534 }
535 return false;
536}
537
538// -----------------------------------------------------------------------
539// wxFloatProperty
540// -----------------------------------------------------------------------
541
542WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty,wxPGProperty,
543 double,double,TextCtrl)
544
545wxFloatProperty::wxFloatProperty( const wxString& label,
546 const wxString& name,
547 double value )
548 : wxPGProperty(label,name)
549{
550 m_precision = -1;
551 SetValue(value);
552}
553
554wxFloatProperty::~wxFloatProperty() { }
555
556// This helper method provides standard way for floating point-using
557// properties to convert values to string.
558void wxPropertyGrid::DoubleToString(wxString& target,
559 double value,
560 int precision,
561 bool removeZeroes,
562 wxString* precTemplate)
563{
564 if ( precision >= 0 )
565 {
566 wxString text1;
567 if (!precTemplate)
568 precTemplate = &text1;
569
570 if ( !precTemplate->length() )
571 {
572 *precTemplate = wxS("%.");
573 *precTemplate << wxString::Format( wxS("%i"), precision );
574 *precTemplate << wxS('f');
575 }
576
577 target.Printf( precTemplate->c_str(), value );
578 }
579 else
580 {
581 target.Printf( wxS("%f"), value );
582 }
583
584 if ( removeZeroes && precision != 0 && target.length() )
585 {
586 // Remove excess zeroes (do not remove this code just yet,
587 // since sprintf can't do the same consistently across platforms).
588 wxString::const_iterator i = target.end() - 1;
589 size_t new_len = target.length() - 1;
590
591 for ( ; i != target.begin(); i-- )
592 {
593 if ( *i != wxS('0') )
594 break;
595 new_len--;
596 }
597
598 wxChar cur_char = *i;
599 if ( cur_char != wxS('.') && cur_char != wxS(',') )
600 new_len++;
601
602 if ( new_len != target.length() )
603 target.resize(new_len);
604 }
605}
606
607wxString wxFloatProperty::GetValueAsString( int argFlags ) const
608{
609 wxString text;
610 if ( !m_value.IsNull() )
611 {
612 wxPropertyGrid::DoubleToString(text,
613 m_value,
614 m_precision,
615 !(argFlags & wxPG_FULL_VALUE),
616 (wxString*) NULL);
617 }
618 return text;
619}
620
621bool wxFloatProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
622{
623 wxString s;
624 double value;
625
626 if ( text.length() == 0 )
627 {
628 variant.MakeNull();
629 return true;
630 }
631
632 bool res = text.ToDouble(&value);
633 if ( res )
634 {
635 if ( m_value != value )
636 {
637 variant = value;
638 return true;
639 }
640 }
641 else if ( argFlags & wxPG_REPORT_ERROR )
642 {
643 }
644 return false;
645}
646
647bool wxFloatProperty::DoValidation( const wxPGProperty* property, double& value, wxPGValidationInfo* pValidationInfo, int mode )
648{
649 // Check for min/max
650 double min = (double)wxINT64_MIN;
651 double max = (double)wxINT64_MAX;
652 wxVariant variant;
653 bool minOk = false;
654 bool maxOk = false;
655
656 variant = property->GetAttribute(wxPGGlobalVars->m_strMin);
657 if ( !variant.IsNull() )
658 {
659 wxPGVariantToDouble(variant, &min);
660 minOk = true;
661 }
662
663 variant = property->GetAttribute(wxPGGlobalVars->m_strMax);
664 if ( !variant.IsNull() )
665 {
666 wxPGVariantToDouble(variant, &max);
667 maxOk = true;
668 }
669
670 if ( minOk )
671 {
672 if ( value < min )
673 {
674 if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
675 pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or higher"),min);
676 else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
677 value = min;
678 else
679 value = max - (min - value);
680 return false;
681 }
682 }
683
684 if ( maxOk )
685 {
686 wxPGVariantToDouble(variant, &max);
687 if ( value > max )
688 {
689 if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
690 pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or less"),max);
691 else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
692 value = max;
693 else
694 value = min + (value - max);
695 return false;
696 }
697 }
698 return true;
699}
700
701bool wxFloatProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
702{
703 double fpv;
704 if ( wxPGVariantToDouble(value, &fpv) )
705 return DoValidation(this, fpv, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE);
706 return true;
707}
708
709bool wxFloatProperty::DoSetAttribute( const wxString& name, wxVariant& value )
710{
711 if ( name == wxPG_FLOAT_PRECISION )
712 {
713 m_precision = value.GetLong();
714 return true;
715 }
716 return false;
717}
718
719wxValidator* wxFloatProperty::DoGetValidator() const
720{
721 return wxIntProperty::GetClassValidator();
722}
723
724// -----------------------------------------------------------------------
725// wxBoolProperty
726// -----------------------------------------------------------------------
727
728// We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since
729// there is a custom GetEditorClass.
730
731IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty, wxPGProperty)
732
733const wxPGEditor* wxBoolProperty::DoGetEditorClass() const
734{
735 // Select correct editor control.
736#if wxPG_INCLUDE_CHECKBOX
737 if ( !(m_flags & wxPG_PROP_USE_CHECKBOX) )
738 return wxPG_EDITOR(Choice);
739 return wxPG_EDITOR(CheckBox);
740#else
741 return wxPG_EDITOR(Choice);
742#endif
743}
744
745wxBoolProperty::wxBoolProperty( const wxString& label, const wxString& name, bool value ) :
746 wxPGProperty(label,name)
747{
939d9364
JS
748 m_choices.Assign(wxPGGlobalVars->m_boolChoices);
749
1c4293cb
VZ
750 SetValue(wxPGVariant_Bool(value));
751
752 m_flags |= wxPG_PROP_USE_DCC;
753}
754
755wxBoolProperty::~wxBoolProperty() { }
756
757wxString wxBoolProperty::GetValueAsString( int argFlags ) const
758{
759 bool value = m_value.GetBool();
760
761 // As a fragment of composite string value,
762 // make it a little more readable.
763 if ( argFlags & wxPG_COMPOSITE_FRAGMENT )
764 {
765 if ( value )
766 {
767 return m_label;
768 }
769 else
770 {
771 if ( argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT )
772 return wxEmptyString;
773
18b5bcb0 774 wxString notFmt;
1c4293cb
VZ
775 if ( wxPGGlobalVars->m_autoGetTranslation )
776 notFmt = _("Not %s");
777 else
18b5bcb0 778 notFmt = wxS("Not %s");
1c4293cb 779
18b5bcb0 780 return wxString::Format(notFmt.c_str(), m_label.c_str());
1c4293cb
VZ
781 }
782 }
783
784 if ( !(argFlags & wxPG_FULL_VALUE) )
785 {
786 return wxPGGlobalVars->m_boolChoices[value?1:0].GetText();
787 }
788
789 wxString text;
790
791 if (value) text = wxS("true");
792 else text = wxS("false");
793
794 return text;
795}
796
1c4293cb
VZ
797bool wxBoolProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const
798{
799 int value = 0;
800 if ( text.CmpNoCase(wxPGGlobalVars->m_boolChoices[1].GetText()) == 0 ||
801 text.CmpNoCase(wxS("true")) == 0 ||
802 text.CmpNoCase(m_label) == 0 )
803 value = 1;
804
805 if ( text.length() == 0 )
806 {
807 variant.MakeNull();
808 return true;
809 }
810
811 bool oldValue = m_value.GetBool();
812
813 if ( (oldValue && !value) || (!oldValue && value) )
814 {
815 variant = wxPGVariant_Bool(value);
816 return true;
817 }
818 return false;
819}
820
821bool wxBoolProperty::IntToValue( wxVariant& variant, int value, int ) const
822{
823 bool boolValue = value ? true : false;
824 bool oldValue = m_value.GetBool();
825
826 if ( oldValue != boolValue )
827 {
828 variant = wxPGVariant_Bool(boolValue);
829 return true;
830 }
831 return false;
832}
833
834bool wxBoolProperty::DoSetAttribute( const wxString& name, wxVariant& value )
835{
836#if wxPG_INCLUDE_CHECKBOX
837 if ( name == wxPG_BOOL_USE_CHECKBOX )
838 {
839 int ival = wxPGVariantToInt(value);
840 if ( ival )
841 m_flags |= wxPG_PROP_USE_CHECKBOX;
842 else
843 m_flags &= ~(wxPG_PROP_USE_CHECKBOX);
844 return true;
845 }
846#endif
847 if ( name == wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING )
848 {
849 int ival = wxPGVariantToInt(value);
850 if ( ival )
851 m_flags |= wxPG_PROP_USE_DCC;
852 else
853 m_flags &= ~(wxPG_PROP_USE_DCC);
854 return true;
855 }
856 return false;
857}
858
859// -----------------------------------------------------------------------
860// wxBaseEnumProperty
861// -----------------------------------------------------------------------
862
863int wxBaseEnumProperty::ms_nextIndex = -2;
864
865wxBaseEnumProperty::wxBaseEnumProperty( const wxString& label, const wxString& name )
866 : wxPGProperty(label,name)
867{
868 m_value = wxPGVariant_Zero;
869}
870
871/** If has values array, then returns number at index with value -
872 otherwise just returns the value.
873*/
874int wxBaseEnumProperty::GetIndexForValue( int value ) const
875{
876 return value;
877}
878
879void wxBaseEnumProperty::OnSetValue()
880{
0372d42e
JS
881 wxString variantType = m_value.GetType();
882
883 if ( variantType == wxPG_VARIANT_TYPE_LONG )
1c4293cb 884 ValueFromInt_( m_value, m_value.GetLong(), wxPG_FULL_VALUE );
0372d42e 885 else if ( variantType == wxPG_VARIANT_TYPE_STRING )
1c4293cb
VZ
886 ValueFromString_( m_value, m_value.GetString(), 0 );
887 else
888 wxASSERT( false );
889
890 if ( ms_nextIndex != -2 )
891 {
892 m_index = ms_nextIndex;
893 ms_nextIndex = -2;
894 }
895}
896
897bool wxBaseEnumProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& WXUNUSED(validationInfo) ) const
898{
899 // Make sure string value is in the list,
900 // unless property has string as preferred value type
901 // To reduce code size, use conversion here as well
0372d42e 902 if ( value.GetType() == wxPG_VARIANT_TYPE_STRING &&
1c4293cb
VZ
903 !this->IsKindOf(CLASSINFO(wxEditEnumProperty)) )
904 return ValueFromString_( value, value.GetString(), wxPG_PROPERTY_SPECIFIC );
905
906 return true;
907}
908
909wxString wxBaseEnumProperty::GetValueAsString( int ) const
910{
0372d42e 911 if ( m_value.GetType() == wxPG_VARIANT_TYPE_STRING )
1c4293cb
VZ
912 return m_value.GetString();
913
914 if ( m_index >= 0 )
915 {
916 int unusedVal;
917 const wxString* pstr = GetEntry( m_index, &unusedVal );
918
919 if ( pstr )
920 return *pstr;
921 }
922 return wxEmptyString;
923}
924
925bool wxBaseEnumProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
926{
927 return ValueFromString_( variant, text, argFlags );
928}
929
930bool wxBaseEnumProperty::IntToValue( wxVariant& variant, int intVal, int argFlags ) const
931{
932 return ValueFromInt_( variant, intVal, argFlags );
933}
934
935bool wxBaseEnumProperty::ValueFromString_( wxVariant& value, const wxString& text, int argFlags ) const
936{
937 size_t i = 0;
938 const wxString* entryLabel;
939 int entryValue;
940 int useIndex = -1;
941 long useValue = 0;
942
943 entryLabel = GetEntry(i, &entryValue);
944 while ( entryLabel )
945 {
946 if ( text.CmpNoCase(*entryLabel) == 0 )
947 {
948 useIndex = (int)i;
949 useValue = (long)entryValue;
950 break;
951 }
952
953 i++;
954 entryLabel = GetEntry(i, &entryValue);
955 }
956
957 bool asText = false;
958
959 bool isEdit = this->IsKindOf(CLASSINFO(wxEditEnumProperty));
960
961 // If text not any of the choices, store as text instead
962 // (but only if we are wxEditEnumProperty)
963 if ( useIndex == -1 &&
0372d42e 964 (value.GetType() != wxPG_VARIANT_TYPE_STRING || (m_value.GetString() != text)) &&
1c4293cb
VZ
965 isEdit )
966 {
967 asText = true;
968 }
969
970 int setAsNextIndex = -2;
971
972 if ( asText )
973 {
974 setAsNextIndex = -1;
975 value = text;
976 }
977 else if ( m_index != useIndex )
978 {
979 if ( useIndex != -1 )
980 {
981 setAsNextIndex = useIndex;
982 value = (long)useValue;
983 }
984 else
985 {
986 setAsNextIndex = -1;
987 value = wxPGVariant_MinusOne;
988 }
989 }
990
991 if ( setAsNextIndex != -2 )
992 {
993 // If wxPG_PROPERTY_SPECIFIC is set, then this is done for
994 // validation purposes only, and index must not be changed
995 if ( !(argFlags & wxPG_PROPERTY_SPECIFIC) )
996 ms_nextIndex = setAsNextIndex;
997
998 if ( isEdit || setAsNextIndex != -1 )
999 return true;
1000 else
1001 return false;
1002 }
1003 return false;
1004}
1005
1006bool wxBaseEnumProperty::ValueFromInt_( wxVariant& variant, int intVal, int argFlags ) const
1007{
1008 // If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box.
1009 //
1010 ms_nextIndex = -2;
1011
1012 if ( argFlags & wxPG_FULL_VALUE )
1013 {
1014 ms_nextIndex = GetIndexForValue( intVal );
1015 }
1016 else
1017 {
1018 if ( m_index != intVal )
1019 {
1020 ms_nextIndex = intVal;
1021 }
1022 }
1023
1024 if ( ms_nextIndex != -2 )
1025 {
1026 if ( !(argFlags & wxPG_FULL_VALUE) )
1027 GetEntry(intVal, &intVal);
1028
1029 variant = (long)intVal;
1030
1031 return true;
1032 }
1033
1034 return false;
1035}
1036
1037void wxBaseEnumProperty::SetIndex( int index )
1038{
1039 ms_nextIndex = -2;
1040 m_index = index;
1041}
1042
1043int wxBaseEnumProperty::GetIndex() const
1044{
1045 if ( ms_nextIndex != -2 )
1046 return ms_nextIndex;
1047 return m_index;
1048}
1049
1050// -----------------------------------------------------------------------
1051// wxEnumProperty
1052// -----------------------------------------------------------------------
1053
1054IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty, wxPGProperty)
1055
1056WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty,long,Choice)
1057
1058wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1059 const long* values, int value ) : wxBaseEnumProperty(label,name)
1060{
1061 SetIndex(0);
1062
1063 if ( labels )
1064 {
1065 m_choices.Add(labels,values);
1066
1067 if ( GetItemCount() )
1068 SetValue( (long)value );
1069 }
1070}
1071
1072wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1073 const long* values, wxPGChoices* choicesCache, int value )
1074 : wxBaseEnumProperty(label,name)
1075{
1076 SetIndex(0);
1077
1078 wxASSERT( choicesCache );
1079
1080 if ( choicesCache->IsOk() )
1081 {
1082 m_choices.Assign( *choicesCache );
1083 m_value = wxPGVariant_Zero;
1084 }
1085 else if ( labels )
1086 {
1087 m_choices.Add(labels,values);
1088
1089 if ( GetItemCount() )
1090 SetValue( (long)value );
1091 }
1092}
1093
1094wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name,
1095 const wxArrayString& labels, const wxArrayInt& values, int value ) : wxBaseEnumProperty(label,name)
1096{
1097 SetIndex(0);
1098
1099 if ( &labels && labels.size() )
1100 {
1101 m_choices.Set(labels, values);
1102
1103 if ( GetItemCount() )
1104 SetValue( (long)value );
1105 }
1106}
1107
1108wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name,
1109 wxPGChoices& choices, int value )
1110 : wxBaseEnumProperty(label,name)
1111{
1112 m_choices.Assign( choices );
1113
1114 if ( GetItemCount() )
1115 SetValue( (long)value );
1116}
1117
1118int wxEnumProperty::GetIndexForValue( int value ) const
1119{
1120 if ( !m_choices.IsOk() )
1121 return -1;
1122
1123 if ( m_choices.HasValues() )
1124 {
1125 int intVal = m_choices.Index(value);
1126 if ( intVal >= 0 )
1127 return intVal;
1128 }
1129
1130 return value;
1131}
1132
1133wxEnumProperty::~wxEnumProperty ()
1134{
1135}
1136
1137const wxString* wxEnumProperty::GetEntry( size_t index, int* pvalue ) const
1138{
1139 if ( m_choices.IsOk() && index < m_choices.GetCount() )
1140 {
1141 int value = (int)index;
1142 if ( m_choices.HasValue(index) )
1143 value = m_choices.GetValue(index);
1144
1145 if ( pvalue )
1146 *pvalue = value;
1147
1148 return &m_choices.GetLabel(index);
1149 }
1150 return (const wxString*) NULL;
1151}
1152
1c4293cb
VZ
1153// -----------------------------------------------------------------------
1154// wxEditEnumProperty
1155// -----------------------------------------------------------------------
1156
1157IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty, wxPGProperty)
1158
1159WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty,wxString,ComboBox)
1160
1161wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1162 const long* values, const wxString& value )
1163 : wxEnumProperty(label,name,labels,values,0)
1164{
1165 SetValue( value );
1166}
1167
1168wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1169 const long* values, wxPGChoices* choicesCache, const wxString& value )
1170 : wxEnumProperty(label,name,labels,values,choicesCache,0)
1171{
1172 SetValue( value );
1173}
1174
1175wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name,
1176 const wxArrayString& labels, const wxArrayInt& values, const wxString& value )
1177 : wxEnumProperty(label,name,labels,values,0)
1178{
1179 SetValue( value );
1180}
1181
1182wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name,
1183 wxPGChoices& choices, const wxString& value )
1184 : wxEnumProperty(label,name,choices,0)
1185{
1186 SetValue( value );
1187}
1188
1189wxEditEnumProperty::~wxEditEnumProperty()
1190{
1191}
1192
1193// -----------------------------------------------------------------------
1194// wxFlagsProperty
1195// -----------------------------------------------------------------------
1196
1197IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty,wxPGProperty)
1198
1199WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty,long,TextCtrl)
1200
1201void wxFlagsProperty::Init()
1202{
1203 SetFlag(wxPG_PROP_AGGREGATE); // This is must be done here to support flag props
1204 // with inital zero children.
1205
1206 long value = m_value;
1207
1208 //
1209 // Generate children
1210 //
1211 unsigned int i;
1212
1213 unsigned int prevChildCount = m_children.GetCount();
1214
1215 int oldSel = -1;
1216 if ( prevChildCount )
1217 {
1218 wxPropertyGridPageState* state = GetParentState();
1219
1220 // State safety check (it may be NULL in immediate parent)
1221 wxASSERT( state );
1222
1223 if ( state )
1224 {
1225 wxPGProperty* selected = state->GetSelection();
1226 if ( selected )
1227 {
1228 if ( selected->GetParent() == this )
1229 oldSel = selected->GetArrIndex();
1230 else if ( selected == this )
1231 oldSel = -2;
1232 }
1233 }
1234 state->DoClearSelection();
1235 }
1236
1237 // Delete old children
1238 for ( i=0; i<prevChildCount; i++ )
1239 delete ( (wxPGProperty*) m_children[i] );
1240
1241 m_children.Empty();
1242
1243 if ( m_choices.IsOk() )
1244 {
1245 const wxPGChoices& choices = m_choices;
1246
1247 for ( i=0; i<GetItemCount(); i++ )
1248 {
1249 bool child_val;
1250 if ( choices.HasValue(i) )
1251 child_val = ( value & choices.GetValue(i) )?true:false;
1252 else
1253 child_val = ( value & (1<<i) )?true:false;
1254
1255 wxPGProperty* boolProp;
d665918b 1256 wxString label = GetLabel(i);
1c4293cb
VZ
1257
1258 #if wxUSE_INTL
1259 if ( wxPGGlobalVars->m_autoGetTranslation )
1260 {
d665918b 1261 boolProp = new wxBoolProperty( ::wxGetTranslation(label), label, child_val );
1c4293cb
VZ
1262 }
1263 else
1264 #endif
1265 {
d665918b 1266 boolProp = new wxBoolProperty( label, label, child_val );
1c4293cb
VZ
1267 }
1268 AddChild(boolProp);
1269 }
1270
1271 m_oldChoicesData = m_choices.GetDataPtr();
1272 }
1273
1274 m_oldValue = m_value;
1275
1276 if ( prevChildCount )
1277 SubPropsChanged(oldSel);
1278}
1279
1280wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1281 const wxChar** labels, const long* values, long value ) : wxPGProperty(label,name)
1282{
1283 m_oldChoicesData = (wxPGChoicesData*) NULL;
1284
1285 if ( labels )
1286 {
1287 m_choices.Set(labels,values);
1288
1289 wxASSERT( GetItemCount() );
1290
1291 SetValue( value );
1292 }
1293 else
1294 {
1295 m_value = wxPGVariant_Zero;
1296 }
1297}
1298
1299wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1300 const wxArrayString& labels, const wxArrayInt& values, int value )
1301 : wxPGProperty(label,name)
1302{
1303 m_oldChoicesData = (wxPGChoicesData*) NULL;
1304
1305 if ( &labels && labels.size() )
1306 {
1307 m_choices.Set(labels,values);
1308
1309 wxASSERT( GetItemCount() );
1310
1311 SetValue( (long)value );
1312 }
1313 else
1314 {
1315 m_value = wxPGVariant_Zero;
1316 }
1317}
1318
1319wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1320 wxPGChoices& choices, long value )
1321 : wxPGProperty(label,name)
1322{
1323 m_oldChoicesData = (wxPGChoicesData*) NULL;
1324
1325 if ( choices.IsOk() )
1326 {
1327 m_choices.Assign(choices);
1328
1329 wxASSERT( GetItemCount() );
1330
1331 SetValue( value );
1332 }
1333 else
1334 {
1335 m_value = wxPGVariant_Zero;
1336 }
1337}
1338
1339wxFlagsProperty::~wxFlagsProperty()
1340{
1341}
1342
1343void wxFlagsProperty::OnSetValue()
1344{
1345 if ( !m_choices.IsOk() || !GetItemCount() )
1346 {
1347 m_value = wxPGVariant_Zero;
1348 }
1349 else
1350 {
1351 long val = m_value.GetLong();
1352
1353 long fullFlags = 0;
1354
1355 // normalize the value (i.e. remove extra flags)
1356 unsigned int i;
1357 const wxPGChoices& choices = m_choices;
1358 for ( i = 0; i < GetItemCount(); i++ )
1359 {
1360 if ( choices.HasValue(i) )
1361 fullFlags |= choices.GetValue(i);
1362 else
1363 fullFlags |= (1<<i);
1364 }
1365
1366 val &= fullFlags;
1367
1368 m_value = val;
1369
1370 // Need to (re)init now?
1371 if ( GetChildCount() != GetItemCount() ||
1372 m_choices.GetDataPtr() != m_oldChoicesData )
1373 {
1374 Init();
1375 }
1376 }
1377
1378 long newFlags = m_value;
1379
1380 if ( newFlags != m_oldValue )
1381 {
1382 // Set child modified states
1383 unsigned int i;
1384 const wxPGChoices& choices = m_choices;
1385 for ( i = 0; i<GetItemCount(); i++ )
1386 {
1387 int flag;
1388
1389 if ( choices.HasValue(i) )
1390 flag = choices.GetValue(i);
1391 else
1392 flag = (1<<i);
1393
1394 if ( (newFlags & flag) != (m_oldValue & flag) )
1395 Item(i)->SetFlag( wxPG_PROP_MODIFIED );
1396 }
1397
1398 m_oldValue = newFlags;
1399 }
1400}
1401
1402wxString wxFlagsProperty::GetValueAsString( int ) const
1403{
1404 wxString text;
1405
1406 if ( !m_choices.IsOk() )
1407 return text;
1408
1409 long flags = m_value;
1410 unsigned int i;
1411 const wxPGChoices& choices = m_choices;
1412
1413 for ( i = 0; i < GetItemCount(); i++ )
1414 {
1415 int doAdd;
1416 if ( choices.HasValue(i) )
1417 doAdd = ( flags & choices.GetValue(i) );
1418 else
1419 doAdd = ( flags & (1<<i) );
1420
1421 if ( doAdd )
1422 {
1423 text += choices.GetLabel(i);
1424 text += wxS(", ");
1425 }
1426 }
1427
1428 // remove last comma
1429 if ( text.Len() > 1 )
1430 text.Truncate ( text.Len() - 2 );
1431
1432 return text;
1433}
1434
1435// Translate string into flag tokens
1436bool wxFlagsProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1437{
1438 if ( !m_choices.IsOk() )
1439 return false;
1440
1441 long newFlags = 0;
1442 long oldValue = m_value;
1443
1444 // semicolons are no longer valid delimeters
1445 WX_PG_TOKENIZER1_BEGIN(text,wxS(','))
1446
1447 if ( token.length() )
1448 {
1449 // Determine which one it is
1450 long bit = IdToBit( token );
1451
1452 if ( bit != -1 )
1453 {
1454 // Changed?
1455 newFlags |= bit;
1456 }
1457 else
1458 {
1459 break;
1460 }
1461 }
1462
1463 WX_PG_TOKENIZER1_END()
1464
1465 variant = newFlags;
1466
1467 if ( newFlags != oldValue )
1468 return true;
1469
1470 return false;
1471}
1472
1473// Converts string id to a relevant bit.
1474long wxFlagsProperty::IdToBit( const wxString& id ) const
1475{
1476 unsigned int i;
1477 for ( i = 0; i < GetItemCount(); i++ )
1478 {
1479 if ( id == GetLabel(i) )
1480 {
1481 if ( m_choices.HasValue(i) )
1482 return m_choices.GetValue(i);
1483 return (1<<i);
1484 }
1485 }
1486 return -1;
1487}
1488
1489void wxFlagsProperty::RefreshChildren()
1490{
1491 if ( !m_choices.IsOk() || !GetChildCount() ) return;
1492
1493 int flags = m_value.GetLong();
1494
1495 const wxPGChoices& choices = m_choices;
1496 unsigned int i;
1497 for ( i = 0; i < GetItemCount(); i++ )
1498 {
1499 long flag;
1500
1501 if ( choices.HasValue(i) )
1502 flag = choices.GetValue(i);
1503 else
1504 flag = (1<<i);
1505
1506 long subVal = flags & flag;
1507 wxPGProperty* p = Item(i);
1508
1509 if ( subVal != (m_oldValue & flag) )
1510 p->SetFlag( wxPG_PROP_MODIFIED );
1511
1512 p->SetValue( subVal?true:false );
1513 }
1514
1515 m_oldValue = flags;
1516}
1517
1518void wxFlagsProperty::ChildChanged( wxVariant& thisValue, int childIndex, wxVariant& childValue ) const
1519{
1520 long oldValue = thisValue.GetLong();
1521 long val = childValue.GetLong();
1522 unsigned long vi = (1<<childIndex);
1523 if ( m_choices.HasValue(childIndex) ) vi = m_choices.GetValue(childIndex);
1524 if ( val )
1525 thisValue = (long)(oldValue | vi);
1526 else
1527 thisValue = (long)(oldValue & ~(vi));
1528}
1529
1c4293cb
VZ
1530// -----------------------------------------------------------------------
1531// wxDirProperty
1532// -----------------------------------------------------------------------
1533
d53f610c 1534IMPLEMENT_DYNAMIC_CLASS(wxDirProperty, wxLongStringProperty)
1c4293cb
VZ
1535
1536wxDirProperty::wxDirProperty( const wxString& name, const wxString& label, const wxString& value )
1537 : wxLongStringProperty(name,label,value)
1538{
1539 m_flags |= wxPG_NO_ESCAPE;
1540}
1541wxDirProperty::~wxDirProperty() { }
1542
1543wxValidator* wxDirProperty::DoGetValidator() const
1544{
1545 return wxFileProperty::GetClassValidator();
1546}
1547
1548bool wxDirProperty::OnButtonClick( wxPropertyGrid* propGrid, wxString& value )
1549{
1550 wxSize dlg_sz(300,400);
1551
1552 wxDirDialog dlg( propGrid,
1553 m_dlgMessage.length() ? m_dlgMessage : wxString(_("Choose a directory:")),
1554 value,
1555 0,
1556#if !wxPG_SMALL_SCREEN
1557 propGrid->GetGoodEditorDialogPosition(this,dlg_sz),
1558 dlg_sz );
1559#else
1560 wxDefaultPosition,
1561 wxDefaultSize );
1562#endif
1563
1564 if ( dlg.ShowModal() == wxID_OK )
1565 {
1566 value = dlg.GetPath();
1567 return true;
1568 }
1569 return false;
1570}
1571
1572bool wxDirProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1573{
1574 if ( name == wxPG_DIR_DIALOG_MESSAGE )
1575 {
1576 m_dlgMessage = value.GetString();
1577 return true;
1578 }
1579 return false;
1580}
1581
1582// -----------------------------------------------------------------------
1583// wxPGFileDialogAdapter
1584// -----------------------------------------------------------------------
1585
1586bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property )
1587{
1588 wxFileProperty* fileProp = NULL;
1589 wxString path;
1590 int indFilter = -1;
1591
1592 if ( property->IsKindOf(CLASSINFO(wxFileProperty)) )
1593 {
1594 fileProp = ((wxFileProperty*)property);
1595 path = fileProp->m_filename.GetPath();
1596 indFilter = fileProp->m_indFilter;
1597
1598 if ( !path.length() && fileProp->m_basePath.length() )
1599 path = fileProp->m_basePath;
1600 }
1601 else
1602 {
1603 wxFileName fn(property->GetValue().GetString());
1604 path = fn.GetPath();
1605 }
1606
1607 wxFileDialog dlg( propGrid->GetPanel(),
1608 property->GetAttribute(wxS("DialogTitle"), _("Choose a file")),
1609 property->GetAttribute(wxS("InitialPath"), path),
1610 wxEmptyString,
1611 property->GetAttribute(wxPG_FILE_WILDCARD, _("All files (*.*)|*.*")),
1612 0,
1613 wxDefaultPosition );
1614
1615 if ( indFilter >= 0 )
1616 dlg.SetFilterIndex( indFilter );
1617
1618 if ( dlg.ShowModal() == wxID_OK )
1619 {
1620 if ( fileProp )
1621 fileProp->m_indFilter = dlg.GetFilterIndex();
1622 SetValue( dlg.GetPath() );
1623 return true;
1624 }
1625 return false;
1626}
1627
1628// -----------------------------------------------------------------------
1629// wxFileProperty
1630// -----------------------------------------------------------------------
1631
1632WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty,wxPGProperty,
1633 wxString,const wxString&,TextCtrlAndButton)
1634
1635wxFileProperty::wxFileProperty( const wxString& label, const wxString& name,
1636 const wxString& value ) : wxPGProperty(label,name)
1637{
1638 m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1639 m_indFilter = -1;
1640 SetAttribute( wxPG_FILE_WILDCARD, _("All files (*.*)|*.*") );
1641
1642 SetValue(value);
1643}
1644
1645wxFileProperty::~wxFileProperty() {}
1646
1647#if wxUSE_VALIDATORS
1648
1649wxValidator* wxFileProperty::GetClassValidator()
1650{
1651 WX_PG_DOGETVALIDATOR_ENTRY()
1652
1653 // Atleast wxPython 2.6.2.1 required that the string argument is given
1654 static wxString v;
1655 wxTextValidator* validator = new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST,&v);
1656
1657 wxArrayString exChars;
1658 exChars.Add(wxS("?"));
1659 exChars.Add(wxS("*"));
1660 exChars.Add(wxS("|"));
1661 exChars.Add(wxS("<"));
1662 exChars.Add(wxS(">"));
1663 exChars.Add(wxS("\""));
1664
1665 validator->SetExcludes(exChars);
1666
1667 WX_PG_DOGETVALIDATOR_EXIT(validator)
1668}
1669
1670wxValidator* wxFileProperty::DoGetValidator() const
1671{
1672 return GetClassValidator();
1673}
1674
1675#endif
1676
1677void wxFileProperty::OnSetValue()
1678{
1679 const wxString& fnstr = m_value.GetString();
1680
1681 m_filename = fnstr;
1682
1683 if ( !m_filename.HasName() )
1684 {
1685 m_value = wxPGVariant_EmptyString;
1686 m_filename.Clear();
1687 }
1688
1689 // Find index for extension.
1690 if ( m_indFilter < 0 && fnstr.length() )
1691 {
1692 wxString ext = m_filename.GetExt();
1693 int curind = 0;
1694 size_t pos = 0;
1695 size_t len = m_wildcard.length();
1696
1697 pos = m_wildcard.find(wxS("|"), pos);
1698 while ( pos != wxString::npos && pos < (len-3) )
1699 {
1700 size_t ext_begin = pos + 3;
1701
1702 pos = m_wildcard.find(wxS("|"), ext_begin);
1703 if ( pos == wxString::npos )
1704 pos = len;
1705 wxString found_ext = m_wildcard.substr(ext_begin, pos-ext_begin);
1706
1707 if ( found_ext.length() > 0 )
1708 {
1709 if ( found_ext[0] == wxS('*') )
1710 {
1711 m_indFilter = curind;
1712 break;
1713 }
1714 if ( ext.CmpNoCase(found_ext) == 0 )
1715 {
1716 m_indFilter = curind;
1717 break;
1718 }
1719 }
1720
1721 if ( pos != len )
1722 pos = m_wildcard.find(wxS("|"), pos+1);
1723
1724 curind++;
1725 }
1726 }
1727}
1728
1729wxString wxFileProperty::GetValueAsString( int argFlags ) const
1730{
1731 // Always return empty string when name component is empty
1732 wxString fullName = m_filename.GetFullName();
1733 if ( !fullName.length() )
1734 return fullName;
1735
1736 if ( argFlags & wxPG_FULL_VALUE )
1737 {
1738 return m_filename.GetFullPath();
1739 }
1740 else if ( m_flags & wxPG_PROP_SHOW_FULL_FILENAME )
1741 {
1742 if ( m_basePath.Length() )
1743 {
1744 wxFileName fn2(m_filename);
1745 fn2.MakeRelativeTo(m_basePath);
1746 return fn2.GetFullPath();
1747 }
1748 return m_filename.GetFullPath();
1749 }
1750
1751 return m_filename.GetFullName();
1752}
1753
1754wxPGEditorDialogAdapter* wxFileProperty::GetEditorDialog() const
1755{
1756 return new wxPGFileDialogAdapter();
1757}
1758
1759bool wxFileProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
1760{
1761 if ( (m_flags & wxPG_PROP_SHOW_FULL_FILENAME) || (argFlags & wxPG_FULL_VALUE) )
1762 {
1763 if ( m_filename != text )
1764 {
1765 variant = text;
1766 return true;
1767 }
1768 }
1769 else
1770 {
1771 if ( m_filename.GetFullName() != text )
1772 {
1773 wxFileName fn = m_filename;
1774 fn.SetFullName(text);
1775 variant = fn.GetFullPath();
1776 return true;
1777 }
1778 }
1779
1780 return false;
1781}
1782
1783bool wxFileProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1784{
1785 // Return false on some occasions to make sure those attribs will get
1786 // stored in m_attributes.
1787 if ( name == wxPG_FILE_SHOW_FULL_PATH )
1788 {
1789 if ( wxPGVariantToInt(value) )
1790 m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1791 else
1792 m_flags &= ~(wxPG_PROP_SHOW_FULL_FILENAME);
1793 return true;
1794 }
1795 else if ( name == wxPG_FILE_WILDCARD )
1796 {
1797 m_wildcard = value.GetString();
1798 }
1799 else if ( name == wxPG_FILE_SHOW_RELATIVE_PATH )
1800 {
1801 m_basePath = value.GetString();
1802
1803 // Make sure wxPG_FILE_SHOW_FULL_PATH is also set
1804 m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1805 }
1806 else if ( name == wxPG_FILE_INITIAL_PATH )
1807 {
1808 m_initialPath = value.GetString();
1809 return true;
1810 }
1811 else if ( name == wxPG_FILE_DIALOG_TITLE )
1812 {
1813 m_dlgTitle = value.GetString();
1814 return true;
1815 }
1816 return false;
1817}
1818
1819// -----------------------------------------------------------------------
1820// wxPGLongStringDialogAdapter
1821// -----------------------------------------------------------------------
1822
1823bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property )
1824{
1825 wxString val1 = property->GetValueAsString(0);
1826 wxString val_orig = val1;
1827
1828 wxString value;
1829 if ( !property->HasFlag(wxPG_PROP_NO_ESCAPE) )
1830 wxPropertyGrid::ExpandEscapeSequences(value, val1);
1831 else
1832 value = wxString(val1);
1833
1834 // Run editor dialog.
1835 if ( wxLongStringProperty::DisplayEditorDialog(property, propGrid, value) )
1836 {
1837 if ( !property->HasFlag(wxPG_PROP_NO_ESCAPE) )
1838 wxPropertyGrid::CreateEscapeSequences(val1,value);
1839 else
1840 val1 = value;
1841
1842 if ( val1 != val_orig )
1843 {
1844 SetValue( val1 );
1845 return true;
1846 }
1847 }
1848 return false;
1849}
1850
1851// -----------------------------------------------------------------------
1852// wxLongStringProperty
1853// -----------------------------------------------------------------------
1854
1855WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty,wxPGProperty,
1856 wxString,const wxString&,TextCtrlAndButton)
1857
1858wxLongStringProperty::wxLongStringProperty( const wxString& label, const wxString& name,
1859 const wxString& value ) : wxPGProperty(label,name)
1860{
1861 SetValue(value);
1862}
1863
1864wxLongStringProperty::~wxLongStringProperty() {}
1865
1866wxString wxLongStringProperty::GetValueAsString( int ) const
1867{
1868 return m_value;
1869}
1870
1871bool wxLongStringProperty::OnEvent( wxPropertyGrid* propGrid, wxWindow* WXUNUSED(primary),
1872 wxEvent& event )
1873{
1874 if ( propGrid->IsMainButtonEvent(event) )
1875 {
1876 // Update the value
1877 PrepareValueForDialogEditing(propGrid);
1878
1879 wxString val1 = GetValueAsString(0);
1880 wxString val_orig = val1;
1881
1882 wxString value;
1883 if ( !(m_flags & wxPG_PROP_NO_ESCAPE) )
1884 wxPropertyGrid::ExpandEscapeSequences(value,val1);
1885 else
1886 value = wxString(val1);
1887
1888 // Run editor dialog.
1889 if ( OnButtonClick(propGrid,value) )
1890 {
1891 if ( !(m_flags & wxPG_PROP_NO_ESCAPE) )
1892 wxPropertyGrid::CreateEscapeSequences(val1,value);
1893 else
1894 val1 = value;
1895
1896 if ( val1 != val_orig )
1897 {
1898 SetValueInEvent( val1 );
1899 return true;
1900 }
1901 }
1902 }
1903 return false;
1904}
1905
1906bool wxLongStringProperty::OnButtonClick( wxPropertyGrid* propGrid, wxString& value )
1907{
1908 return DisplayEditorDialog(this, propGrid, value);
1909}
1910
1911bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty* prop, wxPropertyGrid* propGrid, wxString& value )
1912
1913{
1914 // launch editor dialog
1915 wxDialog* dlg = new wxDialog(propGrid,-1,prop->GetLabel(),wxDefaultPosition,wxDefaultSize,
1916 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxCLIP_CHILDREN);
1917
1918 dlg->SetFont(propGrid->GetFont()); // To allow entering chars of the same set as the propGrid
1919
1920 // Multi-line text editor dialog.
1921#if !wxPG_SMALL_SCREEN
1922 const int spacing = 8;
1923#else
1924 const int spacing = 4;
1925#endif
1926 wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL );
1927 wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL );
1928 wxTextCtrl* ed = new wxTextCtrl(dlg,11,value,
1929 wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE);
1930
1931 rowsizer->Add( ed, 1, wxEXPAND|wxALL, spacing );
1932 topsizer->Add( rowsizer, 1, wxEXPAND, 0 );
1933 rowsizer = new wxBoxSizer( wxHORIZONTAL );
1934 const int but_sz_flags =
1935 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT;
1936 rowsizer->Add( new wxButton(dlg,wxID_OK,_("Ok")),
1937 0, but_sz_flags, spacing );
1938 rowsizer->Add( new wxButton(dlg,wxID_CANCEL,_("Cancel")),
1939 0, but_sz_flags, spacing );
1940 topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 );
1941
1942 dlg->SetSizer( topsizer );
1943 topsizer->SetSizeHints( dlg );
1944
1945#if !wxPG_SMALL_SCREEN
1946 dlg->SetSize(400,300);
1947
1948 dlg->Move( propGrid->GetGoodEditorDialogPosition(prop,dlg->GetSize()) );
1949#endif
1950
1951 int res = dlg->ShowModal();
1952
1953 if ( res == wxID_OK )
1954 {
1955 value = ed->GetValue();
1956 dlg->Destroy();
1957 return true;
1958 }
1959 dlg->Destroy();
1960 return false;
1961}
1962
1963bool wxLongStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1964{
1965 if ( m_value != text )
1966 {
1967 variant = text;
1968 return true;
1969 }
1970 return false;
1971}
1972
1973// -----------------------------------------------------------------------
1974// wxArrayEditorDialog
1975// -----------------------------------------------------------------------
1976
1977BEGIN_EVENT_TABLE(wxArrayEditorDialog, wxDialog)
1978 EVT_IDLE(wxArrayEditorDialog::OnIdle)
1979 EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick)
1980 EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick)
1981 EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick)
1982 EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick)
1983 EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick)
1984 EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick)
1985 EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick)
1986 //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick)
1987END_EVENT_TABLE()
1988
1989IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog, wxDialog)
1990
1991#include <wx/statline.h>
1992
1993// -----------------------------------------------------------------------
1994
1995void wxArrayEditorDialog::OnIdle(wxIdleEvent& event)
1996{
1997 //
1998 // Do control focus detection here.
1999 //
2000
2001 wxWindow* focused = FindFocus();
2002
2003 // This strange focus thing is a workaround for wxGTK wxListBox focus
2004 // reporting bug.
2005 if ( m_curFocus == 0 && focused != m_edValue &&
2006 focused != m_butAdd && focused != m_butUpdate &&
2007 m_lbStrings->GetSelection() >= 0 )
2008 {
2009 // ListBox was just focused.
2010 m_butAdd->Enable(false);
2011 m_butUpdate->Enable(false);
2012 m_butRemove->Enable(true);
2013 m_butUp->Enable(true);
2014 m_butDown->Enable(true);
2015 m_curFocus = 1;
2016 }
2017 else if ( (m_curFocus == 1 && focused == m_edValue) /*|| m_curFocus == 2*/ )
2018 {
2019 // TextCtrl was just focused.
2020 m_butAdd->Enable(true);
2021 bool upd_enable = false;
2022 if ( m_lbStrings->GetCount() && m_lbStrings->GetSelection() >= 0 )
2023 upd_enable = true;
2024 m_butUpdate->Enable(upd_enable);
2025 m_butRemove->Enable(false);
2026 m_butUp->Enable(false);
2027 m_butDown->Enable(false);
2028 m_curFocus = 0;
2029 }
2030
2031 event.Skip();
2032}
2033
2034// -----------------------------------------------------------------------
2035
2036wxArrayEditorDialog::wxArrayEditorDialog()
2037 : wxDialog()
2038{
2039 Init();
2040}
2041
2042// -----------------------------------------------------------------------
2043
2044void wxArrayEditorDialog::Init()
2045{
2046 m_custBtText = (const wxChar*) NULL;
2047}
2048
2049// -----------------------------------------------------------------------
2050
2051wxArrayEditorDialog::wxArrayEditorDialog( wxWindow *parent,
2052 const wxString& message,
2053 const wxString& caption,
2054 long style,
2055 const wxPoint& pos,
2056 const wxSize& sz )
2057 : wxDialog()
2058{
2059 Init();
2060 Create(parent,message,caption,style,pos,sz);
2061}
2062
2063// -----------------------------------------------------------------------
2064
2065bool wxArrayEditorDialog::Create( wxWindow *parent,
2066 const wxString& message,
2067 const wxString& caption,
2068 long style,
2069 const wxPoint& pos,
2070 const wxSize& sz )
2071{
2072 // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION
2073 // FIXME: This should be only a temporary fix.
2074#ifdef __WXMAC__
2075 int useStyle = wxCAPTION;
2076#else
2077 int useStyle = style;
2078#endif
2079
2080 bool res = wxDialog::Create(parent, wxID_ANY, caption, pos, sz, useStyle);
2081
2082 SetFont(parent->GetFont()); // To allow entering chars of the same set as the propGrid
2083
2084#if !wxPG_SMALL_SCREEN
2085 const int spacing = 4;
2086#else
2087 const int spacing = 3;
2088#endif
2089
2090 m_modified = false;
2091
2092 m_curFocus = 1;
2093
2094 const int but_sz_flags =
2095 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxALL; //wxBOTTOM|wxLEFT|wxRIGHT;
2096
2097 wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL );
2098
2099 // Message
2100 if ( message.length() )
2101 topsizer->Add( new wxStaticText(this,-1,message),
2102 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing );
2103
2104 // String editor
2105 wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL );
2106 m_edValue = new wxTextCtrl(this,21,wxEmptyString,
2107 wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
2108 wxValidator* validator = GetTextCtrlValidator();
2109 if ( validator )
2110 {
2111 m_edValue->SetValidator( *validator );
2112 delete validator;
2113 }
2114 rowsizer->Add( m_edValue,
2115 1, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing );
2116
2117 // Add button
2118 m_butAdd = new wxButton(this,22,_("Add"));
2119 rowsizer->Add( m_butAdd,
2120 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, spacing );
2121 topsizer->Add( rowsizer, 0, wxEXPAND, spacing );
2122
2123 // Separator line
2124 topsizer->Add( new wxStaticLine(this,-1),
2125 0, wxEXPAND|wxBOTTOM|wxLEFT|wxRIGHT, spacing );
2126
2127 rowsizer = new wxBoxSizer( wxHORIZONTAL );
2128
2129 // list box
2130 m_lbStrings = new wxListBox(this, 24, wxDefaultPosition, wxDefaultSize);
2131 unsigned int i;
2132 for ( i=0; i<ArrayGetCount(); i++ )
2133 m_lbStrings->Append( ArrayGet(i) );
2134 rowsizer->Add( m_lbStrings, 1, wxEXPAND|wxRIGHT, spacing );
2135
2136 // Manipulator buttons
2137 wxBoxSizer* colsizer = new wxBoxSizer( wxVERTICAL );
2138 m_butCustom = (wxButton*) NULL;
2139 if ( m_custBtText )
2140 {
2141 m_butCustom = new wxButton(this,28,::wxGetTranslation(m_custBtText));
2142 colsizer->Add( m_butCustom,
2143 0, wxALIGN_CENTER|wxTOP/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/,
2144 spacing );
2145 }
2146 m_butUpdate = new wxButton(this,27,_("Update"));
2147 colsizer->Add( m_butUpdate,
2148 0, wxALIGN_CENTER|wxTOP, spacing );
2149 m_butRemove = new wxButton(this,23,_("Remove"));
2150 colsizer->Add( m_butRemove,
2151 0, wxALIGN_CENTER|wxTOP, spacing );
2152 m_butUp = new wxButton(this,25,_("Up"));
2153 colsizer->Add( m_butUp,
2154 0, wxALIGN_CENTER|wxTOP, spacing );
2155 m_butDown = new wxButton(this,26,_("Down"));
2156 colsizer->Add( m_butDown,
2157 0, wxALIGN_CENTER|wxTOP, spacing );
2158 rowsizer->Add( colsizer, 0, 0, spacing );
2159
2160 topsizer->Add( rowsizer, 1, wxLEFT|wxRIGHT|wxEXPAND, spacing );
2161
2162 // Separator line
2163 topsizer->Add( new wxStaticLine(this,-1),
2164 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, spacing );
2165
2166 // buttons
2167 rowsizer = new wxBoxSizer( wxHORIZONTAL );
2168 /*
2169 const int but_sz_flags =
2170 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT;
2171 */
2172 rowsizer->Add( new wxButton(this,wxID_OK,_("Ok")),
2173 0, but_sz_flags, spacing );
2174 rowsizer->Add( new wxButton(this,wxID_CANCEL,_("Cancel")),
2175 0, but_sz_flags, spacing );
2176 topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 );
2177
2178 m_edValue->SetFocus();
2179
2180 SetSizer( topsizer );
2181 topsizer->SetSizeHints( this );
2182
2183#if !wxPG_SMALL_SCREEN
2184 if ( sz.x == wxDefaultSize.x &&
2185 sz.y == wxDefaultSize.y )
2186 SetSize( wxSize(275,360) );
2187 else
2188 SetSize(sz);
2189#endif
2190
2191 return res;
2192}
2193
2194// -----------------------------------------------------------------------
2195
2196void wxArrayEditorDialog::OnAddClick(wxCommandEvent& )
2197{
2198 wxString text = m_edValue->GetValue();
2199 if ( text.length() )
2200 {
2201 if ( ArrayInsert( text, -1 ) )
2202 {
2203 m_lbStrings->Append( text );
2204 m_modified = true;
2205 m_edValue->Clear();
2206 }
2207 }
2208}
2209
2210// -----------------------------------------------------------------------
2211
2212void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent& )
2213{
2214 int index = m_lbStrings->GetSelection();
2215 if ( index >= 0 )
2216 {
2217 ArrayRemoveAt( index );
2218 m_lbStrings->Delete ( index );
2219 m_modified = true;
2220 }
2221}
2222
2223// -----------------------------------------------------------------------
2224
2225void wxArrayEditorDialog::OnUpClick(wxCommandEvent& )
2226{
2227 int index = m_lbStrings->GetSelection();
2228 if ( index > 0 )
2229 {
2230 ArraySwap(index-1,index);
2231 /*wxString old_str = m_array[index-1];
2232 wxString new_str = m_array[index];
2233 m_array[index-1] = new_str;
2234 m_array[index] = old_str;*/
2235 m_lbStrings->SetString ( index-1, ArrayGet(index-1) );
2236 m_lbStrings->SetString ( index, ArrayGet(index) );
2237 m_lbStrings->SetSelection ( index-1 );
2238 m_modified = true;
2239 }
2240}
2241
2242// -----------------------------------------------------------------------
2243
2244void wxArrayEditorDialog::OnDownClick(wxCommandEvent& )
2245{
2246 int index = m_lbStrings->GetSelection();
2247 int lastStringIndex = ((int) m_lbStrings->GetCount()) - 1;
2248 if ( index >= 0 && index < lastStringIndex )
2249 {
2250 ArraySwap(index,index+1);
2251 /*wxString old_str = m_array[index+1];
2252 wxString new_str = m_array[index];
2253 m_array[index+1] = new_str;
2254 m_array[index] = old_str;*/
2255 m_lbStrings->SetString ( index+1, ArrayGet(index+1) );
2256 m_lbStrings->SetString ( index, ArrayGet(index) );
2257 m_lbStrings->SetSelection ( index+1 );
2258 m_modified = true;
2259 }
2260}
2261
2262// -----------------------------------------------------------------------
2263
2264void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent& )
2265{
2266 int index = m_lbStrings->GetSelection();
2267 if ( index >= 0 )
2268 {
2269 wxString str = m_edValue->GetValue();
2270 if ( ArraySet(index,str) )
2271 {
2272 m_lbStrings->SetString ( index, str );
2273 //m_array[index] = str;
2274 m_modified = true;
2275 }
2276 }
2277}
2278
2279// -----------------------------------------------------------------------
2280
2281void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent& )
2282{
2283 int index = m_lbStrings->GetSelection();
2284 if ( index >= 0 )
2285 {
2286 m_edValue->SetValue( m_lbStrings->GetString(index) );
2287 }
2288}
2289
2290// -----------------------------------------------------------------------
2291// wxPGArrayStringEditorDialog
2292// -----------------------------------------------------------------------
2293
2294IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog, wxArrayEditorDialog)
2295
2296BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog, wxArrayEditorDialog)
2297 EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick)
2298END_EVENT_TABLE()
2299
2300// -----------------------------------------------------------------------
2301
2302wxString wxPGArrayStringEditorDialog::ArrayGet( size_t index )
2303{
2304 return m_array[index];
2305}
2306
2307size_t wxPGArrayStringEditorDialog::ArrayGetCount()
2308{
2309 return m_array.size();
2310}
2311
2312bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString& str, int index )
2313{
2314 if (index<0)
2315 m_array.Add(str);
2316 else
2317 m_array.Insert(str,index);
2318 return true;
2319}
2320
2321bool wxPGArrayStringEditorDialog::ArraySet( size_t index, const wxString& str )
2322{
2323 m_array[index] = str;
2324 return true;
2325}
2326
2327void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index )
2328{
2329 m_array.RemoveAt(index);
2330}
2331
2332void wxPGArrayStringEditorDialog::ArraySwap( size_t first, size_t second )
2333{
2334 wxString old_str = m_array[first];
2335 wxString new_str = m_array[second];
2336 m_array[first] = new_str;
2337 m_array[second] = old_str;
2338}
2339
2340wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog()
2341 : wxArrayEditorDialog()
2342{
2343 Init();
2344}
2345
2346void wxPGArrayStringEditorDialog::Init()
2347{
2348 m_pCallingClass = (wxArrayStringProperty*) NULL;
2349}
2350
2351void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent& )
2352{
2353 wxASSERT( m_pCallingClass );
2354 wxString str = m_edValue->GetValue();
2355 if ( m_pCallingClass->OnCustomStringEdit(m_parent,str) )
2356 {
2357 //m_edValue->SetValue ( str );
2358 m_lbStrings->Append ( str );
2359 m_array.Add ( str );
2360 m_modified = true;
2361 }
2362}
2363
2364// -----------------------------------------------------------------------
2365// wxArrayStringProperty
2366// -----------------------------------------------------------------------
2367
2368WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty, // Property name
2369 wxPGProperty, // Property we inherit from
2370 wxArrayString, // Value type name
2371 const wxArrayString&, // Value type, as given in constructor
2372 TextCtrlAndButton) // Initial editor
2373
2374wxArrayStringProperty::wxArrayStringProperty( const wxString& label,
2375 const wxString& name,
2376 const wxArrayString& array )
2377 : wxPGProperty(label,name)
2378{
2379 SetValue( array );
2380}
2381
2382wxArrayStringProperty::~wxArrayStringProperty() { }
2383
2384void wxArrayStringProperty::OnSetValue()
2385{
2386 GenerateValueAsString();
2387}
2388
2389wxString wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags) ) const
2390{
2391 return m_display;
2392}
2393
2394// Converts wxArrayString to a string separated by delimeters and spaces.
2395// preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash
2396// conversion.
2397void wxPropertyGrid::ArrayStringToString( wxString& dst, const wxArrayString& src,
2398 wxChar preDelim, wxChar postDelim,
2399 int flags )
2400{
2401 wxString pdr;
2402
2403 unsigned int i;
2404 unsigned int itemCount = src.size();
2405
2406 wxChar preas[2];
2407
2408 dst.Empty();
2409
2410 if ( !preDelim )
2411 preas[0] = 0;
2412 else if ( (flags & 1) )
2413 {
2414 preas[0] = preDelim;
2415 preas[1] = 0;
2416 pdr = wxS("\\");
2417 pdr += preDelim;
2418 }
2419
2420 if ( itemCount )
2421 dst.append( preas );
2422
2423 wxASSERT( postDelim );
2424 wxString postDelimStr(postDelim);
2425 //wxString preDelimStr(preDelim);
2426
2427 for ( i = 0; i < itemCount; i++ )
2428 {
2429 wxString str( src.Item(i) );
2430
2431 // Do some character conversion.
2432 // Convertes \ to \\ and <preDelim> to \<preDelim>
2433 // Useful when preDelim and postDelim are "\"".
2434 if ( flags & 1 )
2435 {
2436 str.Replace( wxS("\\"), wxS("\\\\"), true );
2437 if ( pdr.length() )
2438 str.Replace( preas, pdr, true );
2439 }
2440
2441 dst.append( str );
2442
2443 if ( i < (itemCount-1) )
2444 {
2445 dst.append( postDelimStr );
2446 dst.append( wxS(" ") );
2447 dst.append( preas );
2448 }
2449 else if ( preDelim )
2450 dst.append( postDelimStr );
2451 }
2452}
2453
2454#define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \
2455 wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxS('"'),wxS('"'),1);
2456
2457void wxArrayStringProperty::GenerateValueAsString()
2458{
2459 wxArrayString arr = m_value.GetArrayString();
2460 ARRSTRPROP_ARRAY_TO_STRING(m_display, arr)
2461}
2462
2463// Default implementation doesn't do anything.
2464bool wxArrayStringProperty::OnCustomStringEdit( wxWindow*, wxString& )
2465{
2466 return false;
2467}
2468
2469wxArrayEditorDialog* wxArrayStringProperty::CreateEditorDialog()
2470{
2471 return new wxPGArrayStringEditorDialog();
2472}
2473
2474bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid* propGrid,
2475 wxWindow* WXUNUSED(primaryCtrl),
2476 const wxChar* cbt )
2477{
2478 // Update the value
2479 PrepareValueForDialogEditing(propGrid);
2480
2481 if ( !propGrid->EditorValidate() )
2482 return false;
2483
2484 // Create editor dialog.
2485 wxArrayEditorDialog* dlg = CreateEditorDialog();
2486#if wxUSE_VALIDATORS
2487 wxValidator* validator = GetValidator();
2488 wxPGInDialogValidator dialogValidator;
2489#endif
2490
2491 wxPGArrayStringEditorDialog* strEdDlg = wxDynamicCast(dlg, wxPGArrayStringEditorDialog);
2492
2493 if ( strEdDlg )
2494 strEdDlg->SetCustomButton(cbt, this);
2495
2496 dlg->SetDialogValue( wxVariant(m_value) );
2497 dlg->Create(propGrid, wxEmptyString, m_label);
2498
2499#if !wxPG_SMALL_SCREEN
2500 dlg->Move( propGrid->GetGoodEditorDialogPosition(this,dlg->GetSize()) );
2501#endif
2502
2503 bool retVal;
2504
2505 for (;;)
2506 {
2507 retVal = false;
2508
2509 int res = dlg->ShowModal();
2510
2511 if ( res == wxID_OK && dlg->IsModified() )
2512 {
2513 wxVariant value = dlg->GetDialogValue();
2514 if ( !value.IsNull() )
2515 {
2516 wxArrayString actualValue = value.GetArrayString();
2517 wxString tempStr;
2518 ARRSTRPROP_ARRAY_TO_STRING(tempStr, actualValue)
2519 #if wxUSE_VALIDATORS
2520 if ( dialogValidator.DoValidate( propGrid, validator, tempStr ) )
2521 #endif
2522 {
2523 SetValueInEvent( actualValue );
2524 retVal = true;
2525 break;
2526 }
2527 }
2528 else
2529 break;
2530 }
2531 else
2532 break;
2533 }
2534
2535 delete dlg;
2536
2537 return retVal;
2538}
2539
2540bool wxArrayStringProperty::OnEvent( wxPropertyGrid* propGrid,
2541 wxWindow* primary,
2542 wxEvent& event )
2543{
2544 if ( propGrid->IsMainButtonEvent(event) )
2545 return OnButtonClick(propGrid,primary,(const wxChar*) NULL);
2546 return false;
2547}
2548
2549bool wxArrayStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2550{
2551 wxArrayString arr;
2552
2553 WX_PG_TOKENIZER2_BEGIN(text,wxS('"'))
2554
2555 // Need to replace backslashes with empty characters
2556 // (opposite what is done in GenerateValueString).
2557 token.Replace ( wxS("\\"), wxEmptyString, true );
2558
2559 arr.Add( token );
2560
2561 WX_PG_TOKENIZER2_END()
2562
2563 variant = arr;
2564
2565 return true;
2566}
2567
2568// -----------------------------------------------------------------------
2569// wxPGInDialogValidator
2570// -----------------------------------------------------------------------
2571
2572#if wxUSE_VALIDATORS
2573bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* propGrid,
2574 wxValidator* validator,
2575 const wxString& value )
2576{
2577 if ( !validator )
2578 return true;
2579
2580 wxTextCtrl* tc = m_textCtrl;
2581
2582 if ( !tc )
2583 {
2584 {
2585 tc = new wxTextCtrl( propGrid, wxPG_SUBID_TEMP1, wxEmptyString,
2586 wxPoint(30000,30000));
2587 tc->Hide();
2588 }
2589
2590 m_textCtrl = tc;
2591 }
2592
2593 tc->SetValue(value);
2594
2595 validator->SetWindow(tc);
2596 bool res = validator->Validate(propGrid);
2597
2598 return res;
2599}
2600#else
2601bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* WXUNUSED(propGrid),
2602 wxValidator* WXUNUSED(validator),
2603 const wxString& WXUNUSED(value) )
2604{
2605 return true;
2606}
2607#endif
2608
2609// -----------------------------------------------------------------------
2610
f4bc1aa2 2611#endif // wxUSE_PROPGRID