Split this out from other changes to keep things sane..
[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( wxT("") );
153 }
154 wxNode *node = m_propertySheet->GetProperties().GetFirst();
155
156 // Should sort them... later...
157 while (node)
158 {
159 wxProperty *property = (wxProperty *)node->GetData();
160 wxString stringValueRepr(property->GetValue().GetStringRepresentation());
161 wxString paddedString(MakeNameValueString(property->GetName(), stringValueRepr));
162 m_propertyScrollingList->Append(paddedString.GetData(), (void *)property);
163 node = node->GetNext();
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( wxT(' '), 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( wxT("") );
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( 0u );
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 wxChar buf[200];
898 wxSprintf(buf, wxT("Value must be a real number between %.2f and %.2f!"), m_realMin, m_realMax);
899 wxMessageBox(buf, wxT("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 str( wxT("Value ") );
1133 str += value.GetData();
1134 str += wxT(" is not valid.");
1135 wxMessageBox( str.GetData(), wxT("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,
1200 wxPropertyListView *view,
1201 wxWindow *WXUNUSED(parentWindow) )
1202 {
1203 if (view->GetValueList())
1204 {
1205 view->ShowListBoxControl(TRUE);
1206 view->GetValueList()->Enable(TRUE);
1207 wxStringList::Node *node = m_strings->GetFirst();
1208 while (node)
1209 {
1210 wxChar *s = node->GetData();
1211 view->GetValueList()->Append(s);
1212 node = node->GetNext();
1213 }
1214 wxChar *currentString = property->GetValue().StringValue();
1215 view->GetValueList()->SetStringSelection(currentString);
1216 }
1217 return TRUE;
1218 }
1219
1220 bool wxStringListValidator::OnClearDetailControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1221 {
1222 if (!m_strings)
1223 {
1224 return TRUE;
1225 }
1226
1227 if (view->GetValueList())
1228 {
1229 view->GetValueList()->Clear();
1230 view->ShowListBoxControl(FALSE);
1231 view->GetValueList()->Enable(FALSE);
1232 }
1233 return TRUE;
1234 }
1235
1236 // Called when the property is double clicked. Extra functionality can be provided,
1237 // cycling through possible values.
1238 bool wxStringListValidator::OnDoubleClick( wxProperty *property,
1239 wxPropertyListView *view,
1240 wxWindow *WXUNUSED(parentWindow) )
1241 {
1242 if (!view->GetValueText())
1243 return FALSE;
1244 if (!m_strings)
1245 return FALSE;
1246
1247 wxStringList::Node *node = m_strings->GetFirst();
1248 wxChar *currentString = property->GetValue().StringValue();
1249 while (node)
1250 {
1251 wxChar *s = node->GetData();
1252 if (wxStrcmp(s, currentString) == 0)
1253 {
1254 wxChar *nextString = NULL;
1255 if (node->GetNext())
1256 nextString = node->GetNext()->GetData();
1257 else
1258 nextString = m_strings->GetFirst()->GetData();
1259 property->GetValue() = wxString(nextString);
1260 view->DisplayProperty(property);
1261 view->UpdatePropertyDisplayInList(property);
1262 view->OnPropertyChanged(property);
1263 return TRUE;
1264 }
1265 else node = node->GetNext();
1266 }
1267 return TRUE;
1268 }
1269
1270 ///
1271 /// Filename validator
1272 ///
1273 IMPLEMENT_DYNAMIC_CLASS(wxFilenameListValidator, wxPropertyListValidator)
1274
1275 wxFilenameListValidator::wxFilenameListValidator(wxString message , wxString wildcard, long flags):
1276 wxPropertyListValidator(flags), m_filenameWildCard(wildcard), m_filenameMessage(message)
1277 {
1278 }
1279
1280 wxFilenameListValidator::~wxFilenameListValidator()
1281 {
1282 }
1283
1284 bool wxFilenameListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1285 {
1286 return TRUE;
1287 }
1288
1289 // Called when TICK is pressed or focus is lost or view wants to update
1290 // the property list.
1291 // Does the transferance from the property editing area to the property itself
1292 bool wxFilenameListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1293 {
1294 if (!view->GetValueText())
1295 return FALSE;
1296 wxString value(view->GetValueText()->GetValue());
1297 property->GetValue() = value ;
1298 return TRUE;
1299 }
1300
1301 // Called when TICK is pressed or focus is lost or view wants to update
1302 // the property list.
1303 // Does the transferance from the property editing area to the property itself
1304 bool wxFilenameListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1305 {
1306 if (!view->GetValueText())
1307 return FALSE;
1308 wxString str(property->GetValue().GetStringRepresentation());
1309 view->GetValueText()->SetValue(str);
1310 return TRUE;
1311 }
1312
1313 // Called when the property is double clicked. Extra functionality can be provided,
1314 // cycling through possible values.
1315 bool wxFilenameListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1316 {
1317 if (!view->GetValueText())
1318 return FALSE;
1319 OnEdit(property, view, parentWindow);
1320 return TRUE;
1321 }
1322
1323 bool wxFilenameListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1324 {
1325 if (view->GetConfirmButton())
1326 view->GetConfirmButton()->Enable(TRUE);
1327 if (view->GetCancelButton())
1328 view->GetCancelButton()->Enable(TRUE);
1329 if (view->GetEditButton())
1330 view->GetEditButton()->Enable(TRUE);
1331 if (view->GetValueText())
1332 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
1333 return TRUE;
1334 }
1335
1336 void wxFilenameListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1337 {
1338 if (!view->GetValueText())
1339 return;
1340
1341 wxString s = wxFileSelector(
1342 m_filenameMessage.GetData(),
1343 wxPathOnly(property->GetValue().StringValue()),
1344 wxFileNameFromPath(property->GetValue().StringValue()),
1345 NULL,
1346 m_filenameWildCard.GetData(),
1347 0,
1348 parentWindow);
1349 if (s != wxT(""))
1350 {
1351 property->GetValue() = s;
1352 view->DisplayProperty(property);
1353 view->UpdatePropertyDisplayInList(property);
1354 view->OnPropertyChanged(property);
1355 }
1356 }
1357
1358 ///
1359 /// Colour validator
1360 ///
1361 IMPLEMENT_DYNAMIC_CLASS(wxColourListValidator, wxPropertyListValidator)
1362
1363 wxColourListValidator::wxColourListValidator(long flags):
1364 wxPropertyListValidator(flags)
1365 {
1366 }
1367
1368 wxColourListValidator::~wxColourListValidator()
1369 {
1370 }
1371
1372 bool wxColourListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1373 {
1374 return TRUE;
1375 }
1376
1377 // Called when TICK is pressed or focus is lost or view wants to update
1378 // the property list.
1379 // Does the transferance from the property editing area to the property itself
1380 bool wxColourListValidator::OnRetrieveValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1381 {
1382 if (!view->GetValueText())
1383 return FALSE;
1384 wxString value(view->GetValueText()->GetValue());
1385
1386 property->GetValue() = value ;
1387 return TRUE;
1388 }
1389
1390 // Called when TICK is pressed or focus is lost or view wants to update
1391 // the property list.
1392 // Does the transferance from the property editing area to the property itself
1393 bool wxColourListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1394 {
1395 if (!view->GetValueText())
1396 return FALSE;
1397 wxString str(property->GetValue().GetStringRepresentation());
1398 view->GetValueText()->SetValue(str);
1399 return TRUE;
1400 }
1401
1402 // Called when the property is double clicked. Extra functionality can be provided,
1403 // cycling through possible values.
1404 bool wxColourListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1405 {
1406 if (!view->GetValueText())
1407 return FALSE;
1408 OnEdit(property, view, parentWindow);
1409 return TRUE;
1410 }
1411
1412 bool wxColourListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1413 {
1414 if (view->GetConfirmButton())
1415 view->GetConfirmButton()->Enable(TRUE);
1416 if (view->GetCancelButton())
1417 view->GetCancelButton()->Enable(TRUE);
1418 if (view->GetEditButton())
1419 view->GetEditButton()->Enable(TRUE);
1420 if (view->GetValueText())
1421 view->GetValueText()->Enable((GetFlags() & wxPROP_ALLOW_TEXT_EDITING) == wxPROP_ALLOW_TEXT_EDITING);
1422 return TRUE;
1423 }
1424
1425 void wxColourListValidator::OnEdit(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1426 {
1427 if (!view->GetValueText())
1428 return;
1429
1430 wxChar *s = property->GetValue().StringValue();
1431 int r = 0;
1432 int g = 0;
1433 int b = 0;
1434 if (s)
1435 {
1436 r = wxHexToDec(s);
1437 g = wxHexToDec(s+2);
1438 b = wxHexToDec(s+4);
1439 }
1440
1441 wxColour col(r,g,b);
1442
1443 wxColourData data;
1444 data.SetChooseFull(TRUE);
1445 data.SetColour(col);
1446
1447 for (int i = 0; i < 16; i++)
1448 {
1449 wxColour colour(i*16, i*16, i*16);
1450 data.SetCustomColour(i, colour);
1451 }
1452
1453 wxColourDialog dialog(parentWindow, &data);
1454 if (dialog.ShowModal() != wxID_CANCEL)
1455 {
1456 wxColourData retData = dialog.GetColourData();
1457 col = retData.GetColour();
1458
1459 wxChar buf[7];
1460 wxDecToHex(col.Red(), buf);
1461 wxDecToHex(col.Green(), buf+2);
1462 wxDecToHex(col.Blue(), buf+4);
1463
1464 property->GetValue() = wxString(buf);
1465 view->DisplayProperty(property);
1466 view->UpdatePropertyDisplayInList(property);
1467 view->OnPropertyChanged(property);
1468 }
1469 }
1470
1471 ///
1472 /// List of strings validator. For this we need more user interface than
1473 /// we get with a property list; so create a new dialog for editing the list.
1474 ///
1475 IMPLEMENT_DYNAMIC_CLASS(wxListOfStringsListValidator, wxPropertyListValidator)
1476
1477 wxListOfStringsListValidator::wxListOfStringsListValidator(long flags):
1478 wxPropertyListValidator(flags)
1479 {
1480 }
1481
1482 bool wxListOfStringsListValidator::OnCheckValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1483 {
1484 // No constraints for an arbitrary, user-editable list of strings.
1485 return TRUE;
1486 }
1487
1488 // Called when TICK is pressed or focus is lost or view wants to update
1489 // the property list.
1490 // Does the transferance from the property editing area to the property itself.
1491 // In this case, the user cannot directly edit the string list.
1492 bool wxListOfStringsListValidator::OnRetrieveValue(wxProperty *WXUNUSED(property), wxPropertyListView *WXUNUSED(view), wxWindow *WXUNUSED(parentWindow))
1493 {
1494 return TRUE;
1495 }
1496
1497 bool wxListOfStringsListValidator::OnDisplayValue(wxProperty *property, wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1498 {
1499 if (!view->GetValueText())
1500 return FALSE;
1501 wxString str(property->GetValue().GetStringRepresentation());
1502 view->GetValueText()->SetValue(str);
1503 return TRUE;
1504 }
1505
1506 bool wxListOfStringsListValidator::OnPrepareControls(wxProperty *WXUNUSED(property), wxPropertyListView *view, wxWindow *WXUNUSED(parentWindow))
1507 {
1508 if (view->GetEditButton())
1509 view->GetEditButton()->Enable(TRUE);
1510 if (view->GetValueText())
1511 view->GetValueText()->Enable(FALSE);
1512
1513 if (view->GetConfirmButton())
1514 view->GetConfirmButton()->Enable(FALSE);
1515 if (view->GetCancelButton())
1516 view->GetCancelButton()->Enable(FALSE);
1517 return TRUE;
1518 }
1519
1520 // Called when the property is double clicked. Extra functionality can be provided,
1521 // cycling through possible values.
1522 bool wxListOfStringsListValidator::OnDoubleClick(wxProperty *property, wxPropertyListView *view, wxWindow *parentWindow)
1523 {
1524 OnEdit(property, view, parentWindow);
1525 return TRUE;
1526 }
1527
1528 void wxListOfStringsListValidator::OnEdit( wxProperty *property,
1529 wxPropertyListView *view,
1530 wxWindow *parentWindow )
1531 {
1532 // Convert property value to a list of strings for editing
1533 wxStringList *stringList = new wxStringList;
1534
1535 wxPropertyValue *expr = property->GetValue().GetFirst();
1536 while (expr)
1537 {
1538 wxChar *s = expr->StringValue();
1539 if (s)
1540 stringList->Add(s);
1541 expr = expr->GetNext();
1542 }
1543
1544 wxString title(wxT("Editing "));
1545 title += property->GetName();
1546
1547 if (EditStringList(parentWindow, stringList, title.GetData()))
1548 {
1549 wxPropertyValue& oldValue = property->GetValue();
1550 oldValue.ClearList();
1551 wxStringList::Node *node = stringList->GetFirst();
1552 while (node)
1553 {
1554 wxChar *s = node->GetData();
1555 oldValue.Append(new wxPropertyValue(s));
1556
1557 node = node->GetNext();
1558 }
1559
1560 view->DisplayProperty(property);
1561 view->UpdatePropertyDisplayInList(property);
1562 view->OnPropertyChanged(property);
1563 }
1564 delete stringList;
1565 }
1566
1567 class wxPropertyStringListEditorDialog: public wxDialog
1568 {
1569 public:
1570 wxPropertyStringListEditorDialog(wxWindow *parent, const wxString& title,
1571 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1572 long windowStyle = wxDEFAULT_DIALOG_STYLE, const wxString& name = wxT("stringEditorDialogBox")):
1573 wxDialog(parent, -1, title, pos, size, windowStyle, name)
1574 {
1575 m_stringList = NULL;
1576 m_stringText = NULL;
1577 m_listBox = NULL;
1578 sm_dialogCancelled = FALSE;
1579 m_currentSelection = -1;
1580 }
1581 ~wxPropertyStringListEditorDialog(void) {}
1582 void OnCloseWindow(wxCloseEvent& event);
1583 void SaveCurrentSelection(void);
1584 void ShowCurrentSelection(void);
1585
1586 void OnOK(wxCommandEvent& event);
1587 void OnCancel(wxCommandEvent& event);
1588 void OnAdd(wxCommandEvent& event);
1589 void OnDelete(wxCommandEvent& event);
1590 void OnStrings(wxCommandEvent& event);
1591 void OnText(wxCommandEvent& event);
1592
1593 public:
1594 wxStringList* m_stringList;
1595 wxListBox* m_listBox;
1596 wxTextCtrl* m_stringText;
1597 static bool sm_dialogCancelled;
1598 int m_currentSelection;
1599 DECLARE_EVENT_TABLE()
1600 };
1601
1602 #define wxID_PROP_SL_ADD 3000
1603 #define wxID_PROP_SL_DELETE 3001
1604 #define wxID_PROP_SL_STRINGS 3002
1605 #define wxID_PROP_SL_TEXT 3003
1606
1607 BEGIN_EVENT_TABLE(wxPropertyStringListEditorDialog, wxDialog)
1608 EVT_BUTTON(wxID_OK, wxPropertyStringListEditorDialog::OnOK)
1609 EVT_BUTTON(wxID_CANCEL, wxPropertyStringListEditorDialog::OnCancel)
1610 EVT_BUTTON(wxID_PROP_SL_ADD, wxPropertyStringListEditorDialog::OnAdd)
1611 EVT_BUTTON(wxID_PROP_SL_DELETE, wxPropertyStringListEditorDialog::OnDelete)
1612 EVT_LISTBOX(wxID_PROP_SL_STRINGS, wxPropertyStringListEditorDialog::OnStrings)
1613 EVT_TEXT_ENTER(wxID_PROP_SL_TEXT, wxPropertyStringListEditorDialog::OnText)
1614 EVT_CLOSE(wxPropertyStringListEditorDialog::OnCloseWindow)
1615 END_EVENT_TABLE()
1616
1617 class wxPropertyStringListEditorText: public wxTextCtrl
1618 {
1619 public:
1620 wxPropertyStringListEditorText(wxWindow *parent, wxWindowID id, const wxString& val,
1621 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
1622 long windowStyle = 0, const wxString& name = wxT("text")):
1623 wxTextCtrl(parent, id, val, pos, size, windowStyle, wxDefaultValidator, name)
1624 {
1625 }
1626 void OnKillFocus()
1627 {
1628 wxPropertyStringListEditorDialog *dialog = (wxPropertyStringListEditorDialog *)GetParent();
1629 dialog->SaveCurrentSelection();
1630 }
1631 };
1632
1633 bool wxPropertyStringListEditorDialog::sm_dialogCancelled = FALSE;
1634
1635 // Edit the string list.
1636 bool wxListOfStringsListValidator::EditStringList(wxWindow *parent, wxStringList *stringList, const wxChar *title)
1637 {
1638 int largeButtonWidth = 60;
1639 int largeButtonHeight = 25;
1640
1641 wxBeginBusyCursor();
1642 wxPropertyStringListEditorDialog *dialog = new wxPropertyStringListEditorDialog(parent,
1643 title, wxPoint(10, 10), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL);
1644
1645 dialog->m_stringList = stringList;
1646
1647 dialog->m_listBox = new wxListBox(dialog, wxID_PROP_SL_STRINGS,
1648 wxPoint(-1, -1), wxSize(-1, -1), 0, NULL, wxLB_SINGLE);
1649
1650 dialog->m_stringText = new wxPropertyStringListEditorText(dialog,
1651 wxID_PROP_SL_TEXT, wxT(""), wxPoint(5, 240),
1652 wxSize(300, -1), wxPROCESS_ENTER);
1653 dialog->m_stringText->Enable(FALSE);
1654
1655 wxButton *addButton = new wxButton(dialog, wxID_PROP_SL_ADD, wxT("Add"), wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1656 wxButton *deleteButton = new wxButton(dialog, wxID_PROP_SL_DELETE, wxT("Delete"), wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1657 wxButton *cancelButton = new wxButton(dialog, wxID_CANCEL, wxT("Cancel"), wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1658 wxButton *okButton = new wxButton(dialog, wxID_OK, wxT("OK"), wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight));
1659
1660 #ifndef __WXGTK__
1661 okButton->SetDefault();
1662 #endif
1663
1664 wxLayoutConstraints *c = new wxLayoutConstraints;
1665
1666 c->top.SameAs (dialog, wxTop, 2);
1667 c->left.SameAs (dialog, wxLeft, 2);
1668 c->right.SameAs (dialog, wxRight, 2);
1669 c->bottom.SameAs (dialog->m_stringText, wxTop, 2);
1670 dialog->m_listBox->SetConstraints(c);
1671
1672 c = new wxLayoutConstraints;
1673 c->left.SameAs (dialog, wxLeft, 2);
1674 c->right.SameAs (dialog, wxRight, 2);
1675 c->bottom.SameAs (addButton, wxTop, 2);
1676 c->height.AsIs();
1677 dialog->m_stringText->SetConstraints(c);
1678
1679 c = new wxLayoutConstraints;
1680 c->bottom.SameAs (dialog, wxBottom, 2);
1681 c->left.SameAs (dialog, wxLeft, 2);
1682 c->width.AsIs();
1683 c->height.AsIs();
1684 addButton->SetConstraints(c);
1685
1686 c = new wxLayoutConstraints;
1687 c->bottom.SameAs (dialog, wxBottom, 2);
1688 c->left.SameAs (addButton, wxRight, 2);
1689 c->width.AsIs();
1690 c->height.AsIs();
1691 deleteButton->SetConstraints(c);
1692
1693 c = new wxLayoutConstraints;
1694 c->bottom.SameAs (dialog, wxBottom, 2);
1695 c->right.SameAs (dialog, wxRight, 2);
1696 c->width.AsIs();
1697 c->height.AsIs();
1698 cancelButton->SetConstraints(c);
1699
1700 c = new wxLayoutConstraints;
1701 c->bottom.SameAs (dialog, wxBottom, 2);
1702 c->right.SameAs (cancelButton, wxLeft, 2);
1703 c->width.AsIs();
1704 c->height.AsIs();
1705 okButton->SetConstraints(c);
1706
1707 wxStringList::Node *node = stringList->GetFirst();
1708 while (node)
1709 {
1710 wxChar *str = node->GetData();
1711 // Save node as client data for each listbox item
1712 dialog->m_listBox->Append(str, (wxChar *)node);
1713 node = node->GetNext();
1714 }
1715
1716 dialog->SetClientSize(310, 305);
1717 dialog->Layout();
1718
1719 dialog->Centre(wxBOTH);
1720 wxEndBusyCursor();
1721 if (dialog->ShowModal() == wxID_CANCEL)
1722 return FALSE;
1723 else
1724 return TRUE;
1725 }
1726
1727 /*
1728 * String list editor callbacks
1729 *
1730 */
1731
1732 void wxPropertyStringListEditorDialog::OnStrings(wxCommandEvent& WXUNUSED(event))
1733 {
1734 int sel = m_listBox->GetSelection();
1735 if (sel > -1)
1736 {
1737 m_currentSelection = sel;
1738
1739 ShowCurrentSelection();
1740 }
1741 }
1742
1743 void wxPropertyStringListEditorDialog::OnDelete(wxCommandEvent& WXUNUSED(event))
1744 {
1745 int sel = m_listBox->GetSelection();
1746 if (sel == -1)
1747 return;
1748
1749 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(sel);
1750 if (!node)
1751 return;
1752
1753 m_listBox->Delete(sel);
1754 delete[] (wxChar *)node->GetData();
1755 delete node;
1756 m_currentSelection = -1;
1757 m_stringText->SetValue(_T(""));
1758 }
1759
1760 void wxPropertyStringListEditorDialog::OnAdd(wxCommandEvent& WXUNUSED(event))
1761 {
1762 SaveCurrentSelection();
1763
1764 wxString initialText;
1765 wxNode *node = m_stringList->Add(initialText);
1766 m_listBox->Append(initialText, (void *)node);
1767 m_currentSelection = m_stringList->GetCount() - 1;
1768 m_listBox->SetSelection(m_currentSelection);
1769 ShowCurrentSelection();
1770 m_stringText->SetFocus();
1771 }
1772
1773 void wxPropertyStringListEditorDialog::OnOK(wxCommandEvent& WXUNUSED(event))
1774 {
1775 SaveCurrentSelection();
1776 EndModal(wxID_OK);
1777 // Close(TRUE);
1778 this->Destroy();
1779 }
1780
1781 void wxPropertyStringListEditorDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
1782 {
1783 sm_dialogCancelled = TRUE;
1784 EndModal(wxID_CANCEL);
1785 // Close(TRUE);
1786 this->Destroy();
1787 }
1788
1789 void wxPropertyStringListEditorDialog::OnText(wxCommandEvent& event)
1790 {
1791 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
1792 {
1793 SaveCurrentSelection();
1794 }
1795 }
1796
1797 void
1798 wxPropertyStringListEditorDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1799 {
1800 SaveCurrentSelection();
1801
1802 Destroy();
1803 }
1804
1805 void wxPropertyStringListEditorDialog::SaveCurrentSelection()
1806 {
1807 if (m_currentSelection == -1)
1808 return;
1809
1810 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1811 if (!node)
1812 return;
1813
1814 wxString txt(m_stringText->GetValue());
1815 if (node->GetData())
1816 delete[] (wxChar *)node->GetData();
1817 node->SetData((wxObject *)wxStrdup(txt));
1818
1819 m_listBox->SetString(m_currentSelection, (wxChar *)node->GetData());
1820 }
1821
1822 void wxPropertyStringListEditorDialog::ShowCurrentSelection()
1823 {
1824 if (m_currentSelection == -1)
1825 {
1826 m_stringText->SetValue(wxT(""));
1827 return;
1828 }
1829 wxNode *node = (wxNode *)m_listBox->wxListBox::GetClientData(m_currentSelection);
1830 wxChar *txt = (wxChar *)node->GetData();
1831 m_stringText->SetValue(txt);
1832 m_stringText->Enable(TRUE);
1833 }
1834
1835
1836 #endif // wxUSE_PROPSHEET