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