1 /////////////////////////////////////////////////////////////////////////////
2 // Name: configtooldoc.h
3 // Purpose: Document class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/process.h"
22 #include "wx/mimetype.h"
23 #include "wx/process.h"
27 #include "wx/textfile.h"
28 #include "wx/txtstrm.h"
29 #include "wx/wfstream.h"
30 #include "wx/config.h"
31 #include "configtooldoc.h"
32 #include "configtoolview.h"
33 #include "configtree.h"
34 #include "mainframe.h"
36 #include "wxconfigtool.h"
37 #include "htmlparser.h"
39 IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc
, wxDocument
)
42 ctConfigToolDoc::ctConfigToolDoc()
45 m_clipboardItem
= NULL
;
49 ctConfigToolDoc::~ctConfigToolDoc()
53 if (GetCommandProcessor())
54 GetCommandProcessor()->SetEditMenu(NULL
);
57 // Delete all the items not already deleted
58 void ctConfigToolDoc::DeleteItems()
65 /// Clears the clipboard item.
66 void ctConfigToolDoc::ClearClipboard()
69 delete m_clipboardItem
;
70 m_clipboardItem
= NULL
;
73 /// Sets the clipboard item.
74 void ctConfigToolDoc::SetClipboardItem(ctConfigItem
* item
)
77 delete m_clipboardItem
;
78 m_clipboardItem
= item
;
82 // Closes and clears the document
83 bool ctConfigToolDoc::OnCloseDocument()
85 if (wxDocument::OnCloseDocument())
87 ctConfigToolHint
hint(NULL
, ctClear
);
88 UpdateAllViews (NULL
, & hint
);
100 bool ctConfigToolDoc::Save()
102 if (!IsModified() && m_savedYet
) return true;
104 bool ret
= (m_documentFile
.empty() || !m_savedYet
) ?
106 OnSaveDocument(m_documentFile
);
108 SetDocumentSaved(true);
112 // Create the document
113 bool ctConfigToolDoc::OnCreate(const wxString
& path
, long flags
)
115 GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
116 GetCommandProcessor()->Initialize();
117 GetCommandProcessor()->ClearCommands();
119 // wxGetApp().m_currentDoc = this;
121 if (flags
& wxDOC_NEW
)
123 ctConfigItem
* rootItem
= new ctConfigItem(NULL
, ctTypeGroup
, _T("Configuration"));
124 //rootItem->InitProperties();
125 rootItem
->GetProperties().AddProperty(
127 wxT("The item description."),
128 wxVariant(wxEmptyString
, wxT("description")),
131 rootItem
->SetPropertyString(_T("description"),
132 _T("<B>This is the top-level configuration item.</B>"));
135 SetTopItem(rootItem
);
138 SetDocumentSaved(false);
140 wxString
rootName(wxT("untitled"));
141 wxStripExtension(rootName
);
142 SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName
));
145 // Creates the view, so do any view updating after this
146 bool success
= wxDocument::OnCreate(path
, flags
);
150 if (flags
& wxDOC_NEW
)
154 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
155 UpdateAllViews (NULL
, & hint
);
157 SetFilename(GetFilename(), true);
164 bool ctConfigToolDoc::OnSaveDocument(const wxString
& filename
)
168 const wxString
strOldPath(GetFilename());
170 // Do some backing up first
172 // This is the backup filename
173 wxString
backupFilename(filename
);
174 backupFilename
+= wxT(".bak");
176 // This is the temporary copy of the backup
177 wxString
tempFilename(filename
);
178 tempFilename
+= wxT(".tmp");
179 if (wxFileExists(tempFilename
))
180 wxRemoveFile(tempFilename
);
182 bool leaveBackup
= true;
184 bool saved
= DoSave(tempFilename
);
188 // Remove the old .bak file
189 if (wxFileExists(backupFilename
))
191 wxRemoveFile(backupFilename
);
194 // Copy the old file to the .bak
198 if (wxFileExists(filename
))
200 if (!wxRenameFile(filename
, backupFilename
))
202 wxCopyFile(filename
, backupFilename
);
203 wxRemoveFile(filename
);
209 if (wxFileExists(filename
))
210 wxRemoveFile(filename
);
213 // Finally, copy the temporary file to the proper filename
214 if (!wxRenameFile(tempFilename
, filename
))
216 wxCopyFile(tempFilename
, filename
);
217 wxRemoveFile(tempFilename
);
221 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
222 SetDocumentSaved(true);
223 SetFilename(filename
);
224 wxGetApp().GetSettings().m_lastFilename
= filename
;
227 SetFilename(strOldPath
);
229 wxGetApp().GetMainFrame()->UpdateFrameTitle();
234 bool ctConfigToolDoc::OnOpenDocument(const wxString
& filename
)
238 bool opened
= DoOpen(filename
);
242 SetFilename(filename
);
243 wxGetApp().GetSettings().m_lastFilename
= filename
;
245 ((ctConfigToolView
*)GetFirstView())->OnChangeFilename();
247 RefreshDependencies();
249 // ctConfigToolHint hint(NULL, ctFilenameChanged);
250 ctConfigToolHint
hint(NULL
, ctInitialUpdate
);
251 UpdateAllViews (NULL
, & hint
);
254 SetDocumentSaved(true); // Necessary or it will pop up the Save As dialog
259 /// Save the settings file
260 bool ctConfigToolDoc::DoSave(const wxString
& filename
)
262 wxFileOutputStream
osFile(filename
);
266 wxTextOutputStream
stream(osFile
);
268 stream
<< wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
269 stream
<< wxT("<settings xmlns=\"http://www.wxwidgets.org/wxs\" version=\"2.5.0.1\">");
271 DoSave(m_topItem
, osFile
, 1);
273 stream
<< wxT("\n</settings>\n");
278 inline static void OutputIndentation(wxOutputStream
& osFile
, int indent
)
280 wxTextOutputStream
stream(osFile
);
281 wxString str
= wxT("\n");
282 for (int i
= 0; i
< indent
; i
++)
287 /// Recursive helper function for file saving
288 bool ctConfigToolDoc::DoSave(ctConfigItem
* item
, wxOutputStream
& osFile
, int indent
)
290 OutputIndentation(osFile
, indent
*2);
291 wxTextOutputStream
stream(osFile
);
293 wxString
name(item
->GetName());
296 if (item
->GetType() == ctTypeGroup
)
297 typeStr
= wxT("group");
298 else if (item
->GetType() == ctTypeCheckGroup
)
299 typeStr
= wxT("check-group");
300 else if (item
->GetType() == ctTypeRadioGroup
)
301 typeStr
= wxT("radio-group");
302 else if (item
->GetType() == ctTypeString
)
303 typeStr
= wxT("string");
304 else if (item
->GetType() == ctTypeBoolCheck
)
305 typeStr
= wxT("bool-check");
306 else if (item
->GetType() == ctTypeBoolRadio
)
307 typeStr
= wxT("bool-radio");
308 else if (item
->GetType() == ctTypeInteger
)
309 typeStr
= wxT("integer");
311 typeStr
= wxT("unknown");
313 stream
<< wxT("<setting type=\"") << typeStr
<< wxT("\">");
317 OutputIndentation(osFile
, indent
*2);
318 if (item
->IsActive())
319 stream
<< wxT("<active>1</active>");
321 stream
<< wxT("<active>0</active>");
322 OutputIndentation(osFile
, indent
*2);
323 if (item
->IsEnabled())
324 stream
<< wxT("<enabled>1</enabled>");
326 stream
<< wxT("<enabled>0</enabled>");
329 wxObjectList::compatibility_iterator node
= item
->GetProperties().GetList().GetFirst();
332 ctProperty
* prop
= (ctProperty
*) node
->GetData();
333 OutputIndentation(osFile
, indent
*2);
334 stream
<< wxT("<") << prop
->GetName() ;
336 if (prop
->IsCustom())
338 stream
<< wxT(" custom=\"true\"");
339 stream
<< wxT(" type=\"") << prop
->GetVariant().GetType() << wxT("\"");
340 stream
<< wxT(" editor-type=\"") << prop
->GetEditorType() << wxT("\"");
341 stream
<< wxT(" description=\"") << prop
->GetDescription() << wxT("\"");
342 if (prop
->GetChoices().GetCount() > 0)
345 ctConfigItem::ArrayToString(prop
->GetChoices(), choices
);
346 stream
<< wxT(" choices=\"") << choices
<< wxT("\"");
352 stream
<< ctEscapeHTMLCharacters(prop
->GetVariant().GetString()) ;
353 stream
<< wxT("</") << prop
->GetName() << wxT(">");
355 node
= node
->GetNext();
359 node
= item
->GetChildren().GetFirst();
362 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
363 DoSave(child
, osFile
, indent
);
365 node
= node
->GetNext();
370 OutputIndentation(osFile
, indent
*2);
371 stream
<< wxT("</setting>");
376 /// Open the settings file
377 bool ctConfigToolDoc::DoOpen(const wxString
& filename
)
379 wxSimpleHtmlParser parser
;
380 if (parser
.ParseFile(filename
))
382 ctConfigToolHint
hint(NULL
, ctClear
);
383 UpdateAllViews (NULL
, & hint
);
386 if (parser
.GetTopLevelTag()->GetChildren())
388 wxSimpleHtmlTag
* settingsTag
= parser
.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
389 if (settingsTag
&& settingsTag
->GetChildren())
391 wxSimpleHtmlTag
* firstSettingTag
= settingsTag
->GetChildren();
393 DoOpen(firstSettingTag
, NULL
);
402 static bool GetHtmlBoolValue(const wxString
& value
)
404 if (value
.IsSameAs(wxT("true"),false) || value
== wxT("1"))
410 static int GetHtmlIntegerValue(const wxString
& value
)
412 return wxAtoi(value
);
415 static double GetHtmlDoubleValue(const wxString
& value
)
417 return wxAtof(value
);
420 bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag
* tag
, ctConfigItem
* parent
)
422 ctConfigItem
* newItem
= NULL
;
423 if (tag
->NameIs(wxT("setting")))
425 wxSimpleHtmlAttribute
* attr
= tag
->FindAttribute(wxT("type"));
428 ctConfigType type
= ctTypeUnknown
;
429 wxString
typeStr(attr
->GetValue());
430 if (typeStr
== wxT("group"))
432 else if (typeStr
== wxT("option-group") || typeStr
== wxT("check-group"))
433 type
= ctTypeCheckGroup
;
434 else if (typeStr
== wxT("radio-group"))
435 type
= ctTypeRadioGroup
;
436 else if (typeStr
== wxT("bool-check"))
437 type
= ctTypeBoolCheck
;
438 else if (typeStr
== wxT("bool-radio"))
439 type
= ctTypeBoolRadio
;
440 else if (typeStr
== wxT("string"))
442 else if (typeStr
== wxT("integer"))
443 type
= ctTypeInteger
;
446 wxLogError(wxT("Unknown type %s"), (const wxChar
*) typeStr
);
448 if (type
!= ctTypeUnknown
)
450 newItem
= new ctConfigItem(parent
, type
, wxT(""));
451 newItem
->InitProperties();
457 wxSimpleHtmlTag
* childTag
= tag
->GetChildren();
461 if (childTag
->GetType() == wxSimpleHtmlTag_Open
)
463 if (childTag
->GetName() == wxT("setting"))
465 DoOpen(childTag
, newItem
);
467 else if (childTag
->GetName() == wxT("name"))
471 wxString
name(childTag
->GetNext()->GetTagText());
472 newItem
->SetName(name
);
475 else if (childTag
->GetName() == wxT("active"))
478 newItem
->SetActive(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
480 else if (childTag
->GetName() == wxT("enabled"))
483 newItem
->Enable(GetHtmlBoolValue(childTag
->GetNext()->GetTagText()));
489 ctProperty
* prop
= newItem
->GetProperties().FindProperty(childTag
->GetName());
492 // A custom property, else an obsolete
493 // property that we should ignore.
495 if (childTag
->GetAttributeValue(isCustom
, wxT("custom")) &&
496 isCustom
== wxT("true"))
498 prop
= new ctProperty
;
500 wxString
name(childTag
->GetName());
501 wxString
type(wxT("string"));
503 wxString
editorType(wxT("string"));
504 wxString description
;
505 childTag
->GetAttributeValue(type
, wxT("type"));
506 childTag
->GetAttributeValue(type
, wxT("editor-type"));
507 childTag
->GetAttributeValue(type
, wxT("choices"));
508 childTag
->GetAttributeValue(description
, wxT("description"));
510 if (type
== wxT("bool"))
511 prop
->GetVariant() = wxVariant(false, name
);
512 else if (type
== wxT("double"))
513 prop
->GetVariant() = wxVariant((double) 0.0, name
);
514 else if (type
== wxT("long"))
515 prop
->GetVariant() = wxVariant((long) 0, name
);
517 prop
->GetVariant() = wxVariant(wxEmptyString
, name
);
518 prop
->SetDescription(description
);
519 prop
->SetCustom(true);
520 prop
->SetEditorType(editorType
);
521 if (!choices
.IsEmpty())
524 ctConfigItem::StringToArray(choices
, arr
);
525 prop
->SetChoices(arr
);
527 newItem
->GetProperties().AddProperty(prop
);
532 if (prop
->GetVariant().GetType() == wxT("string"))
533 prop
->GetVariant() = childTag
->GetNext()->GetTagText();
534 else if (prop
->GetVariant().GetType() == wxT("long"))
535 prop
->GetVariant() = (long) GetHtmlIntegerValue(childTag
->GetNext()->GetTagText());
536 else if (prop
->GetVariant().GetType() == wxT("bool"))
537 prop
->GetVariant() = GetHtmlBoolValue(childTag
->GetNext()->GetTagText());
538 else if (prop
->GetVariant().GetType() == wxT("double"))
539 prop
->GetVariant() = (double) GetHtmlDoubleValue(childTag
->GetNext()->GetTagText());
544 childTag
= childTag
->GetNext();
549 /// Clear dependencies
550 void ctConfigToolDoc::ClearDependencies(ctConfigItem
* item
)
558 item
->GetDependents().Clear();
559 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
561 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
562 ClearDependencies(child
);
566 /// Refresh dependencies
567 void ctConfigToolDoc::RefreshDependencies()
569 ClearDependencies(GetTopItem());
570 RefreshDependencies(GetTopItem());
573 /// Refresh dependencies
574 void ctConfigToolDoc::RefreshDependencies(ctConfigItem
* item
)
579 wxArrayString requiresArr
;
580 wxString
requires = item
->GetPropertyString(wxT("requires"));
581 wxString precludes
= item
->GetPropertyString(wxT("precludes"));
582 wxString enabledIf
= item
->GetPropertyString(wxT("enabled-if"));
583 wxString enabledIfNot
= item
->GetPropertyString(wxT("enabled-if-not"));
584 wxString indeterminateIf
= item
->GetPropertyString(wxT("indeterminate-if"));
585 wxString context
= item
->GetPropertyString(wxT("context"));
587 if (!requires.IsEmpty())
588 item
->StringToArray(requires, requiresArr
);
590 if (!precludes
.IsEmpty())
591 item
->StringToArray(precludes
, requiresArr
);
593 if (!enabledIfNot
.IsEmpty())
594 item
->StringToArray(enabledIfNot
, requiresArr
);
596 if (!enabledIf
.IsEmpty())
597 item
->StringToArray(enabledIf
, requiresArr
);
599 if (!indeterminateIf
.IsEmpty())
600 item
->StringToArray(indeterminateIf
, requiresArr
);
602 // Add the parent to the list of dependencies, if the
603 // parent is a check or radio group.
604 ctConfigItem
* parent
= item
->GetParent();
606 (parent
->GetType() == ctTypeCheckGroup
||
607 parent
->GetType() == ctTypeRadioGroup
))
608 requiresArr
.Add(parent
->GetName());
610 // Also look in 'context' since these items
611 // are another kind of dependency (switching to
612 // a different platform may cause the dependencies
613 // to be evaluated differently).
614 if (!context
.IsEmpty())
615 item
->StringToArray(context
, requiresArr
);
618 for (i
= 0; i
< requiresArr
.GetCount(); i
++)
620 wxString
itemName(requiresArr
[i
]);
621 ctConfigItem
* otherItem
= GetTopItem()->FindItem(itemName
);
622 if (otherItem
&& !otherItem
->GetDependents().Member(item
))
624 otherItem
->GetDependents().Append(item
);
627 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
629 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
630 RefreshDependencies(child
);
634 /// Generate the text of a setup.h
635 wxString
ctConfigToolDoc::GenerateSetup()
638 str
<< wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
640 GenerateSetup(GetTopItem(), str
);
646 void ctConfigToolDoc::GenerateSetup(ctConfigItem
* item
, wxString
& str
)
648 // Generate the setup.h entries for this item
649 wxString name
= item
->GetName();
651 // We don't process the platform choice
652 if (item
->GetName() == wxT("Target"))
655 if (item
->IsInActiveContext() &&
656 (item
->GetType() == ctTypeCheckGroup
||
657 item
->GetType() == ctTypeRadioGroup
||
658 item
->GetType() == ctTypeBoolCheck
||
659 item
->GetType() == ctTypeBoolRadio
))
661 // TODO: write description
662 wxString name
= item
->GetName();
663 if (name
.Left(6) == wxT("wxUSE_") ||
664 name
== wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
665 name
.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND
)
667 str
<< wxT("#define ") << name
;
668 if (item
->IsEnabled())
676 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
678 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
679 GenerateSetup(child
, str
);
684 /// Generate a configure command
685 wxString
ctConfigToolDoc::GenerateConfigureCommand()
688 str
<< wxT("# configurewx\n# Generated by wxConfigTool\n\n");
690 wxString path
= GetFrameworkDir(true);
691 bool makeUnix
= true;
697 path
+= wxFILE_SEP_PATH
;
700 str
<< path
<< wxT("configure");
702 // Find the target to use
703 ctConfigItem
* platformsFolder
= GetTopItem()->FindItem(wxT("Target"));
706 for ( wxObjectList::compatibility_iterator node
= platformsFolder
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
708 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
709 if (child
->GetType() == ctTypeBoolRadio
&& child
->IsEnabled())
711 wxString configureCommand
= child
->GetPropertyString(wxT("configure-command"));
712 if (!configureCommand
.IsEmpty())
713 str
<< wxT(" ") << configureCommand
;
718 GenerateConfigureCommand(GetTopItem(), str
);
723 void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem
* item
, wxString
& str
)
725 // We don't process the platform group, since we've
727 if (item
->GetName() == wxT("Target"))
730 if (item
->IsInActiveContext() &&
731 (item
->GetType() == ctTypeCheckGroup
||
732 item
->GetType() == ctTypeRadioGroup
||
733 item
->GetType() == ctTypeBoolCheck
||
734 item
->GetType() == ctTypeBoolRadio
))
736 wxString name
= item
->GetName();
737 wxString configureCommand
= item
->GetPropertyString(wxT("configure-command"));
738 if (!configureCommand
.IsEmpty())
740 if (!item
->IsEnabled())
742 // Replace 'enable' with 'disable' if this
744 configureCommand
.Replace(wxT("--enable-"), wxT("--disable-"));
745 configureCommand
.Replace(wxT("--with-"), wxT("--without-"));
747 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("builtin"));
748 if (prop
&& prop
->GetVariant().GetType() == wxT("bool"))
750 bool builtin
= prop
->GetVariant().GetBool();
751 str
<< wxT(" ") << configureCommand
;
753 str
<< wxT("=builtin");
759 ctProperty
* prop
= item
->GetProperties().FindProperty(wxT("value"));
760 if (prop
&& prop
->GetVariant().GetType() == wxT("string"))
762 wxString val
= prop
->GetVariant().GetString();
763 if (item
->IsEnabled() && !val
.IsEmpty())
765 str
<< wxT(" ") << configureCommand
;
766 str
<< wxT("=\"") << val
<< wxT("\"");
768 // If the string is empty, ignore this parameter,
769 // since it's obviously intended to be supplied
770 // only if there's a string to use and it's enabled.
774 str
<< wxT(" ") << configureCommand
;
780 for ( wxObjectList::compatibility_iterator node
= item
->GetChildren().GetFirst(); node
; node
= node
->GetNext() )
782 ctConfigItem
* child
= (ctConfigItem
*) node
->GetData();
783 GenerateConfigureCommand(child
, str
);
787 /// Gets the current framework directory
788 wxString
ctConfigToolDoc::GetFrameworkDir(bool makeUnix
)
790 wxString path
= wxGetApp().GetSettings().m_frameworkDir
;
791 if (wxGetApp().GetSettings().m_useEnvironmentVariable
)
793 // Should probably allow other variables
794 // to be used, and maybe expand variables within m_frameworkDir
795 wxString
pathEnv(wxGetenv(wxT("WXWIN")));
799 path
.Replace(wxT("\\"), wxT("/"));
801 wxUnusedVar(makeUnix
);
807 /// Finds the next item in the tree
808 ctConfigItem
* ctConfigToolDoc::FindNextItem(ctConfigItem
* item
, bool wrap
)
813 // First, try to find the first child
814 if (item
->GetChildCount() > 0)
816 return item
->GetChild(0);
820 ctConfigItem
* p
= item
;
823 ctConfigItem
* toFind
= FindNextSibling(p
);
830 // Finally, wrap around to the root.
837 /// Finds the next sibling in the tree
838 ctConfigItem
* ctConfigToolDoc::FindNextSibling(ctConfigItem
* item
)
840 if (item
->GetParent())
842 wxObjectList::compatibility_iterator node
= item
->GetParent()->GetChildren().Member(item
);
843 if (node
&& node
->GetNext())
845 ctConfigItem
* nextItem
= (ctConfigItem
*) node
->GetNext()->GetData();
854 * Implements a document editing command.
857 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
858 ctConfigItem
* activeState
, ctConfigItem
* savedState
,
859 ctConfigItem
* parent
, ctConfigItem
* insertBefore
,
860 bool ignoreFirstTime
): wxCommand(true, name
)
862 m_activeState
= activeState
;
863 m_savedState
= savedState
;
864 m_ignoreThis
= ignoreFirstTime
;
868 m_insertBefore
= insertBefore
;
871 ctConfigCommand::ctConfigCommand(const wxString
& name
, int cmdId
,
872 ctConfigItem
* activeState
, ctProperties
* properties
,
873 bool ignoreFirstTime
): wxCommand(true, name
)
875 m_activeState
= activeState
;
877 m_properties
= properties
;
878 m_ignoreThis
= ignoreFirstTime
;
880 m_properties
= properties
;
882 m_insertBefore
= NULL
;
885 ctConfigCommand::~ctConfigCommand()
893 bool ctConfigCommand::Do()
895 return DoAndUndo(true);
898 bool ctConfigCommand::Undo()
900 return DoAndUndo(false);
903 // Combine Do and Undo into one
904 bool ctConfigCommand::DoAndUndo(bool doCmd
)
912 wxASSERT(m_savedState
== NULL
);
913 wxASSERT(m_activeState
!= NULL
);
915 ctConfigItem
* newItem
= m_activeState
->DeepClone();
916 ctConfigToolDoc
* doc
= m_activeState
->GetDocument();
918 // This will delete the old clipboard contents, if any.
919 doc
->SetClipboardItem(newItem
);
921 m_parent
= m_activeState
->GetParent();
922 m_insertBefore
= m_activeState
->FindNextSibling();
924 m_activeState
->Detach();
925 m_savedState
= m_activeState
;
926 m_activeState
= NULL
;
928 m_savedState
->GetDocument()->Modify(true);
929 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
930 view
->OnChangeFilename();
934 wxASSERT(m_savedState
!= NULL
);
935 wxASSERT(m_activeState
== NULL
);
937 m_savedState
->GetDocument()->Modify(true);
938 m_savedState
->Attach(m_parent
, m_insertBefore
);
939 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
940 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
941 m_activeState
= m_savedState
;
944 m_insertBefore
= NULL
;
945 view
->OnChangeFilename();
953 wxASSERT(m_savedState
!= NULL
);
954 wxASSERT(m_activeState
== NULL
);
956 m_savedState
->GetDocument()->Modify(true);
957 m_savedState
->Attach(m_parent
, m_insertBefore
);
958 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
959 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
960 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
961 m_activeState
= m_savedState
;
963 view
->OnChangeFilename();
967 wxASSERT(m_savedState
== NULL
);
968 wxASSERT(m_activeState
!= NULL
);
970 m_activeState
->GetDocument()->Modify(true);
971 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
972 m_activeState
->Detach();
973 m_savedState
= m_activeState
;
974 m_activeState
= NULL
;
975 view
->OnChangeFilename();
979 case ctCMD_NEW_ELEMENT
:
983 wxASSERT(m_savedState
!= NULL
);
984 wxASSERT(m_activeState
== NULL
);
986 m_savedState
->GetDocument()->Modify(true);
987 m_savedState
->Attach(m_parent
, m_insertBefore
);
988 ctConfigToolView
* view
= (ctConfigToolView
*) m_savedState
->GetDocument()->GetFirstView();
989 view
->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState
);
990 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState
->GetTreeItemId());
992 m_activeState
= m_savedState
;
997 wxASSERT(m_savedState
== NULL
);
998 wxASSERT(m_activeState
!= NULL
);
1000 m_activeState
->GetDocument()->Modify(true);
1001 m_activeState
->Detach();
1002 m_savedState
= m_activeState
;
1003 m_activeState
= NULL
;
1007 case ctCMD_APPLY_PROPERTY
:
1009 wxASSERT(m_properties
!= NULL
);
1010 wxASSERT(m_activeState
!= NULL
);
1012 // Don't update the properties editor first time
1013 // around since it will be done one property at a time
1014 // initially (and no property editor update required)
1017 // Just swap the saved and current properties.
1018 ctProperties propsTemp
= m_activeState
->GetProperties() ;
1019 m_activeState
->GetProperties() = (* m_properties
);
1020 (* m_properties
) = propsTemp
;
1022 // Apply only those that need applying
1023 // (those properties in activeState that are not in propsTemp)
1024 wxObjectList::compatibility_iterator node
= m_activeState
->GetProperties().GetList().GetFirst();
1027 ctProperty
* prop
= (ctProperty
*) node
->GetData();
1028 ctProperty
* otherProp
= propsTemp
.FindProperty(prop
->GetName());
1029 if (otherProp
&& ((*prop
) != (*otherProp
)))
1031 m_activeState
->ApplyProperty(prop
, otherProp
->GetVariant());
1033 node
= node
->GetNext();
1035 m_activeState
->GetDocument()->Modify(true);
1036 ctConfigToolView
* view
= (ctConfigToolView
*) m_activeState
->GetDocument()->GetFirstView();
1039 ctConfigToolHint
hint(NULL
, ctValueChanged
);
1040 m_activeState
->GetDocument()->UpdateAllViews (NULL
, & hint
);
1043 m_ignoreThis
= false;
1051 IMPLEMENT_CLASS(ctConfiguration
, wxObject
)
1053 ctConfiguration::ctConfiguration()
1055 m_treeItemId
= wxTreeItemId();
1060 ctConfiguration::ctConfiguration(ctConfiguration
* parent
, const wxString
& name
)
1062 m_treeItemId
= wxTreeItemId();
1066 parent
->AddChild(this);
1069 ctConfiguration::~ctConfiguration()
1072 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
1073 if (m_treeItemId.IsOk() && treeCtrl)
1075 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
1077 data->SetConfigItem(NULL);
1080 GetParent()->RemoveChild(this);
1083 if (wxGetApp().GetMainFrame()->GetDocument() &&
1084 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
1085 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
1092 /// Assignment operator.
1093 void ctConfiguration::operator= (const ctConfiguration
& configuration
)
1095 m_name
= configuration
.m_name
;
1096 m_description
= configuration
.m_description
;
1100 void ctConfiguration::Clear()
1102 wxObjectList::compatibility_iterator node
= m_children
.GetFirst();
1105 wxObjectList::compatibility_iterator next
= node
->GetNext();
1106 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1108 // This should delete 'node' too, assuming
1109 // child's m_parent points to 'this'. If not,
1110 // it'll be cleaned up by m_children.Clear().
1118 // Get the nth child
1119 ctConfiguration
* ctConfiguration::GetChild(int n
) const
1121 wxASSERT ( n
< GetChildCount() && n
> -1 );
1123 if ( n
< GetChildCount() && n
> -1 )
1125 ctConfiguration
* child
= wxDynamicCast(m_children
.Item(n
)->GetData(), ctConfiguration
);
1132 // Get the child count
1133 int ctConfiguration::GetChildCount() const
1135 return m_children
.GetCount();
1139 void ctConfiguration::AddChild(ctConfiguration
* configuration
)
1141 m_children
.Append(configuration
);
1142 configuration
->SetParent(this);
1145 /// Remove (but don't delete) a child
1146 void ctConfiguration::RemoveChild(ctConfiguration
* configuration
)
1148 m_children
.DeleteObject(configuration
);
1149 configuration
->SetParent(NULL
);
1152 /// Get the associated document (currently, assumes
1153 /// there's only ever one document active)
1154 ctConfigToolDoc
* ctConfiguration::GetDocument()
1156 ctConfigToolDoc
* doc
= wxGetApp().GetMainFrame()->GetDocument();
1160 /// Find an item in this hierarchy
1161 // TODO: ensure that names are unique, somehow.
1162 ctConfiguration
* ctConfiguration::FindConfiguration(const wxString
& name
)
1164 if (GetName() == name
)
1167 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1169 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1170 ctConfiguration
* found
= child
->FindConfiguration(name
);
1177 /// Find the next sibling
1178 ctConfiguration
* ctConfiguration::FindNextSibling()
1182 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1183 if (node
&& node
->GetNext())
1185 return (ctConfiguration
*) node
->GetNext()->GetData();
1190 /// Find the previous sibling
1191 ctConfiguration
* ctConfiguration::FindPreviousSibling()
1195 wxObjectList::compatibility_iterator node
= GetParent()->GetChildren().Member(this);
1196 if (node
&& node
->GetPrevious())
1198 return (ctConfiguration
*) node
->GetPrevious()->GetData();
1203 /// Create a clone of this and children
1204 ctConfiguration
* ctConfiguration::DeepClone()
1206 ctConfiguration
* newItem
= Clone();
1208 for ( wxObjectList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext() )
1210 ctConfiguration
* child
= (ctConfiguration
*) node
->GetData();
1211 ctConfiguration
* newChild
= child
->DeepClone();
1212 newItem
->AddChild(newChild
);
1217 /// Detach: remove from parent, and remove tree items
1218 void ctConfiguration::Detach()
1222 GetParent()->RemoveChild(this);
1224 GetDocument()->SetTopItem(NULL
);
1228 wxTreeItemId treeItem = GetTreeItemId();
1232 // Will delete the branch, but not the config items.
1233 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
1237 /// Hide from tree: make sure tree deletions won't delete
1238 /// the config items
1239 void ctConfiguration::DetachFromTree()
1242 wxTreeItemId item = GetTreeItemId();
1245 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
1246 data->SetConfigItem(NULL);
1247 m_treeItemId = wxTreeItemId();
1249 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
1251 ctConfiguration* child = (ctConfiguration*) node->GetData();
1252 child->DetachFromTree();