]>
git.saurik.com Git - wxWidgets.git/blob - utils/configtool/src/configitem.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: configitem.cpp
3 // Purpose: wxWindows Configuration Tool config item class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "configitem.h"
16 // Includes other headers for precompiled compilation
23 #include "wx/tokenzr.h"
25 #include "configitem.h"
26 #include "configtree.h"
27 #include "configtooldoc.h"
28 #include "configtoolview.h"
29 #include "wxconfigtool.h"
30 #include "mainframe.h"
32 IMPLEMENT_CLASS ( ctConfigItem
, wxObject
)
34 ctConfigItem :: ctConfigItem ()
37 m_type
= ctTypeBoolCheck
;
38 m_treeItemId
= wxTreeItemId ();
44 ctConfigItem :: ctConfigItem ( ctConfigItem
* parent
, ctConfigType type
, const wxString
& name
)
48 m_treeItemId
= wxTreeItemId ();
54 parent
-> AddChild ( this );
57 ctConfigItem ::~ ctConfigItem ()
59 ctConfigTreeCtrl
* treeCtrl
= wxGetApp (). GetMainFrame ()-> GetConfigTreeCtrl ();
60 if ( m_treeItemId
. IsOk () && treeCtrl
)
62 ctTreeItemData
* data
= ( ctTreeItemData
*) treeCtrl
-> GetItemData ( m_treeItemId
);
64 data
-> SetConfigItem ( NULL
);
67 GetParent ()-> RemoveChild ( this );
70 if ( wxGetApp (). GetMainFrame ()-> GetDocument () &&
71 wxGetApp (). GetMainFrame ()-> GetDocument ()-> GetTopItem () == this )
72 wxGetApp (). GetMainFrame ()-> GetDocument ()-> SetTopItem ( NULL
);
78 /// Can we edit this property?
79 bool ctConfigItem :: CanEditProperty ( const wxString
& propName
) const
81 ctProperty
* prop
= m_properties
. FindProperty ( propName
);
83 return ! prop
-> GetReadOnly ();
88 /// Assignment operator.
89 void ctConfigItem :: operator = ( const ctConfigItem
& item
)
91 m_properties
= item
. m_properties
;
92 m_modified
= item
. m_modified
;
93 m_defaultProperty
= item
. m_defaultProperty
;
95 m_enabled
= item
. m_enabled
;
96 m_active
= item
. m_active
;
99 /// Sets the name property.
100 void ctConfigItem :: SetName ( const wxString
& name
)
102 m_properties
. SetProperty ( wxT ( "name" ), name
);
106 void ctConfigItem :: Clear ()
108 wxNode
* node
= m_children
. GetFirst ();
111 wxNode
* next
= node
-> GetNext ();
112 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
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().
125 ctConfigItem
* ctConfigItem :: GetChild ( int n
) const
127 wxASSERT ( n
< GetChildCount () && n
> - 1 );
129 if ( n
< GetChildCount () && n
> - 1 )
131 ctConfigItem
* child
= wxDynamicCast ( m_children
. Nth ( n
)-> Data (), ctConfigItem
);
138 // Get the child count
139 int ctConfigItem :: GetChildCount () const
141 return m_children
. GetCount ();
145 void ctConfigItem :: AddChild ( ctConfigItem
* item
)
147 m_children
. Append ( item
);
148 item
-> SetParent ( this );
151 /// Remove (but don't delete) a child
152 void ctConfigItem :: RemoveChild ( ctConfigItem
* item
)
154 m_children
. DeleteObject ( item
);
155 item
-> SetParent ( NULL
);
158 /// Initialise standard properties
159 void ctConfigItem :: InitProperties ()
161 ctProperty
* prop
= m_properties
. FindProperty ( wxT ( "name" ));
164 prop
= new ctProperty
;
165 m_properties
. AddProperty ( prop
);
167 prop
-> SetDescription ( _ ( "<B>Name</B><P> The name of the configuration setting." ));
168 prop
-> SetReadOnly ( TRUE
);
170 m_properties
. AddProperty (
172 wxT ( "<B>Description</B><P> The setting description." ),
173 wxVariant ( wxT ( "" ), wxT ( "description" )),
176 m_properties
. AddProperty (
178 wxT ( "<B>Default-state</B><P> The default state." ),
179 wxVariant (( bool ) TRUE
, wxT ( "default-state" )),
182 if ( GetType () == ctTypeString
)
184 m_properties
. AddProperty (
186 wxT ( "<B>Default-value</B><P> The default value." ),
187 wxVariant (( bool ) TRUE
, wxT ( "default-value" )),
190 else if ( GetType () == ctTypeInteger
)
192 m_properties
. AddProperty (
194 wxT ( "<B>Default-value</B><P> The default value." ),
195 wxVariant (( long ) 0 , wxT ( "default-value" )),
199 m_properties
. AddProperty (
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" )));
205 m_properties
. AddProperty (
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" )));
211 m_properties
. AddProperty (
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" )));
217 m_properties
. AddProperty (
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" )));
223 m_properties
. AddProperty (
225 wxT ( "<B>Exclusivity</B><P> The settings that are mutually exclusive with this one." ),
226 wxVariant ( wxT ( "" ), wxT ( "exclusivity" )),
227 wxT ( "configitems" )));
229 m_properties
. AddProperty (
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> \n If empty, this item will always be used in dependency rules.<P> \n Mostly 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" )));
235 m_properties
. AddProperty (
237 wxT ( "<B>Configure-command</B><P> Configure command to generate if this is on." ),
238 wxVariant ( wxT ( "" ), wxT ( "configure-command" )),
241 m_properties
. AddProperty (
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" )),
247 m_properties
. AddProperty (
249 wxT ( "<B>Notes</B><P> User notes." ),
250 wxVariant ( wxT ( "" ), wxT ( "notes" )),
253 m_defaultProperty
= wxT ( "description" );
256 /// Do additional actions to apply the property to the internal
258 void ctConfigItem :: ApplyProperty ( ctProperty
* prop
, const wxVariant
& oldValue
)
260 ctConfigToolDoc
* doc
= GetDocument ();
261 bool oldModified
= doc
-> IsModified ();
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" ))
271 doc
-> RefreshDependencies ();
273 if ( doc
&& doc
-> GetFirstView () && oldModified
!= doc
-> IsModified ())
274 (( ctConfigToolView
*) doc
-> GetFirstView ())-> OnChangeFilename ();
277 /// Get the associated document (currently, assumes
278 /// there's only ever one document active)
279 ctConfigToolDoc
* ctConfigItem :: GetDocument ()
281 ctConfigToolDoc
* doc
= wxGetApp (). GetMainFrame ()-> GetDocument ();
285 /// Convert string containing config item names to
286 /// an array of config item names
287 void ctConfigItem :: StringToArray ( const wxString
& items
, wxArrayString
& itemsArray
)
289 wxStringTokenizer
tokenizer ( items
, wxT ( "," ));
290 while ( tokenizer
. HasMoreTokens ())
292 wxString token
= tokenizer
. GetNextToken ();
293 itemsArray
. Add ( token
);
297 /// Convert array containing config item names to
299 void ctConfigItem :: ArrayToString ( const wxArrayString
& itemsArray
, wxString
& items
)
301 items
= wxEmptyString
;
303 for ( i
= 0 ; i
< itemsArray
. GetCount (); i
++)
305 items
+= itemsArray
[ i
];
306 if ( i
< ( itemsArray
. GetCount () - 1 ))
311 /// Populate a list of items found in the string.
312 void ctConfigItem :: StringToItems ( ctConfigItem
* topItem
, const wxString
& items
, wxList
& list
)
314 wxArrayString strArray
;
315 StringToArray ( items
, strArray
);
317 for ( i
= 0 ; i
< strArray
. GetCount (); i
++)
319 wxString
str ( strArray
[ i
]);
320 ctConfigItem
* item
= topItem
-> FindItem ( str
);
326 /// Find an item in this hierarchy
327 ctConfigItem
* ctConfigItem :: FindItem ( const wxString
& name
)
329 if ( GetName () == name
)
332 for ( wxNode
* node
= GetChildren (). GetFirst (); node
; node
= node
-> GetNext () )
334 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
335 ctConfigItem
* found
= child
-> FindItem ( name
);
342 /// Find the next sibling
343 ctConfigItem
* ctConfigItem :: FindNextSibling ()
347 wxNode
* node
= GetParent ()-> GetChildren (). Member ( this );
348 if ( node
&& node
-> GetNext ())
350 return ( ctConfigItem
*) node
-> GetNext ()-> GetData ();
355 /// Find the previous sibling
356 ctConfigItem
* ctConfigItem :: FindPreviousSibling ()
360 wxNode
* node
= GetParent ()-> GetChildren (). Member ( this );
361 if ( node
&& node
-> GetPrevious ())
363 return ( ctConfigItem
*) node
-> GetPrevious ()-> GetData ();
369 void ctConfigItem :: Sync ()
373 ctConfigToolView
* view
= ( ctConfigToolView
*) GetDocument ()-> GetFirstView ();
376 view
-> SyncItem ( wxGetApp (). GetMainFrame ()-> GetConfigTreeCtrl (), this );
381 /// Create a clone of this and children
382 ctConfigItem
* ctConfigItem :: DeepClone ()
384 ctConfigItem
* newItem
= Clone ();
386 for ( wxNode
* node
= GetChildren (). GetFirst (); node
; node
= node
-> GetNext () )
388 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
389 ctConfigItem
* newChild
= child
-> DeepClone ();
390 newItem
-> AddChild ( newChild
);
395 /// Detach: remove from parent, and remove tree items
396 void ctConfigItem :: Detach ()
399 GetParent ()-> RemoveChild ( this );
401 GetDocument ()-> SetTopItem ( NULL
);
404 wxTreeItemId treeItem
= GetTreeItemId ();
408 // Will delete the branch, but not the config items.
409 wxGetApp (). GetMainFrame ()-> GetConfigTreeCtrl ()-> Delete ( treeItem
);
412 /// Hide from tree: make sure tree deletions won't delete
414 void ctConfigItem :: DetachFromTree ()
416 wxTreeItemId item
= GetTreeItemId ();
418 ctTreeItemData
* data
= ( ctTreeItemData
*) wxGetApp (). GetMainFrame ()-> GetConfigTreeCtrl ()-> GetItemData ( item
);
419 data
-> SetConfigItem ( NULL
);
420 m_treeItemId
= wxTreeItemId ();
422 for ( wxNode
* node
= GetChildren (). GetFirst (); node
; node
= node
-> GetNext () )
424 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
425 child
-> DetachFromTree ();
429 /// Attach: insert after the given position
430 void ctConfigItem :: Attach ( ctConfigItem
* parent
, ctConfigItem
* insertBefore
)
437 node
= parent
-> GetChildren (). Member ( insertBefore
);
440 parent
-> GetChildren (). Insert ( node
, this );
442 parent
-> GetChildren (). Append ( this );
446 GetDocument ()-> SetTopItem ( this );
450 /// Can have children?
451 bool ctConfigItem :: CanHaveChildren () const
453 return ( GetType () == ctTypeGroup
||
454 GetType () == ctTypeCheckGroup
||
455 GetType () == ctTypeRadioGroup
);
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.
461 bool ctConfigItem :: IsInActiveContext ()
463 wxString context
= GetPropertyString ( wxT ( "context" ));
464 if ( context
. IsEmpty ())
468 StringToItems ( GetDocument ()-> GetTopItem (), context
, contextItems
);
470 for ( wxNode
* node
= contextItems
. GetFirst (); node
; node
= node
-> GetNext () )
472 ctConfigItem
* otherItem
= ( ctConfigItem
*) node
-> GetData ();
473 if ( otherItem
-> IsEnabled ())
479 /// Evaluate the requires properties:
480 /// if any of the 'requires' items are disabled,
481 /// then this one is disabled (and inactive).
482 void ctConfigItem :: EvaluateDependencies ()
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" ));
491 bool enabled
= IsEnabled ();
492 bool oldEnabled
= enabled
;
493 bool oldActive
= IsActive ();
494 bool explicitlyEnabled
= FALSE
;
495 bool explicitlyDisabled
= FALSE
;
496 bool inActiveContext
= IsInActiveContext ();
498 // Add the parent to the list of dependencies, if the
499 // parent is a check or radio group.
500 ctConfigItem
* parent
= GetParent ();
502 ( parent
-> GetType () == ctTypeCheckGroup
||
503 parent
-> GetType () == ctTypeRadioGroup
))
504 items
. Append ( parent
);
507 StringToItems ( GetDocument ()-> GetTopItem (), requires , tempItems
);
510 for ( node
= tempItems
. GetFirst (); node
; node
= node
-> GetNext () )
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
);
523 int enabledCount
= 0 ;
524 for ( node
= items
. GetFirst (); node
; node
= node
-> GetNext () )
526 ctConfigItem
* otherItem
= ( ctConfigItem
*) node
-> GetData ();
528 if ( otherItem
-> IsEnabled ())
533 if ( items
. GetCount () > 0 && enabledCount
== 0 )
535 // None of the items were enabled
538 explicitlyDisabled
= TRUE
;
543 if (! enabledIfNot
. IsEmpty ())
545 StringToItems ( GetDocument ()-> GetTopItem (), enabledIfNot
, items
);
546 int disabledCount
= 0 ;
547 int inContextCount
= 0 ;
549 for ( wxNode
* node
= items
. GetFirst (); node
; node
= node
-> GetNext () )
551 ctConfigItem
* otherItem
= ( ctConfigItem
*) node
-> GetData ();
553 if ( inActiveContext
&& otherItem
-> IsInActiveContext ())
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 ())
565 // Enable if there were no related items that were enabled
566 if ( inContextCount
> 0 && ( disabledCount
== inContextCount
) && ! explicitlyDisabled
)
568 explicitlyEnabled
= TRUE
;
575 if (! enabledIf
. IsEmpty ())
577 StringToItems ( GetDocument ()-> GetTopItem (), enabledIf
, items
);
578 int enabledCount
= 0 ;
579 int inContextCount
= 0 ;
581 for ( wxNode
* node
= items
. GetFirst (); node
; node
= node
-> GetNext () )
583 ctConfigItem
* otherItem
= ( ctConfigItem
*) node
-> GetData ();
585 if ( inActiveContext
&& otherItem
-> IsInActiveContext ())
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 ())
597 // Enable if there were no related items that were disabled
598 if ( inContextCount
> 0 && ( enabledCount
> 0 ) && ! explicitlyDisabled
)
600 explicitlyEnabled
= TRUE
;
607 if (! precludes
. IsEmpty ())
609 StringToItems ( GetDocument ()-> GetTopItem (), precludes
, items
);
610 int enabledCount
= 0 ;
611 int inContextCount
= 0 ;
613 for ( wxNode
* node
= items
. GetFirst (); node
; node
= node
-> GetNext () )
615 ctConfigItem
* otherItem
= ( ctConfigItem
*) node
-> GetData ();
617 if ( inActiveContext
&& otherItem
-> IsInActiveContext ())
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 ())
628 // Disable if there were no related items that were disabled
629 if ( inContextCount
> 0 && ( enabledCount
== inContextCount
) && ! explicitlyEnabled
)
636 // Finally check a sort of dependency: whether our
637 // context is active. If not, make this inactive.
638 if (! IsInActiveContext ())
643 // If going active, set enabled state to the default state
645 oldActive
!= active
&&
646 ( GetType () == ctTypeBoolCheck
|| GetType () == ctTypeCheckGroup
) &&
647 m_properties
. FindProperty ( wxT ( "default-state" )))
649 bool defaultState
= m_properties
. FindProperty ( wxT ( "default-state" ))-> GetVariant (). GetBool ();
650 enabled
= defaultState
;
654 // Deal with setting a radio button
655 if ( enabled
&& enabled
!= oldEnabled
&&
656 ( GetType () == ctTypeBoolRadio
|| GetType () == ctTypeRadioGroup
))
659 PropagateRadioButton ( considered
);
663 /// Get description, which may be dynamically
664 /// generated depending on the property.
665 wxString
ctConfigItem :: GetDescription ( ctProperty
* property
)
667 if ( property
-> GetName () == wxT ( "description" ))
669 wxString
value ( property
-> GetValue ());
671 return wxT ( "Double-click on <B>description</B> to write a brief explanation of the setting.<P>" );
675 else if ( property
-> GetName () == wxT ( "notes" ))
677 wxString
value ( property
-> GetValue ());
679 return wxT ( "Double-click on <B>notes</B> to write notes about this setting.<P>" );
683 return property
-> GetDescription ();
686 /// Get the title for the property editor
687 wxString
ctConfigItem :: GetTitle ()
689 wxString
title ( GetName ());
690 if ( GetType () == ctTypeCheckGroup
||
691 GetType () == ctTypeRadioGroup
||
692 GetType () == ctTypeBoolCheck
||
693 GetType () == ctTypeBoolRadio
)
696 title
= title
+ _T ( " - enabled" );
698 title
= title
+ _T ( " - disabled" );
703 /// Propagate a change in enabled/disabled status
704 void ctConfigItem :: PropagateChange ( wxList
& considered
)
706 if ( GetType () == ctTypeCheckGroup
||
707 GetType () == ctTypeRadioGroup
||
708 GetType () == ctTypeBoolCheck
||
709 GetType () == ctTypeBoolRadio
)
711 // TODO: what about string, integer? Can they have
714 for ( wxNode
* node
= GetDependents (). GetFirst (); node
; node
= node
-> GetNext () )
716 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
719 if (! considered
. Member ( child
))
721 considered
. Append ( child
);
723 child
-> EvaluateDependencies ();
726 child
-> PropagateChange ( considered
);
732 /// Process radio button selection
733 void ctConfigItem :: PropagateRadioButton ( wxList
& considered
)
735 if (( GetType () == ctTypeBoolRadio
|| GetType () == ctTypeRadioGroup
) && IsEnabled ())
737 wxString
mutuallyExclusive ( GetPropertyString ( wxT ( "exclusivity" )));
740 StringToItems ( GetDocument ()-> GetTopItem (), mutuallyExclusive
, list
);
742 for ( wxNode
* node
= list
. GetFirst (); node
; node
= node
-> GetNext () )
744 ctConfigItem
* child
= ( ctConfigItem
*) node
-> GetData ();
745 if ( child
-> IsEnabled () && child
!= this )
747 child
-> Enable ( FALSE
);
750 if (! considered
. Member ( child
))
751 child
-> PropagateChange ( considered
);