~ubuntu-branches/ubuntu/wily/ginkgocadx/wily-proposed

« back to all changes in this revision

Viewing changes to src/cadxcore/wx/propgrid/props.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Tille
  • Date: 2011-05-02 08:09:26 UTC
  • Revision ID: james.westby@ubuntu.com-20110502080926-bql5wep49c7hg91t
Tags: upstream-2.4.1.1
ImportĀ upstreamĀ versionĀ 2.4.1.1

Show diffs side-by-side

added added

removed removed

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