]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/common/win32/ConfigItem.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / common / win32 / ConfigItem.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
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) 
11 // any later version.
12 // 
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 
16 // more details.
17 // 
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.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 //
26 //===========================================================================
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
29 //
30 // Author(s):   sdf
31 // Contact(s):  sdf
32 // Date:                1998/08/11
33 // Version:             0.01
34 // Purpose:     
35 // Description: This is the implementation of the configuration item class
36 // Requires:    
37 // Provides:    
38 // See also:    
39 // Known bugs:  
40 // Usage:       
41 //
42 //####DESCRIPTIONEND####
43 //
44 //===========================================================================
45 #include "stdafx.h"
46 #include "ConfigItem.h"
47 #include "ControlView.h"
48 #include "CTUtils.h"
49 #ifdef PLUGIN
50   #define INCLUDEFILE "ide.common.h" // for setEditLocation
51   #include "IncludeSTL.h"
52   #include "common/CodeCoordinate.h"
53 #endif
54 #include "ConfigToolDoc.h"
55 #include "ConfigTool.h"
56
57 LPCTSTR CConfigItem::TreeItemTypeImage[MaxTreeItemType + 1]={
58   _T("None"), _T("Integer"), _T("Enumeration"), _T("String"), _T("Double"), 0}; // Internationalization OK
59
60 const CFileName CConfigItem::FileName() const
61 {
62   CFileName strFile;
63   const CdlNode node = dynamic_cast<CdlNode> (m_CdlItem);
64   if (node){
65     // get the package which owns the configuration item
66     const CdlPackage package = GetOwnerPackage();
67     if (package){
68       
69       // return the filename of the config header
70       strFile=CFileName(CConfigTool::GetConfigToolDoc()->InstallTree()+_T("include\\pkgconf"))+package->get_config_header ().c_str ();
71     }
72   }
73   return strFile;
74 }
75
76 CConfigItem::CConfigItem(CConfigItem *pParent, CdlUserVisible CdlItem):
77   m_CdlItem(CdlItem)
78 {
79   CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
80   HTREEITEM hParent;
81   if(NULL==CdlItem){
82     // This is the root item
83     hParent=TVI_ROOT;
84     m_Type=None;
85   } else {
86     hParent=pParent->HItem();
87   
88     // FIXME: re-implement using CdlValuableBody::get_widget_hint()
89     if (IsPackage()) {
90       // If a package item, display the package version string
91       m_Type=String; 
92     } else {
93       const CdlValuable valuable = dynamic_cast<CdlValuable> (CdlItem);
94       switch (valuable->get_flavor ()){
95         case CdlValueFlavor_None:
96         case CdlValueFlavor_Bool:
97           m_Type=None;
98           break;
99         case CdlValueFlavor_Data:
100         case CdlValueFlavor_BoolData:
101           if (! valuable->has_legal_values ()) {
102             m_Type=String;
103           } else if (0 == valuable->get_legal_values ()->ranges.size ()) {
104             m_Type=Enum;
105           } else {
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;
110           }
111           break;
112         default:
113           ASSERT (0); // specified flavor not supported
114           break;
115       }
116     }  
117   }
118   m_hItem=tree.InsertItem(ItemNameOrMacro(),hParent);
119   tree.SetItemData(m_hItem,(DWORD)this);
120   CConfigTool::GetControlView()->AdjustItemImage(m_hItem);
121 }
122
123 CConfigItem::~CConfigItem()
124 {
125 }
126
127 CString CConfigItem::GetURL() const
128 {
129   for(const CConfigItem *pItem=this;pItem;pItem=pItem->Parent()){
130     if(pItem->GetCdlItem()){
131       CString strURL;
132       strURL=pItem->GetCdlItem()->get_doc_url().c_str();
133       if(strURL.GetLength()){
134         return strURL;
135       }
136       strURL=pItem->GetCdlItem()->get_doc().c_str();
137       if(strURL.GetLength()){
138         return strURL;
139       }
140     }
141   }
142   return _T("ref/ecos-ref.html"); // the default URL
143 }
144
145 bool CConfigItem::SetValue(LPCTSTR pszValue, CdlTransaction transaction/*=NULL*/)
146 {
147   ASSERT ((m_Type == String) || (m_Type == Enum));
148   const CdlValuable valuable = GetCdlValuable();
149   ASSERT (valuable);
150   const std::string str=CUtils::UnicodeToStdStr (pszValue);
151   if(transaction){
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);
158     }
159   } else {
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);
166     }
167   }
168   
169   return true;
170 }
171
172 bool CConfigItem::SetValue (double dValue, CdlTransaction transaction/*=NULL*/)
173 {
174   ASSERT (m_Type == Double);
175   const CdlValuable valuable = GetCdlValuable();
176   ASSERT (valuable);
177   
178   if(transaction) {
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);
185     }
186   } else {
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);
193     }
194   }
195   
196   return true;
197 }
198
199 CConfigItem *CConfigItem::FirstRadio() const
200 {
201   ASSERT(HasRadio ());
202   
203   for(CConfigItem *h=Parent()->FirstChild();h;h=h->NextSibling()){
204     if(h->HasRadio ()){
205       return h;
206     }
207   }
208   // No radio buttons found
209   ASSERT(false);
210   return false;
211 }
212
213 bool CConfigItem::IsEnabled() const
214 {
215   const CdlValuable valuable = GetCdlValuable();
216   return NULL==valuable ||valuable->is_enabled();
217 }
218
219 bool CConfigItem::SetValue (ItemIntegerType nValue, CdlTransaction transaction/*=NULL*/)
220 {
221   ASSERT (m_Type == Integer);
222   const CdlValuable valuable = GetCdlValuable();
223   ASSERT (valuable);
224
225   if(transaction) {
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);
232     }
233   } else {
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);
240     }
241   }
242   
243   return true;
244 }
245
246 bool CConfigItem::HasModifiedChildren() const
247 {
248   for(CConfigItem *pItem=FirstChild();pItem;pItem=pItem->NextSibling()){
249     if(pItem->Modified()||pItem->HasModifiedChildren()){
250       return true;
251     }
252   }
253   return false;
254 }
255
256 ItemIntegerType CConfigItem::Value () const
257 {
258   ASSERT (!IsPackage()); // not a package item
259   const CdlValuable valuable = GetCdlValuable();
260   ASSERT (valuable);
261   ItemIntegerType nValue (0);
262   
263   switch (valuable->get_flavor ())
264   {
265     //  case CdlValueFlavor_Bool:
266     //          nValue = valuable->is_enabled (CdlValueSource_Current) ? 1 : 0;
267     //          break;
268     
269   case CdlValueFlavor_BoolData:
270   case CdlValueFlavor_Data:
271     nValue = (ItemIntegerType) valuable->get_integer_value (CdlValueSource_Current);
272     break;
273     
274   default:
275     ASSERT (0); // specified flavor not supported
276   }
277   
278   return nValue;
279 }
280
281 const double CConfigItem::DoubleValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
282 {
283   ASSERT (!IsPackage()); // not a package item
284   const CdlValuable valuable = GetCdlValuable();
285   ASSERT (valuable);
286   ASSERT (valuable->has_double_value (source));
287   return valuable->get_double_value (source);
288 }
289
290 ItemIntegerType CConfigItem::DefaultValue () const
291 {
292   ItemIntegerType nValue;
293   return CUtils::StrToItemIntegerType (StringValue (CdlValueSource_Default), nValue) ? nValue : 0;
294 }
295
296 const CString CConfigItem::StringValue (CdlValueSource source /* = CdlValueSource_Current */ ) const
297 {
298   //    ASSERT (!IsPackage()); // not a package item
299   const CdlValuable valuable = GetCdlValuable();
300   ASSERT (valuable);
301   CString strValue (_T(""));
302   
303   switch (valuable->get_flavor ())
304   {
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 ());
312       else
313         strValue = valuable->get_value (source).c_str ();
314       break;
315     
316     default:
317       ASSERT (0); // specified flavor not supported
318   }
319   
320   return strValue;
321 }
322
323 const CString CConfigItem::StringValue(WhereType where) const
324 {
325   CString str;
326   switch(where){
327     case InName:
328       str=Name();
329       break;
330     case InMacro:
331       str=Macro();
332       break;
333     case InDesc:
334       str=Desc();
335       break;
336     case InCurrentValue:
337       str=CConfigItem::None==Type()?_T(""):StringValue(CdlValueSource_Current);
338       break;
339     case InDefaultValue:
340       str=CConfigItem::None==Type()?_T(""):StringValue(CdlValueSource_Default);
341       break;
342     default:
343       ASSERT(FALSE);
344       break;
345   }
346   return str;
347 }    
348
349 void CConfigItem::DumpItem()
350 {
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());
354   
355   TRACE(_T("\n"));
356 }
357
358 CConfigItem * CConfigItem::NextRadio() const
359 {
360   ASSERT(this->HasRadio ());
361   for(CConfigItem *pItem=NextSibling();pItem;pItem=pItem->NextSibling()){
362     if(pItem->HasRadio()){
363       return pItem;
364     }
365   }
366   return NULL;
367 }
368
369 bool CConfigItem::Modified () const
370 {
371   const CdlValuable valuable = GetCdlValuable();
372   return 
373     valuable        // accommodate the root config item which has no CDL item
374     && !IsPackage() // packages are never modified
375     && valuable->get_source () != CdlValueSource_Default;
376 }
377
378 CString CConfigItem::ItemNameOrMacro() const
379 {
380   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
381   return pDoc->m_bMacroNames&&!Macro().IsEmpty()?Macro():Name();
382 }
383
384 bool CConfigItem::IsDescendantOf(CConfigItem * pAncestor)
385 {
386   for(CConfigItem *pItem=Parent();pItem;pItem=pItem->Parent()){
387     if(pItem==pAncestor){
388       return true;
389     }
390   }
391   return false;
392 }
393
394 int CConfigItem::EvalEnumStrings (CStringArray &arEnumStrings) const
395 {
396   const CdlValuable valuable = GetCdlValuable();
397   ASSERT (valuable);
398   /*
399   if (m_Type == Boolean)
400   {
401   arEnumStrings.SetSize (2);
402   arEnumStrings.SetAt (0, _T("True"));
403   arEnumStrings.SetAt (1, _T("False"));
404   }
405   else
406   */
407   {
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 ();
413     
414     // add legal values to the list
415     arEnumStrings.SetSize (table.size ());
416     for (unsigned int nValue = 0; nValue < table.size (); nValue++)
417     {
418       arEnumStrings.SetAt (nValue, table [nValue].get_value ().c_str ());
419     }
420   }
421   return arEnumStrings.GetSize();
422 }
423
424 bool CConfigItem::HasBool() const
425 {
426   if (!m_CdlItem) {
427     return false;
428   } else if (IsPackage()) {
429     return false;
430   } else {
431     const CdlValuable valuable = GetCdlValuable();
432     CdlValueFlavor flavor = valuable->get_flavor ();
433     return (flavor == CdlValueFlavor_Bool) || (flavor == CdlValueFlavor_BoolData);
434   }
435 }
436
437 bool CConfigItem::HasRadio() const
438 {
439   const CdlValuable valuable = GetCdlValuable();
440   if (! valuable)
441     return false;
442   
443   CdlWidgetHint hint;
444   valuable->get_widget_hint (hint);
445   return (CdlBoolWidget_Radio == hint.bool_widget);
446 }
447
448 bool CConfigItem::SetEnabled(bool bEnabled, CdlTransaction current_transaction/*=NULL*/)
449 {
450   const CdlValuable valuable = GetCdlValuable();
451   ASSERT (valuable);
452   
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 ());
455   
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
460       }
461     }
462   }
463   
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);
471   }
472   
473   if (! current_transaction) { // if not a recursive call to disable a radio button
474     transaction->body (); // commit the transaction
475     deleteZ(transaction);
476   }
477   
478   return true;
479 }
480
481 bool CConfigItem::ViewHeader()
482 {
483   bool rc=false;
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"));
489     } else {
490 #ifdef PLUGIN
491       // Load or activate window and leave
492       CodeCoordinate loc((LPCTSTR)strFile, 0, 0, CodeCoordinate::FILE_LINE);
493       rc=AppInstance::getAppManager()->getEditorController()->setEditLocation(loc);
494 #else
495       rc=CUtils::Launch(strFile,pDoc->m_strViewer);
496 #endif
497     }
498   }
499   return rc;
500 }
501
502 bool CConfigItem::ViewURL()
503 {
504   return CConfigTool::GetConfigToolDoc()->ShowURL(GetURL());
505 }
506
507 // Unload (a package)
508 bool CConfigItem::Unload()
509 {
510   bool rc=false;
511   CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
512   ASSERT(package);
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
522     }
523   }
524   
525   const CString strMacroName(Macro());
526   TRACE (_T("Unloading package %s\n"), strMacroName);
527   try {
528     pDoc->GetCdlConfig()->unload_package (package);
529     rc=true;
530   }
531   catch (CdlStringException exception) {
532     CUtils::MessageBoxF(_T("Error unloading package %s:\n\n%s"), strMacroName, CString (exception.get_message ().c_str ()));
533   }
534   catch (...) {
535     CUtils::MessageBoxF(_T("Error unloading package %s"), strMacroName);
536   }
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
539   return rc;
540 }
541
542 // Change version (of a package)
543 bool CConfigItem::ChangeVersion(const CString &strVersion)
544 {
545   bool rc=false;
546   CdlPackage package=dynamic_cast<CdlPackage>(GetCdlItem());
547   ASSERT(package);
548   const CdlValuable valuable = GetCdlValuable();
549   ASSERT (valuable);
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);
553     try {
554       CConfigTool::GetConfigToolDoc()->GetCdlConfig()->change_package_version (package, CUtils::UnicodeToStdStr (strVersion), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
555       rc=true;
556     }
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 ()));
559     }
560     catch (...) {
561       CUtils::MessageBoxF(_T("Error changing package %s to version '%s'"), strMacroName, strVersion);
562     }
563   }
564   return rc;
565 }
566
567 CConfigItem *CConfigItem::Parent() const 
568
569   CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
570   HTREEITEM hParent=tree.GetParentItem(HItem());
571   return (NULL==hParent||TVI_ROOT==hParent)?NULL:(CConfigItem *)tree.GetItemData(hParent);
572 }
573
574 CConfigItem *CConfigItem::FirstChild() const
575
576   CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
577   HTREEITEM hChild=tree.GetChildItem(HItem());
578   return hChild?(CConfigItem *)tree.GetItemData(hChild):NULL;
579 }
580
581 CConfigItem *CConfigItem::NextSibling() const
582
583   CTreeCtrl &tree=CConfigTool::GetControlView()->GetTreeCtrl();
584   HTREEITEM hSibling=tree.GetNextSiblingItem(HItem());
585   return hSibling?(CConfigItem *)tree.GetItemData(hSibling):NULL;
586 }