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"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/process.h"
26 #include "wx/mimetype.h"
27 #include "wx/process.h"
31 #include "wx/textfile.h"
32 #include "wx/wfstream.h"
33 #include "wx/config.h"
34 #include "configtooldoc.h"
35 #include "configtoolview.h"
36 #include "configtree.h"
37 #include "mainframe.h"
39 #include "wxconfigtool.h"
40 #include "htmlparser.h"
42 IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc
, wxDocument
)
45 ctConfigToolDoc::ctConfigToolDoc()
48 m_clipboardItem
= NULL
;
52 ctConfigToolDoc::~ctConfigToolDoc()
56 if (GetCommandProcessor())
57 GetCommandProcessor()->SetEditMenu(NULL
);
60 // Delete all the items not already deleted
61 void ctConfigToolDoc::DeleteItems()
68 /// Clears the clipboard item.
69 void ctConfigToolDoc::ClearClipboard()
72 delete m_clipboardItem
;
73 m_clipboardItem
= NULL
;
76 /// Sets the clipboard item.
77 void ctConfigToolDoc::SetClipboardItem(ctConfigItem
* item
)
80 delete m_clipboardItem
;
81 m_clipboardItem
= item
;
85 // Closes and clears the document
86 bool ctConfigToolDoc::OnCloseDocument()
88 if (wxDocument::OnCloseDocument())
90 ctConfigToolHint
hint(NULL
, ctClear
);
91 UpdateAllViews (NULL
, & hint
);
103 bool ctConfigToolDoc::Save()
105 if (!IsModified() && m_savedYet
) return true;
107 bool ret
= (m_documentFile
== wxT("") || !m_savedYet
) ?
109 OnSaveDocument(m_documentFile
);
111 SetDocumentSaved(true);
115 // Create the document
116 bool ctConfigToolDoc::OnCreate(const wxString
& path
, long flags
)
118 GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
119 GetCommandProcessor()->Initialize();
120 GetCommandProcessor()->ClearCommands();
122 // wxGetApp().m_currentDoc = this;
124 if (flags
& wxDOC_NEW
)
126 ctConfigItem
* rootItem
= new ctConfigItem(NULL
, ctTypeGroup
, _T("Configuration"));
127 //rootItem->InitProperties();
128 rootItem
->GetProperties().AddProperty(
130 wxT("The item description."),
131 wxVariant(wxT(""), wxT("description")),
134 rootItem
->SetPropertyString(_T("description"),
135 _T("<B>This is the top-level configuration item.</B>"));
138 SetTopItem(rootItem
);
141 SetDocumentSaved(false);
143 wxString
rootName(wxT("untitled"));
144 wxStripExtension(rootName
);
145 SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName
));
148 // Creates the view, so do any view updating after this
149 bool success
= wxDocument::OnCreate(path
, flags
);
153 if (flags
& wxDOC_NEW
)
157 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
158 UpdateAllViews (NULL
, & hint
);
160 SetFilename(GetFilename(), true);
167 bool ctConfigToolDoc::OnSaveDocument(const wxString
& filename
)
171 const wxString
strOldPath(GetFilename());
173 // Do some backing up first
175 // This is the backup filename
176 wxString
backupFilename(filename
);
177 backupFilename
+= wxT(".bak");
179 // This is the temporary copy of the backup
180 wxString
tempFilename(filename
);
181 tempFilename
+= wxT(".tmp");
182 if (wxFileExists(tempFilename
))
183 wxRemoveFile(tempFilename
);
185 bool leaveBackup
= true;
187 bool saved
= DoSave(tempFilename
);
191 // Remove the old .bak file
192 if (wxFileExists(backupFilename
))
194 wxRemoveFile(backupFilename
);
197 // Copy the old file to the .bak
201 if (wxFileExists(filename
))
203 if (!wxRenameFile(filename
, backupFilename
))
205 wxCopyFile(filename
, backupFilename
);
206 wxRemoveFile(filename
);
212 if (wxFileExists(filename
))
213 wxRemoveFile(filename
);
216 // Finally, copy the temporary file to the proper filename
217 if (!wxRenameFile(tempFilename
, filename
))
219 wxCopyFile(tempFilename
, filename
);
220 wxRemoveFile(tempFilename
);
224 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
225 SetDocumentSaved(true);
226 SetFilename(filename
);
227 wxGetApp().GetSettings().m_lastFilename
= filename
;
230 SetFilename(strOldPath
);
232 wxGetApp().GetMainFrame()->UpdateFrameTitle();
237 bool ctConfigToolDoc::OnOpenDocument(const wxString
& filename
)
241 bool opened
= DoOpen(filename
);
245 SetFilename(filename
);
246 wxGetApp().GetSettings().m_lastFilename
= filename
;
248 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
250 RefreshDependencies();
252 // ctConfigToolHint hint(NULL, ctFilenameChanged);
253 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
254 UpdateAllViews (NULL
, & hint
);
257 SetDocumentSaved(true); // Necessary or it will pop up the Save As dialog
262 /// Save the settings file
263 bool ctConfigToolDoc::DoSave(const wxString
& filename
)
265 wxFileOutputStream
stream(filename
);
269 stream
<< wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
270 stream
<< wxT("<settings xmlns=\"http://www.wxwidgets.org/wxs\" version=\"2.5.0.1\">");
272 DoSave(m_topItem
, stream
, 1);
274 stream
<< wxT("\n</settings>\n");
279 inline static void OutputIndentation(wxOutputStream
& stream
, int indent
)
281 wxString str
= wxT("\n");
282 for (int i
= 0; i
< indent
; i
++)
283 str
<< wxT(' ') << wxT(' ');
287 /// Recursive helper function for file saving
288 bool ctConfigToolDoc::DoSave(ctConfigItem
* item
, wxOutputStream
& stream
, int indent
)
290 OutputIndentation(stream
, indent
*2);
292 wxString
name(item
->GetName());
295 if (item
->GetType() == ctTypeGroup
)
296 typeStr
= wxT("group");
297 else if (item
->GetType() == ctTypeCheckGroup
)
298 typeStr
= wxT("check-group");
299 else if (item
->GetType() == ctTypeRadioGroup
)
300 typeStr
= wxT("radio-group");
301 else if (item
->GetType() == ctTypeString
)
302 typeStr
= wxT("string");
303 else if (item
->GetType() == ctTypeBoolCheck
)
304 typeStr
= wxT("bool-check");
305 else if (item
->GetType() == ctTypeBoolRadio
)
306 typeStr
= wxT("bool-radio");
307 else if (item
->GetType() == ctTypeInteger
)
308 typeStr
= wxT("integer");
310 typeStr
= wxT("unknown");
312 stream
<< wxT("<setting type=\"") << typeStr
<< wxT("\">");
316 OutputIndentation(stream
, indent
*2);
317 if (item
->IsActive())
318 stream
<< wxT("<active>1</active>");
320 stream
<< wxT("<active>0</active>");
321 OutputIndentation(stream
, indent
*2);
322 if (item
->IsEnabled())
323 stream
<< wxT("<enabled>1</enabled>");
325 stream
<< wxT("<enabled>0</enabled>");
328 wxObjectList::compatibility_iterator node
= item
->GetProperties().GetList().GetFirst();
331 ctProperty
* prop
= (ctProperty
*) node
->GetData();
332 OutputIndentation(stream
, indent
*2);
333 stream
<< wxT("<") << prop
->GetName() ;
335 if (prop
->IsCustom())
337 stream
<< wxT(" custom=\"true\"");
338 stream
<< wxT(" type=\"") << prop
->GetVariant().GetType() << wxT("\"");
339 stream
<< wxT(" editor-type=\"") << prop
->GetEditorType() << wxT("\"");
340 stream
<< wxT(" description=\"") << prop
->GetDescription() << wxT("\"");
341 if (prop
->GetChoices().GetCount() > 0)
344 ctConfigItem::ArrayToString(prop
->GetChoices(), choices
);
345 stream
<< wxT(" choices=\"") << choices
<< wxT("\"");
351 stream
<< ctEscapeHTMLCharacters(prop
->GetVariant().GetString()) ;
352 stream
<< wxT("</") << prop
->GetName() << wxT(">");
354 node
= node
->GetNext();
358 node
= item
->GetChildren().GetFirst();
361 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
362 DoSave(child
, stream
, indent
);
364 node
= node
->GetNext();
369 OutputIndentation(stream
, indent
*2);
370 stream
<< wxT("</setting>");
375 /// Open the settings file
376 bool ctConfigToolDoc::DoOpen(const wxString
& filename
)
378 wxSimpleHtmlParser parser
;
379 if (parser
.ParseFile(filename
))
381 ctConfigToolHint
hint(NULL
, ctClear
);
382 UpdateAllViews (NULL
, & hint
);
385 if (parser
.GetTopLevelTag()->GetChildren())
387 wxSimpleHtmlTag
* settingsTag
= parser
.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
388 if (settingsTag
&& settingsTag
->GetChildren())
390 wxSimpleHtmlTag
* firstSettingTag
= settingsTag
->GetChildren();
392 DoOpen(firstSettingTag
, NULL
);
401 static bool GetHtmlBoolValue(const wxString
& value
)
403 if (value
== wxT("true") || value
== wxT("TRUE") || value
== wxT("1"))
409 static int GetHtmlIntegerValue(const wxString
& value
)
411 return wxAtoi(value
);
414 static double GetHtmlDoubleValue(const wxString
& value
)
416 return wxAtof(value
);
419 bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag
* tag
, ctConfigItem
* parent
)
421 ctConfigItem
* newItem
= NULL
;
422 if (tag
->NameIs(wxT("setting")))
424 wxSimpleHtmlAttribute
* attr
= tag
->FindAttribute(wxT("type"));
427 ctConfigType type
= ctTypeUnknown
;
428 wxString
typeStr(attr
->GetValue());
429 if (typeStr
== wxT("group"))
431 else if (typeStr
== wxT("option-group") || typeStr
== wxT("check-group"))
432 type
= ctTypeCheckGroup
;
433 else if (typeStr
== wxT("radio-group"))
434 type
= ctTypeRadioGroup
;
435 else if (typeStr
== wxT("bool-check"))
436 type
= ctTypeBoolCheck
;
437 else if (typeStr
== wxT("bool-radio"))
438 type
= ctTypeBoolRadio
;
439 else if (typeStr
== wxT("string"))
441 else if (typeStr
== wxT("integer"))
442 type
= ctTypeInteger
;
445 wxLogError(wxT("Unknown type %s"), (const wxChar
*) typeStr
);
447 if (type
!= ctTypeUnknown
)
449 newItem
= new ctConfigItem(parent
, type
, wxT(""));
450 newItem
->InitProperties();
456 wxSimpleHtmlTag
* childTag
= tag
->GetChildren();
460 if (childTag
->GetType() == wxSimpleHtmlTag_Open
)
462 if (childTag
->GetName() == wxT("setting"))
464 DoOpen(childTag
, newItem
);
466 else if (childTag
->GetName() == wxT("name"))
470 wxString
name(childTag
->GetNext()->GetTagText());
471 newItem
->SetName(name
);
474 else if (childTag
->GetName() == wxT("active"))
477 newItem
->SetActive(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
479 else if (childTag
->GetName() == wxT("enabled"))
482 newItem
->Enable(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
488 ctProperty
* prop
= newItem
->GetProperties().FindProperty(childTag
->GetName());
491 // A custom property, else an obsolete
492 // property that we should ignore.
494 if (childTag
->GetAttributeValue(isCustom
, wxT("custom")) &&
495 isCustom
== wxT("true"))
497 prop
= new ctProperty
;
499 wxString
name(childTag
->GetName());
500 wxString
type(wxT("string"));
502 wxString
editorType(wxT("string"));
503 wxString
description(wxT(""));
504 childTag
->GetAttributeValue(type
, wxT("type"));
505 childTag
->GetAttributeValue(type
, wxT("editor-type"));
506 childTag
->GetAttributeValue(type
, wxT("choices"));
507 childTag
->GetAttributeValue(description
, wxT("description"));
509 if (type
== wxT("bool"))
510 prop
->GetVariant() = wxVariant(false, name
);
511 else if (type
== wxT("double"))
512 prop
->GetVariant() = wxVariant((double) 0.0, name
);
513 else if (type
== wxT("long"))
514 prop
->GetVariant() = wxVariant((long) 0, name
);
516 prop
->GetVariant() = wxVariant(wxT(""), name
);
517 prop
->SetDescription(description
);
518 prop
->SetCustom(true);
519 prop
->SetEditorType(editorType
);
520 if (!choices
.IsEmpty())
523 ctConfigItem::StringToArray(choices
, arr
);
524 prop
->SetChoices(arr
);
526 newItem
->GetProperties().AddProperty(prop
);
531 if (prop
->GetVariant().GetType() == wxT("string"))
532 prop
->GetVariant() = childTag
->GetNext()->GetTagText();
533 else if (prop
->GetVariant().GetType() == wxT("long"))
534 prop
->GetVariant() = (long) GetHtmlIntegerValue(childTag
->GetNext()->GetTagText());
535 else if (prop
->GetVariant().GetType() == wxT("bool"))
536 prop
->GetVariant() = GetHtmlBoolValue(childTag
->GetNext()->GetTagText());
537 else if (prop
->GetVariant().GetType() == wxT("double"))
538 prop
->GetVariant() = (double) GetHtmlDoubleValue(childTag
->GetNext()->GetTagText());
543 childTag
= childTag
->GetNext();
548 /// Clear dependencies
549 void ctConfigToolDoc::ClearDependencies(ctConfigItem
* item
)
557 item
->GetDependents().Clear();
558 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
560 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
561 ClearDependencies(child
);
565 /// Refresh dependencies
566 void ctConfigToolDoc::RefreshDependencies()
568 ClearDependencies(GetTopItem());
569 RefreshDependencies(GetTopItem());
572 /// Refresh dependencies
573 void ctConfigToolDoc::RefreshDependencies(ctConfigItem
* item
)
578 wxArrayString requiresArr
;
579 wxString
requires = item
->GetPropertyString(wxT("requires"));
580 wxString precludes
= item
->GetPropertyString(wxT("precludes"));
581 wxString enabledIf
= item
->GetPropertyString(wxT("enabled-if"));
582 wxString enabledIfNot
= item
->GetPropertyString(wxT("enabled-if-not"));
583 wxString indeterminateIf
= item
->GetPropertyString(wxT("indeterminate-if"));
584 wxString context
= item
->GetPropertyString(wxT("context"));
586 if (!requires.IsEmpty())
587 item
->StringToArray(requires, requiresArr
);
589 if (!precludes
.IsEmpty())
590 item
->StringToArray(precludes
, requiresArr
);
592 if (!enabledIfNot
.IsEmpty())
593 item
->StringToArray(enabledIfNot
, requiresArr
);
595 if (!enabledIf
.IsEmpty())
596 item
->StringToArray(enabledIf
, requiresArr
);
598 if (!indeterminateIf
.IsEmpty())
599 item
->StringToArray(indeterminateIf
, requiresArr
);
601 // Add the parent to the list of dependencies, if the
602 // parent is a check or radio group.
603 ctConfigItem
* parent
= item
->GetParent();
605 (parent
->GetType() == ctTypeCheckGroup
||
606 parent
->GetType() == ctTypeRadioGroup
))
607 requiresArr
.Add(parent
->GetName());
609 // Also look in 'context' since these items
610 // are another kind of dependency (switching to
611 // a different platform may cause the dependencies
612 // to be evaluated differently).
613 if (!context
.IsEmpty())
614 item
->StringToArray(context
, requiresArr
);
617 for (i
= 0; i
< requiresArr
.GetCount(); i
++)
619 wxString
itemName(requiresArr
[i
]);
620 ctConfigItem
* otherItem
= GetTopItem()->FindItem(itemName
);
621 if (otherItem
&& !otherItem
->GetDependents().Member(item
))
623 otherItem
->GetDependents().Append(item
);
626 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
628 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
629 RefreshDependencies(child
);
633 /// Generate the text of a setup.h
634 wxString
ctConfigToolDoc::GenerateSetup()
637 str
<< wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
639 GenerateSetup(GetTopItem(), str
);
645 void ctConfigToolDoc::GenerateSetup(ctConfigItem
* item
, wxString
& str
)
647 // Generate the setup.h entries for this item
648 wxString name
= item
->GetName();
650 // We don't process the platform choice
651 if (item
->GetName() == wxT("Target"))
654 if (item
->IsInActiveContext() &&
655 (item
->GetType() == ctTypeCheckGroup
||
656 item
->GetType() == ctTypeRadioGroup
||
657 item
->GetType() == ctTypeBoolCheck
||
658 item
->GetType() == ctTypeBoolRadio
))
660 // TODO: write description
661 wxString name
= item
->GetName();
662 if (name
.Left(6) == wxT("wxUSE_") ||
663 name
== wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
664 name
.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND
)
666 str
<< wxT("#define ") << name
;
667 if (item
->IsEnabled())
675 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
677 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
678 GenerateSetup(child
, str
);
683 /// Generate a configure command
684 wxString
ctConfigToolDoc::GenerateConfigureCommand()
687 str
<< wxT("# configurewx\n# Generated by wxConfigTool\n\n");
689 wxString path
= GetFrameworkDir(true);
690 bool makeUnix
= true;
696 path
+= wxFILE_SEP_PATH
;
699 str
<< path
<< wxT("configure");
701 // Find the target to use
702 ctConfigItem
* platformsFolder
= GetTopItem()->FindItem(wxT("Target"));
705 for ( wxObjectList::compatibility_iterator node
= platformsFolder
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
707 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
708 if (child
->GetType() == ctTypeBoolRadio
&& child
->IsEnabled())
710 wxString configureCommand
= child
->GetPropertyString(wxT("configure-command"));
711 if (!configureCommand
.IsEmpty())
712 str
<< wxT(" ") << configureCommand
;
717 GenerateConfigureCommand(GetTopItem(), str
);
722 void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem
* item
, wxString
& str
)
724 // We don't process the platform group, since we've
726 if (item
->GetName() == wxT("Target"))
729 if (item
->IsInActiveContext() &&
730 (item
->GetType() == ctTypeCheckGroup
||
731 item
->GetType() == ctTypeRadioGroup
||
732 item
->GetType() == ctTypeBoolCheck
||
733 item
->GetType() == ctTypeBoolRadio
))
735 wxString name
= item
->GetName();
736 wxString configureCommand
= item
->GetPropertyString(wxT("configure-command"));
737 if (!configureCommand
.IsEmpty())
739 if (!item
->IsEnabled())
741 // Replace 'enable' with 'disable' if this
743 configureCommand
.Replace(wxT("--enable-"), wxT("--disable-"));
744 configureCommand
.Replace(wxT("--with-"), wxT("--without-"));
746 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("builtin"));
747 if (prop
&& prop
->GetVariant().GetType() == wxT("bool"))
749 bool builtin
= prop
->GetVariant().GetBool();
750 str
<< wxT(" ") << configureCommand
;
752 str
<< wxT("=builtin");
758 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("value"));
759 if (prop
&& prop
->GetVariant().GetType() == wxT("string"))
761 wxString val
= prop
->GetVariant().GetString();
762 if (item
->IsEnabled() && !val
.IsEmpty())
764 str
<< wxT(" ") << configureCommand
;
765 str
<< wxT("=\"") << val
<< wxT("\"");
767 // If the string is empty, ignore this parameter,
768 // since it's obviously intended to be supplied
769 // only if there's a string to use and it's enabled.
773 str
<< wxT(" ") << configureCommand
;
779 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
781 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
782 GenerateConfigureCommand(child
, str
);
786 /// Gets the current framework directory
787 wxString
ctConfigToolDoc::GetFrameworkDir(bool makeUnix
)
789 wxString path
= wxGetApp().GetSettings().m_frameworkDir
;
790 if (wxGetApp().GetSettings().m_useEnvironmentVariable
)
792 // Should probably allow other variables
793 // to be used, and maybe expand variables within m_frameworkDir
794 wxString
pathEnv(wxGetenv(wxT("WXWIN")));
798 path
.Replace(wxT("\\"), wxT("/"));
804 /// Finds the next item in the tree
805 ctConfigItem
* ctConfigToolDoc::FindNextItem(ctConfigItem
* item
, bool wrap
)
810 // First, try to find the first child
811 if (item
->GetChildCount() > 0)
813 return item
->GetChild(0);
817 ctConfigItem
* p
= item
;
820 ctConfigItem
* toFind
= FindNextSibling(p
);
827 // Finally, wrap around to the root.
834 /// Finds the next sibling in the tree
835 ctConfigItem
* ctConfigToolDoc::FindNextSibling(ctConfigItem
* item
)
837 if (item
->GetParent())
839 wxObjectList::compatibility_iterator node
= item
->GetParent()->GetChildren().Member(item
);
840 if (node
&& node
->GetNext())
842 ctConfigItem
* nextItem
= (ctConfigItem
*) node
->GetNext()->GetData();
851 * Implements a document editing command.
854 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
855 ctConfigItem
* activeState
, ctConfigItem
* savedState
,
856 ctConfigItem
* parent
, ctConfigItem
* insertBefore
,
857 bool ignoreFirstTime
): wxCommand(true, name
)
859 m_activeState
= activeState
;
860 m_savedState
= savedState
;
861 m_ignoreThis
= ignoreFirstTime
;
865 m_insertBefore
= insertBefore
;
868 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
869 ctConfigItem
* activeState
, ctProperties
* properties
,
870 bool ignoreFirstTime
): wxCommand(true, name
)
872 m_activeState
= activeState
;
874 m_properties
= properties
;
875 m_ignoreThis
= ignoreFirstTime
;
877 m_properties
= properties
;
879 m_insertBefore
= NULL
;
882 ctConfigCommand::~ctConfigCommand()
890 bool ctConfigCommand::Do()
892 return DoAndUndo(true);
895 bool ctConfigCommand::Undo()
897 return DoAndUndo(false);
900 // Combine Do and Undo into one
901 bool ctConfigCommand::DoAndUndo(bool doCmd
)
909 wxASSERT(m_savedState
== NULL
);
910 wxASSERT(m_activeState
!= NULL
);
912 ctConfigItem
* newItem
= m_activeState
->DeepClone();
913 ctConfigToolDoc
* doc
= m_activeState
->GetDocument();
915 // This will delete the old clipboard contents, if any.
916 doc
->SetClipboardItem(newItem
);
918 m_parent
= m_activeState
->GetParent();
919 m_insertBefore
= m_activeState
->FindNextSibling();
921 m_activeState
->Detach();
922 m_savedState
= m_activeState
;
923 m_activeState
= NULL
;
925 m_savedState
->GetDocument()->Modify(true);
926 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
927 view
->OnChangeFilename();
931 wxASSERT(m_savedState
!= NULL
);
932 wxASSERT(m_activeState
== NULL
);
934 m_savedState
->GetDocument()->Modify(true);
935 m_savedState
->Attach(m_parent
, m_insertBefore
);
936 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
937 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
938 m_activeState
= m_savedState
;
941 m_insertBefore
= NULL
;
942 view
->OnChangeFilename();
950 wxASSERT(m_savedState
!= NULL
);
951 wxASSERT(m_activeState
== NULL
);
953 m_savedState
->GetDocument()->Modify(true);
954 m_savedState
->Attach(m_parent
, m_insertBefore
);
955 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
956 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
957 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
958 m_activeState
= m_savedState
;
960 view
->OnChangeFilename();
964 wxASSERT(m_savedState
== NULL
);
965 wxASSERT(m_activeState
!= NULL
);
967 m_activeState
->GetDocument()->Modify(true);
968 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
969 m_activeState
->Detach();
970 m_savedState
= m_activeState
;
971 m_activeState
= NULL
;
972 view
->OnChangeFilename();
976 case ctCMD_NEW_ELEMENT
:
980 wxASSERT(m_savedState
!= NULL
);
981 wxASSERT(m_activeState
== NULL
);
983 m_savedState
->GetDocument()->Modify(true);
984 m_savedState
->Attach(m_parent
, m_insertBefore
);
985 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
986 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
987 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
989 m_activeState
= m_savedState
;
994 wxASSERT(m_savedState
== NULL
);
995 wxASSERT(m_activeState
!= NULL
);
997 m_activeState
->GetDocument()->Modify(true);
998 m_activeState
->Detach();
999 m_savedState
= m_activeState
;
1000 m_activeState
= NULL
;
1004 case ctCMD_APPLY_PROPERTY
:
1006 wxASSERT(m_properties
!= NULL
);
1007 wxASSERT(m_activeState
!= NULL
);
1009 // Don't update the properties editor first time
1010 // around since it will be done one property at a time
1011 // initially (and no property editor update required)
1014 // Just swap the saved and current properties.
1015 ctProperties propsTemp
= m_activeState
->GetProperties() ;
1016 m_activeState
->GetProperties() = (* m_properties
);
1017 (* m_properties
) = propsTemp
;
1019 // Apply only those that need applying
1020 // (those properties in activeState that are not in propsTemp)
1021 wxObjectList::compatibility_iterator node
= m_activeState
->GetProperties().GetList().GetFirst();
1024 ctProperty
* prop
= (ctProperty
*) node
->GetData();
1025 ctProperty
* otherProp
= propsTemp
.FindProperty(prop
->GetName());
1026 if (otherProp
&& ((*prop
) != (*otherProp
)))
1028 m_activeState
->ApplyProperty(prop
, otherProp
->GetVariant());
1030 node
= node
->GetNext();
1032 m_activeState
->GetDocument()->Modify(true);
1033 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
1036 ctConfigToolHint
hint(NULL
, ctValueChanged
);
1037 m_activeState
->GetDocument()->UpdateAllViews (NULL
, & hint
);
1040 m_ignoreThis
= false;
1048 IMPLEMENT_CLASS(ctConfiguration
, wxObject
)
1050 ctConfiguration::ctConfiguration()
1052 m_treeItemId
= wxTreeItemId();
1057 ctConfiguration::ctConfiguration(ctConfiguration
* parent
, const wxString
& name
)
1059 m_treeItemId
= wxTreeItemId();
1063 parent
->AddChild(this);
1066 ctConfiguration::~ctConfiguration()
1069 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
1070 if (m_treeItemId.IsOk() && treeCtrl)
1072 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
1074 data->SetConfigItem(NULL);
1077 GetParent()->RemoveChild(this);
1080 if (wxGetApp().GetMainFrame()->GetDocument() &&
1081 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
1082 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
1089 /// Assignment operator.
1090 void ctConfiguration::operator= (const ctConfiguration
& configuration
)
1092 m_name
= configuration
.m_name
;
1093 m_description
= configuration
.m_description
;
1097 void ctConfiguration::Clear()
1099 wxObjectList::compatibility_iterator node
= m_children
.GetFirst();
1102 wxObjectList::compatibility_iterator next
= node
->GetNext();
1103 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1105 // This should delete 'node' too, assuming
1106 // child's m_parent points to 'this'. If not,
1107 // it'll be cleaned up by m_children.Clear().
1115 // Get the nth child
1116 ctConfiguration
* ctConfiguration::GetChild(int n
) const
1118 wxASSERT ( n
< GetChildCount() && n
> -1 );
1120 if ( n
< GetChildCount() && n
> -1 )
1122 ctConfiguration
* child
= wxDynamicCast(m_children
.Item(n
)->GetData(), ctConfiguration
);
1129 // Get the child count
1130 int ctConfiguration::GetChildCount() const
1132 return m_children
.GetCount();
1136 void ctConfiguration::AddChild(ctConfiguration
* configuration
)
1138 m_children
.Append(configuration
);
1139 configuration
->SetParent(this);
1142 /// Remove (but don't delete) a child
1143 void ctConfiguration::RemoveChild(ctConfiguration
* configuration
)
1145 m_children
.DeleteObject(configuration
);
1146 configuration
->SetParent(NULL
);
1149 /// Get the associated document (currently, assumes
1150 /// there's only ever one document active)
1151 ctConfigToolDoc
* ctConfiguration::GetDocument()
1153 ctConfigToolDoc
* doc
= wxGetApp().GetMainFrame()->GetDocument();
1157 /// Find an item in this hierarchy
1158 // TODO: ensure that names are unique, somehow.
1159 ctConfiguration
* ctConfiguration::FindConfiguration(const wxString
& name
)
1161 if (GetName() == name
)
1164 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1166 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1167 ctConfiguration
* found
= child
->FindConfiguration(name
);
1174 /// Find the next sibling
1175 ctConfiguration
* ctConfiguration::FindNextSibling()
1179 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1180 if (node
&& node
->GetNext())
1182 return (ctConfiguration
*) node
->GetNext()->GetData();
1187 /// Find the previous sibling
1188 ctConfiguration
* ctConfiguration::FindPreviousSibling()
1192 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1193 if (node
&& node
->GetPrevious())
1195 return (ctConfiguration
*) node
->GetPrevious()->GetData();
1200 /// Create a clone of this and children
1201 ctConfiguration
* ctConfiguration::DeepClone()
1203 ctConfiguration
* newItem
= Clone();
1205 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1207 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1208 ctConfiguration
* newChild
= child
->DeepClone();
1209 newItem
->AddChild(newChild
);
1214 /// Detach: remove from parent, and remove tree items
1215 void ctConfiguration::Detach()
1219 GetParent()->RemoveChild(this);
1221 GetDocument()->SetTopItem(NULL
);
1225 wxTreeItemId treeItem = GetTreeItemId();
1229 // Will delete the branch, but not the config items.
1230 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
1234 /// Hide from tree: make sure tree deletions won't delete
1235 /// the config items
1236 void ctConfiguration::DetachFromTree()
1239 wxTreeItemId item = GetTreeItemId();
1242 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
1243 data->SetConfigItem(NULL);
1244 m_treeItemId = wxTreeItemId();
1246 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
1248 ctConfiguration* child = (ctConfiguration*) node->GetData();
1249 child->DetachFromTree();