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

« back to all changes in this revision

Viewing changes to src/cadxcore/wx/propgrid/editors.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:        editors.cpp
 
3
// Purpose:     wxPropertyGrid editors
 
4
// Author:      Jaakko Salli
 
5
// Modified by:
 
6
// Created:     Apr-14-2007
 
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/layout.h"
 
43
    #include "wx/sizer.h"
 
44
    #include "wx/textdlg.h"
 
45
    #include "wx/filedlg.h"
 
46
    #include "wx/statusbr.h"
 
47
    #include "wx/intl.h"
 
48
    #include "wx/frame.h"
 
49
#endif
 
50
 
 
51
 
 
52
#include "wx/timer.h"
 
53
#include "wx/dcbuffer.h"
 
54
#include "wx/bmpbuttn.h"
 
55
 
 
56
 
 
57
// This define is necessary to prevent macro clearing
 
58
#define __wxPG_SOURCE_FILE__
 
59
 
 
60
#include <wx/propgrid/propgrid.h>
 
61
#include <wx/propgrid/propdev.h>
 
62
#include <wx/propgrid/editors.h>
 
63
#include <wx/propgrid/props.h>
 
64
 
 
65
#ifdef __WXPYTHON__
 
66
    #include <wx/propgrid/advprops.h>
 
67
    #include <wx/propgrid/extras.h>
 
68
#endif
 
69
 
 
70
#if wxPG_USE_RENDERER_NATIVE
 
71
    #include <wx/renderer.h>
 
72
#endif
 
73
 
 
74
// How many pixels between textctrl and button
 
75
#ifdef __WXMAC__
 
76
    // Backported from wx2.9 by Julian Smart (old value was 8)
 
77
    #define wxPG_TEXTCTRL_AND_BUTTON_SPACING        4
 
78
#else
 
79
    #define wxPG_TEXTCTRL_AND_BUTTON_SPACING        2
 
80
#endif 
 
81
 
 
82
#define wxPG_BUTTON_SIZEDEC                         0
 
83
 
 
84
#if wxPG_USING_WXOWNERDRAWNCOMBOBOX
 
85
    #include <wx/odcombo.h>
 
86
#else
 
87
    #include <wx/propgrid/odcombo.h>
 
88
#endif
 
89
 
 
90
#ifdef __WXMSW__
 
91
    #include <wx/msw/private.h>
 
92
#endif
 
93
 
 
94
// -----------------------------------------------------------------------
 
95
 
 
96
#if defined(__WXMSW__)
 
97
    // tested
 
98
    #define wxPG_NAT_TEXTCTRL_BORDER_X          0 // Unremovable border of native textctrl.
 
99
    #define wxPG_NAT_TEXTCTRL_BORDER_Y          0 // Unremovable border of native textctrl.
 
100
 
 
101
    #define wxPG_NAT_BUTTON_BORDER_ANY          1
 
102
    #define wxPG_NAT_BUTTON_BORDER_X            1
 
103
    #define wxPG_NAT_BUTTON_BORDER_Y            1
 
104
 
 
105
    #define wxPG_CHECKMARK_XADJ                 1
 
106
    #define wxPG_CHECKMARK_YADJ                 (-1)
 
107
    #define wxPG_CHECKMARK_WADJ                 0
 
108
    #define wxPG_CHECKMARK_HADJ                 0
 
109
    #define wxPG_CHECKMARK_DEFLATE              0
 
110
 
 
111
    #define wxPG_TEXTCTRLYADJUST                (m_spacingy+0)
 
112
 
 
113
#elif defined(__WXGTK__)
 
114
    // tested
 
115
    #define wxPG_CHECKMARK_XADJ                 0
 
116
    #define wxPG_CHECKMARK_YADJ                 0
 
117
    #define wxPG_CHECKMARK_WADJ                 (-1)
 
118
    #define wxPG_CHECKMARK_HADJ                 (-1)
 
119
    #define wxPG_CHECKMARK_DEFLATE              3
 
120
 
 
121
    #define wxPG_NAT_TEXTCTRL_BORDER_X      3 // Unremovable border of native textctrl.
 
122
    #define wxPG_NAT_TEXTCTRL_BORDER_Y      3 // Unremovable border of native textctrl.
 
123
 
 
124
    #define wxPG_NAT_BUTTON_BORDER_ANY      1
 
125
    #define wxPG_NAT_BUTTON_BORDER_X        1
 
126
    #define wxPG_NAT_BUTTON_BORDER_Y        1
 
127
 
 
128
    #define wxPG_TEXTCTRLYADJUST            0
 
129
 
 
130
#elif defined(__WXMAC__)
 
131
    // *not* tested
 
132
    #define wxPG_CHECKMARK_XADJ                 0
 
133
    #define wxPG_CHECKMARK_YADJ                 0
 
134
    #define wxPG_CHECKMARK_WADJ                 0
 
135
    #define wxPG_CHECKMARK_HADJ                 0
 
136
    #define wxPG_CHECKMARK_DEFLATE              0
 
137
 
 
138
    #define wxPG_NAT_TEXTCTRL_BORDER_X      0 // Unremovable border of native textctrl.
 
139
    #define wxPG_NAT_TEXTCTRL_BORDER_Y      0 // Unremovable border of native textctrl.
 
140
 
 
141
    #define wxPG_NAT_BUTTON_BORDER_ANY      0
 
142
    #define wxPG_NAT_BUTTON_BORDER_X        0
 
143
    #define wxPG_NAT_BUTTON_BORDER_Y        0
 
144
 
 
145
    // Backported from wx2.9 by Julian Smart (old value was 3)
 
146
    #define wxPG_TEXTCTRLYADJUST            0
 
147
 
 
148
#else
 
149
    // defaults
 
150
    #define wxPG_CHECKMARK_XADJ                 0
 
151
    #define wxPG_CHECKMARK_YADJ                 0
 
152
    #define wxPG_CHECKMARK_WADJ                 0
 
153
    #define wxPG_CHECKMARK_HADJ                 0
 
154
    #define wxPG_CHECKMARK_DEFLATE              0
 
155
 
 
156
    #define wxPG_NAT_TEXTCTRL_BORDER_X      0 // Unremovable border of native textctrl.
 
157
    #define wxPG_NAT_TEXTCTRL_BORDER_Y      0 // Unremovable border of native textctrl.
 
158
 
 
159
    #define wxPG_NAT_BUTTON_BORDER_ANY      0
 
160
    #define wxPG_NAT_BUTTON_BORDER_X        0
 
161
    #define wxPG_NAT_BUTTON_BORDER_Y        0
 
162
 
 
163
    #define wxPG_TEXTCTRLYADJUST            0
 
164
 
 
165
#endif
 
166
 
 
167
#if (!wxPG_NAT_TEXTCTRL_BORDER_X && !wxPG_NAT_TEXTCTRL_BORDER_Y)
 
168
    #define wxPG_ENABLE_CLIPPER_WINDOW      0
 
169
#else
 
170
    #define wxPG_ENABLE_CLIPPER_WINDOW      1
 
171
#endif
 
172
 
 
173
 
 
174
// for odcombo
 
175
#ifdef __WXMAC__
 
176
    // Backported from wx2.9 by Julian Smart
 
177
    // required because wxComboCtrl reserves 3pixels for wxTextCtrl's
 
178
    // focus ring.
 
179
    #define wxPG_CHOICEXADJUST           -3
 
180
    #define wxPG_CHOICEYADJUST           -3
 
181
#else
 
182
    #define wxPG_CHOICEXADJUST           0
 
183
    #define wxPG_CHOICEYADJUST           0
 
184
#endif
 
185
 
 
186
//
 
187
// Number added to image width for SetCustomPaintWidth
 
188
// NOTE: Use different custom paint margin because of better textctrl spacing
 
189
#define ODCB_CUST_PAINT_MARGIN_RO            6
 
190
#define ODCB_CUST_PAINT_MARGIN               8
 
191
 
 
192
// Milliseconds to wait for two mouse-ups after focus inorder
 
193
// to trigger a double-click.
 
194
#define DOUBLE_CLICK_CONVERSION_TRESHOLD        500
 
195
 
 
196
// -----------------------------------------------------------------------
 
197
// wxPGEditor
 
198
// -----------------------------------------------------------------------
 
199
 
 
200
IMPLEMENT_ABSTRACT_CLASS(wxPGEditor, wxObject)
 
201
 
 
202
wxPGEditor::~wxPGEditor()
 
203
{
 
204
}
 
205
 
 
206
 
 
207
/*wxPGCellRenderer* wxPGEditor::GetCellRenderer() const
 
208
{
 
209
    return &g_wxPGDefaultRenderer;
 
210
}*/
 
211
 
 
212
void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const
 
213
{
 
214
    if ( !property->IsValueUnspecified() )
 
215
        dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y );
 
216
}
 
217
 
 
218
#ifdef __WXPYTHON__
 
219
bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const
 
220
{
 
221
    return false;
 
222
}
 
223
 
 
224
wxPGVariantAndBool wxPGEditor::PyGetValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const
 
225
{
 
226
    wxPGVariantAndBool vab;
 
227
    vab.m_result = GetValueFromControl(vab.m_value, property, ctrl);
 
228
    if ( vab.m_result )
 
229
        vab.m_valueValid = true;
 
230
    return vab;
 
231
}
 
232
#endif
 
233
 
 
234
void wxPGEditor::SetControlStringValue( wxPGProperty* WXUNUSED(property), wxWindow*, const wxString& ) const
 
235
{
 
236
}
 
237
 
 
238
 
 
239
void wxPGEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxWindow*, int ) const
 
240
{
 
241
}
 
242
 
 
243
 
 
244
int wxPGEditor::InsertItem( wxWindow*, const wxString&, int ) const
 
245
{
 
246
    return -1;
 
247
}
 
248
 
 
249
 
 
250
void wxPGEditor::DeleteItem( wxWindow*, int ) const
 
251
{
 
252
    return;
 
253
}
 
254
 
 
255
 
 
256
void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const
 
257
{
 
258
}
 
259
 
 
260
 
 
261
bool wxPGEditor::CanContainCustomImage() const
 
262
{
 
263
    return false;
 
264
}
 
265
 
 
266
// -----------------------------------------------------------------------
 
267
// wxPGClipperWindow
 
268
// -----------------------------------------------------------------------
 
269
 
 
270
#if wxPG_ENABLE_CLIPPER_WINDOW
 
271
 
 
272
//
 
273
// Clipper window is used to "remove" borders from controls
 
274
// which otherwise insist on having them despite of supplied
 
275
// wxNO_BORDER window style.
 
276
//
 
277
class wxPGClipperWindow : public wxWindow
 
278
{
 
279
    DECLARE_CLASS(wxPGClipperWindow)
 
280
public:
 
281
 
 
282
    wxPGClipperWindow()
 
283
        : wxWindow()
 
284
    {
 
285
        wxPGClipperWindow::Init();
 
286
    }
 
287
 
 
288
    wxPGClipperWindow(wxWindow* parent,
 
289
                      wxWindowID id,
 
290
                      const wxPoint& pos = wxDefaultPosition,
 
291
                      const wxSize& size = wxDefaultSize)
 
292
    {
 
293
        Init();
 
294
        Create(parent,id,pos,size);
 
295
    }
 
296
 
 
297
    void Create(wxWindow* parent,
 
298
                wxWindowID id,
 
299
                const wxPoint& pos = wxDefaultPosition,
 
300
                const wxSize& size = wxDefaultSize);
 
301
 
 
302
    virtual ~wxPGClipperWindow();
 
303
 
 
304
    virtual bool ProcessEvent(wxEvent& event);
 
305
 
 
306
    inline wxWindow* GetControl() const { return m_ctrl; }
 
307
 
 
308
    // This is called before wxControl is constructed.
 
309
    void GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz );
 
310
 
 
311
    // This is caleed after wxControl has been constructed.
 
312
    void SetControl( wxWindow* ctrl );
 
313
 
 
314
    virtual void Refresh( bool eraseBackground = true,
 
315
                          const wxRect *rect = (const wxRect *) NULL );
 
316
    virtual void SetFocus();
 
317
 
 
318
    virtual bool SetFont(const wxFont& font);
 
319
 
 
320
    virtual bool SetForegroundColour(const wxColour& col)
 
321
    {
 
322
        bool res = wxWindow::SetForegroundColour(col);
 
323
        if ( m_ctrl )
 
324
            m_ctrl->SetForegroundColour(col);
 
325
        return res;
 
326
    }
 
327
 
 
328
    virtual bool SetBackgroundColour(const wxColour& col)
 
329
    {
 
330
        bool res = wxWindow::SetBackgroundColour(col);
 
331
        if ( m_ctrl )
 
332
            m_ctrl->SetBackgroundColour(col);
 
333
        return res;
 
334
    }
 
335
 
 
336
    inline int GetXClip() const { return m_xadj; }
 
337
 
 
338
    inline int GetYClip() const { return m_yadj; }
 
