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