]> git.saurik.com Git - wxWidgets.git/blob - src/generic/proplist.cpp
Added Property List classes to main library; added proplist sample; merged
[wxWidgets.git] / src / generic / proplist.cpp
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
52 IMPLEMENT_CLASS(wxPropertyTextEdit, wxTextCtrl)
53
54 wxPropertyTextEdit::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
63 void wxPropertyTextEdit::OnSetFocus(void)
64 {
65 }
66
67 void wxPropertyTextEdit::OnKillFocus(void)
68 {
69 }
70
71 /*
72 * Property list view
73 */
74
75 IMPLEMENT_DYNAMIC_CLASS(wxPropertyListView, wxPropertyView)
76
77 BEGIN_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)
88 END_EVENT_TABLE()
89
90 bool wxPropertyListView::sm_dialogCancelled = FALSE;
91 wxBitmap *wxPropertyListView::sm_tickBitmap = NULL;
92 wxBitmap *wxPropertyListView::sm_crossBitmap = NULL;
93
94 wxPropertyListView::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
112 wxPropertyListView::~wxPropertyListView(void)
113 {
114 /*
115 if (m_tickBitmap)
116 delete m_tickBitmap;
117 if (m_crossBitmap)
118 delete m_crossBitmap;
119 */
120 }
121
122 void 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.
135 bool wxPropertyListView::OnUpdateView(void)
136 {
137 return TRUE;
138 }
139
140 bool 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
166 bool 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
199 int 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
210 wxString 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.
231 bool 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
257 bool 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
274 bool 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
295 void 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
314 void 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
335 bool 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
354 bool 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
383 bool wxPropertyListView::EditProperty(wxProperty *WXUNUSED(property))
384 {
385 return TRUE;
386 }
387
388 // Called by the listbox callback
389 void 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
402 bool 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
654 void wxPropertyListView::ShowTextControl(bool show)
655 {
656 if (m_valueText)
657 m_valueText->Show(show);
658 }
659
660 void 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
688 void wxPropertyListView::EnableCheck(bool show)
689 {
690 if (m_confirmButton)
691 m_confirmButton->Enable(show);
692 }
693
694 void wxPropertyListView::EnableCross(bool show)
695 {
696 if (m_cancelButton)
697 m_cancelButton->Enable(show);
698 }
699
700 bool 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
710 void 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
723 void wxPropertyListView::OnOk(wxCommandEvent& event)
724 {
725 // Retrieve the value if any
726 OnCheck(event);
727
728 m_managedWindow->Close(TRUE);
729 }
730
731 void wxPropertyListView::OnCancel(wxCommandEvent& WXUNUSED(event))
732 {
733 // SetReturnCode(wxID_CANCEL);
734 m_managedWindow->Close(TRUE);
735 sm_dialogCancelled = TRUE;
736 }
737
738 void wxPropertyListView::OnHelp(wxCommandEvent& WXUNUSED(event))
739 {
740 }
741
742 void wxPropertyListView::OnCheck(wxCommandEvent& WXUNUSED(event))
743 {
744 if (m_currentProperty)
745 {
746 RetrieveProperty(m_currentProperty);
747 }
748 }
749
750 void 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
764 void 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
778 void 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
791 void 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
803 IMPLEMENT_CLASS(wxPropertyListDialog, wxDialog)
804
805 BEGIN_EVENT_TABLE(wxPropertyListDialog, wxDialog)
806 EVT_BUTTON(wxID_CANCEL, wxPropertyListDialog::OnCancel)
807 END_EVENT_TABLE()
808
809 wxPropertyListDialog::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
820 bool 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
833 void wxPropertyListDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
834 {
835 SetReturnCode(wxID_CANCEL);
836 this->Close();
837 }
838
839 void 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
848 bool 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
860 IMPLEMENT_CLASS(wxPropertyListPanel, wxPanel)
861
862 BEGIN_EVENT_TABLE(wxPropertyListPanel, wxPanel)
863 EVT_SIZE(wxPropertyListPanel::OnSize)
864 END_EVENT_TABLE()
865
866 wxPropertyListPanel::~wxPropertyListPanel()
867 {
868 }
869
870 void 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
879 bool 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
887 void wxPropertyListPanel::OnSize(wxSizeEvent& WXUNUSED(event))
888 {
889 Layout();
890 }
891
892 /*
893 * Property frame
894 */
895
896 IMPLEMENT_CLASS(wxPropertyListFrame, wxFrame)
897
898 bool 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
912 wxPropertyListPanel *wxPropertyListFrame::OnCreatePanel(wxFrame *parent, wxPropertyListView *v)
913 {
914 return new wxPropertyListPanel(v, parent);
915 }
916
917 bool 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
935 IMPLEMENT_ABSTRACT_CLASS(wxPropertyListValidator, wxPropertyValidator)
936
937 bool 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
946 bool 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
957 bool 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
969 bool wxPropertyListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
970 {
971 if (!view->GetValueText())
972 return FALSE;
973 return FALSE;
974 }
975
976 void wxPropertyListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
977 {
978 if (view->GetDetailedEditing())
979 view->EndDetailedEditing();
980 else
981 view->BeginDetailedEditing();
982 }
983
984 bool 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
999 IMPLEMENT_DYNAMIC_CLASS(wxRealListValidator, wxPropertyListValidator)
1000
1001 ///
1002 /// Real number validator
1003 ///
1004 bool 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
1035 bool 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
1049 bool 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 ///
1065 IMPLEMENT_DYNAMIC_CLASS(wxIntegerListValidator, wxPropertyListValidator)
1066
1067 bool 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
1097 bool 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
1111 bool 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 ///
1127 IMPLEMENT_DYNAMIC_CLASS(wxBoolListValidator, wxPropertyListValidator)
1128
1129 bool 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
1145 bool 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
1163 bool 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
1178 bool 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
1191 bool 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
1207 bool 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.
1220 bool 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 ///
1237 IMPLEMENT_DYNAMIC_CLASS(wxStringListValidator, wxPropertyListValidator)
1238
1239 wxStringListValidator::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
1248 bool 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
1271 bool 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
1283 bool 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
1296 bool 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
1326 bool 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
1345 bool 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.
1363 bool 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 ///
1396 IMPLEMENT_DYNAMIC_CLASS(wxFilenameListValidator, wxPropertyListValidator)
1397
1398 wxFilenameListValidator::wxFilenameListValidator(wxString message , wxString wildcard, long flags):
1399 wxPropertyListValidator(flags), m_filenameWildCard(wildcard), m_filenameMessage(message)
1400 {
1401 }
1402
1403 wxFilenameListValidator::~wxFilenameListValidator(void)
1404 {
1405 }
1406
1407 bool 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
1415 bool 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
1427 bool 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.
1438 bool 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
1446 bool 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
1459 void 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 ///
1484 IMPLEMENT_DYNAMIC_CLASS(wxColourListValidator, wxPropertyListValidator)
1485
1486 wxColourListValidator::wxColourListValidator(long flags):
1487 wxPropertyListValidator(flags)
1488 {
1489 }
1490
1491 wxColourListValidator::~wxColourListValidator(void)
1492 {
1493 }
1494
1495 bool 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
1503 bool 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
1516 bool 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.
1527 bool 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
1535 bool 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
1548 void 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 ///
1598 IMPLEMENT_DYNAMIC_CLASS(wxListOfStringsListValidator, wxPropertyListValidator)
1599
1600 wxListOfStringsListValidator::wxListOfStringsListValidator(long flags):
1601 wxPropertyListValidator(flags)
1602 {
1603 }
1604
1605 bool 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.
1615 bool wxListOfStringsListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1616 {
1617 return TRUE;
1618 }
1619
1620 bool 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
1629 bool 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.
1645 bool wxListOfStringsListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1646 {
1647 OnEdit(property, view, parentWindow);
1648 return TRUE;
1649 }
1650
1651 void 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
1688 class 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
1714 public:
1715 wxStringList* m_stringList;
1716 wxListBox* m_listBox;
1717 wxTextCtrl* m_stringText;
1718 static bool sm_dialogCancelled;
1719 int m_currentSelection;
1720 DECLARE_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
1728 BEGIN_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)
1735 END_EVENT_TABLE()
1736
1737 class 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
1753 bool wxPropertyStringListEditorDialog::sm_dialogCancelled = FALSE;
1754
1755 // Edit the string list.
1756 bool 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
1850 void 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
1861 void 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
1878 void 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
1891 void wxPropertyStringListEditorDialog::OnOK(wxCommandEvent& WXUNUSED(event))
1892 {
1893 SaveCurrentSelection();
1894 EndModal(wxID_OK);
1895 Close(TRUE);
1896 }
1897
1898 void wxPropertyStringListEditorDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
1899 {
1900 sm_dialogCancelled = TRUE;
1901 EndModal(wxID_CANCEL);
1902 Close(TRUE);
1903 }
1904
1905 void wxPropertyStringListEditorDialog::OnText(wxCommandEvent& event)
1906 {
1907 if (event.GetEventType() == wxEVENT_TYPE_TEXT_ENTER_COMMAND)
1908 {
1909 SaveCurrentSelection();
1910 }
1911 }
1912
1913 bool wxPropertyStringListEditorDialog::OnClose(void)
1914 {
1915 SaveCurrentSelection();
1916 return TRUE;
1917 }
1918
1919 void 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
1936 void 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