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