339
 
 
340
protected:
 
341
    wxWindow*       m_ctrl;
 
342
 
 
343
    int             m_xadj; // Horizontal border clip.
 
344
 
 
345
    int             m_yadj; // Vertical border clip.
 
346
 
 
347
private:
 
348
    void Init ()
 
349
    {
 
350
        m_ctrl = (wxWindow*) NULL;
 
351
    }
 
352
};
 
353
 
 
354
 
 
355
IMPLEMENT_CLASS(wxPGClipperWindow,wxWindow)
 
356
 
 
357
 
 
358
// This is called before wxControl is constructed.
 
359
void wxPGClipperWindow::GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz )
 
360
{
 
361
    m_xadj = xadj;
 
362
    m_yadj = yadj;
 
363
    pt.x = -xadj;
 
364
    pt.y = -yadj;
 
365
    wxSize own_size = GetSize();
 
366
    sz.x = own_size.x+(xadj*2);
 
367
    sz.y = own_size.y+(yadj*2);
 
368
}
 
369
 
 
370
 
 
371
// This is caleed after wxControl has been constructed.
 
372
void wxPGClipperWindow::SetControl( wxWindow* ctrl )
 
373
{
 
374
    m_ctrl = ctrl;
 
375
 
 
376
    // GTK requires this.
 
377
    ctrl->SetSizeHints(3,3);
 
378
 
 
379
    // Correct size of this window to match the child.
 
380
    wxSize sz = GetSize();
 
381
    wxSize chsz = ctrl->GetSize();
 
382
 
 
383
    int hei_adj = chsz.y - (sz.y+(m_yadj*2));
 
384
    if ( hei_adj )
 
385
        SetSize(sz.x,chsz.y-(m_yadj*2));
 
386
 
 
387
}
 
388
 
 
389
 
 
390
void wxPGClipperWindow::Refresh( bool eraseBackground, const wxRect *rect )
 
391
{
 
392
    wxWindow::Refresh(false,rect);
 
393
    if ( m_ctrl )
 
394
        m_ctrl->Refresh(eraseBackground);
 
395
}
 
396
 
 
397
 
 
398
// Pass focus to control
 
399
void wxPGClipperWindow::SetFocus()
 
400
{
 
401
    if ( m_ctrl )
 
402
        m_ctrl->SetFocus();
 
403
    else
 
404
        wxWindow::SetFocus();
 
405
}
 
406
 
 
407
 
 
408
bool wxPGClipperWindow::SetFont(const wxFont& font)
 
409
{
 
410
    bool res = wxWindow::SetFont(font);
 
411
    if ( m_ctrl )
 
412
        return m_ctrl->SetFont(font);
 
413
    return res;
 
414
}
 
415
 
 
416
 
 
417
void wxPGClipperWindow::Create(wxWindow* parent,
 
418
                               wxWindowID id,
 
419
                               const wxPoint& pos,
 
420
                               const wxSize& size )
 
421
{
 
422
    wxWindow::Create(parent,id,pos,size);
 
423
}
 
424
 
 
425
 
 
426
wxPGClipperWindow::~wxPGClipperWindow()
 
427
{
 
428
}
 
429
 
 
430
 
 
431
bool wxPGClipperWindow::ProcessEvent(wxEvent& event)
 
432
{
 
433
    if ( event.GetEventType() == wxEVT_SIZE )
 
434
    {
 
435
        if ( m_ctrl )
 
436
        {
 
437
            // Maintain correct size relationship.
 
438
            wxSize sz = GetSize();
 
439
            m_ctrl->SetSize(sz.x+(m_xadj*2),sz.y+(m_yadj*2));
 
440
            event.Skip();
 
441
            return false;
 
442
        }
 
443
    }
 
444
    return wxWindow::ProcessEvent(event);
 
445
}
 
446
 
 
447
#endif // wxPG_ENABLE_CLIPPER_WINDOW
 
448
 
 
449
/*wxWindow* wxPropertyGrid::GetActualEditorControl( wxWindow* ctrl )
 
450
{
 
451
#if wxPG_ENABLE_CLIPPER_WINDOW
 
452
    // Pass real control instead of clipper window
 
453
    if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) )
 
454
    {
 
455
        return ((wxPGClipperWindow*)ctrl)->GetControl();
 
456
    }
 
457
#else
 
458
    return ctrl;
 
459
#endif
 
460
}*/
 
461
 
 
462
// -----------------------------------------------------------------------
 
463
// wxPGTextCtrlEditor
 
464
// -----------------------------------------------------------------------
 
465
 
 
466
// Clipper window support macro (depending on whether it is used
 
467
// for this editor or not)
 
468
#if wxPG_NAT_TEXTCTRL_BORDER_X || wxPG_NAT_TEXTCTRL_BORDER_Y
 
469
    #define wxPG_NAT_TEXTCTRL_BORDER_ANY    1
 
470
#else
 
471
    #define wxPG_NAT_TEXTCTRL_BORDER_ANY    0
 
472
#endif
 
473
 
 
474
 
 
475
WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor)
 
476
 
 
477
 
 
478
wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid,
 
479
                                                   wxPGProperty* property,
 
480
                                                   const wxPoint& pos,
 
481
                                                   const wxSize& sz ) const
 
482
{
 
483
    wxString text;
 
484
 
 
485
    //
 
486
    // If has children, and limited editing is specified, then don't create.
 
487
    if ( (property->GetFlags() & wxPG_PROP_NOEDITOR) &&
 
488
         property->GetChildCount() )
 
489
        return (wxWindow*) NULL;
 
490
 
 
491
    if ( !property->IsValueUnspecified() )
 
492
    {
 
493
        int flags = property->HasFlag(wxPG_PROP_READONLY) ? 
 
494
            0 : wxPG_EDITABLE_VALUE;
 
495
        text = property->GetValueString(flags);
 
496
    }
 
497
    else
 
498
    {
 
499
        text = propGrid->GetUnspecifiedValueText();
 
500
    }
 
501
 
 
502
    int flags = 0;
 
503
    if ( (property->GetFlags() & wxPG_PROP_PASSWORD) &&
 
504
         property->IsKindOf(WX_PG_CLASSINFO(wxStringProperty)) )
 
505
        flags |= wxTE_PASSWORD;
 
506
 
 
507
    wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,(wxWindow*)NULL,flags,
 
508
                                                     property->GetMaxLength());
 
509
 
 
510
    return wnd;
 
511
}
 
512
 
 
513
#if 0
 
514
void wxPGTextCtrlEditor::DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const
 
515
{
 
516
    if ( !property->IsValueUnspecified() )
 
517
    {
 
518
        wxString drawStr = property->GetDisplayedString();
 
519
 
 
520
        // Code below should no longer be needed, as the obfuscation
 
521
        // is now done in GetValueAsString.
 
522
        /*if ( (property->GetFlags() & wxPG_PROP_PASSWORD) &&
 
523
             property->IsKindOf(WX_PG_CLASSINFO(wxStringProperty)) )
 
524
        {
 
525
            size_t a = drawStr.length();
 
526
            drawStr.Empty();
 
527
            drawStr.Append(wxT('*'),a);
 
528
        }*/
 
529
        dc.DrawText( drawStr, rect.x+wxPG_XBEFORETEXT, rect.y );
 
530
    }
 
531
}
 
532
#endif
 
533
 
 
534
void wxPGTextCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 
535
{
 
536
    wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 
537
 
 
538
    wxString s;
 
539
 
 
540
    if ( tc->HasFlag(wxTE_PASSWORD) )
 
541
        s = property->GetValueAsString(wxPG_FULL_VALUE);
 
542
    else
 
543
        s = property->GetDisplayedString();
 
544
 
 
545
    wxPropertyGrid* pg = property->GetGrid();
 
546
 
 
547
    pg->SetupTextCtrlValue(s);
 
548
    tc->SetValue(s);    
 
549
 
 
550
    // Must always fix indentation, just in case
 
551
#if defined(__WXMSW__) && !defined(__WXWINCE__)
 
552
        ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
 
553
#endif
 
554
}
 
555
 
 
556
 
 
557
// Provided so that, for example, ComboBox editor can use the same code
 
558
// (multiple inheritance would get way too messy).
 
559
bool wxPGTextCtrlEditor::OnTextCtrlEvent( wxPropertyGrid* propGrid,
 
560
                                          wxPGProperty* WXUNUSED(property),
 
561
                                          wxWindow* ctrl,
 
562
                                          wxEvent& event )
 
563
{
 
564
    if ( !ctrl )
 
565
        return false;
 
566
 
 
567
    if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
 
568
    {
 
569
        if ( propGrid->IsEditorsValueModified() )
 
570
        {
 
571
            return true;
 
572
        }
 
573
    }
 
574
    else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED )
 
575
    {
 
576
        //
 
577
        // Pass this event outside wxPropertyGrid so that,
 
578
        // if necessary, program can tell when user is editing
 
579
        // a textctrl.
 
580
        // FIXME: Is it safe to change event id in the middle of event
 
581
        //        processing (seems to work, but...)?
 
582
        event.Skip();
 
583
        event.SetId(propGrid->GetId());
 
584
 
 
585
        propGrid->EditorsValueWasModified();
 
586
    }
 
587
    return false;
 
588
}
 
589
 
 
590
 
 
591
bool wxPGTextCtrlEditor::OnEvent( wxPropertyGrid* propGrid,
 
592
                                  wxPGProperty* property,
 
593
                                  wxWindow* ctrl,
 
594
                                  wxEvent& event ) const
 
595
{
 
596
    return wxPGTextCtrlEditor::OnTextCtrlEvent(propGrid,property,ctrl,event);
 
597
}
 
598
 
 
599
 
 
600
bool wxPGTextCtrlEditor::GetTextCtrlValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl )
 
601
{
 
602
    wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 
603
    wxString textVal = tc->GetValue();
 
604
 
 
605
    if ( property->UsesAutoUnspecified() && !textVal.length() )
 
606
    {
 
607
        variant.MakeNull();
 
608
        return true;
 
609
    }
 
610
 
 
611
    bool res = property->ActualStringToValue(variant, textVal, wxPG_EDITABLE_VALUE);
 
612
 
 
613
    // Changing unspecified always causes event (returning
 
614
    // true here should be enough to trigger it).
 
615
    // TODO: Move to propgrid.cpp
 
616
    if ( !res && variant.IsNull() )
 
617
        res = true;
 
618
 
 
619
    return res;
 
620
}
 
621
 
 
622
 
 
623
bool wxPGTextCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const
 
624
{
 
625
    return wxPGTextCtrlEditor::GetTextCtrlValueFromControl(variant, property, ctrl);
 
626
}
 
627
 
 
628
 
 
629
void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const
 
630
{
 
631
    wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 
632
 
 
633
    wxPropertyGrid* pg = property->GetGrid();
 
634
    wxASSERT(pg);  // Really, property grid should exist if editor does
 
635
    if ( pg )
 
636
    {
 
637
        wxString tcText = pg->GetUnspecifiedValueText();
 
638
        pg->SetupTextCtrlValue(tcText);
 
639
        tc->SetValue(tcText);
 
640
    }
 
641
}
 
642
 
 
643
 
 
644
void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const
 
645
{
 
646
    wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl);
 
647
 
 
648
    wxPropertyGrid* pg = property->GetGrid();
 
649
    wxASSERT(pg);  // Really, property grid should exist if editor does
 
650
    if ( pg )
 
651
        tc->SetValue(txt);
 
652
}
 
653
 
 
654
void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property,
 
655
                                 wxTextCtrl*tc )
 
656
{
 
657
    // Make sure there is correct text (instead of unspecified value
 
658
    // indicator or inline help)
 
659
    int flags = property->HasFlag(wxPG_PROP_READONLY) ? 
 
660
        0 : wxPG_EDITABLE_VALUE;
 
661
    wxString correctText = property->GetValueString(flags);
 
662
 
 
663
    if ( tc->GetValue() != correctText )
 
664
    {
 
665
        property->GetGrid()->SetupTextCtrlValue(correctText);
 
666
        tc->SetValue(correctText);
 
667
    }
 
668
 
 
669
    tc->SetSelection(-1,-1);
 
670
}
 
671
 
 
672
void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property,
 
673
                                  wxWindow* wnd ) const
 
674
{
 
675
    wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl);
 
676
    wxPGTextCtrlEditor_OnFocus(property, tc);
 
677
}
 
678
 
 
679
 
 
680
wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { }
 
681
 
 
682
 
 
683
// -----------------------------------------------------------------------
 
684
// wxPGChoiceEditor
 
685
// -----------------------------------------------------------------------
 
686
 
 
687
 
 
688
WX_PG_IMPLEMENT_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor)
 
689
 
 
690
 
 
691
// This is a special enhanced double-click processor class.
 
692
// In essence, it allows for double-clicks for which the
 
693
// first click "created" the control.
 
