]> git.saurik.com Git - wxWidgets.git/blame - utils/configtool/src/configtooldoc.cpp
MinGW warning fixes. Source cleaning. Stock items.
[wxWidgets.git] / utils / configtool / src / configtooldoc.cpp
CommitLineData
d7463f75
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: configtooldoc.h
3// Purpose: Document class
4// Author: Julian Smart
5// Modified by:
6// Created: 2003-06-04
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence:
10/////////////////////////////////////////////////////////////////////////////
11
71ada1a5 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
d7463f75
JS
13#pragma implementation "configtooldoc.h"
14#endif
15
d9ab621e
WS
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
d7463f75
JS
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
d9ab621e
WS
23#ifndef WX_PRECOMP
24
d7463f75
JS
25#include "wx/process.h"
26#include "wx/mimetype.h"
27#include "wx/process.h"
d7463f75 28
d7463f75
JS
29#endif
30
d9ab621e
WS
31#include "wx/textfile.h"
32#include "wx/wfstream.h"
33#include "wx/config.h"
d7463f75
JS
34#include "configtooldoc.h"
35#include "configtoolview.h"
36#include "configtree.h"
37#include "mainframe.h"
38#include "utils.h"
39#include "wxconfigtool.h"
40#include "htmlparser.h"
41
42IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc, wxDocument)
43
44// Ctor
45ctConfigToolDoc::ctConfigToolDoc()
46{
47 m_topItem = NULL;
48 m_clipboardItem = NULL;
49}
50
51// Dtor
52ctConfigToolDoc::~ctConfigToolDoc()
53{
54 DeleteItems();
55 ClearClipboard();
56 if (GetCommandProcessor())
57 GetCommandProcessor()->SetEditMenu(NULL);
58}
59
60// Delete all the items not already deleted
61void ctConfigToolDoc::DeleteItems()
62{
63 if (m_topItem)
64 delete m_topItem;
65 m_topItem = NULL;
66}
67
68/// Clears the clipboard item.
69void ctConfigToolDoc::ClearClipboard()
70{
71 if (m_clipboardItem)
72 delete m_clipboardItem;
73 m_clipboardItem = NULL;
74}
75
76/// Sets the clipboard item.
77void ctConfigToolDoc::SetClipboardItem(ctConfigItem* item)
78{
79 if (m_clipboardItem)
80 delete m_clipboardItem;
81 m_clipboardItem = item;
82}
83
84
85// Closes and clears the document
86bool ctConfigToolDoc::OnCloseDocument()
87{
88 if (wxDocument::OnCloseDocument())
89 {
90 ctConfigToolHint hint(NULL, ctClear);
91 UpdateAllViews (NULL, & hint);
92
93 DeleteItems();
4fe30bce 94 return true;
d7463f75
JS
95 }
96 else
97 {
4fe30bce 98 return false;
d7463f75
JS
99 }
100}
101
102// Saves the doc
103bool ctConfigToolDoc::Save()
104{
4fe30bce 105 if (!IsModified() && m_savedYet) return true;
79830320
JS
106
107 bool ret = (m_documentFile == wxT("") || !m_savedYet) ?
108 SaveAs() :
109 OnSaveDocument(m_documentFile);
d7463f75 110 if ( ret )
4fe30bce 111 SetDocumentSaved(true);
d7463f75
JS
112 return ret;
113}
114
115// Create the document
116bool ctConfigToolDoc::OnCreate(const wxString& path, long flags)
117{
118 GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
119 GetCommandProcessor()->Initialize();
120 GetCommandProcessor()->ClearCommands();
121
122 // wxGetApp().m_currentDoc = this;
123
124 if (flags & wxDOC_NEW)
125 {
126 ctConfigItem* rootItem = new ctConfigItem(NULL, ctTypeGroup, _T("Configuration"));
127 //rootItem->InitProperties();
128 rootItem->GetProperties().AddProperty(
129 new ctProperty(
130 wxT("The item description."),
131 wxVariant(wxT(""), wxT("description")),
132 wxT("multiline")));
133
134 rootItem->SetPropertyString(_T("description"),
135 _T("<B>This is the top-level configuration item.</B>"));
136
137
138 SetTopItem(rootItem);
139
4fe30bce
WS
140 Modify(false);
141 SetDocumentSaved(false);
d7463f75
JS
142
143 wxString rootName(wxT("untitled"));
144 wxStripExtension(rootName);
145 SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName));
146 }
147
148 // Creates the view, so do any view updating after this
149 bool success = wxDocument::OnCreate(path, flags);
150
151 if (success)
152 {
153 if (flags & wxDOC_NEW)
154 {
155 wxBusyCursor wait;
156
157 ctConfigToolHint hint(NULL, ctInitialUpdate);
158 UpdateAllViews (NULL, & hint);
159
4fe30bce 160 SetFilename(GetFilename(), true);
d7463f75
JS
161 }
162 }
163 return success;
164}
165
166// Save the document
167bool ctConfigToolDoc::OnSaveDocument(const wxString& filename)
168{
169 wxBusyCursor cursor;
170
171 const wxString strOldPath(GetFilename());
172
173 // Do some backing up first
174
175 // This is the backup filename
176 wxString backupFilename(filename);
177 backupFilename += wxT(".bak");
178
179 // This is the temporary copy of the backup
180 wxString tempFilename(filename);
181 tempFilename += wxT(".tmp");
182 if (wxFileExists(tempFilename))
183 wxRemoveFile(tempFilename);
184
4fe30bce 185 bool leaveBackup = true;
d7463f75
JS
186
187 bool saved = DoSave(tempFilename);
188
189 if (saved)
190 {
191 // Remove the old .bak file
192 if (wxFileExists(backupFilename))
193 {
194 wxRemoveFile(backupFilename);
195 }
196
197 // Copy the old file to the .bak
198
199 if (leaveBackup)
200 {
201 if (wxFileExists(filename))
202 {
203 if (!wxRenameFile(filename, backupFilename))
204 {
205 wxCopyFile(filename, backupFilename);
206 wxRemoveFile(filename);
207 }
208 }
209 }
210 else
211 {
212 if (wxFileExists(filename))
213 wxRemoveFile(filename);
214 }
215
216 // Finally, copy the temporary file to the proper filename
217 if (!wxRenameFile(tempFilename, filename))
218 {
219 wxCopyFile(tempFilename, filename);
220 wxRemoveFile(tempFilename);
221 }
222
4fe30bce 223 Modify(false);
d7463f75 224 ((ctConfigToolView*)GetFirstView())->OnChangeFilename();
4fe30bce 225 SetDocumentSaved(true);
d7463f75
JS
226 SetFilename(filename);
227 wxGetApp().GetSettings().m_lastFilename = filename;
228 } else
229 {
230 SetFilename(strOldPath);
231 }
232 wxGetApp().GetMainFrame()->UpdateFrameTitle();
233 return saved;
234}
235
236// Open the document
237bool ctConfigToolDoc::OnOpenDocument(const wxString& filename)
238{
239 wxBusyCursor cursor;
240
241 bool opened = DoOpen(filename);
242
243 if (opened)
244 {
245 SetFilename(filename);
246 wxGetApp().GetSettings().m_lastFilename = filename;
247
248 ((ctConfigToolView*)GetFirstView())->OnChangeFilename();
249
250 RefreshDependencies();
251
252 // ctConfigToolHint hint(NULL, ctFilenameChanged);
253 ctConfigToolHint hint(NULL, ctInitialUpdate);
254 UpdateAllViews (NULL, & hint);
255 }
256
4fe30bce 257 SetDocumentSaved(true); // Necessary or it will pop up the Save As dialog
d7463f75
JS
258
259 return opened;
260}
261
262/// Save the settings file
263bool ctConfigToolDoc::DoSave(const wxString& filename)
264{
265 wxFileOutputStream stream(filename);
266 if (!stream.Ok())
4fe30bce 267 return false;
d7463f75
JS
268
269 stream << wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
be5a51fb 270 stream << wxT("<settings xmlns=\"http://www.wxwidgets.org/wxs\" version=\"2.5.0.1\">");
d7463f75
JS
271
272 DoSave(m_topItem, stream, 1);
273
274 stream << wxT("\n</settings>\n");
275
4fe30bce 276 return true;
d7463f75
JS
277}
278
279inline static void OutputIndentation(wxOutputStream& stream, int indent)
280{
281 wxString str = wxT("\n");
282 for (int i = 0; i < indent; i++)
283 str << wxT(' ') << wxT(' ');
284 stream << str ;
285}
286
287/// Recursive helper function for file saving
288bool ctConfigToolDoc::DoSave(ctConfigItem* item, wxOutputStream& stream, int indent)
289{
290 OutputIndentation(stream, indent*2);
291
292 wxString name(item->GetName());
293 wxString s;
294 wxString typeStr;
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");
309 else
310 typeStr = wxT("unknown");
311
312 stream << wxT("<setting type=\"") << typeStr << wxT("\">");
313
314 indent ++;
315
316 OutputIndentation(stream, indent*2);
317 if (item->IsActive())
318 stream << wxT("<active>1</active>");
319 else
320 stream << wxT("<active>0</active>");
321 OutputIndentation(stream, indent*2);
322 if (item->IsEnabled())
323 stream << wxT("<enabled>1</enabled>");
324 else
325 stream << wxT("<enabled>0</enabled>");
326
327 // Output properties
d9ab621e 328 wxObjectList::compatibility_iterator node = item->GetProperties().GetList().GetFirst();
d7463f75
JS
329 while (node)
330 {
331 ctProperty* prop = (ctProperty*) node->GetData();
332 OutputIndentation(stream, indent*2);
333 stream << wxT("<") << prop->GetName() ;
334
335 if (prop->IsCustom())
336 {
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)
342 {
343 wxString choices;
344 ctConfigItem::ArrayToString(prop->GetChoices(), choices);
345 stream << wxT(" choices=\"") << choices << wxT("\"");
346 }
347 }
348
349 stream << wxT(">");
350
351 stream << ctEscapeHTMLCharacters(prop->GetVariant().GetString()) ;
352 stream << wxT("</") << prop->GetName() << wxT(">");
353
f8105809 354 node = node->GetNext();
d7463f75
JS
355 }
356
357 // Output children
358 node = item->GetChildren().GetFirst();
359 while (node)
360 {
361 ctConfigItem* child = (ctConfigItem*) node->GetData();
362 DoSave(child, stream, indent);
363
f8105809 364 node = node->GetNext();
d7463f75
JS
365 }
366
367 indent --;
368
369 OutputIndentation(stream, indent*2);
370 stream << wxT("</setting>");
371
4fe30bce 372 return true;
d7463f75
JS
373}
374
375/// Open the settings file
376bool ctConfigToolDoc::DoOpen(const wxString& filename)
377{
378 wxSimpleHtmlParser parser;
379 if (parser.ParseFile(filename))
380 {
381 ctConfigToolHint hint(NULL, ctClear);
382 UpdateAllViews (NULL, & hint);
383 m_topItem = NULL;
384
385 if (parser.GetTopLevelTag()->GetChildren())
386 {
387 wxSimpleHtmlTag* settingsTag = parser.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
388 if (settingsTag && settingsTag->GetChildren())
389 {
390 wxSimpleHtmlTag* firstSettingTag = settingsTag->GetChildren();
391 if (firstSettingTag)
392 DoOpen(firstSettingTag, NULL);
4fe30bce 393 return true;
d7463f75 394 }
4fe30bce 395 return true;
d7463f75
JS
396 }
397 }
4fe30bce 398 return false;
d7463f75
JS
399}
400
401static bool GetHtmlBoolValue(const wxString& value)
402{
403 if (value == wxT("true") || value == wxT("TRUE") || value == wxT("1"))
4fe30bce 404 return true;
d7463f75 405 else
4fe30bce 406 return false;
d7463f75
JS
407}
408
409static int GetHtmlIntegerValue(const wxString& value)
410{
411 return wxAtoi(value);
412}
413
414static double GetHtmlDoubleValue(const wxString& value)
415{
416 return wxAtof(value);
417}
418
419bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag* tag, ctConfigItem* parent)
420{
421 ctConfigItem* newItem = NULL;
422 if (tag->NameIs(wxT("setting")))
423 {
424 wxSimpleHtmlAttribute* attr = tag->FindAttribute(wxT("type"));
425 if (attr)
426 {
427 ctConfigType type = ctTypeUnknown;
428 wxString typeStr(attr->GetValue());
429 if (typeStr == wxT("group"))
430 type = ctTypeGroup;
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"))
440 type = ctTypeString;
441 else if (typeStr == wxT("integer"))
442 type = ctTypeInteger;
443 else
444 {
445 wxLogError(wxT("Unknown type %s"), (const wxChar*) typeStr);
446 }
447 if (type != ctTypeUnknown)
448 {
449 newItem = new ctConfigItem(parent, type, wxT(""));
450 newItem->InitProperties();
451 if (!parent)
452 SetTopItem(newItem);
453 }
454 }
455 }
456 wxSimpleHtmlTag* childTag = tag->GetChildren();
457
458 while (childTag)
459 {
460 if (childTag->GetType() == wxSimpleHtmlTag_Open)
461 {
462 if (childTag->GetName() == wxT("setting"))
463 {
464 DoOpen(childTag, newItem);
465 }
466 else if (childTag->GetName() == wxT("name"))
467 {
468 if (newItem)
469 {
470 wxString name(childTag->GetNext()->GetTagText());
471 newItem->SetName(name);
472 }
473 }
474 else if (childTag->GetName() == wxT("active"))
475 {
476 if (newItem)
477 newItem->SetActive(GetHtmlBoolValue(childTag->GetNext()->GetTagText()));
478 }
479 else if (childTag->GetName() == wxT("enabled"))
480 {
481 if (newItem)
482 newItem->Enable(GetHtmlBoolValue(childTag->GetNext()->GetTagText()));
483 }
484 else
485 {
486 if (newItem)
487 {
488 ctProperty* prop = newItem->GetProperties().FindProperty(childTag->GetName());
489 if (!prop)
490 {
491 // A custom property, else an obsolete
492 // property that we should ignore.
493 wxString isCustom;
494 if (childTag->GetAttributeValue(isCustom, wxT("custom")) &&
495 isCustom == wxT("true"))
496 {
497 prop = new ctProperty;
498
499 wxString name(childTag->GetName());
500 wxString type(wxT("string"));
501 wxString choices;
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"));
508
509 if (type == wxT("bool"))
4fe30bce 510 prop->GetVariant() = wxVariant(false, name);
d7463f75
JS
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);
515 else
516 prop->GetVariant() = wxVariant(wxT(""), name);
517 prop->SetDescription(description);
4fe30bce 518 prop->SetCustom(true);
d7463f75
JS
519 prop->SetEditorType(editorType);
520 if (!choices.IsEmpty())
521 {
522 wxArrayString arr;
523 ctConfigItem::StringToArray(choices, arr);
524 prop->SetChoices(arr);
525 }
526 newItem->GetProperties().AddProperty(prop);
527 }
528 }
529 if (prop)
530 {
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"))
4fe30bce 536 prop->GetVariant() = GetHtmlBoolValue(childTag->GetNext()->GetTagText());
d7463f75
JS
537 else if (prop->GetVariant().GetType() == wxT("double"))
538 prop->GetVariant() = (double) GetHtmlDoubleValue(childTag->GetNext()->GetTagText());
539 }
540 }
541 }
542 }
543 childTag = childTag->GetNext();
544 }
4fe30bce 545 return true;
d7463f75
JS
546}
547
548/// Clear dependencies
549void ctConfigToolDoc::ClearDependencies(ctConfigItem* item)
550{
551 if (!item)
552 item = GetTopItem();
553
554 item->GetDependents().Clear();
d9ab621e 555 for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
d7463f75
JS
556 {
557 ctConfigItem* child = (ctConfigItem*) node->GetData();
558 ClearDependencies(child);
559 }
560}
561
562/// Refresh dependencies
563void ctConfigToolDoc::RefreshDependencies()
564{
565 ClearDependencies(GetTopItem());
566 RefreshDependencies(GetTopItem());
567}
568
569/// Refresh dependencies
570void ctConfigToolDoc::RefreshDependencies(ctConfigItem* item)
571{
572 wxArrayString requiresArr;
573 wxString requires = item->GetPropertyString(wxT("requires"));
574 wxString precludes = item->GetPropertyString(wxT("precludes"));
575 wxString enabledIf = item->GetPropertyString(wxT("enabled-if"));
576 wxString enabledIfNot = item->GetPropertyString(wxT("enabled-if-not"));
afc51590 577 wxString indeterminateIf = item->GetPropertyString(wxT("indeterminate-if"));
d7463f75
JS
578 wxString context = item->GetPropertyString(wxT("context"));
579
580 if (!requires.IsEmpty())
581 item->StringToArray(requires, requiresArr);
582
583 if (!precludes.IsEmpty())
584 item->StringToArray(precludes, requiresArr);
585
586 if (!enabledIfNot.IsEmpty())
587 item->StringToArray(enabledIfNot, requiresArr);
588
589 if (!enabledIf.IsEmpty())
590 item->StringToArray(enabledIf, requiresArr);
591
afc51590
JS
592 if (!indeterminateIf.IsEmpty())
593 item->StringToArray(indeterminateIf, requiresArr);
594
d7463f75
JS
595 // Add the parent to the list of dependencies, if the
596 // parent is a check or radio group.
597 ctConfigItem* parent = item->GetParent();
598 if (parent &&
599 (parent->GetType() == ctTypeCheckGroup ||
600 parent->GetType() == ctTypeRadioGroup))
601 requiresArr.Add(parent->GetName());
602
603 // Also look in 'context' since these items
604 // are another kind of dependency (switching to
605 // a different platform may cause the dependencies
606 // to be evaluated differently).
607 if (!context.IsEmpty())
608 item->StringToArray(context, requiresArr);
609
610 size_t i;
611 for (i = 0; i < requiresArr.GetCount(); i++)
612 {
613 wxString itemName(requiresArr[i]);
614 ctConfigItem* otherItem = GetTopItem()->FindItem(itemName);
615 if (otherItem && !otherItem->GetDependents().Member(item))
616 {
617 otherItem->GetDependents().Append(item);
618 }
619 }
d9ab621e 620 for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
d7463f75
JS
621 {
622 ctConfigItem* child = (ctConfigItem*) node->GetData();
623 RefreshDependencies(child);
624 }
625}
626
627/// Generate the text of a setup.h
628wxString ctConfigToolDoc::GenerateSetup()
629{
630 wxString str;
631 str << wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
632
633 GenerateSetup(GetTopItem(), str);
634
635 return str;
636}
637
638/// Helper function
639void ctConfigToolDoc::GenerateSetup(ctConfigItem* item, wxString& str)
640{
641 // Generate the setup.h entries for this item
642 wxString name = item->GetName();
643
644 // We don't process the platform choice
d9a41dfe 645 if (item->GetName() == wxT("Target"))
d7463f75
JS
646 return;
647
648 if (item->IsInActiveContext() &&
649 (item->GetType() == ctTypeCheckGroup ||
650 item->GetType() == ctTypeRadioGroup ||
651 item->GetType() == ctTypeBoolCheck ||
652 item->GetType() == ctTypeBoolRadio))
653 {
654 // TODO: write description
655 wxString name = item->GetName();
656 if (name.Left(6) == wxT("wxUSE_") ||
657 name == wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
658 name.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND)
659 {
660 str << wxT("#define ") << name ;
661 if (item->IsEnabled())
662 str << wxT(" 1");
663 else
664 str << wxT(" 0");
665 str << wxT("\n\n");
666 }
667 }
668
d9ab621e 669 for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
d7463f75
JS
670 {
671 ctConfigItem* child = (ctConfigItem*) node->GetData();
672 GenerateSetup(child, str);
673 }
674}
675
676
677/// Generate a configure command
678wxString ctConfigToolDoc::GenerateConfigureCommand()
679{
680 wxString str;
681 str << wxT("# configurewx\n# Generated by wxConfigTool\n\n");
682
4fe30bce
WS
683 wxString path = GetFrameworkDir(true);
684 bool makeUnix = true;
d7463f75
JS
685 if (!path.IsEmpty())
686 {
687 if (makeUnix)
688 path += wxT("/");
689 else
690 path += wxFILE_SEP_PATH ;
691 }
692
693 str << path << wxT("configure");
694
d9a41dfe
JS
695 // Find the target to use
696 ctConfigItem* platformsFolder = GetTopItem()->FindItem(wxT("Target"));
d7463f75
JS
697 if (platformsFolder)
698 {
d9ab621e 699 for ( wxObjectList::compatibility_iterator node = platformsFolder->GetChildren().GetFirst(); node; node = node->GetNext() )
d7463f75
JS
700 {
701 ctConfigItem* child = (ctConfigItem*) node->GetData();
702 if (child->GetType() == ctTypeBoolRadio && child->IsEnabled())
703 {
704 wxString configureCommand = child->GetPropertyString(wxT("configure-command"));
705 if (!configureCommand.IsEmpty())
706 str << wxT(" ") << configureCommand;
707 }
708 }
709 }
710
711 GenerateConfigureCommand(GetTopItem(), str);
712 return str;
713}
714
715/// Helper function
716void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem* item, wxString& str)
717{
718 // We don't process the platform group, since we've
719 // already done so.
d9a41dfe 720 if (item->GetName() == wxT("Target"))
d7463f75
JS
721 return;
722
723 if (item->IsInActiveContext() &&
724 (item->GetType() == ctTypeCheckGroup ||
725 item->GetType() == ctTypeRadioGroup ||
726 item->GetType() == ctTypeBoolCheck ||
727 item->GetType() == ctTypeBoolRadio))
728 {
729 wxString name = item->GetName();
730 wxString configureCommand = item->GetPropertyString(wxT("configure-command"));
731 if (!configureCommand.IsEmpty())
732 {
733 if (!item->IsEnabled())
734 {
735 // Replace 'enable' with 'disable' if this
736 // option is off.
737 configureCommand.Replace(wxT("--enable-"), wxT("--disable-"));
738 configureCommand.Replace(wxT("--with-"), wxT("--without-"));
739 }
740 ctProperty* prop = item->GetProperties().FindProperty(wxT("builtin"));
741 if (prop && prop->GetVariant().GetType() == wxT("bool"))
742 {
743 bool builtin = prop->GetVariant().GetBool();
744 str << wxT(" ") << configureCommand;
745 if (builtin)
746 str << wxT("=builtin");
747 else
748 str << wxT("=sys");
749 }
750 else
751 {
752 ctProperty* prop = item->GetProperties().FindProperty(wxT("value"));
753 if (prop && prop->GetVariant().GetType() == wxT("string"))
754 {
755 wxString val = prop->GetVariant().GetString();
756 if (item->IsEnabled() && !val.IsEmpty())
757 {
758 str << wxT(" ") << configureCommand;
759 str << wxT("=\"") << val << wxT("\"");
760 }
761 // If the string is empty, ignore this parameter,
762 // since it's obviously intended to be supplied
763 // only if there's a string to use and it's enabled.
764 }
765 else
766 {
767 str << wxT(" ") << configureCommand;
768 }
769 }
770 }
771 }
772
d9ab621e 773 for ( wxObjectList::compatibility_iterator node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
d7463f75
JS
774 {
775 ctConfigItem* child = (ctConfigItem*) node->GetData();
776 GenerateConfigureCommand(child, str);
777 }
778}
779
780/// Gets the current framework directory
781wxString ctConfigToolDoc::GetFrameworkDir(bool makeUnix)
782{
783 wxString path = wxGetApp().GetSettings().m_frameworkDir;
784 if (wxGetApp().GetSettings().m_useEnvironmentVariable)
785 {
786 // Should probably allow other variables
787 // to be used, and maybe expand variables within m_frameworkDir
d9ab621e
WS
788 wxString pathEnv(wxGetenv(wxT("WXWIN")));
789 path = pathEnv;
d7463f75
JS
790#ifdef __WXMSW__
791 if (makeUnix)
792 path.Replace(wxT("\\"), wxT("/"));
793#endif
794 }
795 return path;
796}
797
e7767867
JS
798/// Finds the next item in the tree
799ctConfigItem* ctConfigToolDoc::FindNextItem(ctConfigItem* item, bool wrap)
800{
801 if (!item)
802 return GetTopItem();
803
804 // First, try to find the first child
805 if (item->GetChildCount() > 0)
806 {
807 return item->GetChild(0);
808 }
809 else
810 {
811 ctConfigItem* p = item;
812 while (p)
813 {
814 ctConfigItem* toFind = FindNextSibling(p);
815 if (toFind)
816 return toFind;
817 p = p->GetParent();
818 }
819 }
820
821 // Finally, wrap around to the root.
822 if (wrap)
823 return GetTopItem();
824 else
825 return NULL;
826}
827
828/// Finds the next sibling in the tree
829ctConfigItem* ctConfigToolDoc::FindNextSibling(ctConfigItem* item)
830{
831 if (item->GetParent())
832 {
d9ab621e 833 wxObjectList::compatibility_iterator node = item->GetParent()->GetChildren().Member(item);
e7767867
JS
834 if (node && node->GetNext())
835 {
836 ctConfigItem* nextItem = (ctConfigItem*) node->GetNext()->GetData();
837 return nextItem;
838 }
839 }
840 return NULL;
841}
842
d7463f75
JS
843
844/*
845 * Implements a document editing command.
846 */
847
848ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId,
849 ctConfigItem* activeState, ctConfigItem* savedState,
850 ctConfigItem* parent, ctConfigItem* insertBefore,
4fe30bce 851 bool ignoreFirstTime): wxCommand(true, name)
d7463f75
JS
852{
853 m_activeState = activeState;
854 m_savedState = savedState;
855 m_ignoreThis = ignoreFirstTime;
856 m_cmdId = cmdId;
857 m_properties = NULL;
858 m_parent = parent;
859 m_insertBefore = insertBefore;
860}
861
862ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId,
863 ctConfigItem* activeState, ctProperties* properties,
4fe30bce 864 bool ignoreFirstTime): wxCommand(true, name)
d7463f75
JS
865{
866 m_activeState = activeState;
867 m_savedState = NULL;
868 m_properties = properties;
869 m_ignoreThis = ignoreFirstTime;
870 m_cmdId = cmdId;
871 m_properties = properties;
872 m_parent = NULL;
873 m_insertBefore = NULL;
874}
875
876ctConfigCommand::~ctConfigCommand()
877{
878 if (m_savedState)
879 delete m_savedState;
880 if (m_properties)
881 delete m_properties;
882}
883
884bool ctConfigCommand::Do()
885{
4fe30bce 886 return DoAndUndo(true);
d7463f75
JS
887}
888
889bool ctConfigCommand::Undo()
890{
4fe30bce 891 return DoAndUndo(false);
d7463f75
JS
892}
893
894// Combine Do and Undo into one
895bool ctConfigCommand::DoAndUndo(bool doCmd)
896{
897 switch (m_cmdId)
898 {
899 case ctCMD_CUT:
900 {
901 if (doCmd)
902 {
903 wxASSERT(m_savedState == NULL);
904 wxASSERT(m_activeState != NULL);
905
906 ctConfigItem* newItem = m_activeState->DeepClone();
907 ctConfigToolDoc* doc = m_activeState->GetDocument();
908
909 // This will delete the old clipboard contents, if any.
910 doc->SetClipboardItem(newItem);
911
912 m_parent = m_activeState->GetParent();
913 m_insertBefore = m_activeState->FindNextSibling();
914
915 m_activeState->Detach();
916 m_savedState = m_activeState;
917 m_activeState = NULL;
918
4fe30bce 919 m_savedState->GetDocument()->Modify(true);
d7463f75
JS
920 ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
921 view->OnChangeFilename();
922 }
923 else
924 {
925 wxASSERT(m_savedState != NULL);
926 wxASSERT(m_activeState == NULL);
927
4fe30bce 928 m_savedState->GetDocument()->Modify(true);
d7463f75
JS
929 m_savedState->Attach(m_parent, m_insertBefore);
930 ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
931 view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
932 m_activeState = m_savedState;
933 m_savedState = NULL;
934 m_parent = NULL;
935 m_insertBefore = NULL;
936 view->OnChangeFilename();
937 }
938 break;
939 }
940 case ctCMD_PASTE:
941 {
942 if (doCmd)
943 {
944 wxASSERT(m_savedState != NULL);
945 wxASSERT(m_activeState == NULL);
946
4fe30bce 947 m_savedState->GetDocument()->Modify(true);
d7463f75
JS
948 m_savedState->Attach(m_parent, m_insertBefore);
949 ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
950 view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
951 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId());
952 m_activeState = m_savedState;
953 m_savedState = NULL;
954 view->OnChangeFilename();
955 }
956 else
957 {
958 wxASSERT(m_savedState == NULL);
959 wxASSERT(m_activeState != NULL);
960
4fe30bce 961 m_activeState->GetDocument()->Modify(true);
d7463f75
JS
962 ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView();
963 m_activeState->Detach();
964 m_savedState = m_activeState;
965 m_activeState = NULL;
966 view->OnChangeFilename();
967 }
968 break;
969 }
970 case ctCMD_NEW_ELEMENT:
971 {
972 if (doCmd)
973 {
974 wxASSERT(m_savedState != NULL);
975 wxASSERT(m_activeState == NULL);
976
4fe30bce 977 m_savedState->GetDocument()->Modify(true);
d7463f75
JS
978 m_savedState->Attach(m_parent, m_insertBefore);
979 ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
980 view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
981 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId());
982
983 m_activeState = m_savedState;
984 m_savedState = NULL;
985 }
986 else
987 {
988 wxASSERT(m_savedState == NULL);
989 wxASSERT(m_activeState != NULL);
990
4fe30bce 991 m_activeState->GetDocument()->Modify(true);
d7463f75
JS
992 m_activeState->Detach();
993 m_savedState = m_activeState;
994 m_activeState = NULL;
995 }
996 break;
997 }
998 case ctCMD_APPLY_PROPERTY:
999 {
1000 wxASSERT(m_properties != NULL);
1001 wxASSERT(m_activeState != NULL);
1002
1003 // Don't update the properties editor first time
1004 // around since it will be done one property at a time
1005 // initially (and no property editor update required)
1006 if (!m_ignoreThis)
1007 {
1008 // Just swap the saved and current properties.
1009 ctProperties propsTemp = m_activeState->GetProperties() ;
1010 m_activeState->GetProperties() = (* m_properties);
1011 (* m_properties) = propsTemp;
1012
1013 // Apply only those that need applying
1014 // (those properties in activeState that are not in propsTemp)
d9ab621e 1015 wxObjectList::compatibility_iterator node = m_activeState->GetProperties().GetList().GetFirst();
d7463f75
JS
1016 while (node)
1017 {
1018 ctProperty* prop = (ctProperty*) node->GetData();
1019 ctProperty* otherProp = propsTemp.FindProperty(prop->GetName());
1020 if (otherProp && ((*prop) != (*otherProp)))
1021 {
1022 m_activeState->ApplyProperty(prop, otherProp->GetVariant());
1023 }
1024 node = node->GetNext();
1025 }
4fe30bce 1026 m_activeState->GetDocument()->Modify(true);
d7463f75
JS
1027 ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView();
1028 if (view)
1029 {
1030 ctConfigToolHint hint(NULL, ctValueChanged);
1031 m_activeState->GetDocument()->UpdateAllViews (NULL, & hint);
1032 }
1033 }
4fe30bce 1034 m_ignoreThis = false;
d7463f75
JS
1035
1036 break;
1037 }
1038 }
4fe30bce 1039 return true;
d7463f75
JS
1040}
1041
61775320
JS
1042IMPLEMENT_CLASS(ctConfiguration, wxObject)
1043
1044ctConfiguration::ctConfiguration()
1045{
1046 m_treeItemId = wxTreeItemId();
1047 m_parent = NULL;
1048 m_topItem = NULL;
1049}
1050
1051ctConfiguration::ctConfiguration(ctConfiguration* parent, const wxString& name)
1052{
1053 m_treeItemId = wxTreeItemId();
1054 SetName(name);
1055 m_parent = parent;
1056 if (parent)
1057 parent->AddChild(this);
1058}
1059
1060ctConfiguration::~ctConfiguration()
1061{
1062/*
1063 ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
1064 if (m_treeItemId.IsOk() && treeCtrl)
1065 {
1066 ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
1067 if (data)
1068 data->SetConfigItem(NULL);
1069 }
1070 if (GetParent())
1071 GetParent()->RemoveChild(this);
1072 else
1073 {
1074 if (wxGetApp().GetMainFrame()->GetDocument() &&
1075 wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
1076 wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
1077 }
1078*/
1079
1080 Clear();
1081}
1082
1083/// Assignment operator.
1084void ctConfiguration::operator= (const ctConfiguration& configuration)
1085{
1086 m_name = configuration.m_name;
1087 m_description = configuration.m_description;
1088}
1089
1090/// Clear children
1091void ctConfiguration::Clear()
1092{
d9ab621e 1093 wxObjectList::compatibility_iterator node = m_children.GetFirst();
61775320
JS
1094 while (node)
1095 {
d9ab621e 1096 wxObjectList::compatibility_iterator next = node->GetNext();
61775320
JS
1097 ctConfiguration* child = (ctConfiguration*) node->GetData();
1098
1099 // This should delete 'node' too, assuming
1100 // child's m_parent points to 'this'. If not,
1101 // it'll be cleaned up by m_children.Clear().
1102 delete child;
1103
1104 node = next;
1105 }
1106 m_children.Clear();
1107}
1108
1109// Get the nth child
1110ctConfiguration* ctConfiguration::GetChild(int n) const
1111{
1112 wxASSERT ( n < GetChildCount() && n > -1 );
1113
1114 if ( n < GetChildCount() && n > -1 )
1115 {
1116 ctConfiguration* child = wxDynamicCast(m_children.Item(n)->GetData(), ctConfiguration);
1117 return child;
1118 }
1119 else
1120 return NULL;
1121}
1122
1123// Get the child count
1124int ctConfiguration::GetChildCount() const
1125{
1126 return m_children.GetCount();
1127}
1128
1129/// Add a child
1130void ctConfiguration::AddChild(ctConfiguration* configuration)
1131{
1132 m_children.Append(configuration);
1133 configuration->SetParent(this);
1134}
1135
1136/// Remove (but don't delete) a child
1137void ctConfiguration::RemoveChild(ctConfiguration* configuration)
1138{
1139 m_children.DeleteObject(configuration);
1140 configuration->SetParent(NULL);
1141}
1142
1143/// Get the associated document (currently, assumes
1144/// there's only ever one document active)
1145ctConfigToolDoc* ctConfiguration::GetDocument()
1146{
1147 ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
1148 return doc;
1149}
1150
1151/// Find an item in this hierarchy
1152// TODO: ensure that names are unique, somehow.
1153ctConfiguration* ctConfiguration::FindConfiguration(const wxString& name)
1154{
1155 if (GetName() == name)
1156 return this;
1157
d9ab621e 1158 for ( wxObjectList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() )
61775320
JS
1159 {
1160 ctConfiguration* child = (ctConfiguration*) node->GetData();
1161 ctConfiguration* found = child->FindConfiguration(name);
1162 if (found)
1163 return found;
1164 }
1165 return NULL;
1166}
1167
1168/// Find the next sibling
1169ctConfiguration* ctConfiguration::FindNextSibling()
1170{
1171 if (!GetParent())
1172 return NULL;
d9ab621e 1173 wxObjectList::compatibility_iterator node = GetParent()->GetChildren().Member(this);
61775320
JS
1174 if (node && node->GetNext())
1175 {
1176 return (ctConfiguration*) node->GetNext()->GetData();
1177 }
1178 return NULL;
1179}
1180
1181/// Find the previous sibling
1182ctConfiguration* ctConfiguration::FindPreviousSibling()
1183{
1184 if (!GetParent())
1185 return NULL;
d9ab621e 1186 wxObjectList::compatibility_iterator node = GetParent()->GetChildren().Member(this);
61775320
JS
1187 if (node && node->GetPrevious())
1188 {
1189 return (ctConfiguration*) node->GetPrevious()->GetData();
1190 }
1191 return NULL;
1192}
1193
1194/// Create a clone of this and children
1195ctConfiguration* ctConfiguration::DeepClone()
1196{
1197 ctConfiguration* newItem = Clone();
1198
d9ab621e 1199 for ( wxObjectList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() )
61775320
JS
1200 {
1201 ctConfiguration* child = (ctConfiguration*) node->GetData();
1202 ctConfiguration* newChild = child->DeepClone();
1203 newItem->AddChild(newChild);
1204 }
1205 return newItem;
1206}
1207
1208/// Detach: remove from parent, and remove tree items
1209void ctConfiguration::Detach()
1210{
1211 // TODO
1212 if (GetParent())
1213 GetParent()->RemoveChild(this);
1214 else
1215 GetDocument()->SetTopItem(NULL);
1216 SetParent(NULL);
1217
1218/*
1219 wxTreeItemId treeItem = GetTreeItemId();
1220
1221 DetachFromTree();
1222
1223 // Will delete the branch, but not the config items.
1224 wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
1225*/
1226}
1227
1228/// Hide from tree: make sure tree deletions won't delete
1229/// the config items
1230void ctConfiguration::DetachFromTree()
1231{
ddc4f3b5 1232/*
61775320
JS
1233 wxTreeItemId item = GetTreeItemId();
1234
1235 // TODO
61775320
JS
1236 ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
1237 data->SetConfigItem(NULL);
1238 m_treeItemId = wxTreeItemId();
1239
1240 for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
1241 {
1242 ctConfiguration* child = (ctConfiguration*) node->GetData();
1243 child->DetachFromTree();
1244 }
1245*/
1246}
1247
e7767867 1248