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