694
class wxPGDoubleClickProcessor : public wxEvtHandler
 
695
{
 
696
public:
 
697
 
 
698
    wxPGDoubleClickProcessor( wxPGOwnerDrawnComboBox* combo )
 
699
        : wxEvtHandler()
 
700
    {
 
701
        m_timeLastMouseUp = 0;
 
702
        m_combo = combo;
 
703
        m_downReceived = false;
 
704
    }
 
705
 
 
706
protected:
 
707
 
 
708
    void OnMouseEvent( wxMouseEvent& event )
 
709
    {
 
710
        wxLongLong t = ::wxGetLocalTimeMillis();
 
711
        int evtType = event.GetEventType();
 
712
 
 
713
        if ( m_combo->HasFlag(wxPGCC_DCLICK_CYCLES) &&
 
714
             !m_combo->IsPopupShown() )
 
715
        {
 
716
            // Just check that it is in the text area
 
717
            wxPoint pt = event.GetPosition();
 
718
            if ( m_combo->GetTextRect().wxPGRectContains(pt) )
 
719
            {
 
720
                if ( evtType == wxEVT_LEFT_DOWN )
 
721
                {
 
722
                    // Set value to avoid up-events without corresponding downs
 
723
                    m_downReceived = true;
 
724
                }
 
725
                else if ( evtType == wxEVT_LEFT_DCLICK )
 
726
                {
 
727
                    // We'll make our own double-clicks
 
728
                    event.SetEventType(0);
 
729
                    return;
 
730
                }
 
731
                else if ( evtType == wxEVT_LEFT_UP )
 
732
                {
 
733
                    if ( m_downReceived || m_timeLastMouseUp == 1 )
 
734
                    {
 
735
                        wxLongLong timeFromLastUp = (t-m_timeLastMouseUp);
 
736
 
 
737
                        if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD )
 
738
                        {
 
739
                            event.SetEventType(wxEVT_LEFT_DCLICK);
 
740
                            m_timeLastMouseUp = 1;
 
741
                        }
 
742
                        else
 
743
                        {
 
744
                            m_timeLastMouseUp = t;
 
745
                        }
 
746
                    }
 
747
                }
 
748
            }
 
749
        }
 
750
 
 
751
        event.Skip();
 
752
    }
 
753
 
 
754
    void OnSetFocus( wxFocusEvent& event )
 
755
    {
 
756
        m_timeLastMouseUp = ::wxGetLocalTimeMillis();
 
757
        event.Skip();
 
758
    }
 
759
 
 
760
private:
 
761
    wxLongLong                  m_timeLastMouseUp;
 
762
    wxPGOwnerDrawnComboBox*     m_combo;
 
763
    bool                        m_downReceived;
 
764
 
 
765
    DECLARE_EVENT_TABLE()
 
766
};
 
767
 
 
768
BEGIN_EVENT_TABLE(wxPGDoubleClickProcessor, wxEvtHandler)
 
769
    EVT_MOUSE_EVENTS(wxPGDoubleClickProcessor::OnMouseEvent)
 
770
    EVT_SET_FOCUS(wxPGDoubleClickProcessor::OnSetFocus)
 
771
END_EVENT_TABLE()
 
772
 
 
773
 
 
774
 
 
775
class wxPGComboBox : public wxPGOwnerDrawnComboBox
 
776
{
 
777
public:
 
778
 
 
779
    wxPGComboBox()
 
780
        : wxPGOwnerDrawnComboBox()
 
781
    {
 
782
        m_dclickProcessor = (wxPGDoubleClickProcessor*) NULL;
 
783
        m_sizeEventCalled = false;
 
784
    }
 
785
 
 
786
    ~wxPGComboBox()
 
787
    {
 
788
        if ( m_dclickProcessor )
 
789
        {
 
790
            RemoveEventHandler(m_dclickProcessor);
 
791
            delete m_dclickProcessor;
 
792
        }
 
793
    }
 
794
 
 
795
    bool Create(wxWindow *parent,
 
796
                wxWindowID id,
 
797
                const wxString& value,
 
798
                const wxPoint& pos,
 
799
                const wxSize& size,
 
800
                const wxArrayString& choices,
 
801
                long style = 0,
 
802
                const wxValidator& validator = wxDefaultValidator,
 
803
                const wxString& name = wxT("wxOwnerDrawnComboBox"))
 
804
    {
 
805
        if ( !wxPGOwnerDrawnComboBox::Create( parent,
 
806
                                              id,
 
807
                                              value,
 
808
                                              pos,
 
809
                                              size,
 
810
                                              choices,
 
811
                                              style,
 
812
                                              validator,
 
813
                                              name ) )
 
814
            return false;
 
815
 
 
816
        m_dclickProcessor = new wxPGDoubleClickProcessor(this);
 
817
 
 
818
        PushEventHandler(m_dclickProcessor);
 
819
 
 
820
        return true;
 
821
    }
 
822
 
 
823
#if wxPG_USING_WXOWNERDRAWNCOMBOBOX
 
824
    virtual void OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const
 
825
#else
 
826
    virtual bool OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const
 
827
#endif
 
828
    {
 
829
        wxPropertyGrid* pg = GetGrid();
 
830
        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,dc,(wxRect&)rect,flags);
 
831
#if !wxPG_USING_WXOWNERDRAWNCOMBOBOX
 
832
        return true;
 
833
#endif    
 
834
    }
 
835
    virtual wxCoord OnMeasureItem( size_t item ) const
 
836
    {
 
837
        wxPropertyGrid* pg = GetGrid();
 
838
        wxRect rect;
 
839
        rect.x = -1;
 
840
        rect.width = 0;
 
841
        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0);
 
842
        return rect.height;
 
843
    }
 
844
 
 
845
    wxPropertyGrid* GetGrid() const
 
846
    {
 
847
        wxPropertyGrid* pg = wxDynamicCast(GetParent()->GetParent(),wxPropertyGrid);
 
848
        wxASSERT(pg);
 
849
        return pg;
 
850
    }
 
851
 
 
852
    virtual wxCoord OnMeasureItemWidth( size_t item ) const
 
853
    {
 
854
        wxPropertyGrid* pg = GetGrid();
 
855
        wxRect rect;
 
856
        rect.x = -1;
 
857
        rect.width = -1;
 
858
        pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0);
 
859
        return rect.width;
 
860
    }
 
861
 
 
862
    virtual void PositionTextCtrl( int WXUNUSED(textCtrlXAdjust), int WXUNUSED(textCtrlYAdjust) )
 
863
    {
 
864
        wxPropertyGrid* pg = GetGrid();
 
865
        wxPGOwnerDrawnComboBox::PositionTextCtrl(
 
866
            wxPG_TEXTCTRLXADJUST - (wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1) - 1,
 
867
            pg->GetSpacingY() + 2
 
868
        );
 
869
    }
 
870
 
 
871
private:
 
872
    wxPGDoubleClickProcessor*   m_dclickProcessor;
 
873
    bool                        m_sizeEventCalled;
 
874
};
 
875
 
 
876
 
 
877
void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc,
 
878
                                       int item,
 
879
                                       wxDC& dc,
 
880
                                       wxRect& rect,
 
881
                                       int flags )
 
882
{
 
883
    wxPGComboBox* pCb = (wxPGComboBox*)pCc;
 
884
 
 
885
    // Sanity check
 
886
    wxASSERT( IsKindOf(CLASSINFO(wxPropertyGrid)) );
 
887
 
 
888
    wxPGProperty* p = GetSelection();
 
889
    wxString text;
 
890
 
 
891
    const wxPGChoices* pChoices = &p->GetChoices();
 
892
    const wxPGCommonValue* comVal = NULL;
 
893
    int choiceCount = p->GetChoiceCount();
 
894
    int comVals = p->GetDisplayedCommonValueCount();
 
895
    int comValIndex = -1;
 
896
    if ( item >= choiceCount && comVals > 0 )
 
897
    {
 
898
        comValIndex = item - choiceCount;
 
899
        comVal = GetCommonValue(comValIndex);
 
900
        if ( !p->IsValueUnspecified() )
 
901
            text = comVal->GetLabel();
 
902
    }
 
903
    else
 
904
    {
 
905
        if ( !(flags & wxPGCC_PAINTING_CONTROL) )
 
906
        {
 
907
            text = pCb->GetString(item);
 
908
        }
 
909
        else
 
910
        {
 
911
            if ( !p->IsValueUnspecified() )
 
912
                text = p->GetValueString(0);
 
913
        }
 
914
    }
 
915
 
 
916
    if ( item < 0 )
 
917
        return;
 
918
 
 
919
#if !wxPG_USING_WXOWNERDRAWNCOMBOBOX
 
920
    // Add wxPGCC_PAINTING_SELECTED
 
921
    if ( !(flags & wxPGCC_PAINTING_CONTROL) &&
 
922
         wxDynamicCast(pCb->GetPopup()->GetControl(),wxVListBox)->GetSelection() == item )
 
923
         flags |= wxPGCC_PAINTING_SELECTED;
 
924
#endif
 
925
 
 
926
    wxSize cis;
 
927
 
 
928
    const wxBitmap* itemBitmap = NULL;
 
929
 
 
930
    if ( item >= 0 && pChoices && pChoices->Item(item).GetBitmap().Ok() && comValIndex == -1 )
 
931
        itemBitmap = &pChoices->Item(item).GetBitmap();
 
932
 
 
933
    //
 
934
    // Decide what custom image size to use
 
935
    if ( itemBitmap )
 
936
    {
 
937
        cis.x = itemBitmap->GetWidth();
 
938
        cis.y = itemBitmap->GetHeight();
 
939
    }
 
940
    else
 
941
    {
 
942
        cis = GetImageSize(p, item);
 
943
    }
 
944
 
 
945
    if ( rect.x < 0 )
 
946
    {
 
947
        // Default measure behaviour (no flexible, custom paint image only)
 
948
        if ( rect.width < 0 )
 
949
        {
 
950
            wxCoord x, y;
 
951
            GetTextExtent(text, &x, &y, 0, 0);
 
952
            rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9 + x;
 
953
        }
 
954
 
 
955
        rect.height = cis.y + 2;
 
956
        return;
 
957
    }
 
958
 
 
959
    wxPGPaintData paintdata;
 
960
    paintdata.m_parent = NULL;
 
961
    paintdata.m_choiceItem = item;
 
962
 
 
963
    // This is by the current (1.0.0b) spec - if painting control, item is -1
 
964
    if ( (flags & wxPGCC_PAINTING_CONTROL) )
 
965
        paintdata.m_choiceItem = -1;
 
966
 
 
967
    if ( &dc )
 
968
        dc.SetBrush(*wxWHITE_BRUSH);
 
969
 
 
970
    wxPGCellRenderer* renderer = NULL;
 
971
    const wxPGCell* cell = NULL;
 
972
 
 
973
    if ( rect.x >= 0 )
 
974
    {
 
975
        //
 
976
        // DrawItem call
 
977
 
 
978
        wxPoint pt(rect.x + wxPG_CONTROL_MARGIN - wxPG_CHOICEXADJUST - 1,
 
979
                   rect.y + 1);
 
980
 
 
981
        int renderFlags = 0;
 
982
 
 
983
        if ( flags & wxPGCC_PAINTING_CONTROL )
 
984
        {
 
985
            renderFlags |= wxPGCellRenderer::Control;
 
986
        }
 
987
        else
 
988
        {
 
989
            // For consistency, always use normal font when drawing drop down
 
990
            // items
 
991
            dc.SetFont(GetFont());
 
992
        }
 
993
 
 
994
        if ( flags & wxPGCC_PAINTING_SELECTED )
 
995
            renderFlags |= wxPGCellRenderer::Selected;
 
996
 
 
997
        if ( cis.x > 0 && (p->HasFlag(wxPG_PROP_CUSTOMIMAGE) || !(flags & wxPGCC_PAINTING_CONTROL)) &&
 
998
             ( !p->m_valueBitmap || item == pCb->GetSelection() ) &&
 
999
             ( item >= 0 || (flags & wxPGCC_PAINTING_CONTROL) ) &&
 
1000
             !itemBitmap
 
1001
           )
 
1002
        {
 
1003
            pt.x += wxCC_CUSTOM_IMAGE_MARGIN1;
 
1004
            wxRect r(pt.x,pt.y,cis.x,cis.y);
 
1005
 
 
1006
            if ( flags & wxPGCC_PAINTING_CONTROL )
 
1007
            {
 
1008
                //r.width = cis.x;
 
1009
                r.height = wxPG_STD_CUST_IMAGE_HEIGHT(m_lineHeight);
 
1010
            }
 
1011
 
 
1012
            paintdata.m_drawnWidth = r.width;
 
1013
 
 
1014
            dc.SetPen(m_colPropFore);
 
1015
            if ( comValIndex >= 0 )
 
1016
            {
 
1017
                const wxPGCommonValue* cv = GetCommonValue(comValIndex);
 
1018
                wxPGCellRenderer* renderer = cv->GetRenderer();
 
1019
                r.width = rect.width;
 
1020
                renderer->Render( dc, r, this, p, m_selColumn, comValIndex, renderFlags );
 
1021
                return;
 
1022
            }
 
1023
            else if ( item >= 0 )
 
1024
            {
 
1025
                p->OnCustomPaint( dc, r, paintdata );
 
1026
            }
 
1027
            else
 
1028
            {
 
1029
                dc.DrawRectangle( r );
 
1030
            }
 
1031
 
 
1032
            pt.x += paintdata.m_drawnWidth + wxCC_CUSTOM_IMAGE_MARGIN2 - 1;
 
1033
        }
 
1034
        else
 
1035
        {
 
1036
            // TODO: This aligns text so that it seems to be horizontally
 
1037
            //       on the same line as property values. Not really
 
1038
            //       sure if its needed, but seems to not cause any harm.
 
1039
            pt.x -= 1;
 
1040
 
 
1041
            if ( (flags & wxPGCC_PAINTING_CONTROL) )
 
1042
            {
 
1043
                if ( p->IsValueUnspecified() )
 
1044
                    cell = &m_unspecifiedAppearance;
 
1045
                else if ( item < 0 )
 
1046
                    item = pCb->GetSelection();
 
1047
            }
 
1048
 
 
1049
            if ( p->IsValueUnspecified() && item < 0 )
 
1050
            {
 
1051
                cell = &m_unspecifiedAppearance;
 
1052
            }
 
1053
 
 
1054
            if ( pChoices && item >= 0 && comValIndex < 0 )
 
1055
            {
 
1056
                cell = &pChoices->Item(item);
 
1057
                renderer = wxPGGlobalVars->m_defaultRenderer;
 
1058
                int imageOffset = renderer->PreDrawCell(dc, rect, *cell,
 
1059
                                                        renderFlags );
 
1060
                if ( imageOffset )
 
1061
                    imageOffset += wxCC_CUSTOM_IMAGE_MARGIN1 +
 
1062
                                   wxCC_CUSTOM_IMAGE_MARGIN2;
 
1063
                pt.x += imageOffset;
 
1064
            }
 
1065
        }
 
1066
 
 
1067
        //
 
1068
        // Draw text
 
1069
        //
 
1070
 
 
1071
        pt.y += (rect.height-m_fontHeight)/2 - 1;
 
1072
 
 
1073
        pt.x += 1;
 
1074
 
 
1075
        dc.DrawText( text, pt.x + wxPG_XBEFORETEXT, pt.y );
 
1076
 
 
1077
        if ( renderer )
 
1078
            renderer->PostDrawCell(dc, this, *cell, renderFlags);
 
1079
    }
 
1080
    else
 
1081
    {
 
1082
        //
 
1083
        // MeasureItem call
 
1084
 
 
1085
        p->OnCustomPaint( dc, rect, paintdata );
 
1086
        rect.height = paintdata.m_drawnHeight + 2;
 
1087
        rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9;
 
1088
    }
 
1089
}
 
