URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [configtool/] [standalone/] [wxwin/] [configitem.cpp] - Rev 174
Compare with Previous | Blame | View Log
//####COPYRIGHTBEGIN#### // // ---------------------------------------------------------------------------- // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // // This program is part of the eCos host tools. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // ---------------------------------------------------------------------------- // //####COPYRIGHTEND#### // configitem.cpp : // //=========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): julians // Contact(s): julians // Date: 2000/09/01 // Version: $Id: configitem.cpp,v 1.1.1.1 2004-02-14 13:28:47 phoenix Exp $ // Purpose: // Description: Implementation file for the ConfigTool application class // Requires: // Provides: // See also: // Known bugs: // Usage: // //####DESCRIPTIONEND#### // //=========================================================================== // ============================================================================ // declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- #ifdef __GNUG__ #pragma implementation "configitem.h" #endif // Includes other headers for precompiled compilation #include "ecpch.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/settings.h" #include "wx/valgen.h" #include "configitem.h" #include "configtree.h" #include "configtooldoc.h" #include "configtoolview.h" #include "ecutils.h" IMPLEMENT_CLASS(ecConfigItem, wxObject) /* * ecConfigItem * Represents a node in the configuration hierarchy. * For every ecConfigItem, there is also an ecTreeItemData * that points to it. */ ecConfigItem::ecConfigItem(ecConfigItem* parent, const wxString& name, ecConfigType ctype, ecOptionFlavor flavor, ecOptionType otype, bool active, bool enabled, ecUIHint hint) { m_CdlItem = NULL; m_name = name; m_configType = ctype; m_optionType = otype; m_optionFlavor = flavor; m_enabled = enabled; m_active = active; m_parent = parent; m_hint = hint; m_treeItem = wxTreeItemId(); switch (otype) { case ecDouble: { m_value = 0.0; break; } case ecString: case ecEnumerated: { m_value = wxT(""); break; } case ecLong: { m_value = (long) 0; break; } case ecBool: { m_value = (bool) FALSE; break; } default: { break; } } } ecConfigItem::ecConfigItem(ecConfigItem* parent, CdlUserVisible vitem) { m_name = wxT("UNNAMED"); m_configType = ecConfigTypeNone; m_optionType = ecOptionTypeNone; m_optionFlavor = ecFlavorNone; m_enabled = FALSE; m_active = FALSE; m_parent = parent; m_CdlItem = vitem; m_hint = ecHintNone; m_treeItem = wxTreeItemId(); ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl(); m_treeItem = treeCtrl->AppendItem(parent->GetTreeItem(), m_name, -1, -1, new ecTreeItemData(this)); ConvertFromCdl(); UpdateTreeItem(* treeCtrl); } ecConfigItem::~ecConfigItem() { // Make sure that the tree item no longer references this object ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl(); if (m_treeItem && treeCtrl) { ecTreeItemData* data = (ecTreeItemData*) treeCtrl->GetItemData(m_treeItem); data->SetConfigItem(NULL); } ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc(); if (doc) { doc->GetItems().DeleteObject(this); } } // Convert from Cdl to internal representation bool ecConfigItem::ConvertFromCdl() { if (!GetCdlItem()) return FALSE; m_name = GetCdlItem()->get_display ().c_str (); m_macro = GetCdlItem()->get_name().c_str(); m_strDescr = ecUtils::StripExtraWhitespace (wxString (GetCdlItem()->get_description ().c_str ())); // FIXME: re-implement using CdlValuableBody::get_widget_hint() // (comment from original MFC configtool) if (IsPackage()) { // If a package item, display the package version string m_optionType = ecString; m_configType = ecPackage; m_optionFlavor = ecFlavorNone; } else { const CdlValuable valuable = dynamic_cast<CdlValuable> (GetCdlItem()); switch (valuable->get_flavor ()){ case CdlValueFlavor_None: m_optionFlavor = ecFlavorNone; m_optionType=ecOptionTypeNone; //??? Shouldn't it be ecBool for CdlValueFlavor_Bool? m_configType = ecContainer; break; case CdlValueFlavor_Bool: m_optionFlavor = ecFlavorBool; m_optionType=ecOptionTypeNone; //??? Shouldn't it be ecBool for CdlValueFlavor_Bool? m_configType = ecOption; m_hint = (HasRadio() ? ecHintRadio : ecHintCheck); break; case CdlValueFlavor_Data: case CdlValueFlavor_BoolData: m_optionFlavor = (valuable->get_flavor() == CdlValueFlavor_Data ? ecFlavorData : ecFlavorBoolData); m_configType = ecOption; m_hint = (HasRadio() ? ecHintRadio : ecHintCheck); if (! valuable->has_legal_values ()) { m_optionType=ecString; } else if (0 == valuable->get_legal_values ()->ranges.size ()) { m_optionType=ecEnumerated; } else { CdlListValue list_value; CdlEvalContext context (NULL, valuable, valuable->get_property (CdlPropertyId_LegalValues)); valuable->get_legal_values ()->eval (context, list_value); m_optionType=list_value.get_double_ranges ().size () ? ecDouble : ecLong; } break; default: wxASSERT (0); // specified flavor not supported break; } } m_active = IsActive(); m_enabled = IsEnabled(); return TRUE; } wxString ecConfigItem::GetItemNameOrMacro() const { return (wxGetApp().GetSettings().m_showMacroNames && !GetMacro().IsEmpty() ? GetMacro() : GetName()); } // Sets the text and icon for this item bool ecConfigItem::UpdateTreeItem(ecConfigTreeCtrl& treeCtrl) { treeCtrl.SetItemText(m_treeItem, m_name); static wxColour normalColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); static wxColour disabledColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT); treeCtrl.SetItemTextColour(m_treeItem, GetActive() ? normalColour : disabledColour); // Find which icon state we're in so we can get the appropriate icon id int iconState = 0; wxString iconName; switch (GetConfigType()) { case ecContainer: { iconName = _("Container"); iconState = 0; break; } case ecPackage: { iconName = _("Package"); iconState = 0; break; } case ecComponent: { iconName = _("??"); iconState = 0; break; } case ecOption: { if (GetOptionFlavor() == ecFlavorData) { switch (GetOptionType()) { case ecDouble: case ecLong: { iconName = _("Integer"); iconState = 0; break; } case ecEnumerated: { iconName = _("Enumerated"); iconState = 0; break; } case ecString: { iconName = _("Text"); iconState = 0; break; } // ??? Actually I don't think there's such a think as ecBool type, only enabled/disabled case ecBool: { if (GetUIHint() == ecHintCheck) iconName = _("Checkbox"); else iconName = _("Radiobox"); iconState = (m_value.GetBool() ? 0 : 1); break; } default: { break; } } } if (GetOptionFlavor() == ecFlavorBoolData || GetOptionFlavor() == ecFlavorBool) { if (GetUIHint() == ecHintCheck) iconName = _("Checkbox"); else iconName = _("Radiobox"); iconState = (m_enabled ? 0 : 1); } break; } default: { break; } } if (!iconName.IsEmpty()) { int iconId = treeCtrl.GetIconDB().GetIconId(iconName, iconState, GetActive()); treeCtrl.SetItemImage(m_treeItem, iconId, wxTreeItemIcon_Normal); treeCtrl.SetItemImage(m_treeItem, iconId, wxTreeItemIcon_Selected); } return TRUE; } // Handle a left click on the icon: e.g. (un)check the option // In the old MFC tool, this was handled by CControlView::Bump void ecConfigItem::OnIconLeftDown(ecConfigTreeCtrl& treeCtrl) { if (GetConfigType() != ecOption) return; switch (GetOptionFlavor()) { case ecFlavorBool: case ecFlavorBoolData: { if (GetActive()) { wxGetApp().GetConfigToolDoc()->SetEnabled(*this, !m_enabled); } break; } case ecFlavorData: { if (GetActive()) { switch (GetOptionType()) { case ecLong: { int nInc = 1; long nOldValue = Value(); if(nInc==1 && nOldValue == long(-1)) { nOldValue=0; } else if(nInc==-1 && nOldValue==0){ nOldValue = long(-1); } else { nOldValue+=nInc; } wxGetApp().GetConfigToolDoc()->SetValue(*this, nOldValue); break; } case ecEnumerated: { int nInc = 1; wxArrayString arEnum; EvalEnumStrings (arEnum); // calculate legal values just in time if (0 == arEnum.GetCount()) // if no legal values... break; // ...do nothing int nIndex = -1; const wxString strCurrent = StringValue (); int nEnum; for (nEnum = 0; (nEnum < arEnum.GetCount()) && (nIndex == -1); nEnum++) if (0 == arEnum[nEnum].CompareTo (strCurrent)) nIndex = nEnum; // the index of the current value if (nIndex != -1) // if the current value is still legal nIndex += (nInc < 0 ? -1 : 1); // increment/decrement the index else nIndex = 0; // otherwise select the first enum if (nIndex < 0) // if the new index is negative nIndex = arEnum.GetCount()-1; // make it positive wxGetApp().GetConfigToolDoc()->SetValue(*this, arEnum[nIndex % arEnum.GetCount()]); break; } default: { break; } } } break; } default: { break; } } } // Gets the value to display (often an empty string) wxString ecConfigItem::GetDisplayValue() const { wxString str; switch(GetOptionType()) { case ecEnumerated: case ecLong: case ecDouble: case ecString: { if (GetCdlValuable()) str = StringValue(); } break; default: break; } return str; #if 0 switch (GetConfigType()) { case ecComponent: case ecContainer: { return wxEmptyString; break; } case ecPackage: { return m_value.GetString(); break; } case ecOption: { switch (GetOptionType()) { case ecDouble: { wxString val; val.Printf("%.4lf", (double) m_value.GetDouble()); return val; } case ecLong: { wxString val; val.Printf("%.ld", (long) m_value.GetLong()); return val; break; } case ecEnumerated: case ecString: { return m_value.GetString(); break; } case ecBool: { return wxEmptyString; break; } default: { break; } } break; } default: { break; } } return wxEmptyString; #endif } // Can we start editing this item? bool ecConfigItem::CanEdit() const { if (!GetActive()) return FALSE; if (GetConfigType() != ecOption) return FALSE; if (GetOptionFlavor() != ecFlavorData && GetOptionFlavor() != ecFlavorBoolData) return FALSE; // TODO: other criteria for editability return TRUE; } // Creates an edit window. It will be positioned by the caller. wxWindow* ecConfigItem::CreateEditWindow(wxWindow* parent) { wxWindow* window = NULL; switch(GetOptionType()) { case ecEnumerated: { window = new ecEnumEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize, /* wxNO_BORDER */ 0); wxArrayString arEnumStrings; EvalEnumStrings(arEnumStrings); int i; for (i = 0; i < arEnumStrings.GetCount(); i++) { ((ecEnumEditorCtrl*) window)->Append(arEnumStrings[i]); } break; } case ecLong: { window = new ecIntegerEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize, /* wxNO_BORDER | */ wxSP_ARROW_KEYS); break; } case ecDouble: { window = new ecDoubleEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize, /* wxNO_BORDER|*/ wxTE_PROCESS_ENTER); break; } case ecString: { window = new ecTextEditorCtrl(parent, ecID_ITEM_EDIT_WINDOW, wxDefaultPosition, wxDefaultSize, /* wxNO_BORDER|*/ wxTE_PROCESS_ENTER); break; } default: break; } wxASSERT (window != NULL) ; return window; } // Transfers data between item and window bool ecConfigItem::TransferDataToWindow(wxWindow* window) { if (window->IsKindOf(CLASSINFO(ecTextEditorCtrl))) { ecTextEditorCtrl* win = (ecTextEditorCtrl*) window; win->SetValue(GetDisplayValue()); } else if (window->IsKindOf(CLASSINFO(ecDoubleEditorCtrl))) { ecDoubleEditorCtrl* win = (ecDoubleEditorCtrl*) window; win->SetValue(GetDisplayValue()); } else if (window->IsKindOf(CLASSINFO(ecEnumEditorCtrl))) { ecEnumEditorCtrl* win = (ecEnumEditorCtrl*) window; win->SetStringSelection(GetDisplayValue()); } else if (window->IsKindOf(CLASSINFO(ecIntegerEditorCtrl))) { ecIntegerEditorCtrl* win = (ecIntegerEditorCtrl*) window; long i; ecUtils::StrToItemIntegerType(StringValue(), i); wxString val; val.Printf(wxT("%ld"), i); win->SetValue(val); } return TRUE; } bool ecConfigItem::TransferDataFromWindow(wxWindow* window) { ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc(); wxASSERT (doc != NULL); if (!doc) return FALSE; if (window->IsKindOf(CLASSINFO(ecTextEditorCtrl))) { ecTextEditorCtrl* win = (ecTextEditorCtrl*) window; wxASSERT ( GetOptionType() == ecString ); // TODO: do checking doc->SetValue(*this, win->GetValue()); } else if (window->IsKindOf(CLASSINFO(ecDoubleEditorCtrl))) { ecDoubleEditorCtrl* win = (ecDoubleEditorCtrl*) window; wxASSERT ( GetOptionType() == ecString ); // TODO: do checking doc->SetValue(*this, atof(win->GetValue())); } else if (window->IsKindOf(CLASSINFO(ecEnumEditorCtrl))) { ecEnumEditorCtrl* win = (ecEnumEditorCtrl*) window; wxASSERT ( GetOptionType() == ecEnumerated ); // TODO: do checking doc->SetValue(*this, win->GetStringSelection()); } else if (window->IsKindOf(CLASSINFO(ecIntegerEditorCtrl))) { ecIntegerEditorCtrl* win = (ecIntegerEditorCtrl*) window; wxASSERT ( GetOptionType() == ecLong ); // TODO: do checking doc->SetValue(*this, (long) win->GetValue()); } return TRUE; } //// Taken from MFC version const ecFileName ecConfigItem::GetFilename() const { wxString sep(wxFILE_SEP_PATH); ecFileName strFile; const CdlNode node = dynamic_cast<CdlNode> (m_CdlItem); if (node){ // get the package which owns the configuration item const CdlPackage package = GetOwnerPackage(); if (package){ // return the filename of the config header wxString pkg(wxT("include")); pkg += sep; pkg += wxT("pkgconf"); strFile=ecFileName(wxGetApp().GetConfigToolDoc()->GetInstallTree()+sep+pkg) + package->get_config_header ().c_str (); } } return strFile; } // Change version (of a package) bool ecConfigItem::ChangeVersion(const wxString &strVersion) { bool rc=FALSE; CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem()); wxASSERT(package != 0); const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable != 0); const wxString strMacroName(GetMacro()); if (strVersion != valuable->get_value ().c_str ()) { // if the wrong version is loaded // TRACE (wxT("Changing package %s to version '%s'\n"), strMacroName, strVersion); try { wxGetApp().GetConfigToolDoc()->GetCdlConfig()->change_package_version (package, ecUtils::UnicodeToStdStr (strVersion), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler); rc=TRUE; } catch (CdlStringException exception) { wxString msg; 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 ())) ; wxMessageBox(msg); } catch (...) { wxString msg; msg.Printf(wxT("Error changing package %s to version '%s'"), (const wxChar*) strMacroName, (const wxChar*) strVersion) ; wxMessageBox(msg); } } return rc; } // Unload (a package) bool ecConfigItem::Unload() { bool rc=FALSE; CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem()); wxASSERT(package); ecConfigToolDoc* pDoc=wxGetApp().GetConfigToolDoc(); // Remove its objects from the view to prevent any painting problems ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(GetTreeItem()); wxASSERT(data); // I _think_ we should do this to stop 'this' from being deleted when we delete the item. // But, in that case, where do we delete this item? // Perhaps should store them in an array in the document, as per the MFC tool. data->SetConfigItem(NULL); wxGetApp().GetTreeCtrl()->Delete(GetTreeItem()); wxNode* node = pDoc->GetItems().First(); while (node) { ecConfigItem* item = wxDynamicCast(node->Data(), ecConfigItem); if (package == item->GetOwnerPackage()) { item->SetTreeItem(wxTreeItemId()); // Make sure we can't attempt to paint it item->SetCdlItem(NULL); // Make sure we can't access stale data } node = node->Next(); } const wxString strMacroName(GetMacro()); //TRACE (wxT("Unloading package %s\n"), strMacroName); try { pDoc->GetCdlConfig()->unload_package (package); rc=TRUE; } catch (CdlStringException exception) { wxString msg; wxString exceptionMsg(exception.get_message ().c_str ()); msg.Printf(wxT("Error unloading package %s:\n\n%s"), (const wxChar*) strMacroName, (const wxChar*) exceptionMsg ); wxMessageBox(msg); } catch (...) { wxString msg; msg.Printf(wxT("Error unloading package %s"), (const wxChar*) strMacroName); wxMessageBox(msg); } m_treeItem=wxTreeItemId(); // Make sure we can't attempt to paint it m_CdlItem=NULL; // Make sure we can't access stale data return rc; } wxString ecConfigItem::GetURL() const { for(const ecConfigItem *pItem=this;pItem;pItem=pItem->GetParent()){ if(pItem->GetCdlItem()){ wxString strURL; strURL=pItem->GetCdlItem()->get_doc_url().c_str(); if(strURL.Len()){ return strURL; } strURL=pItem->GetCdlItem()->get_doc().c_str(); if(strURL.Len()){ return strURL; } } } return wxT("ref/ecos-ref.html"); // the default URL } bool ecConfigItem::SetValue(const wxString& value, CdlTransaction transaction/*=NULL*/) { wxASSERT ((m_optionType == ecString) || (m_optionType == ecEnumerated)); const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); const std::string str = value.c_str(); if(transaction){ if (CdlValueFlavor_BoolData == valuable->get_flavor ()){ // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (transaction, valuable->is_enabled (), str, CdlValueSource_User); } else {// CdlValueFlavor_Data valuable->set_value (transaction, str, CdlValueSource_User); } } else { if (CdlValueFlavor_BoolData == valuable->get_flavor ()){ // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (valuable->is_enabled (), str, CdlValueSource_User); } else {// CdlValueFlavor_Data valuable->set_value (str, CdlValueSource_User); } } // TODO: eliminate m_value, since the value is always taken from the Cdl object. m_value = value; return TRUE; } bool ecConfigItem::SetValue (double dValue, CdlTransaction transaction/*=NULL*/) { wxASSERT (m_optionType == ecDouble); const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); if(transaction) { if (CdlValueFlavor_BoolData == valuable->get_flavor ()) { // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (transaction, valuable->is_enabled (), dValue, CdlValueSource_User); } else {// CdlValueFlavor_Data valuable->set_double_value (transaction, dValue, CdlValueSource_User); } } else { if (CdlValueFlavor_BoolData == valuable->get_flavor ()) { // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (valuable->is_enabled (), dValue, CdlValueSource_User); } else {// CdlValueFlavor_Data valuable->set_double_value (dValue, CdlValueSource_User); } } // TODO: BoolData? m_value = dValue; return TRUE; } bool ecConfigItem::SetValue (long nValue, CdlTransaction transaction/*=NULL*/) { wxASSERT (m_optionType == ecLong); const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); if(transaction) { if (CdlValueFlavor_BoolData == valuable->get_flavor ()) { // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (transaction, valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User); } else { // CdlValueFlavor_Data valuable->set_integer_value (transaction, nValue, CdlValueSource_User); } } else { if (CdlValueFlavor_BoolData == valuable->get_flavor ()) { // set the user bool to the current bool when changing a booldata // value to avoid a possible change in the current bool valuable->set_enabled_and_value (valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User); } else { // CdlValueFlavor_Data valuable->set_integer_value (nValue, CdlValueSource_User); } } // TODO: BoolData? m_value = nValue; return TRUE; } bool ecConfigItem::HasRadio() const { const CdlValuable valuable = GetCdlValuable(); if (! valuable) return FALSE; CdlWidgetHint hint; valuable->get_widget_hint (hint); return (CdlBoolWidget_Radio == hint.bool_widget); } ecConfigItem *ecConfigItem::FirstRadio() const { wxASSERT(HasRadio ()); for(ecConfigItem *h=GetParent()->FirstChild();h;h=h->NextSibling()){ if(h->HasRadio ()){ return h; } } // No radio buttons found wxASSERT(FALSE); return FALSE; } ecConfigItem *ecConfigItem::FirstChild() const { ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl(); long cookie; wxTreeItemId hChild=treeCtrl->GetFirstChild(GetTreeItem(), cookie); if (hChild) { ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(hChild); wxASSERT(data); return data->GetConfigItem(); } else return NULL; } ecConfigItem *ecConfigItem::NextSibling() const { ecConfigTreeCtrl* treeCtrl = wxGetApp().GetTreeCtrl(); wxTreeItemId hChild=treeCtrl->GetNextSibling(GetTreeItem()); if (hChild) { ecTreeItemData* data = (ecTreeItemData*) wxGetApp().GetTreeCtrl()->GetItemData(hChild); wxASSERT(data); return data->GetConfigItem(); } else return NULL; } bool ecConfigItem::IsEnabled() const { const CdlValuable valuable = GetCdlValuable(); return NULL==valuable ||valuable->is_enabled(); } bool ecConfigItem::IsActive() const { // return GetCdlItem()->is_active(); const CdlValuable valuable = GetCdlValuable(); if (valuable && ((GetOptionType() != ecOptionTypeNone) || HasBool())) { return (valuable->is_modifiable () && valuable->is_active ()); } else return GetCdlItem()->is_active(); } bool ecConfigItem::HasModifiedChildren() const { for(ecConfigItem *pItem=FirstChild();pItem;pItem=pItem->NextSibling()){ if(pItem->Modified()||pItem->HasModifiedChildren()){ return TRUE; } } return FALSE; } bool ecConfigItem::Modified () const { const CdlValuable valuable = GetCdlValuable(); return valuable // accommodate the root config item which has no CDL item && !IsPackage() // packages are never modified && valuable->get_source () != CdlValueSource_Default; } void ecConfigItem::DumpItem() { //TRACE(wxT("Item %08x\n\tDisplay Name='%s'\n\tMacro Name='%s'\n\tType=%s"), this, Name(), Macro(), TreeItemTypeImage[m_Type]); //TRACE(wxT("\n\tValue=%s\n\tURL=%s\n\tParent=%08x"),StringValue(), GetURL(), Parent()); //TRACE(wxT("\n")); } ecConfigItem * ecConfigItem::NextRadio() const { wxASSERT(this->HasRadio ()); for(ecConfigItem *pItem=NextSibling();pItem;pItem=pItem->NextSibling()){ if(pItem->HasRadio()){ return pItem; } } return NULL; } bool ecConfigItem::IsDescendantOf(ecConfigItem * pAncestor) { for(ecConfigItem *pItem=GetParent();pItem;pItem=pItem->GetParent()){ if(pItem==pAncestor){ return TRUE; } } return FALSE; } bool ecConfigItem::ViewHeader() { bool rc=FALSE; const ecFileName strFile(GetFilename()); if(!strFile.IsEmpty()) { ecConfigToolDoc *pDoc=wxGetApp().GetConfigToolDoc(); if(pDoc->GetBuildTree().IsEmpty()){ wxString msg; msg.Printf(wxT("Cannot display header file until configuration is saved")); wxMessageBox(msg); } else { rc=wxGetApp().Launch(strFile, wxGetApp().GetSettings().m_strViewer); } } return rc; } bool ecConfigItem::ViewURL() { return wxGetApp().GetConfigToolDoc()->ShowURL(GetURL()); } bool ecConfigItem::HasBool() const { if (!m_CdlItem) { return FALSE; } else if (IsPackage()) { return FALSE; } else { const CdlValuable valuable = GetCdlValuable(); CdlValueFlavor flavor = valuable->get_flavor (); return (flavor == CdlValueFlavor_Bool) || (flavor == CdlValueFlavor_BoolData); } } bool ecConfigItem::SetEnabled(bool bEnabled, CdlTransaction current_transaction/*=NULL*/) { const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); // use a transaction object to ensure that all config items are changed together CdlTransaction transaction = current_transaction ? current_transaction : CdlTransactionBody::make (wxGetApp().GetConfigToolDoc ()->GetCdlConfig ()); if (HasRadio () && bEnabled) { // if a new radio button has been selected for (ecConfigItem *pItem = FirstRadio(); pItem; pItem = pItem->NextRadio ()) { // for each radio button in the group if (pItem != this) { // if not the newly selected radio button pItem->SetEnabled (FALSE, transaction); // disable the radio button } } } if (CdlValueFlavor_BoolData == valuable->get_flavor ()) { // set the user value to the current data value when enabling/disabling // a booldata item to avoid a possible change in the current data value CdlSimpleValue simple_value = valuable->get_simple_value (); valuable->set_enabled_and_value (transaction, bEnabled, simple_value, CdlValueSource_User); } else { // CdlValueFlavor_Bool valuable->set_enabled (transaction, bEnabled, CdlValueSource_User); } if (! current_transaction) { // if not a recursive call to disable a radio button transaction->body (); // commit the transaction delete transaction; transaction = NULL; } return TRUE; } long ecConfigItem::DefaultValue () const { return (long) atoi (StringValue (CdlValueSource_Default)) ; } long ecConfigItem::Value () const { wxASSERT (!IsPackage()); // not a package item const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); long nValue (0); switch (valuable->get_flavor ()) { // case CdlValueFlavor_Bool: // nValue = valuable->is_enabled (CdlValueSource_Current) ? 1 : 0; // break; case CdlValueFlavor_BoolData: case CdlValueFlavor_Data: nValue = (long) valuable->get_integer_value (CdlValueSource_Current); break; default: wxASSERT (0); // specified flavor not supported } return nValue; } const double ecConfigItem::DoubleValue (CdlValueSource source /* = CdlValueSource_Current */ ) const { wxASSERT (!IsPackage()); // not a package item const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); wxASSERT (valuable->has_double_value (source)); return valuable->get_double_value (source); } const wxString ecConfigItem::StringValue (CdlValueSource source /* = CdlValueSource_Current */ ) const { // wxASSERT (!IsPackage()); // not a package item const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); wxString strValue (wxT("")); switch (valuable->get_flavor ()) { case CdlValueFlavor_Data: case CdlValueFlavor_BoolData: case CdlValueFlavor_None: // a package if (m_optionType == ecLong) strValue = ecUtils::IntToStr (Value (), wxGetApp().GetSettings().m_bHex); else if (m_optionType == ecDouble) strValue = ecUtils::DoubleToStr (DoubleValue ()); else strValue = valuable->get_value (source).c_str (); break; default: wxASSERT (0); // specified flavor not supported } return strValue; } const wxString ecConfigItem::StringValue(ecWhereType where) const { wxString str; switch(where){ case ecInName: str=GetName(); break; case ecInMacro: str=GetMacro(); break; case ecInDesc: str=GetDescription(); break; case ecInCurrentValue: if (ecOptionTypeNone==GetOptionType()) str = wxEmptyString; else str = StringValue(CdlValueSource_Current); break; case ecInDefaultValue: if (ecOptionTypeNone==GetOptionType()) str = wxEmptyString; else str = StringValue(CdlValueSource_Default); break; default: wxASSERT(FALSE); break; } return str; } int ecConfigItem::EvalEnumStrings (wxArrayString &arEnumStrings) const { const CdlValuable valuable = GetCdlValuable(); wxASSERT (valuable); /* if (m_Type == Boolean) { arEnumStrings.SetSize (2); arEnumStrings.SetAt (0, wxT("True")); arEnumStrings.SetAt (1, wxT("False")); } else */ { wxASSERT (m_optionType == ecEnumerated); CdlListValue list_value; CdlEvalContext context (NULL, m_CdlItem, m_CdlItem->get_property (CdlPropertyId_LegalValues)); valuable->get_legal_values ()->eval (context, list_value); const std::vector<CdlSimpleValue> & table = list_value.get_table (); // add legal values to the list for (unsigned int nValue = 0; nValue < table.size (); nValue++) { arEnumStrings.Add (table [nValue].get_value ().c_str ()); } } return arEnumStrings.GetCount(); } static const wxChar* gs_whereTypes[] = { _("Macro names"), _("Item names"), _("Short descriptions"), _("Current Values"), _("Default Values") }; // Convert a string representation of 'where' (e.g. "Macro names") to // ecWhereType ecWhereType ecConfigItem::WhereStringToType(const wxString& whereString) { int sz = 5; int i; for (i = 0; i < sz; i++) if (whereString == gs_whereTypes[i]) return (ecWhereType) i; wxASSERT( FALSE ); return (ecWhereType) 0; } // Convert a type representation of 'where' to a string wxString ecConfigItem::WhereTypeToString(ecWhereType whereType) { return gs_whereTypes[(size_t) whereType] ; } // Bump by specified amount, or toggle if a boolean value bool ecConfigItem::BumpItem(int nInc) { bool rc = FALSE; // Take an action for clicking on the icon ecConfigToolDoc* pDoc = wxGetApp().GetConfigToolDoc(); // do not modify the option value if it is inactive or not modifiable const CdlValuable valuable = GetCdlValuable(); if (!valuable || (valuable->is_modifiable () && valuable->is_active ())) { if (0 == nInc) // if a toggle request { if (HasBool () && ! (HasRadio () && IsEnabled ())) { // only enable (not disable) a radio button rc = pDoc->SetEnabled (*this, ! this->IsEnabled ()); // toggle enabled/disabled state } } else if (IsEnabled ()) { // the item is enabled... switch(GetOptionType()) { case ecOptionTypeNone: case ecString: case ecDouble: break; case ecEnumerated: { wxArrayString arEnum; EvalEnumStrings (arEnum); // calculate legal values just in time if (0==arEnum.Count()) // if no legal values... break; // ...do nothing int nIndex = -1; const wxString strCurrent = StringValue (); int nEnum; for (nEnum = 0; (nEnum < arEnum.Count()) && (nIndex == -1); nEnum++) if (strCurrent == arEnum[nEnum]) nIndex = nEnum; // the index of the current value if (nIndex != -1) // if the current value is still legal nIndex += (nInc < 0 ? -1 : 1); // increment/decrement the index else nIndex = 0; // otherwise select the first enum if (nIndex < 0) // if the new index is negative nIndex = arEnum.Count()-1; // make it positive rc=pDoc->SetValue (*this, arEnum[nIndex % arEnum.Count()]); } break; case ecLong: { // TODO: if we're editing, we should get the value in the edit item // and not the ecConfigItem. long nOldValue = Value(); if(nInc==1 && nOldValue==-1){ nOldValue=0; } else if(nInc==-1 && nOldValue==0){ nOldValue=-1; } else { nOldValue+=nInc; } rc=pDoc->SetValue(*this, nOldValue); break; } break; /* case CConfigItem::Boolean: { ItemIntegerType nOldValue=Value(h); pDoc->SetValue(ti,nOldValue^1); } break; case CConfigItem::Radio: if(0==Value(h)){ pDoc->SetValue(ti, (ItemIntegerType) 1); } break; */ default: break; } } } return rc; } #if 0 /* Presumably we don't need this since we use the m_parent member instead ecConfigItem *ecConfigItem::Parent() const { CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl(); HTREEITEM hParent=tree.GetParentItem(HItem()); return (NULL==hParent||TVI_ROOT==hParent)?NULL:(ecConfigItem *)tree.GetItemData(hParent); } */ #endif /* * ecTextEditorCtrl * A specialised wxTextCtrl, for editing config values */ BEGIN_EVENT_TABLE(ecTextEditorCtrl, wxTextCtrl) EVT_TEXT_ENTER(-1, ecTextEditorCtrl::OnEnter) EVT_KILL_FOCUS(ecTextEditorCtrl::OnKillFocus) EVT_LEFT_DCLICK(ecTextEditorCtrl::OnLeftDClick) END_EVENT_TABLE() IMPLEMENT_CLASS(ecTextEditorCtrl, wxTextCtrl) ecTextEditorCtrl::ecTextEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): wxTextCtrl(parent, id, wxEmptyString, pos, size, style) { } void ecTextEditorCtrl::OnEnter(wxCommandEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } void ecTextEditorCtrl::OnKillFocus(wxFocusEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } // Edit the string in a separate dialog, for convenience void ecTextEditorCtrl::OnLeftDClick(wxMouseEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); ecConfigItem* item = parent->GetCurrentConfigItem(); ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc(); wxString initialValue(GetValue()); ecEditStringDialog dialog(initialValue, wxGetApp().GetTopWindow(), ecID_EDIT_STRING_DIALOG); if (dialog.ShowModal() == wxID_OK) { wxString val = dialog.GetValue() ; // This control will have been deleted at this point, due to losing the focus. // So update the item, not the control. // wxTextCtrl::SetValue(val); doc->SetValue(*item, val); } } /* * ecDoubleEditorCtrl * A specialised wxTextCtrl, for editing double config values */ BEGIN_EVENT_TABLE(ecDoubleEditorCtrl, wxTextCtrl) EVT_TEXT_ENTER(-1, ecDoubleEditorCtrl::OnEnter) EVT_KILL_FOCUS(ecDoubleEditorCtrl::OnKillFocus) END_EVENT_TABLE() IMPLEMENT_CLASS(ecDoubleEditorCtrl, wxTextCtrl) ecDoubleEditorCtrl::ecDoubleEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): wxTextCtrl(parent, id, wxEmptyString, pos, size, style) { } void ecDoubleEditorCtrl::OnEnter(wxCommandEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } void ecDoubleEditorCtrl::OnKillFocus(wxFocusEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } /* * ecIntegerEditorCtrl * A specialised wxTextCtrl, for editing double config values */ BEGIN_EVENT_TABLE(ecIntegerEditorCtrl, wxSpinCtrl) EVT_TEXT_ENTER(-1, ecIntegerEditorCtrl::OnEnter) EVT_KILL_FOCUS(ecIntegerEditorCtrl::OnKillFocus) END_EVENT_TABLE() IMPLEMENT_CLASS(ecIntegerEditorCtrl, wxSpinCtrl) ecIntegerEditorCtrl::ecIntegerEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): wxSpinCtrl(parent, id, wxEmptyString, pos, size, style, -32000, 32000, 0) { } void ecIntegerEditorCtrl::OnEnter(wxCommandEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } void ecIntegerEditorCtrl::OnKillFocus(wxFocusEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } /* * ecEnumEditorCtrl * A specialised wxChoice, for editing enumerated config values */ BEGIN_EVENT_TABLE(ecEnumEditorCtrl, wxChoice) EVT_CHAR(ecEnumEditorCtrl::OnChar) EVT_KILL_FOCUS(ecEnumEditorCtrl::OnKillFocus) END_EVENT_TABLE() IMPLEMENT_CLASS(ecEnumEditorCtrl, wxChoice) ecEnumEditorCtrl::ecEnumEditorCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): wxChoice(parent, id, pos, size, 0, 0, style) { } void ecEnumEditorCtrl::OnChar(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_RETURN) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } else event.Skip(); } void ecEnumEditorCtrl::OnKillFocus(wxFocusEvent& event) { ecValueWindow* parent = (ecValueWindow*) GetParent(); parent->EndEditing(); } /* * ecEditStringDialog * Pops up to make it easier to edit large string values */ BEGIN_EVENT_TABLE(ecEditStringDialog, ecDialog) EVT_BUTTON(wxID_OK, ecEditStringDialog::OnOK) END_EVENT_TABLE() ecEditStringDialog::ecEditStringDialog(const wxString& initialValue, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) { m_value = initialValue; //SetExtraStyle(wxDIALOG_EX_CONTEXTHELP); ecDialog::Create(parent, id, _("String Edit"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER); CreateControls(this); TransferDataToWindow(); Centre(wxBOTH); } ecEditStringDialog::~ecEditStringDialog() { } //// Event handlers void ecEditStringDialog::OnOK(wxCommandEvent& event) { wxDialog::OnOK(event); } //// Operations void ecEditStringDialog::CreateControls(wxWindow* parent) { wxSizer *item0 = new wxBoxSizer( wxVERTICAL ); wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL ); item1->Add( 20, 20, 10, wxALIGN_CENTRE|wxALL, 5 ); wxButton *item2 = new wxButton( parent, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 ); item2->SetDefault(); item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 ); wxButton *item3 = new wxButton( parent, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 ); item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP, 5 ); wxTextCtrl *item4 = new wxTextCtrl( parent, ecID_STRING_EDIT_TEXTCTRL, _(""), wxDefaultPosition, wxSize(420,250), wxTE_MULTILINE ); item0->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 ); parent->SetAutoLayout( TRUE ); parent->SetSizer( item0 ); parent->Layout(); item0->Fit( parent ); item0->SetSizeHints( parent ); FindWindow(ecID_STRING_EDIT_TEXTCTRL)->SetValidator(wxGenericValidator(& m_value)); FindWindow(ecID_STRING_EDIT_TEXTCTRL)->SetFocus(); }