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)
167 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxPropertyFormPanel
)))
169 ((wxPropertyFormPanel
*)m_propertyWindow
)->SetView(NULL
);
175 void wxPropertyFormView::OnOk(wxCommandEvent
& WXUNUSED(event
))
177 // Retrieve the value if any
181 sm_dialogCancelled
= FALSE
;
182 TransferToPropertySheet();
184 m_managedWindow
->Close(TRUE
);
187 void wxPropertyFormView::OnCancel(wxCommandEvent
& WXUNUSED(event
))
189 sm_dialogCancelled
= TRUE
;
191 m_managedWindow
->Close(TRUE
);
194 void wxPropertyFormView::OnHelp(wxCommandEvent
& WXUNUSED(event
))
198 void wxPropertyFormView::OnUpdate(wxCommandEvent
& WXUNUSED(event
))
201 TransferToPropertySheet();
204 void wxPropertyFormView::OnRevert(wxCommandEvent
& WXUNUSED(event
))
209 void wxPropertyFormView::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
211 if (!m_propertySheet
)
214 if (win
.GetName() == wxT(""))
217 if (wxStrcmp(win
.GetName(), wxT("ok")) == 0)
219 else if (wxStrcmp(win
.GetName(), wxT("cancel")) == 0)
221 else if (wxStrcmp(win
.GetName(), wxT("help")) == 0)
223 else if (wxStrcmp(win
.GetName(), wxT("update")) == 0)
225 else if (wxStrcmp(win
.GetName(), wxT("revert")) == 0)
229 // Find a validator to route the command to.
230 wxNode
*node
= m_propertySheet
->GetProperties().First();
233 wxProperty
*prop
= (wxProperty
*)node
->Data();
234 if (prop
->GetWindow() && (prop
->GetWindow() == &win
))
236 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
237 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
239 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
240 formValidator
->OnCommand(prop
, this, m_propertyWindow
, event
);
249 // Extend event processing to call OnCommand
250 bool wxPropertyFormView::ProcessEvent(wxEvent
& event
)
252 if (wxEvtHandler::ProcessEvent(event
))
254 else if (event
.IsCommandEvent() && !event
.IsKindOf(CLASSINFO(wxUpdateUIEvent
)) && event
.GetEventObject())
256 OnCommand(* ((wxWindow
*) event
.GetEventObject()), (wxCommandEvent
&) event
);
263 void wxPropertyFormView::OnDoubleClick(wxControl
*item
)
265 if (!m_propertySheet
)
268 // Find a validator to route the command to.
269 wxNode
*node
= m_propertySheet
->GetProperties().First();
272 wxProperty
*prop
= (wxProperty
*)node
->Data();
273 if (prop
->GetWindow() && ((wxControl
*)prop
->GetWindow() == item
))
275 wxPropertyValidator
*validator
= FindPropertyValidator(prop
);
276 if (validator
&& validator
->IsKindOf(CLASSINFO(wxPropertyFormValidator
)))
278 wxPropertyFormValidator
*formValidator
= (wxPropertyFormValidator
*)validator
;
279 formValidator
->OnDoubleClick(prop
, this, m_propertyWindow
);
288 * Property form dialog box
291 IMPLEMENT_DYNAMIC_CLASS(wxPropertyFormDialog
, wxDialog
)
293 BEGIN_EVENT_TABLE(wxPropertyFormDialog
, wxDialog
)
294 EVT_CLOSE(wxPropertyFormDialog::OnCloseWindow
)
297 wxPropertyFormDialog::wxPropertyFormDialog(wxPropertyFormView
*v
, wxWindow
*parent
, const wxString
& title
,
298 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
299 wxDialog(parent
, -1, title
, pos
, size
, style
, name
)
302 m_view
->AssociatePanel(this);
303 m_view
->SetManagedWindow(this);
304 // SetAutoLayout(TRUE);
307 void wxPropertyFormDialog::OnCloseWindow(wxCloseEvent
& event
)
319 void wxPropertyFormDialog::OnDefaultAction(wxControl
*item
)
321 m_view
->OnDoubleClick(item
);
324 void wxPropertyFormDialog::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
327 m_view
->OnCommand(win
, event
);
330 // Extend event processing to search the view's event table
331 bool wxPropertyFormDialog::ProcessEvent(wxEvent
& event
)
333 if ( !m_view
|| ! m_view
->ProcessEvent(event
) )
334 return wxEvtHandler::ProcessEvent(event
);
341 * Property form panel
344 IMPLEMENT_DYNAMIC_CLASS(wxPropertyFormPanel
, wxPanel
)
346 void wxPropertyFormPanel::OnDefaultAction(wxControl
*item
)
348 m_view
->OnDoubleClick(item
);
351 void wxPropertyFormPanel::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
353 m_view
->OnCommand(win
, event
);
356 // Extend event processing to search the view's event table
357 bool wxPropertyFormPanel::ProcessEvent(wxEvent
& event
)
359 if ( !m_view
|| ! m_view
->ProcessEvent(event
) )
360 return wxEvtHandler::ProcessEvent(event
);
369 IMPLEMENT_DYNAMIC_CLASS(wxPropertyFormFrame
, wxFrame
)
371 BEGIN_EVENT_TABLE(wxPropertyFormFrame
, wxFrame
)
372 EVT_CLOSE(wxPropertyFormFrame::OnCloseWindow
)
375 void wxPropertyFormFrame::OnCloseWindow(wxCloseEvent
& event
)
377 if (m_view
&& m_view
->OnClose())
383 wxPanel
*wxPropertyFormFrame::OnCreatePanel(wxFrame
*parent
, wxPropertyFormView
*v
)
385 return new wxPropertyFormPanel(v
, parent
);
388 bool wxPropertyFormFrame::Initialize(void)
390 m_propertyPanel
= OnCreatePanel(this, m_view
);
393 m_view
->AssociatePanel(m_propertyPanel
);
394 m_view
->SetManagedWindow(this);
402 * Property form specific validator
405 IMPLEMENT_ABSTRACT_CLASS(wxPropertyFormValidator
, wxPropertyValidator
)
412 IMPLEMENT_DYNAMIC_CLASS(wxRealFormValidator
, wxPropertyFormValidator
)
415 /// Real number form validator
417 bool wxRealFormValidator::OnCheckValue( wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
418 wxWindow
*parentWindow
)
420 if (m_realMin
== 0.0 && m_realMax
== 0.0)
423 // The item used for viewing the real number: should be a text item.
424 wxWindow
*m_propertyWindow
= property
->GetWindow();
425 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
428 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
431 if (!StringToFloat(WXSTRINGCAST value
, &val
))
434 wxSprintf(buf
, wxT("Value %s is not a valid real number!"), (const wxChar
*)value
);
435 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
439 if (val
< m_realMin
|| val
> m_realMax
)
442 wxSprintf(buf
, wxT("Value must be a real number between %.2f and %.2f!"), m_realMin
, m_realMax
);
443 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
449 bool wxRealFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
450 wxWindow
*WXUNUSED(parentWindow
) )
452 // The item used for viewing the real number: should be a text item.
453 wxWindow
*m_propertyWindow
= property
->GetWindow();
454 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
457 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
459 if (value
.Length() == 0)
462 float f
= (float)wxAtof((const wxChar
*)value
);
463 property
->GetValue() = f
;
467 bool wxRealFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
468 wxWindow
*WXUNUSED(parentWindow
) )
470 // The item used for viewing the real number: should be a text item.
471 wxWindow
*m_propertyWindow
= property
->GetWindow();
472 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
475 wxTextCtrl
*textItem
= (wxTextCtrl
*)m_propertyWindow
;
476 textItem
->SetValue(FloatToString(property
->GetValue().RealValue()));
481 /// Integer validator
483 IMPLEMENT_DYNAMIC_CLASS(wxIntegerFormValidator
, wxPropertyFormValidator
)
485 bool wxIntegerFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
486 wxWindow
*parentWindow
)
488 if (m_integerMin
== 0.0 && m_integerMax
== 0.0)
491 // The item used for viewing the real number: should be a text item or a slider
492 wxWindow
*m_propertyWindow
= property
->GetWindow();
493 if (!m_propertyWindow
)
498 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
500 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
502 if (!StringToLong(WXSTRINGCAST value
, &val
))
505 wxSprintf(buf
, wxT("Value %s is not a valid integer!"), (const wxChar
*)value
);
506 wxMessageBox(buf
, wxT("Property value error"), wxOK
| wxICON_EXCLAMATION
, parentWindow
);
510 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
512 val
= (long)((wxSlider
*)m_propertyWindow
)->GetValue();
517 if (val
< m_integerMin
|| val
> m_integerMax
)
520 sprintf(buf
, "Value must be an integer between %ld and %ld!", m_integerMin
, m_integerMax
);
521 wxMessageBox(buf
, "Property value error", wxOK
| wxICON_EXCLAMATION
, parentWindow
);
527 bool wxIntegerFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
528 wxWindow
*WXUNUSED(parentWindow
))
530 // The item used for viewing the real number: should be a text item or a slider
531 wxWindow
*m_propertyWindow
= property
->GetWindow();
532 if (!m_propertyWindow
)
535 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
537 wxString
value(((wxTextCtrl
*)m_propertyWindow
)->GetValue());
539 if (value
.Length() == 0)
542 long i
= wxAtol((const wxChar
*)value
);
543 property
->GetValue() = i
;
545 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
547 property
->GetValue() = (long)((wxSlider
*)m_propertyWindow
)->GetValue();
555 bool wxIntegerFormValidator::OnDisplayValue( wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
556 wxWindow
*WXUNUSED(parentWindow
))
558 // The item used for viewing the real number: should be a text item or a slider
559 wxWindow
*m_propertyWindow
= property
->GetWindow();
560 if (!m_propertyWindow
)
563 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
565 wxTextCtrl
*textItem
= (wxTextCtrl
*)m_propertyWindow
;
566 textItem
->SetValue(LongToString(property
->GetValue().IntegerValue()));
568 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxSlider
)))
570 ((wxSlider
*)m_propertyWindow
)->SetValue((int)property
->GetValue().IntegerValue());
578 /// Boolean validator
580 IMPLEMENT_DYNAMIC_CLASS(wxBoolFormValidator
, wxPropertyFormValidator
)
582 bool wxBoolFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
583 wxWindow
*WXUNUSED(parentWindow
))
585 // The item used for viewing the boolean: should be a checkbox
586 wxWindow
*m_propertyWindow
= property
->GetWindow();
587 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
593 bool wxBoolFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
594 wxWindow
*WXUNUSED(parentWindow
) )
596 // The item used for viewing the boolean: should be a checkbox.
597 wxWindow
*m_propertyWindow
= property
->GetWindow();
598 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
601 wxCheckBox
*checkBox
= (wxCheckBox
*)m_propertyWindow
;
603 property
->GetValue() = (bool)checkBox
->GetValue();
607 bool wxBoolFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
608 wxWindow
*WXUNUSED(parentWindow
))
610 // The item used for viewing the boolean: should be a checkbox.
611 wxWindow
*m_propertyWindow
= property
->GetWindow();
612 if (!m_propertyWindow
|| !m_propertyWindow
->IsKindOf(CLASSINFO(wxCheckBox
)))
615 wxCheckBox
*checkBox
= (wxCheckBox
*)m_propertyWindow
;
616 checkBox
->SetValue((bool)property
->GetValue().BoolValue());
623 IMPLEMENT_DYNAMIC_CLASS(wxStringFormValidator
, wxPropertyFormValidator
)
625 wxStringFormValidator::wxStringFormValidator(wxStringList
*list
, long flags
):
626 wxPropertyFormValidator(flags
)
631 bool wxStringFormValidator::OnCheckValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
632 wxWindow
*parentWindow
)
637 // The item used for viewing the string: should be a text item, choice item or listbox.
638 wxWindow
*m_propertyWindow
= property
->GetWindow();
639 if (!m_propertyWindow
)
641 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
643 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
644 if (!m_strings
->Member(text
->GetValue()))
646 wxString
s("Value ");
647 s
+= text
->GetValue();
648 s
+= " is not valid.";
649 wxMessageBox(s
, "Property value error", wxOK
| wxICON_EXCLAMATION
, parentWindow
);
655 // Any other item constrains the string value,
656 // so we don't have to check it.
661 bool wxStringFormValidator::OnRetrieveValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
662 wxWindow
*WXUNUSED(parentWindow
) )
664 // The item used for viewing the string: should be a text item, choice item or listbox.
665 wxWindow
*m_propertyWindow
= property
->GetWindow();
666 if (!m_propertyWindow
)
668 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
670 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
671 property
->GetValue() = text
->GetValue();
673 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxListBox
)))
675 wxListBox
*lbox
= (wxListBox
*)m_propertyWindow
;
676 if (lbox
->GetSelection() > -1)
677 property
->GetValue() = lbox
->GetStringSelection();
680 else if (m_propertyWindow->IsKindOf(CLASSINFO(wxRadioBox)))
682 wxRadioBox *rbox = (wxRadioBox *)m_propertyWindow;
684 if ((n = rbox->GetSelection()) > -1)
685 property->GetValue() = rbox->GetString(n);
688 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxChoice
)))
690 wxChoice
*choice
= (wxChoice
*)m_propertyWindow
;
691 if (choice
->GetSelection() > -1)
692 property
->GetValue() = choice
->GetStringSelection();
699 bool wxStringFormValidator::OnDisplayValue(wxProperty
*property
, wxPropertyFormView
*WXUNUSED(view
),
700 wxWindow
*WXUNUSED(parentWindow
) )
702 // The item used for viewing the string: should be a text item, choice item or listbox.
703 wxWindow
*m_propertyWindow
= property
->GetWindow();
704 if (!m_propertyWindow
)
706 if (m_propertyWindow
->IsKindOf(CLASSINFO(wxTextCtrl
)))
708 wxTextCtrl
*text
= (wxTextCtrl
*)m_propertyWindow
;
709 text
->SetValue(property
->GetValue().StringValue());
711 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxListBox
)))
713 wxListBox
*lbox
= (wxListBox
*)m_propertyWindow
;
714 if (lbox
->Number() == 0 && m_strings
)
716 // Try to initialize the listbox from 'strings'
717 wxNode
*node
= m_strings
->First();
720 char *s
= (char *)node
->Data();
725 lbox
->SetStringSelection(property
->GetValue().StringValue());
728 else if (m_propertyWindow->IsKindOf(CLASSINFO(wxRadioBox)))
730 wxRadioBox *rbox = (wxRadioBox *)m_propertyWindow;
731 rbox->SetStringSelection(property->GetValue().StringValue());
734 else if (m_propertyWindow
->IsKindOf(CLASSINFO(wxChoice
)))
736 wxChoice
*choice
= (wxChoice
*)m_propertyWindow
;
738 if (choice
->Number() == 0 && m_strings
)
740 // Try to initialize the choice item from 'strings'
741 // XView doesn't allow this kind of thing.
742 wxNode
*node
= m_strings
->First();
745 char *s
= (char *)node
->Data();
751 choice
->SetStringSelection(property
->GetValue().StringValue());