1090
 
 
1091
bool wxPGChoiceEditor_SetCustomPaintWidth( wxPropertyGrid* propGrid,
 
1092
                                           wxPGComboBox* cb,
 
1093
                                           wxPGProperty* property,
 
1094
                                           int cmnVal )
 
1095
{
 
1096
    // Must return true if value was not a common value
 
1097
    int custPaintMargin;
 
1098
 
 
1099
    //
 
1100
    // Use different custom paint margin because of better textctrl spacing
 
1101
    if ( cb->HasFlag(wxCB_READONLY) )
 
1102
        custPaintMargin = ODCB_CUST_PAINT_MARGIN_RO;
 
1103
    else
 
1104
        custPaintMargin = ODCB_CUST_PAINT_MARGIN;
 
1105
 
 
1106
    if ( property->IsValueUnspecified() )
 
1107
    {
 
1108
        cb->SetCustomPaintWidth( 0 );
 
1109
        return true;
 
1110
    }
 
1111
 
 
1112
    if ( cmnVal >= 0 )
 
1113
    {
 
1114
        // Yes, a common value is being selected
 
1115
        property->SetCommonValue( cmnVal );
 
1116
        wxSize imageSize = propGrid->GetCommonValue(cmnVal)->
 
1117
                            GetRenderer()->GetImageSize(property, 1, cmnVal);
 
1118
        if ( imageSize.x ) imageSize.x += custPaintMargin;
 
1119
        cb->SetCustomPaintWidth( imageSize.x );
 
1120
        return false;
 
1121
    }
 
1122
    else
 
1123
    {
 
1124
        wxSize imageSize = propGrid->GetImageSize(property, -1);
 
1125
        if ( imageSize.x ) imageSize.x += custPaintMargin;
 
1126
        cb->SetCustomPaintWidth( imageSize.x );
 
1127
        return true;
 
1128
    }
 
1129
}
 
1130
 
 
1131
// CreateControls calls this with CB_READONLY in extraStyle
 
1132
wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid,
 
1133
                                                wxPGProperty* property,
 
1134
                                                const wxPoint& pos,
 
1135
                                                const wxSize& sz,
 
1136
                                                long extraStyle ) const
 
1137
{
 
1138
    wxString        defString;
 
1139
 
 
1140
    // Since it is not possible (yet) to create a read-only combo box in
 
1141
    // the same sense that wxTextCtrl is read-only, simply do not create
 
1142
    // the control in this case.
 
1143
    if ( property->HasFlag(wxPG_PROP_READONLY) )
 
1144
        return NULL;
 
1145
 
 
1146
    // Get choices.
 
1147
    int index = property->GetChoiceInfo( NULL );
 
1148
 
 
1149
    bool isUnspecified = property->IsValueUnspecified();
 
1150
 
 
1151
    if ( isUnspecified )
 
1152
        index = -1;
 
1153
    else
 
1154
        defString = property->GetDisplayedString();
 
1155
 
 
1156
    const wxPGChoices& choices = property->GetChoices();
 
1157
 
 
1158
    wxArrayString labels = choices.GetLabels();
 
1159
 
 
1160
    wxPGComboBox* cb;
 
1161
 
 
1162
    wxPoint po(pos);
 
1163
    wxSize si(sz);
 
1164
    po.y += wxPG_CHOICEYADJUST;
 
1165
    si.y -= (wxPG_CHOICEYADJUST*2);
 
1166
 
 
1167
    po.x += wxPG_CHOICEXADJUST;
 
1168
    si.x -= wxPG_CHOICEXADJUST;
 
1169
    wxWindow* ctrlParent = propGrid->GetPanel();
 
1170
 
 
1171
    int odcbFlags = extraStyle | wxNO_BORDER | wxPGCC_PROCESS_ENTER | wxPGCC_ALT_KEYS;
 
1172
 
 
1173
    if ( (property->GetFlags() & wxPG_PROP_USE_DCC) &&
 
1174
         (property->IsKindOf(CLASSINFO(wxBoolProperty)) ) )
 
1175
        odcbFlags |= wxPGCC_DCLICK_CYCLES;
 
1176
 
 
1177
    //
 
1178
    // If common value specified, use appropriate index
 
1179
    unsigned int cmnVals = property->GetDisplayedCommonValueCount();
 
1180
    if ( cmnVals )
 
1181
    {
 
1182
        if ( !isUnspecified )
 
1183
        {
 
1184
            int cmnVal = property->GetCommonValue();
 
1185
            if ( cmnVal >= 0 )
 
1186
            {
 
1187
                index = labels.size() + cmnVal;
 
1188
            }
 
1189
        }
 
1190
 
 
1191
        unsigned int i;
 
1192
        for ( i=0; i<cmnVals; i++ )
 
1193
            labels.Add(propGrid->GetCommonValueLabel(i));
 
1194
    }
 
1195
 
 
1196
    cb = new wxPGComboBox();
 
1197
#ifdef __WXMSW__
 
1198
    cb->Hide();
 
1199
#endif
 
1200
    cb->Create(ctrlParent,
 
1201
               wxPG_SUBID1,
 
1202
               wxString(),
 
1203
               po,
 
1204
               si,
 
1205
               labels,
 
1206
               odcbFlags);
 
1207
 
 
1208
    //int extRight = propGrid->GetClientSize().x - (po.x+si.x);
 
1209
    //int extRight =  - (po.x+si.x);
 
1210
 
 
1211
    cb->SetButtonPosition(si.y,0,wxRIGHT);
 
1212
    //cb->SetPopupExtents( 1, extRight );
 
1213
    cb->SetTextIndent(wxPG_XBEFORETEXT-1);
 
1214
 
 
1215
    wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property,
 
1216
                                          property->GetCommonValue() );
 
1217
    /*if ( property->GetFlags() & wxPG_PROP_CUSTOMIMAGE )
 
1218
    {
 
1219
        wxSize imageSize = propGrid->GetImageSize(property, index);
 
1220
        if ( imageSize.x ) imageSize.x += ODCB_CUST_PAINT_MARGIN;
 
1221
        cb->SetCustomPaintWidth( imageSize.x );
 
1222
    }*/
 
1223
 
 
1224
    if ( index >= 0 && index < (int)cb->GetCount() )
 
1225
    {
 
1226
        cb->SetSelection( index );
 
1227
        if ( defString.length() )
 
1228
            cb->SetText( defString );
 
1229
    }
 
1230
    else if ( !(extraStyle & wxCB_READONLY) && defString.length() )
 
1231
        cb->SetValue( defString );
 
1232
    else
 
1233
        cb->SetSelection( -1 );
 
1234
 
 
1235
#ifdef __WXMSW__
 
1236
    cb->Show();
 
1237
#endif
 
1238
 
 
1239
    return (wxWindow*) cb;
 
1240
}
 
1241
 
 
1242
 
 
1243
void wxPGChoiceEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 
1244
{
 
1245
    wxASSERT( ctrl );
 
1246
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1247
    wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)));
 
1248
    int ind = property->GetChoiceInfo( (wxPGChoiceInfo*)NULL );
 
1249
    cb->SetSelection(ind);
 
1250
}
 
1251
 
 
1252
wxPGWindowList wxPGChoiceEditor::CreateControls( wxPropertyGrid* propGrid, wxPGProperty* property,
 
1253
        const wxPoint& pos, const wxSize& sz ) const
 
1254
{
 
1255
    return CreateControlsBase(propGrid,property,pos,sz,wxCB_READONLY);
 
1256
}
 
1257
 
 
1258
 
 
1259
int wxPGChoiceEditor::InsertItem( wxWindow* ctrl, const wxString& label, int index ) const
 
1260
{
 
1261
    wxASSERT( ctrl );
 
1262
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1263
    wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)));
 
1264
 
 
1265
    if (index < 0)
 
1266
        index = cb->GetCount();
 
1267
 
 
1268
    return cb->Insert(label,index);
 
1269
}
 
1270
 
 
1271
 
 
1272
void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const
 
1273
{
 
1274
    wxASSERT( ctrl );
 
1275
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1276
    wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)));
 
1277
 
 
1278
    cb->Delete(index);
 
1279
}
 
1280
 
 
1281
bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* propGrid, wxPGProperty* property,
 
1282
    wxWindow* ctrl, wxEvent& event ) const
 
1283
{
 
1284
    if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
 
1285
    {
 
1286
        wxPGComboBox* cb = (wxPGComboBox*)ctrl;
 
1287
        int index = cb->GetSelection();
 
1288
        int cmnValIndex = -1;
 
1289
        int cmnVals = property->GetDisplayedCommonValueCount();
 
1290
        int items = cb->GetCount();
 
1291
 
 
1292
        if ( index >= (items-cmnVals) )
 
1293
        {
 
1294
            // Yes, a common value is being selected
 
1295
            cmnValIndex = index - (items-cmnVals);
 
1296
            property->SetCommonValue( cmnValIndex );
 
1297
 
 
1298
            // Truly set value to unspecified?
 
1299
            if ( propGrid->GetUnspecifiedCommonValue() == cmnValIndex )
 
1300
            {
 
1301
                if ( !property->IsValueUnspecified() )
 
1302
                    propGrid->SetInternalFlag(wxPG_FL_VALUE_CHANGE_IN_EVENT);
 
1303
                property->SetValueToUnspecified();
 
1304
                if ( !cb->HasFlag(wxCB_READONLY) )
 
1305
                    cb->GetTextCtrl()->SetValue(wxEmptyString);
 
1306
                return false;
 
1307
            }
 
1308
        }
 
1309
        return wxPGChoiceEditor_SetCustomPaintWidth( propGrid, cb, property,
 
1310
                                                     cmnValIndex);
 
1311
    }
 
1312
    return false;
 
1313
}
 
1314
 
 
1315
 
 
1316
bool wxPGChoiceEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const
 
1317
{
 
1318
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1319
 
 
1320
    int index = cb->GetSelection();
 
1321
 
 
1322
    if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) ||
 
