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