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/txtstrm.h"
33 #include "wx/wfstream.h"
34 #include "wx/config.h"
35 #include "configtooldoc.h"
36 #include "configtoolview.h"
37 #include "configtree.h"
38 #include "mainframe.h"
40 #include "wxconfigtool.h"
41 #include "htmlparser.h"
43 IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc
, wxDocument
)
46 ctConfigToolDoc::ctConfigToolDoc()
49 m_clipboardItem
= NULL
;
53 ctConfigToolDoc::~ctConfigToolDoc()
57 if (GetCommandProcessor())
58 GetCommandProcessor()->SetEditMenu(NULL
);
61 // Delete all the items not already deleted
62 void ctConfigToolDoc::DeleteItems()
69 /// Clears the clipboard item.
70 void ctConfigToolDoc::ClearClipboard()
73 delete m_clipboardItem
;
74 m_clipboardItem
= NULL
;
77 /// Sets the clipboard item.
78 void ctConfigToolDoc::SetClipboardItem(ctConfigItem
* item
)
81 delete m_clipboardItem
;
82 m_clipboardItem
= item
;
86 // Closes and clears the document
87 bool ctConfigToolDoc::OnCloseDocument()
89 if (wxDocument::OnCloseDocument())
91 ctConfigToolHint
hint(NULL
, ctClear
);
92 UpdateAllViews (NULL
, & hint
);
104 bool ctConfigToolDoc::Save()
106 if (!IsModified() && m_savedYet
) return true;
108 bool ret
= (m_documentFile
== wxT("") || !m_savedYet
) ?
110 OnSaveDocument(m_documentFile
);
112 SetDocumentSaved(true);
116 // Create the document
117 bool ctConfigToolDoc::OnCreate(const wxString
& path
, long flags
)
119 GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
120 GetCommandProcessor()->Initialize();
121 GetCommandProcessor()->ClearCommands();
123 // wxGetApp().m_currentDoc = this;
125 if (flags
& wxDOC_NEW
)
127 ctConfigItem
* rootItem
= new ctConfigItem(NULL
, ctTypeGroup
, _T("Configuration"));
128 //rootItem->InitProperties();
129 rootItem
->GetProperties().AddProperty(
131 wxT("The item description."),
132 wxVariant(wxT(""), wxT("description")),
135 rootItem
->SetPropertyString(_T("description"),
136 _T("<B>This is the top-level configuration item.</B>"));
139 SetTopItem(rootItem
);
142 SetDocumentSaved(false);
144 wxString
rootName(wxT("untitled"));
145 wxStripExtension(rootName
);
146 SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName
));
149 // Creates the view, so do any view updating after this
150 bool success
= wxDocument::OnCreate(path
, flags
);
154 if (flags
& wxDOC_NEW
)
158 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
159 UpdateAllViews (NULL
, & hint
);
161 SetFilename(GetFilename(), true);
168 bool ctConfigToolDoc::OnSaveDocument(const wxString
& filename
)
172 const wxString
strOldPath(GetFilename());
174 // Do some backing up first
176 // This is the backup filename
177 wxString
backupFilename(filename
);
178 backupFilename
+= wxT(".bak");
180 // This is the temporary copy of the backup
181 wxString
tempFilename(filename
);
182 tempFilename
+= wxT(".tmp");
183 if (wxFileExists(tempFilename
))
184 wxRemoveFile(tempFilename
);
186 bool leaveBackup
= true;
188 bool saved
= DoSave(tempFilename
);
192 // Remove the old .bak file
193 if (wxFileExists(backupFilename
))
195 wxRemoveFile(backupFilename
);
198 // Copy the old file to the .bak
202 if (wxFileExists(filename
))
204 if (!wxRenameFile(filename
, backupFilename
))
206 wxCopyFile(filename
, backupFilename
);
207 wxRemoveFile(filename
);
213 if (wxFileExists(filename
))
214 wxRemoveFile(filename
);
217 // Finally, copy the temporary file to the proper filename
218 if (!wxRenameFile(tempFilename
, filename
))
220 wxCopyFile(tempFilename
, filename
);
221 wxRemoveFile(tempFilename
);
225 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
226 SetDocumentSaved(true);
227 SetFilename(filename
);
228 wxGetApp().GetSettings().m_lastFilename
= filename
;
231 SetFilename(strOldPath
);
233 wxGetApp().GetMainFrame()->UpdateFrameTitle();
238 bool ctConfigToolDoc::OnOpenDocument(const wxString
& filename
)
242 bool opened
= DoOpen(filename
);
246 SetFilename(filename
);
247 wxGetApp().GetSettings().m_lastFilename
= filename
;
249 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
251 RefreshDependencies();
253 // ctConfigToolHint hint(NULL, ctFilenameChanged);
254 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
255 UpdateAllViews (NULL
, & hint
);
258 SetDocumentSaved(true); // Necessary or it will pop up the Save As dialog
263 /// Save the settings file
264 bool ctConfigToolDoc::DoSave(const wxString
& filename
)
266 wxFileOutputStream
osFile(filename
);
270 wxTextOutputStream
stream(osFile
);
272 stream
<< wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
273 stream
<< wxT("<settings xmlns=\"http://www.wxwidgets.org/wxs\" version=\"2.5.0.1\">");
275 DoSave(m_topItem
, osFile
, 1);
277 stream
<< wxT("\n</settings>\n");
282 inline static void OutputIndentation(wxOutputStream
& osFile
, int indent
)
284 wxTextOutputStream
stream(osFile
);
285 wxString str
= wxT("\n");
286 for (int i
= 0; i
< indent
; i
++)
291 /// Recursive helper function for file saving
292 bool ctConfigToolDoc::DoSave(ctConfigItem
* item
, wxOutputStream
& osFile
, int indent
)
294 OutputIndentation(osFile
, indent
*2);
295 wxTextOutputStream
stream(osFile
);
297 wxString
name(item
->GetName());
300 if (item
->GetType() == ctTypeGroup
)
301 typeStr
= wxT("group");
302 else if (item
->GetType() == ctTypeCheckGroup
)
303 typeStr
= wxT("check-group");
304 else if (item
->GetType() == ctTypeRadioGroup
)
305 typeStr
= wxT("radio-group");
306 else if (item
->GetType() == ctTypeString
)
307 typeStr
= wxT("string");
308 else if (item
->GetType() == ctTypeBoolCheck
)
309 typeStr
= wxT("bool-check");
310 else if (item
->GetType() == ctTypeBoolRadio
)
311 typeStr
= wxT("bool-radio");
312 else if (item
->GetType() == ctTypeInteger
)
313 typeStr
= wxT("integer");
315 typeStr
= wxT("unknown");
317 stream
<< wxT("<setting type=\"") << typeStr
<< wxT("\">");
321 OutputIndentation(osFile
, indent
*2);
322 if (item
->IsActive())
323 stream
<< wxT("<active>1</active>");
325 stream
<< wxT("<active>0</active>");
326 OutputIndentation(osFile
, indent
*2);
327 if (item
->IsEnabled())
328 stream
<< wxT("<enabled>1</enabled>");
330 stream
<< wxT("<enabled>0</enabled>");
333 wxObjectList::compatibility_iterator node
= item
->GetProperties().GetList().GetFirst();
336 ctProperty
* prop
= (ctProperty
*) node
->GetData();
337 OutputIndentation(osFile
, indent
*2);
338 stream
<< wxT("<") << prop
->GetName() ;
340 if (prop
->IsCustom())
342 stream
<< wxT(" custom=\"true\"");
343 stream
<< wxT(" type=\"") << prop
->GetVariant().GetType() << wxT("\"");
344 stream
<< wxT(" editor-type=\"") << prop
->GetEditorType() << wxT("\"");
345 stream
<< wxT(" description=\"") << prop
->GetDescription() << wxT("\"");
346 if (prop
->GetChoices().GetCount() > 0)
349 ctConfigItem::ArrayToString(prop
->GetChoices(), choices
);
350 stream
<< wxT(" choices=\"") << choices
<< wxT("\"");
356 stream
<< ctEscapeHTMLCharacters(prop
->GetVariant().GetString()) ;
357 stream
<< wxT("</") << prop
->GetName() << wxT(">");
359 node
= node
->GetNext();
363 node
= item
->GetChildren().GetFirst();
366 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
367 DoSave(child
, osFile
, indent
);
369 node
= node
->GetNext();
374 OutputIndentation(osFile
, indent
*2);
375 stream
<< wxT("</setting>");
380 /// Open the settings file
381 bool ctConfigToolDoc::DoOpen(const wxString
& filename
)
383 wxSimpleHtmlParser parser
;
384 if (parser
.ParseFile(filename
))
386 ctConfigToolHint
hint(NULL
, ctClear
);
387 UpdateAllViews (NULL
, & hint
);
390 if (parser
.GetTopLevelTag()->GetChildren())
392 wxSimpleHtmlTag
* settingsTag
= parser
.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
393 if (settingsTag
&& settingsTag
->GetChildren())
395 wxSimpleHtmlTag
* firstSettingTag
= settingsTag
->GetChildren();
397 DoOpen(firstSettingTag
, NULL
);
406 static bool GetHtmlBoolValue(const wxString
& value
)
408 if (value
.IsSameAs(wxT("true"),false) || value
== wxT("1"))
414 static int GetHtmlIntegerValue(const wxString
& value
)
416 return wxAtoi(value
);
419 static double GetHtmlDoubleValue(const wxString
& value
)
421 return wxAtof(value
);
424 bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag
* tag
, ctConfigItem
* parent
)
426 ctConfigItem
* newItem
= NULL
;
427 if (tag
->NameIs(wxT("setting")))
429 wxSimpleHtmlAttribute
* attr
= tag
->FindAttribute(wxT("type"));
432 ctConfigType type
= ctTypeUnknown
;
433 wxString
typeStr(attr
->GetValue());
434 if (typeStr
== wxT("group"))
436 else if (typeStr
== wxT("option-group") || typeStr
== wxT("check-group"))
437 type
= ctTypeCheckGroup
;
438 else if (typeStr
== wxT("radio-group"))
439 type
= ctTypeRadioGroup
;
440 else if (typeStr
== wxT("bool-check"))
441 type
= ctTypeBoolCheck
;
442 else if (typeStr
== wxT("bool-radio"))
443 type
= ctTypeBoolRadio
;
444 else if (typeStr
== wxT("string"))
446 else if (typeStr
== wxT("integer"))
447 type
= ctTypeInteger
;
450 wxLogError(wxT("Unknown type %s"), (const wxChar
*) typeStr
);
452 if (type
!= ctTypeUnknown
)
454 newItem
= new ctConfigItem(parent
, type
, wxT(""));
455 newItem
->InitProperties();
461 wxSimpleHtmlTag
* childTag
= tag
->GetChildren();
465 if (childTag
->GetType() == wxSimpleHtmlTag_Open
)
467 if (childTag
->GetName() == wxT("setting"))
469 DoOpen(childTag
, newItem
);
471 else if (childTag
->GetName() == wxT("name"))
475 wxString
name(childTag
->GetNext()->GetTagText());
476 newItem
->SetName(name
);
479 else if (childTag
->GetName() == wxT("active"))
482 newItem
->SetActive(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
484 else if (childTag
->GetName() == wxT("enabled"))
487 newItem
->Enable(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
493 ctProperty
* prop
= newItem
->GetProperties().FindProperty(childTag
->GetName());
496 // A custom property, else an obsolete
497 // property that we should ignore.
499 if (childTag
->GetAttributeValue(isCustom
, wxT("custom")) &&
500 isCustom
== wxT("true"))
502 prop
= new ctProperty
;
504 wxString
name(childTag
->GetName());
505 wxString
type(wxT("string"));
507 wxString
editorType(wxT("string"));
508 wxString
description(wxT(""));
509 childTag
->GetAttributeValue(type
, wxT("type"));
510 childTag
->GetAttributeValue(type
, wxT("editor-type"));
511 childTag
->GetAttributeValue(type
, wxT("choices"));
512 childTag
->GetAttributeValue(description
, wxT("description"));
514 if (type
== wxT("bool"))
515 prop
->GetVariant() = wxVariant(false, name
);
516 else if (type
== wxT("double"))
517 prop
->GetVariant() = wxVariant((double) 0.0, name
);
518 else if (type
== wxT("long"))
519 prop
->GetVariant() = wxVariant((long) 0, name
);
521 prop
->GetVariant() = wxVariant(wxT(""), name
);
522 prop
->SetDescription(description
);
523 prop
->SetCustom(true);
524 prop
->SetEditorType(editorType
);
525 if (!choices
.IsEmpty())
528 ctConfigItem::StringToArray(choices
, arr
);
529 prop
->SetChoices(arr
);
531 newItem
->GetProperties().AddProperty(prop
);
536 if (prop
->GetVariant().GetType() == wxT("string"))
537 prop
->GetVariant() = childTag
->GetNext()->GetTagText();
538 else if (prop
->GetVariant().GetType() == wxT("long"))
539 prop
->GetVariant() = (long) GetHtmlIntegerValue(childTag
->GetNext()->GetTagText());
540 else if (prop
->GetVariant().GetType() == wxT("bool"))
541 prop
->GetVariant() = GetHtmlBoolValue(childTag
->GetNext()->GetTagText());
542 else if (prop
->GetVariant().GetType() == wxT("double"))
543 prop
->GetVariant() = (double) GetHtmlDoubleValue(childTag
->GetNext()->GetTagText());
548 childTag
= childTag
->GetNext();
553 /// Clear dependencies
554 void ctConfigToolDoc::ClearDependencies(ctConfigItem
* item
)
562 item
->GetDependents().Clear();
563 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
565 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
566 ClearDependencies(child
);
570 /// Refresh dependencies
571 void ctConfigToolDoc::RefreshDependencies()
573 ClearDependencies(GetTopItem());
574 RefreshDependencies(GetTopItem());
577 /// Refresh dependencies
578 void ctConfigToolDoc::RefreshDependencies(ctConfigItem
* item
)
583 wxArrayString requiresArr
;
584 wxString
requires = item
->GetPropertyString(wxT("requires"));
585 wxString precludes
= item
->GetPropertyString(wxT("precludes"));
586 wxString enabledIf
= item
->GetPropertyString(wxT("enabled-if"));
587 wxString enabledIfNot
= item
->GetPropertyString(wxT("enabled-if-not"));
588 wxString indeterminateIf
= item
->GetPropertyString(wxT("indeterminate-if"));
589 wxString context
= item
->GetPropertyString(wxT("context"));
591 if (!requires.IsEmpty())
592 item
->StringToArray(requires, requiresArr
);
594 if (!precludes
.IsEmpty())
595 item
->StringToArray(precludes
, requiresArr
);
597 if (!enabledIfNot
.IsEmpty())
598 item
->StringToArray(enabledIfNot
, requiresArr
);
600 if (!enabledIf
.IsEmpty())
601 item
->StringToArray(enabledIf
, requiresArr
);
603 if (!indeterminateIf
.IsEmpty())
604 item
->StringToArray(indeterminateIf
, requiresArr
);
606 // Add the parent to the list of dependencies, if the
607 // parent is a check or radio group.
608 ctConfigItem
* parent
= item
->GetParent();
610 (parent
->GetType() == ctTypeCheckGroup
||
611 parent
->GetType() == ctTypeRadioGroup
))
612 requiresArr
.Add(parent
->GetName());
614 // Also look in 'context' since these items
615 // are another kind of dependency (switching to
616 // a different platform may cause the dependencies
617 // to be evaluated differently).
618 if (!context
.IsEmpty())
619 item
->StringToArray(context
, requiresArr
);
622 for (i
= 0; i
< requiresArr
.GetCount(); i
++)
624 wxString
itemName(requiresArr
[i
]);
625 ctConfigItem
* otherItem
= GetTopItem()->FindItem(itemName
);
626 if (otherItem
&& !otherItem
->GetDependents().Member(item
))
628 otherItem
->GetDependents().Append(item
);
631 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
633 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
634 RefreshDependencies(child
);
638 /// Generate the text of a setup.h
639 wxString
ctConfigToolDoc::GenerateSetup()
642 str
<< wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
644 GenerateSetup(GetTopItem(), str
);
650 void ctConfigToolDoc::GenerateSetup(ctConfigItem
* item
, wxString
& str
)
652 // Generate the setup.h entries for this item
653 wxString name
= item
->GetName();
655 // We don't process the platform choice
656 if (item
->GetName() == wxT("Target"))
659 if (item
->IsInActiveContext() &&
660 (item
->GetType() == ctTypeCheckGroup
||
661 item
->GetType() == ctTypeRadioGroup
||
662 item
->GetType() == ctTypeBoolCheck
||
663 item
->GetType() == ctTypeBoolRadio
))
665 // TODO: write description
666 wxString name
= item
->GetName();
667 if (name
.Left(6) == wxT("wxUSE_") ||
668 name
== wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
669 name
.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND
)
671 str
<< wxT("#define ") << name
;
672 if (item
->IsEnabled())
680 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
682 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
683 GenerateSetup(child
, str
);
688 /// Generate a configure command
689 wxString
ctConfigToolDoc::GenerateConfigureCommand()
692 str
<< wxT("# configurewx\n# Generated by wxConfigTool\n\n");
694 wxString path
= GetFrameworkDir(true);
695 bool makeUnix
= true;
701 path
+= wxFILE_SEP_PATH
;
704 str
<< path
<< wxT("configure");
706 // Find the target to use
707 ctConfigItem
* platformsFolder
= GetTopItem()->FindItem(wxT("Target"));
710 for ( wxObjectList::compatibility_iterator node
= platformsFolder
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
712 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
713 if (child
->GetType() == ctTypeBoolRadio
&& child
->IsEnabled())
715 wxString configureCommand
= child
->GetPropertyString(wxT("configure-command"));
716 if (!configureCommand
.IsEmpty())
717 str
<< wxT(" ") << configureCommand
;
722 GenerateConfigureCommand(GetTopItem(), str
);
727 void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem
* item
, wxString
& str
)
729 // We don't process the platform group, since we've
731 if (item
->GetName() == wxT("Target"))
734 if (item
->IsInActiveContext() &&
735 (item
->GetType() == ctTypeCheckGroup
||
736 item
->GetType() == ctTypeRadioGroup
||
737 item
->GetType() == ctTypeBoolCheck
||
738 item
->GetType() == ctTypeBoolRadio
))
740 wxString name
= item
->GetName();
741 wxString configureCommand
= item
->GetPropertyString(wxT("configure-command"));
742 if (!configureCommand
.IsEmpty())
744 if (!item
->IsEnabled())
746 // Replace 'enable' with 'disable' if this
748 configureCommand
.Replace(wxT("--enable-"), wxT("--disable-"));
749 configureCommand
.Replace(wxT("--with-"), wxT("--without-"));
751 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("builtin"));
752 if (prop
&& prop
->GetVariant().GetType() == wxT("bool"))
754 bool builtin
= prop
->GetVariant().GetBool();
755 str
<< wxT(" ") << configureCommand
;
757 str
<< wxT("=builtin");
763 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("value"));
764 if (prop
&& prop
->GetVariant().GetType() == wxT("string"))
766 wxString val
= prop
->GetVariant().GetString();
767 if (item
->IsEnabled() && !val
.IsEmpty())
769 str
<< wxT(" ") << configureCommand
;
770 str
<< wxT("=\"") << val
<< wxT("\"");
772 // If the string is empty, ignore this parameter,
773 // since it's obviously intended to be supplied
774 // only if there's a string to use and it's enabled.
778 str
<< wxT(" ") << configureCommand
;
784 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
786 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
787 GenerateConfigureCommand(child
, str
);
791 /// Gets the current framework directory
792 wxString
ctConfigToolDoc::GetFrameworkDir(bool makeUnix
)
794 wxString path
= wxGetApp().GetSettings().m_frameworkDir
;
795 if (wxGetApp().GetSettings().m_useEnvironmentVariable
)
797 // Should probably allow other variables
798 // to be used, and maybe expand variables within m_frameworkDir
799 wxString
pathEnv(wxGetenv(wxT("WXWIN")));
803 path
.Replace(wxT("\\"), wxT("/"));
809 /// Finds the next item in the tree
810 ctConfigItem
* ctConfigToolDoc::FindNextItem(ctConfigItem
* item
, bool wrap
)
815 // First, try to find the first child
816 if (item
->GetChildCount() > 0)
818 return item
->GetChild(0);
822 ctConfigItem
* p
= item
;
825 ctConfigItem
* toFind
= FindNextSibling(p
);
832 // Finally, wrap around to the root.
839 /// Finds the next sibling in the tree
840 ctConfigItem
* ctConfigToolDoc::FindNextSibling(ctConfigItem
* item
)
842 if (item
->GetParent())
844 wxObjectList::compatibility_iterator node
= item
->GetParent()->GetChildren().Member(item
);
845 if (node
&& node
->GetNext())
847 ctConfigItem
* nextItem
= (ctConfigItem
*) node
->GetNext()->GetData();
856 * Implements a document editing command.
859 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
860 ctConfigItem
* activeState
, ctConfigItem
* savedState
,
861 ctConfigItem
* parent
, ctConfigItem
* insertBefore
,
862 bool ignoreFirstTime
): wxCommand(true, name
)
864 m_activeState
= activeState
;
865 m_savedState
= savedState
;
866 m_ignoreThis
= ignoreFirstTime
;
870 m_insertBefore
= insertBefore
;
873 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
874 ctConfigItem
* activeState
, ctProperties
* properties
,
875 bool ignoreFirstTime
): wxCommand(true, name
)
877 m_activeState
= activeState
;
879 m_properties
= properties
;
880 m_ignoreThis
= ignoreFirstTime
;
882 m_properties
= properties
;
884 m_insertBefore
= NULL
;
887 ctConfigCommand::~ctConfigCommand()
895 bool ctConfigCommand::Do()
897 return DoAndUndo(true);
900 bool ctConfigCommand::Undo()
902 return DoAndUndo(false);
905 // Combine Do and Undo into one
906 bool ctConfigCommand::DoAndUndo(bool doCmd
)
914 wxASSERT(m_savedState
== NULL
);
915 wxASSERT(m_activeState
!= NULL
);
917 ctConfigItem
* newItem
= m_activeState
->DeepClone();
918 ctConfigToolDoc
* doc
= m_activeState
->GetDocument();
920 // This will delete the old clipboard contents, if any.
921 doc
->SetClipboardItem(newItem
);
923 m_parent
= m_activeState
->GetParent();
924 m_insertBefore
= m_activeState
->FindNextSibling();
926 m_activeState
->Detach();
927 m_savedState
= m_activeState
;
928 m_activeState
= NULL
;
930 m_savedState
->GetDocument()->Modify(true);
931 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
932 view
->OnChangeFilename();
936 wxASSERT(m_savedState
!= NULL
);
937 wxASSERT(m_activeState
== NULL
);
939 m_savedState
->GetDocument()->Modify(true);
940 m_savedState
->Attach(m_parent
, m_insertBefore
);
941 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
942 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
943 m_activeState
= m_savedState
;
946 m_insertBefore
= NULL
;
947 view
->OnChangeFilename();
955 wxASSERT(m_savedState
!= NULL
);
956 wxASSERT(m_activeState
== NULL
);
958 m_savedState
->GetDocument()->Modify(true);
959 m_savedState
->Attach(m_parent
, m_insertBefore
);
960 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
961 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
962 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
963 m_activeState
= m_savedState
;
965 view
->OnChangeFilename();
969 wxASSERT(m_savedState
== NULL
);
970 wxASSERT(m_activeState
!= NULL
);
972 m_activeState
->GetDocument()->Modify(true);
973 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
974 m_activeState
->Detach();
975 m_savedState
= m_activeState
;
976 m_activeState
= NULL
;
977 view
->OnChangeFilename();
981 case ctCMD_NEW_ELEMENT
:
985 wxASSERT(m_savedState
!= NULL
);
986 wxASSERT(m_activeState
== NULL
);
988 m_savedState
->GetDocument()->Modify(true);
989 m_savedState
->Attach(m_parent
, m_insertBefore
);
990 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
991 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
992 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
994 m_activeState
= m_savedState
;
999 wxASSERT(m_savedState
== NULL
);
1000 wxASSERT(m_activeState
!= NULL
);
1002 m_activeState
->GetDocument()->Modify(true);
1003 m_activeState
->Detach();
1004 m_savedState
= m_activeState
;
1005 m_activeState
= NULL
;
1009 case ctCMD_APPLY_PROPERTY
:
1011 wxASSERT(m_properties
!= NULL
);
1012 wxASSERT(m_activeState
!= NULL
);
1014 // Don't update the properties editor first time
1015 // around since it will be done one property at a time
1016 // initially (and no property editor update required)
1019 // Just swap the saved and current properties.
1020 ctProperties propsTemp
= m_activeState
->GetProperties() ;
1021 m_activeState
->GetProperties() = (* m_properties
);
1022 (* m_properties
) = propsTemp
;
1024 // Apply only those that need applying
1025 // (those properties in activeState that are not in propsTemp)
1026 wxObjectList::compatibility_iterator node
= m_activeState
->GetProperties().GetList().GetFirst();
1029 ctProperty
* prop
= (ctProperty
*) node
->GetData();
1030 ctProperty
* otherProp
= propsTemp
.FindProperty(prop
->GetName());
1031 if (otherProp
&& ((*prop
) != (*otherProp
)))
1033 m_activeState
->ApplyProperty(prop
, otherProp
->GetVariant());
1035 node
= node
->GetNext();
1037 m_activeState
->GetDocument()->Modify(true);
1038 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
1041 ctConfigToolHint
hint(NULL
, ctValueChanged
);
1042 m_activeState
->GetDocument()->UpdateAllViews (NULL
, & hint
);
1045 m_ignoreThis
= false;
1053 IMPLEMENT_CLASS(ctConfiguration
, wxObject
)
1055 ctConfiguration::ctConfiguration()
1057 m_treeItemId
= wxTreeItemId();
1062 ctConfiguration::ctConfiguration(ctConfiguration
* parent
, const wxString
& name
)
1064 m_treeItemId
= wxTreeItemId();
1068 parent
->AddChild(this);
1071 ctConfiguration::~ctConfiguration()
1074 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
1075 if (m_treeItemId.IsOk() && treeCtrl)
1077 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
1079 data->SetConfigItem(NULL);
1082 GetParent()->RemoveChild(this);
1085 if (wxGetApp().GetMainFrame()->GetDocument() &&
1086 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
1087 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
1094 /// Assignment operator.
1095 void ctConfiguration::operator= (const ctConfiguration
& configuration
)
1097 m_name
= configuration
.m_name
;
1098 m_description
= configuration
.m_description
;
1102 void ctConfiguration::Clear()
1104 wxObjectList::compatibility_iterator node
= m_children
.GetFirst();
1107 wxObjectList::compatibility_iterator next
= node
->GetNext();
1108 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1110 // This should delete 'node' too, assuming
1111 // child's m_parent points to 'this'. If not,
1112 // it'll be cleaned up by m_children.Clear().
1120 // Get the nth child
1121 ctConfiguration
* ctConfiguration::GetChild(int n
) const
1123 wxASSERT ( n
< GetChildCount() && n
> -1 );
1125 if ( n
< GetChildCount() && n
> -1 )
1127 ctConfiguration
* child
= wxDynamicCast(m_children
.Item(n
)->GetData(), ctConfiguration
);
1134 // Get the child count
1135 int ctConfiguration::GetChildCount() const
1137 return m_children
.GetCount();
1141 void ctConfiguration::AddChild(ctConfiguration
* configuration
)
1143 m_children
.Append(configuration
);
1144 configuration
->SetParent(this);
1147 /// Remove (but don't delete) a child
1148 void ctConfiguration::RemoveChild(ctConfiguration
* configuration
)
1150 m_children
.DeleteObject(configuration
);
1151 configuration
->SetParent(NULL
);
1154 /// Get the associated document (currently, assumes
1155 /// there's only ever one document active)
1156 ctConfigToolDoc
* ctConfiguration::GetDocument()
1158 ctConfigToolDoc
* doc
= wxGetApp().GetMainFrame()->GetDocument();
1162 /// Find an item in this hierarchy
1163 // TODO: ensure that names are unique, somehow.
1164 ctConfiguration
* ctConfiguration::FindConfiguration(const wxString
& name
)
1166 if (GetName() == name
)
1169 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1171 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1172 ctConfiguration
* found
= child
->FindConfiguration(name
);
1179 /// Find the next sibling
1180 ctConfiguration
* ctConfiguration::FindNextSibling()
1184 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1185 if (node
&& node
->GetNext())
1187 return (ctConfiguration
*) node
->GetNext()->GetData();
1192 /// Find the previous sibling
1193 ctConfiguration
* ctConfiguration::FindPreviousSibling()
1197 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1198 if (node
&& node
->GetPrevious())
1200 return (ctConfiguration
*) node
->GetPrevious()->GetData();
1205 /// Create a clone of this and children
1206 ctConfiguration
* ctConfiguration::DeepClone()
1208 ctConfiguration
* newItem
= Clone();
1210 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1212 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1213 ctConfiguration
* newChild
= child
->DeepClone();
1214 newItem
->AddChild(newChild
);
1219 /// Detach: remove from parent, and remove tree items
1220 void ctConfiguration::Detach()
1224 GetParent()->RemoveChild(this);
1226 GetDocument()->SetTopItem(NULL
);
1230 wxTreeItemId treeItem = GetTreeItemId();
1234 // Will delete the branch, but not the config items.
1235 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
1239 /// Hide from tree: make sure tree deletions won't delete
1240 /// the config items
1241 void ctConfiguration::DetachFromTree()
1244 wxTreeItemId item = GetTreeItemId();
1247 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
1248 data->SetConfigItem(NULL);
1249 m_treeItemId = wxTreeItemId();
1251 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
1253 ctConfiguration* child = (ctConfiguration*) node->GetData();
1254 child->DetachFromTree();