1323
        // Changing unspecified always causes event (returning
 
1324
        // true here should be enough to trigger it).
 
1325
         property->IsValueUnspecified()
 
1326
       )
 
1327
    {
 
1328
        return property->ActualIntToValue( variant, index, 0 );
 
1329
    }
 
1330
    return false;
 
1331
}
 
1332
 
 
1333
 
 
1334
void wxPGChoiceEditor::SetControlStringValue( wxPGProperty* WXUNUSED(property), wxWindow* ctrl, const wxString& txt ) const
 
1335
{
 
1336
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1337
    wxASSERT( cb );
 
1338
    cb->SetValue(txt);
 
1339
}
 
1340
 
 
1341
 
 
1342
void wxPGChoiceEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxWindow* ctrl, int value ) const
 
1343
{
 
1344
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1345
    wxASSERT( cb );
 
1346
    cb->SetSelection(value);
 
1347
}
 
1348
 
 
1349
 
 
1350
void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* property,
 
1351
                                              wxWindow* ctrl ) const
 
1352
{
 
1353
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1354
 
 
1355
    if ( !cb->HasFlag(wxCB_READONLY) )
 
1356
    {
 
1357
        wxPropertyGrid* pg = property->GetGrid();
 
1358
        if ( pg )
 
1359
        {
 
1360
            wxString tcText = pg->GetUnspecifiedValueText();
 
1361
            pg->SetupTextCtrlValue(tcText);
 
1362
            cb->SetValue(tcText);
 
1363
        }
 
1364
    }
 
1365
    else
 
1366
    {
 
1367
        cb->SetSelection(-1);
 
1368
    }
 
1369
}
 
1370
 
 
1371
 
 
1372
bool wxPGChoiceEditor::CanContainCustomImage() const
 
1373
{
 
1374
    return true;
 
1375
}
 
1376
 
 
1377
 
 
1378
wxPGChoiceEditor::~wxPGChoiceEditor() { }
 
1379
 
 
1380
 
 
1381
// -----------------------------------------------------------------------
 
1382
// wxPGComboBoxEditor
 
1383
// -----------------------------------------------------------------------
 
1384
 
 
1385
 
 
1386
WX_PG_IMPLEMENT_EDITOR_CLASS(ComboBox,wxPGComboBoxEditor,wxPGChoiceEditor)
 
1387
 
 
1388
 
 
1389
void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const
 
1390
{
 
1391
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1392
    cb->SetValue(property->GetValueString(wxPG_EDITABLE_VALUE));
 
1393
 
 
1394
    // TODO: If string matches any selection, then select that.
 
1395
}
 
1396
 
 
1397
 
 
1398
wxPGWindowList wxPGComboBoxEditor::CreateControls( wxPropertyGrid* propGrid,
 
1399
                                                   wxPGProperty* property,
 
1400
                                                   const wxPoint& pos,
 
1401
                                                   const wxSize& sz ) const
 
1402
{
 
1403
    return CreateControlsBase(propGrid,property,pos,sz,0);
 
1404
}
 
1405
 
 
1406
 
 
1407
bool wxPGComboBoxEditor::OnEvent( wxPropertyGrid* propGrid,
 
1408
                                  wxPGProperty* property,
 
1409
                                  wxWindow* ctrl,
 
1410
                                  wxEvent& event ) const
 
1411
{
 
1412
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*) NULL;
 
1413
    wxWindow* textCtrl = (wxWindow*) NULL;
 
1414
 
 
1415
    if ( ctrl )
 
1416
    {
 
1417
        cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1418
        textCtrl = cb->GetTextCtrl();
 
1419
    }
 
1420
 
 
1421
    if ( wxPGTextCtrlEditor::OnTextCtrlEvent(propGrid,property,textCtrl,event) )
 
1422
        return true;
 
1423
 
 
1424
    return wxPGChoiceEditor::OnEvent(propGrid,property,ctrl,event);
 
1425
}
 
1426
 
 
1427
 
 
1428
bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const
 
1429
{
 
1430
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1431
    wxString textVal = cb->GetValue();
 
1432
 
 
1433
    if ( property->UsesAutoUnspecified() && !textVal.length() )
 
1434
    {
 
1435
        variant.MakeNull();
 
1436
        return true;
 
1437
    }
 
1438
 
 
1439
    bool res = property->ActualStringToValue(variant, textVal, wxPG_EDITABLE_VALUE);
 
1440
 
 
1441
    // Changing unspecified always causes event (returning
 
1442
    // true here should be enough to trigger it).
 
1443
    if ( !res && variant.IsNull() )
 
1444
        res = true;
 
1445
 
 
1446
    return res;
 
1447
}
 
1448
 
 
1449
void wxPGComboBoxEditor::OnFocus( wxPGProperty* property,
 
1450
                                  wxWindow* ctrl ) const
 
1451
{
 
1452
    wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl;
 
1453
    wxPGTextCtrlEditor_OnFocus(property, cb->GetTextCtrl());
 
1454
}
 
1455
 
 
1456
 
 
1457
wxPGComboBoxEditor::~wxPGComboBoxEditor() { }
 
1458
 
 
1459
 
 
1460
// -----------------------------------------------------------------------
 
1461
// wxPGChoiceAndButtonEditor
 
1462
// -----------------------------------------------------------------------
 
1463
 
 
1464
 
 
1465
// This simpler implement_editor macro doesn't define class body.
 
1466
WX_PG_IMPLEMENT_EDITOR_CLASS(ChoiceAndButton,wxPGChoiceAndButtonEditor,wxPGChoiceEditor)
 
1467
 
 
1468
 
 
1469
wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid,
 
1470
                                                          wxPGProperty* property,
 
1471
                                                          const wxPoint& pos,
 
1472
                                                          const wxSize& sz ) const
 
1473
{
 
1474
    // Use one two units smaller to match size of the combo's dropbutton.
 
1475
    // (normally a bigger button is used because it looks better)
 
1476
    int bt_wid = sz.y;
 
1477
    bt_wid -= 2;
 
1478
    wxSize bt_sz(bt_wid,bt_wid);
 
1479
 
 
1480
    // Position of button.
 
1481
    wxPoint bt_pos(pos.x+sz.x-bt_sz.x,pos.y);
 
1482
#ifdef __WXMAC__
 
1483
    bt_pos.y -= 1;
 
1484
#else
 
1485
    bt_pos.y += 1;
 
1486
#endif
 
1487
 
 
1488
    wxWindow* bt = propGrid->GenerateEditorButton( bt_pos, bt_sz );
 
1489
 
 
1490
    // Size of choice.
 
1491
    wxSize ch_sz(sz.x-bt->GetSize().x,sz.y);
 
1492
 
 
1493
#ifdef __WXMAC__
 
1494
    ch_sz.x -= wxPG_TEXTCTRL_AND_BUTTON_SPACING;
 
1495
#endif
 
1496
 
 
1497
    wxWindow* ch = wxPG_EDITOR(Choice)->CreateControls(propGrid,property,
 
1498
        pos,ch_sz).m_primary;
 
1499
 
 
1500
#ifdef __WXMSW__
 
1501
    bt->Show();
 
1502
#endif
 
1503
 
 
1504
    return wxPGWindowList(ch, bt);
 
1505
}
 
1506
 
 
1507
 
 
1508
wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { }
 
1509
 
 
1510
 
 
1511
// -----------------------------------------------------------------------
 
1512
// wxPGTextCtrlAndButtonEditor
 
1513
// -----------------------------------------------------------------------
 
1514
 
 
1515
 
 
1516
// This simpler implement_editor macro doesn't define class body.
 
1517
WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrlAndButton,wxPGTextCtrlAndButtonEditor,wxPGTextCtrlEditor)
 
1518
 
 
1519
 
 
1520
wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid,
 
1521
                                                            wxPGProperty* property,
 
1522
                                                            const wxPoint& pos,
 
1523
                                                            const wxSize& sz ) const
 
1524
{
 
1525
    wxWindow* wnd2;
 
1526
    wxWindow* wnd = propGrid->GenerateEditorTextCtrlAndButton( pos, sz, &wnd2,
 
1527
        property->GetFlags() & wxPG_PROP_NOEDITOR, property);
 
1528
 
 
1529
    return wxPGWindowList(wnd, wnd2);
 
1530
}
 
1531
 
 
1532
 
 
1533
wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { }
 
1534
 
 
1535
 
 
1536
// -----------------------------------------------------------------------
 
1537
// wxPGCheckBoxEditor
 
1538
// -----------------------------------------------------------------------
 
1539
 
 
1540
#if wxPG_INCLUDE_CHECKBOX
 
1541
 
 
1542
WX_PG_IMPLEMENT_EDITOR_CLASS(CheckBox,wxPGCheckBoxEditor,wxPGEditor)
 
1543
 
 
1544
 
 
1545
// Check box state flags
 
1546
enum
 
1547
{
 
1548
    wxSCB_STATE_UNCHECKED   = 0,
 
1549
    wxSCB_STATE_CHECKED     = 1,
 
1550
    wxSCB_STATE_BOLD        = 2,
 
1551
    wxSCB_STATE_UNSPECIFIED = 4
 
1552
};
 
1553
 
 
1554
const int wxSCB_SETVALUE_CYCLE = 2;
 
1555
 
 
1556
 
 
1557
static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei,
 
1558
                                int state )
 
1559
{
 
1560
    // Box rectangle.
 
1561
    wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),
 
1562
             box_hei,box_hei);
 
1563
    wxColour useCol = dc.GetTextForeground();
 
1564
 
 
1565
    // Draw check mark first because it is likely to overdraw the
 
1566
    // surrounding rectangle.
 
1567
    if ( state & wxSCB_STATE_CHECKED )
 
1568
    {
 
1569
        wxRect r2(r.x+wxPG_CHECKMARK_XADJ,
 
1570
                  r.y+wxPG_CHECKMARK_YADJ,
 
1571
                  r.width+wxPG_CHECKMARK_WADJ,
 
1572
                  r.height+wxPG_CHECKMARK_HADJ);
 
1573
    #if wxPG_CHECKMARK_DEFLATE
 
1574
        r2.Deflate(wxPG_CHECKMARK_DEFLATE);
 
1575
    #endif
 
1576
        dc.DrawCheckMark(r2);
 
1577
 
 
1578
        // This would draw a simple cross check mark.
 
1579
        // dc.DrawLine(r.x,r.y,r.x+r.width-1,r.y+r.height-1);
 
1580
        // dc.DrawLine(r.x,r.y+r.height-1,r.x+r.width-1,r.y);
 
1581
 
 
1582
    }
 
1583
 
 
1584
    if ( !(state & wxSCB_STATE_BOLD) )
 
1585
    {
 
1586
        // Pen for thin rectangle.
 
1587
        dc.SetPen(useCol);
 
1588
    }
 
1589
    else
 
1590
    {
 
1591
        // Pen for bold rectangle.
 
1592
        wxPen linepen(useCol,2,wxSOLID);
 
1593
        linepen.SetJoin(wxJOIN_MITER); // This prevents round edges.
 
1594
        dc.SetPen(linepen);
 
1595
        r.x++;
 
1596
        r.y++;
 
1597
        r.width--;
 
1598
        r.height--;
 
1599
    }
 
1600
 
 
1601
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
 
1602
 
 
1603
    dc.DrawRectangle(r);
 
1604
    dc.SetPen(*wxTRANSPARENT_PEN);
 
1605
}
 
1606
 
 
1607
//
 
1608
// Real simple custom-drawn checkbox-without-label class.
 
1609
//
 
1610
class wxSimpleCheckBox : public wxControl
 
1611
{
 
1612
public:
 
1613
 
 
1614
    void SetValue( int value );
 
1615
 
 
1616
    wxSimpleCheckBox( wxWindow* parent,
 
1617
                      wxWindowID id,
 
1618
                      const wxPoint& pos = wxDefaultPosition,
 
1619
                      const wxSize& size = wxDefaultSize )
 
1620
        : wxControl(parent,id,pos,size,wxNO_BORDER|wxWANTS_CHARS)
 
1621
    {
 
1622
        // Due to SetOwnFont stuff necessary for GTK+ 1.2, we need to have this
 
1623
        SetFont( parent->GetFont() );
 
1624
 
 
1625
        m_state = wxSCB_STATE_UNCHECKED;
 
1626
        wxPropertyGrid* pg = (wxPropertyGrid*) parent->GetParent();
 
1627
        wxASSERT( pg->IsKindOf(CLASSINFO(wxPropertyGrid)) );
 
1628
        m_boxHeight = pg->GetFontHeight();
 
1629
        SetBackgroundStyle( wxBG_STYLE_COLOUR );
 
1630
    }
 
1631
 
 
1632
    virtual ~wxSimpleCheckBox();
 
1633
 
 
1634
    virtual bool ProcessEvent(wxEvent& event);
 
1635
 
 
1636
    int m_state;
 
1637
    int m_boxHeight;
 
1638
 
 
1639
    static wxBitmap* ms_doubleBuffer;
 
1640
 
 
1641
};
 
