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