]> git.saurik.com Git - wxWidgets.git/blame - utils/configtool/src/configitem.cpp
fix some more samples for digital mars
[wxWidgets.git] / utils / configtool / src / configitem.cpp
CommitLineData
d7463f75
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: configitem.cpp
3// Purpose: wxWindows Configuration Tool config item class
4// Author: Julian Smart
5// Modified by:
6// Created: 2003-06-03
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence:
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "configitem.h"
14#endif
15
16// Includes other headers for precompiled compilation
17#include "wx/wx.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#include "wx/tokenzr.h"
24
25#include "configitem.h"
26#include "configtree.h"
27#include "configtooldoc.h"
28#include "configtoolview.h"
29#include "wxconfigtool.h"
30#include "mainframe.h"
31
32IMPLEMENT_CLASS(ctConfigItem, wxObject)
33
34ctConfigItem::ctConfigItem()
35{
36 m_modified = FALSE;
37 m_type = ctTypeBoolCheck;
38 m_treeItemId = wxTreeItemId();
39 m_enabled = TRUE;
40 m_parent = NULL;
41 m_active = TRUE;
42}
43
44ctConfigItem::ctConfigItem(ctConfigItem* parent, ctConfigType type, const wxString& name)
45{
46 m_modified = FALSE;
47 m_type = type;
48 m_treeItemId = wxTreeItemId();
49 m_enabled = FALSE;
50 m_active = TRUE;
51 SetName(name);
52 m_parent = parent;
53 if (parent)
54 parent->AddChild(this);
55}
56
57ctConfigItem::~ctConfigItem()
58{
59 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
60 if (m_treeItemId.IsOk() && treeCtrl)
61 {
62 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
63 if (data)
64 data->SetConfigItem(NULL);
65 }
66 if (GetParent())
67 GetParent()->RemoveChild(this);
68 else
69 {
70 if (wxGetApp().GetMainFrame()->GetDocument() &&
71 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
72 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
73 }
74
75 Clear();
76}
77
78/// Can we edit this property?
79bool ctConfigItem::CanEditProperty(const wxString& propName) const
80{
81 ctProperty* prop = m_properties.FindProperty(propName);
82 if (prop)
83 return !prop->GetReadOnly();
84 else
85 return FALSE;
86}
87
88/// Assignment operator.
89void ctConfigItem::operator= (const ctConfigItem& item)
90{
91 m_properties = item.m_properties;
92 m_modified = item.m_modified;
93 m_defaultProperty = item.m_defaultProperty;
94 m_type = item.m_type;
95 m_enabled = item.m_enabled;
96 m_active = item.m_active;
97}
98
99/// Sets the name property.
100void ctConfigItem::SetName(const wxString& name )
101{
102 m_properties.SetProperty(wxT("name"), name);
103}
104
105/// Clear children
106void ctConfigItem::Clear()
107{
108 wxNode* node = m_children.GetFirst();
109 while (node)
110 {
111 wxNode* next = node->GetNext();
112 ctConfigItem* child = (ctConfigItem*) node->GetData();
113
114 // This should delete 'node' too, assuming
115 // child's m_parent points to 'this'. If not,
116 // it'll be cleaned up by m_children.Clear().
117 delete child;
118
119 node = next;
120 }
121 m_children.Clear();
122}
123
124// Get the nth child
125ctConfigItem* ctConfigItem::GetChild(int n) const
126{
127 wxASSERT ( n < GetChildCount() && n > -1 );
128
129 if ( n < GetChildCount() && n > -1 )
130 {
f8105809 131 ctConfigItem* child = wxDynamicCast(m_children.Item(n)->GetData(), ctConfigItem);
d7463f75
JS
132 return child;
133 }
134 else
135 return NULL;
136}
137
138// Get the child count
139int ctConfigItem::GetChildCount() const
140{
141 return m_children.GetCount();
142}
143
144/// Add a child
145void ctConfigItem::AddChild(ctConfigItem* item)
146{
147 m_children.Append(item);
148 item->SetParent(this);
149}
150
151/// Remove (but don't delete) a child
152void ctConfigItem::RemoveChild(ctConfigItem* item)
153{
154 m_children.DeleteObject(item);
155 item->SetParent(NULL);
156}
157
158/// Initialise standard properties
159void ctConfigItem::InitProperties()
160{
161 ctProperty* prop = m_properties.FindProperty(wxT("name"));
162 if (!prop)
163 {
164 prop = new ctProperty;
165 m_properties.AddProperty(prop);
166 }
167 prop->SetDescription(_("<B>Name</B><P> The name of the configuration setting."));
168 prop->SetReadOnly(TRUE);
169
170 m_properties.AddProperty(
171 new ctProperty(
172 wxT("<B>Description</B><P> The setting description."),
173 wxVariant(wxT(""), wxT("description")),
174 wxT("multiline")));
175
176 m_properties.AddProperty(
177 new ctProperty(
178 wxT("<B>Default-state</B><P> The default state."),
179 wxVariant((bool) TRUE, wxT("default-state")),
180 wxT("bool")));
181
182 if (GetType() == ctTypeString)
183 {
184 m_properties.AddProperty(
185 new ctProperty(
186 wxT("<B>Default-value</B><P> The default value."),
187 wxVariant((bool) TRUE, wxT("default-value")),
188 wxT("")));
189 }
190 else if (GetType() == ctTypeInteger)
191 {
192 m_properties.AddProperty(
193 new ctProperty(
194 wxT("<B>Default-value</B><P> The default value."),
195 wxVariant((long) 0, wxT("default-value")),
196 wxT("")));
197 }
198
199 m_properties.AddProperty(
200 new ctProperty(
201 wxT("<B>Requires</B><P> When any of the given settings are 0, this setting <I>must</I> be 0. Taking wxUSE_ZIPSTREAM as an example:<P> If wxUSE_STREAMS is 0, then wxUSE_ZIPSTREAM must be 0.<BR>If wxUSE_STREAMS is 1, then wxUSE_ZIPSTREAM may be 0 or 1."),
202 wxVariant(wxT(""), wxT("requires")),
203 wxT("configitems")));
204
205 m_properties.AddProperty(
206 new ctProperty(
207 wxT("<B>Precludes</B><P> When any of these settings are 1, this setting <I>must</I> be 0. Taking wxUSE_ODBC as an example:<P> If wxUSE_UNICODE is 1, then wxUSE_ODBC must be 0.<BR>If wxUSE_UNICODE is 0, then wxUSE_ODBC may be 0 or 1."),
208 wxVariant(wxT(""), wxT("precludes")),
209 wxT("configitems")));
210
211 m_properties.AddProperty(
212 new ctProperty(
213 wxT("<B>Enabled-if</B><P> When any of these settings are 1, this setting <I>must</I> be 1."),
214 wxVariant(wxT(""), wxT("enabled-if")),
215 wxT("configitems")));
216
217 m_properties.AddProperty(
218 new ctProperty(
219 wxT("<B>Enabled-if-not</B><P> When any of these settings are 0, this setting <I>must</I> be 1. Taking wxUSE_TOOLBAR_SIMPLE as an example:<P>If wxUSE_TOOLBAR_NATIVE is 0, wxUSE_TOOLBAR_SIMPLE must be 1.<BR>If wxUSE_TOOLBAR_NATIVE is 1, wxUSE_TOOLBAR_SIMPLE may be 0 or 1."),
220 wxVariant(wxT(""), wxT("enabled-if-not")),
221 wxT("configitems")));
222
223 m_properties.AddProperty(
224 new ctProperty(
225 wxT("<B>Exclusivity</B><P> The settings that are mutually exclusive with this one."),
226 wxVariant(wxT(""), wxT("exclusivity")),
227 wxT("configitems")));
228
229 m_properties.AddProperty(
230 new ctProperty(
231 wxT("<B>Context</B><P> A list of symbols (config settings), at least one of which must be enabled for this item to participate in dependency rules.<P>\nIf empty, this item will always be used in dependency rules.<P>\nMostly this will be used to specify the applicable platforms, but it can contain other symbols, for example compilers."),
232 wxVariant(wxT(""), wxT("context")),
233 wxT("configitems")));
234
235 m_properties.AddProperty(
236 new ctProperty(
237 wxT("<B>Configure-command</B><P> Configure command to generate if this is on."),
238 wxVariant(wxT(""), wxT("configure-command")),
239 wxT("multiline")));
240
241 m_properties.AddProperty(
242 new ctProperty(
243 wxT("<B>Help-topic</B><P> The help topic in the wxWindows manual for this component or setting."),
244 wxVariant(wxT(""), wxT("help-topic")),
245 wxT("multiline")));
246
247 m_properties.AddProperty(
248 new ctProperty(
249 wxT("<B>Notes</B><P> User notes."),
250 wxVariant(wxT(""), wxT("notes")),
251 wxT("multiline")));
252
253 m_defaultProperty = wxT("description");
254}
255
256/// Do additional actions to apply the property to the internal
257/// representation.
258void ctConfigItem::ApplyProperty(ctProperty* prop, const wxVariant& oldValue)
259{
260 ctConfigToolDoc* doc = GetDocument();
261 bool oldModified = doc->IsModified();
262 doc->Modify(TRUE);
263
264 wxString name = prop->GetName();
265 if (name == wxT("requires") ||
266 name == wxT("precludes") ||
267 name == wxT("enabled-if") ||
268 name == wxT("enabled-if-not") ||
269 name == wxT("context"))
270 {
271 doc->RefreshDependencies();
272 }
273 if (doc && doc->GetFirstView() && oldModified != doc->IsModified())
274 ((ctConfigToolView*)doc->GetFirstView())->OnChangeFilename();
275}
276
277/// Get the associated document (currently, assumes
278/// there's only ever one document active)
279ctConfigToolDoc* ctConfigItem::GetDocument()
280{
281 ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
282 return doc;
283}
284
285/// Convert string containing config item names to
286/// an array of config item names
287void ctConfigItem::StringToArray(const wxString& items, wxArrayString& itemsArray)
288{
289 wxStringTokenizer tokenizer(items, wxT(","));
290 while (tokenizer.HasMoreTokens())
291 {
292 wxString token = tokenizer.GetNextToken();
293 itemsArray.Add(token);
294 }
295}
296
297/// Convert array containing config item names to
298/// a string
299void ctConfigItem::ArrayToString(const wxArrayString& itemsArray, wxString& items)
300{
301 items = wxEmptyString;
302 size_t i;
303 for (i = 0; i < itemsArray.GetCount(); i++)
304 {
305 items += itemsArray[i];
306 if (i < (itemsArray.GetCount() - 1))
307 items += wxT(",");
308 }
309}
310
311/// Populate a list of items found in the string.
312void ctConfigItem::StringToItems(ctConfigItem* topItem, const wxString& items, wxList& list)
313{
314 wxArrayString strArray;
315 StringToArray(items, strArray);
316 size_t i;
317 for (i = 0; i < strArray.GetCount(); i++)
318 {
319 wxString str(strArray[i]);
320 ctConfigItem* item = topItem->FindItem(str);
321 if (item)
322 list.Append(item);
323 }
324}
325
326/// Find an item in this hierarchy
327ctConfigItem* ctConfigItem::FindItem(const wxString& name)
328{
329 if (GetName() == name)
330 return this;
331
332 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
333 {
334 ctConfigItem* child = (ctConfigItem*) node->GetData();
335 ctConfigItem* found = child->FindItem(name);
336 if (found)
337 return found;
338 }
339 return NULL;
340}
341
342/// Find the next sibling
343ctConfigItem* ctConfigItem::FindNextSibling()
344{
345 if (!GetParent())
346 return NULL;
347 wxNode* node = GetParent()->GetChildren().Member(this);
348 if (node && node->GetNext())
349 {
350 return (ctConfigItem*) node->GetNext()->GetData();
351 }
352 return NULL;
353}
354
355/// Find the previous sibling
356ctConfigItem* ctConfigItem::FindPreviousSibling()
357{
358 if (!GetParent())
359 return NULL;
360 wxNode* node = GetParent()->GetChildren().Member(this);
361 if (node && node->GetPrevious())
362 {
363 return (ctConfigItem*) node->GetPrevious()->GetData();
364 }
365 return NULL;
366}
367
368/// Sync appearance
369void ctConfigItem::Sync()
370{
371 if (GetDocument())
372 {
373 ctConfigToolView* view = (ctConfigToolView*) GetDocument()->GetFirstView();
374 if (view)
375 {
376 view->SyncItem(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), this);
377 }
378 }
379}
380
381/// Create a clone of this and children
382ctConfigItem* ctConfigItem::DeepClone()
383{
384 ctConfigItem* newItem = Clone();
385
386 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
387 {
388 ctConfigItem* child = (ctConfigItem*) node->GetData();
389 ctConfigItem* newChild = child->DeepClone();
390 newItem->AddChild(newChild);
391 }
392 return newItem;
393}
394
395/// Detach: remove from parent, and remove tree items
396void ctConfigItem::Detach()
397{
398 if (GetParent())
399 GetParent()->RemoveChild(this);
400 else
401 GetDocument()->SetTopItem(NULL);
402 SetParent(NULL);
403
404 wxTreeItemId treeItem = GetTreeItemId();
405
406 DetachFromTree();
407
408 // Will delete the branch, but not the config items.
409 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
410}
411
412/// Hide from tree: make sure tree deletions won't delete
413/// the config items
414void ctConfigItem::DetachFromTree()
415{
416 wxTreeItemId item = GetTreeItemId();
417
418 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
419 data->SetConfigItem(NULL);
420 m_treeItemId = wxTreeItemId();
421
422 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
423 {
424 ctConfigItem* child = (ctConfigItem*) node->GetData();
425 child->DetachFromTree();
426 }
427}
428
429/// Attach: insert after the given position
430void ctConfigItem::Attach(ctConfigItem* parent, ctConfigItem* insertBefore)
431{
432 if (parent)
433 {
434 SetParent(parent);
435 wxNode* node = NULL;
436 if (insertBefore)
437 node = parent->GetChildren().Member(insertBefore);
438
439 if (node)
440 parent->GetChildren().Insert(node, this);
441 else
442 parent->GetChildren().Append(this);
443 }
444 else
445 {
446 GetDocument()->SetTopItem(this);
447 }
448}
449
450/// Can have children?
451bool ctConfigItem::CanHaveChildren() const
452{
453 return (GetType() == ctTypeGroup ||
454 GetType() == ctTypeCheckGroup ||
455 GetType() == ctTypeRadioGroup);
456}
457
458// An item is in the active context if:
459// The context field is empty; or
460// The context field contains a symbol that is currently enabled.
461bool ctConfigItem::IsInActiveContext()
462{
463 wxString context = GetPropertyString(wxT("context"));
464 if (context.IsEmpty())
465 return TRUE;
466
467 wxList contextItems;
468 StringToItems(GetDocument()->GetTopItem(), context, contextItems);
469
470 for ( wxNode* node = contextItems.GetFirst(); node; node = node->GetNext() )
471 {
472 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
473 if (otherItem->IsEnabled())
474 return TRUE;
475 }
476 return FALSE;
477}
478
479/// Evaluate the requires properties:
480/// if any of the 'requires' items are disabled,
481/// then this one is disabled (and inactive).
482void ctConfigItem::EvaluateDependencies()
483{
484 wxList items;
485 wxString requires = GetPropertyString(wxT("requires"));
486 wxString precludes = GetPropertyString(wxT("precludes"));
487 wxString enabledIf = GetPropertyString(wxT("enabled-if"));
488 wxString enabledIfNot = GetPropertyString(wxT("enabled-if-not"));
489
490 bool active = TRUE;
491 bool enabled = IsEnabled();
492 bool oldEnabled = enabled;
493 bool oldActive = IsActive();
494 bool explicitlyEnabled = FALSE;
495 bool explicitlyDisabled = FALSE;
496 bool inActiveContext = IsInActiveContext();
497
498 // Add the parent to the list of dependencies, if the
499 // parent is a check or radio group.
500 ctConfigItem* parent = GetParent();
501 if (parent &&
502 (parent->GetType() == ctTypeCheckGroup ||
503 parent->GetType() == ctTypeRadioGroup))
504 items.Append(parent);
505
506 wxList tempItems;
507 StringToItems(GetDocument()->GetTopItem(), requires, tempItems);
508
509 wxNode* node;
510 for ( node = tempItems.GetFirst(); node; node = node->GetNext() )
511 {
512 // Only consider the dependency if both items are in
513 // an active context.
514 // Each is in the active context if:
515 // The context field is empty; or
516 // The context field contains a symbol that is currently enabled.
517 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
518 if (inActiveContext && otherItem->IsInActiveContext())
519 items.Append(otherItem);
520 }
521
522 {
523 int enabledCount = 0;
524 for ( node = items.GetFirst(); node; node = node->GetNext() )
525 {
526 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
527
528 if (otherItem->IsEnabled())
529 {
530 enabledCount ++;
531 }
532 }
533 if (items.GetCount() > 0 && enabledCount == 0)
534 {
535 // None of the items were enabled
536 enabled = FALSE;
537 active = FALSE;
538 explicitlyDisabled = TRUE;
539 }
540 }
541
542 items.Clear();
543 if (!enabledIfNot.IsEmpty())
544 {
545 StringToItems(GetDocument()->GetTopItem(), enabledIfNot, items);
546 int disabledCount = 0;
547 int inContextCount = 0;
548
549 for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
550 {
551 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
552
553 if (inActiveContext && otherItem->IsInActiveContext())
554 {
555 // Make this enabled and inactive, _unless_ it's
556 // already been explicitly disabled in the previous
557 // requires evaluation (it really _has_ to be off)
558 if (!otherItem->IsEnabled())
559 {
560 disabledCount ++;
561 }
562 inContextCount ++;
563 }
564 }
565 // Enable if there were no related items that were enabled
566 if (inContextCount > 0 && (disabledCount == inContextCount) && !explicitlyDisabled)
567 {
568 explicitlyEnabled = TRUE;
569 enabled = TRUE;
570 active = FALSE;
571 }
572 }
573
574 items.Clear();
575 if (!enabledIf.IsEmpty())
576 {
577 StringToItems(GetDocument()->GetTopItem(), enabledIf, items);
578 int enabledCount = 0;
579 int inContextCount = 0;
580
581 for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
582 {
583 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
584
585 if (inActiveContext && otherItem->IsInActiveContext())
586 {
587 // Make this enabled and inactive, _unless_ it's
588 // already been explicitly disabled in the previous
589 // requires evaluation (it really _has_ to be off)
590 if (otherItem->IsEnabled())
591 {
592 enabledCount ++;
593 }
594 inContextCount ++;
595 }
596 }
597 // Enable if there were no related items that were disabled
598 if (inContextCount > 0 && (enabledCount > 0) && !explicitlyDisabled)
599 {
600 explicitlyEnabled = TRUE;
601 enabled = TRUE;
602 active = FALSE;
603 }
604 }
605
606 items.Clear();
607 if (!precludes.IsEmpty())
608 {
609 StringToItems(GetDocument()->GetTopItem(), precludes, items);
610 int enabledCount = 0;
611 int inContextCount = 0;
612
613 for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
614 {
615 ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
616
617 if (inActiveContext && otherItem->IsInActiveContext())
618 {
619 // Make this enabled and inactive, _unless_ it's
620 // already been explicitly disabled in the previous
621 // requires evaluation (it really _has_ to be off)
622 if (otherItem->IsEnabled())
623 {
624 enabledCount ++;
625 }
626 }
627 }
628 // Disable if there were no related items that were disabled
629 if (inContextCount > 0 && (enabledCount == inContextCount) && !explicitlyEnabled)
630 {
631 enabled = FALSE;
632 active = FALSE;
633 }
634 }
635
636 // Finally check a sort of dependency: whether our
637 // context is active. If not, make this inactive.
638 if (!IsInActiveContext())
639 active = FALSE;
640
641 SetActive(active);
642
643 // If going active, set enabled state to the default state
644 if (active &&
645 oldActive != active &&
646 (GetType() == ctTypeBoolCheck || GetType() == ctTypeCheckGroup) &&
647 m_properties.FindProperty(wxT("default-state")))
648 {
649 bool defaultState = m_properties.FindProperty(wxT("default-state"))->GetVariant().GetBool();
650 enabled = defaultState;
651 }
652 Enable(enabled);
653
654 // Deal with setting a radio button
655 if (enabled && enabled != oldEnabled &&
656 (GetType() == ctTypeBoolRadio || GetType() == ctTypeRadioGroup))
657 {
658 wxList considered;
659 PropagateRadioButton(considered);
660 }
661}
662
663/// Get description, which may be dynamically
664/// generated depending on the property.
665wxString ctConfigItem::GetDescription(ctProperty* property)
666{
667 if (property->GetName() == wxT("description"))
668 {
669 wxString value(property->GetValue());
670 if (value.IsEmpty())
671 return wxT("Double-click on <B>description</B> to write a brief explanation of the setting.<P>");
672 else
673 return value;
674 }
675 else if (property->GetName() == wxT("notes"))
676 {
677 wxString value(property->GetValue());
678 if (value.IsEmpty())
679 return wxT("Double-click on <B>notes</B> to write notes about this setting.<P>");
680 else
681 return value;
682 }
683 return property->GetDescription();
684}
685
686/// Get the title for the property editor
687wxString ctConfigItem::GetTitle()
688{
689 wxString title(GetName());
690 if (GetType() == ctTypeCheckGroup ||
691 GetType() == ctTypeRadioGroup ||
692 GetType() == ctTypeBoolCheck ||
693 GetType() == ctTypeBoolRadio)
694 {
695 if (IsEnabled())
696 title = title + _T(" - enabled");
697 else
698 title = title + _T(" - disabled");
699 }
700 return title;
701}
702
703/// Propagate a change in enabled/disabled status
704void ctConfigItem::PropagateChange(wxList& considered)
705{
706 if (GetType() == ctTypeCheckGroup ||
707 GetType() == ctTypeRadioGroup ||
708 GetType() == ctTypeBoolCheck ||
709 GetType() == ctTypeBoolRadio)
710 {
711 // TODO: what about string, integer? Can they have
712 // dependencies?
713
714 for ( wxNode* node = GetDependents().GetFirst(); node; node = node->GetNext() )
715 {
716 ctConfigItem* child = (ctConfigItem*) node->GetData();
717
718 // Avoid loops
719 if (!considered.Member(child))
720 {
721 considered.Append(child);
722
723 child->EvaluateDependencies();
724 child->Sync();
725
726 child->PropagateChange(considered);
727 }
728 }
729 }
730}
731
732/// Process radio button selection
733void ctConfigItem::PropagateRadioButton(wxList& considered)
734{
735 if ((GetType() == ctTypeBoolRadio || GetType() == ctTypeRadioGroup) && IsEnabled())
736 {
737 wxString mutuallyExclusive(GetPropertyString(wxT("exclusivity")));
738
739 wxList list;
740 StringToItems(GetDocument()->GetTopItem(), mutuallyExclusive, list);
741
742 for ( wxNode* node = list.GetFirst(); node; node = node->GetNext() )
743 {
744 ctConfigItem* child = (ctConfigItem*) node->GetData();
745 if (child->IsEnabled() && child != this)
746 {
747 child->Enable(FALSE);
748 child->Sync();
749
750 if (!considered.Member(child))
751 child->PropagateChange(considered);
752 }
753 }
754 }
755}