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####
26 //===========================================================================
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
35 // Description: This is the implementation of the configuration item class
42 //####DESCRIPTIONEND####
44 //===========================================================================
46 #include "ConfigItem.h"
47 #include "ControlView.h"
50 #define INCLUDEFILE "ide.common.h" // for setEditLocation
51 #include "IncludeSTL.h"
52 #include "common/CodeCoordinate.h"
54 #include "ConfigToolDoc.h"
55 #include "ConfigTool.h"
57 LPCTSTR CConfigItem::TreeItemTypeImage[MaxTreeItemType + 1]={
58 _T("None"), _T("Integer"), _T("Enumeration"), _T("String"), _T("Double"), 0}; // Internationalization OK
60 const CFileName CConfigItem::FileName() const
63 const CdlNode node = dynamic_cast<CdlNode> (m_CdlItem);
65 // get the package which owns the configuration item
66 const CdlPackage package = GetOwnerPackage();
69 // return the filename of the config header
70 strFile=CFileName(CConfigTool::GetConfigToolDoc()->InstallTree()+_T("include\\pkgconf"))+package->get_config_header ().c_str ();
76 CConfigItem::CConfigItem(CConfigItem *pParent, CdlUserVisible CdlItem):
79 CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
82 // This is the root item
86 hParent=pParent->HItem();
88 // FIXME: re-implement using CdlValuableBody::get_widget_hint()
90 // If a package item, display the package version string
93 const CdlValuable valuable = dynamic_cast<CdlValuable> (CdlItem);
94 switch (valuable->get_flavor ()){
95 case CdlValueFlavor_None:
96 case CdlValueFlavor_Bool:
99 case CdlValueFlavor_Data:
100 case CdlValueFlavor_BoolData:
101 if (! valuable->has_legal_values ()) {
103 } else if (0 == valuable->get_legal_values ()->ranges.size ()) {
106 CdlListValue list_value;
107 CdlEvalContext context (NULL, valuable, valuable->get_property (CdlPropertyId_LegalValues));
108 valuable->get_legal_values ()->eval (context, list_value);
109 m_Type=list_value.get_double_ranges ().size () ? Double : Integer;
113 ASSERT (0); // specified flavor not supported
118 m_hItem=tree.InsertItem(ItemNameOrMacro(),hParent);
119 tree.SetItemData(m_hItem,(DWORD)this);
120 CConfigTool::GetControlView()->AdjustItemImage(m_hItem);
123 CConfigItem::~CConfigItem()
127 CString CConfigItem::GetURL() const
129 for(const CConfigItem *pItem=this;pItem;pItem=pItem->Parent()){
130 if(pItem->GetCdlItem()){
132 strURL=pItem->GetCdlItem()->get_doc_url().c_str();
133 if(strURL.GetLength()){
136 strURL=pItem->GetCdlItem()->get_doc().c_str();
137 if(strURL.GetLength()){
142 return _T("ref/ecos-ref.html"); // the default URL
145 bool CConfigItem::SetValue(LPCTSTR pszValue, CdlTransaction transaction/*=NULL*/)
147 ASSERT ((m_Type == String) || (m_Type == Enum));
148 const CdlValuable valuable = GetCdlValuable();
150 const std::string str=CUtils::UnicodeToStdStr (pszValue);
152 if (CdlValueFlavor_BoolData == valuable->get_flavor ()){
153 // set the user bool to the current bool when changing a booldata
154 // value to avoid a possible change in the current bool
155 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), str, CdlValueSource_User);
156 } else {// CdlValueFlavor_Data
157 valuable->set_value (transaction, str, CdlValueSource_User);
160 if (CdlValueFlavor_BoolData == valuable->get_flavor ()){
161 // set the user bool to the current bool when changing a booldata
162 // value to avoid a possible change in the current bool
163 valuable->set_enabled_and_value (valuable->is_enabled (), str, CdlValueSource_User);
164 } else {// CdlValueFlavor_Data
165 valuable->set_value (str, CdlValueSource_User);
172 bool CConfigItem::SetValue (double dValue, CdlTransaction transaction/*=NULL*/)
174 ASSERT (m_Type == Double);
175 const CdlValuable valuable = GetCdlValuable();
179 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
180 // set the user bool to the current bool when changing a booldata
181 // value to avoid a possible change in the current bool
182 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), dValue, CdlValueSource_User);
183 } else {// CdlValueFlavor_Data
184 valuable->set_double_value (transaction, dValue, CdlValueSource_User);
187 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
188 // set the user bool to the current bool when changing a booldata
189 // value to avoid a possible change in the current bool
190 valuable->set_enabled_and_value (valuable->is_enabled (), dValue, CdlValueSource_User);
191 } else {// CdlValueFlavor_Data
192 valuable->set_double_value (dValue, CdlValueSource_User);
199 CConfigItem *CConfigItem::FirstRadio() const
203 for(CConfigItem *h=Parent()->FirstChild();h;h=h->NextSibling()){
208 // No radio buttons found
213 bool CConfigItem::IsEnabled() const
215 const CdlValuable valuable = GetCdlValuable();
216 return NULL==valuable ||valuable->is_enabled();
219 bool CConfigItem::SetValue (ItemIntegerType nValue, CdlTransaction transaction/*=NULL*/)
221 ASSERT (m_Type == Integer);
222 const CdlValuable valuable = GetCdlValuable();
226 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
227 // set the user bool to the current bool when changing a booldata
228 // value to avoid a possible change in the current bool
229 valuable->set_enabled_and_value (transaction, valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User);
230 } else { // CdlValueFlavor_Data
231 valuable->set_integer_value (transaction, nValue, CdlValueSource_User);
234 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
235 // set the user bool to the current bool when changing a booldata
236 // value to avoid a possible change in the current bool
237 valuable->set_enabled_and_value (valuable->is_enabled (), (cdl_int) nValue, CdlValueSource_User);
238 } else { // CdlValueFlavor_Data
239 valuable->set_integer_value (nValue, CdlValueSource_User);
246 bool CConfigItem::HasModifiedChildren() const
248 for(CConfigItem *pItem=FirstChild();pItem;pItem=pItem->NextSibling()){
249 if(pItem->Modified()||pItem->HasModifiedChildren()){
256 ItemIntegerType CConfigItem::Value () const
258 ASSERT (!IsPackage()); // not a package item
259 const CdlValuable valuable = GetCdlValuable();
261 ItemIntegerType nValue (0);
263 switch (valuable->get_flavor ())
265 // case CdlValueFlavor_Bool:
266 // nValue = valuable->is_enabled (CdlValueSource_Current) ? 1 : 0;
269 case CdlValueFlavor_BoolData:
270 case CdlValueFlavor_Data:
271 nValue = (ItemIntegerType) valuable->get_integer_value (CdlValueSource_Current);
275 ASSERT (0); // specified flavor not supported
281 const double CConfigItem::DoubleValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
283 ASSERT (!IsPackage()); // not a package item
284 const CdlValuable valuable = GetCdlValuable();
286 ASSERT (valuable->has_double_value (source));
287 return valuable->get_double_value (source);
290 ItemIntegerType CConfigItem::DefaultValue () const
292 ItemIntegerType nValue;
293 return CUtils::StrToItemIntegerType (StringValue (CdlValueSource_Default), nValue) ? nValue : 0;
296 const CString CConfigItem::StringValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
298 // ASSERT (!IsPackage()); // not a package item
299 const CdlValuable valuable = GetCdlValuable();
301 CString strValue (_T(""));
303 switch (valuable->get_flavor ())
305 case CdlValueFlavor_Data:
306 case CdlValueFlavor_BoolData:
307 case CdlValueFlavor_None: // a package
308 if (m_Type == Integer)
309 strValue = CUtils::IntToStr (Value (), CConfigTool::GetConfigToolDoc ()->m_bHex);
310 else if (m_Type == Double)
311 strValue = CUtils::DoubleToStr (DoubleValue ());
313 strValue = valuable->get_value (source).c_str ();
317 ASSERT (0); // specified flavor not supported
323 const CString CConfigItem::StringValue(WhereType where) const
337 str=CConfigItem::None==Type()?_T(""):StringValue(CdlValueSource_Current);
340 str=CConfigItem::None==Type()?_T(""):StringValue(CdlValueSource_Default);
349 void CConfigItem::DumpItem()
351 TRACE(_T("Item %08x\n\tDisplay Name='%s'\n\tMacro Name='%s'\n\tType=%s"),
352 this, Name(), Macro(), TreeItemTypeImage[m_Type]);
353 TRACE(_T("\n\tValue=%s\n\tURL=%s\n\tParent=%08x"),StringValue(), GetURL(), Parent());
358 CConfigItem * CConfigItem::NextRadio() const
360 ASSERT(this->HasRadio ());
361 for(CConfigItem *pItem=NextSibling();pItem;pItem=pItem->NextSibling()){
362 if(pItem->HasRadio()){
369 bool CConfigItem::Modified () const
371 const CdlValuable valuable = GetCdlValuable();
373 valuable // accommodate the root config item which has no CDL item
374 && !IsPackage() // packages are never modified
375 && valuable->get_source () != CdlValueSource_Default;
378 CString CConfigItem::ItemNameOrMacro() const
380 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
381 return pDoc->m_bMacroNames&&!Macro().IsEmpty()?Macro():Name();
384 bool CConfigItem::IsDescendantOf(CConfigItem * pAncestor)
386 for(CConfigItem *pItem=Parent();pItem;pItem=pItem->Parent()){
387 if(pItem==pAncestor){
394 int CConfigItem::EvalEnumStrings (CStringArray &arEnumStrings) const
396 const CdlValuable valuable = GetCdlValuable();
399 if (m_Type == Boolean)
401 arEnumStrings.SetSize (2);
402 arEnumStrings.SetAt (0, _T("True"));
403 arEnumStrings.SetAt (1, _T("False"));
408 ASSERT (m_Type == Enum);
409 CdlListValue list_value;
410 CdlEvalContext context (NULL, m_CdlItem, m_CdlItem->get_property (CdlPropertyId_LegalValues));
411 valuable->get_legal_values ()->eval (context, list_value);
412 const std::vector<CdlSimpleValue> & table = list_value.get_table ();
414 // add legal values to the list
415 arEnumStrings.SetSize (table.size ());
416 for (unsigned int nValue = 0; nValue < table.size (); nValue++)
418 arEnumStrings.SetAt (nValue, table [nValue].get_value ().c_str ());
421 return arEnumStrings.GetSize();
424 bool CConfigItem::HasBool() const
428 } else if (IsPackage()) {
431 const CdlValuable valuable = GetCdlValuable();
432 CdlValueFlavor flavor = valuable->get_flavor ();
433 return (flavor == CdlValueFlavor_Bool) || (flavor == CdlValueFlavor_BoolData);
437 bool CConfigItem::HasRadio() const
439 const CdlValuable valuable = GetCdlValuable();
444 valuable->get_widget_hint (hint);
445 return (CdlBoolWidget_Radio == hint.bool_widget);
448 bool CConfigItem::SetEnabled(bool bEnabled, CdlTransaction current_transaction/*=NULL*/)
450 const CdlValuable valuable = GetCdlValuable();
453 // use a transaction object to ensure that all config items are changed together
454 CdlTransaction transaction = current_transaction ? current_transaction : CdlTransactionBody::make (CConfigTool::GetConfigToolDoc ()->GetCdlConfig ());
456 if (HasRadio () && bEnabled) { // if a new radio button has been selected
457 for (CConfigItem *pItem = FirstRadio(); pItem; pItem = pItem->NextRadio ()) { // for each radio button in the group
458 if (pItem != this) { // if not the newly selected radio button
459 pItem->SetEnabled (false, transaction); // disable the radio button
464 if (CdlValueFlavor_BoolData == valuable->get_flavor ()) {
465 // set the user value to the current data value when enabling/disabling
466 // a booldata item to avoid a possible change in the current data value
467 CdlSimpleValue simple_value = valuable->get_simple_value ();
468 valuable->set_enabled_and_value (transaction, bEnabled, simple_value, CdlValueSource_User);
469 } else { // CdlValueFlavor_Bool
470 valuable->set_enabled (transaction, bEnabled, CdlValueSource_User);
473 if (! current_transaction) { // if not a recursive call to disable a radio button
474 transaction->body (); // commit the transaction
475 deleteZ(transaction);
481 bool CConfigItem::ViewHeader()
484 const CFileName strFile(FileName());
485 if(!strFile.IsEmpty()){
486 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
487 if(pDoc->BuildTree().IsEmpty()){
488 CUtils::MessageBoxF(_T("Cannot display header file until configuration is saved"));
491 // Load or activate window and leave
492 CodeCoordinate loc((LPCTSTR)strFile, 0, 0, CodeCoordinate::FILE_LINE);
493 rc=AppInstance::getAppManager()->getEditorController()->setEditLocation(loc);
495 rc=CUtils::Launch(strFile,pDoc->m_strViewer);
502 bool CConfigItem::ViewURL()
504 return CConfigTool::GetConfigToolDoc()->ShowURL(GetURL());
507 // Unload (a package)
508 bool CConfigItem::Unload()
511 CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
513 CConfigToolDoc* pDoc=CConfigTool::GetConfigToolDoc();
514 // Remove its objects from the view to prevent any painting problems
515 CConfigTool::GetControlView()->GetTreeCtrl().DeleteItem(HItem());
516 for(int nItem=0;nItem<pDoc->ItemCount();nItem++){
517 CConfigItem *pItem=pDoc->Item(nItem);
518 if(package==pItem->GetOwnerPackage()){
519 //CConfigTool::GetControlView()->GetTreeCtrl().DeleteItem(pItem->HItem());
520 pItem->m_hItem=NULL; // Make sure we can't attempt to paint it
521 pItem->m_CdlItem=NULL; // Make sure we can't access stale data
525 const CString strMacroName(Macro());
526 TRACE (_T("Unloading package %s\n"), strMacroName);
528 pDoc->GetCdlConfig()->unload_package (package);
531 catch (CdlStringException exception) {
532 CUtils::MessageBoxF(_T("Error unloading package %s:\n\n%s"), strMacroName, CString (exception.get_message ().c_str ()));
535 CUtils::MessageBoxF(_T("Error unloading package %s"), strMacroName);
537 m_hItem=NULL; // Make sure we can't attempt to paint it
538 m_CdlItem=NULL; // Make sure we can't access stale data
542 // Change version (of a package)
543 bool CConfigItem::ChangeVersion(const CString &strVersion)
546 CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
548 const CdlValuable valuable = GetCdlValuable();
550 const CString strMacroName(Macro());
551 if (strVersion != valuable->get_value ().c_str ()) { // if the wrong version is loaded
552 TRACE (_T("Changing package %s to version '%s'\n"), strMacroName, strVersion);
554 CConfigTool::GetConfigToolDoc()->GetCdlConfig()->change_package_version (package, CUtils::UnicodeToStdStr (strVersion), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
557 catch (CdlStringException exception) {
558 CUtils::MessageBoxF(_T("Error changing package %s to version '%s':\n\n%s"), strMacroName, strVersion, CString (exception.get_message ().c_str ()));
561 CUtils::MessageBoxF(_T("Error changing package %s to version '%s'"), strMacroName, strVersion);
567 CConfigItem *CConfigItem::Parent() const
569 CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
570 HTREEITEM hParent=tree.GetParentItem(HItem());
571 return (NULL==hParent||TVI_ROOT==hParent)?NULL:(CConfigItem *)tree.GetItemData(hParent);
574 CConfigItem *CConfigItem::FirstChild() const
576 CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
577 HTREEITEM hChild=tree.GetChildItem(HItem());
578 return hChild?(CConfigItem *)tree.GetItemData(hChild):NULL;
581 CConfigItem *CConfigItem::NextSibling() const
583 CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
584 HTREEITEM hSibling=tree.GetNextSiblingItem(HItem());
585 return hSibling?(CConfigItem *)tree.GetItemData(hSibling):NULL;