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