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