1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
31 // Contact(s): julians
33 // Version: $Id: configitem.cpp,v 1.10 2001/04/30 17:12:32 julians Exp $
35 // Description: Implementation file for the ConfigTool application class
42 //####DESCRIPTIONEND####
44 //===========================================================================
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 #pragma implementation "configitem.h"
57 // Includes other headers for precompiled compilation
64 #include "wx/settings.h"
65 #include "wx/valgen.h"
67 #include "configitem.h"
68 #include "configtree.h"
69 #include "configtooldoc.h"
70 #include "configtoolview.h"
73 IMPLEMENT_CLASS(ecConfigItem, wxObject)
77 * Represents a node in the configuration hierarchy.
78 * For every ecConfigItem, there is also an ecTreeItemData
82 ecConfigItem::ecConfigItem(ecConfigItem* parent, const wxString& name, ecConfigType ctype,
83 ecOptionFlavor flavor, ecOptionType otype,
84 bool active, bool enabled, ecUIHint hint)
90 m_optionFlavor = flavor;
95 m_treeItem = wxTreeItemId();
117 m_value = (bool) FALSE;
127 ecConfigItem::ecConfigItem(ecConfigItem* parent, CdlUserVisible vitem)
129 m_name = wxT("UNNAMED");
130 m_configType = ecConfigTypeNone;
131 m_optionType = ecOptionTypeNone;
132 m_optionFlavor = ecFlavorNone;
138 m_treeItem = wxTreeItemId();
140 ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl();
141 m_treeItem = treeCtrl->AppendItem(parent->GetTreeItem(), m_name, -1, -1, new ecTreeItemData(this));
144 UpdateTreeItem(* treeCtrl);
147 ecConfigItem::~ecConfigItem()
149 // Make sure that the tree item no longer references this object
150 ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl();
151 if (m_treeItem && treeCtrl)
153 ecTreeItemData* data = (ecTreeItemData*) treeCtrl->GetItemData(m_treeItem);
154 data->SetConfigItem(NULL);
157 ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc();
160 doc->GetItems().DeleteObject(this);
164 // Convert from Cdl to internal representation
165 bool ecConfigItem::ConvertFromCdl()
170 m_name = GetCdlItem()->get_display ().c_str ();
171 m_macro = GetCdlItem()->get_name().c_str();
172 m_strDescr = ecUtils::StripExtraWhitespace (wxString (GetCdlItem()->get_description ().c_str ()));
175 // FIXME: re-implement using CdlValuableBody::get_widget_hint()
176 // (comment from original MFC configtool)
180 // If a package item, display the package version string
181 m_optionType = ecString;
182 m_configType = ecPackage;
183 m_optionFlavor = ecFlavorNone;
187 const CdlValuable valuable = dynamic_cast<CdlValuable> (GetCdlItem());
188 switch (valuable->get_flavor ()){
189 case CdlValueFlavor_None:
190 m_optionFlavor = ecFlavorNone;
191 m_optionType=ecOptionTypeNone; //??? Shouldn't it be ecBool for CdlValueFlavor_Bool?
192 m_configType = ecContainer;
194 case CdlValueFlavor_Bool:
195 m_optionFlavor = ecFlavorBool;
196 m_optionType=ecOptionTypeNone; //??? Shouldn't it be ecBool for CdlValueFlavor_Bool?
197 m_configType = ecOption;
198 m_hint = (HasRadio() ? ecHintRadio : ecHintCheck);
200 case CdlValueFlavor_Data:
201 case CdlValueFlavor_BoolData:
203 m_optionFlavor = (valuable->get_flavor() == CdlValueFlavor_Data ? ecFlavorData : ecFlavorBoolData);
204 m_configType = ecOption;
205 m_hint = (HasRadio() ? ecHintRadio : ecHintCheck);
207 if (! valuable->has_legal_values ()) {
208 m_optionType=ecString;
209 } else if (0 == valuable->get_legal_values ()->ranges.size ()) {
210 m_optionType=ecEnumerated;
212 CdlListValue list_value;
213 CdlEvalContext context (NULL, valuable, valuable->get_property (CdlPropertyId_LegalValues));
214 valuable->get_legal_values ()->eval (context, list_value);
215 m_optionType=list_value.get_double_ranges ().size () ? ecDouble : ecLong;
219 wxASSERT (0); // specified flavor not supported
224 m_active = IsActive();
225 m_enabled = IsEnabled();
230 wxString ecConfigItem::GetItemNameOrMacro() const
232 return (wxGetApp().GetSettings().m_showMacroNames && !GetMacro().IsEmpty() ? GetMacro() : GetName());
235 // Sets the text and icon for this item
236 bool ecConfigItem::UpdateTreeItem(ecConfigTreeCtrl& treeCtrl)
238 treeCtrl.SetItemText(m_treeItem, m_name);
240 static wxColour normalColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
241 static wxColour disabledColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT);
243 treeCtrl.SetItemTextColour(m_treeItem, GetActive() ? normalColour : disabledColour);
246 // Find which icon state we're in so we can get the appropriate icon id
250 switch (GetConfigType())
254 iconName = _("Container");
260 iconName = _("Package");
272 if (GetOptionFlavor() == ecFlavorData)
274 switch (GetOptionType())
279 iconName = _("Integer");
285 iconName = _("Enumerated");
291 iconName = _("Text");
295 // ??? Actually I don't think there's such a think as ecBool type, only enabled/disabled
298 if (GetUIHint() == ecHintCheck)
299 iconName = _("Checkbox");
301 iconName = _("Radiobox");
302 iconState = (m_value.GetBool() ? 0 : 1);
311 if (GetOptionFlavor() == ecFlavorBoolData || GetOptionFlavor() == ecFlavorBool)
313 if (GetUIHint() == ecHintCheck)
314 iconName = _("Checkbox");
316 iconName = _("Radiobox");
317 iconState = (m_enabled ? 0 : 1);
327 if (!iconName.IsEmpty())
329 int iconId = treeCtrl.GetIconDB().GetIconId(iconName, iconState, GetActive());
330 treeCtrl.SetItemImage(m_treeItem, iconId, wxTreeItemIcon_Normal);
331 treeCtrl.SetItemImage(m_treeItem, iconId, wxTreeItemIcon_Selected);
337 // Handle a left click on the icon: e.g. (un)check the option
338 // In the old MFC tool, this was handled by CControlView::Bump
339 void ecConfigItem::OnIconLeftDown(ecConfigTreeCtrl& treeCtrl)
341 if (GetConfigType() != ecOption)
344 switch (GetOptionFlavor())
347 case ecFlavorBoolData:
351 wxGetApp().GetConfigToolDoc()->SetEnabled(*this, !m_enabled);
359 switch (GetOptionType())
365 long nOldValue = Value();
366 if(nInc==1 && nOldValue == long(-1))
369 } else if(nInc==-1 && nOldValue==0){
370 nOldValue = long(-1);
374 wxGetApp().GetConfigToolDoc()->SetValue(*this, nOldValue);
381 wxArrayString arEnum;
382 EvalEnumStrings (arEnum); // calculate legal values just in time
383 if (0 == arEnum.GetCount()) // if no legal values...
384 break; // ...do nothing
386 const wxString strCurrent = StringValue ();
388 for (nEnum = 0; (nEnum < arEnum.GetCount()) && (nIndex == -1); nEnum++)
389 if (0 == arEnum[nEnum].CompareTo (strCurrent))
390 nIndex = nEnum; // the index of the current value
392 if (nIndex != -1) // if the current value is still legal
393 nIndex += (nInc < 0 ? -1 : 1); // increment/decrement the index
395 nIndex = 0; // otherwise select the first enum
397 if (nIndex < 0) // if the new index is negative
398 nIndex = arEnum.GetCount()-1; // make it positive
400 wxGetApp().GetConfigToolDoc()->SetValue(*this, arEnum[nIndex % arEnum.GetCount()]);
419 // Gets the value to display (often an empty string)
420 wxString ecConfigItem::GetDisplayValue() const
423 switch(GetOptionType())
430 if (GetCdlValuable())
439 switch (GetConfigType())
444 return wxEmptyString;
449 return m_value.GetString();
454 switch (GetOptionType())
459 val.Printf("%.4lf", (double) m_value.GetDouble());
465 val.Printf("%.ld", (long) m_value.GetLong());
472 return m_value.GetString();
477 return wxEmptyString;
493 return wxEmptyString;
497 // Can we start editing this item?
498 bool ecConfigItem::CanEdit() const
503 if (GetConfigType() != ecOption)
506 if (GetOptionFlavor() != ecFlavorData && GetOptionFlavor() != ecFlavorBoolData)
509 // TODO: other criteria for editability
514 // Creates an edit window. It will be positioned by the caller.
515 wxWindow* ecConfigItem::CreateEditWindow(wxWindow* parent)
517 wxWindow* window = NULL;
519 switch(GetOptionType())
523 window = new ecEnumEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize,
524 /* wxNO_BORDER */ 0);
525 wxArrayString arEnumStrings;
526 EvalEnumStrings(arEnumStrings);
528 for (i = 0; i < arEnumStrings.GetCount(); i++)
530 ((ecEnumEditorCtrl*) window)->Append(arEnumStrings[i]);
536 window = new ecIntegerEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize,
537 /* wxNO_BORDER | */ wxSP_ARROW_KEYS);
542 window = new ecDoubleEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize,
543 /* wxNO_BORDER|*/ wxTE_PROCESS_ENTER);
548 window = new ecTextEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize,
549 /* wxNO_BORDER|*/ wxTE_PROCESS_ENTER);
556 wxASSERT (window != NULL) ;
561 // Transfers data between item and window
562 bool ecConfigItem::TransferDataToWindow(wxWindow* window)
564 if (window->IsKindOf(CLASSINFO(ecTextEditorCtrl)))
566 ecTextEditorCtrl* win = (ecTextEditorCtrl*) window;
567 win->SetValue(GetDisplayValue());
569 else if (window->IsKindOf(CLASSINFO(ecDoubleEditorCtrl)))
571 ecDoubleEditorCtrl* win = (ecDoubleEditorCtrl*) window;
572 win->SetValue(GetDisplayValue());
574 else if (window->IsKindOf(CLASSINFO(ecEnumEditorCtrl)))
576 ecEnumEditorCtrl* win = (ecEnumEditorCtrl*) window;
577 win->SetStringSelection(GetDisplayValue());
579 else if (window->IsKindOf(CLASSINFO(ecIntegerEditorCtrl)))
581 ecIntegerEditorCtrl* win = (ecIntegerEditorCtrl*) window;
583 ecUtils::StrToItemIntegerType(StringValue(), i);
586 val.Printf(wxT("%ld"), i);
593 bool ecConfigItem::TransferDataFromWindow(wxWindow* window)
595 ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc();
596 wxASSERT (doc != NULL);
601 if (window->IsKindOf(CLASSINFO(ecTextEditorCtrl)))
603 ecTextEditorCtrl* win = (ecTextEditorCtrl*) window;
605 wxASSERT ( GetOptionType() == ecString );
608 doc->SetValue(*this, win->GetValue());
610 else if (window->IsKindOf(CLASSINFO(ecDoubleEditorCtrl)))
612 ecDoubleEditorCtrl* win = (ecDoubleEditorCtrl*) window;
614 wxASSERT ( GetOptionType() == ecString );
617 doc->SetValue(*this, atof(win->GetValue()));
619 else if (window->IsKindOf(CLASSINFO(ecEnumEditorCtrl)))
621 ecEnumEditorCtrl* win = (ecEnumEditorCtrl*) window;
623 wxASSERT ( GetOptionType() == ecEnumerated );
626 doc->SetValue(*this, win->GetStringSelection());
628 else if (window->IsKindOf(CLASSINFO(ecIntegerEditorCtrl)))
630 ecIntegerEditorCtrl* win = (ecIntegerEditorCtrl*) window;
632 wxASSERT ( GetOptionType() == ecLong );
635 doc->SetValue(*this, (long) win->GetValue());
641 //// Taken from MFC version
643 const ecFileName ecConfigItem::GetFilename() const
645 wxString sep(wxFILE_SEP_PATH);
648 const CdlNode node = dynamic_cast<CdlNode> (m_CdlItem);
650 // get the package which owns the configuration item
651 const CdlPackage package = GetOwnerPackage();
654 // return the filename of the config header
655 wxString pkg(wxT("include"));
657 pkg += wxT("pkgconf");
658 strFile=ecFileName(wxGetApp().GetConfigToolDoc()->GetInstallTree()+sep+pkg) + package->get_config_header ().c_str ();
664 // Change version (of a package)
665 bool ecConfigItem::ChangeVersion(const wxString &strVersion)
668 CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
669 wxASSERT(package != 0);
670 const CdlValuable valuable = GetCdlValuable();
671 wxASSERT (valuable != 0);
672 const wxString strMacroName(GetMacro());
673 if (strVersion != valuable->get_value ().c_str ()) { // if the wrong version is loaded
674 // TRACE (wxT("Changing package %s to version '%s'\n"), strMacroName, strVersion);
676 wxGetApp().GetConfigToolDoc()->GetCdlConfig()->change_package_version (package, ecUtils::UnicodeToStdStr (strVersion), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler);
679 catch (CdlStringException exception) {
681 msg.Printf(wxT("Error changing package %s to version '%s':\n\n%s"), (const wxChar*) strMacroName, (const wxChar*) strVersion, (const wxChar*) wxString (exception.get_message ().c_str ())) ;
686 msg.Printf(wxT("Error changing package %s to version '%s'"), (const wxChar*) strMacroName, (const wxChar*) strVersion) ;
693 // Unload (a package)
694 bool ecConfigItem::Unload()
697 CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
699 ecConfigToolDoc* pDoc=wxGetApp().GetConfigToolDoc();
701 // Remove its objects from the view to prevent any painting problems
702 ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(GetTreeItem());
705 // I _think_ we should do this to stop 'this' from being deleted when we delete the item.
706 // But, in that case, where do we delete this item?
707 // Perhaps should store them in an array in the document, as per the MFC tool.
708 data->SetConfigItem(NULL);
710 wxGetApp().GetTreeCtrl()->Delete(GetTreeItem());
712 wxNode* node = pDoc->GetItems().First();
715 ecConfigItem* item = wxDynamicCast(node->Data(), ecConfigItem);
716 if (package == item->GetOwnerPackage())
718 item->SetTreeItem(wxTreeItemId()); // Make sure we can't attempt to paint it
719 item->SetCdlItem(NULL); // Make sure we can't access stale data
724 const wxString strMacroName(GetMacro());
725 //TRACE (wxT("Unloading package %s\n"), strMacroName);
727 pDoc->GetCdlConfig()->unload_package (package);
730 catch (CdlStringException exception) {
732 wxString exceptionMsg(exception.get_message ().c_str ());
733 msg.Printf(wxT("Error unloading package %s:\n\n%s"), (const wxChar*) strMacroName, (const wxChar*) exceptionMsg );
738 msg.Printf(wxT("Error unloading package %s"), (const wxChar*) strMacroName);
741 m_treeItem=wxTreeItemId(); // Make sure we can't attempt to paint it
742 m_CdlItem=NULL; // Make sure we can't access stale data
746 wxString ecConfigItem::GetURL() const
748 for(const ecConfigItem *pItem=this;pItem;pItem=pItem->GetParent()){
749 if(pItem->GetCdlItem()){
751 strURL=pItem->GetCdlItem()->get_doc_url().c_str();
755 strURL=pItem->GetCdlItem()->get_doc().c_str();
761 return wxT("ref/ecos-ref.html"); // the default URL
764 bool ecConfigItem::SetValue(const wxString& value, CdlTransaction transaction/*=NULL*/)
766 wxASSERT ((m_optionType == ecString) || (m_optionType == ecEnumerated));
767 const CdlValuable valuable = GetCdlValuable();
769 const std::string str = value.c_str();
771 if (CdlValueFlavor_BoolData == valuable->get_flavor ()){
772 // set the user bool to the current bool when changing a booldata
773 // value to avoid a possible change in the current bool
774 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), str, CdlValueSource_User);
775 } else {// CdlValueFlavor_Data
776 valuable->set_value (transaction, str, CdlValueSource_User);
779 if (CdlValueFlavor_BoolData == valuable->get_flavor ()){
780 // set the user bool to the current bool when changing a booldata
781 // value to avoid a possible change in the current bool
782 valuable->set_enabled_and_value (valuable->is_enabled (), str, CdlValueSource_User);
783 } else {// CdlValueFlavor_Data
784 valuable->set_value (str, CdlValueSource_User);
788 // TODO: eliminate m_value, since the value is always taken from the Cdl object.
794 bool ecConfigItem::SetValue (double dValue, CdlTransaction transaction/*=NULL*/)
796 wxASSERT (m_optionType == ecDouble);
798 const CdlValuable valuable = GetCdlValuable();
802 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
803 // set the user bool to the current bool when changing a booldata
804 // value to avoid a possible change in the current bool
805 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), dValue, CdlValueSource_User);
806 } else {// CdlValueFlavor_Data
807 valuable->set_double_value (transaction, dValue, CdlValueSource_User);
810 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
811 // set the user bool to the current bool when changing a booldata
812 // value to avoid a possible change in the current bool
813 valuable->set_enabled_and_value (valuable->is_enabled (), dValue, CdlValueSource_User);
814 } else {// CdlValueFlavor_Data
815 valuable->set_double_value (dValue, CdlValueSource_User);
825 bool ecConfigItem::SetValue (long nValue, CdlTransaction transaction/*=NULL*/)
827 wxASSERT (m_optionType == ecLong);
828 const CdlValuable valuable = GetCdlValuable();
832 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
833 // set the user bool to the current bool when changing a booldata
834 // value to avoid a possible change in the current bool
835 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User);
836 } else { // CdlValueFlavor_Data
837 valuable->set_integer_value (transaction, nValue, CdlValueSource_User);
840 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
841 // set the user bool to the current bool when changing a booldata
842 // value to avoid a possible change in the current bool
843 valuable->set_enabled_and_value (valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User);
844 } else { // CdlValueFlavor_Data
845 valuable->set_integer_value (nValue, CdlValueSource_User);
855 bool ecConfigItem::HasRadio() const
857 const CdlValuable valuable = GetCdlValuable();
862 valuable->get_widget_hint (hint);
863 return (CdlBoolWidget_Radio == hint.bool_widget);
866 ecConfigItem *ecConfigItem::FirstRadio() const
868 wxASSERT(HasRadio ());
870 for(ecConfigItem *h=GetParent()->FirstChild();h;h=h->NextSibling()){
875 // No radio buttons found
880 ecConfigItem *ecConfigItem::FirstChild() const
882 ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl();
885 wxTreeItemId hChild=treeCtrl->GetFirstChild(GetTreeItem(), cookie);
888 ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(hChild);
891 return data->GetConfigItem();
897 ecConfigItem *ecConfigItem::NextSibling() const
899 ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl();
901 wxTreeItemId hChild=treeCtrl->GetNextSibling(GetTreeItem());
904 ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(hChild);
907 return data->GetConfigItem();
913 bool ecConfigItem::IsEnabled() const
915 const CdlValuable valuable = GetCdlValuable();
916 return NULL==valuable ||valuable->is_enabled();
919 bool ecConfigItem::IsActive() const
921 // return GetCdlItem()->is_active();
922 const CdlValuable valuable = GetCdlValuable();
923 if (valuable && ((GetOptionType() != ecOptionTypeNone) || HasBool()))
925 return (valuable->is_modifiable () && valuable->is_active ());
928 return GetCdlItem()->is_active();
931 bool ecConfigItem::HasModifiedChildren() const
933 for(ecConfigItem *pItem=FirstChild();pItem;pItem=pItem->NextSibling()){
934 if(pItem->Modified()||pItem->HasModifiedChildren()){
941 bool ecConfigItem::Modified () const
943 const CdlValuable valuable = GetCdlValuable();
945 valuable // accommodate the root config item which has no CDL item
946 && !IsPackage() // packages are never modified
947 && valuable->get_source () != CdlValueSource_Default;
950 void ecConfigItem::DumpItem()
952 //TRACE(wxT("Item %08x\n\tDisplay Name='%s'\n\tMacro Name='%s'\n\tType=%s"), this, Name(), Macro(), TreeItemTypeImage[m_Type]);
953 //TRACE(wxT("\n\tValue=%s\n\tURL=%s\n\tParent=%08x"),StringValue(), GetURL(), Parent());
958 ecConfigItem * ecConfigItem::NextRadio() const
960 wxASSERT(this->HasRadio ());
961 for(ecConfigItem *pItem=NextSibling();pItem;pItem=pItem->NextSibling()){
962 if(pItem->HasRadio()){
969 bool ecConfigItem::IsDescendantOf(ecConfigItem * pAncestor)
971 for(ecConfigItem *pItem=GetParent();pItem;pItem=pItem->GetParent()){
972 if(pItem==pAncestor){
979 bool ecConfigItem::ViewHeader()
982 const ecFileName strFile(GetFilename());
983 if(!strFile.IsEmpty())
985 ecConfigToolDoc *pDoc=wxGetApp().GetConfigToolDoc();
986 if(pDoc->GetBuildTree().IsEmpty()){
988 msg.Printf(wxT("Cannot display header file until configuration is saved"));
992 rc=wxGetApp().Launch(strFile, wxGetApp().GetSettings().m_strViewer);
998 bool ecConfigItem::ViewURL()
1000 return wxGetApp().GetConfigToolDoc()->ShowURL(GetURL());
1003 bool ecConfigItem::HasBool() const
1007 } else if (IsPackage()) {
1010 const CdlValuable valuable = GetCdlValuable();
1011 CdlValueFlavor flavor = valuable->get_flavor ();
1012 return (flavor == CdlValueFlavor_Bool) || (flavor == CdlValueFlavor_BoolData);
1016 bool ecConfigItem::SetEnabled(bool bEnabled, CdlTransaction current_transaction/*=NULL*/)
1018 const CdlValuable valuable = GetCdlValuable();
1019 wxASSERT (valuable);
1021 // use a transaction object to ensure that all config items are changed together
1022 CdlTransaction transaction = current_transaction ? current_transaction : CdlTransactionBody::make (wxGetApp().GetConfigToolDoc ()->GetCdlConfig ());
1024 if (HasRadio () && bEnabled) { // if a new radio button has been selected
1025 for (ecConfigItem *pItem = FirstRadio(); pItem; pItem = pItem->NextRadio ()) { // for each radio button in the group
1026 if (pItem != this) { // if not the newly selected radio button
1027 pItem->SetEnabled (FALSE, transaction); // disable the radio button
1032 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
1033 // set the user value to the current data value when enabling/disabling
1034 // a booldata item to avoid a possible change in the current data value
1035 CdlSimpleValue simple_value = valuable->get_simple_value ();
1036 valuable->set_enabled_and_value (transaction, bEnabled, simple_value, CdlValueSource_User);
1037 } else { // CdlValueFlavor_Bool
1038 valuable->set_enabled (transaction, bEnabled, CdlValueSource_User);
1041 if (! current_transaction) { // if not a recursive call to disable a radio button
1042 transaction->body (); // commit the transaction
1050 long ecConfigItem::DefaultValue () const
1052 return (long) atoi (StringValue (CdlValueSource_Default)) ;
1055 long ecConfigItem::Value () const
1057 wxASSERT (!IsPackage()); // not a package item
1058 const CdlValuable valuable = GetCdlValuable();
1059 wxASSERT (valuable);
1062 switch (valuable->get_flavor ())
1064 // case CdlValueFlavor_Bool:
1065 // nValue = valuable->is_enabled (CdlValueSource_Current) ? 1 : 0;
1068 case CdlValueFlavor_BoolData:
1069 case CdlValueFlavor_Data:
1070 nValue = (long) valuable->get_integer_value (CdlValueSource_Current);
1074 wxASSERT (0); // specified flavor not supported
1080 const double ecConfigItem::DoubleValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
1082 wxASSERT (!IsPackage()); // not a package item
1083 const CdlValuable valuable = GetCdlValuable();
1084 wxASSERT (valuable);
1085 wxASSERT (valuable->has_double_value (source));
1086 return valuable->get_double_value (source);
1089 const wxString ecConfigItem::StringValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
1091 // wxASSERT (!IsPackage()); // not a package item
1092 const CdlValuable valuable = GetCdlValuable();
1093 wxASSERT (valuable);
1094 wxString strValue (wxT(""));
1096 switch (valuable->get_flavor ())
1098 case CdlValueFlavor_Data:
1099 case CdlValueFlavor_BoolData:
1100 case CdlValueFlavor_None: // a package
1101 if (m_optionType == ecLong)
1102 strValue = ecUtils::IntToStr (Value (), wxGetApp().GetSettings().m_bHex);
1103 else if (m_optionType == ecDouble)
1104 strValue = ecUtils::DoubleToStr (DoubleValue ());
1106 strValue = valuable->get_value (source).c_str ();
1110 wxASSERT (0); // specified flavor not supported
1116 const wxString ecConfigItem::StringValue(ecWhereType where) const
1127 str=GetDescription();
1129 case ecInCurrentValue:
1130 if (ecOptionTypeNone==GetOptionType())
1131 str = wxEmptyString;
1133 str = StringValue(CdlValueSource_Current);
1135 case ecInDefaultValue:
1136 if (ecOptionTypeNone==GetOptionType())
1137 str = wxEmptyString;
1139 str = StringValue(CdlValueSource_Default);
1148 int ecConfigItem::EvalEnumStrings (wxArrayString &arEnumStrings) const
1150 const CdlValuable valuable = GetCdlValuable();
1151 wxASSERT (valuable);
1153 if (m_Type == Boolean)
1155 arEnumStrings.SetSize (2);
1156 arEnumStrings.SetAt (0, wxT("True"));
1157 arEnumStrings.SetAt (1, wxT("False"));
1162 wxASSERT (m_optionType == ecEnumerated);
1163 CdlListValue list_value;
1164 CdlEvalContext context (NULL, m_CdlItem, m_CdlItem->get_property (CdlPropertyId_LegalValues));
1165 valuable->get_legal_values ()->eval (context, list_value);
1166 const std::vector<CdlSimpleValue> & table = list_value.get_table ();
1168 // add legal values to the list
1169 for (unsigned int nValue = 0; nValue < table.size (); nValue++)
1171 arEnumStrings.Add (table [nValue].get_value ().c_str ());
1174 return arEnumStrings.GetCount();
1177 static const wxChar* gs_whereTypes[] =
1181 _("Short descriptions"),
1182 _("Current Values"),
1186 // Convert a string representation of 'where' (e.g. "Macro names") to
1188 ecWhereType ecConfigItem::WhereStringToType(const wxString& whereString)
1192 for (i = 0; i < sz; i++)
1193 if (whereString == gs_whereTypes[i])
1194 return (ecWhereType) i;
1198 return (ecWhereType) 0;
1201 // Convert a type representation of 'where' to a string
1202 wxString ecConfigItem::WhereTypeToString(ecWhereType whereType)
1204 return gs_whereTypes[(size_t) whereType] ;
1207 // Bump by specified amount, or toggle if a boolean value
1208 bool ecConfigItem::BumpItem(int nInc)
1212 // Take an action for clicking on the icon
1213 ecConfigToolDoc* pDoc = wxGetApp().GetConfigToolDoc();
1215 // do not modify the option value if it is inactive or not modifiable
1216 const CdlValuable valuable = GetCdlValuable();
1217 if (!valuable || (valuable->is_modifiable () && valuable->is_active ()))
1219 if (0 == nInc) // if a toggle request
1221 if (HasBool () && ! (HasRadio () && IsEnabled ())) { // only enable (not disable) a radio button
1222 rc = pDoc->SetEnabled (*this, ! this->IsEnabled ()); // toggle enabled/disabled state
1224 } else if (IsEnabled ()) { // the item is enabled...
1225 switch(GetOptionType())
1227 case ecOptionTypeNone:
1233 wxArrayString arEnum;
1234 EvalEnumStrings (arEnum); // calculate legal values just in time
1235 if (0==arEnum.Count()) // if no legal values...
1236 break; // ...do nothing
1238 const wxString strCurrent = StringValue ();
1240 for (nEnum = 0; (nEnum < arEnum.Count()) && (nIndex == -1); nEnum++)
1241 if (strCurrent == arEnum[nEnum])
1242 nIndex = nEnum; // the index of the current value
1244 if (nIndex != -1) // if the current value is still legal
1245 nIndex += (nInc < 0 ? -1 : 1); // increment/decrement the index
1247 nIndex = 0; // otherwise select the first enum
1249 if (nIndex < 0) // if the new index is negative
1250 nIndex = arEnum.Count()-1; // make it positive
1252 rc=pDoc->SetValue (*this, arEnum[nIndex % arEnum.Count()]);
1257 // TODO: if we're editing, we should get the value in the edit item
1258 // and not the ecConfigItem.
1259 long nOldValue = Value();
1260 if(nInc==1 && nOldValue==-1){
1262 } else if(nInc==-1 && nOldValue==0){
1267 rc=pDoc->SetValue(*this, nOldValue);
1273 case CConfigItem::Boolean:
1276 ItemIntegerType nOldValue=Value(h);
1277 pDoc->SetValue(ti,nOldValue^1);
1280 case CConfigItem::Radio:
1283 pDoc->SetValue(ti, (ItemIntegerType) 1);
1297 /* Presumably we don't need this since we use the m_parent member instead
1298 ecConfigItem *ecConfigItem::Parent() const
1300 CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
1301 HTREEITEM hParent=tree.GetParentItem(HItem());
1302 return (NULL==hParent||TVI_ROOT==hParent)?NULL:(ecConfigItem *)tree.GetItemData(hParent);
1310 * A specialised wxTextCtrl, for editing config values
1313 BEGIN_EVENT_TABLE(ecTextEditorCtrl, wxTextCtrl)
1314 EVT_TEXT_ENTER(-1, ecTextEditorCtrl::OnEnter)
1315 EVT_KILL_FOCUS(ecTextEditorCtrl::OnKillFocus)
1316 EVT_LEFT_DCLICK(ecTextEditorCtrl::OnLeftDClick)
1319 IMPLEMENT_CLASS(ecTextEditorCtrl, wxTextCtrl)
1321 ecTextEditorCtrl::ecTextEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1323 wxTextCtrl(parent, id, wxEmptyString, pos, size, style)
1327 void ecTextEditorCtrl::OnEnter(wxCommandEvent& event)
1329 ecValueWindow* parent = (ecValueWindow*) GetParent();
1330 parent->EndEditing();
1333 void ecTextEditorCtrl::OnKillFocus(wxFocusEvent& event)
1335 ecValueWindow* parent = (ecValueWindow*) GetParent();
1336 parent->EndEditing();
1339 // Edit the string in a separate dialog, for convenience
1340 void ecTextEditorCtrl::OnLeftDClick(wxMouseEvent& event)
1342 ecValueWindow* parent = (ecValueWindow*) GetParent();
1343 ecConfigItem* item = parent->GetCurrentConfigItem();
1344 ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc();
1346 wxString initialValue(GetValue());
1348 ecEditStringDialog dialog(initialValue, wxGetApp().GetTopWindow(), ecID_EDIT_STRING_DIALOG);
1349 if (dialog.ShowModal() == wxID_OK)
1351 wxString val = dialog.GetValue() ;
1352 // This control will have been deleted at this point, due to losing the focus.
1353 // So update the item, not the control.
1354 // wxTextCtrl::SetValue(val);
1355 doc->SetValue(*item, val);
1360 * ecDoubleEditorCtrl
1361 * A specialised wxTextCtrl, for editing double config values
1364 BEGIN_EVENT_TABLE(ecDoubleEditorCtrl, wxTextCtrl)
1365 EVT_TEXT_ENTER(-1, ecDoubleEditorCtrl::OnEnter)
1366 EVT_KILL_FOCUS(ecDoubleEditorCtrl::OnKillFocus)
1369 IMPLEMENT_CLASS(ecDoubleEditorCtrl, wxTextCtrl)
1371 ecDoubleEditorCtrl::ecDoubleEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1373 wxTextCtrl(parent, id, wxEmptyString, pos, size, style)
1377 void ecDoubleEditorCtrl::OnEnter(wxCommandEvent& event)
1379 ecValueWindow* parent = (ecValueWindow*) GetParent();
1380 parent->EndEditing();
1383 void ecDoubleEditorCtrl::OnKillFocus(wxFocusEvent& event)
1385 ecValueWindow* parent = (ecValueWindow*) GetParent();
1386 parent->EndEditing();
1390 * ecIntegerEditorCtrl
1391 * A specialised wxTextCtrl, for editing double config values
1394 BEGIN_EVENT_TABLE(ecIntegerEditorCtrl, wxSpinCtrl)
1395 EVT_TEXT_ENTER(-1, ecIntegerEditorCtrl::OnEnter)
1396 EVT_KILL_FOCUS(ecIntegerEditorCtrl::OnKillFocus)
1399 IMPLEMENT_CLASS(ecIntegerEditorCtrl, wxSpinCtrl)
1401 ecIntegerEditorCtrl::ecIntegerEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1403 wxSpinCtrl(parent, id, wxEmptyString, pos, size, style, -32000, 32000, 0)
1407 void ecIntegerEditorCtrl::OnEnter(wxCommandEvent& event)
1409 ecValueWindow* parent = (ecValueWindow*) GetParent();
1410 parent->EndEditing();
1413 void ecIntegerEditorCtrl::OnKillFocus(wxFocusEvent& event)
1415 ecValueWindow* parent = (ecValueWindow*) GetParent();
1416 parent->EndEditing();
1421 * A specialised wxChoice, for editing enumerated config values
1424 BEGIN_EVENT_TABLE(ecEnumEditorCtrl, wxChoice)
1425 EVT_CHAR(ecEnumEditorCtrl::OnChar)
1426 EVT_KILL_FOCUS(ecEnumEditorCtrl::OnKillFocus)
1429 IMPLEMENT_CLASS(ecEnumEditorCtrl, wxChoice)
1431 ecEnumEditorCtrl::ecEnumEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1433 wxChoice(parent, id, pos, size, 0, 0, style)
1437 void ecEnumEditorCtrl::OnChar(wxKeyEvent& event)
1439 if (event.GetKeyCode() == WXK_RETURN)
1441 ecValueWindow* parent = (ecValueWindow*) GetParent();
1442 parent->EndEditing();
1448 void ecEnumEditorCtrl::OnKillFocus(wxFocusEvent& event)
1450 ecValueWindow* parent = (ecValueWindow*) GetParent();
1451 parent->EndEditing();
1455 * ecEditStringDialog
1456 * Pops up to make it easier to edit large string values
1459 BEGIN_EVENT_TABLE(ecEditStringDialog, ecDialog)
1460 EVT_BUTTON(wxID_OK, ecEditStringDialog::OnOK)
1463 ecEditStringDialog::ecEditStringDialog(const wxString& initialValue, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1466 m_value = initialValue;
1467 //SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
1469 ecDialog::Create(parent, id, _("String Edit"),
1470 wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
1472 CreateControls(this);
1474 TransferDataToWindow();
1479 ecEditStringDialog::~ecEditStringDialog()
1485 void ecEditStringDialog::OnOK(wxCommandEvent& event)
1487 wxDialog::OnOK(event);
1491 void ecEditStringDialog::CreateControls(wxWindow* parent)
1493 wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1495 wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
1497 item1->Add( 20, 20, 10, wxALIGN_CENTRE|wxALL, 5 );
1499 wxButton *item2 = new wxButton( parent, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
1500 item2->SetDefault();
1501 item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 );
1503 wxButton *item3 = new wxButton( parent, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
1504 item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 );
1506 item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP, 5 );
1508 wxTextCtrl *item4 = new wxTextCtrl( parent, ecID_STRING_EDIT_TEXTCTRL, _(""), wxDefaultPosition, wxSize(420,250), wxTE_MULTILINE );
1509 item0->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
1511 parent->SetAutoLayout( TRUE );
1512 parent->SetSizer( item0 );
1514 item0->Fit( parent );
1515 item0->SetSizeHints( parent );
1517 FindWindow(ecID_STRING_EDIT_TEXTCTRL)->SetValidator(wxGenericValidator(& m_value));
1518 FindWindow(ecID_STRING_EDIT_TEXTCTRL)->SetFocus();