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