]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/deprecated/proplist.cpp
set SMALL_FONT for controls here because InheritAttributes() doesn't do it any longer
[wxWidgets.git] / contrib / src / deprecated / proplist.cpp
CommitLineData
4a3bdee6
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: proplist.cpp
3// Purpose: Property list classes
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "proplist.h"
22#endif
23
24// For compilers that support precompilation, includes "wx/wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#include "wx/deprecated/setup.h"
32
33#if wxUSE_PROPSHEET
34
35#ifndef WX_PRECOMP
36 #include "wx/window.h"
37 #include "wx/font.h"
38 #include "wx/button.h"
39 #include "wx/bmpbuttn.h"
40 #include "wx/textctrl.h"
41 #include "wx/listbox.h"
42 #include "wx/settings.h"
43 #include "wx/msgdlg.h"
44 #include "wx/filedlg.h"
45#endif
46
47#include "wx/sizer.h"
48#include "wx/module.h"
49#include "wx/intl.h"
50#include "wx/artprov.h"
51
52#include "wx/colordlg.h"
53#include "wx/deprecated/proplist.h"
54
55#include <ctype.h>
56#include <stdlib.h>
57#include <math.h>
58#include <string.h>
59
bba965d6 60#if !WXWIN_COMPATIBILITY_2_4
c74caa09
MB
61static inline wxChar* copystring(const wxChar* s)
62 { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
bba965d6 63#endif
c74caa09 64
4a3bdee6
JS
65// ----------------------------------------------------------------------------
66// Property text edit control
67// ----------------------------------------------------------------------------
68
69IMPLEMENT_DYNAMIC_CLASS(wxPropertyTextEdit, wxTextCtrl)
70
71wxPropertyTextEdit::wxPropertyTextEdit(wxPropertyListView *v, wxWindow *parent,
72 const wxWindowID id, const wxString& value,
73 const wxPoint& pos, const wxSize& size,
74 long style, const wxString& name):
75 wxTextCtrl(parent, id, value, pos, size, style, wxDefaultValidator, name)
76{
77 m_view = v;
78}
79
80void wxPropertyTextEdit::OnSetFocus()
81{
82}
83
84void wxPropertyTextEdit::OnKillFocus()
85{
86}
87
88// ----------------------------------------------------------------------------
89// Property list view
90// ----------------------------------------------------------------------------
91
b5982058 92bool wxPropertyListView::sm_dialogCancelled = false;
4a3bdee6
JS
93
94IMPLEMENT_DYNAMIC_CLASS(wxPropertyListView, wxPropertyView)
95
96BEGIN_EVENT_TABLE(wxPropertyListView, wxPropertyView)
97 EVT_BUTTON(wxID_OK, wxPropertyListView::OnOk)
98 EVT_BUTTON(wxID_CANCEL, wxPropertyListView::OnCancel)
99 EVT_BUTTON(wxID_HELP, wxPropertyListView::OnHelp)
100 EVT_BUTTON(wxID_PROP_CROSS, wxPropertyListView::OnCross)
101 EVT_BUTTON(wxID_PROP_CHECK, wxPropertyListView::OnCheck)
102 EVT_BUTTON(wxID_PROP_EDIT, wxPropertyListView::OnEdit)
103 EVT_TEXT_ENTER(wxID_PROP_TEXT, wxPropertyListView::OnText)
104 EVT_LISTBOX(wxID_PROP_SELECT, wxPropertyListView::OnPropertySelect)
105 EVT_COMMAND(wxID_PROP_SELECT, wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,
106 wxPropertyListView::OnPropertyDoubleClick)
107 EVT_LISTBOX(wxID_PROP_VALUE_SELECT, wxPropertyListView::OnValueListSelect)
108END_EVENT_TABLE()
109
110wxPropertyListView::wxPropertyListView(wxPanel *propPanel, long flags):wxPropertyView(flags)
111{
112 m_propertyScrollingList = NULL;
113 m_valueList = NULL;
114 m_valueText = NULL;
115 m_editButton = NULL;
116 m_confirmButton = NULL;
117 m_cancelButton = NULL;
118 m_propertyWindow = propPanel;
119 m_managedWindow = NULL;
120
121 m_windowCloseButton = NULL;
122 m_windowCancelButton = NULL;
123 m_windowHelpButton = NULL;
124
b5982058 125 m_detailedEditing = false;
4a3bdee6
JS
126}
127
128wxPropertyListView::~wxPropertyListView()
129{
130}
131
132void wxPropertyListView::ShowView(wxPropertySheet *ps, wxPanel *panel)
133{
134 m_propertySheet = ps;
135
136 AssociatePanel(panel);
137 CreateControls();
138
139 UpdatePropertyList();
140 panel->Layout();
141}
142
143// Update this view of the viewed object, called e.g. by
144// the object itself.
145bool wxPropertyListView::OnUpdateView()
146{
b5982058 147 return true;
4a3bdee6
JS
148}
149
150bool wxPropertyListView::UpdatePropertyList(bool clearEditArea)
151{
152 if (!m_propertyScrollingList || !m_propertySheet)
b5982058 153 return false;
4a3bdee6
JS
154
155 m_propertyScrollingList->Clear();
156 if (clearEditArea)
157 {
158 m_valueList->Clear();
159 m_valueText->SetValue( wxT("") );
160 }
161 wxNode *node = m_propertySheet->GetProperties().GetFirst();
162
163 // Should sort them... later...
164 while (node)
165 {
166 wxProperty *property = (wxProperty *)node->GetData();
167 wxString stringValueRepr(property->GetValue().GetStringRepresentation());
168 wxString paddedString(MakeNameValueString(property->GetName(), stringValueRepr));
169 m_propertyScrollingList->Append(paddedString.GetData(), (void *)property);
170 node = node->GetNext();
171 }
b5982058 172 return true;
4a3bdee6
JS
173}
174
175bool wxPropertyListView::UpdatePropertyDisplayInList(wxProperty *property)
176{
177 if (!m_propertyScrollingList || !m_propertySheet)
b5982058 178 return false;
4a3bdee6
JS
179
180#ifdef __WXMSW__
181 int currentlySelected = m_propertyScrollingList->GetSelection();
182#endif
183// #ifdef __WXMSW__
184 wxString stringValueRepr(property->GetValue().GetStringRepresentation());
185 wxString paddedString(MakeNameValueString(property->GetName(), stringValueRepr));
186 int sel = FindListIndexForProperty(property);
187
188 if (sel > -1)
189 {
190 // Don't update the listbox unnecessarily because it can cause
191 // ugly flashing.
192
193 if (paddedString != m_propertyScrollingList->GetString(sel))
194 m_propertyScrollingList->SetString(sel, paddedString.GetData());
195 }
196//#else
b5982058 197// UpdatePropertyList(false);
4a3bdee6
JS
198//#endif
199
200 // TODO: why is this necessary?
201#ifdef __WXMSW__
202 if (currentlySelected > -1)
203 m_propertyScrollingList->SetSelection(currentlySelected);
204#endif
205
b5982058 206 return true;
4a3bdee6
JS
207}
208
209// Find the wxListBox index corresponding to this property
210int wxPropertyListView::FindListIndexForProperty(wxProperty *property)
211{
212 int n = m_propertyScrollingList->GetCount();
213 for (int i = 0; i < n; i++)
214 {
215 if (property == (wxProperty *)m_propertyScrollingList->wxListBox::GetClientData(i))
216 return i;
217 }
218 return -1;
219}
220
221wxString wxPropertyListView::MakeNameValueString(wxString name, wxString value)
222{
223 wxString theString(name);
224
225 int nameWidth = 25;
226 int padWith = nameWidth - theString.Length();
227 if (padWith < 0)
228 padWith = 0;
229
230 if (GetFlags() & wxPROP_SHOWVALUES)
231 {
232 // Want to pad with spaces
233 theString.Append( wxT(' '), padWith);
234 theString += value;
235 }
236
237 return theString;
238}
239
240// Select and show string representation in validator the given
241// property. NULL resets to show no property.
242bool wxPropertyListView::ShowProperty(wxProperty *property, bool select)
243{
244 if (m_currentProperty)
245 {
246 EndShowingProperty(m_currentProperty);
247 m_currentProperty = NULL;
248 }
249
250 m_valueList->Clear();
251 m_valueText->SetValue( wxT("") );
252
253 if (property)
254 {
255 m_currentProperty = property;
256 BeginShowingProperty(property);
257 }
258 if (select)
259 {
260 int sel = FindListIndexForProperty(property);
261 if (sel > -1)
262 m_propertyScrollingList->SetSelection(sel);
263 }
b5982058 264 return true;
4a3bdee6
JS
265}
266
267// Find appropriate validator and load property into value controls
268bool wxPropertyListView::BeginShowingProperty(wxProperty *property)
269{
270 m_currentValidator = FindPropertyValidator(property);
271 if (!m_currentValidator)
b5982058 272 return false;
4a3bdee6
JS
273
274 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
b5982058 275 return false;
4a3bdee6
JS
276
277 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
278
279 listValidator->OnPrepareControls(property, this, m_propertyWindow);
280 DisplayProperty(property);
b5982058 281 return true;
4a3bdee6
JS
282}
283
284// Find appropriate validator and unload property from value controls
285bool wxPropertyListView::EndShowingProperty(wxProperty *property)
286{
287 if (!m_currentValidator)
b5982058 288 return false;
4a3bdee6
JS
289
290 RetrieveProperty(property);
291
292 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
b5982058 293 return false;
4a3bdee6
JS
294
295 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
296
297 listValidator->OnClearControls(property, this, m_propertyWindow);
298 if (m_detailedEditing)
299 {
300 listValidator->OnClearDetailControls(property, this, m_propertyWindow);
b5982058 301 m_detailedEditing = false;
4a3bdee6 302 }
b5982058 303 return true;
4a3bdee6
JS
304}
305
306void wxPropertyListView::BeginDetailedEditing()
307{
308 if (!m_currentValidator)
309 return;
310 if (!m_currentProperty)
311 return;
312 if (m_detailedEditing)
313 return;
314 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
315 return;
316 if (!m_currentProperty->IsEnabled())
317 return;
318
319 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
320
321 if (listValidator->OnPrepareDetailControls(m_currentProperty, this, m_propertyWindow))
b5982058 322 m_detailedEditing = true;
4a3bdee6
JS
323}
324
325void wxPropertyListView::EndDetailedEditing()
326{
327 if (!m_currentValidator)
328 return;
329 if (!m_currentProperty)
330 return;
331
332 RetrieveProperty(m_currentProperty);
333
334 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
335 return;
336
337 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
338
339 if (m_detailedEditing)
340 {
341 listValidator->OnClearDetailControls(m_currentProperty, this, m_propertyWindow);
b5982058 342 m_detailedEditing = false;
4a3bdee6
JS
343 }
344}
345
346bool wxPropertyListView::DisplayProperty(wxProperty *property)
347{
348 if (!m_currentValidator)
b5982058 349 return false;
4a3bdee6
JS
350
351 if (((m_currentValidator->GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == 0) || !property->IsEnabled())
b5982058 352 m_valueText->SetEditable(false);
4a3bdee6 353 else
b5982058 354 m_valueText->SetEditable(true);
4a3bdee6
JS
355
356 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
b5982058 357 return false;
4a3bdee6
JS
358
359 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
360
361 listValidator->OnDisplayValue(property, this, m_propertyWindow);
b5982058 362 return true;
4a3bdee6
JS
363}
364
365bool wxPropertyListView::RetrieveProperty(wxProperty *property)
366{
367 if (!m_currentValidator)
b5982058 368 return false;
4a3bdee6 369 if (!property->IsEnabled())
b5982058 370 return false;
4a3bdee6
JS
371
372 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
b5982058 373 return false;
4a3bdee6
JS
374
375 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
376
377 if (listValidator->OnCheckValue(property, this, m_propertyWindow))
378 {
379 if (listValidator->OnRetrieveValue(property, this, m_propertyWindow))
380 {
381 UpdatePropertyDisplayInList(property);
382 OnPropertyChanged(property);
383 }
384 }
385 else
386 {
387 // Revert to old value
388 listValidator->OnDisplayValue(property, this, m_propertyWindow);
389 }
b5982058 390 return true;
4a3bdee6
JS
391}
392
393
394bool wxPropertyListView::EditProperty(wxProperty *WXUNUSED(property))
395{
b5982058 396 return true;
4a3bdee6
JS
397}
398
399// Called by the listbox callback
400void wxPropertyListView::OnPropertySelect(wxCommandEvent& WXUNUSED(event))
401{
402 int sel = m_propertyScrollingList->GetSelection();
403 if (sel > -1)
404 {
405 wxProperty *newSel = (wxProperty *)m_propertyScrollingList->wxListBox::GetClientData(sel);
406 if (newSel && newSel != m_currentProperty)
407 {
b5982058 408 ShowProperty(newSel, false);
4a3bdee6
JS
409 }
410 }
411}
412
413bool wxPropertyListView::CreateControls()
414{
415 wxPanel *panel = (wxPanel *)m_propertyWindow;
416
417 wxSize largeButtonSize( 70, 25 );
418 wxSize smallButtonSize( 23, 23 );
419
420 if (m_valueText)
b5982058 421 return true;
4a3bdee6
JS
422
423 if (!panel)
b5982058 424 return false;
4a3bdee6
JS
425
426 wxFont guiFont = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
427
428#ifdef __WXMSW__
429 wxFont *boringFont =
430 wxTheFontList->FindOrCreateFont(guiFont.GetPointSize(), wxMODERN,
b5982058 431 wxNORMAL, wxNORMAL, false, _T("Courier New"));
4a3bdee6
JS
432#else
433 wxFont *boringFont = wxTheFontList->FindOrCreateFont(guiFont.GetPointSize(), wxTELETYPE, wxNORMAL, wxNORMAL);
434#endif
435
436 // May need to be changed in future to eliminate clashes with app.
437 // WHAT WAS THIS FOR?
438// panel->SetClientData((char *)this);
439
440 wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );
441
442 // top row with optional buttons and input line
443
444 wxBoxSizer *topsizer = new wxBoxSizer( wxHORIZONTAL );
445 int buttonborder = 3;
446
447 if (m_buttonFlags & wxPROP_BUTTON_CHECK_CROSS)
448 {
449 wxBitmap tickBitmap = wxArtProvider::GetBitmap(wxART_TICK_MARK);
450 wxBitmap crossBitmap = wxArtProvider::GetBitmap(wxART_CROSS_MARK);
451
452 if ( tickBitmap.Ok() && crossBitmap.Ok() )
453 {
b5982058
VS
454 m_confirmButton = new wxBitmapButton(panel, wxID_PROP_CHECK, tickBitmap, wxDefaultPosition, smallButtonSize );
455 m_cancelButton = new wxBitmapButton(panel, wxID_PROP_CROSS, crossBitmap, wxDefaultPosition, smallButtonSize );
4a3bdee6
JS
456 }
457 else
458 {
b5982058
VS
459 m_confirmButton = new wxButton(panel, wxID_PROP_CHECK, _T(":-)"), wxDefaultPosition, smallButtonSize );
460 m_cancelButton = new wxButton(panel, wxID_PROP_CROSS, _T("X"), wxDefaultPosition, smallButtonSize );
4a3bdee6
JS
461 }
462
463 topsizer->Add( m_confirmButton, 0, wxLEFT|wxTOP|wxBOTTOM | wxEXPAND, buttonborder );
464 topsizer->Add( m_cancelButton, 0, wxLEFT|wxTOP|wxBOTTOM | wxEXPAND, buttonborder );
465 }
466
467 m_valueText = new wxPropertyTextEdit(this, panel, wxID_PROP_TEXT, _T(""),
b5982058
VS
468 wxDefaultPosition, wxSize(wxDefaultSize.x, smallButtonSize.y), wxPROCESS_ENTER);
469 m_valueText->Enable(false);
4a3bdee6
JS
470 topsizer->Add( m_valueText, 1, wxALL | wxEXPAND, buttonborder );
471
472 if (m_buttonFlags & wxPROP_PULLDOWN)
473 {
b5982058
VS
474 m_editButton = new wxButton(panel, wxID_PROP_EDIT, _T("..."), wxDefaultPosition, smallButtonSize);
475 m_editButton->Enable(false);
4a3bdee6
JS
476 topsizer->Add( m_editButton, 0, wxRIGHT|wxTOP|wxBOTTOM | wxEXPAND, buttonborder );
477 }
478
479 mainsizer->Add( topsizer, 0, wxEXPAND );
480
481 // middle section with two list boxes
482
483 m_middleSizer = new wxBoxSizer( wxVERTICAL );
484
b5982058
VS
485 m_valueList = new wxListBox(panel, wxID_PROP_VALUE_SELECT, wxDefaultPosition, wxSize(wxDefaultSize.x, 60));
486 m_valueList->Show(false);
4a3bdee6 487
b5982058 488 m_propertyScrollingList = new wxListBox(panel, wxID_PROP_SELECT, wxDefaultPosition, wxSize(100, 100));
4a3bdee6
JS
489 m_propertyScrollingList->SetFont(* boringFont);
490 m_middleSizer->Add( m_propertyScrollingList, 1, wxALL|wxEXPAND, buttonborder );
491
492 mainsizer->Add( m_middleSizer, 1, wxEXPAND );
493
494 // bottom row with buttons
495
496 if ((m_buttonFlags & wxPROP_BUTTON_OK) ||
497 (m_buttonFlags & wxPROP_BUTTON_CLOSE) ||
498 (m_buttonFlags & wxPROP_BUTTON_CANCEL) ||
499 (m_buttonFlags & wxPROP_BUTTON_HELP))
500 {
501 wxBoxSizer *bottomsizer = new wxBoxSizer( wxHORIZONTAL );
502 buttonborder = 5;
503
504 if (m_buttonFlags & wxPROP_BUTTON_OK)
505 {
b5982058 506 m_windowCloseButton = new wxButton(panel, wxID_OK, _("OK"), wxDefaultPosition, largeButtonSize );
4a3bdee6
JS
507 m_windowCloseButton->SetDefault();
508 m_windowCloseButton->SetFocus();
509 bottomsizer->Add( m_windowCloseButton, 0, wxALL, buttonborder );
510 }
511 else if (m_buttonFlags & wxPROP_BUTTON_CLOSE)
512 {
b5982058 513 m_windowCloseButton = new wxButton(panel, wxID_OK, _("Close"), wxDefaultPosition, largeButtonSize );
4a3bdee6
JS
514 bottomsizer->Add( m_windowCloseButton, 0, wxALL, buttonborder );
515 }
516 if (m_buttonFlags & wxPROP_BUTTON_CANCEL)
517 {
b5982058 518 m_windowCancelButton = new wxButton(panel, wxID_CANCEL, _("Cancel"), wxDefaultPosition, largeButtonSize );
4a3bdee6
JS
519 bottomsizer->Add( m_windowCancelButton, 0, wxALL, buttonborder );
520 }
521 if (m_buttonFlags & wxPROP_BUTTON_HELP)
522 {
b5982058 523 m_windowHelpButton = new wxButton(panel, wxID_HELP, _("Help"), wxDefaultPosition, largeButtonSize );
4a3bdee6
JS
524 bottomsizer->Add( m_windowHelpButton, 0, wxALL, buttonborder );
525 }
526
527 mainsizer->Add( bottomsizer, 0, wxALIGN_RIGHT | wxEXPAND );
528 }
529
530 panel->SetSizer( mainsizer );
531
b5982058 532 return true;
4a3bdee6
JS
533}
534
535void wxPropertyListView::ShowTextControl(bool show)
536{
537 if (m_valueText)
538 m_valueText->Show(show);
539}
540
541void wxPropertyListView::ShowListBoxControl(bool show)
542{
543 if (!m_valueList) return;
544
545 m_valueList->Show(show);
546
547 if (m_buttonFlags & wxPROP_DYNAMIC_VALUE_FIELD)
548 {
549 if (show)
550 m_middleSizer->Prepend( m_valueList, 0, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 3 );
551 else
552 m_middleSizer->Remove( 0 );
553
554 m_propertyWindow->Layout();
555 }
556}
557
558void wxPropertyListView::EnableCheck(bool show)
559{
560 if (m_confirmButton)
561 m_confirmButton->Enable(show);
562}
563
564void wxPropertyListView::EnableCross(bool show)
565{
566 if (m_cancelButton)
567 m_cancelButton->Enable(show);
568}
569
570bool wxPropertyListView::OnClose()
571{
572 // Retrieve the value if any
573 wxCommandEvent event;
574 OnCheck(event);
575
576 delete this;
b5982058 577 return true;
4a3bdee6
JS
578}
579
580void wxPropertyListView::OnValueListSelect(wxCommandEvent& WXUNUSED(event))
581{
582 if (m_currentProperty && m_currentValidator)
583 {
584 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
585 return;
586
587 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
588
589 listValidator->OnValueListSelect(m_currentProperty, this, m_propertyWindow);
590 }
591}
592
593void wxPropertyListView::OnOk(wxCommandEvent& event)
594{
595 // Retrieve the value if any
596 OnCheck(event);
597
b5982058
VS
598 m_managedWindow->Close(true);
599 sm_dialogCancelled = false;
4a3bdee6
JS
600}
601
602void wxPropertyListView::OnCancel(wxCommandEvent& WXUNUSED(event))
603{
604// SetReturnCode(wxID_CANCEL);
b5982058
VS
605 m_managedWindow->Close(true);
606 sm_dialogCancelled = true;
4a3bdee6
JS
607}
608
609void wxPropertyListView::OnHelp(wxCommandEvent& WXUNUSED(event))
610{
611}
612
613void wxPropertyListView::OnCheck(wxCommandEvent& WXUNUSED(event))
614{
615 if (m_currentProperty)
616 {
617 RetrieveProperty(m_currentProperty);
618 }
619}
620
621void wxPropertyListView::OnCross(wxCommandEvent& WXUNUSED(event))
622{
623 if (m_currentProperty && m_currentValidator)
624 {
625 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
626 return;
627
628 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
629
630 // Revert to old value
631 listValidator->OnDisplayValue(m_currentProperty, this, m_propertyWindow);
632 }
633}
634
635void wxPropertyListView::OnPropertyDoubleClick(wxCommandEvent& WXUNUSED(event))
636{
637 if (m_currentProperty && m_currentValidator)
638 {
639 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
640 return;
641
642 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
643
644 // Revert to old value
645 listValidator->OnDoubleClick(m_currentProperty, this, m_propertyWindow);
646 }
647}
648
649void wxPropertyListView::OnEdit(wxCommandEvent& WXUNUSED(event))
650{
651 if (m_currentProperty && m_currentValidator)
652 {
653 if (!m_currentValidator->IsKindOf(CLASSINFO(wxPropertyListValidator)))
654 return;
655
656 wxPropertyListValidator *listValidator = (wxPropertyListValidator *)m_currentValidator;
657
658 listValidator->OnEdit(m_currentProperty, this, m_propertyWindow);
659 }
660}
661
662void wxPropertyListView::OnText(wxCommandEvent& event)
663{
664 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
665 {
666 OnCheck(event);
667 }
668}
669
670// ----------------------------------------------------------------------------
671// Property dialog box
672// ----------------------------------------------------------------------------
673
674IMPLEMENT_DYNAMIC_CLASS(wxPropertyListDialog, wxDialog)
675
676BEGIN_EVENT_TABLE(wxPropertyListDialog, wxDialog)
677 EVT_BUTTON(wxID_CANCEL, wxPropertyListDialog::OnCancel)
678 EVT_CLOSE(wxPropertyListDialog::OnCloseWindow)
679END_EVENT_TABLE()
680
681wxPropertyListDialog::wxPropertyListDialog(wxPropertyListView *v, wxWindow *parent,
682 const wxString& title, const wxPoint& pos,
683 const wxSize& size, long style, const wxString& name):
b5982058 684 wxDialog(parent, wxID_ANY, title, pos, size, style, name)
4a3bdee6
JS
685{
686 m_view = v;
687 m_view->AssociatePanel( ((wxPanel*)this) );
688 m_view->SetManagedWindow(this);
b5982058 689 SetAutoLayout(true);
4a3bdee6
JS
690}
691
692void wxPropertyListDialog::OnCloseWindow(wxCloseEvent& event)
693{
694 if (m_view)
695 {
696 SetReturnCode(wxID_CANCEL);
697 m_view->OnClose();
698 m_view = NULL;
699 this->Destroy();
700 }
701 else
702 {
703 event.Veto();
704 }
705}
706
707void wxPropertyListDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
708{
709 SetReturnCode(wxID_CANCEL);
710 this->Close();
711}
712
713void wxPropertyListDialog::OnDefaultAction(wxControl *WXUNUSED(item))
714{
715/*
716 if (item == m_view->GetPropertyScrollingList())
717 view->OnDoubleClick();
718*/
719}
720
721// Extend event processing to search the view's event table
722bool wxPropertyListDialog::ProcessEvent(wxEvent& event)
723{
724 if ( !m_view || ! m_view->ProcessEvent(event) )
725 return wxEvtHandler::ProcessEvent(event);
726 else
b5982058 727 return true;
4a3bdee6
JS
728}
729
730// ----------------------------------------------------------------------------
731// Property panel
732// ----------------------------------------------------------------------------
733
734IMPLEMENT_DYNAMIC_CLASS(wxPropertyListPanel, wxPanel)
735
736BEGIN_EVENT_TABLE(wxPropertyListPanel, wxPanel)
737 EVT_SIZE(wxPropertyListPanel::OnSize)
738END_EVENT_TABLE()
739
740wxPropertyListPanel::~wxPropertyListPanel()
741{
742}
743
744void wxPropertyListPanel::OnDefaultAction(wxControl *WXUNUSED(item))
745{
746/*
747 if (item == view->GetPropertyScrollingList())
748 view->OnDoubleClick();
749*/
750}
751
752// Extend event processing to search the view's event table
753bool wxPropertyListPanel::ProcessEvent(wxEvent& event)
754{
755 if ( !m_view || ! m_view->ProcessEvent(event) )
756 return wxEvtHandler::ProcessEvent(event);
757 else
b5982058 758 return true;
4a3bdee6
JS
759}
760
761void wxPropertyListPanel::OnSize(wxSizeEvent& WXUNUSED(event))
762{
763 Layout();
764}
765
766// ----------------------------------------------------------------------------
767// Property frame
768// ----------------------------------------------------------------------------
769
770IMPLEMENT_DYNAMIC_CLASS(wxPropertyListFrame, wxFrame)
771
772BEGIN_EVENT_TABLE(wxPropertyListFrame, wxFrame)
773 EVT_CLOSE(wxPropertyListFrame::OnCloseWindow)
774END_EVENT_TABLE()
775
776void wxPropertyListFrame::OnCloseWindow(wxCloseEvent& event)
777{
778 if (m_view)
779 {
780 if (m_propertyPanel)
781 m_propertyPanel->SetView(NULL);
782 m_view->OnClose();
783 m_view = NULL;
784 this->Destroy();
785 }
786 else
787 {
788 event.Veto();
789 }
790}
791
792wxPropertyListPanel *wxPropertyListFrame::OnCreatePanel(wxFrame *parent, wxPropertyListView *v)
793{
794 return new wxPropertyListPanel(v, parent);
795}
796
797bool wxPropertyListFrame::Initialize()
798{
799 m_propertyPanel = OnCreatePanel(this, m_view);
800 if (m_propertyPanel)
801 {
802 m_view->AssociatePanel(m_propertyPanel);
803 m_view->SetManagedWindow(this);
b5982058
VS
804 m_propertyPanel->SetAutoLayout(true);
805 return true;
4a3bdee6
JS
806 }
807 else
b5982058 808 return false;
4a3bdee6
JS
809}
810
811// ----------------------------------------------------------------------------
812// Property list specific validator
813// ----------------------------------------------------------------------------
814
815IMPLEMENT_ABSTRACT_CLASS(wxPropertyListValidator, wxPropertyValidator)
816
817bool wxPropertyListValidator::OnSelect(bool select, wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
818{
b5982058 819// view->GetValueText()->Show(true);
4a3bdee6
JS
820 if (select)
821 OnDisplayValue(property, view, parentWindow);
822
b5982058 823 return true;
4a3bdee6
JS
824}
825
826bool wxPropertyListValidator::OnValueListSelect(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
827{
828 wxString s(view->GetValueList()->GetStringSelection());
829 if (s != wxT(""))
830 {
831 view->GetValueText()->SetValue(s);
832 view->RetrieveProperty(property);
833 }
b5982058 834 return true;
4a3bdee6
JS
835}
836
837bool wxPropertyListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
838{
b5982058 839// view->GetValueText()->Show(true);
4a3bdee6
JS
840 wxString str(property->GetValue().GetStringRepresentation());
841
842 view->GetValueText()->SetValue(str);
b5982058 843 return true;
4a3bdee6
JS
844}
845
846// Called when TICK is pressed or focus is lost or view wants to update
847// the property list.
848// Does the transferance from the property editing area to the property itself
849bool wxPropertyListValidator::OnRetrieveValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
850{
851 if (!view->GetValueText())
b5982058
VS
852 return false;
853 return false;
4a3bdee6
JS
854}
855
856void wxPropertyListValidator::OnEdit(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
857{
858 if (view->GetDetailedEditing())
859 view->EndDetailedEditing();
860 else
861 view->BeginDetailedEditing();
862}
863
864bool wxPropertyListValidator::OnClearControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
865{
866 if (view->GetConfirmButton())
b5982058 867 view->GetConfirmButton()->Enable(false);
4a3bdee6 868 if (view->GetCancelButton())
b5982058 869 view->GetCancelButton()->Enable(false);
4a3bdee6 870 if (view->GetEditButton())
b5982058
VS
871 view->GetEditButton()->Enable(false);
872 return true;
4a3bdee6
JS
873}
874
875// ----------------------------------------------------------------------------
876// Default validators
877// ----------------------------------------------------------------------------
878
879IMPLEMENT_DYNAMIC_CLASS(wxRealListValidator, wxPropertyListValidator)
880
881///
882/// Real number validator
883///
884bool wxRealListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
885{
886 if (m_realMin == 0.0 && m_realMax == 0.0)
b5982058 887 return true;
4a3bdee6
JS
888
889 if (!view->GetValueText())
b5982058 890 return false;
4a3bdee6
JS
891 wxString value(view->GetValueText()->GetValue());
892
893 float val = 0.0;
894 if (!StringToFloat(WXSTRINGCAST value, &val))
895 {
896 wxChar buf[200];
897 wxSprintf(buf, wxT("Value %s is not a valid real number!"), value.GetData());
898 wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 899 return false;
4a3bdee6
JS
900 }
901
902 if (val < m_realMin || val > m_realMax)
903 {
904 wxChar buf[200];
905 wxSprintf(buf, wxT("Value must be a real number between %.2f and %.2f!"), m_realMin, m_realMax);
906 wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 907 return false;
4a3bdee6 908 }
b5982058 909 return true;
4a3bdee6
JS
910}
911
912// Called when TICK is pressed or focus is lost or view wants to update
913// the property list.
914// Does the transferance from the property editing area to the property itself
915bool wxRealListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
916{
917 if (!view->GetValueText())
b5982058 918 return false;
4a3bdee6
JS
919
920 if (wxStrlen(view->GetValueText()->GetValue()) == 0)
b5982058 921 return false;
4a3bdee6
JS
922
923 wxString value(view->GetValueText()->GetValue());
924 float f = (float)wxAtof(value.GetData());
925 property->GetValue() = f;
b5982058 926 return true;
4a3bdee6
JS
927}
928
929bool wxRealListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
930{
931 if (view->GetConfirmButton())
b5982058 932 view->GetConfirmButton()->Enable(true);
4a3bdee6 933 if (view->GetCancelButton())
b5982058 934 view->GetCancelButton()->Enable(true);
4a3bdee6 935 if (view->GetEditButton())
b5982058 936 view->GetEditButton()->Enable(false);
4a3bdee6 937 if (view->GetValueText())
b5982058
VS
938 view->GetValueText()->Enable(true);
939 return true;
4a3bdee6
JS
940}
941
942///
943/// Integer validator
944///
945IMPLEMENT_DYNAMIC_CLASS(wxIntegerListValidator, wxPropertyListValidator)
946
947bool wxIntegerListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
948{
949 if (m_integerMin == 0 && m_integerMax == 0)
b5982058 950 return true;
4a3bdee6
JS
951
952 if (!view->GetValueText())
b5982058 953 return false;
4a3bdee6
JS
954 wxString value(view->GetValueText()->GetValue());
955
956 long val = 0;
957 if (!StringToLong(WXSTRINGCAST value, &val))
958 {
959 wxChar buf[200];
960 wxSprintf(buf, wxT("Value %s is not a valid integer!"), value.GetData());
961 wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 962 return false;
4a3bdee6
JS
963 }
964 if (val < m_integerMin || val > m_integerMax)
965 {
966 wxChar buf[200];
967 wxSprintf(buf, wxT("Value must be an integer between %ld and %ld!"), m_integerMin, m_integerMax);
968 wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 969 return false;
4a3bdee6 970 }
b5982058 971 return true;
4a3bdee6
JS
972}
973
974// Called when TICK is pressed or focus is lost or view wants to update
975// the property list.
976// Does the transferance from the property editing area to the property itself
977bool wxIntegerListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
978{
979 if (!view->GetValueText())
b5982058 980 return false;
4a3bdee6
JS
981
982 if (wxStrlen(view->GetValueText()->GetValue()) == 0)
b5982058 983 return false;
4a3bdee6
JS
984
985 wxString value(view->GetValueText()->GetValue());
986 long val = (long)wxAtoi(value.GetData());
987 property->GetValue() = (long)val;
b5982058 988 return true;
4a3bdee6
JS
989}
990
991bool wxIntegerListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
992{
993 if (view->GetConfirmButton())
b5982058 994 view->GetConfirmButton()->Enable(true);
4a3bdee6 995 if (view->GetCancelButton())
b5982058 996 view->GetCancelButton()->Enable(true);
4a3bdee6 997 if (view->GetEditButton())
b5982058 998 view->GetEditButton()->Enable(false);
4a3bdee6 999 if (view->GetValueText())
b5982058
VS
1000 view->GetValueText()->Enable(true);
1001 return true;
4a3bdee6
JS
1002}
1003
1004///
1005/// boolean validator
1006///
1007IMPLEMENT_DYNAMIC_CLASS(wxBoolListValidator, wxPropertyListValidator)
1008
1009bool wxBoolListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1010{
1011 if (!view->GetValueText())
b5982058 1012 return false;
4a3bdee6
JS
1013 wxString value(view->GetValueText()->GetValue());
1014 if (value != wxT("True") && value != wxT("False"))
1015 {
1016 wxMessageBox(wxT("Value must be True or False!"), wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 1017 return false;
4a3bdee6 1018 }
b5982058 1019 return true;
4a3bdee6
JS
1020}
1021
1022// Called when TICK is pressed or focus is lost or view wants to update
1023// the property list.
1024// Does the transferance from the property editing area to the property itself
1025bool wxBoolListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1026{
1027 if (!view->GetValueText())
b5982058 1028 return false;
4a3bdee6
JS
1029
1030 if (wxStrlen(view->GetValueText()->GetValue()) == 0)
b5982058 1031 return false;
4a3bdee6
JS
1032
1033 wxString value(view->GetValueText()->GetValue());
8552e6f0 1034 bool boolValue = (value == wxT("True"));
b5982058
VS
1035 property->GetValue() = boolValue;
1036 return true;
4a3bdee6
JS
1037}
1038
1039bool wxBoolListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1040{
1041 if (!view->GetValueText())
b5982058 1042 return false;
4a3bdee6
JS
1043 wxString str(property->GetValue().GetStringRepresentation());
1044
1045 view->GetValueText()->SetValue(str);
1046
1047 if (view->GetValueList()->IsShown())
1048 {
1049 view->GetValueList()->SetStringSelection(str);
1050 }
b5982058 1051 return true;
4a3bdee6
JS
1052}
1053
1054bool wxBoolListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1055{
1056 if (view->GetConfirmButton())
b5982058 1057 view->GetConfirmButton()->Enable(false);
4a3bdee6 1058 if (view->GetCancelButton())
b5982058 1059 view->GetCancelButton()->Enable(false);
4a3bdee6 1060 if (view->GetEditButton())
b5982058 1061 view->GetEditButton()->Enable(true);
4a3bdee6 1062 if (view->GetValueText())
b5982058
VS
1063 view->GetValueText()->Enable(false);
1064 return true;
4a3bdee6
JS
1065}
1066
1067bool wxBoolListValidator::OnPrepareDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1068{
1069 if (view->GetValueList())
1070 {
b5982058
VS
1071 view->ShowListBoxControl(true);
1072 view->GetValueList()->Enable(true);
4a3bdee6
JS
1073
1074 view->GetValueList()->Append(wxT("True"));
1075 view->GetValueList()->Append(wxT("False"));
1076 wxChar *currentString = copystring(view->GetValueText()->GetValue());
1077 view->GetValueList()->SetStringSelection(currentString);
1078 delete[] currentString;
1079 }
b5982058 1080 return true;
4a3bdee6
JS
1081}
1082
1083bool wxBoolListValidator::OnClearDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1084{
1085 if (view->GetValueList())
1086 {
1087 view->GetValueList()->Clear();
b5982058
VS
1088 view->ShowListBoxControl(false);
1089 view->GetValueList()->Enable(false);
4a3bdee6 1090 }
b5982058 1091 return true;
4a3bdee6
JS
1092}
1093
1094// Called when the property is double clicked. Extra functionality can be provided,
1095// cycling through possible values.
1096bool wxBoolListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1097{
1098 if (!view->GetValueText())
b5982058 1099 return false;
4a3bdee6 1100 if (property->GetValue().BoolValue())
b5982058 1101 property->GetValue() = false;
4a3bdee6 1102 else
b5982058 1103 property->GetValue() = true;
4a3bdee6
JS
1104 view->DisplayProperty(property);
1105 view->UpdatePropertyDisplayInList(property);
1106 view->OnPropertyChanged(property);
b5982058 1107 return true;
4a3bdee6
JS
1108}
1109
1110///
1111/// String validator
1112///
1113IMPLEMENT_DYNAMIC_CLASS(wxStringListValidator, wxPropertyListValidator)
1114
1115wxStringListValidator::wxStringListValidator(wxStringList *list, long flags):
1116 wxPropertyListValidator(flags)
1117{
1118 m_strings = list;
1119 // If no constraint, we just allow the string to be edited.
1120 if (!m_strings && ((m_validatorFlags & wxPROP_ALLOW_TEXT_EDITING) == 0))
1121 m_validatorFlags |= wxPROP_ALLOW_TEXT_EDITING;
1122}
1123
1124bool wxStringListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1125{
1126 if (!m_strings)
b5982058 1127 return true;
4a3bdee6
JS
1128
1129 if (!view->GetValueText())
b5982058 1130 return false;
4a3bdee6
JS
1131 wxString value(view->GetValueText()->GetValue());
1132
1133 if (!m_strings->Member(value.GetData()))
1134 {
1135 wxString str( wxT("Value ") );
1136 str += value.GetData();
1137 str += wxT(" is not valid.");
1138 wxMessageBox( str.GetData(), wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
b5982058 1139 return false;
4a3bdee6 1140 }
b5982058 1141 return true;
4a3bdee6
JS
1142}
1143
1144// Called when TICK is pressed or focus is lost or view wants to update
1145// the property list.
1146// Does the transferance from the property editing area to the property itself
1147bool wxStringListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1148{
1149 if (!view->GetValueText())
b5982058 1150 return false;
4a3bdee6
JS
1151 wxString value(view->GetValueText()->GetValue());
1152 property->GetValue() = value ;
b5982058 1153 return true;
4a3bdee6
JS
1154}
1155
1156// Called when TICK is pressed or focus is lost or view wants to update
1157// the property list.
1158// Does the transferance from the property editing area to the property itself
1159bool wxStringListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1160{
1161 if (!view->GetValueText())
b5982058 1162 return false;
4a3bdee6
JS
1163 wxString str(property->GetValue().GetStringRepresentation());
1164 view->GetValueText()->SetValue(str);
1165 if (m_strings && view->GetValueList() && view->GetValueList()->IsShown() && view->GetValueList()->GetCount() > 0)
1166 {
1167 view->GetValueList()->SetStringSelection(str);
1168 }
b5982058 1169 return true;
4a3bdee6
JS
1170}
1171
1172bool wxStringListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1173{
1174 // Unconstrained
1175 if (!m_strings)
1176 {
1177 if (view->GetEditButton())
b5982058 1178 view->GetEditButton()->Enable(false);
4a3bdee6 1179 if (view->GetConfirmButton())
b5982058 1180 view->GetConfirmButton()->Enable(true);
4a3bdee6 1181 if (view->GetCancelButton())
b5982058 1182 view->GetCancelButton()->Enable(true);
4a3bdee6 1183 if (view->GetValueText())
b5982058
VS
1184 view->GetValueText()->Enable(true);
1185 return true;
4a3bdee6
JS
1186 }
1187
1188 // Constrained
1189 if (view->GetValueText())
b5982058 1190 view->GetValueText()->Enable(false);
4a3bdee6
JS
1191
1192 if (view->GetEditButton())
b5982058 1193 view->GetEditButton()->Enable(true);
4a3bdee6
JS
1194
1195 if (view->GetConfirmButton())
b5982058 1196 view->GetConfirmButton()->Enable(false);
4a3bdee6 1197 if (view->GetCancelButton())
b5982058
VS
1198 view->GetCancelButton()->Enable(false);
1199 return true;
4a3bdee6
JS
1200}
1201
1202bool wxStringListValidator::OnPrepareDetailControls( wxProperty *property,
1203 wxPropertyListView *view,
1204 wxWindow *WXUNUSED(parentWindow) )
1205{
1206 if (view->GetValueList())
1207 {
b5982058
VS
1208 view->ShowListBoxControl(true);
1209 view->GetValueList()->Enable(true);
4a3bdee6
JS
1210 wxStringList::Node *node = m_strings->GetFirst();
1211 while (node)
1212 {
1213 wxChar *s = node->GetData();
1214 view->GetValueList()->Append(s);
1215 node = node->GetNext();
1216 }
1217 wxChar *currentString = property->GetValue().StringValue();
1218 view->GetValueList()->SetStringSelection(currentString);
1219 }
b5982058 1220 return true;
4a3bdee6
JS
1221}
1222
1223bool wxStringListValidator::OnClearDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1224{
1225 if (!m_strings)
1226 {
b5982058 1227 return true;
4a3bdee6
JS
1228 }
1229
1230 if (view->GetValueList())
1231 {
1232 view->GetValueList()->Clear();
b5982058
VS
1233 view->ShowListBoxControl(false);
1234 view->GetValueList()->Enable(false);
4a3bdee6 1235 }
b5982058 1236 return true;
4a3bdee6
JS
1237}
1238
1239// Called when the property is double clicked. Extra functionality can be provided,
1240// cycling through possible values.
1241bool wxStringListValidator::OnDoubleClick( wxProperty *property,
1242 wxPropertyListView *view,
1243 wxWindow *WXUNUSED(parentWindow) )
1244{
1245 if (!view->GetValueText())
b5982058 1246 return false;
4a3bdee6 1247 if (!m_strings)
b5982058 1248 return false;
4a3bdee6
JS
1249
1250 wxStringList::Node *node = m_strings->GetFirst();
1251 wxChar *currentString = property->GetValue().StringValue();
1252 while (node)
1253 {
1254 wxChar *s = node->GetData();
1255 if (wxStrcmp(s, currentString) == 0)
1256 {
8552e6f0 1257 wxChar *nextString;
4a3bdee6
JS
1258 if (node->GetNext())
1259 nextString = node->GetNext()->GetData();
1260 else
1261 nextString = m_strings->GetFirst()->GetData();
1262 property->GetValue() = wxString(nextString);
1263 view->DisplayProperty(property);
1264 view->UpdatePropertyDisplayInList(property);
1265 view->OnPropertyChanged(property);
b5982058 1266 return true;
4a3bdee6
JS
1267 }
1268 else node = node->GetNext();
1269 }
b5982058 1270 return true;
4a3bdee6
JS
1271}
1272
1273///
1274/// Filename validator
1275///
1276IMPLEMENT_DYNAMIC_CLASS(wxFilenameListValidator, wxPropertyListValidator)
1277
1278wxFilenameListValidator::wxFilenameListValidator(wxString message , wxString wildcard, long flags):
1279 wxPropertyListValidator(flags), m_filenameWildCard(wildcard), m_filenameMessage(message)
1280{
1281}
1282
1283wxFilenameListValidator::~wxFilenameListValidator()
1284{
1285}
1286
1287bool wxFilenameListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1288{
b5982058 1289 return true;
4a3bdee6
JS
1290}
1291
1292// Called when TICK is pressed or focus is lost or view wants to update
1293// the property list.
1294// Does the transferance from the property editing area to the property itself
1295bool wxFilenameListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1296{
1297 if (!view->GetValueText())
b5982058 1298 return false;
4a3bdee6
JS
1299 wxString value(view->GetValueText()->GetValue());
1300 property->GetValue() = value ;
b5982058 1301 return true;
4a3bdee6
JS
1302}
1303
1304// Called when TICK is pressed or focus is lost or view wants to update
1305// the property list.
1306// Does the transferance from the property editing area to the property itself
1307bool wxFilenameListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1308{
1309 if (!view->GetValueText())
b5982058 1310 return false;
4a3bdee6
JS
1311 wxString str(property->GetValue().GetStringRepresentation());
1312 view->GetValueText()->SetValue(str);
b5982058 1313 return true;
4a3bdee6
JS
1314}
1315
1316// Called when the property is double clicked. Extra functionality can be provided,
1317// cycling through possible values.
1318bool wxFilenameListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1319{
1320 if (!view->GetValueText())
b5982058 1321 return false;
4a3bdee6 1322 OnEdit(property, view, parentWindow);
b5982058 1323 return true;
4a3bdee6
JS
1324}
1325
1326bool wxFilenameListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1327{
1328 if (view->GetConfirmButton())
b5982058 1329 view->GetConfirmButton()->Enable(true);
4a3bdee6 1330 if (view->GetCancelButton())
b5982058 1331 view->GetCancelButton()->Enable(true);
4a3bdee6 1332 if (view->GetEditButton())
b5982058 1333 view->GetEditButton()->Enable(true);
4a3bdee6
JS
1334 if (view->GetValueText())
1335 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
b5982058 1336 return true;
4a3bdee6
JS
1337}
1338
1339void wxFilenameListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1340{
1341 if (!view->GetValueText())
1342 return;
1343
1344 wxString s = wxFileSelector(
1345 m_filenameMessage.GetData(),
1346 wxPathOnly(property->GetValue().StringValue()),
1347 wxFileNameFromPath(property->GetValue().StringValue()),
1348 NULL,
1349 m_filenameWildCard.GetData(),
1350 0,
1351 parentWindow);
1352 if (s != wxT(""))
1353 {
1354 property->GetValue() = s;
1355 view->DisplayProperty(property);
1356 view->UpdatePropertyDisplayInList(property);
1357 view->OnPropertyChanged(property);
1358 }
1359}
1360
1361///
1362/// Colour validator
1363///
1364IMPLEMENT_DYNAMIC_CLASS(wxColourListValidator, wxPropertyListValidator)
1365
1366wxColourListValidator::wxColourListValidator(long flags):
1367 wxPropertyListValidator(flags)
1368{
1369}
1370
1371wxColourListValidator::~wxColourListValidator()
1372{
1373}
1374
1375bool wxColourListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1376{
b5982058 1377 return true;
4a3bdee6
JS
1378}
1379
1380// Called when TICK is pressed or focus is lost or view wants to update
1381// the property list.
1382// Does the transferance from the property editing area to the property itself
1383bool wxColourListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1384{
1385 if (!view->GetValueText())
b5982058 1386 return false;
4a3bdee6
JS
1387 wxString value(view->GetValueText()->GetValue());
1388
1389 property->GetValue() = value ;
b5982058 1390 return true;
4a3bdee6
JS
1391}
1392
1393// Called when TICK is pressed or focus is lost or view wants to update
1394// the property list.
1395// Does the transferance from the property editing area to the property itself
1396bool wxColourListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1397{
1398 if (!view->GetValueText())
b5982058 1399 return false;
4a3bdee6
JS
1400 wxString str(property->GetValue().GetStringRepresentation());
1401 view->GetValueText()->SetValue(str);
b5982058 1402 return true;
4a3bdee6
JS
1403}
1404
1405// Called when the property is double clicked. Extra functionality can be provided,
1406// cycling through possible values.
1407bool wxColourListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1408{
1409 if (!view->GetValueText())
b5982058 1410 return false;
4a3bdee6 1411 OnEdit(property, view, parentWindow);
b5982058 1412 return true;
4a3bdee6
JS
1413}
1414
1415bool wxColourListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1416{
1417 if (view->GetConfirmButton())
b5982058 1418 view->GetConfirmButton()->Enable(true);
4a3bdee6 1419 if (view->GetCancelButton())
b5982058 1420 view->GetCancelButton()->Enable(true);
4a3bdee6 1421 if (view->GetEditButton())
b5982058 1422 view->GetEditButton()->Enable(true);
4a3bdee6
JS
1423 if (view->GetValueText())
1424 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
b5982058 1425 return true;
4a3bdee6
JS
1426}
1427
1428void wxColourListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1429{
1430 if (!view->GetValueText())
1431 return;
1432
1433 wxChar *s = property->GetValue().StringValue();
1434 int r = 0;
1435 int g = 0;
1436 int b = 0;
1437 if (s)
1438 {
1439 r = wxHexToDec(s);
1440 g = wxHexToDec(s+2);
1441 b = wxHexToDec(s+4);
1442 }
1443
1444 wxColour col(r,g,b);
1445
1446 wxColourData data;
b5982058 1447 data.SetChooseFull(true);
4a3bdee6
JS
1448 data.SetColour(col);
1449
1450 for (int i = 0; i < 16; i++)
1451 {
1452 wxColour colour(i*16, i*16, i*16);
1453 data.SetCustomColour(i, colour);
1454 }
1455
1456 wxColourDialog dialog(parentWindow, &data);
1457 if (dialog.ShowModal() != wxID_CANCEL)
1458 {
1459 wxColourData retData = dialog.GetColourData();
1460 col = retData.GetColour();
1461
1462 wxChar buf[7];
1463 wxDecToHex(col.Red(), buf);
1464 wxDecToHex(col.Green(), buf+2);
1465 wxDecToHex(col.Blue(), buf+4);
1466
1467 property->GetValue() = wxString(buf);
1468 view->DisplayProperty(property);
1469 view->UpdatePropertyDisplayInList(property);
1470 view->OnPropertyChanged(property);
1471 }
1472}
1473
1474///
1475/// List of strings validator. For this we need more user interface than
1476/// we get with a property list; so create a new dialog for editing the list.
1477///
1478IMPLEMENT_DYNAMIC_CLASS(wxListOfStringsListValidator, wxPropertyListValidator)
1479
1480wxListOfStringsListValidator::wxListOfStringsListValidator(long flags):
1481 wxPropertyListValidator(flags)
1482{
1483}
1484
1485bool wxListOfStringsListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1486{
1487 // No constraints for an arbitrary, user-editable list of strings.
b5982058 1488 return true;
4a3bdee6
JS
1489}
1490
1491// Called when TICK is pressed or focus is lost or view wants to update
1492// the property list.
1493// Does the transferance from the property editing area to the property itself.
1494// In this case, the user cannot directly edit the string list.
1495bool wxListOfStringsListValidator::OnRetrieveValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1496{
b5982058 1497 return true;
4a3bdee6
JS
1498}
1499
1500bool wxListOfStringsListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1501{
1502 if (!view->GetValueText())
b5982058 1503 return false;
4a3bdee6
JS
1504 wxString str(property->GetValue().GetStringRepresentation());
1505 view->GetValueText()->SetValue(str);
b5982058 1506 return true;
4a3bdee6
JS
1507}
1508
1509bool wxListOfStringsListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1510{
1511 if (view->GetEditButton())
b5982058 1512 view->GetEditButton()->Enable(true);
4a3bdee6 1513 if (view->GetValueText())
b5982058 1514 view->GetValueText()->Enable(false);
4a3bdee6
JS
1515
1516 if (view->GetConfirmButton())
b5982058 1517 view->GetConfirmButton()->Enable(false);
4a3bdee6 1518 if (view->GetCancelButton())
b5982058
VS
1519 view->GetCancelButton()->Enable(false);
1520 return true;
4a3bdee6
JS
1521}
1522
1523// Called when the property is double clicked. Extra functionality can be provided,
1524// cycling through possible values.
1525bool wxListOfStringsListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1526{
1527 OnEdit(property, view, parentWindow);
b5982058 1528 return true;
4a3bdee6
JS
1529}
1530
1531void wxListOfStringsListValidator::OnEdit( wxProperty *property,
1532 wxPropertyListView *view,
1533 wxWindow *parentWindow )
1534{
1535 // Convert property value to a list of strings for editing
1536 wxStringList *stringList = new wxStringList;
1537
1538 wxPropertyValue *expr = property->GetValue().GetFirst();
1539 while (expr)
1540 {
1541 wxChar *s = expr->StringValue();
1542 if (s)
1543 stringList->Add(s);
1544 expr = expr->GetNext();
1545 }
1546
1547 wxString title(wxT("Editing "));
1548 title += property->GetName();
1549
1550 if (EditStringList(parentWindow, stringList, title.GetData()))
1551 {
1552 wxPropertyValue& oldValue = property->GetValue();
1553 oldValue.ClearList();
1554 wxStringList::Node *node = stringList->GetFirst();
1555 while (node)
1556 {
1557 wxChar *s = node->GetData();
1558 oldValue.Append(new wxPropertyValue(s));
1559
1560 node = node->GetNext();
1561 }
1562
1563 view->DisplayProperty(property);
1564 view->UpdatePropertyDisplayInList(property);
1565 view->OnPropertyChanged(property);
1566 }
1567 delete stringList;
1568}
1569
1570class wxPropertyStringListEditorDialog: public wxDialog
1571{
1572 public:
1573 wxPropertyStringListEditorDialog(wxWindow *parent, const wxString& title,
1574 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1575 long windowStyle = wxDEFAULT_DIALOG_STYLE, const wxString& name = wxT("stringEditorDialogBox")):
b5982058 1576 wxDialog(parent, wxID_ANY, title, pos, size, windowStyle, name)
4a3bdee6
JS
1577 {
1578 m_stringList = NULL;
1579 m_stringText = NULL;
1580 m_listBox = NULL;
b5982058 1581 sm_dialogCancelled = false;
4a3bdee6
JS
1582 m_currentSelection = -1;
1583 }
1584 ~wxPropertyStringListEditorDialog(void) {}
1585 void OnCloseWindow(wxCloseEvent& event);
1586 void SaveCurrentSelection(void);
1587 void ShowCurrentSelection(void);
1588
1589 void OnOK(wxCommandEvent& event);
1590 void OnCancel(wxCommandEvent& event);
1591 void OnAdd(wxCommandEvent& event);
1592 void OnDelete(wxCommandEvent& event);
1593 void OnStrings(wxCommandEvent& event);
1594 void OnText(wxCommandEvent& event);
1595
1596public:
1597 wxStringList* m_stringList;
1598 wxListBox* m_listBox;
1599 wxTextCtrl* m_stringText;
1600 static bool sm_dialogCancelled;
1601 int m_currentSelection;
1602DECLARE_EVENT_TABLE()
1603};
1604
1605#define wxID_PROP_SL_ADD 3000
1606#define wxID_PROP_SL_DELETE 3001
1607#define wxID_PROP_SL_STRINGS 3002
1608#define wxID_PROP_SL_TEXT 3003
1609
1610BEGIN_EVENT_TABLE(wxPropertyStringListEditorDialog, wxDialog)
1611 EVT_BUTTON(wxID_OK, wxPropertyStringListEditorDialog::OnOK)
1612 EVT_BUTTON(wxID_CANCEL, wxPropertyStringListEditorDialog::OnCancel)
1613 EVT_BUTTON(wxID_PROP_SL_ADD, wxPropertyStringListEditorDialog::OnAdd)
1614 EVT_BUTTON(wxID_PROP_SL_DELETE, wxPropertyStringListEditorDialog::OnDelete)
1615 EVT_LISTBOX(wxID_PROP_SL_STRINGS, wxPropertyStringListEditorDialog::OnStrings)
1616 EVT_TEXT_ENTER(wxID_PROP_SL_TEXT, wxPropertyStringListEditorDialog::OnText)
1617 EVT_CLOSE(wxPropertyStringListEditorDialog::OnCloseWindow)
1618END_EVENT_TABLE()
1619
1620class wxPropertyStringListEditorText: public wxTextCtrl
1621{
1622 public:
1623 wxPropertyStringListEditorText(wxWindow *parent, wxWindowID id, const wxString& val,
1624 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1625 long windowStyle = 0, const wxString& name = wxT("text")):
1626 wxTextCtrl(parent, id, val, pos, size, windowStyle, wxDefaultValidator, name)
1627 {
1628 }
1629 void OnKillFocus()
1630 {
1631 wxPropertyStringListEditorDialog *dialog = (wxPropertyStringListEditorDialog *)GetParent();
1632 dialog->SaveCurrentSelection();
1633 }
1634};
1635
b5982058 1636bool wxPropertyStringListEditorDialog::sm_dialogCancelled = false;
4a3bdee6
JS
1637
1638// Edit the string list.
1639bool wxListOfStringsListValidator::EditStringList(wxWindow *parent, wxStringList *stringList, const wxChar *title)
1640{
1641 int largeButtonWidth = 60;
1642 int largeButtonHeight = 25;
1643
1644 wxBeginBusyCursor();
1645 wxPropertyStringListEditorDialog *dialog = new wxPropertyStringListEditorDialog(parent,
1646 title, wxPoint(10, 10), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL);
1647
1648 dialog->m_stringList = stringList;
1649
1650 dialog->m_listBox = new wxListBox(dialog, wxID_PROP_SL_STRINGS,
b5982058 1651 wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
4a3bdee6
JS
1652
1653 dialog->m_stringText = new wxPropertyStringListEditorText(dialog,
1654 wxID_PROP_SL_TEXT, wxT(""), wxPoint(5, 240),
b5982058
VS
1655 wxSize(300, wxDefaultSize.y), wxPROCESS_ENTER);
1656 dialog->m_stringText->Enable(false);
4a3bdee6 1657
b5982058
VS
1658 wxButton *addButton = new wxButton(dialog, wxID_PROP_SL_ADD, wxT("Add"), wxDefaultPosition, wxSize(largeButtonWidth, largeButtonHeight));
1659 wxButton *deleteButton = new wxButton(dialog, wxID_PROP_SL_DELETE, wxT("Delete"), wxDefaultPosition, wxSize(largeButtonWidth, largeButtonHeight));
1660 wxButton *cancelButton = new wxButton(dialog, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxSize(largeButtonWidth, largeButtonHeight));
1661 wxButton *okButton = new wxButton(dialog, wxID_OK, wxT("OK"), wxDefaultPosition, wxSize(largeButtonWidth, largeButtonHeight));
4a3bdee6
JS
1662
1663#ifndef __WXGTK__
1664 okButton->SetDefault();
1665#endif
1666
b5982058
VS
1667 wxBoxSizer *m_bottom_sizer = new wxBoxSizer( wxHORIZONTAL );
1668 m_bottom_sizer->Add(addButton, 0, wxALL | wxALIGN_LEFT, 2 );
1669 m_bottom_sizer->Add(deleteButton, 0, wxALL | wxALIGN_LEFT, 2 );
1670 m_bottom_sizer->Add(1, 1, 1, wxEXPAND | wxALL);
1671 m_bottom_sizer->Add(cancelButton, 0, wxALL | wxALIGN_RIGHT, 2 );
1672 m_bottom_sizer->Add(okButton, 0, wxALL | wxALIGN_RIGHT, 2 );
1673
1674 wxBoxSizer *m_sizer = new wxBoxSizer( wxVERTICAL );
1675 m_sizer->Add(dialog->m_listBox, 1, wxEXPAND | wxALL, 2 );
1676 m_sizer->Add(dialog->m_stringText, 0, wxEXPAND | wxALL, 2 );
1677 m_sizer->Add(m_bottom_sizer, 0, wxEXPAND | wxALL , 0 );
1678
1679 dialog->SetSizer( m_sizer );
1680 m_sizer->SetSizeHints( dialog );
4a3bdee6
JS
1681
1682 wxStringList::Node *node = stringList->GetFirst();
1683 while (node)
1684 {
1685 wxChar *str = node->GetData();
1686 // Save node as client data for each listbox item
1687 dialog->m_listBox->Append(str, (wxChar *)node);
1688 node = node->GetNext();
1689 }
1690
1691 dialog->SetClientSize(310, 305);
1692 dialog->Layout();
1693
1694 dialog->Centre(wxBOTH);
1695 wxEndBusyCursor();
1696 if (dialog->ShowModal() == wxID_CANCEL)
b5982058 1697 return false;
4a3bdee6 1698 else
b5982058 1699 return true;
4a3bdee6
JS
1700}
1701
1702/*
1703 * String list editor callbacks
1704 *
1705 */
1706
1707void wxPropertyStringListEditorDialog::OnStrings(wxCommandEvent& WXUNUSED(event))
1708{
1709 int sel = m_listBox->GetSelection();
1710 if (sel > -1)
1711 {
1712 m_currentSelection = sel;
1713
1714 ShowCurrentSelection();
1715 }
1716}
1717
1718void wxPropertyStringListEditorDialog::OnDelete(wxCommandEvent& WXUNUSED(event))
1719{
1720 int sel = m_listBox->GetSelection();
1721 if (sel == -1)
1722 return;
1723
1724 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(sel);
1725 if (!node)
1726 return;
1727
1728 m_listBox->Delete(sel);
1729 delete[] (wxChar *)node->GetData();
1730 delete node;
1731 m_currentSelection = -1;
1732 m_stringText->SetValue(_T(""));
1733}
1734
1735void wxPropertyStringListEditorDialog::OnAdd(wxCommandEvent& WXUNUSED(event))
1736{
1737 SaveCurrentSelection();
1738
1739 wxString initialText;
1740 wxNode *node = m_stringList->Add(initialText);
1741 m_listBox->Append(initialText, (void *)node);
1742 m_currentSelection = m_stringList->GetCount() - 1;
1743 m_listBox->SetSelection(m_currentSelection);
1744 ShowCurrentSelection();
1745 m_stringText->SetFocus();
1746}
1747
1748void wxPropertyStringListEditorDialog::OnOK(wxCommandEvent& WXUNUSED(event))
1749{
1750 SaveCurrentSelection();
1751 EndModal(wxID_OK);
b5982058 1752 // Close(true);
4a3bdee6
JS
1753 this->Destroy();
1754}
1755
1756void wxPropertyStringListEditorDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
1757{
b5982058 1758 sm_dialogCancelled = true;
4a3bdee6 1759 EndModal(wxID_CANCEL);
b5982058 1760// Close(true);
4a3bdee6
JS
1761 this->Destroy();
1762}
1763
1764void wxPropertyStringListEditorDialog::OnText(wxCommandEvent& event)
1765{
1766 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
1767 {
1768 SaveCurrentSelection();
1769 }
1770}
1771
1772void
1773wxPropertyStringListEditorDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1774{
1775 SaveCurrentSelection();
1776
1777 Destroy();
1778}
1779
1780void wxPropertyStringListEditorDialog::SaveCurrentSelection()
1781{
1782 if (m_currentSelection == -1)
1783 return;
1784
1785 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1786 if (!node)
1787 return;
1788
1789 wxString txt(m_stringText->GetValue());
1790 if (node->GetData())
1791 delete[] (wxChar *)node->GetData();
1792 node->SetData((wxObject *)wxStrdup(txt));
1793
1794 m_listBox->SetString(m_currentSelection, (wxChar *)node->GetData());
1795}
1796
1797void wxPropertyStringListEditorDialog::ShowCurrentSelection()
1798{
1799 if (m_currentSelection == -1)
1800 {
1801 m_stringText->SetValue(wxT(""));
1802 return;
1803 }
1804 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1805 wxChar *txt = (wxChar *)node->GetData();
1806 m_stringText->SetValue(txt);
b5982058 1807 m_stringText->Enable(true);
4a3bdee6
JS
1808}
1809
1810
1811#endif // wxUSE_PROPSHEET