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