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