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