1 /////////////////////////////////////////////////////////////////////////////
2 // Name: configtooldoc.h
3 // Purpose: Document class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "configtooldoc.h"
22 #include "wx/config.h"
23 #include "wx/textfile.h"
24 #include "wx/process.h"
25 #include "wx/mimetype.h"
26 #include "wx/process.h"
27 #include "wx/wfstream.h"
33 #include "configtooldoc.h"
34 #include "configtoolview.h"
35 #include "configtree.h"
36 #include "mainframe.h"
38 #include "wxconfigtool.h"
39 #include "htmlparser.h"
41 IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc
, wxDocument
)
44 ctConfigToolDoc::ctConfigToolDoc()
47 m_clipboardItem
= NULL
;
51 ctConfigToolDoc::~ctConfigToolDoc()
55 if (GetCommandProcessor())
56 GetCommandProcessor()->SetEditMenu(NULL
);
59 // Delete all the items not already deleted
60 void ctConfigToolDoc::DeleteItems()
67 /// Clears the clipboard item.
68 void ctConfigToolDoc::ClearClipboard()
71 delete m_clipboardItem
;
72 m_clipboardItem
= NULL
;
75 /// Sets the clipboard item.
76 void ctConfigToolDoc::SetClipboardItem(ctConfigItem
* item
)
79 delete m_clipboardItem
;
80 m_clipboardItem
= item
;
84 // Closes and clears the document
85 bool ctConfigToolDoc::OnCloseDocument()
87 if (wxDocument::OnCloseDocument())
89 ctConfigToolHint
hint(NULL
, ctClear
);
90 UpdateAllViews (NULL
, & hint
);
102 bool ctConfigToolDoc::Save()
104 if (!IsModified() && m_savedYet
) return TRUE
;
106 bool ret
= (m_documentFile
== wxT("") || !m_savedYet
) ?
108 OnSaveDocument(m_documentFile
);
110 SetDocumentSaved(TRUE
);
114 // Create the document
115 bool ctConfigToolDoc::OnCreate(const wxString
& path
, long flags
)
117 GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
118 GetCommandProcessor()->Initialize();
119 GetCommandProcessor()->ClearCommands();
121 // wxGetApp().m_currentDoc = this;
123 if (flags
& wxDOC_NEW
)
125 ctConfigItem
* rootItem
= new ctConfigItem(NULL
, ctTypeGroup
, _T("Configuration"));
126 //rootItem->InitProperties();
127 rootItem
->GetProperties().AddProperty(
129 wxT("The item description."),
130 wxVariant(wxT(""), wxT("description")),
133 rootItem
->SetPropertyString(_T("description"),
134 _T("<B>This is the top-level configuration item.</B>"));
137 SetTopItem(rootItem
);
140 SetDocumentSaved(FALSE
);
142 wxString
rootName(wxT("untitled"));
143 wxStripExtension(rootName
);
144 SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName
));
147 // Creates the view, so do any view updating after this
148 bool success
= wxDocument::OnCreate(path
, flags
);
152 if (flags
& wxDOC_NEW
)
156 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
157 UpdateAllViews (NULL
, & hint
);
159 SetFilename(GetFilename(), TRUE
);
166 bool ctConfigToolDoc::OnSaveDocument(const wxString
& filename
)
170 const wxString
strOldPath(GetFilename());
172 // Do some backing up first
174 // This is the backup filename
175 wxString
backupFilename(filename
);
176 backupFilename
+= wxT(".bak");
178 // This is the temporary copy of the backup
179 wxString
tempFilename(filename
);
180 tempFilename
+= wxT(".tmp");
181 if (wxFileExists(tempFilename
))
182 wxRemoveFile(tempFilename
);
184 bool leaveBackup
= TRUE
;
186 bool saved
= DoSave(tempFilename
);
190 // Remove the old .bak file
191 if (wxFileExists(backupFilename
))
193 wxRemoveFile(backupFilename
);
196 // Copy the old file to the .bak
200 if (wxFileExists(filename
))
202 if (!wxRenameFile(filename
, backupFilename
))
204 wxCopyFile(filename
, backupFilename
);
205 wxRemoveFile(filename
);
211 if (wxFileExists(filename
))
212 wxRemoveFile(filename
);
215 // Finally, copy the temporary file to the proper filename
216 if (!wxRenameFile(tempFilename
, filename
))
218 wxCopyFile(tempFilename
, filename
);
219 wxRemoveFile(tempFilename
);
223 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
224 SetDocumentSaved(TRUE
);
225 SetFilename(filename
);
226 wxGetApp().GetSettings().m_lastFilename
= filename
;
229 SetFilename(strOldPath
);
231 wxGetApp().GetMainFrame()->UpdateFrameTitle();
236 bool ctConfigToolDoc::OnOpenDocument(const wxString
& filename
)
240 bool opened
= DoOpen(filename
);
244 SetFilename(filename
);
245 wxGetApp().GetSettings().m_lastFilename
= filename
;
247 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
249 RefreshDependencies();
251 // ctConfigToolHint hint(NULL, ctFilenameChanged);
252 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
253 UpdateAllViews (NULL
, & hint
);
256 SetDocumentSaved(TRUE
); // Necessary or it will pop up the Save As dialog
261 /// Save the settings file
262 bool ctConfigToolDoc::DoSave(const wxString
& filename
)
264 wxFileOutputStream
stream(filename
);
268 stream
<< wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
269 stream
<< wxT("<settings xmlns=\"http://www.wxwindows.org/wxs\" version=\"2.5.0.1\">");
271 DoSave(m_topItem
, stream
, 1);
273 stream
<< wxT("\n</settings>\n");
278 inline static void OutputIndentation(wxOutputStream
& stream
, int indent
)
280 wxString str
= wxT("\n");
281 for (int i
= 0; i
< indent
; i
++)
282 str
<< wxT(' ') << wxT(' ');
286 /// Recursive helper function for file saving
287 bool ctConfigToolDoc::DoSave(ctConfigItem
* item
, wxOutputStream
& stream
, int indent
)
289 OutputIndentation(stream
, indent
*2);
291 wxString
name(item
->GetName());
294 if (item
->GetType() == ctTypeGroup
)
295 typeStr
= wxT("group");
296 else if (item
->GetType() == ctTypeCheckGroup
)
297 typeStr
= wxT("check-group");
298 else if (item
->GetType() == ctTypeRadioGroup
)
299 typeStr
= wxT("radio-group");
300 else if (item
->GetType() == ctTypeString
)
301 typeStr
= wxT("string");
302 else if (item
->GetType() == ctTypeBoolCheck
)
303 typeStr
= wxT("bool-check");
304 else if (item
->GetType() == ctTypeBoolRadio
)
305 typeStr
= wxT("bool-radio");
306 else if (item
->GetType() == ctTypeInteger
)
307 typeStr
= wxT("integer");
309 typeStr
= wxT("unknown");
311 stream
<< wxT("<setting type=\"") << typeStr
<< wxT("\">");
315 OutputIndentation(stream
, indent
*2);
316 if (item
->IsActive())
317 stream
<< wxT("<active>1</active>");
319 stream
<< wxT("<active>0</active>");
320 OutputIndentation(stream
, indent
*2);
321 if (item
->IsEnabled())
322 stream
<< wxT("<enabled>1</enabled>");
324 stream
<< wxT("<enabled>0</enabled>");
327 wxNode
* node
= item
->GetProperties().GetList().GetFirst();
330 ctProperty
* prop
= (ctProperty
*) node
->GetData();
331 OutputIndentation(stream
, indent
*2);
332 stream
<< wxT("<") << prop
->GetName() ;
334 if (prop
->IsCustom())
336 stream
<< wxT(" custom=\"true\"");
337 stream
<< wxT(" type=\"") << prop
->GetVariant().GetType() << wxT("\"");
338 stream
<< wxT(" editor-type=\"") << prop
->GetEditorType() << wxT("\"");
339 stream
<< wxT(" description=\"") << prop
->GetDescription() << wxT("\"");
340 if (prop
->GetChoices().GetCount() > 0)
343 ctConfigItem::ArrayToString(prop
->GetChoices(), choices
);
344 stream
<< wxT(" choices=\"") << choices
<< wxT("\"");
350 stream
<< ctEscapeHTMLCharacters(prop
->GetVariant().GetString()) ;
351 stream
<< wxT("</") << prop
->GetName() << wxT(">");
353 node
= node
->GetNext();
357 node
= item
->GetChildren().GetFirst();
360 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
361 DoSave(child
, stream
, indent
);
363 node
= node
->GetNext();
368 OutputIndentation(stream
, indent
*2);
369 stream
<< wxT("</setting>");
374 /// Open the settings file
375 bool ctConfigToolDoc::DoOpen(const wxString
& filename
)
377 wxSimpleHtmlParser parser
;
378 if (parser
.ParseFile(filename
))
380 ctConfigToolHint
hint(NULL
, ctClear
);
381 UpdateAllViews (NULL
, & hint
);
384 if (parser
.GetTopLevelTag()->GetChildren())
386 wxSimpleHtmlTag
* settingsTag
= parser
.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
387 if (settingsTag
&& settingsTag
->GetChildren())
389 wxSimpleHtmlTag
* firstSettingTag
= settingsTag
->GetChildren();
391 DoOpen(firstSettingTag
, NULL
);
400 static bool GetHtmlBoolValue(const wxString
& value
)
402 if (value
== wxT("true") || value
== wxT("TRUE") || value
== wxT("1"))
408 static int GetHtmlIntegerValue(const wxString
& value
)
410 return wxAtoi(value
);
413 static double GetHtmlDoubleValue(const wxString
& value
)
415 return wxAtof(value
);
418 bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag
* tag
, ctConfigItem
* parent
)
420 ctConfigItem
* newItem
= NULL
;
421 if (tag
->NameIs(wxT("setting")))
423 wxSimpleHtmlAttribute
* attr
= tag
->FindAttribute(wxT("type"));
426 ctConfigType type
= ctTypeUnknown
;
427 wxString
typeStr(attr
->GetValue());
428 if (typeStr
== wxT("group"))
430 else if (typeStr
== wxT("option-group") || typeStr
== wxT("check-group"))
431 type
= ctTypeCheckGroup
;
432 else if (typeStr
== wxT("radio-group"))
433 type
= ctTypeRadioGroup
;
434 else if (typeStr
== wxT("bool-check"))
435 type
= ctTypeBoolCheck
;
436 else if (typeStr
== wxT("bool-radio"))
437 type
= ctTypeBoolRadio
;
438 else if (typeStr
== wxT("string"))
440 else if (typeStr
== wxT("integer"))
441 type
= ctTypeInteger
;
444 wxLogError(wxT("Unknown type %s"), (const wxChar
*) typeStr
);
446 if (type
!= ctTypeUnknown
)
448 newItem
= new ctConfigItem(parent
, type
, wxT(""));
449 newItem
->InitProperties();
455 wxSimpleHtmlTag
* childTag
= tag
->GetChildren();
459 if (childTag
->GetType() == wxSimpleHtmlTag_Open
)
461 if (childTag
->GetName() == wxT("setting"))
463 DoOpen(childTag
, newItem
);
465 else if (childTag
->GetName() == wxT("name"))
469 wxString
name(childTag
->GetNext()->GetTagText());
470 newItem
->SetName(name
);
473 else if (childTag
->GetName() == wxT("active"))
476 newItem
->SetActive(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
478 else if (childTag
->GetName() == wxT("enabled"))
481 newItem
->Enable(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
487 ctProperty
* prop
= newItem
->GetProperties().FindProperty(childTag
->GetName());
490 // A custom property, else an obsolete
491 // property that we should ignore.
493 if (childTag
->GetAttributeValue(isCustom
, wxT("custom")) &&
494 isCustom
== wxT("true"))
496 prop
= new ctProperty
;
498 wxString
name(childTag
->GetName());
499 wxString
type(wxT("string"));
501 wxString
editorType(wxT("string"));
502 wxString
description(wxT(""));
503 childTag
->GetAttributeValue(type
, wxT("type"));
504 childTag
->GetAttributeValue(type
, wxT("editor-type"));
505 childTag
->GetAttributeValue(type
, wxT("choices"));
506 childTag
->GetAttributeValue(description
, wxT("description"));
508 if (type
== wxT("bool"))
509 prop
->GetVariant() = wxVariant((bool) FALSE
, name
);
510 else if (type
== wxT("double"))
511 prop
->GetVariant() = wxVariant((double) 0.0, name
);
512 else if (type
== wxT("long"))
513 prop
->GetVariant() = wxVariant((long) 0, name
);
515 prop
->GetVariant() = wxVariant(wxT(""), name
);
516 prop
->SetDescription(description
);
517 prop
->SetCustom(TRUE
);
518 prop
->SetEditorType(editorType
);
519 if (!choices
.IsEmpty())
522 ctConfigItem::StringToArray(choices
, arr
);
523 prop
->SetChoices(arr
);
525 newItem
->GetProperties().AddProperty(prop
);
530 if (prop
->GetVariant().GetType() == wxT("string"))
531 prop
->GetVariant() = childTag
->GetNext()->GetTagText();
532 else if (prop
->GetVariant().GetType() == wxT("long"))
533 prop
->GetVariant() = (long) GetHtmlIntegerValue(childTag
->GetNext()->GetTagText());
534 else if (prop
->GetVariant().GetType() == wxT("bool"))
535 prop
->GetVariant() = (bool) GetHtmlBoolValue(childTag
->GetNext()->GetTagText());
536 else if (prop
->GetVariant().GetType() == wxT("double"))
537 prop
->GetVariant() = (double) GetHtmlDoubleValue(childTag
->GetNext()->GetTagText());
542 childTag
= childTag
->GetNext();
547 /// Clear dependencies
548 void ctConfigToolDoc::ClearDependencies(ctConfigItem
* item
)
553 item
->GetDependents().Clear();
554 for ( wxNode
* node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
556 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
557 ClearDependencies(child
);
561 /// Refresh dependencies
562 void ctConfigToolDoc::RefreshDependencies()
564 ClearDependencies(GetTopItem());
565 RefreshDependencies(GetTopItem());
568 /// Refresh dependencies
569 void ctConfigToolDoc::RefreshDependencies(ctConfigItem
* item
)
571 wxArrayString requiresArr
;
572 wxString
requires = item
->GetPropertyString(wxT("requires"));
573 wxString precludes
= item
->GetPropertyString(wxT("precludes"));
574 wxString enabledIf
= item
->GetPropertyString(wxT("enabled-if"));
575 wxString enabledIfNot
= item
->GetPropertyString(wxT("enabled-if-not"));
576 wxString indeterminateIf
= item
->GetPropertyString(wxT("indeterminate-if"));
577 wxString context
= item
->GetPropertyString(wxT("context"));
579 if (!requires.IsEmpty())
580 item
->StringToArray(requires, requiresArr
);
582 if (!precludes
.IsEmpty())
583 item
->StringToArray(precludes
, requiresArr
);
585 if (!enabledIfNot
.IsEmpty())
586 item
->StringToArray(enabledIfNot
, requiresArr
);
588 if (!enabledIf
.IsEmpty())
589 item
->StringToArray(enabledIf
, requiresArr
);
591 if (!indeterminateIf
.IsEmpty())
592 item
->StringToArray(indeterminateIf
, requiresArr
);
594 // Add the parent to the list of dependencies, if the
595 // parent is a check or radio group.
596 ctConfigItem
* parent
= item
->GetParent();
598 (parent
->GetType() == ctTypeCheckGroup
||
599 parent
->GetType() == ctTypeRadioGroup
))
600 requiresArr
.Add(parent
->GetName());
602 // Also look in 'context' since these items
603 // are another kind of dependency (switching to
604 // a different platform may cause the dependencies
605 // to be evaluated differently).
606 if (!context
.IsEmpty())
607 item
->StringToArray(context
, requiresArr
);
610 for (i
= 0; i
< requiresArr
.GetCount(); i
++)
612 wxString
itemName(requiresArr
[i
]);
613 ctConfigItem
* otherItem
= GetTopItem()->FindItem(itemName
);
614 if (otherItem
&& !otherItem
->GetDependents().Member(item
))
616 otherItem
->GetDependents().Append(item
);
619 for ( wxNode
* node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
621 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
622 RefreshDependencies(child
);
626 /// Generate the text of a setup.h
627 wxString
ctConfigToolDoc::GenerateSetup()
630 str
<< wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
632 GenerateSetup(GetTopItem(), str
);
638 void ctConfigToolDoc::GenerateSetup(ctConfigItem
* item
, wxString
& str
)
640 // Generate the setup.h entries for this item
641 wxString name
= item
->GetName();
643 // We don't process the platform choice
644 if (item
->GetName() == wxT("Target"))
647 if (item
->IsInActiveContext() &&
648 (item
->GetType() == ctTypeCheckGroup
||
649 item
->GetType() == ctTypeRadioGroup
||
650 item
->GetType() == ctTypeBoolCheck
||
651 item
->GetType() == ctTypeBoolRadio
))
653 // TODO: write description
654 wxString name
= item
->GetName();
655 if (name
.Left(6) == wxT("wxUSE_") ||
656 name
== wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
657 name
.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND
)
659 str
<< wxT("#define ") << name
;
660 if (item
->IsEnabled())
668 for ( wxNode
* node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
670 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
671 GenerateSetup(child
, str
);
676 /// Generate a configure command
677 wxString
ctConfigToolDoc::GenerateConfigureCommand()
680 str
<< wxT("# configurewx\n# Generated by wxConfigTool\n\n");
682 wxString path
= GetFrameworkDir(TRUE
);
683 bool makeUnix
= TRUE
;
689 path
+= wxFILE_SEP_PATH
;
692 str
<< path
<< wxT("configure");
694 // Find the target to use
695 ctConfigItem
* platformsFolder
= GetTopItem()->FindItem(wxT("Target"));
698 for ( wxNode
* node
= platformsFolder
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
700 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
701 if (child
->GetType() == ctTypeBoolRadio
&& child
->IsEnabled())
703 wxString configureCommand
= child
->GetPropertyString(wxT("configure-command"));
704 if (!configureCommand
.IsEmpty())
705 str
<< wxT(" ") << configureCommand
;
710 GenerateConfigureCommand(GetTopItem(), str
);
715 void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem
* item
, wxString
& str
)
717 // We don't process the platform group, since we've
719 if (item
->GetName() == wxT("Target"))
722 if (item
->IsInActiveContext() &&
723 (item
->GetType() == ctTypeCheckGroup
||
724 item
->GetType() == ctTypeRadioGroup
||
725 item
->GetType() == ctTypeBoolCheck
||
726 item
->GetType() == ctTypeBoolRadio
))
728 wxString name
= item
->GetName();
729 wxString configureCommand
= item
->GetPropertyString(wxT("configure-command"));
730 if (!configureCommand
.IsEmpty())
732 if (!item
->IsEnabled())
734 // Replace 'enable' with 'disable' if this
736 configureCommand
.Replace(wxT("--enable-"), wxT("--disable-"));
737 configureCommand
.Replace(wxT("--with-"), wxT("--without-"));
739 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("builtin"));
740 if (prop
&& prop
->GetVariant().GetType() == wxT("bool"))
742 bool builtin
= prop
->GetVariant().GetBool();
743 str
<< wxT(" ") << configureCommand
;
745 str
<< wxT("=builtin");
751 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("value"));
752 if (prop
&& prop
->GetVariant().GetType() == wxT("string"))
754 wxString val
= prop
->GetVariant().GetString();
755 if (item
->IsEnabled() && !val
.IsEmpty())
757 str
<< wxT(" ") << configureCommand
;
758 str
<< wxT("=\"") << val
<< wxT("\"");
760 // If the string is empty, ignore this parameter,
761 // since it's obviously intended to be supplied
762 // only if there's a string to use and it's enabled.
766 str
<< wxT(" ") << configureCommand
;
772 for ( wxNode
* node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
774 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
775 GenerateConfigureCommand(child
, str
);
779 /// Gets the current framework directory
780 wxString
ctConfigToolDoc::GetFrameworkDir(bool makeUnix
)
782 wxString path
= wxGetApp().GetSettings().m_frameworkDir
;
783 if (wxGetApp().GetSettings().m_useEnvironmentVariable
)
785 // Should probably allow other variables
786 // to be used, and maybe expand variables within m_frameworkDir
787 path
= wxGetenv(wxT("WXWIN"));
790 path
.Replace(wxT("\\"), wxT("/"));
796 /// Finds the next item in the tree
797 ctConfigItem
* ctConfigToolDoc::FindNextItem(ctConfigItem
* item
, bool wrap
)
802 // First, try to find the first child
803 if (item
->GetChildCount() > 0)
805 return item
->GetChild(0);
809 ctConfigItem
* p
= item
;
812 ctConfigItem
* toFind
= FindNextSibling(p
);
819 // Finally, wrap around to the root.
826 /// Finds the next sibling in the tree
827 ctConfigItem
* ctConfigToolDoc::FindNextSibling(ctConfigItem
* item
)
829 if (item
->GetParent())
831 wxNode
* node
= item
->GetParent()->GetChildren().Member(item
);
832 if (node
&& node
->GetNext())
834 ctConfigItem
* nextItem
= (ctConfigItem
*) node
->GetNext()->GetData();
843 * Implements a document editing command.
846 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
847 ctConfigItem
* activeState
, ctConfigItem
* savedState
,
848 ctConfigItem
* parent
, ctConfigItem
* insertBefore
,
849 bool ignoreFirstTime
): wxCommand(TRUE
, name
)
851 m_activeState
= activeState
;
852 m_savedState
= savedState
;
853 m_ignoreThis
= ignoreFirstTime
;
857 m_insertBefore
= insertBefore
;
860 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
861 ctConfigItem
* activeState
, ctProperties
* properties
,
862 bool ignoreFirstTime
): wxCommand(TRUE
, name
)
864 m_activeState
= activeState
;
866 m_properties
= properties
;
867 m_ignoreThis
= ignoreFirstTime
;
869 m_properties
= properties
;
871 m_insertBefore
= NULL
;
874 ctConfigCommand::~ctConfigCommand()
882 bool ctConfigCommand::Do()
884 return DoAndUndo(TRUE
);
887 bool ctConfigCommand::Undo()
889 return DoAndUndo(FALSE
);
892 // Combine Do and Undo into one
893 bool ctConfigCommand::DoAndUndo(bool doCmd
)
901 wxASSERT(m_savedState
== NULL
);
902 wxASSERT(m_activeState
!= NULL
);
904 ctConfigItem
* newItem
= m_activeState
->DeepClone();
905 ctConfigToolDoc
* doc
= m_activeState
->GetDocument();
907 // This will delete the old clipboard contents, if any.
908 doc
->SetClipboardItem(newItem
);
910 m_parent
= m_activeState
->GetParent();
911 m_insertBefore
= m_activeState
->FindNextSibling();
913 m_activeState
->Detach();
914 m_savedState
= m_activeState
;
915 m_activeState
= NULL
;
917 m_savedState
->GetDocument()->Modify(TRUE
);
918 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
919 view
->OnChangeFilename();
923 wxASSERT(m_savedState
!= NULL
);
924 wxASSERT(m_activeState
== NULL
);
926 m_savedState
->GetDocument()->Modify(TRUE
);
927 m_savedState
->Attach(m_parent
, m_insertBefore
);
928 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
929 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
930 m_activeState
= m_savedState
;
933 m_insertBefore
= NULL
;
934 view
->OnChangeFilename();
942 wxASSERT(m_savedState
!= NULL
);
943 wxASSERT(m_activeState
== NULL
);
945 m_savedState
->GetDocument()->Modify(TRUE
);
946 m_savedState
->Attach(m_parent
, m_insertBefore
);
947 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
948 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
949 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
950 m_activeState
= m_savedState
;
952 view
->OnChangeFilename();
956 wxASSERT(m_savedState
== NULL
);
957 wxASSERT(m_activeState
!= NULL
);
959 m_activeState
->GetDocument()->Modify(TRUE
);
960 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
961 m_activeState
->Detach();
962 m_savedState
= m_activeState
;
963 m_activeState
= NULL
;
964 view
->OnChangeFilename();
968 case ctCMD_NEW_ELEMENT
:
972 wxASSERT(m_savedState
!= NULL
);
973 wxASSERT(m_activeState
== NULL
);
975 m_savedState
->GetDocument()->Modify(TRUE
);
976 m_savedState
->Attach(m_parent
, m_insertBefore
);
977 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
978 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
979 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
981 m_activeState
= m_savedState
;
986 wxASSERT(m_savedState
== NULL
);
987 wxASSERT(m_activeState
!= NULL
);
989 m_activeState
->GetDocument()->Modify(TRUE
);
990 m_activeState
->Detach();
991 m_savedState
= m_activeState
;
992 m_activeState
= NULL
;
996 case ctCMD_APPLY_PROPERTY
:
998 wxASSERT(m_properties
!= NULL
);
999 wxASSERT(m_activeState
!= NULL
);
1001 // Don't update the properties editor first time
1002 // around since it will be done one property at a time
1003 // initially (and no property editor update required)
1006 // Just swap the saved and current properties.
1007 ctProperties propsTemp
= m_activeState
->GetProperties() ;
1008 m_activeState
->GetProperties() = (* m_properties
);
1009 (* m_properties
) = propsTemp
;
1011 // Apply only those that need applying
1012 // (those properties in activeState that are not in propsTemp)
1013 wxNode
* node
= m_activeState
->GetProperties().GetList().GetFirst();
1016 ctProperty
* prop
= (ctProperty
*) node
->GetData();
1017 ctProperty
* otherProp
= propsTemp
.FindProperty(prop
->GetName());
1018 if (otherProp
&& ((*prop
) != (*otherProp
)))
1020 m_activeState
->ApplyProperty(prop
, otherProp
->GetVariant());
1022 node
= node
->GetNext();
1024 m_activeState
->GetDocument()->Modify(TRUE
);
1025 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
1028 ctConfigToolHint
hint(NULL
, ctValueChanged
);
1029 m_activeState
->GetDocument()->UpdateAllViews (NULL
, & hint
);
1032 m_ignoreThis
= FALSE
;
1040 IMPLEMENT_CLASS(ctConfiguration
, wxObject
)
1042 ctConfiguration::ctConfiguration()
1044 m_treeItemId
= wxTreeItemId();
1049 ctConfiguration::ctConfiguration(ctConfiguration
* parent
, const wxString
& name
)
1051 m_treeItemId
= wxTreeItemId();
1055 parent
->AddChild(this);
1058 ctConfiguration::~ctConfiguration()
1061 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
1062 if (m_treeItemId.IsOk() && treeCtrl)
1064 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
1066 data->SetConfigItem(NULL);
1069 GetParent()->RemoveChild(this);
1072 if (wxGetApp().GetMainFrame()->GetDocument() &&
1073 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
1074 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
1081 /// Assignment operator.
1082 void ctConfiguration::operator= (const ctConfiguration
& configuration
)
1084 m_name
= configuration
.m_name
;
1085 m_description
= configuration
.m_description
;
1089 void ctConfiguration::Clear()
1091 wxNode
* node
= m_children
.GetFirst();
1094 wxNode
* next
= node
->GetNext();
1095 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1097 // This should delete 'node' too, assuming
1098 // child's m_parent points to 'this'. If not,
1099 // it'll be cleaned up by m_children.Clear().
1107 // Get the nth child
1108 ctConfiguration
* ctConfiguration::GetChild(int n
) const
1110 wxASSERT ( n
< GetChildCount() && n
> -1 );
1112 if ( n
< GetChildCount() && n
> -1 )
1114 ctConfiguration
* child
= wxDynamicCast(m_children
.Item(n
)->GetData(), ctConfiguration
);
1121 // Get the child count
1122 int ctConfiguration::GetChildCount() const
1124 return m_children
.GetCount();
1128 void ctConfiguration::AddChild(ctConfiguration
* configuration
)
1130 m_children
.Append(configuration
);
1131 configuration
->SetParent(this);
1134 /// Remove (but don't delete) a child
1135 void ctConfiguration::RemoveChild(ctConfiguration
* configuration
)
1137 m_children
.DeleteObject(configuration
);
1138 configuration
->SetParent(NULL
);
1141 /// Get the associated document (currently, assumes
1142 /// there's only ever one document active)
1143 ctConfigToolDoc
* ctConfiguration::GetDocument()
1145 ctConfigToolDoc
* doc
= wxGetApp().GetMainFrame()->GetDocument();
1149 /// Find an item in this hierarchy
1150 // TODO: ensure that names are unique, somehow.
1151 ctConfiguration
* ctConfiguration::FindConfiguration(const wxString
& name
)
1153 if (GetName() == name
)
1156 for ( wxNode
* node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1158 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1159 ctConfiguration
* found
= child
->FindConfiguration(name
);
1166 /// Find the next sibling
1167 ctConfiguration
* ctConfiguration::FindNextSibling()
1171 wxNode
* node
= GetParent()->GetChildren().Member(this);
1172 if (node
&& node
->GetNext())
1174 return (ctConfiguration
*) node
->GetNext()->GetData();
1179 /// Find the previous sibling
1180 ctConfiguration
* ctConfiguration::FindPreviousSibling()
1184 wxNode
* node
= GetParent()->GetChildren().Member(this);
1185 if (node
&& node
->GetPrevious())
1187 return (ctConfiguration
*) node
->GetPrevious()->GetData();
1192 /// Create a clone of this and children
1193 ctConfiguration
* ctConfiguration::DeepClone()
1195 ctConfiguration
* newItem
= Clone();
1197 for ( wxNode
* node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1199 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1200 ctConfiguration
* newChild
= child
->DeepClone();
1201 newItem
->AddChild(newChild
);
1206 /// Detach: remove from parent, and remove tree items
1207 void ctConfiguration::Detach()
1211 GetParent()->RemoveChild(this);
1213 GetDocument()->SetTopItem(NULL
);
1217 wxTreeItemId treeItem = GetTreeItemId();
1221 // Will delete the branch, but not the config items.
1222 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
1226 /// Hide from tree: make sure tree deletions won't delete
1227 /// the config items
1228 void ctConfiguration::DetachFromTree()
1231 wxTreeItemId item = GetTreeItemId();
1234 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
1235 data->SetConfigItem(NULL);
1236 m_treeItemId = wxTreeItemId();
1238 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
1240 ctConfiguration* child = (ctConfiguration*) node->GetData();
1241 child->DetachFromTree();