1642
 
 
1643
wxSimpleCheckBox::~wxSimpleCheckBox()
 
1644
{
 
1645
    delete ms_doubleBuffer;
 
1646
    ms_doubleBuffer = NULL;
 
1647
}
 
1648
 
 
1649
 
 
1650
wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = (wxBitmap*) NULL;
 
1651
 
 
1652
void wxSimpleCheckBox::SetValue( int value )
 
1653
{
 
1654
    if ( value == wxSCB_SETVALUE_CYCLE )
 
1655
    {
 
1656
        if ( m_state & wxSCB_STATE_CHECKED )
 
1657
            m_state &= ~wxSCB_STATE_CHECKED;
 
1658
        else
 
1659
            m_state |= wxSCB_STATE_CHECKED;
 
1660
    }
 
1661
    else
 
1662
    {
 
1663
        m_state = value;
 
1664
    }
 
1665
    Refresh();
 
1666
 
 
1667
    wxCommandEvent evt(wxEVT_COMMAND_CHECKBOX_CLICKED,GetParent()->GetId());
 
1668
 
 
1669
    wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent();
 
1670
    wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) );
 
1671
    propGrid->OnCustomEditorEvent(evt);
 
1672
}
 
1673
 
 
1674
 
 
1675
bool wxSimpleCheckBox::ProcessEvent(wxEvent& event)
 
1676
{
 
1677
    wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent();
 
1678
    wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) );
 
1679
 
 
1680
    if ( event.GetEventType() == wxEVT_NAVIGATION_KEY )
 
1681
    {
 
1682
        //wxLogDebug(wxT("wxEVT_NAVIGATION_KEY"));
 
1683
        //SetFocusFromKbd();
 
1684
        //event.Skip();
 
1685
        //return wxControl::ProcessEvent(event);
 
1686
    }
 
1687
    else
 
1688
    if ( ( (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK)
 
1689
          && ((wxMouseEvent&)event).m_x > (wxPG_XBEFORETEXT-2)
 
1690
          && ((wxMouseEvent&)event).m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight) )
 
1691
       )
 
1692
    {
 
1693
        SetValue(wxSCB_SETVALUE_CYCLE);
 
1694
        return true;
 
1695
    }
 
1696
    else if ( event.GetEventType() == wxEVT_PAINT )
 
1697
    {
 
1698
        wxSize clientSize = GetClientSize();
 
1699
        wxPaintDC dc(this);
 
1700
 
 
1701
        /*
 
1702
        // Buffered paint DC doesn't seem to do much good
 
1703
        if ( !ms_doubleBuffer ||
 
1704
             clientSize.x > ms_doubleBuffer->GetWidth() ||
 
1705
             clientSize.y > ms_doubleBuffer->GetHeight() )
 
1706
        {
 
1707
            delete ms_doubleBuffer;
 
1708
            ms_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25);
 
1709
        }
 
1710
 
 
1711
        wxBufferedPaintDC dc(this,*ms_doubleBuffer);
 
1712
        */
 
1713
 
 
1714
        wxRect rect(0,0,clientSize.x,clientSize.y);
 
1715
        //rect.x -= 1;
 
1716
        rect.y += 1;
 
1717
        rect.width += 1;
 
1718
 
 
1719
        m_boxHeight = propGrid->GetFontHeight();
 
1720
 
 
1721
        wxColour bgcol = GetBackgroundColour();
 
1722
        dc.SetBrush( bgcol );
 
1723
        dc.SetPen( bgcol );
 
1724
        dc.DrawRectangle( rect );
 
1725
 
 
1726
        dc.SetTextForeground(GetForegroundColour());
 
1727
 
 
1728
        int state = m_state;
 
1729
        if ( !(state & wxSCB_STATE_UNSPECIFIED) &&
 
1730
             GetFont().GetWeight() == wxBOLD )
 
1731
            state |= wxSCB_STATE_BOLD;
 
1732
 
 
1733
        DrawSimpleCheckBox(dc, rect, m_boxHeight, state);
 
1734
 
 
1735
        return true;
 
1736
    }
 
1737
    else if ( event.GetEventType() == wxEVT_SIZE ||
 
1738
              event.GetEventType() == wxEVT_SET_FOCUS ||
 
1739
              event.GetEventType() == wxEVT_KILL_FOCUS
 
1740
            )
 
1741
    {
 
1742
        Refresh();
 
1743
    }
 
1744
    else if ( event.GetEventType() == wxEVT_KEY_DOWN )
 
1745
    {
 
1746
        wxKeyEvent& keyEv = (wxKeyEvent&) event;
 
1747
 
 
1748
        if ( keyEv.GetKeyCode() == WXK_TAB )
 
1749
        {
 
1750
            propGrid->SendNavigationKeyEvent( keyEv.ShiftDown()?0:1 );
 
1751
            return true;
 
1752
        }
 
1753
        else
 
1754
        if ( keyEv.GetKeyCode() == WXK_SPACE )
 
1755
        {
 
1756
            SetValue(wxSCB_SETVALUE_CYCLE);
 
1757
            return true;
 
1758
        }
 
1759
    }
 
1760
    return wxControl::ProcessEvent(event);
 
1761
}
 
1762
 
 
1763
 
 
1764
wxPGWindowList wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid,
 
1765
                                                   wxPGProperty* property,
 
1766
                                                   const wxPoint& pos,
 
1767
                                                   const wxSize& size ) const
 
1768
{
 
1769
    if ( property->HasFlag(wxPG_PROP_READONLY) )
 
1770
        return NULL;
 
1771
 
 
1772
    wxPoint pt = pos;
 
1773
    pt.x -= wxPG_XBEFOREWIDGET;
 
1774
    wxSize sz = size;
 
1775
    sz.x = propGrid->GetFontHeight() + (wxPG_XBEFOREWIDGET*2) + 4;
 
1776
 
 
1777
    wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid->GetPanel(),wxPG_SUBID1,pt,sz);
 
1778
 
 
1779
    cb->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 
1780
 
 
1781
    cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DOWN,
 
1782
            (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
 
1783
            &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid );
 
1784
 
 
1785
    cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DCLICK,
 
1786
            (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
 
1787
            &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid );
 
1788
 
 
1789
    if ( property->IsValueUnspecified() )
 
1790
    {
 
1791
        cb->m_state = wxSCB_STATE_UNSPECIFIED;
 
1792
    }
 
1793
    else
 
1794
    {
 
1795
        if ( property->GetChoiceInfo((wxPGChoiceInfo*)NULL) )
 
1796
            cb->m_state = wxSCB_STATE_CHECKED;
 
1797
 
 
1798
        // If mouse cursor was on the item, toggle the value now.
 
1799
        if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK )
 
1800
        {
 
1801
            wxPoint pt = cb->ScreenToClient(::wxGetMousePosition());
 
1802
            if ( pt.x <= (wxPG_XBEFORETEXT-2+cb->m_boxHeight) )
 
1803
            {
 
1804
                if ( cb->m_state & wxSCB_STATE_CHECKED )
 
1805
                    cb->m_state &= ~wxSCB_STATE_CHECKED;
 
1806
                else
 
1807
                    cb->m_state |= wxSCB_STATE_CHECKED;
 
1808
 
 
1809
                // Makes sure wxPG_EVT_CHANGING etc. is sent for this initial
 
1810
                // click 
 
1811
                propGrid->ChangePropertyValue(property,
 
1812
                                              wxPGVariant_Bool(cb->m_state));
 
1813
            }
 
1814
        }
 
1815
    }
 
1816
 
 
1817
    propGrid->SetInternalFlag( wxPG_FL_FIXED_WIDTH_EDITOR );
 
1818
 
 
1819
    return cb;
 
1820
}
 
1821
 
 
1822
void wxPGCheckBoxEditor::DrawValue( wxDC& dc, const wxRect& rect,
 
1823
                                    wxPGProperty* property,
 
1824
                                    const wxString& WXUNUSED(text) ) const
 
1825
{
 
1826
    int state = wxSCB_STATE_UNCHECKED;
 
1827
 
 
1828
    if ( !property->IsValueUnspecified() )
 
1829
    {
 
1830
        state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL);
 
1831
        if ( dc.GetFont().GetWeight() == wxBOLD )
 
1832
            state |= wxSCB_STATE_BOLD;
 
1833
    }
 
1834
    else
 
1835
    {
 
1836
        state |= wxSCB_STATE_UNSPECIFIED;
 
1837
    }
 
1838
 
 
1839
    DrawSimpleCheckBox(dc, rect, dc.GetCharHeight(), state);
 
1840
}
 
1841
 
 
1842
void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property,
 
1843
                                        wxWindow* ctrl ) const
 
1844
{
 
1845
    wxSimpleCheckBox* cb = (wxSimpleCheckBox*) ctrl;
 
1846
    wxASSERT( cb );
 
1847
 
 
1848
    if ( !property->IsValueUnspecified() )
 
1849
        cb->m_state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL);
 
1850
    else
 
1851
        cb->m_state = wxSCB_STATE_UNSPECIFIED;
 
1852
 
 
1853
    cb->Refresh();
 
1854
}
 
1855
 
 
1856
bool wxPGCheckBoxEditor::OnEvent( wxPropertyGrid* WXUNUSED(propGrid), wxPGProperty* WXUNUSED(property),
 
1857
    wxWindow* WXUNUSED(ctrl), wxEvent& event ) const
 
1858
{
 
1859
    if ( event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED )
 
1860
    {
 
1861
        return true;
 
1862
    }
 
1863
    return false;
 
1864
}
 
1865
 
 
1866
 
 
1867
bool wxPGCheckBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const
 
1868
{
 
1869
    wxSimpleCheckBox* cb = (wxSimpleCheckBox*)ctrl;
 
1870
 
 
1871
    int index = cb->m_state;
 
1872
 
 
1873
    if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) ||
 
1874
         // Changing unspecified always causes event (returning
 
1875
         // true here should be enough to trigger it).
 
1876
         property->IsValueUnspecified()
 
1877
       )
 
1878
    {
 
1879
        return property->ActualIntToValue(variant, index, 0);
 
1880
    }
 
1881
    return false;
 
1882
}
 
1883
 
 
1884
 
 
1885
void wxPGCheckBoxEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxWindow* ctrl, int value ) const
 
1886
{
 
1887
    if ( value != 0 ) value = 1;
 
1888
    ((wxSimpleCheckBox*)ctrl)->m_state = value;
 
1889
    ctrl->Refresh();
 
1890
}
 
1891
 
 
1892
 
 
1893
void wxPGCheckBoxEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const
 
1894
{
 
1895
    ((wxSimpleCheckBox*)ctrl)->m_state = wxSCB_STATE_UNSPECIFIED;
 
1896
    ctrl->Refresh();
 
1897
}
 
1898
 
 
1899
 
 
1900
wxPGCheckBoxEditor::~wxPGCheckBoxEditor() { }
 
1901
 
 
1902
 
 
1903
#endif // wxPG_INCLUDE_CHECKBOX
 
1904
 
 
1905
// -----------------------------------------------------------------------
 
1906
 
 
1907
wxWindow* wxPropertyGrid::GetEditorControl() const
 
1908
{
 
1909
    wxWindow* ctrl = m_wndEditor;
 
1910
 
 
1911
    if ( !ctrl )
 
1912
        return ctrl;
 
1913
 
 
1914
    // If it's clipper window, return its child instead
 
1915
#if wxPG_ENABLE_CLIPPER_WINDOW
 
1916
    if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) )
 
1917
    {
 
1918
        return ((wxPGClipperWindow*)ctrl)->GetControl();
 
1919
    }
 
1920
#endif
 
1921
 
 
1922
    return ctrl;
 
1923
}
 
1924
 
 
1925
// -----------------------------------------------------------------------
 
1926
 
 
1927
wxTextCtrl* wxPropertyGrid::GetLabelEditor() const
 
1928
{
 
1929
    wxWindow* tcWnd = m_labelEditor;
 
1930
 
 
1931
    if ( !tcWnd )
 
1932
        return NULL;
 
1933
 
 
1934
#if wxPG_ENABLE_CLIPPER_WINDOW
 
1935
    if ( tcWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) )
 
1936
    {
 
1937
        tcWnd = ((wxPGClipperWindow*)tcWnd)->GetControl();
 
1938
    }
 
1939
#endif
 
1940
 
 
1941
    return wxStaticCast(tcWnd, wxTextCtrl);
 
1942
}
 
1943
 
 
1944
// -----------------------------------------------------------------------
 
1945
 
 
1946
void wxPropertyGrid::CorrectEditorWidgetSizeX()
 
