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