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