1947
{
 
1948
    int secWid = 0;
 
1949
 
 
1950
    // Use fixed selColumn 1 for main editor widgets
 
1951
    int newSplitterx = m_pState->DoGetSplitterPosition(0);
 
1952
    int newWidth = newSplitterx + m_pState->m_colWidths[1];
 
1953
 
 
1954
    if ( m_wndEditor2 )
 
1955
    {
 
1956
        // if width change occurred, move secondary wnd by that amount
 
1957
        wxRect r = m_wndEditor2->GetRect();
 
1958
        secWid = r.width;
 
1959
        r.x = newWidth - secWid;
 
1960
 
 
1961
        m_wndEditor2->SetSize( r );
 
1962
 
 
1963
        // if primary is textctrl, then we have to add some extra space
 
1964
#ifdef __WXMAC__
 
1965
        if ( m_wndEditor )
 
1966
#else
 
1967
        if ( m_wndEditor && m_wndEditor->IsKindOf(CLASSINFO(wxTextCtrl)) )
 
1968
#endif
 
1969
            secWid += wxPG_TEXTCTRL_AND_BUTTON_SPACING;
 
1970
    }
 
1971
 
 
1972
    if ( m_wndEditor )
 
1973
    {
 
1974
        wxRect r = m_wndEditor->GetRect();
 
1975
 
 
1976
        r.x = newSplitterx+m_ctrlXAdjust;
 
1977
 
 
1978
        if ( !(m_iFlags & wxPG_FL_FIXED_WIDTH_EDITOR) )
 
1979
            r.width = newWidth - r.x - secWid;
 
1980
 
 
1981
        m_wndEditor->SetSize(r);
 
1982
    }
 
1983
 
 
1984
    if ( m_wndEditor2 )
 
1985
        m_wndEditor2->Refresh();
 
1986
}
 
1987
 
 
1988
// -----------------------------------------------------------------------
 
1989
 
 
1990
void wxPropertyGrid::CorrectEditorWidgetPosY()
 
1991
{
 
1992
    wxPGProperty* selected = GetSelection();
 
1993
 
 
1994
    if ( selected )
 
1995
    {
 
1996
        if ( m_labelEditor )
 
1997
        {
 
1998
            wxRect r = GetEditorWidgetRect(selected, m_selColumn);
 
1999
            wxPoint pos = m_labelEditor->GetPosition();
 
2000
 
 
2001
            // Calculate y offset
 
2002
            int offset = pos.y % m_lineHeight;
 
2003
 
 
2004
            m_labelEditor->Move(pos.x, r.y + offset);
 
2005
        }
 
2006
 
 
2007
        if ( m_wndEditor || m_wndEditor2 ) 
 
2008
        {
 
2009
            wxRect r = GetEditorWidgetRect(selected, 1);
 
2010
 
 
2011
            if ( m_wndEditor )
 
2012
            {
 
2013
                wxPoint pos = m_wndEditor->GetPosition();
 
2014
 
 
2015
                // Calculate y offset
 
2016
                int offset = pos.y % m_lineHeight;
 
2017
 
 
2018
                m_wndEditor->Move(pos.x, r.y + offset);
 
2019
            }
 
2020
 
 
2021
            if ( m_wndEditor2 )
 
2022
            {
 
2023
                wxPoint pos = m_wndEditor2->GetPosition();
 
2024
 
 
2025
                m_wndEditor2->Move(pos.x, r.y);
 
2026
            }
 
2027
        }
 
2028
    }
 
2029
}
 
2030
 
 
2031
// -----------------------------------------------------------------------
 
2032
 
 
2033
bool wxPropertyGrid::AdjustPosForClipperWindow( wxWindow* topCtrlWnd, int* x, int* y )
 
2034
{
 
2035
#if wxPG_ENABLE_CLIPPER_WINDOW
 
2036
    // Take clipper window into account
 
2037
    if (topCtrlWnd->GetPosition().x < 1 &&
 
2038
        !topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)))
 
2039
    {
 
2040
        topCtrlWnd = topCtrlWnd->GetParent();
 
2041
        wxASSERT( topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) );
 
2042
        *x -= ((wxPGClipperWindow*)topCtrlWnd)->GetXClip();
 
2043
        *y -= ((wxPGClipperWindow*)topCtrlWnd)->GetYClip();
 
2044
        return true;
 
2045
    }
 
2046
#else
 
2047
    wxUnusedVar(topCtrlWnd);
 
2048
    wxUnusedVar(x);
 
2049
    wxUnusedVar(y);
 
2050
#endif
 
2051
    return false;
 
2052
}
 
2053
 
 
2054
// -----------------------------------------------------------------------
 
2055
 
 
2056
// Fixes position of wxTextCtrl-like control (wxSpinCtrl usually
 
2057
// fits into that category as well).
 
2058
void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl,
 
2059
                                        unsigned int forColumn,
 
2060
                                        const wxPoint& offset )
 
2061
{
 
2062
    // Center the control vertically
 
2063
    wxRect finalPos = ctrl->GetRect();
 
2064
    int y_adj = (m_lineHeight - finalPos.height)/2 + wxPG_TEXTCTRLYADJUST;
 
2065
 
 
2066
    // Prevent over-sized control
 
2067
    int sz_dec = (y_adj + finalPos.height) - m_lineHeight;
 
2068
    if ( sz_dec < 0 ) sz_dec = 0;
 
2069
 
 
2070
    finalPos.y += y_adj;
 
2071
    finalPos.height -= (y_adj+sz_dec);
 
2072
 
 
2073
    int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST;
 
2074
 
 
2075
    if ( forColumn != 1 )
 
2076
        textCtrlXAdjust -= 3;  // magic number!
 
2077
 
 
2078
    finalPos.x += textCtrlXAdjust;
 
2079
    finalPos.width -= textCtrlXAdjust;
 
2080
 
 
2081
    finalPos.x += offset.x;
 
2082
    finalPos.y += offset.y;
 
2083
 
 
2084
    ctrl->SetSize(finalPos);
 
2085
}
 
2086
 
 
2087
// -----------------------------------------------------------------------
 
2088
 
 
2089
wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos,
 
2090
                                                  const wxSize& sz,
 
2091
                                                  const wxString& value,
 
2092
                                                  wxWindow* secondary,
 
2093
                                                  int extraStyle,
 
2094
                                                  int maxLen,
 
2095
                                                  unsigned int forColumn )
 
2096
{
 
2097
    wxPGProperty* selected = GetSelection();
 
2098
    wxASSERT(selected);
 
2099
 
 
2100
    int tcFlags = wxTE_PROCESS_ENTER | extraStyle;
 
2101
 
 
2102
    if ( selected->HasFlag(wxPG_PROP_READONLY) && forColumn == 1 )
 
2103
        tcFlags |= wxTE_READONLY;
 
2104
 
 
2105
    wxPoint p(pos.x,pos.y);
 
2106
    wxSize s(sz.x,sz.y);
 
2107
 
 
2108
   // Need to reduce width of text control on Mac
 
2109
#if defined(__WXMAC__)
 
2110
   s.x -= 8;
 
2111
#endif
 
2112
 
 
2113
    // For label editors, trim the size to allow better splitter grabbing
 
2114
    if ( forColumn != 1 )
 
2115
        s.x -= 2;
 
2116
 
 
2117
     // Take button into acccount
 
2118
    if ( secondary )
 
2119
    {
 
2120
        s.x -= (secondary->GetSize().x + wxPG_TEXTCTRL_AND_BUTTON_SPACING);
 
2121
        m_iFlags &= ~(wxPG_FL_PRIMARY_FILLS_ENTIRE);
 
2122
    }
 
2123
 
 
2124
    // If the height is significantly higher, then use border, and fill the rect exactly.
 
2125
    bool hasSpecialSize = false;
 
2126
 
 
2127
    if ( (sz.y - m_lineHeight) > 5 )
 
2128
        hasSpecialSize = true;
 
2129
 
 
2130
#if wxPG_NAT_TEXTCTRL_BORDER_ANY
 
2131
 
 
2132
    // Create clipper window
 
2133
    wxPGClipperWindow* wnd = new wxPGClipperWindow();
 
2134
#if defined(__WXMSW__)
 
2135
    wnd->Hide();
 
2136
#endif
 
2137
    wnd->Create(GetPanel(),wxPG_SUBID1,p,s);
 
2138
 
 
2139
    // This generates rect of the control inside the clipper window
 
2140
    if ( !hasSpecialSize )
 
2141
        wnd->GetControlRect(wxPG_NAT_TEXTCTRL_BORDER_X, wxPG_NAT_TEXTCTRL_BORDER_Y, p, s);
 
2142
    else
 
2143
        wnd->GetControlRect(0, 0, p, s);
 
2144
 
 
2145
    wxWindow* ctrlParent = wnd;
 
2146
 
 
2147
#else
 
2148
 
 
2149
    wxWindow* ctrlParent = GetPanel();
 
2150
 
 
2151
    if ( !hasSpecialSize )
 
2152
        tcFlags |= wxNO_BORDER;
 
2153
 
 
2154
#endif
 
2155
 
 
2156
    wxTextCtrl* tc = new wxTextCtrl();
 
2157
 
 
2158
#if defined(__WXMSW__) && !wxPG_NAT_TEXTCTRL_BORDER_ANY
 
2159
    tc->Hide();
 
2160
#endif
 
2161
    SetupTextCtrlValue(value);
 
2162
    tc->Create(ctrlParent,wxPG_SUBID1,value, p, s,tcFlags);
 
2163
 
 
2164
#if wxPG_NAT_TEXTCTRL_BORDER_ANY
 
2165
    wxWindow* ed = wnd;
 
2166
    wnd->SetControl(tc);
 
2167
#else
 
2168
    wxWindow* ed = tc;
 
2169
#endif
 
2170
 
 
2171
    // Center the control vertically
 
2172
    if ( !hasSpecialSize )
 
2173
        FixPosForTextCtrl(ed, forColumn);
 
2174
 
 
2175
    if ( forColumn != 1 )
 
2176
    {
 
2177
        if ( tc != ed )
 
2178
        {
 
2179
            ed->SetBackgroundColour(m_colSelBack);
 
2180
            ed->SetForegroundColour(m_colSelFore);
 
2181
        }
 
2182
        tc->SetBackgroundColour(m_colSelBack);
 
2183
        tc->SetForegroundColour(m_colSelFore);
 
2184
    }
 
2185
 
 
2186
#ifdef __WXMSW__
 
2187
    ed->Show();
 
2188
    if ( secondary )
 
2189
        secondary->Show();
 
2190
#endif
 
2191
 
 
2192
    // Set maximum length
 
2193
    if ( maxLen > 0 )
 
2194
        tc->SetMaxLength( maxLen );
 
2195
 
 
2196
    return (wxWindow*) ed;
 
2197
}
 
2198
 
 
2199
// -----------------------------------------------------------------------
 
2200
 
 
2201
wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize& sz )
 
2202
{
 
2203
    wxPGProperty* selected = GetSelection();
 
2204
    wxASSERT(selected);
 
2205
 
 
2206
#ifdef __WXMAC__
 
2207
   // Decorations are chunky on Mac, and we can't make the button square, so
 
2208
   // do things a bit differently on this platform.
 
2209
 
 
2210
   wxPoint p(pos.x+sz.x,
 
2211
             pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y);
 
2212
   wxSize s(25, -1);
 
2213
 
 
2214
   wxButton* but = new wxButton();
 
2215
   but->Create(GetPanel(),wxPG_SUBID2,wxT("..."),p,s,wxWANTS_CHARS);
 
2216
 
 
2217
   // Now that we know the size, move to the correct position
 
2218
   p.x = pos.x + sz.x - but->GetSize().x - 2;
 
2219
   but->Move(p);
 
2220
 
 
2221
#else 
 
2222
    wxSize s(sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2),
 
2223
        sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2));
 
2224
 
 
2225
    // Reduce button width to lineheight
 
2226
    if ( s.x > m_lineHeight )
 
2227
        s.x = m_lineHeight;
 
2228
 
 
2229
#ifdef __WXGTK__
 
2230
    // On wxGTK, take fixed button margins into account
 
2231
    if ( s.x < 25 )
 
2232
        s.x = 25;
 
2233
#endif
 
2234
 
 
2235
    wxPoint p(pos.x+sz.x-s.x,
 
2236
        pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y);
 
2237
 
 
2238
    wxButton* but = new wxButton();
 
2239
  #ifdef __WXMSW__
 
2240
    but->Hide();
 
2241
  #endif
 
2242
    but->Create(GetPanel(),wxPG_SUBID2,wxT("..."),p,s,wxWANTS_CHARS);
 
2243
 
 
2244
  #ifdef __WXGTK__
 
2245
    wxFont font = GetFont();
 
2246
    font.SetPointSize(font.GetPointSize()-2);
 
2247
    but->SetFont(font);
 
2248
  #else
 
2249
    but->SetFont(GetFont());
 
2250
  #endif
 
2251
#endif
 
2252
 
 
2253
    if ( selected->HasFlag(wxPG_PROP_READONLY) )
 
2254
        but->Disable();
 
