]> git.saurik.com Git - wxWidgets.git/blob - src/generic/proplist.cpp
another attempt to improve combobox behaviour
[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 EVT_CLOSE(wxPropertyListDialog::OnCloseWindow)
812 END_EVENT_TABLE()
813
814 wxPropertyListDialog::wxPropertyListDialog(wxPropertyListView *v, wxWindow *parent,
815 const wxString& title, const wxPoint& pos,
816 const wxSize& size, long style, const wxString& name):
817 wxDialog(parent, -1, title, pos, size, style, name)
818 {
819 m_view = v;
820 m_view->AssociatePanel( ((wxPanel*)this) );
821 m_view->SetManagedWindow(this);
822 SetAutoLayout(TRUE);
823 }
824
825 void wxPropertyListDialog::OnCloseWindow(wxCloseEvent& event)
826 {
827 if (m_view)
828 {
829 SetReturnCode(wxID_CANCEL);
830 m_view->OnClose();
831 m_view = NULL;
832 this->Destroy();
833 }
834 else
835 {
836 event.Veto();
837 }
838 }
839
840 void wxPropertyListDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
841 {
842 SetReturnCode(wxID_CANCEL);
843 this->Close();
844 }
845
846 void wxPropertyListDialog::OnDefaultAction(wxControl *WXUNUSED(item))
847 {
848 /*
849 if (item == m_view->GetPropertyScrollingList())
850 view->OnDoubleClick();
851 */
852 }
853
854 // Extend event processing to search the view's event table
855 bool wxPropertyListDialog::ProcessEvent(wxEvent& event)
856 {
857 if ( !m_view || ! m_view->ProcessEvent(event) )
858 return wxEvtHandler::ProcessEvent(event);
859 else
860 return TRUE;
861 }
862
863 /*
864 * Property panel
865 */
866
867 IMPLEMENT_CLASS(wxPropertyListPanel, wxPanel)
868
869 BEGIN_EVENT_TABLE(wxPropertyListPanel, wxPanel)
870 EVT_SIZE(wxPropertyListPanel::OnSize)
871 END_EVENT_TABLE()
872
873 wxPropertyListPanel::~wxPropertyListPanel()
874 {
875 }
876
877 void wxPropertyListPanel::OnDefaultAction(wxControl *WXUNUSED(item))
878 {
879 /*
880 if (item == view->GetPropertyScrollingList())
881 view->OnDoubleClick();
882 */
883 }
884
885 // Extend event processing to search the view's event table
886 bool wxPropertyListPanel::ProcessEvent(wxEvent& event)
887 {
888 if ( !m_view || ! m_view->ProcessEvent(event) )
889 return wxEvtHandler::ProcessEvent(event);
890 else
891 return TRUE;
892 }
893
894 void wxPropertyListPanel::OnSize(wxSizeEvent& WXUNUSED(event))
895 {
896 Layout();
897 }
898
899 /*
900 * Property frame
901 */
902
903 IMPLEMENT_CLASS(wxPropertyListFrame, wxFrame)
904
905 BEGIN_EVENT_TABLE(wxPropertyListFrame, wxFrame)
906 EVT_CLOSE(wxPropertyListFrame::OnCloseWindow)
907 END_EVENT_TABLE()
908
909 void wxPropertyListFrame::OnCloseWindow(wxCloseEvent& event)
910 {
911 if (m_view)
912 {
913 if (m_propertyPanel)
914 m_propertyPanel->SetView(NULL);
915 m_view->OnClose();
916 m_view = NULL;
917 this->Destroy();
918 }
919 else
920 {
921 event.Veto();
922 }
923 }
924
925 wxPropertyListPanel *wxPropertyListFrame::OnCreatePanel(wxFrame *parent, wxPropertyListView *v)
926 {
927 return new wxPropertyListPanel(v, parent);
928 }
929
930 bool wxPropertyListFrame::Initialize(void)
931 {
932 m_propertyPanel = OnCreatePanel(this, m_view);
933 if (m_propertyPanel)
934 {
935 m_view->AssociatePanel(m_propertyPanel);
936 m_view->SetManagedWindow(this);
937 m_propertyPanel->SetAutoLayout(TRUE);
938 return TRUE;
939 }
940 else
941 return FALSE;
942 }
943
944 /*
945 * Property list specific validator
946 */
947
948 IMPLEMENT_ABSTRACT_CLASS(wxPropertyListValidator, wxPropertyValidator)
949
950 bool wxPropertyListValidator::OnSelect(bool select, wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
951 {
952 // view->GetValueText()->Show(TRUE);
953 if (select)
954 OnDisplayValue(property, view, parentWindow);
955
956 return TRUE;
957 }
958
959 bool wxPropertyListValidator::OnValueListSelect(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
960 {
961 wxString s(view->GetValueList()->GetStringSelection());
962 if (s != "")
963 {
964 view->GetValueText()->SetValue(s);
965 view->RetrieveProperty(property);
966 }
967 return TRUE;
968 }
969
970 bool wxPropertyListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
971 {
972 // view->GetValueText()->Show(TRUE);
973 wxString str(property->GetValue().GetStringRepresentation());
974
975 view->GetValueText()->SetValue(str);
976 return TRUE;
977 }
978
979 // Called when TICK is pressed or focus is lost or view wants to update
980 // the property list.
981 // Does the transferance from the property editing area to the property itself
982 bool wxPropertyListValidator::OnRetrieveValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
983 {
984 if (!view->GetValueText())
985 return FALSE;
986 return FALSE;
987 }
988
989 void wxPropertyListValidator::OnEdit(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
990 {
991 if (view->GetDetailedEditing())
992 view->EndDetailedEditing();
993 else
994 view->BeginDetailedEditing();
995 }
996
997 bool wxPropertyListValidator::OnClearControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
998 {
999 if (view->GetConfirmButton())
1000 view->GetConfirmButton()->Enable(FALSE);
1001 if (view->GetCancelButton())
1002 view->GetCancelButton()->Enable(FALSE);
1003 if (view->GetEditButton())
1004 view->GetEditButton()->Enable(FALSE);
1005 return TRUE;
1006 }
1007
1008 /*
1009 * Default validators
1010 */
1011
1012 IMPLEMENT_DYNAMIC_CLASS(wxRealListValidator, wxPropertyListValidator)
1013
1014 ///
1015 /// Real number validator
1016 ///
1017 bool wxRealListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1018 {
1019 if (m_realMin == 0.0 && m_realMax == 0.0)
1020 return TRUE;
1021
1022 if (!view->GetValueText())
1023 return FALSE;
1024 wxString value(view->GetValueText()->GetValue());
1025
1026 float val = 0.0;
1027 if (!StringToFloat(WXSTRINGCAST value, &val))
1028 {
1029 char buf[200];
1030 sprintf(buf, "Value %s is not a valid real number!", value.GetData());
1031 wxMessageBox(buf, "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1032 return FALSE;
1033 }
1034
1035 if (val < m_realMin || val > m_realMax)
1036 {
1037 char buf[200];
1038 sprintf(buf, "Value must be a real number between %.2f and %.2f!", m_realMin, m_realMax);
1039 wxMessageBox(buf, "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1040 return FALSE;
1041 }
1042 return TRUE;
1043 }
1044
1045 // Called when TICK is pressed or focus is lost or view wants to update
1046 // the property list.
1047 // Does the transferance from the property editing area to the property itself
1048 bool wxRealListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1049 {
1050 if (!view->GetValueText())
1051 return FALSE;
1052
1053 if (strlen(view->GetValueText()->GetValue()) == 0)
1054 return FALSE;
1055
1056 wxString value(view->GetValueText()->GetValue());
1057 float f = (float)atof(value.GetData());
1058 property->GetValue() = f;
1059 return TRUE;
1060 }
1061
1062 bool wxRealListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1063 {
1064 if (view->GetConfirmButton())
1065 view->GetConfirmButton()->Enable(TRUE);
1066 if (view->GetCancelButton())
1067 view->GetCancelButton()->Enable(TRUE);
1068 if (view->GetEditButton())
1069 view->GetEditButton()->Enable(FALSE);
1070 if (view->GetValueText())
1071 view->GetValueText()->Enable(TRUE);
1072 return TRUE;
1073 }
1074
1075 ///
1076 /// Integer validator
1077 ///
1078 IMPLEMENT_DYNAMIC_CLASS(wxIntegerListValidator, wxPropertyListValidator)
1079
1080 bool wxIntegerListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1081 {
1082 if (m_integerMin == 0 && m_integerMax == 0)
1083 return TRUE;
1084
1085 if (!view->GetValueText())
1086 return FALSE;
1087 wxString value(view->GetValueText()->GetValue());
1088
1089 long val = 0;
1090 if (!StringToLong(WXSTRINGCAST value, &val))
1091 {
1092 char buf[200];
1093 sprintf(buf, "Value %s is not a valid integer!", value.GetData());
1094 wxMessageBox(buf, "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1095 return FALSE;
1096 }
1097 if (val < m_integerMin || val > m_integerMax)
1098 {
1099 char buf[200];
1100 sprintf(buf, "Value must be an integer between %ld and %ld!", m_integerMin, m_integerMax);
1101 wxMessageBox(buf, "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1102 return FALSE;
1103 }
1104 return TRUE;
1105 }
1106
1107 // Called when TICK is pressed or focus is lost or view wants to update
1108 // the property list.
1109 // Does the transferance from the property editing area to the property itself
1110 bool wxIntegerListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1111 {
1112 if (!view->GetValueText())
1113 return FALSE;
1114
1115 if (strlen(view->GetValueText()->GetValue()) == 0)
1116 return FALSE;
1117
1118 wxString value(view->GetValueText()->GetValue());
1119 long val = (long)atoi(value.GetData());
1120 property->GetValue() = (long)val;
1121 return TRUE;
1122 }
1123
1124 bool wxIntegerListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1125 {
1126 if (view->GetConfirmButton())
1127 view->GetConfirmButton()->Enable(TRUE);
1128 if (view->GetCancelButton())
1129 view->GetCancelButton()->Enable(TRUE);
1130 if (view->GetEditButton())
1131 view->GetEditButton()->Enable(FALSE);
1132 if (view->GetValueText())
1133 view->GetValueText()->Enable(TRUE);
1134 return TRUE;
1135 }
1136
1137 ///
1138 /// boolean validator
1139 ///
1140 IMPLEMENT_DYNAMIC_CLASS(wxBoolListValidator, wxPropertyListValidator)
1141
1142 bool wxBoolListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1143 {
1144 if (!view->GetValueText())
1145 return FALSE;
1146 wxString value(view->GetValueText()->GetValue());
1147 if (value != "True" && value != "False")
1148 {
1149 wxMessageBox("Value must be True or False!", "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1150 return FALSE;
1151 }
1152 return TRUE;
1153 }
1154
1155 // Called when TICK is pressed or focus is lost or view wants to update
1156 // the property list.
1157 // Does the transferance from the property editing area to the property itself
1158 bool wxBoolListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1159 {
1160 if (!view->GetValueText())
1161 return FALSE;
1162
1163 if (strlen(view->GetValueText()->GetValue()) == 0)
1164 return FALSE;
1165
1166 wxString value(view->GetValueText()->GetValue());
1167 bool boolValue = FALSE;
1168 if (value == "True")
1169 boolValue = TRUE;
1170 else
1171 boolValue = FALSE;
1172 property->GetValue() = (bool)boolValue;
1173 return TRUE;
1174 }
1175
1176 bool wxBoolListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1177 {
1178 if (!view->GetValueText())
1179 return FALSE;
1180 wxString str(property->GetValue().GetStringRepresentation());
1181
1182 view->GetValueText()->SetValue(str);
1183
1184 if (view->GetValueList()->IsShown())
1185 {
1186 view->GetValueList()->SetStringSelection(str);
1187 }
1188 return TRUE;
1189 }
1190
1191 bool wxBoolListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1192 {
1193 if (view->GetConfirmButton())
1194 view->GetConfirmButton()->Enable(FALSE);
1195 if (view->GetCancelButton())
1196 view->GetCancelButton()->Enable(FALSE);
1197 if (view->GetEditButton())
1198 view->GetEditButton()->Enable(TRUE);
1199 if (view->GetValueText())
1200 view->GetValueText()->Enable(FALSE);
1201 return TRUE;
1202 }
1203
1204 bool wxBoolListValidator::OnPrepareDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1205 {
1206 if (view->GetValueList())
1207 {
1208 view->ShowListBoxControl(TRUE);
1209 view->GetValueList()->Enable(TRUE);
1210
1211 view->GetValueList()->Append("True");
1212 view->GetValueList()->Append("False");
1213 char *currentString = copystring(view->GetValueText()->GetValue());
1214 view->GetValueList()->SetStringSelection(currentString);
1215 delete[] currentString;
1216 }
1217 return TRUE;
1218 }
1219
1220 bool wxBoolListValidator::OnClearDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1221 {
1222 if (view->GetValueList())
1223 {
1224 view->GetValueList()->Clear();
1225 view->ShowListBoxControl(FALSE);
1226 view->GetValueList()->Enable(FALSE);
1227 }
1228 return TRUE;
1229 }
1230
1231 // Called when the property is double clicked. Extra functionality can be provided,
1232 // cycling through possible values.
1233 bool wxBoolListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1234 {
1235 if (!view->GetValueText())
1236 return FALSE;
1237 if (property->GetValue().BoolValue())
1238 property->GetValue() = (bool)FALSE;
1239 else
1240 property->GetValue() = (bool)TRUE;
1241 view->DisplayProperty(property);
1242 view->UpdatePropertyDisplayInList(property);
1243 view->OnPropertyChanged(property);
1244 return TRUE;
1245 }
1246
1247 ///
1248 /// String validator
1249 ///
1250 IMPLEMENT_DYNAMIC_CLASS(wxStringListValidator, wxPropertyListValidator)
1251
1252 wxStringListValidator::wxStringListValidator(wxStringList *list, long flags):
1253 wxPropertyListValidator(flags)
1254 {
1255 m_strings = list;
1256 // If no constraint, we just allow the string to be edited.
1257 if (!m_strings && ((m_validatorFlags & wxPROP_ALLOW_TEXT_EDITING) == 0))
1258 m_validatorFlags |= wxPROP_ALLOW_TEXT_EDITING;
1259 }
1260
1261 bool wxStringListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *parentWindow)
1262 {
1263 if (!m_strings)
1264 return TRUE;
1265
1266 if (!view->GetValueText())
1267 return FALSE;
1268 wxString value(view->GetValueText()->GetValue());
1269
1270 if (!m_strings->Member(value.GetData()))
1271 {
1272 wxString s("Value ");
1273 s += value.GetData();
1274 s += " is not valid.";
1275 wxMessageBox(s.GetData(), "Property value error", wxOK | wxICON_EXCLAMATION, parentWindow);
1276 return FALSE;
1277 }
1278 return TRUE;
1279 }
1280
1281 // Called when TICK is pressed or focus is lost or view wants to update
1282 // the property list.
1283 // Does the transferance from the property editing area to the property itself
1284 bool wxStringListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1285 {
1286 if (!view->GetValueText())
1287 return FALSE;
1288 wxString value(view->GetValueText()->GetValue());
1289 property->GetValue() = value ;
1290 return TRUE;
1291 }
1292
1293 // Called when TICK is pressed or focus is lost or view wants to update
1294 // the property list.
1295 // Does the transferance from the property editing area to the property itself
1296 bool wxStringListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1297 {
1298 if (!view->GetValueText())
1299 return FALSE;
1300 wxString str(property->GetValue().GetStringRepresentation());
1301 view->GetValueText()->SetValue(str);
1302 if (m_strings && view->GetValueList() && view->GetValueList()->IsShown() && view->GetValueList()->Number() > 0)
1303 {
1304 view->GetValueList()->SetStringSelection(str);
1305 }
1306 return TRUE;
1307 }
1308
1309 bool wxStringListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1310 {
1311 // Unconstrained
1312 if (!m_strings)
1313 {
1314 if (view->GetEditButton())
1315 view->GetEditButton()->Enable(FALSE);
1316 if (view->GetConfirmButton())
1317 view->GetConfirmButton()->Enable(TRUE);
1318 if (view->GetCancelButton())
1319 view->GetCancelButton()->Enable(TRUE);
1320 if (view->GetValueText())
1321 view->GetValueText()->Enable(TRUE);
1322 return TRUE;
1323 }
1324
1325 // Constrained
1326 if (view->GetValueText())
1327 view->GetValueText()->Enable(FALSE);
1328
1329 if (view->GetEditButton())
1330 view->GetEditButton()->Enable(TRUE);
1331
1332 if (view->GetConfirmButton())
1333 view->GetConfirmButton()->Enable(FALSE);
1334 if (view->GetCancelButton())
1335 view->GetCancelButton()->Enable(FALSE);
1336 return TRUE;
1337 }
1338
1339 bool wxStringListValidator::OnPrepareDetailControls(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1340 {
1341 if (view->GetValueList())
1342 {
1343 view->ShowListBoxControl(TRUE);
1344 view->GetValueList()->Enable(TRUE);
1345 wxNode *node = m_strings->First();
1346 while (node)
1347 {
1348 char *s = (char *)node->Data();
1349 view->GetValueList()->Append(s);
1350 node = node->Next();
1351 }
1352 char *currentString = property->GetValue().StringValue();
1353 view->GetValueList()->SetStringSelection(currentString);
1354 }
1355 return TRUE;
1356 }
1357
1358 bool wxStringListValidator::OnClearDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1359 {
1360 if (!m_strings)
1361 {
1362 return TRUE;
1363 }
1364
1365 if (view->GetValueList())
1366 {
1367 view->GetValueList()->Clear();
1368 view->ShowListBoxControl(FALSE);
1369 view->GetValueList()->Enable(FALSE);
1370 }
1371 return TRUE;
1372 }
1373
1374 // Called when the property is double clicked. Extra functionality can be provided,
1375 // cycling through possible values.
1376 bool wxStringListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1377 {
1378 if (!view->GetValueText())
1379 return FALSE;
1380 if (!m_strings)
1381 return FALSE;
1382
1383 wxNode *node = m_strings->First();
1384 char *currentString = property->GetValue().StringValue();
1385 while (node)
1386 {
1387 char *s = (char *)node->Data();
1388 if (strcmp(s, currentString) == 0)
1389 {
1390 char *nextString = NULL;
1391 if (node->Next())
1392 nextString = (char *)node->Next()->Data();
1393 else
1394 nextString = (char *)m_strings->First()->Data();
1395 property->GetValue() = wxString(nextString);
1396 view->DisplayProperty(property);
1397 view->UpdatePropertyDisplayInList(property);
1398 view->OnPropertyChanged(property);
1399 return TRUE;
1400 }
1401 else node = node->Next();
1402 }
1403 return TRUE;
1404 }
1405
1406 ///
1407 /// Filename validator
1408 ///
1409 IMPLEMENT_DYNAMIC_CLASS(wxFilenameListValidator, wxPropertyListValidator)
1410
1411 wxFilenameListValidator::wxFilenameListValidator(wxString message , wxString wildcard, long flags):
1412 wxPropertyListValidator(flags), m_filenameWildCard(wildcard), m_filenameMessage(message)
1413 {
1414 }
1415
1416 wxFilenameListValidator::~wxFilenameListValidator(void)
1417 {
1418 }
1419
1420 bool wxFilenameListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1421 {
1422 return TRUE;
1423 }
1424
1425 // Called when TICK is pressed or focus is lost or view wants to update
1426 // the property list.
1427 // Does the transferance from the property editing area to the property itself
1428 bool wxFilenameListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1429 {
1430 if (!view->GetValueText())
1431 return FALSE;
1432 wxString value(view->GetValueText()->GetValue());
1433 property->GetValue() = value ;
1434 return TRUE;
1435 }
1436
1437 // Called when TICK is pressed or focus is lost or view wants to update
1438 // the property list.
1439 // Does the transferance from the property editing area to the property itself
1440 bool wxFilenameListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1441 {
1442 if (!view->GetValueText())
1443 return FALSE;
1444 wxString str(property->GetValue().GetStringRepresentation());
1445 view->GetValueText()->SetValue(str);
1446 return TRUE;
1447 }
1448
1449 // Called when the property is double clicked. Extra functionality can be provided,
1450 // cycling through possible values.
1451 bool wxFilenameListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1452 {
1453 if (!view->GetValueText())
1454 return FALSE;
1455 OnEdit(property, view, parentWindow);
1456 return TRUE;
1457 }
1458
1459 bool wxFilenameListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1460 {
1461 if (view->GetConfirmButton())
1462 view->GetConfirmButton()->Enable(TRUE);
1463 if (view->GetCancelButton())
1464 view->GetCancelButton()->Enable(TRUE);
1465 if (view->GetEditButton())
1466 view->GetEditButton()->Enable(TRUE);
1467 if (view->GetValueText())
1468 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
1469 return TRUE;
1470 }
1471
1472 void wxFilenameListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1473 {
1474 if (!view->GetValueText())
1475 return;
1476
1477 wxString s = wxFileSelector(
1478 m_filenameMessage.GetData(),
1479 wxPathOnly(property->GetValue().StringValue()),
1480 wxFileNameFromPath(property->GetValue().StringValue()),
1481 NULL,
1482 m_filenameWildCard.GetData(),
1483 0,
1484 parentWindow);
1485 if (s != "")
1486 {
1487 property->GetValue() = s;
1488 view->DisplayProperty(property);
1489 view->UpdatePropertyDisplayInList(property);
1490 view->OnPropertyChanged(property);
1491 }
1492 }
1493
1494 ///
1495 /// Colour validator
1496 ///
1497 IMPLEMENT_DYNAMIC_CLASS(wxColourListValidator, wxPropertyListValidator)
1498
1499 wxColourListValidator::wxColourListValidator(long flags):
1500 wxPropertyListValidator(flags)
1501 {
1502 }
1503
1504 wxColourListValidator::~wxColourListValidator(void)
1505 {
1506 }
1507
1508 bool wxColourListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1509 {
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::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1517 {
1518 if (!view->GetValueText())
1519 return FALSE;
1520 wxString value(view->GetValueText()->GetValue());
1521
1522 property->GetValue() = value ;
1523 return TRUE;
1524 }
1525
1526 // Called when TICK is pressed or focus is lost or view wants to update
1527 // the property list.
1528 // Does the transferance from the property editing area to the property itself
1529 bool wxColourListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1530 {
1531 if (!view->GetValueText())
1532 return FALSE;
1533 wxString str(property->GetValue().GetStringRepresentation());
1534 view->GetValueText()->SetValue(str);
1535 return TRUE;
1536 }
1537
1538 // Called when the property is double clicked. Extra functionality can be provided,
1539 // cycling through possible values.
1540 bool wxColourListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1541 {
1542 if (!view->GetValueText())
1543 return FALSE;
1544 OnEdit(property, view, parentWindow);
1545 return TRUE;
1546 }
1547
1548 bool wxColourListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1549 {
1550 if (view->GetConfirmButton())
1551 view->GetConfirmButton()->Enable(TRUE);
1552 if (view->GetCancelButton())
1553 view->GetCancelButton()->Enable(TRUE);
1554 if (view->GetEditButton())
1555 view->GetEditButton()->Enable(TRUE);
1556 if (view->GetValueText())
1557 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
1558 return TRUE;
1559 }
1560
1561 void wxColourListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1562 {
1563 if (!view->GetValueText())
1564 return;
1565
1566 char *s = property->GetValue().StringValue();
1567 int r = 0;
1568 int g = 0;
1569 int b = 0;
1570 if (s)
1571 {
1572 r = wxHexToDec(s);
1573 g = wxHexToDec(s+2);
1574 b = wxHexToDec(s+4);
1575 }
1576
1577 wxColour col(r,g,b);
1578
1579 wxColourData data;
1580 data.SetChooseFull(TRUE);
1581 data.SetColour(col);
1582
1583 for (int i = 0; i < 16; i++)
1584 {
1585 wxColour colour(i*16, i*16, i*16);
1586 data.SetCustomColour(i, colour);
1587 }
1588
1589 wxColourDialog dialog(parentWindow, &data);
1590 if (dialog.ShowModal() != wxID_CANCEL)
1591 {
1592 wxColourData retData = dialog.GetColourData();
1593 col = retData.GetColour();
1594
1595 char buf[7];
1596 wxDecToHex(col.Red(), buf);
1597 wxDecToHex(col.Green(), buf+2);
1598 wxDecToHex(col.Blue(), buf+4);
1599
1600 property->GetValue() = wxString(buf);
1601 view->DisplayProperty(property);
1602 view->UpdatePropertyDisplayInList(property);
1603 view->OnPropertyChanged(property);
1604 }
1605 }
1606
1607 ///
1608 /// List of strings validator. For this we need more user interface than
1609 /// we get with a property list; so create a new dialog for editing the list.
1610 ///
1611 IMPLEMENT_DYNAMIC_CLASS(wxListOfStringsListValidator, wxPropertyListValidator)
1612
1613 wxListOfStringsListValidator::wxListOfStringsListValidator(long flags):
1614 wxPropertyListValidator(flags)
1615 {
1616 }
1617
1618 bool wxListOfStringsListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1619 {
1620 // No constraints for an arbitrary, user-editable list of strings.
1621 return TRUE;
1622 }
1623
1624 // Called when TICK is pressed or focus is lost or view wants to update
1625 // the property list.
1626 // Does the transferance from the property editing area to the property itself.
1627 // In this case, the user cannot directly edit the string list.
1628 bool wxListOfStringsListValidator::OnRetrieveValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1629 {
1630 return TRUE;
1631 }
1632
1633 bool wxListOfStringsListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1634 {
1635 if (!view->GetValueText())
1636 return FALSE;
1637 wxString str(property->GetValue().GetStringRepresentation());
1638 view->GetValueText()->SetValue(str);
1639 return TRUE;
1640 }
1641
1642 bool wxListOfStringsListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1643 {
1644 if (view->GetEditButton())
1645 view->GetEditButton()->Enable(TRUE);
1646 if (view->GetValueText())
1647 view->GetValueText()->Enable(FALSE);
1648
1649 if (view->GetConfirmButton())
1650 view->GetConfirmButton()->Enable(FALSE);
1651 if (view->GetCancelButton())
1652 view->GetCancelButton()->Enable(FALSE);
1653 return TRUE;
1654 }
1655
1656 // Called when the property is double clicked. Extra functionality can be provided,
1657 // cycling through possible values.
1658 bool wxListOfStringsListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1659 {
1660 OnEdit(property, view, parentWindow);
1661 return TRUE;
1662 }
1663
1664 void wxListOfStringsListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1665 {
1666 // Convert property value to a list of strings for editing
1667 wxStringList *stringList = new wxStringList;
1668
1669 wxPropertyValue *expr = property->GetValue().GetFirst();
1670 while (expr)
1671 {
1672 char *s = expr->StringValue();
1673 if (s)
1674 stringList->Add(s);
1675 expr = expr->GetNext();
1676 }
1677
1678 wxString title("Editing ");
1679 title += property->GetName();
1680
1681 if (EditStringList(parentWindow, stringList, title.GetData()))
1682 {
1683 wxPropertyValue& oldValue = property->GetValue();
1684 oldValue.ClearList();
1685 wxNode *node = stringList->First();
1686 while (node)
1687 {
1688 char *s = (char *)node->Data();
1689 oldValue.Append(new wxPropertyValue(s));
1690
1691 node = node->Next();
1692 }
1693
1694 view->DisplayProperty(property);
1695 view->UpdatePropertyDisplayInList(property);
1696 view->OnPropertyChanged(property);
1697 }
1698 delete stringList;
1699 }
1700
1701 class wxPropertyStringListEditorDialog: public wxDialog
1702 {
1703 public:
1704 wxPropertyStringListEditorDialog(wxWindow *parent, const wxString& title,
1705 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1706 long windowStyle = wxDEFAULT_DIALOG_STYLE, const wxString& name = "stringEditorDialogBox"):
1707 wxDialog(parent, -1, title, pos, size, windowStyle, name)
1708 {
1709 m_stringList = NULL;
1710 m_stringText = NULL;
1711 m_listBox = NULL;
1712 sm_dialogCancelled = FALSE;
1713 m_currentSelection = -1;
1714 }
1715 ~wxPropertyStringListEditorDialog(void) {}
1716 void OnCloseWindow(wxCloseEvent& event);
1717 void SaveCurrentSelection(void);
1718 void ShowCurrentSelection(void);
1719
1720 void OnOK(wxCommandEvent& event);
1721 void OnCancel(wxCommandEvent& event);
1722 void OnAdd(wxCommandEvent& event);
1723 void OnDelete(wxCommandEvent& event);
1724 void OnStrings(wxCommandEvent& event);
1725 void OnText(wxCommandEvent& event);
1726
1727 public:
1728 wxStringList* m_stringList;
1729 wxListBox* m_listBox;
1730 wxTextCtrl* m_stringText;
1731 static bool sm_dialogCancelled;
1732 int m_currentSelection;
1733 DECLARE_EVENT_TABLE()
1734 };
1735
1736 #define wxID_PROP_SL_ADD 3000
1737 #define wxID_PROP_SL_DELETE 3001
1738 #define wxID_PROP_SL_STRINGS 3002
1739 #define wxID_PROP_SL_TEXT 3003
1740
1741 BEGIN_EVENT_TABLE(wxPropertyStringListEditorDialog, wxDialog)
1742 EVT_BUTTON(wxID_OK, wxPropertyStringListEditorDialog::OnOK)
1743 EVT_BUTTON(wxID_CANCEL, wxPropertyStringListEditorDialog::OnCancel)
1744 EVT_BUTTON(wxID_PROP_SL_ADD, wxPropertyStringListEditorDialog::OnAdd)
1745 EVT_BUTTON(wxID_PROP_SL_DELETE, wxPropertyStringListEditorDialog::OnDelete)
1746 EVT_LISTBOX(wxID_PROP_SL_STRINGS, wxPropertyStringListEditorDialog::OnStrings)
1747 EVT_TEXT_ENTER(wxID_PROP_SL_TEXT, wxPropertyStringListEditorDialog::OnText)
1748 EVT_CLOSE(wxPropertyStringListEditorDialog::OnCloseWindow)
1749 END_EVENT_TABLE()
1750
1751 class wxPropertyStringListEditorText: public wxTextCtrl
1752 {
1753 public:
1754 wxPropertyStringListEditorText(wxWindow *parent, wxWindowID id, const wxString& val,
1755 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1756 long windowStyle = 0, const wxString& name = "text"):
1757 wxTextCtrl(parent, id, val, pos, size, windowStyle, wxDefaultValidator, name)
1758 {
1759 }
1760 void OnKillFocus(void)
1761 {
1762 wxPropertyStringListEditorDialog *dialog = (wxPropertyStringListEditorDialog *)GetParent();
1763 dialog->SaveCurrentSelection();
1764 }
1765 };
1766
1767 bool wxPropertyStringListEditorDialog::sm_dialogCancelled = FALSE;
1768
1769 // Edit the string list.
1770 bool wxListOfStringsListValidator::EditStringList(wxWindow *parent, wxStringList *stringList, const char *title)
1771 {
1772 int largeButtonWidth = 60;
1773 int largeButtonHeight = 25;
1774
1775 wxBeginBusyCursor();
1776 wxPropertyStringListEditorDialog *dialog = new wxPropertyStringListEditorDialog(parent,
1777 title, wxPoint(10, 10), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL);
1778
1779 dialog->m_stringList = stringList;
1780
1781 dialog->m_listBox = new wxListBox(dialog, wxID_PROP_SL_STRINGS,
1782 wxPoint(-1, -1), wxSize(-1, -1), 0, NULL, wxLB_SINGLE);
1783
1784 dialog->m_stringText = new wxPropertyStringListEditorText(dialog,
1785 wxID_PROP_SL_TEXT, "", wxPoint(5, 240),
1786 wxSize(300, -1), wxPROCESS_ENTER);
1787 dialog->m_stringText->Enable(FALSE);
1788
1789 wxButton *addButton = new wxButton(dialog, wxID_PROP_SL_ADD, "Add", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1790 wxButton *deleteButton = new wxButton(dialog, wxID_PROP_SL_DELETE, "Delete", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1791 wxButton *cancelButton = new wxButton(dialog, wxID_CANCEL, "Cancel", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1792 wxButton *okButton = new wxButton(dialog, wxID_OK, "OK", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1793
1794 okButton->SetDefault();
1795
1796 wxLayoutConstraints *c = new wxLayoutConstraints;
1797
1798 c->top.SameAs (dialog, wxTop, 2);
1799 c->left.SameAs (dialog, wxLeft, 2);
1800 c->right.SameAs (dialog, wxRight, 2);
1801 c->bottom.SameAs (dialog->m_stringText, wxTop, 2);
1802 dialog->m_listBox->SetConstraints(c);
1803
1804 c = new wxLayoutConstraints;
1805 c->left.SameAs (dialog, wxLeft, 2);
1806 c->right.SameAs (dialog, wxRight, 2);
1807 c->bottom.SameAs (addButton, wxTop, 2);
1808 c->height.AsIs();
1809 dialog->m_stringText->SetConstraints(c);
1810
1811 c = new wxLayoutConstraints;
1812 c->bottom.SameAs (dialog, wxBottom, 2);
1813 c->left.SameAs (dialog, wxLeft, 2);
1814 c->width.AsIs();
1815 c->height.AsIs();
1816 addButton->SetConstraints(c);
1817
1818 c = new wxLayoutConstraints;
1819 c->bottom.SameAs (dialog, wxBottom, 2);
1820 c->left.SameAs (addButton, wxRight, 2);
1821 c->width.AsIs();
1822 c->height.AsIs();
1823 deleteButton->SetConstraints(c);
1824
1825 c = new wxLayoutConstraints;
1826 c->bottom.SameAs (dialog, wxBottom, 2);
1827 c->right.SameAs (dialog, wxRight, 2);
1828 c->width.AsIs();
1829 c->height.AsIs();
1830 cancelButton->SetConstraints(c);
1831
1832 c = new wxLayoutConstraints;
1833 c->bottom.SameAs (dialog, wxBottom, 2);
1834 c->right.SameAs (cancelButton, wxLeft, 2);
1835 c->width.AsIs();
1836 c->height.AsIs();
1837 okButton->SetConstraints(c);
1838
1839 wxNode *node = stringList->First();
1840 while (node)
1841 {
1842 char *str = (char *)node->Data();
1843 // Save node as client data for each listbox item
1844 dialog->m_listBox->Append(str, (char *)node);
1845 node = node->Next();
1846 }
1847
1848 dialog->SetClientSize(310, 305);
1849 dialog->Layout();
1850
1851 dialog->Centre(wxBOTH);
1852 wxEndBusyCursor();
1853 if (dialog->ShowModal() == wxID_CANCEL)
1854 return FALSE;
1855 else
1856 return TRUE;
1857 }
1858
1859 /*
1860 * String list editor callbacks
1861 *
1862 */
1863
1864 void wxPropertyStringListEditorDialog::OnStrings(wxCommandEvent& WXUNUSED(event))
1865 {
1866 int sel = m_listBox->GetSelection();
1867 if (sel > -1)
1868 {
1869 m_currentSelection = sel;
1870
1871 ShowCurrentSelection();
1872 }
1873 }
1874
1875 void wxPropertyStringListEditorDialog::OnDelete(wxCommandEvent& WXUNUSED(event))
1876 {
1877 int sel = m_listBox->GetSelection();
1878 if (sel == -1)
1879 return;
1880
1881 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(sel);
1882 if (!node)
1883 return;
1884
1885 m_listBox->Delete(sel);
1886 delete[] (char *)node->Data();
1887 delete node;
1888 m_currentSelection = -1;
1889 m_stringText->SetValue("");
1890 }
1891
1892 void wxPropertyStringListEditorDialog::OnAdd(wxCommandEvent& WXUNUSED(event))
1893 {
1894 SaveCurrentSelection();
1895
1896 char *initialText = "";
1897 wxNode *node = m_stringList->Add(initialText);
1898 m_listBox->Append(initialText, (char *)node);
1899 m_currentSelection = m_stringList->Number() - 1;
1900 m_listBox->SetSelection(m_currentSelection);
1901 ShowCurrentSelection();
1902 m_stringText->SetFocus();
1903 }
1904
1905 void wxPropertyStringListEditorDialog::OnOK(wxCommandEvent& WXUNUSED(event))
1906 {
1907 SaveCurrentSelection();
1908 EndModal(wxID_OK);
1909 // Close(TRUE);
1910 this->Destroy();
1911 }
1912
1913 void wxPropertyStringListEditorDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
1914 {
1915 sm_dialogCancelled = TRUE;
1916 EndModal(wxID_CANCEL);
1917 // Close(TRUE);
1918 this->Destroy();
1919 }
1920
1921 void wxPropertyStringListEditorDialog::OnText(wxCommandEvent& event)
1922 {
1923 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
1924 {
1925 SaveCurrentSelection();
1926 }
1927 }
1928
1929 void wxPropertyStringListEditorDialog::OnCloseWindow(wxCloseEvent& event)
1930 {
1931 SaveCurrentSelection();
1932 this->Destroy();
1933 }
1934
1935 void wxPropertyStringListEditorDialog::SaveCurrentSelection(void)
1936 {
1937 if (m_currentSelection == -1)
1938 return;
1939
1940 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1941 if (!node)
1942 return;
1943
1944 wxString txt(m_stringText->GetValue());
1945 if (node->Data())
1946 delete[] (char *)node->Data();
1947 node->SetData((wxObject *)copystring(txt));
1948
1949 m_listBox->SetString(m_currentSelection, (char *)node->Data());
1950 }
1951
1952 void wxPropertyStringListEditorDialog::ShowCurrentSelection(void)
1953 {
1954 if (m_currentSelection == -1)
1955 {
1956 m_stringText->SetValue("");
1957 return;
1958 }
1959 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1960 char *txt = (char *)node->Data();
1961 m_stringText->SetValue(txt);
1962 m_stringText->Enable(TRUE);
1963 }
1964