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