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