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