1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Property form classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "propform.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/propform.h"
39 IMPLEMENT_DYNAMIC_CLASS(wxPropertyFormView
, wxPropertyView
)
41 BEGIN_EVENT_TABLE(wxPropertyFormView
, wxPropertyView
)
42 EVT_BUTTON(wxID_OK
, wxPropertyFormView::OnOk
)
43 EVT_BUTTON(wxID_CANCEL
, wxPropertyFormView::OnCancel
)
44 EVT_BUTTON(wxID_HELP
, wxPropertyFormView::OnHelp
)
45 EVT_BUTTON(wxID_PROP_REVERT
, wxPropertyFormView::OnRevert
)
46 EVT_BUTTON(wxID_PROP_UPDATE
, wxPropertyFormView::OnUpdate
)
49 bool wxPropertyFormView::sm_dialogCancelled
= FALSE
;
51 wxPropertyFormView::wxPropertyFormView(wxWindow
*propPanel
, long flags
):wxPropertyView(flags
)
53 m_propertyWindow
= propPanel
;
54 m_managedWindow
= NULL
;
56 m_windowCloseButton
= NULL
;
57 m_windowCancelButton
= NULL
;
58 m_windowHelpButton
= NULL
;
60 m_detailedEditing
= FALSE
;
63 wxPropertyFormView::~wxPropertyFormView(void)
67 void wxPropertyFormView::ShowView(wxPropertySheet
*ps
, wxWindow
*panel
)
71 AssociatePanel(panel
);
73 // UpdatePropertyList();
76 // Update this view of the viewed object, called e.g. by
78 bool wxPropertyFormView::OnUpdateView(void)
83 bool wxPropertyFormView::Check(void)
88 wxNode
*node
= m_propertySheet
->GetProperties().First();
91 wxProperty
*prop
= (wxProperty
*)node
->Data();
92 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
93 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
95 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
96 if (!formValidator
->OnCheckValue(prop
, this, m_propertyWindow
))
104 bool wxPropertyFormView::TransferToPropertySheet(void)
106 if (!m_propertySheet
)
109 wxNode
*node
= m_propertySheet
->GetProperties().First();
112 wxProperty
*prop
= (wxProperty
*)node
->Data();
113 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
114 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
116 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
117 formValidator
->OnRetrieveValue(prop
, this, m_propertyWindow
);
124 bool wxPropertyFormView::TransferToDialog(void)
126 if (!m_propertySheet
)
129 wxNode
*node
= m_propertySheet
->GetProperties().First();
132 wxProperty
*prop
= (wxProperty
*)node
->Data();
133 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
134 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
136 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
137 formValidator
->OnDisplayValue(prop
, this, m_propertyWindow
);
144 bool wxPropertyFormView::AssociateNames(void)
146 if (!m_propertySheet
|| !m_propertyWindow
)
149 wxNode
*node
= m_propertyWindow
->GetChildren().First();
152 wxWindow
*win
= (wxWindow
*)node
->Data();
153 if (win
->GetName() != wxT(""))
155 wxProperty
*prop
= m_propertySheet
->GetProperty(win
->GetName());
157 prop
->SetWindow(win
);
165 bool wxPropertyFormView::OnClose(void)
171 void wxPropertyFormView::OnOk(wxCommandEvent
& WXUNUSED(event
))
173 // Retrieve the value if any
177 sm_dialogCancelled
= FALSE
;
178 TransferToPropertySheet();
180 m_managedWindow
->Close(TRUE
);
183 void wxPropertyFormView::OnCancel(wxCommandEvent
& WXUNUSED(event
))
185 sm_dialogCancelled
= TRUE
;
187 m_managedWindow
->Close(TRUE
);
190 void wxPropertyFormView::OnHelp(wxCommandEvent
& WXUNUSED(event
))
194 void wxPropertyFormView::OnUpdate(wxCommandEvent
& WXUNUSED(event
))
197 TransferToPropertySheet();
200 void wxPropertyFormView::OnRevert(wxCommandEvent
& WXUNUSED(event
))
205 void wxPropertyFormView::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
207 if (!m_propertySheet
)
210 if (win
.GetName() == wxT(""))
213 if (wxStrcmp(win
.GetName(), wxT("ok")) == 0)
215 else if (wxStrcmp(win
.GetName(), wxT("cancel")) == 0)
217 else if (wxStrcmp(win
.GetName(), wxT("help")) == 0)
219 else if (wxStrcmp(win
.GetName(), wxT("update")) == 0)
221 else if (wxStrcmp(win
.GetName(), wxT("revert")) == 0)
225 // Find a validator to route the command to.
226 wxNode
*node
= m_propertySheet
->GetProperties().First();
229 wxProperty
*prop
= (wxProperty
*)node
->Data();
230 if (prop
->GetWindow() && (prop
->GetWindow() == &win
))
232 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
233 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
235 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
236 formValidator
->OnCommand(prop
, this, m_propertyWindow
, event
);
245 // Extend event processing to call OnCommand
246 bool wxPropertyFormView::ProcessEvent(wxEvent
& event
)
248 if (wxEvtHandler::ProcessEvent(event
))
250 else if (event
.IsCommandEvent() && !event
.IsKindOf(CLASSINFO(wxUpdateUIEvent
)) && event
.GetEventObject())
252 OnCommand(* ((wxWindow
*) event
.GetEventObject()), (wxCommandEvent
&) event
);
259 void wxPropertyFormView::OnDoubleClick(wxControl
*item
)
261 if (!m_propertySheet
)
264 // Find a validator to route the command to.
265 wxNode
*node
= m_propertySheet
->GetProperties().First();
268 wxProperty
*prop
= (wxProperty
*)node
->Data();
269 if (prop
->GetWindow() && ((wxControl
*)prop
->GetWindow() == item
))
271 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
272 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
274 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
275 formValidator
->OnDoubleClick(prop
, this, m_propertyWindow
);
284 * Property form dialog box
287 IMPLEMENT_CLASS(wxPropertyFormDialog
, wxDialog
)
289 BEGIN_EVENT_TABLE(wxPropertyFormDialog
, wxDialog
)
290 EVT_CLOSE(wxPropertyFormDialog::OnCloseWindow
)
293 wxPropertyFormDialog::wxPropertyFormDialog(wxPropertyFormView
*v
, wxWindow
*parent
, const wxString
& title
,
294 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
295 wxDialog(parent
, -1, title
, pos
, size
, style
, name
)
298 m_view
->AssociatePanel(this);
299 m_view
->SetManagedWindow(this);
300 // SetAutoLayout(TRUE);
303 void wxPropertyFormDialog::OnCloseWindow(wxCloseEvent
& event
)
315 void wxPropertyFormDialog::OnDefaultAction(wxControl
*item
)
317 m_view
->OnDoubleClick(item
);
320 void wxPropertyFormDialog::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
323 m_view
->OnCommand(win
, event
);
326 // Extend event processing to search the view's event table
327 bool wxPropertyFormDialog::ProcessEvent(wxEvent
& event
)
329 if ( !m_view
|| ! m_view
->ProcessEvent(event
) )
330 return wxEvtHandler::ProcessEvent(event
);
337 * Property form panel
340 IMPLEMENT_CLASS(wxPropertyFormPanel
, wxPanel
)
342 void wxPropertyFormPanel::OnDefaultAction(wxControl
*item
)
344 m_view
->OnDoubleClick(item
);
347 void wxPropertyFormPanel::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
349 m_view
->OnCommand(win
, event
);
352 // Extend event processing to search the view's event table
353 bool wxPropertyFormPanel::ProcessEvent(wxEvent
& event
)
355 if ( !m_view
|| ! m_view
->ProcessEvent(event
) )
356 return wxEvtHandler::ProcessEvent(event
);
365 IMPLEMENT_CLASS(wxPropertyFormFrame
, wxFrame
)
367 BEGIN_EVENT_TABLE(wxPropertyFormFrame
, wxFrame
)
368 EVT_CLOSE(wxPropertyFormFrame::OnCloseWindow
)
371 void wxPropertyFormFrame::OnCloseWindow(wxCloseEvent
& event
)
373 if (m_view
&& m_view
->OnClose())
379 wxPanel
*wxPropertyFormFrame::OnCreatePanel(wxFrame
*parent
, wxPropertyFormView
*v
)
381 return new wxPropertyFormPanel(v
, parent
);
384 bool wxPropertyFormFrame::Initialize(void)
386 m_propertyPanel
= OnCreatePanel(this, m_view
);
389 m_view
->AssociatePanel(m_propertyPanel
);
390 m_view
->SetManagedWindow(this);
398 * Property form specific validator
401 IMPLEMENT_ABSTRACT_CLASS(wxPropertyFormValidator
, wxPropertyValidator
)
408 IMPLEMENT_DYNAMIC_CLASS(wxRealFormValidator
, wxPropertyFormValidator
)
411 /// Real number form validator
413 bool wxRealFormValidator::OnCheckValue( wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
414 wxWindow
*parentWindow
)
416 if (m_realMin
== 0.0 && m_realMax
== 0.0)
419 // The item used for viewing the real number: should be a text item.
420 wxWindow
*m_propertyWindow
= property
->GetWindow();
421 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
424 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
427 if (!StringToFloat(WXSTRINGCAST value
, &val
))
430 wxSprintf(buf
, wxT("Value %s is not a valid real number!"), (const wxChar
*)value
);
431 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
435 if (val
< m_realMin
|| val
> m_realMax
)
438 wxSprintf(buf
, wxT("Value must be a real number between %.2f and %.2f!"), m_realMin
, m_realMax
);
439 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
445 bool wxRealFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
446 wxWindow
*WXUNUSED(parentWindow
) )
448 // The item used for viewing the real number: should be a text item.
449 wxWindow
*m_propertyWindow
= property
->GetWindow();
450 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
453 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
455 if (value
.Length() == 0)
458 float f
= (float)wxAtof((const wxChar
*)value
);
459 property
->GetValue() = f
;
463 bool wxRealFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
464 wxWindow
*WXUNUSED(parentWindow
) )
466 // The item used for viewing the real number: should be a text item.
467 wxWindow
*m_propertyWindow
= property
->GetWindow();
468 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
471 wxTextCtrl
*textItem
= (wxTextCtrl
*)m_propertyWindow
;
472 textItem
->SetValue(FloatToString(property
->GetValue().RealValue()));
477 /// Integer validator
479 IMPLEMENT_DYNAMIC_CLASS(wxIntegerFormValidator
, wxPropertyFormValidator
)
481 bool wxIntegerFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
482 wxWindow
*parentWindow
)
484 if (m_integerMin
== 0.0 && m_integerMax
== 0.0)
487 // The item used for viewing the real number: should be a text item or a slider
488 wxWindow
*m_propertyWindow
= property
->GetWindow();
489 if (!m_propertyWindow
)
494 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
496 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
498 if (!StringToLong(WXSTRINGCAST value
, &val
))
501 wxSprintf(buf
, wxT("Value %s is not a valid integer!"), (const wxChar
*)value
);
502 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
506 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
508 val
= (long)((wxSlider
*)m_propertyWindow
)->GetValue();
513 if (val
< m_integerMin
|| val
> m_integerMax
)
516 sprintf(buf
, "Value must be an integer between %ld and %ld!", m_integerMin
, m_integerMax
);
517 wxMessageBox(buf
, "Property value error", wxOK
| wxICON_EXCLAMATION
, parentWindow
);
523 bool wxIntegerFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
524 wxWindow
*WXUNUSED(parentWindow
))
526 // The item used for viewing the real number: should be a text item or a slider
527 wxWindow
*m_propertyWindow
= property
->GetWindow();
528 if (!m_propertyWindow
)
531 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
533 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
535 if (value
.Length() == 0)
538 long i
= wxAtol((const wxChar
*)value
);
539 property
->GetValue() = i
;
541 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
543 property
->GetValue() = (long)((wxSlider
*)m_propertyWindow
)->GetValue();
551 bool wxIntegerFormValidator::OnDisplayValue( wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
552 wxWindow
*WXUNUSED(parentWindow
))
554 // The item used for viewing the real number: should be a text item or a slider
555 wxWindow
*m_propertyWindow
= property
->GetWindow();
556 if (!m_propertyWindow
)
559 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
561 wxTextCtrl
*textItem
= (wxTextCtrl
*)m_propertyWindow
;
562 textItem
->SetValue(LongToString(property
->GetValue().IntegerValue()));
564 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
566 ((wxSlider
*)m_propertyWindow
)->SetValue((int)property
->GetValue().IntegerValue());
574 /// Boolean validator
576 IMPLEMENT_DYNAMIC_CLASS(wxBoolFormValidator
, wxPropertyFormValidator
)
578 bool wxBoolFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
579 wxWindow
*WXUNUSED(parentWindow
))
581 // The item used for viewing the boolean: should be a checkbox
582 wxWindow
*m_propertyWindow
= property
->GetWindow();
583 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
589 bool wxBoolFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
590 wxWindow
*WXUNUSED(parentWindow
) )
592 // The item used for viewing the boolean: should be a checkbox.
593 wxWindow
*m_propertyWindow
= property
->GetWindow();
594 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
597 wxCheckBox
*checkBox
= (wxCheckBox
*)m_propertyWindow
;
599 property
->GetValue() = (bool)checkBox
->GetValue();
603 bool wxBoolFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
604 wxWindow
*WXUNUSED(parentWindow
))
606 // The item used for viewing the boolean: should be a checkbox.
607 wxWindow
*m_propertyWindow
= property
->GetWindow();
608 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
611 wxCheckBox
*checkBox
= (wxCheckBox
*)m_propertyWindow
;
612 checkBox
->SetValue((bool)property
->GetValue().BoolValue());
619 IMPLEMENT_DYNAMIC_CLASS(wxStringFormValidator
, wxPropertyFormValidator
)
621 wxStringFormValidator::wxStringFormValidator(wxStringList
*list
, long flags
):
622 wxPropertyFormValidator(flags
)
627 bool wxStringFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
628 wxWindow
*parentWindow
)
633 // The item used for viewing the string: should be a text item, choice item or listbox.
634 wxWindow
*m_propertyWindow
= property
->GetWindow();
635 if (!m_propertyWindow
)
637 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
639 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
640 if (!m_strings
->Member(text
->GetValue()))
642 wxString
s("Value ");
643 s
+= text
->GetValue();
644 s
+= " is not valid.";
645 wxMessageBox(s
, "Property value error", wxOK
| wxICON_EXCLAMATION
, parentWindow
);
651 // Any other item constrains the string value,
652 // so we don't have to check it.
657 bool wxStringFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
658 wxWindow
*WXUNUSED(parentWindow
) )
660 // The item used for viewing the string: should be a text item, choice item or listbox.
661 wxWindow
*m_propertyWindow
= property
->GetWindow();
662 if (!m_propertyWindow
)
664 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
666 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
667 property
->GetValue() = text
->GetValue();
669 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxListBox
)))
671 wxListBox
*lbox
= (wxListBox
*)m_propertyWindow
;
672 if (lbox
->GetSelection() > -1)
673 property
->GetValue() = lbox
->GetStringSelection();
676 else if (m_propertyWindow->IsKindOf(CLASSINFO(wxRadioBox)))
678 wxRadioBox *rbox = (wxRadioBox *)m_propertyWindow;
680 if ((n = rbox->GetSelection()) > -1)
681 property->GetValue() = rbox->GetString(n);
684 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxChoice
)))
686 wxChoice
*choice
= (wxChoice
*)m_propertyWindow
;
687 if (choice
->GetSelection() > -1)
688 property
->GetValue() = choice
->GetStringSelection();
695 bool wxStringFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
696 wxWindow
*WXUNUSED(parentWindow
) )
698 // The item used for viewing the string: should be a text item, choice item or listbox.
699 wxWindow
*m_propertyWindow
= property
->GetWindow();
700 if (!m_propertyWindow
)
702 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
704 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
705 text
->SetValue(property
->GetValue().StringValue());
707 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxListBox
)))
709 wxListBox
*lbox
= (wxListBox
*)m_propertyWindow
;
710 if (lbox
->Number() == 0 && m_strings
)
712 // Try to initialize the listbox from 'strings'
713 wxNode
*node
= m_strings
->First();
716 char *s
= (char *)node
->Data();
721 lbox
->SetStringSelection(property
->GetValue().StringValue());
724 else if (m_propertyWindow->IsKindOf(CLASSINFO(wxRadioBox)))
726 wxRadioBox *rbox = (wxRadioBox *)m_propertyWindow;
727 rbox->SetStringSelection(property->GetValue().StringValue());
730 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxChoice
)))
732 wxChoice
*choice
= (wxChoice
*)m_propertyWindow
;
734 if (choice
->Number() == 0 && m_strings
)
736 // Try to initialize the choice item from 'strings'
737 // XView doesn't allow this kind of thing.
738 wxNode
*node
= m_strings
->First();
741 char *s
= (char *)node
->Data();
747 choice
->SetStringSelection(property
->GetValue().StringValue());