2255
 
 
2256
    return but;
 
2257
}
 
2258
 
 
2259
// -----------------------------------------------------------------------
 
2260
 
 
2261
wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos,
 
2262
                                                           const wxSize& sz,
 
2263
                                                           wxWindow** psecondary,
 
2264
                                                           int limitedEditing,
 
2265
                                                           wxPGProperty* property )
 
2266
{
 
2267
    wxButton* but = (wxButton*)GenerateEditorButton(pos,sz);
 
2268
    *psecondary = (wxWindow*)but;
 
2269
 
 
2270
    if ( limitedEditing )
 
2271
    {
 
2272
    #ifdef __WXMSW__
 
2273
        // There is button Show in GenerateEditorTextCtrl as well
 
2274
        but->Show();
 
2275
    #endif
 
2276
        return (wxWindow*) NULL;
 
2277
    }
 
2278
 
 
2279
    wxString text;
 
2280
 
 
2281
    if ( !property->IsValueUnspecified() )
 
2282
        text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
 
2283
 
 
2284
    return GenerateEditorTextCtrl(pos,sz,text,but,property->m_maxLen);
 
2285
}
 
2286
 
 
2287
// -----------------------------------------------------------------------
 
2288
 
 
2289
void wxPropertyGrid::SetEditorAppearance( const wxPGCell& cell )
 
2290
{
 
2291
    wxWindow* editor = GetEditorControl();
 
2292
    if ( !editor )
 
2293
        return;
 
2294
 
 
2295
    // Get old editor appearance
 
2296
    const wxPGCell& oCell = m_editorAppearance;
 
2297
    wxPGProperty* property = GetSelection();
 
2298
 
 
2299
    wxTextCtrl* tc = GetEditorTextCtrl();
 
2300
 
 
2301
    wxPGComboBox* cb;
 
2302
    if ( editor->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) )
 
2303
        cb = (wxPGComboBox*) editor;
 
2304
    else
 
2305
        cb = NULL;
 
2306
 
 
2307
    if ( tc || cb )
 
2308
    {
 
2309
        wxString tcText;
 
2310
        bool changeText = false;
 
2311
 
 
2312
        if ( cell.HasText() && !IsEditorFocused() )
 
2313
        {
 
2314
            tcText = cell.GetText();
 
2315
            changeText = true;
 
2316
        }
 
2317
        else if ( oCell.HasText() )
 
2318
        {
 
2319
            tcText = GetSelection()->GetValueString(
 
2320
                property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE);
 
2321
            changeText = true;
 
2322
        }
 
2323
 
 
2324
        if ( changeText )
 
2325
        {
 
2326
            if ( tc )
 
2327
            {
 
2328
                // The next line prevents spurious EVT_TEXT from being
 
2329
                // received.
 
2330
                SetupTextCtrlValue(tcText);
 
2331
                tc->SetValue(tcText);
 
2332
            }
 
2333
            else
 
2334
            {
 
2335
                cb->SetText(tcText);
 
2336
            }
 
2337
        }
 
2338
    }
 
2339
 
 
2340
    // We used to obtain wxVisualAttributes via
 
2341
    // editor->GetDefaultAttributes() here, but that is not
 
2342
    // very consistently implemented in wx2.8, so it is safer
 
2343
    // to just use colours from wxSystemSettings etc. 
 
2344
 
 
2345
    const wxColour& fgCol = cell.GetFgCol();
 
2346
    if ( wxGDI_IS_OK(fgCol) )
 
2347
    {
 
2348
        editor->SetForegroundColour(fgCol);
 
2349
 
 
2350
        // Set for wxTextCtrl separately to work around bug in wx2.8
 
2351
        // that may not be fixable due to ABI compatibility issues.
 
2352
        if ( tc && tc != editor )
 
2353
            tc->SetForegroundColour(fgCol);
 
2354
    }
 
2355
    else if ( wxGDI_IS_OK(oCell.GetFgCol()) )
 
2356
    {
 
2357
        wxColour vColFg =
 
2358
            wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
 
2359
        editor->SetForegroundColour(vColFg);
 
2360
        if ( tc && tc != editor )
 
2361
            tc->SetForegroundColour(vColFg);
 
2362
    }
 
2363
 
 
2364
    const wxColour& bgCol = cell.GetBgCol();
 
2365
    if ( wxGDI_IS_OK(bgCol) )
 
2366
    {
 
2367
        editor->SetBackgroundColour(bgCol);
 
2368
        if ( tc && tc != editor )
 
2369
            tc->SetBackgroundColour(bgCol);
 
2370
    }
 
2371
    else if ( wxGDI_IS_OK(oCell.GetBgCol()) )
 
2372
    {
 
2373
        wxColour vColBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
 
2374
        editor->SetBackgroundColour(vColBg);
 
2375
        if ( tc && tc != editor )
 
2376
            tc->SetBackgroundColour(vColBg);
 
2377
    }
 
2378
 
 
2379
    const wxFont& font = cell.GetFont();
 
2380
    if ( wxGDI_IS_OK(font) )
 
2381
    {
 
2382
        editor->SetFont(font);
 
2383
        if ( tc && tc != editor )
 
2384
            tc->SetFont(font);
 
2385
    }
 
2386
    else if ( wxGDI_IS_OK(oCell.GetFont()) )
 
2387
    {
 
2388
        wxFont vFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
 
2389
        editor->SetFont(vFont);
 
2390
        if ( tc && tc != editor )
 
2391
            tc->SetFont(vFont);
 
2392
    }
 
2393
 
 
2394
    m_editorAppearance.Assign(cell);
 
2395
}
 
2396
 
 
2397
// -----------------------------------------------------------------------
 
2398
 
 
2399
wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const
 
2400
{
 
2401
    wxWindow* wnd = GetEditorControl();
 
2402
 
 
2403
    if ( !wnd )
 
2404
        return NULL;
 
2405
 
 
2406
    if ( wnd->IsKindOf(CLASSINFO(wxTextCtrl)) )
 
2407
        return wxStaticCast(wnd, wxTextCtrl);
 
2408
 
 
2409
    if ( wnd->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) )
 
2410
    {
 
2411
        wxPGOwnerDrawnComboBox* cb = wxStaticCast(wnd, wxPGOwnerDrawnComboBox);
 
2412
        return cb->GetTextCtrl();
 
2413
    }
 
2414
 
 
2415
    return NULL;
 
2416
}
 
2417
 
 
2418
// -----------------------------------------------------------------------
 
2419
 
 
2420
#if defined(__WXMSW__) && !defined(__WXWINCE__)
 
2421
 
 
2422
bool wxPG_TextCtrl_SetMargins(wxWindow* tc, const wxPoint& margins)
 
2423
{
 
2424
    ::SendMessage(GetHwndOf(tc),
 
2425
                  EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
 
2426
                  MAKELONG(margins.x, margins.x));
 
2427
    return true;
 
2428
}
 
2429
 
 
2430
/*#elif defined(__WXGTK20__)
 
2431
 
 
2432
//
 
2433
// NOTE: For this to work we need to somehow include gtk devel
 
2434
//       in the bake/makefile.
 
2435
//
 
2436
 
 
2437
#include <gtk/gtk.h>
 
2438
 
 
2439
bool wxPG_TextCtrl_SetMargins(wxWindow* tc, const wxPoint& margins)
 
2440
{
 
2441
    //
 
2442
    // NB: This code has been ported from wx2.9 SVN trunk
 
2443
    //
 
2444
 
 
2445
  #if GTK_CHECK_VERSION(2,10,0)
 
2446
    GtkEntry *entry = NULL;
 
2447
 
 
2448
    entry = GTK_ENTRY( m_widget );
 
2449
 
 
2450
    if ( !entry )
 
2451
        return false;
 
2452
 
 
2453
    const GtkBorder* oldBorder = gtk_entry_get_inner_border(entry);
 
2454
    GtkBorder* newBorder;
 
2455
 
 
2456
    if ( oldBorder )
 
2457
    {
 
2458
        newBorder = gtk_border_copy(oldBorder);
 
2459
    }
 
2460
    else
 
2461
    {
 
2462
    #if GTK_CHECK_VERSION(2,14,0)
 
2463
        newBorder = gtk_border_new();
 
2464
    #else
 
2465
        newBorder = g_slice_new0(GtkBorder);
 
2466
    #endif
 
2467
        // Use some reasonable defaults for initial margins
 
2468
        newBorder->left = 2;
 
2469
        newBorder->right = 2;
 
2470
 
 
2471
        // These numbers seem to let the text remain vertically centered
 
2472
        // in common use scenarios when margins.y == -1.
 
2473
        newBorder->top = 3;
 
2474
        newBorder->bottom = 3;
 
2475
    }
 
2476
 
 
2477
    if ( margins.x != -1 )
 
2478
        newBorder->left = (gint) margins.x;
 
2479
 
 
2480
    if ( margins.y != -1 )
 
2481
        newBorder->top = (gint) margins.y;
 
2482
 
 
2483
    gtk_entry_set_inner_border(entry, newBorder);
 
2484
 
 
2485
  #if GTK_CHECK_VERSION(2,14,0)
 
2486
    gtk_border_free(newBorder);
 
2487
  #else
 
2488
    g_slice_free(GtkBorder, newBorder);
 
2489
  #endif
 
2490
 
 
2491
    return true;
 
2492
  #else
 
2493
    wxUnusedVar(tc);
 
2494
    wxUnusedVar(margins);
 
2495
    return false;
 
2496
  #endif
 
2497
}
 
2498
*/
 
2499
#else
 
2500
 
 
2501
bool wxPG_TextCtrl_SetMargins(wxWindow* tc, const wxPoint& margins)
 
2502
{
 
2503
    wxUnusedVar(tc);
 
2504
    wxUnusedVar(margins);
 
2505
    return false;
 
2506
}
 
2507
 
 
2508
#endif
 
2509
 
 
2510
// -----------------------------------------------------------------------
 
2511
// wxPGEditorDialogAdapter
 
2512
// -----------------------------------------------------------------------
 
2513
 
 
2514
IMPLEMENT_ABSTRACT_CLASS(wxPGEditorDialogAdapter, wxObject)
 
2515
 
 
2516
bool wxPGEditorDialogAdapter::ShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property )
 
2517
{
 
2518
    if ( !propGrid->EditorValidate() )
 
2519
        return false;
 
2520
 
 
2521
    bool res = DoShowDialog( propGrid, property );
 
2522
 
 
2523
    if ( res )
 
2524
    {
 
2525
        propGrid->ValueChangeInEvent( m_value );
 
2526
        return true;
 
2527
    }
 
2528
 
 
2529
    return false;
 
2530
}
 
2531
 
 
2532
// -----------------------------------------------------------------------
 
2533
// wxPGMultiButton
 
2534
// -----------------------------------------------------------------------
 
2535
 
 
2536
wxPGMultiButton::wxPGMultiButton( wxPropertyGrid* pg, const wxSize& sz )
 
2537
    : wxWindow( pg->GetPanel(), wxPG_SUBID2, wxPoint(-100,-100), wxSize(0, sz.y) ),
 
2538
      m_fullEditorSize(sz), m_buttonsWidth(0)
 
2539
{
 
2540
    SetBackgroundColour(pg->GetCellBackgroundColour());
 
2541
}
 
2542
 
 
2543
int wxPGMultiButton::GenId( int id ) const
 
2544
{
 
2545
    if ( id < -1 )
 
2546
    {
 
2547
        if ( m_buttons.size() )
 
2548
            id = GetButton(m_buttons.size()-1)->GetId() + 1;
 
2549
        else
 
2550
            id = wxPG_SUBID2;
 
2551
    }
 
2552
    return id;
 
2553
}
 
2554
 
 
2555
#if wxUSE_BMPBUTTON
 
2556
void wxPGMultiButton::Add( const wxBitmap& bitmap, int id )
 
2557
{
 
2558
    id = GenId(id);
 
2559
    wxSize sz = GetSize();
 
2560
    wxButton* button = new wxBitmapButton( this, id, bitmap, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) );
 
2561
    m_buttons.push_back(button);
 
2562
    int bw = button->GetSize().x;
 
2563
    SetSize(wxSize(sz.x+bw,sz.y));
 
2564
    m_buttonsWidth += bw;
 
2565
}
 
2566
#endif
 
2567
 
 
2568
void wxPGMultiButton::Add( const wxString& label, int id )
 
2569
{
 
2570
    id = GenId(id);
 
2571
    wxSize sz = GetSize();
 
2572
    wxButton* button = new wxButton( this, id, label, wxPoint(sz.x, 0), wxSize(sz.y, sz.y) );
 
2573
    m_buttons.push_back(button);
 
2574
    int bw = button->GetSize().x;
 
2575
    SetSize(wxSize(sz.x+bw,sz.y));
 
2576
    m_buttonsWidth += bw;
 
2577
}
 
2578
 
 
2579
// -----------------------------------------------------------------------