" > /tmp/appver.c
+ echo "#include \"symbols.h\"" >> /tmp/appver.c
+ echo "int main() { printf(\"%.2f\", ctVERSION_NUMBER); }" >> /tmp/appver.c
+ cc /tmp/appver.c -I$(APPSRCDIR) -o /tmp/appver
+ chmod a+x $(APPSRCDIR)/../scripts/maketarball.sh
+ $(APPSRCDIR)/../scripts/maketarball.sh $(APPDIR) $(APPBUILDDIR) /tmp/wxconfigtool-deliver `/tmp/appver` # --upx
+ echo The release is in /tmp/wxconfigtool-deliver.
+# rm -f /tmp/appver /tmp/appver.c
+
+# Gives a list of targets
+help:
+ @echo "Targets: full, wxconfigtool, wx, cleanall, clean, cleanwx, release"
+
+### File dependencies
+
+# Main app files
+
+$(APPBUILDDIR)/wxconfigtool.o: $(APPSRCDIR)/wxconfigtool.cpp $(APPINCDIR)/wxconfigtool.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/appsettings.o: $(APPSRCDIR)/appsettings.cpp $(APPSRCDIR)/appsettings.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/configitem.o: $(APPSRCDIR)/configitem.cpp $(APPSRCDIR)/configitem.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/configitemselector.o: $(APPSRCDIR)/configitemselector.cpp $(APPSRCDIR)/configitemselector.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/configtooldoc.o: $(APPSRCDIR)/configtooldoc.cpp $(APPSRCDIR)/configtooldoc.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/configtoolview.o: $(APPSRCDIR)/configtoolview.cpp $(APPSRCDIR)/configtoolview.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/configtree.o: $(APPSRCDIR)/configtree.cpp $(APPSRCDIR)/configtree.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/custompropertydialog.o: $(APPSRCDIR)/custompropertydialog.cpp $(APPSRCDIR)/custompropertydialog.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/htmlparser.o: $(APPSRCDIR)/htmlparser.cpp $(APPSRCDIR)/htmlparser.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/mainframe.o: $(APPSRCDIR)/mainframe.cpp $(APPINCDIR)/mainframe.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/propeditor.o: $(APPSRCDIR)/propeditor.cpp $(APPINCDIR)/propeditor.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/property.o: $(APPSRCDIR)/property.cpp $(APPINCDIR)/property.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/settingsdialog.o: $(APPSRCDIR)/settingsdialog.cpp $(APPINCDIR)/settingsdialog.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/utils.o: $(APPSRCDIR)/utils.cpp $(APPINCDIR)/imagewindow.h $(APPSRCDIR)/symbols.h
+ $(CXX) -c $(CXXFLAGS) $(APPEXTRADEFS) -o $@ $<
+
+$(APPBUILDDIR)/wxconfigtool_resources.o: $(APPSRCDIR)/wxconfigtool.rc
+ $(RESCOMP) -i $< -o $@ $(RESFLAGS) --include-dir $(APPSRCDIR)
+
diff --git a/utils/configtool/src/Makefile.in b/utils/configtool/src/Makefile.in
new file mode 100644
index 0000000000..1c4cde62cb
--- /dev/null
+++ b/utils/configtool/src/Makefile.in
@@ -0,0 +1,28 @@
+#
+# File: Makefile.in
+# Author: Julian Smart
+# Created: 2003
+# Updated:
+# Copyright: (c) 2003 Julian Smart
+#
+# "%W% %G%"
+#
+# Makefile for wxWindows Configuration Tool (Unix)
+
+top_srcdir = @top_srcdir@/..
+top_builddir = ../../..
+program_dir = utils/configtool/src
+
+PROGRAM=wxconfigtool
+
+OBJECTS = wxconfigtool.o appsettings.o configitem.o configitemselector.o configtooldoc.o \
+ configtoolview.o configtree.o custompropertydialog.o htmlparser.o mainframe.o \
+ propeditor.o property.o settingsdialog.o utils.o
+
+DEPFILES=wxconfigtool.d appsettings.d configitem.d configitemselector.d configtooldoc.d \
+ configtoolview.d configtree.d custompropertydialog.d htmlparser.d mainframe.d \
+ propeditor.d property.d settingsdialog.o utils.d
+
+include ../../../src/makeprog.env
+
+-include $(DEPFILES)
diff --git a/utils/configtool/src/appsettings.cpp b/utils/configtool/src/appsettings.cpp
new file mode 100644
index 0000000000..69fd5a3d52
--- /dev/null
+++ b/utils/configtool/src/appsettings.cpp
@@ -0,0 +1,272 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: appsettings.cpp
+// Purpose: Implements settings-related functionality
+// Author: Julian Smart
+// Modified by:
+// Created: 2002-09-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation appsettings.h
+#endif
+
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "wx/wfstream.h"
+#include "wx/datstrm.h"
+#include "wx/config.h"
+#include "wx/fileconf.h"
+#include "wx/dir.h"
+#include "wx/valgen.h"
+#include "wx/colordlg.h"
+#include "wx/wxhtml.h"
+#include "wx/effects.h"
+#include "wx/spinctrl.h"
+#include "wx/tooltip.h"
+
+#include "utils.h"
+#include "wxconfigtool.h"
+#include "appsettings.h"
+#include "mainframe.h"
+#include "symbols.h"
+#include "settingsdialog.h"
+
+/*
+ * User-changeable settings
+ */
+
+IMPLEMENT_DYNAMIC_CLASS(ctSettings, wxObject)
+
+ctSettings::ctSettings()
+{
+ m_noUses = 0;
+ m_showToolBar = TRUE;
+ m_showWelcomeDialog = TRUE;
+ m_exportDir = wxEmptyString;
+
+ m_frameSize = wxRect(10, 10, 600, 500);
+ // m_backgroundColour = wxColour(140, 172, 179); // blue-grey
+ m_editWindowFont = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
+
+ m_appName = wxT("wxWindows Configuration Tool");
+ m_appNameShort = wxT("Configuration Tool");
+ m_showSplashScreen = FALSE;
+ m_userName = wxEmptyString;
+ m_frameStatus = ctSHOW_STATUS_NORMAL;
+ m_loadLastDocument = TRUE;
+ m_firstTimeRun = TRUE;
+ m_smallToolbar = TRUE;
+ m_mainSashSize = 200;
+ m_useToolTips = TRUE;
+ m_showTrayIcon = TRUE;
+ m_trayIconIsShown = FALSE;
+ m_useEnvironmentVariable = TRUE;
+ m_frameworkDir = wxEmptyString;
+}
+
+// Copy constructor
+ctSettings::ctSettings(const ctSettings& settings)
+{
+ Copy(settings);
+}
+
+
+ctSettings::~ctSettings()
+{
+}
+
+void ctSettings::operator = (const ctSettings& settings)
+{
+ Copy(settings);
+}
+
+void ctSettings::Copy (const ctSettings& settings)
+{
+ m_currentDocumentDir = settings.m_currentDocumentDir;
+ m_lastDocument = settings.m_lastDocument;
+ m_showToolBar = settings.m_showToolBar;
+ m_frameSize = settings.m_frameSize;
+ m_editWindowFont = settings.m_editWindowFont;
+ m_showSplashScreen = settings.m_showSplashScreen;
+ m_userName = settings.m_userName;
+ m_loadLastDocument = settings.m_loadLastDocument;
+ m_exportDir = settings.m_exportDir;
+ m_firstTimeRun = settings.m_firstTimeRun;
+ m_noUses = settings.m_noUses;
+ m_smallToolbar = settings.m_smallToolbar;
+ m_useToolTips = settings.m_useToolTips;
+ m_showWelcomeDialog = settings.m_showWelcomeDialog;
+ m_mainSashSize = settings.m_mainSashSize;
+
+ m_showTrayIcon = settings.m_showTrayIcon;
+ m_trayIconIsShown = settings.m_trayIconIsShown;
+
+ m_useEnvironmentVariable = settings.m_useEnvironmentVariable;
+ m_frameworkDir = settings.m_frameworkDir;
+}
+
+// Do some initialisation within stApp::OnInit
+bool ctSettings::Init()
+{
+ m_currentDocumentDir = wxEmptyString;
+ if (m_userName.IsEmpty())
+ m_userName = wxGetUserName();
+
+ return TRUE;
+}
+
+// Create new filename
+wxString ctSettings::GenerateFilename(const wxString& rootName)
+{
+ wxString path;
+ if (!m_lastFilename.IsEmpty())
+ path = wxPathOnly(m_lastFilename);
+ else
+ path = wxGetApp().GetAppDir();
+
+ wxString filename(path);
+ if (filename.Last() != wxFILE_SEP_PATH )
+ filename += wxFILE_SEP_PATH;
+ filename += rootName;
+
+ wxString fullFilename = filename + wxT(".wxs");
+ int i = 0;
+ wxString postfixStr;
+ while (wxFileExists(fullFilename))
+ {
+ i ++;
+ postfixStr.Printf("%d", i);
+ fullFilename = filename + postfixStr + wxT(".wxs");
+ }
+
+ m_lastFilename = fullFilename;
+ return fullFilename;
+}
+
+// Load config info
+bool ctSettings::LoadConfig()
+{
+ wxConfig config(wxGetApp().GetSettings().GetAppName(), wxT("wxWindows"));
+
+ config.Read(wxT("Files/LastFile"), & m_lastFilename);
+ config.Read(wxT("Files/DocumentDir"), & m_currentDocumentDir);
+ config.Read(wxT("Files/ExportDir"), & m_exportDir);
+ config.Read(wxT("Files/FrameworkDir"), & m_frameworkDir);
+ config.Read(wxT("Files/UseEnvironmentVariable"), (bool*) & m_useEnvironmentVariable);
+
+ config.Read(wxT("Misc/UserName"), & m_userName);
+ config.Read(wxT("Misc/FrameStatus"), & m_frameStatus);
+ config.Read(wxT("Misc/ShowToolTips"), (bool*) & m_useToolTips);
+ config.Read(wxT("Misc/LastDocument"), & m_lastDocument);
+ config.Read(wxT("Misc/LoadLastDocument"), (bool*) & m_loadLastDocument);
+ config.Read(wxT("Misc/ShowWelcomeDialog"), (bool*) & m_showWelcomeDialog);
+ config.Read(wxT("Misc/Ran"), & m_noUses);
+ config.Read(wxT("Misc/ShowTrayIcon"), (bool*) & m_showTrayIcon);
+
+ m_noUses ++;
+
+ config.Read(wxT("Windows/ShowToolBar"), (bool*) & m_showToolBar);
+
+ m_firstTimeRun = !(config.Read(wxT("Windows/WindowX"), & m_frameSize.x));
+ config.Read(wxT("Windows/WindowY"), & m_frameSize.y);
+ config.Read(wxT("Windows/WindowWidth"), & m_frameSize.width);
+ config.Read(wxT("Windows/WindowHeight"), & m_frameSize.height);
+ config.Read(wxT("Windows/ShowSplashScreen"), (bool*) & m_showSplashScreen);
+ config.Read(wxT("Windows/SmallToolbar"), (bool*) & m_smallToolbar);
+ config.Read(wxT("Windows/MainSashSize"), & m_mainSashSize);
+
+ wxString fontSpec;
+
+ fontSpec = wxEmptyString;
+ config.Read(wxT("Style/EditWindowFont"), & fontSpec);
+ if (!fontSpec.IsEmpty())
+ m_editWindowFont = apStringToFont(fontSpec);
+
+ // Crash-resistance
+ int runningProgram = 0;
+ config.Read(wxT("Misc/RunningProgram"), & runningProgram);
+
+#ifndef __WXDEBUG__
+ // runningProgram should be zero if all is well. If 1,
+ // it crashed during a run, so we should disable the auto-load
+ // facility just in case it's trying to load a damaged file.
+ if (runningProgram != 0)
+ {
+ m_loadLastDocument = FALSE;
+ }
+#endif
+
+ config.Write(wxT("Misc/RunningProgram"), (long) 1);
+
+ return TRUE;
+}
+
+// Save config info
+bool ctSettings::SaveConfig()
+{
+ wxConfig config(wxGetApp().GetSettings().GetAppName(), wxT("wxWindows"));
+
+ config.Write(wxT("Files/LastFile"), m_lastFilename);
+ config.Write(wxT("Files/DocumentDir"), m_currentDocumentDir);
+ config.Write(wxT("Files/ExportDir"), m_exportDir);
+ config.Write(wxT("Files/FrameworkDir"), m_frameworkDir);
+ config.Write(wxT("Files/UseEnvironmentVariable"), m_useEnvironmentVariable);
+
+ config.Write(wxT("Misc/UserName"), m_userName);
+ config.Write(wxT("Misc/FrameStatus"), (long) m_frameStatus);
+ config.Write(wxT("Misc/ShowToolTips"), m_useToolTips);
+ config.Write(wxT("Misc/LastDocument"), m_lastDocument);
+ config.Write(wxT("Misc/LoadLastDocument"), (long) m_loadLastDocument);
+ config.Write(wxT("Misc/ShowWelcomeDialog"), (long) m_showWelcomeDialog);
+ config.Write(wxT("Misc/Ran"), m_noUses);
+ config.Write(wxT("Misc/ShowTrayIcon"), (long) m_showTrayIcon);
+
+ config.Write(wxT("Windows/ShowToolBar"), m_showToolBar);
+ config.Write(wxT("Windows/WindowX"), (long) m_frameSize.x);
+ config.Write(wxT("Windows/WindowY"), (long) m_frameSize.y);
+ config.Write(wxT("Windows/WindowWidth"), (long) m_frameSize.width);
+ config.Write(wxT("Windows/WindowHeight"), (long) m_frameSize.height);
+
+ config.Write(wxT("Windows/ShowSplashScreen"), m_showSplashScreen);
+ config.Write(wxT("Windows/SmallToolbar"), (long) m_smallToolbar);
+ config.Write(wxT("Windows/MainSashSize"), (long) m_mainSashSize);
+
+ /*
+ wxString backgroundColour(apColourToHexString(m_backgroundColour));
+ config.Write(wxT("Style/BackgroundColour"), backgroundColour);
+ */
+
+ config.Write(wxT("Style/EditWindowFont"), apFontToString(m_editWindowFont));
+
+ // Indicate that we're no longer running, so we know if the program
+ // crashed last time around.
+ config.Write(wxT("Misc/RunningProgram"), (long) 0);
+
+ {
+ config.SetPath(wxT("FileHistory/"));
+ wxGetApp().GetDocManager()->FileHistorySave(config);
+ }
+
+ return TRUE;
+}
+
+void ctSettings::ShowSettingsDialog(const wxString& page)
+{
+ ctSettingsDialog* dialog = new ctSettingsDialog(wxGetApp().GetTopWindow());
+// if (!page.IsEmpty())
+// dialog->GetNotebook()->SetSelection(apFindNotebookPage(dialog->GetNotebook(), page));
+
+ /* int ret = */ dialog->ShowModal();
+ dialog->Destroy();
+}
diff --git a/utils/configtool/src/appsettings.h b/utils/configtool/src/appsettings.h
new file mode 100644
index 0000000000..8a529fc82a
--- /dev/null
+++ b/utils/configtool/src/appsettings.h
@@ -0,0 +1,124 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: appsettings.h
+// Purpose: Settings-related classes
+// Author: Julian Smart
+// Modified by:
+// Created: 2002-09-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _AP_APPSETTINGS_H_
+#define _AP_APPSETTINGS_H_
+
+#ifdef __GNUG__
+#pragma interface appsettings.cpp
+#endif
+
+#include "wx/notebook.h"
+#include "wx/dialog.h"
+#include "wx/datetime.h"
+#include "wx/wave.h"
+
+#include "wxconfigtool.h"
+
+// Frame status
+#define ctSHOW_STATUS_NORMAL 0x01
+#define ctSHOW_STATUS_MINIMIZED 0x02
+#define ctSHOW_STATUS_MAXIMIZED 0x03
+
+/*!
+ * \brief ctSettings holds all the settings that can be altered
+ * by the user (and probably some that can't).
+ */
+
+class ctSettings: public wxObject
+{
+DECLARE_DYNAMIC_CLASS(ctSettings)
+public:
+ /// Default constructor.
+ ctSettings();
+
+ /// Copy constructor.
+ ctSettings(const ctSettings& settings);
+
+ /// Destructor.
+ ~ctSettings();
+
+// Operations
+
+ /// Assignment operator.
+ void operator = (const ctSettings& settings);
+
+ /// Copy function.
+ void Copy (const ctSettings& settings);
+
+ /// Loads configuration information from the registry or a file.
+ bool LoadConfig();
+
+ /// Saves configuration information to the registry or a file.
+ bool SaveConfig();
+
+ /// Initialisation before LoadConfig is called.
+ bool Init();
+
+ /// Shows the settings dialog.
+ void ShowSettingsDialog(const wxString& page = wxEmptyString);
+
+ /// Generates a new document filename.
+ wxString GenerateFilename(const wxString& rootName);
+
+// Accessors
+
+ /// Returns the long application name. This name is used
+ /// for the registry key and main frame titlebar.
+ wxString GetAppName() const { return m_appName; }
+
+ /// Returns the short application name.
+ wxString GetShortAppName() const { return m_appNameShort; }
+
+ /// Gets the name of the last filename to be loaded.
+ /// May not be needed in this application.
+ wxString& GetLastFilename() { return m_lastFilename; }
+
+ /// Returns TRUE if this is the first time the application
+ /// has been run.
+ bool GetFirstTimeRun() const { return m_firstTimeRun; }
+
+public:
+ wxString m_currentDocumentDir; // Not yet used
+ wxString m_lastDocument; // Last document
+ bool m_showToolBar;
+ bool m_smallToolbar;
+ wxRect m_frameSize;
+ // wxColour m_backgroundColour; // background colour
+ wxFont m_editWindowFont;
+ int m_noUses; // Number of times the app was invoked
+
+ wxString m_appName; // The current name of the app...
+ wxString m_appNameShort; // The short name of the app...
+ bool m_showSplashScreen; // Show the splash screen
+ wxString m_userName;
+ wxString m_lastFilename; // So we can auto-generate sensible filenames
+ bool m_loadLastDocument;
+ bool m_useToolTips; // Use tooltips on dialogs
+ int m_frameStatus;
+ wxString m_exportDir; // Where files are exported to
+
+ wxString m_frameworkDir; // Where the wxWin hierarchy is
+ bool m_useEnvironmentVariable; // Use WXWIN
+
+ /// This isn't explicitly held in the registry
+ /// but deduced from whether there are values there
+ bool m_firstTimeRun;
+ bool m_showWelcomeDialog; // Show opening helpful dialog
+
+ int m_mainSashSize;
+ bool m_showTrayIcon;
+ bool m_trayIconIsShown;
+};
+
+#endif
+ // _AP_APPSETTINGS_H_
+
diff --git a/utils/configtool/src/bitmaps/checked.xpm b/utils/configtool/src/bitmaps/checked.xpm
new file mode 100644
index 0000000000..bf15083d2a
--- /dev/null
+++ b/utils/configtool/src/bitmaps/checked.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * checked_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" ............ ",
+" .XXXXXXXXXXo ",
+" .X o ",
+" .X X o ",
+" .X XX o ",
+" .X X XXX o ",
+" .X XX XXX o ",
+" .X XXXXX o ",
+" .X XXX o ",
+" .X X o ",
+" .X o ",
+" .ooooooooooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/checked_dis.xpm b/utils/configtool/src/bitmaps/checked_dis.xpm
new file mode 100644
index 0000000000..61e35038bb
--- /dev/null
+++ b/utils/configtool/src/bitmaps/checked_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * checked_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" ............ ",
+" .XXXXXXXXXXo ",
+" .Xoooooooooo ",
+" .Xooooooo.oo ",
+" .Xoooooo..oo ",
+" .Xo.ooo...oo ",
+" .Xo..o...ooo ",
+" .Xo.....oooo ",
+" .Xoo...ooooo ",
+" .Xooo.oooooo ",
+" .Xoooooooooo ",
+" .ooooooooooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/checkedfolder.xpm b/utils/configtool/src/bitmaps/checkedfolder.xpm
new file mode 100644
index 0000000000..2f84ad388f
--- /dev/null
+++ b/utils/configtool/src/bitmaps/checkedfolder.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *checkedfolder_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c #FFFF00",
+"o c #C0C0C0",
+"O c #FFFFFF",
+"+ c #000000",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoXoXoXo+oX.+",
+" .OoXoXoXo++Xo.+",
+" .OXo+oXo+++oX.+",
+" .OoX++o+++oXo.+",
+" .OXo+++++oXoX.+",
+" .OoXo+++oXoXo.+",
+" .OXoXo+oXoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/checkedfolder_dis.xpm b/utils/configtool/src/bitmaps/checkedfolder_dis.xpm
new file mode 100644
index 0000000000..5458f94ac0
--- /dev/null
+++ b/utils/configtool/src/bitmaps/checkedfolder_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char *checkedfolder_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c #C0C0C0",
+"o c #000000",
+" ",
+" ..... ",
+" .XXXXX. ",
+".XXXXXXX...... ",
+".XXXXXXXXXXXX.o ",
+".XXXXXXXXX.XX.o ",
+".XXXXXXXX..XX.o ",
+".XXX.XXX...XX.o ",
+".XXX..X...XXX.o ",
+".XXX.....XXXX.o ",
+".XXXX...XXXXX.o ",
+".XXXXX.XXXXXX.o ",
+"..............o ",
+" oooooooooooooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/closedfolder.xpm b/utils/configtool/src/bitmaps/closedfolder.xpm
new file mode 100644
index 0000000000..03c55a32aa
--- /dev/null
+++ b/utils/configtool/src/bitmaps/closedfolder.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char * closedfolder_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c Yellow",
+"o c #c0c0c0",
+"O c Gray100",
+"+ c Black",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/closedfolder_dis.xpm b/utils/configtool/src/bitmaps/closedfolder_dis.xpm
new file mode 100644
index 0000000000..a8ffebaead
--- /dev/null
+++ b/utils/configtool/src/bitmaps/closedfolder_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char *closedfolder_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c #C0C0C0",
+"o c #000000",
+" ",
+" ..... ",
+" .XXXXX. ",
+" .XXXXXXX...... ",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" ..............o",
+" oooooooooooooo",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/copy.xpm b/utils/configtool/src/bitmaps/copy.xpm
new file mode 100644
index 0000000000..47565c1cae
--- /dev/null
+++ b/utils/configtool/src/bitmaps/copy.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *copy_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c Gray100",
+"o c #000080",
+/* pixels */
+" ",
+" ...... ",
+" .XXXX.. ",
+" .XXXX.X. ",
+" .X..X.oooooo ",
+" .XXXXXoXXXXoo ",
+" .X....oXXXXoXo ",
+" .XXXXXoX..Xoooo",
+" .X....oXXXXXXXo",
+" .XXXXXoX.....Xo",
+" ......oXXXXXXXo",
+" oX.....Xo",
+" oXXXXXXXo",
+" ooooooooo",
+" "
+};
diff --git a/utils/configtool/src/bitmaps/cut.xpm b/utils/configtool/src/bitmaps/cut.xpm
new file mode 100644
index 0000000000..bfe7e95cea
--- /dev/null
+++ b/utils/configtool/src/bitmaps/cut.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *cut_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c #000080",
+/* pixels */
+" ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" . . ",
+" ... ",
+" . ",
+" X.X ",
+" X XXX ",
+" XXX X X ",
+" X X X X ",
+" X X X X ",
+" X X XX ",
+" XX "
+};
diff --git a/utils/configtool/src/bitmaps/ellipsis.xpm b/utils/configtool/src/bitmaps/ellipsis.xpm
new file mode 100644
index 0000000000..5b5e925724
--- /dev/null
+++ b/utils/configtool/src/bitmaps/ellipsis.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static char *ellipsis_xpm[] = {
+"16 16 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .. .. .. ",
+" .. .. .. ",
+" ",
+" ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/folder1.xpm b/utils/configtool/src/bitmaps/folder1.xpm
new file mode 100644
index 0000000000..61fae2325f
--- /dev/null
+++ b/utils/configtool/src/bitmaps/folder1.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char * folder1_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c Yellow",
+"o c None",
+"O c Gray100",
+"+ c Black",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" .OoXoXoXoXoXo.+",
+" .OXoXoXoXoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/help.xpm b/utils/configtool/src/bitmaps/help.xpm
new file mode 100644
index 0000000000..27a87ebb31
--- /dev/null
+++ b/utils/configtool/src/bitmaps/help.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *help_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c #008080",
+/* pixels */
+" ",
+" ...... ",
+" .XXXXX.. ",
+" .XX...XX.. ",
+" .X.. .X.. ",
+" .X.. .XX.. ",
+" .. .XX.. ",
+" .XX.. ",
+" .X.. ",
+" .X.. ",
+" .X.. ",
+" .. ",
+" .XX.. ",
+" .XX.. ",
+" ... "
+};
diff --git a/utils/configtool/src/bitmaps/helpcs.xpm b/utils/configtool/src/bitmaps/helpcs.xpm
new file mode 100644
index 0000000000..2f7f6d3ab1
--- /dev/null
+++ b/utils/configtool/src/bitmaps/helpcs.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *helpcs_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 2 1",
+/* colors */
+". c #000000",
+"# c None",
+/* pixels */
+"################",
+".########.....##",
+"..######..###..#",
+"...####..####...",
+"....###..####...",
+".....###..###..#",
+"......######..##",
+".......####..###",
+"........##..####",
+".....#####..####",
+"..#..###########",
+".###..####...###",
+"####..####...###",
+"#####..#########",
+"#####..#########"
+};
diff --git a/utils/configtool/src/bitmaps/new.xpm b/utils/configtool/src/bitmaps/new.xpm
new file mode 100644
index 0000000000..754d2d20a2
--- /dev/null
+++ b/utils/configtool/src/bitmaps/new.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *new_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 3 1",
+" c None",
+". c Black",
+"X c Gray100",
+/* pixels */
+" ",
+" ........ ",
+" .XXXXXX.. ",
+" .XXXXXX.X. ",
+" .XXXXXX.... ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" .XXXXXXXXX. ",
+" ........... ",
+" "
+};
diff --git a/utils/configtool/src/bitmaps/open.xpm b/utils/configtool/src/bitmaps/open.xpm
new file mode 100644
index 0000000000..54748e910d
--- /dev/null
+++ b/utils/configtool/src/bitmaps/open.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char *open_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 5 1",
+" c None",
+". c Black",
+"X c Yellow",
+"o c Gray100",
+"O c #bfbf00",
+/* pixels */
+" ",
+" ... ",
+" . . .",
+" ..",
+" ... ...",
+" .XoX....... ",
+" .oXoXoXoXo. ",
+" .XoXoXoXoX. ",
+" .oXoX..........",
+" .XoX.OOOOOOOOO.",
+" .oo.OOOOOOOOO. ",
+" .X.OOOOOOOOO. ",
+" ..OOOOOOOOO. ",
+" ........... ",
+" "
+};
diff --git a/utils/configtool/src/bitmaps/paste.xpm b/utils/configtool/src/bitmaps/paste.xpm
new file mode 100644
index 0000000000..69177e9b19
--- /dev/null
+++ b/utils/configtool/src/bitmaps/paste.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char *paste_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 6 1",
+" c None",
+". c Black",
+"X c Yellow",
+"o c #808080",
+"O c #000080",
+"+ c Gray100",
+/* pixels */
+" ",
+" .... ",
+" .....XX..... ",
+".ooo.X..X.ooo. ",
+".oo. .oo. ",
+".oo........oo. ",
+".oooooooooooo. ",
+".oooooOOOOOOO. ",
+".oooooO+++++OO ",
+".oooooO+++++O+O ",
+".oooooO+OOO+OOO ",
+".oooooO+++++++O ",
+".oooooO+OOOOO+O ",
+" .....O+++++++O ",
+" OOOOOOOOO "
+};
diff --git a/utils/configtool/src/bitmaps/radiofolderoff.xpm b/utils/configtool/src/bitmaps/radiofolderoff.xpm
new file mode 100644
index 0000000000..5e4b423380
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiofolderoff.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *radiofolderoff_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c #FFFF00",
+"o c #C0C0C0",
+"O c #FFFFFF",
+"+ c #000000",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoX...XoXoX.+",
+" .OoX.OOO.XoXo.+",
+" .OX.OOOOO.XoX.+",
+" .Oo.OOOOO.oXo.+",
+" .OX.OOOOO.XoX.+",
+" .OoX.OOO.XoXo.+",
+" .OXoX...XoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radiofolderoff_dis.xpm b/utils/configtool/src/bitmaps/radiofolderoff_dis.xpm
new file mode 100644
index 0000000000..dbb7b115ea
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiofolderoff_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char *radiofolderoff_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c #C0C0C0",
+"o c #000000",
+" ",
+" ..... ",
+" .XXXXX. ",
+" .XXXXXXX...... ",
+" .XXXXXXXXXXXX.o",
+" .XXXX...XXXXX.o",
+" .XXX.XXX.XXXX.o",
+" .XX.XXXXX.XXX.o",
+" .XX.XXXXX.XXX.o",
+" .XX.XXXXX.XXX.o",
+" .XXX.XXX.XXXX.o",
+" .XXXX...XXXXX.o",
+" ..............o",
+" oooooooooooooo",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radiofolderon.xpm b/utils/configtool/src/bitmaps/radiofolderon.xpm
new file mode 100644
index 0000000000..d6e61f2617
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiofolderon.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *radiofolderon_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c #FFFF00",
+"o c #C0C0C0",
+"O c #FFFFFF",
+"+ c #000000",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoX...XoXoX.+",
+" .OoX.OOO.XoXo.+",
+" .OX.O+++O.XoX.+",
+" .Oo.O+++O.oXo.+",
+" .OX.O+++O.XoX.+",
+" .OoX.OOO.XoXo.+",
+" .OXoX...XoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radiofolderon_dis.xpm b/utils/configtool/src/bitmaps/radiofolderon_dis.xpm
new file mode 100644
index 0000000000..92d0d9b621
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiofolderon_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char *radiofolderon_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c #C0C0C0",
+"o c #000000",
+" ",
+" ..... ",
+" .XXXXX. ",
+" .XXXXXXX...... ",
+" .XXXXXXXXXXXX.o",
+" .XXXX...XXXXX.o",
+" .XXX.XXX.XXXX.o",
+" .XX.X...X.XXX.o",
+" .XX.X...X.XXX.o",
+" .XX.X...X.XXX.o",
+" .XXX.XXX.XXXX.o",
+" .XXXX...XXXXX.o",
+" ..............o",
+" oooooooooooooo",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radiooff.xpm b/utils/configtool/src/bitmaps/radiooff.xpm
new file mode 100644
index 0000000000..96603c812b
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiooff.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * radiooff_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" .... ",
+" ..XXXX.. ",
+" .XX XXo ",
+" .X oo ",
+" .X oo ",
+" .X oo ",
+" .X oo ",
+" .X oo ",
+" .X oo ",
+" .oo ooo ",
+" oooooooo ",
+" oooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radiooff_dis.xpm b/utils/configtool/src/bitmaps/radiooff_dis.xpm
new file mode 100644
index 0000000000..0d7bef3c49
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radiooff_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * radiooff_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" .... ",
+" ..XXXX.. ",
+" .XXooooXXo ",
+" .Xoooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooo ",
+" .ooooooooo ",
+" oooooooo ",
+" oooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radioon.xpm b/utils/configtool/src/bitmaps/radioon.xpm
new file mode 100644
index 0000000000..f698766c9c
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radioon.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * radioon_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" .... ",
+" ..XXXX.. ",
+" .XX XXo ",
+" .X oo ",
+" .X XX oo ",
+" .X XXXX oo ",
+" .X XXXX oo ",
+" .X XX oo ",
+" .X oo ",
+" .oo ooo ",
+" oooooooo ",
+" oooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/radioon_dis.xpm b/utils/configtool/src/bitmaps/radioon_dis.xpm
new file mode 100644
index 0000000000..ed09eaf9fe
--- /dev/null
+++ b/utils/configtool/src/bitmaps/radioon_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * radioon_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" .... ",
+" ..XXXX.. ",
+" .XXooooXXo ",
+" .Xoooooooo ",
+" .Xooo..ooooo ",
+" .Xoo....oooo ",
+" .Xoo....oooo ",
+" .Xooo..ooooo ",
+" .Xoooooooo ",
+" .ooooooooo ",
+" oooooooo ",
+" oooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/redo.xpm b/utils/configtool/src/bitmaps/redo.xpm
new file mode 100644
index 0000000000..04df64ae54
--- /dev/null
+++ b/utils/configtool/src/bitmaps/redo.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *redo_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000080",
+"# c #c0c0c0",
+"a c #808080",
+/* pixels */
+"################",
+"################",
+"################",
+"################",
+"###a....########",
+"##a.####..###.##",
+"##.#######.#..##",
+"##.########...##",
+"##.#######....##",
+"##a.#####.....##",
+"###.a###########",
+"################",
+"################",
+"################",
+"################"
+};
diff --git a/utils/configtool/src/bitmaps/save.xpm b/utils/configtool/src/bitmaps/save.xpm
new file mode 100644
index 0000000000..01b18f9340
--- /dev/null
+++ b/utils/configtool/src/bitmaps/save.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *save_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 15 4 1",
+" c None",
+". c Black",
+"X c #808000",
+"o c #808080",
+/* pixels */
+" ",
+" .............. ",
+" .X. . . ",
+" .X. ... ",
+" .X. .X. ",
+" .X. .X. ",
+" .X. .X. ",
+" .X. .X. ",
+" .XX........oX. ",
+" .XXXXXXXXXXXX. ",
+" .XX.........X. ",
+" .XX...... .X. ",
+" .XX...... .X. ",
+" .XX...... .X. ",
+" ............. "
+};
diff --git a/utils/configtool/src/bitmaps/unchecked.xpm b/utils/configtool/src/bitmaps/unchecked.xpm
new file mode 100644
index 0000000000..5bb6fc8ca3
--- /dev/null
+++ b/utils/configtool/src/bitmaps/unchecked.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * unchecked_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" ............ ",
+" .XXXXXXXXXXo ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .X o ",
+" .ooooooooooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/unchecked_dis.xpm b/utils/configtool/src/bitmaps/unchecked_dis.xpm
new file mode 100644
index 0000000000..9bbfd717f4
--- /dev/null
+++ b/utils/configtool/src/bitmaps/unchecked_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char * unchecked_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c Black",
+"o c #c0c0c0",
+" ",
+" ",
+" ............ ",
+" .XXXXXXXXXXo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .Xoooooooooo ",
+" .ooooooooooo ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/uncheckedfolder.xpm b/utils/configtool/src/bitmaps/uncheckedfolder.xpm
new file mode 100644
index 0000000000..127d3bbe3b
--- /dev/null
+++ b/utils/configtool/src/bitmaps/uncheckedfolder.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *uncheckedfolder_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #808080",
+"X c #FFFF00",
+"o c #C0C0C0",
+"O c #FFFFFF",
+"+ c #000000",
+" ",
+" ..... ",
+" .XoXoX. ",
+" .XoXoXoX...... ",
+" .OOOOOOOOOOOO.+",
+" .OXoXoXoXoXoX.+",
+" .OoX++oX++oXo.+",
+" .OXoX++++oXoX.+",
+" .OoXoX++oXoXo.+",
+" .OXoX++++oXoX.+",
+" .OoX++oX++oXo.+",
+" .OXoXoXoXoXoX.+",
+" ..............+",
+" ++++++++++++++",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/uncheckedfolder_dis.xpm b/utils/configtool/src/bitmaps/uncheckedfolder_dis.xpm
new file mode 100644
index 0000000000..65f3a81b9c
--- /dev/null
+++ b/utils/configtool/src/bitmaps/uncheckedfolder_dis.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static char *uncheckedfolder_dis_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #808080",
+"X c #C0C0C0",
+"o c #000000",
+" ",
+" ..... ",
+" .XXXXX. ",
+" .XXXXXXX...... ",
+" .XXXXXXXXXXXX.o",
+" .XXXXXXXXXXXX.o",
+" .XXX..XX..XXX.o",
+" .XXXX....XXXX.o",
+" .XXXXX..XXXXX.o",
+" .XXXX....XXXX.o",
+" .XXX..XX..XXX.o",
+" .XXXXXXXXXXXX.o",
+" ..............o",
+" oooooooooooooo",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/undo.xpm b/utils/configtool/src/bitmaps/undo.xpm
new file mode 100644
index 0000000000..157a623e3c
--- /dev/null
+++ b/utils/configtool/src/bitmaps/undo.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *undo_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 15 3 1",
+/* colors */
+". c #000080",
+"# c #c0c0c0",
+"a c #808080",
+/* pixels */
+"################",
+"################",
+"################",
+"################",
+"########....a###",
+"##.###..####.a##",
+"##..#.#######.##",
+"##...########.##",
+"##....#######.##",
+"##.....#####.a##",
+"###########a.###",
+"################",
+"################",
+"################",
+"################"
+};
diff --git a/utils/configtool/src/bitmaps/wxconfigtool.ico b/utils/configtool/src/bitmaps/wxconfigtool.ico
new file mode 100644
index 0000000000..8d2dc18c6b
Binary files /dev/null and b/utils/configtool/src/bitmaps/wxconfigtool.ico differ
diff --git a/utils/configtool/src/bitmaps/wxconfigtool.xpm b/utils/configtool/src/bitmaps/wxconfigtool.xpm
new file mode 100644
index 0000000000..7825bfffe5
--- /dev/null
+++ b/utils/configtool/src/bitmaps/wxconfigtool.xpm
@@ -0,0 +1,41 @@
+/* XPM */
+static char *wxconfigtool_xpm[] = {
+"32 32 6 1",
+" c None",
+". c #000000",
+"X c #000084",
+"o c #FFFFFF",
+"O c #FFFF00",
+"+ c #FF0000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .............. ",
+" .XXXXXXXXXXXX. ",
+" .XXXXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXX..............",
+" .XooXXXXXX.OOOOOOOOOOOO.",
+".........XooXXXXXX.OOOOOOOOOOOO.",
+".+++++++.XooXXXXXX.OooOOOOOOOOO.",
+".+++++++.XooXXXXXX.OooOOOOOOOOO.",
+".+oo++++.XXXXXXXXX.OooOOOOOOOOO.",
+".+oo++++.XXXXXXXXX.OooOOOOOOOOO.",
+".+oo++++...........OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OOOOOOOOOOOO.",
+".+oo+++++++++. .OOOOOOOOOOOO.",
+".++++++++++++. ..............",
+".++++++++++++. ",
+".............. ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/wxconfigtool16x16.xpm b/utils/configtool/src/bitmaps/wxconfigtool16x16.xpm
new file mode 100644
index 0000000000..7c347167d0
--- /dev/null
+++ b/utils/configtool/src/bitmaps/wxconfigtool16x16.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char *wxconfigtool16x16_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #000000",
+"X c #000084",
+"o c #FFFFFF",
+"O c #FFFF00",
+"+ c #FF0000",
+" ",
+" ",
+" ",
+" ....... ",
+" .XXXXX. ",
+" .oXXXX. ",
+" .oXXX.......",
+".....oXXX.OOOOO.",
+".+++.XXXX.oOOOO.",
+".o++......oOOOO.",
+".o++++. .oOOOO.",
+".o++++. .OOOOO.",
+".+++++. .......",
+"....... ",
+" ",
+" "};
diff --git a/utils/configtool/src/bitmaps/wxconfigtool32x32.xpm b/utils/configtool/src/bitmaps/wxconfigtool32x32.xpm
new file mode 100644
index 0000000000..2940865d37
--- /dev/null
+++ b/utils/configtool/src/bitmaps/wxconfigtool32x32.xpm
@@ -0,0 +1,41 @@
+/* XPM */
+static char *wxconfigtool32x32_xpm[] = {
+"32 32 6 1",
+" c None",
+". c #000000",
+"X c #000084",
+"o c #FFFFFF",
+"O c #FFFF00",
+"+ c #FF0000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .............. ",
+" .XXXXXXXXXXXX. ",
+" .XXXXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXXXXX. ",
+" .XooXXXXXX..............",
+" .XooXXXXXX.OOOOOOOOOOOO.",
+".........XooXXXXXX.OOOOOOOOOOOO.",
+".+++++++.XooXXXXXX.OooOOOOOOOOO.",
+".+++++++.XooXXXXXX.OooOOOOOOOOO.",
+".+oo++++.XXXXXXXXX.OooOOOOOOOOO.",
+".+oo++++.XXXXXXXXX.OooOOOOOOOOO.",
+".+oo++++...........OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OooOOOOOOOOO.",
+".+oo+++++++++. .OOOOOOOOOOOO.",
+".+oo+++++++++. .OOOOOOOOOOOO.",
+".++++++++++++. ..............",
+".++++++++++++. ",
+".............. ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/utils/configtool/src/configitem.cpp b/utils/configtool/src/configitem.cpp
new file mode 100644
index 0000000000..2db7ac8e7a
--- /dev/null
+++ b/utils/configtool/src/configitem.cpp
@@ -0,0 +1,755 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configitem.cpp
+// Purpose: wxWindows Configuration Tool config item class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-03
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "configitem.h"
+#endif
+
+// Includes other headers for precompiled compilation
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/tokenzr.h"
+
+#include "configitem.h"
+#include "configtree.h"
+#include "configtooldoc.h"
+#include "configtoolview.h"
+#include "wxconfigtool.h"
+#include "mainframe.h"
+
+IMPLEMENT_CLASS(ctConfigItem, wxObject)
+
+ctConfigItem::ctConfigItem()
+{
+ m_modified = FALSE;
+ m_type = ctTypeBoolCheck;
+ m_treeItemId = wxTreeItemId();
+ m_enabled = TRUE;
+ m_parent = NULL;
+ m_active = TRUE;
+}
+
+ctConfigItem::ctConfigItem(ctConfigItem* parent, ctConfigType type, const wxString& name)
+{
+ m_modified = FALSE;
+ m_type = type;
+ m_treeItemId = wxTreeItemId();
+ m_enabled = FALSE;
+ m_active = TRUE;
+ SetName(name);
+ m_parent = parent;
+ if (parent)
+ parent->AddChild(this);
+}
+
+ctConfigItem::~ctConfigItem()
+{
+ ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
+ if (m_treeItemId.IsOk() && treeCtrl)
+ {
+ ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(m_treeItemId);
+ if (data)
+ data->SetConfigItem(NULL);
+ }
+ if (GetParent())
+ GetParent()->RemoveChild(this);
+ else
+ {
+ if (wxGetApp().GetMainFrame()->GetDocument() &&
+ wxGetApp().GetMainFrame()->GetDocument()->GetTopItem() == this)
+ wxGetApp().GetMainFrame()->GetDocument()->SetTopItem(NULL);
+ }
+
+ Clear();
+}
+
+/// Can we edit this property?
+bool ctConfigItem::CanEditProperty(const wxString& propName) const
+{
+ ctProperty* prop = m_properties.FindProperty(propName);
+ if (prop)
+ return !prop->GetReadOnly();
+ else
+ return FALSE;
+}
+
+/// Assignment operator.
+void ctConfigItem::operator= (const ctConfigItem& item)
+{
+ m_properties = item.m_properties;
+ m_modified = item.m_modified;
+ m_defaultProperty = item.m_defaultProperty;
+ m_type = item.m_type;
+ m_enabled = item.m_enabled;
+ m_active = item.m_active;
+}
+
+/// Sets the name property.
+void ctConfigItem::SetName(const wxString& name )
+{
+ m_properties.SetProperty(wxT("name"), name);
+}
+
+/// Clear children
+void ctConfigItem::Clear()
+{
+ wxNode* node = m_children.GetFirst();
+ while (node)
+ {
+ wxNode* next = node->GetNext();
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+
+ // This should delete 'node' too, assuming
+ // child's m_parent points to 'this'. If not,
+ // it'll be cleaned up by m_children.Clear().
+ delete child;
+
+ node = next;
+ }
+ m_children.Clear();
+}
+
+// Get the nth child
+ctConfigItem* ctConfigItem::GetChild(int n) const
+{
+ wxASSERT ( n < GetChildCount() && n > -1 );
+
+ if ( n < GetChildCount() && n > -1 )
+ {
+ ctConfigItem* child = wxDynamicCast(m_children.Nth(n)->Data(), ctConfigItem);
+ return child;
+ }
+ else
+ return NULL;
+}
+
+// Get the child count
+int ctConfigItem::GetChildCount() const
+{
+ return m_children.GetCount();
+}
+
+/// Add a child
+void ctConfigItem::AddChild(ctConfigItem* item)
+{
+ m_children.Append(item);
+ item->SetParent(this);
+}
+
+/// Remove (but don't delete) a child
+void ctConfigItem::RemoveChild(ctConfigItem* item)
+{
+ m_children.DeleteObject(item);
+ item->SetParent(NULL);
+}
+
+/// Initialise standard properties
+void ctConfigItem::InitProperties()
+{
+ ctProperty* prop = m_properties.FindProperty(wxT("name"));
+ if (!prop)
+ {
+ prop = new ctProperty;
+ m_properties.AddProperty(prop);
+ }
+ prop->SetDescription(_("Name The name of the configuration setting."));
+ prop->SetReadOnly(TRUE);
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Description
The setting description."),
+ wxVariant(wxT(""), wxT("description")),
+ wxT("multiline")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Default-state
The default state."),
+ wxVariant((bool) TRUE, wxT("default-state")),
+ wxT("bool")));
+
+ if (GetType() == ctTypeString)
+ {
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Default-value
The default value."),
+ wxVariant((bool) TRUE, wxT("default-value")),
+ wxT("")));
+ }
+ else if (GetType() == ctTypeInteger)
+ {
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Default-value
The default value."),
+ wxVariant((long) 0, wxT("default-value")),
+ wxT("")));
+ }
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Requires
When any of the given settings are 0, this setting must be 0. Taking wxUSE_ZIPSTREAM as an example:
If wxUSE_STREAMS is 0, then wxUSE_ZIPSTREAM must be 0.
If wxUSE_STREAMS is 1, then wxUSE_ZIPSTREAM may be 0 or 1."),
+ wxVariant(wxT(""), wxT("requires")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Precludes
When any of these settings are 1, this setting must be 0. Taking wxUSE_ODBC as an example:
If wxUSE_UNICODE is 1, then wxUSE_ODBC must be 0.
If wxUSE_UNICODE is 0, then wxUSE_ODBC may be 0 or 1."),
+ wxVariant(wxT(""), wxT("precludes")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Enabled-if
When any of these settings are 1, this setting must be 1."),
+ wxVariant(wxT(""), wxT("enabled-if")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Enabled-if-not
When any of these settings are 0, this setting must be 1. Taking wxUSE_TOOLBAR_SIMPLE as an example:
If wxUSE_TOOLBAR_NATIVE is 0, wxUSE_TOOLBAR_SIMPLE must be 1.
If wxUSE_TOOLBAR_NATIVE is 1, wxUSE_TOOLBAR_SIMPLE may be 0 or 1."),
+ wxVariant(wxT(""), wxT("enabled-if-not")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Exclusivity
The settings that are mutually exclusive with this one."),
+ wxVariant(wxT(""), wxT("exclusivity")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Context
A list of symbols (config settings), at least one of which must be enabled for this item to participate in dependency rules.
\nIf empty, this item will always be used in dependency rules.
\nMostly this will be used to specify the applicable platforms, but it can contain other symbols, for example compilers."),
+ wxVariant(wxT(""), wxT("context")),
+ wxT("configitems")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Configure-command
Configure command to generate if this is on."),
+ wxVariant(wxT(""), wxT("configure-command")),
+ wxT("multiline")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Help-topic
The help topic in the wxWindows manual for this component or setting."),
+ wxVariant(wxT(""), wxT("help-topic")),
+ wxT("multiline")));
+
+ m_properties.AddProperty(
+ new ctProperty(
+ wxT("Notes
User notes."),
+ wxVariant(wxT(""), wxT("notes")),
+ wxT("multiline")));
+
+ m_defaultProperty = wxT("description");
+}
+
+/// Do additional actions to apply the property to the internal
+/// representation.
+void ctConfigItem::ApplyProperty(ctProperty* prop, const wxVariant& oldValue)
+{
+ ctConfigToolDoc* doc = GetDocument();
+ bool oldModified = doc->IsModified();
+ doc->Modify(TRUE);
+
+ wxString name = prop->GetName();
+ if (name == wxT("requires") ||
+ name == wxT("precludes") ||
+ name == wxT("enabled-if") ||
+ name == wxT("enabled-if-not") ||
+ name == wxT("context"))
+ {
+ doc->RefreshDependencies();
+ }
+ if (doc && doc->GetFirstView() && oldModified != doc->IsModified())
+ ((ctConfigToolView*)doc->GetFirstView())->OnChangeFilename();
+}
+
+/// Get the associated document (currently, assumes
+/// there's only ever one document active)
+ctConfigToolDoc* ctConfigItem::GetDocument()
+{
+ ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
+ return doc;
+}
+
+/// Convert string containing config item names to
+/// an array of config item names
+void ctConfigItem::StringToArray(const wxString& items, wxArrayString& itemsArray)
+{
+ wxStringTokenizer tokenizer(items, wxT(","));
+ while (tokenizer.HasMoreTokens())
+ {
+ wxString token = tokenizer.GetNextToken();
+ itemsArray.Add(token);
+ }
+}
+
+/// Convert array containing config item names to
+/// a string
+void ctConfigItem::ArrayToString(const wxArrayString& itemsArray, wxString& items)
+{
+ items = wxEmptyString;
+ size_t i;
+ for (i = 0; i < itemsArray.GetCount(); i++)
+ {
+ items += itemsArray[i];
+ if (i < (itemsArray.GetCount() - 1))
+ items += wxT(",");
+ }
+}
+
+/// Populate a list of items found in the string.
+void ctConfigItem::StringToItems(ctConfigItem* topItem, const wxString& items, wxList& list)
+{
+ wxArrayString strArray;
+ StringToArray(items, strArray);
+ size_t i;
+ for (i = 0; i < strArray.GetCount(); i++)
+ {
+ wxString str(strArray[i]);
+ ctConfigItem* item = topItem->FindItem(str);
+ if (item)
+ list.Append(item);
+ }
+}
+
+/// Find an item in this hierarchy
+ctConfigItem* ctConfigItem::FindItem(const wxString& name)
+{
+ if (GetName() == name)
+ return this;
+
+ for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ ctConfigItem* found = child->FindItem(name);
+ if (found)
+ return found;
+ }
+ return NULL;
+}
+
+/// Find the next sibling
+ctConfigItem* ctConfigItem::FindNextSibling()
+{
+ if (!GetParent())
+ return NULL;
+ wxNode* node = GetParent()->GetChildren().Member(this);
+ if (node && node->GetNext())
+ {
+ return (ctConfigItem*) node->GetNext()->GetData();
+ }
+ return NULL;
+}
+
+/// Find the previous sibling
+ctConfigItem* ctConfigItem::FindPreviousSibling()
+{
+ if (!GetParent())
+ return NULL;
+ wxNode* node = GetParent()->GetChildren().Member(this);
+ if (node && node->GetPrevious())
+ {
+ return (ctConfigItem*) node->GetPrevious()->GetData();
+ }
+ return NULL;
+}
+
+/// Sync appearance
+void ctConfigItem::Sync()
+{
+ if (GetDocument())
+ {
+ ctConfigToolView* view = (ctConfigToolView*) GetDocument()->GetFirstView();
+ if (view)
+ {
+ view->SyncItem(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), this);
+ }
+ }
+}
+
+/// Create a clone of this and children
+ctConfigItem* ctConfigItem::DeepClone()
+{
+ ctConfigItem* newItem = Clone();
+
+ for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ ctConfigItem* newChild = child->DeepClone();
+ newItem->AddChild(newChild);
+ }
+ return newItem;
+}
+
+/// Detach: remove from parent, and remove tree items
+void ctConfigItem::Detach()
+{
+ if (GetParent())
+ GetParent()->RemoveChild(this);
+ else
+ GetDocument()->SetTopItem(NULL);
+ SetParent(NULL);
+
+ wxTreeItemId treeItem = GetTreeItemId();
+
+ DetachFromTree();
+
+ // Will delete the branch, but not the config items.
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(treeItem);
+}
+
+/// Hide from tree: make sure tree deletions won't delete
+/// the config items
+void ctConfigItem::DetachFromTree()
+{
+ wxTreeItemId item = GetTreeItemId();
+
+ ctTreeItemData* data = (ctTreeItemData*) wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetItemData(item);
+ data->SetConfigItem(NULL);
+ m_treeItemId = wxTreeItemId();
+
+ for ( wxNode* node = GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ child->DetachFromTree();
+ }
+}
+
+/// Attach: insert after the given position
+void ctConfigItem::Attach(ctConfigItem* parent, ctConfigItem* insertBefore)
+{
+ if (parent)
+ {
+ SetParent(parent);
+ wxNode* node = NULL;
+ if (insertBefore)
+ node = parent->GetChildren().Member(insertBefore);
+
+ if (node)
+ parent->GetChildren().Insert(node, this);
+ else
+ parent->GetChildren().Append(this);
+ }
+ else
+ {
+ GetDocument()->SetTopItem(this);
+ }
+}
+
+/// Can have children?
+bool ctConfigItem::CanHaveChildren() const
+{
+ return (GetType() == ctTypeGroup ||
+ GetType() == ctTypeCheckGroup ||
+ GetType() == ctTypeRadioGroup);
+}
+
+// An item is in the active context if:
+// The context field is empty; or
+// The context field contains a symbol that is currently enabled.
+bool ctConfigItem::IsInActiveContext()
+{
+ wxString context = GetPropertyString(wxT("context"));
+ if (context.IsEmpty())
+ return TRUE;
+
+ wxList contextItems;
+ StringToItems(GetDocument()->GetTopItem(), context, contextItems);
+
+ for ( wxNode* node = contextItems.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+ if (otherItem->IsEnabled())
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/// Evaluate the requires properties:
+/// if any of the 'requires' items are disabled,
+/// then this one is disabled (and inactive).
+void ctConfigItem::EvaluateDependencies()
+{
+ wxList items;
+ wxString requires = GetPropertyString(wxT("requires"));
+ wxString precludes = GetPropertyString(wxT("precludes"));
+ wxString enabledIf = GetPropertyString(wxT("enabled-if"));
+ wxString enabledIfNot = GetPropertyString(wxT("enabled-if-not"));
+
+ bool active = TRUE;
+ bool enabled = IsEnabled();
+ bool oldEnabled = enabled;
+ bool oldActive = IsActive();
+ bool explicitlyEnabled = FALSE;
+ bool explicitlyDisabled = FALSE;
+ bool inActiveContext = IsInActiveContext();
+
+ // Add the parent to the list of dependencies, if the
+ // parent is a check or radio group.
+ ctConfigItem* parent = GetParent();
+ if (parent &&
+ (parent->GetType() == ctTypeCheckGroup ||
+ parent->GetType() == ctTypeRadioGroup))
+ items.Append(parent);
+
+ wxList tempItems;
+ StringToItems(GetDocument()->GetTopItem(), requires, tempItems);
+
+ wxNode* node;
+ for ( node = tempItems.GetFirst(); node; node = node->GetNext() )
+ {
+ // Only consider the dependency if both items are in
+ // an active context.
+ // Each is in the active context if:
+ // The context field is empty; or
+ // The context field contains a symbol that is currently enabled.
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+ if (inActiveContext && otherItem->IsInActiveContext())
+ items.Append(otherItem);
+ }
+
+ {
+ int enabledCount = 0;
+ for ( node = items.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+
+ if (otherItem->IsEnabled())
+ {
+ enabledCount ++;
+ }
+ }
+ if (items.GetCount() > 0 && enabledCount == 0)
+ {
+ // None of the items were enabled
+ enabled = FALSE;
+ active = FALSE;
+ explicitlyDisabled = TRUE;
+ }
+ }
+
+ items.Clear();
+ if (!enabledIfNot.IsEmpty())
+ {
+ StringToItems(GetDocument()->GetTopItem(), enabledIfNot, items);
+ int disabledCount = 0;
+ int inContextCount = 0;
+
+ for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+
+ if (inActiveContext && otherItem->IsInActiveContext())
+ {
+ // Make this enabled and inactive, _unless_ it's
+ // already been explicitly disabled in the previous
+ // requires evaluation (it really _has_ to be off)
+ if (!otherItem->IsEnabled())
+ {
+ disabledCount ++;
+ }
+ inContextCount ++;
+ }
+ }
+ // Enable if there were no related items that were enabled
+ if (inContextCount > 0 && (disabledCount == inContextCount) && !explicitlyDisabled)
+ {
+ explicitlyEnabled = TRUE;
+ enabled = TRUE;
+ active = FALSE;
+ }
+ }
+
+ items.Clear();
+ if (!enabledIf.IsEmpty())
+ {
+ StringToItems(GetDocument()->GetTopItem(), enabledIf, items);
+ int enabledCount = 0;
+ int inContextCount = 0;
+
+ for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+
+ if (inActiveContext && otherItem->IsInActiveContext())
+ {
+ // Make this enabled and inactive, _unless_ it's
+ // already been explicitly disabled in the previous
+ // requires evaluation (it really _has_ to be off)
+ if (otherItem->IsEnabled())
+ {
+ enabledCount ++;
+ }
+ inContextCount ++;
+ }
+ }
+ // Enable if there were no related items that were disabled
+ if (inContextCount > 0 && (enabledCount > 0) && !explicitlyDisabled)
+ {
+ explicitlyEnabled = TRUE;
+ enabled = TRUE;
+ active = FALSE;
+ }
+ }
+
+ items.Clear();
+ if (!precludes.IsEmpty())
+ {
+ StringToItems(GetDocument()->GetTopItem(), precludes, items);
+ int enabledCount = 0;
+ int inContextCount = 0;
+
+ for ( wxNode* node = items.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* otherItem = (ctConfigItem*) node->GetData();
+
+ if (inActiveContext && otherItem->IsInActiveContext())
+ {
+ // Make this enabled and inactive, _unless_ it's
+ // already been explicitly disabled in the previous
+ // requires evaluation (it really _has_ to be off)
+ if (otherItem->IsEnabled())
+ {
+ enabledCount ++;
+ }
+ }
+ }
+ // Disable if there were no related items that were disabled
+ if (inContextCount > 0 && (enabledCount == inContextCount) && !explicitlyEnabled)
+ {
+ enabled = FALSE;
+ active = FALSE;
+ }
+ }
+
+ // Finally check a sort of dependency: whether our
+ // context is active. If not, make this inactive.
+ if (!IsInActiveContext())
+ active = FALSE;
+
+ SetActive(active);
+
+ // If going active, set enabled state to the default state
+ if (active &&
+ oldActive != active &&
+ (GetType() == ctTypeBoolCheck || GetType() == ctTypeCheckGroup) &&
+ m_properties.FindProperty(wxT("default-state")))
+ {
+ bool defaultState = m_properties.FindProperty(wxT("default-state"))->GetVariant().GetBool();
+ enabled = defaultState;
+ }
+ Enable(enabled);
+
+ // Deal with setting a radio button
+ if (enabled && enabled != oldEnabled &&
+ (GetType() == ctTypeBoolRadio || GetType() == ctTypeRadioGroup))
+ {
+ wxList considered;
+ PropagateRadioButton(considered);
+ }
+}
+
+/// Get description, which may be dynamically
+/// generated depending on the property.
+wxString ctConfigItem::GetDescription(ctProperty* property)
+{
+ if (property->GetName() == wxT("description"))
+ {
+ wxString value(property->GetValue());
+ if (value.IsEmpty())
+ return wxT("Double-click on description to write a brief explanation of the setting.
");
+ else
+ return value;
+ }
+ else if (property->GetName() == wxT("notes"))
+ {
+ wxString value(property->GetValue());
+ if (value.IsEmpty())
+ return wxT("Double-click on notes to write notes about this setting.
");
+ else
+ return value;
+ }
+ return property->GetDescription();
+}
+
+/// Get the title for the property editor
+wxString ctConfigItem::GetTitle()
+{
+ wxString title(GetName());
+ if (GetType() == ctTypeCheckGroup ||
+ GetType() == ctTypeRadioGroup ||
+ GetType() == ctTypeBoolCheck ||
+ GetType() == ctTypeBoolRadio)
+ {
+ if (IsEnabled())
+ title = title + _T(" - enabled");
+ else
+ title = title + _T(" - disabled");
+ }
+ return title;
+}
+
+/// Propagate a change in enabled/disabled status
+void ctConfigItem::PropagateChange(wxList& considered)
+{
+ if (GetType() == ctTypeCheckGroup ||
+ GetType() == ctTypeRadioGroup ||
+ GetType() == ctTypeBoolCheck ||
+ GetType() == ctTypeBoolRadio)
+ {
+ // TODO: what about string, integer? Can they have
+ // dependencies?
+
+ for ( wxNode* node = GetDependents().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+
+ // Avoid loops
+ if (!considered.Member(child))
+ {
+ considered.Append(child);
+
+ child->EvaluateDependencies();
+ child->Sync();
+
+ child->PropagateChange(considered);
+ }
+ }
+ }
+}
+
+/// Process radio button selection
+void ctConfigItem::PropagateRadioButton(wxList& considered)
+{
+ if ((GetType() == ctTypeBoolRadio || GetType() == ctTypeRadioGroup) && IsEnabled())
+ {
+ wxString mutuallyExclusive(GetPropertyString(wxT("exclusivity")));
+
+ wxList list;
+ StringToItems(GetDocument()->GetTopItem(), mutuallyExclusive, list);
+
+ for ( wxNode* node = list.GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ if (child->IsEnabled() && child != this)
+ {
+ child->Enable(FALSE);
+ child->Sync();
+
+ if (!considered.Member(child))
+ child->PropagateChange(considered);
+ }
+ }
+ }
+}
diff --git a/utils/configtool/src/configitem.h b/utils/configtool/src/configitem.h
new file mode 100644
index 0000000000..8ebba6932b
--- /dev/null
+++ b/utils/configtool/src/configitem.h
@@ -0,0 +1,279 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configitem.h
+// Purpose: wxWindows Configuration Tool config item class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-03
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CT_CONFIGITEM_H_
+#define _CT_CONFIGITEM_H_
+
+#ifdef __GNUG__
+#pragma interface "configitem.cpp"
+#endif
+
+#include "wx/wx.h"
+#include "wx/treectrl.h"
+
+#include "property.h"
+
+class ctConfigToolDoc;
+
+/*!
+ * The type of config item
+ */
+
+enum ctConfigType
+{
+ ctTypeUnknown,
+ ctTypeGroup, // A group with no checkbox
+ ctTypeCheckGroup, // A group that can be switched on/off (check)
+ ctTypeRadioGroup, // A group that can be switched on/off (radio)
+ ctTypeString, // An option with a string value
+ ctTypeInteger, // An option with an integer value
+ ctTypeBoolCheck, // An on/off option
+ ctTypeBoolRadio // An on/off mutually exclusive option
+};
+
+/*!
+ * ctConfigItem represents a configuration setting.
+ * Each setting has a number of properties, some of
+ * which may be specific to a particular kind of
+ * setting, so we make it quite generic and extensible
+ * by using a property list.
+ */
+
+class ctConfigItem: public wxObject
+{
+public:
+ /// Ctor and dtor
+ ctConfigItem(ctConfigItem* parent, ctConfigType type, const wxString& name);
+ ctConfigItem();
+ ~ctConfigItem();
+
+ /// Copy constructor.
+ ctConfigItem(const ctConfigItem& item)
+ {
+ (*this) = item;
+ }
+
+/// Operations
+
+ /// Assignment operator.
+ void operator= (const ctConfigItem& item);
+
+ /// Create a clone
+ ctConfigItem* Clone()
+ {
+ ctConfigItem* item = new ctConfigItem;
+ *item = *this;
+ return item;
+ }
+
+ /// Create a clone of this and children
+ ctConfigItem* DeepClone();
+
+ /// Do additional actions to apply the property to the internal
+ /// representation.
+ void ApplyProperty(ctProperty* prop, const wxVariant& oldValue);
+
+ /// Clear children
+ void Clear();
+
+ /// Add a child
+ void AddChild(ctConfigItem* item);
+
+ /// Remove (but don't delete) a child
+ void RemoveChild(ctConfigItem* item);
+
+ /// Initialise standard properties
+ void InitProperties();
+
+ /// Convert string containing config item names to
+ /// an array of config item names
+ static void StringToArray(const wxString& items, wxArrayString& itemsArray);
+
+ /// Convert array containing config item names to
+ /// a string
+ static void ArrayToString(const wxArrayString& itemsArray, wxString& items);
+
+ /// Populate a list of items found in the string.
+ static void StringToItems(ctConfigItem* topItem, const wxString& items, wxList& list);
+
+ /// Find an item in this hierarchy
+ ctConfigItem* FindItem(const wxString& name);
+
+ /// Find the next sibling
+ ctConfigItem* FindNextSibling();
+
+ /// Find the previous sibling
+ ctConfigItem* FindPreviousSibling();
+
+ /// Sync appearance
+ void Sync();
+
+ /// Detach: remove from parent, and remove tree items
+ void Detach();
+
+ /// Attach: insert before the given position
+ void Attach(ctConfigItem* parent, ctConfigItem* insertbefore);
+
+ /// Hide from tree: make sure tree deletions won't delete
+ /// the config items
+ void DetachFromTree();
+
+ /// Evaluate the depends-on properties:
+ /// if any of the depends-on items are disabled,
+ /// then this one is disabled (and inactive).
+ void EvaluateDependencies();
+
+ /// Propagate a change in enabled/disabled status
+ void PropagateChange(wxList& considered);
+
+ /// Process radio button selection
+ void PropagateRadioButton(wxList& considered);
+
+ // An item is in the active context if:
+ // The context field is empty; or
+ // The context field contains a symbol that is currently enabled.
+ bool IsInActiveContext();
+
+/// Accessors
+
+ /// Returns the name property.
+ wxString GetName() const { return GetPropertyString(wxT("name")); }
+
+ /// Sets the name property.
+ void SetName(const wxString& name ) ;
+
+ /// Returns the value property.
+ wxVariant GetValue() const { return m_properties.FindPropertyValue(wxT("value")); }
+
+ /// Sets the value property.
+ void SetValue(const wxVariant& value ) ;
+
+ /// Returns the string for the given property.
+ wxString GetPropertyString(const wxString& propName) const { return m_properties.FindPropertyValueString(propName); }
+
+ /// Sets the string for the given property.
+ void SetPropertyString(const wxString& propName, const wxString& value) { m_properties.SetProperty(propName, value); }
+
+ /// Can we edit this property?
+ bool CanEditProperty(const wxString& propName) const ;
+
+ /// Returns the list of properties for
+ /// this item.
+ ctProperties& GetProperties() { return m_properties; }
+
+ /// Set the default property.
+ void SetDefaultProperty(const wxString& defaultProp) { m_defaultProperty = defaultProp; }
+
+ /// Get the default property.
+ wxString GetDefaultProperty() const { return m_defaultProperty; }
+
+ /// Is this item modified?
+ bool IsModified() const { return m_modified; }
+
+ /// Mark this as modified.
+ void Modify(bool modified = TRUE) { m_modified = modified; }
+
+ /// Is this item enabled? (checked/unchecked)
+ bool IsEnabled() const { return m_enabled; }
+
+ /// Enable or disable (check/uncheck)
+ void Enable(bool enable = TRUE) { m_enabled = enable; }
+
+ /// Is this item active? (sensitive to user input)
+ bool IsActive() const { return m_active; }
+
+ /// Make this (in)active
+ void SetActive(bool active = TRUE) { m_active = active; }
+
+ /// Set the type
+ void SetType(ctConfigType type) { m_type = type; }
+
+ // Get the type
+ ctConfigType GetType() const { return m_type; }
+
+ /// Set the tree item id
+ void SetTreeItem(wxTreeItemId id) { m_treeItemId = id; }
+
+ // Get the type
+ wxTreeItemId GetTreeItemId() const { return m_treeItemId ; }
+
+ /// Get the list of children
+ wxList& GetChildren() { return m_children; }
+
+ /// Get the nth child
+ ctConfigItem* GetChild(int n) const;
+
+ /// Get the child count
+ int GetChildCount() const;
+
+ /// Get the list of dependents
+ wxList& GetDependents() { return m_dependents; }
+
+ /// Get the parent
+ ctConfigItem* GetParent() const { return m_parent; }
+
+ /// Set the parent
+ void SetParent(ctConfigItem* parent) { m_parent = parent; }
+
+ /// Get the associated document (currently, assumes
+ /// there's only ever one document active)
+ ctConfigToolDoc* GetDocument() ;
+
+ /// Can have children?
+ bool CanHaveChildren() const;
+
+ /// Get description, which may be dynamically
+ /// generated depending on the property.
+ wxString GetDescription(ctProperty* property);
+
+ /// Get the title for the property editor
+ wxString GetTitle();
+
+protected:
+
+ /// The properties for this item.
+ ctProperties m_properties;
+
+ /// The default property, from the point of
+ /// of double-clicking the config item.
+ wxString m_defaultProperty;
+
+ /// Whether modified
+ bool m_modified;
+
+ /// The type of the config item
+ ctConfigType m_type;
+
+ /// The corresponding tree item
+ wxTreeItemId m_treeItemId;
+
+ /// Is this option enabled? (checked/unchecked)
+ bool m_enabled;
+
+ /// Is this option active? (i.e. sensitive to user input)
+ bool m_active;
+
+ /// The list of children.
+ wxList m_children;
+
+ /// The list of items that are dependent upon
+ // this one. This is refreshed when the configuration
+ // structurally changes, and is not saved to file.
+ wxList m_dependents;
+
+ /// The parent config item
+ ctConfigItem* m_parent;
+
+DECLARE_CLASS(ctConfigItem)
+};
+
+#endif
+// _CT_CONFIGITEM_H_
diff --git a/utils/configtool/src/configitemselector.cpp b/utils/configtool/src/configitemselector.cpp
new file mode 100644
index 0000000000..35b6ae10bc
--- /dev/null
+++ b/utils/configtool/src/configitemselector.cpp
@@ -0,0 +1,266 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configitemselector.cpp
+// Purpose: Selector for one or more config items
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation configitemselector.cpp
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "configitemselector.h"
+#include "configtooldoc.h"
+#include "configtoolview.h"
+#include "configitem.h"
+#include "mainframe.h"
+#include "wxconfigtool.h"
+
+////@begin XPM images
+////@end XPM images
+
+/*!
+ * ctConfigItemsSelector type definition
+ */
+
+IMPLEMENT_CLASS( ctConfigItemsSelector, wxDialog )
+
+/*!
+ * ctConfigItemsSelector event table definition
+ */
+
+BEGIN_EVENT_TABLE( ctConfigItemsSelector, wxDialog )
+
+////@begin ctConfigItemsSelector event table entries
+ EVT_BUTTON( ID_CONFIG_ADD, ctConfigItemsSelector::OnConfigAdd )
+ EVT_UPDATE_UI( ID_CONFIG_ADD, ctConfigItemsSelector::OnUpdateConfigAdd )
+
+ EVT_BUTTON( ID_CONFIG_REMOVE, ctConfigItemsSelector::OnConfigRemove )
+ EVT_UPDATE_UI( ID_CONFIG_REMOVE, ctConfigItemsSelector::OnUpdateConfigRemove )
+
+ EVT_BUTTON( wxID_OK, ctConfigItemsSelector::OnOk )
+
+////@end ctConfigItemsSelector event table entries
+
+END_EVENT_TABLE()
+
+/*!
+ * ctConfigItemsSelector constructor
+ */
+
+ctConfigItemsSelector::ctConfigItemsSelector( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+ wxDialog::Create( parent, id, caption, pos, size, style );
+
+ CreateControls();
+ InitSourceConfigList();
+}
+
+/*!
+ * Control creation for ctConfigItemsSelector
+ */
+
+void ctConfigItemsSelector::CreateControls()
+{
+////@begin ctConfigItemsSelector content construction
+
+ ctConfigItemsSelector* item1 = this;
+
+ wxBoxSizer* item2 = new wxBoxSizer(wxVERTICAL);
+ item1->SetSizer(item2);
+ item1->SetAutoLayout(TRUE);
+
+ wxBoxSizer* item3 = new wxBoxSizer(wxVERTICAL);
+ item2->Add(item3, 1, wxGROW|wxALL, 5);
+
+ wxStaticText* item4 = new wxStaticText(item1, wxID_STATIC, _("Please edit the list of configuration items by selecting from the\nlist below."), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item4, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxStaticText* item5 = new wxStaticText(item1, wxID_STATIC, _("&Available items:"), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item5, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxString* item6Strings = NULL;
+ wxListBox* item6 = new wxListBox(item1, ID_AVAILABLE_CONFIG_ITEMS, wxDefaultPosition, wxSize(-1, 150), 0, item6Strings, wxLB_SINGLE|wxLB_SORT);
+ item3->Add(item6, 1, wxGROW|wxALL, 5);
+
+ wxStaticText* item7 = new wxStaticText(item1, wxID_STATIC, _("&List of configuration items:"), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item7, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxBoxSizer* item8 = new wxBoxSizer(wxHORIZONTAL);
+ item3->Add(item8, 0, wxGROW, 5);
+
+ wxString* item9Strings = NULL;
+ wxListBox* item9 = new wxListBox(item1, ID_CONFIG_ITEMS, wxDefaultPosition, wxSize(-1, 100), 0, item9Strings, wxLB_SINGLE);
+ item8->Add(item9, 1, wxGROW|wxALL, 5);
+
+ wxBoxSizer* item10 = new wxBoxSizer(wxVERTICAL);
+ item8->Add(item10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item11 = new wxButton(item1, ID_CONFIG_ADD, _("A&dd"), wxDefaultPosition, wxDefaultSize, 0);
+ item10->Add(item11, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+ wxButton* item12 = new wxButton(item1, ID_CONFIG_REMOVE, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0);
+ item10->Add(item12, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+ wxBoxSizer* item13 = new wxBoxSizer(wxHORIZONTAL);
+ item3->Add(item13, 0, wxGROW, 5);
+
+ item13->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item15 = new wxButton(item1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0);
+ item15->SetDefault();
+ item13->Add(item15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item16 = new wxButton(item1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0);
+ item13->Add(item16, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ GetSizer()->Fit(this);
+ GetSizer()->SetSizeHints(this);
+ Centre();
+////@end ctConfigItemsSelector content construction
+}
+
+/*!
+ * Event handler for ID_CONFIG_ADD
+ */
+
+void ctConfigItemsSelector::OnConfigAdd( wxCommandEvent& event )
+{
+ wxListBox* masterList = wxDynamicCast(FindWindow(ID_AVAILABLE_CONFIG_ITEMS), wxListBox);
+ wxListBox* listBox = wxDynamicCast(FindWindow(ID_CONFIG_ITEMS), wxListBox);
+ if (masterList)
+ {
+ if (masterList->GetSelection() > -1)
+ {
+ wxString str = masterList->GetStringSelection();
+ if (m_configItems.Index(str) == wxNOT_FOUND)
+ {
+ listBox->Append(str);
+ m_configItems.Add(str);
+ }
+ }
+ }
+}
+
+/*!
+ * Event handler for ID_CONFIG_REMOVE
+ */
+
+void ctConfigItemsSelector::OnConfigRemove( wxCommandEvent& event )
+{
+ wxListBox* listBox = wxDynamicCast(FindWindow(ID_CONFIG_ITEMS), wxListBox);
+ if (listBox)
+ {
+ if (listBox->GetSelection() > -1)
+ {
+ wxString str = listBox->GetStringSelection();
+ listBox->Delete(listBox->GetSelection());
+ m_configItems.Remove(str);
+ }
+ }
+}
+
+/*!
+ * Event handler for wxID_OK
+ */
+
+void ctConfigItemsSelector::OnOk( wxCommandEvent& event )
+{
+ // Replace with custom code
+ event.Skip();
+}
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool ctConfigItemsSelector::ShowToolTips()
+{
+ return TRUE;
+}
+/*!
+ * Update event handler for ID_CONFIG_ADD
+ */
+
+void ctConfigItemsSelector::OnUpdateConfigAdd( wxUpdateUIEvent& event )
+{
+ wxListBox* masterList = wxDynamicCast(FindWindow(ID_AVAILABLE_CONFIG_ITEMS), wxListBox);
+ event.Enable(masterList && masterList->GetSelection() != -1);
+}
+
+/*!
+ * Update event handler for ID_CONFIG_REMOVE
+ */
+
+void ctConfigItemsSelector::OnUpdateConfigRemove( wxUpdateUIEvent& event )
+{
+ wxListBox* listBox = wxDynamicCast(FindWindow(ID_CONFIG_ITEMS), wxListBox);
+ event.Enable(listBox && listBox->GetSelection() != -1);
+}
+
+/// Initialise the master list
+void ctConfigItemsSelector::InitSourceConfigList(ctConfigItem* item)
+{
+ wxListBox* masterList = wxDynamicCast(FindWindow(ID_AVAILABLE_CONFIG_ITEMS), wxListBox);
+ if (!item)
+ item = wxGetApp().GetMainFrame()->GetDocument()->GetTopItem();
+
+ if (!item)
+ return;
+
+ bool addIt = FALSE;
+
+ if (item->GetType() == ctTypeGroup)
+ addIt = FALSE;
+ else if (item->GetType() == ctTypeCheckGroup)
+ addIt = TRUE;
+ else if (item->GetType() == ctTypeRadioGroup)
+ addIt = TRUE;
+ else if (item->GetType() == ctTypeString)
+ addIt = TRUE;
+ else if (item->GetType() == ctTypeBoolCheck)
+ addIt = TRUE;
+ else if (item->GetType() == ctTypeBoolRadio)
+ addIt = TRUE;
+ else if (item->GetType() == ctTypeInteger)
+ addIt = TRUE;
+ if (addIt)
+ {
+ masterList->Append(item->GetName());
+ }
+
+ wxNode* node = item->GetChildren().GetFirst();
+ while (node)
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ InitSourceConfigList(child);
+
+ node = node->Next();
+ }
+}
+
+/// Set the initial list
+void ctConfigItemsSelector::SetConfigList(const wxArrayString& items)
+{
+ m_configItems = items;
+ wxListBox* listBox = wxDynamicCast(FindWindow(ID_CONFIG_ITEMS), wxListBox);
+ listBox->Clear();
+
+ size_t i;
+ for (i = 0; i < items.GetCount(); i++)
+ listBox->Append(items[i]);
+}
+
diff --git a/utils/configtool/src/configitemselector.h b/utils/configtool/src/configitemselector.h
new file mode 100644
index 0000000000..7b705736ae
--- /dev/null
+++ b/utils/configtool/src/configitemselector.h
@@ -0,0 +1,104 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configitemselector.h
+// Purpose: Selector for one or more config items
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CONFIGITEMSELECTOR_H_
+#define _CONFIGITEMSELECTOR_H_
+
+#ifdef __GNUG__
+#pragma interface configitemselector.h
+#endif
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_DIALOG 10000
+#define ID_AVAILABLE_CONFIG_ITEMS 10002
+#define ID_CONFIG_ITEMS 10005
+#define ID_CONFIG_ADD 10006
+#define ID_CONFIG_REMOVE 10007
+////@end control identifiers
+
+class ctConfigItem;
+
+/*!
+ * ctConfigItemsSelector class declaration
+ */
+
+class ctConfigItemsSelector: public wxDialog
+{
+public:
+ /// Constructor
+ ctConfigItemsSelector( wxWindow* parent, wxWindowID id = -1, const wxString& caption = _("Configuration Items Selector"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU );
+
+ /// Creates the controls and sizers
+ void CreateControls();
+
+////@begin ctConfigItemsSelector event handler declarations
+
+ /// Event handler for ID_CONFIG_ADD
+ void OnConfigAdd( wxCommandEvent& event );
+
+ /// Update event handler for ID_CONFIG_ADD
+ void OnUpdateConfigAdd( wxUpdateUIEvent& event );
+
+ /// Event handler for ID_CONFIG_REMOVE
+ void OnConfigRemove( wxCommandEvent& event );
+
+ /// Update event handler for ID_CONFIG_REMOVE
+ void OnUpdateConfigRemove( wxUpdateUIEvent& event );
+
+ /// Event handler for wxID_OK
+ void OnOk( wxCommandEvent& event );
+
+////@end ctConfigItemsSelector event handler declarations
+
+////@begin ctConfigItemsSelector member function declarations
+
+////@end ctConfigItemsSelector member function declarations
+
+ /// Initialise the master list
+ void InitSourceConfigList(ctConfigItem* item = NULL);
+
+ /// Set the initial list
+ void SetConfigList(const wxArrayString& items);
+
+ /// Get the list
+ const wxArrayString& GetConfigList() const { return m_configItems; }
+
+ /// Should we show tooltips?
+ static bool ShowToolTips();
+
+ DECLARE_CLASS( ctConfigItemsSelector )
+ DECLARE_EVENT_TABLE()
+
+protected:
+ wxArrayString m_configItems;
+
+};
+
+#endif
+ // _CONFIGITEMSELECTOR_H_
diff --git a/utils/configtool/src/configtooldoc.cpp b/utils/configtool/src/configtooldoc.cpp
new file mode 100644
index 0000000000..d5ae2a8b24
--- /dev/null
+++ b/utils/configtool/src/configtooldoc.cpp
@@ -0,0 +1,992 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtooldoc.h
+// Purpose: Document class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "configtooldoc.h"
+#endif
+
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/config.h"
+#include "wx/textfile.h"
+#include "wx/process.h"
+#include "wx/mimetype.h"
+#include "wx/process.h"
+#include "wx/wfstream.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "configtooldoc.h"
+#include "configtoolview.h"
+#include "configtree.h"
+#include "mainframe.h"
+#include "utils.h"
+#include "wxconfigtool.h"
+#include "htmlparser.h"
+
+IMPLEMENT_DYNAMIC_CLASS(ctConfigToolDoc, wxDocument)
+
+// Ctor
+ctConfigToolDoc::ctConfigToolDoc()
+{
+ m_topItem = NULL;
+ m_clipboardItem = NULL;
+}
+
+// Dtor
+ctConfigToolDoc::~ctConfigToolDoc()
+{
+ DeleteItems();
+ ClearClipboard();
+ if (GetCommandProcessor())
+ GetCommandProcessor()->SetEditMenu(NULL);
+}
+
+// Delete all the items not already deleted
+void ctConfigToolDoc::DeleteItems()
+{
+ if (m_topItem)
+ delete m_topItem;
+ m_topItem = NULL;
+}
+
+/// Clears the clipboard item.
+void ctConfigToolDoc::ClearClipboard()
+{
+ if (m_clipboardItem)
+ delete m_clipboardItem;
+ m_clipboardItem = NULL;
+}
+
+/// Sets the clipboard item.
+void ctConfigToolDoc::SetClipboardItem(ctConfigItem* item)
+{
+ if (m_clipboardItem)
+ delete m_clipboardItem;
+ m_clipboardItem = item;
+}
+
+
+// Closes and clears the document
+bool ctConfigToolDoc::OnCloseDocument()
+{
+ if (wxDocument::OnCloseDocument())
+ {
+ ctConfigToolHint hint(NULL, ctClear);
+ UpdateAllViews (NULL, & hint);
+
+ DeleteItems();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+// Saves the doc
+bool ctConfigToolDoc::Save()
+{
+ bool ret = FALSE;
+
+ if (!IsModified() && m_savedYet) return TRUE;
+ if (m_documentFile == wxT("") || !m_savedYet)
+ ret = SaveAs();
+ else
+ ret = OnSaveDocument(m_documentFile);
+ if ( ret )
+ SetDocumentSaved(TRUE);
+ return ret;
+}
+
+// Create the document
+bool ctConfigToolDoc::OnCreate(const wxString& path, long flags)
+{
+ GetCommandProcessor()->SetEditMenu(wxGetApp().GetMainFrame()->GetEditMenu());
+ GetCommandProcessor()->Initialize();
+ GetCommandProcessor()->ClearCommands();
+
+ // wxGetApp().m_currentDoc = this;
+
+ if (flags & wxDOC_NEW)
+ {
+ ctConfigItem* rootItem = new ctConfigItem(NULL, ctTypeGroup, _T("Configuration"));
+ //rootItem->InitProperties();
+ rootItem->GetProperties().AddProperty(
+ new ctProperty(
+ wxT("The item description."),
+ wxVariant(wxT(""), wxT("description")),
+ wxT("multiline")));
+
+ rootItem->SetPropertyString(_T("description"),
+ _T("This is the top-level configuration item."));
+
+
+ SetTopItem(rootItem);
+
+ Modify(FALSE);
+ SetDocumentSaved(FALSE);
+
+ wxString rootName(wxT("untitled"));
+ wxStripExtension(rootName);
+ SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName));
+ }
+
+ // Creates the view, so do any view updating after this
+ bool success = wxDocument::OnCreate(path, flags);
+
+ if (success)
+ {
+ if (flags & wxDOC_NEW)
+ {
+ wxBusyCursor wait;
+
+ ctConfigToolHint hint(NULL, ctInitialUpdate);
+ UpdateAllViews (NULL, & hint);
+
+ SetFilename(GetFilename(), TRUE);
+ }
+ }
+ return success;
+}
+
+// Save the document
+bool ctConfigToolDoc::OnSaveDocument(const wxString& filename)
+{
+ wxBusyCursor cursor;
+
+ const wxString strOldPath(GetFilename());
+
+ // Do some backing up first
+
+ // This is the backup filename
+ wxString backupFilename(filename);
+ backupFilename += wxT(".bak");
+
+ // This is the temporary copy of the backup
+ wxString tempFilename(filename);
+ tempFilename += wxT(".tmp");
+ if (wxFileExists(tempFilename))
+ wxRemoveFile(tempFilename);
+
+ bool leaveBackup = TRUE;
+
+ bool saved = DoSave(tempFilename);
+
+ if (saved)
+ {
+ // Remove the old .bak file
+ if (wxFileExists(backupFilename))
+ {
+ wxRemoveFile(backupFilename);
+ }
+
+ // Copy the old file to the .bak
+
+ if (leaveBackup)
+ {
+ if (wxFileExists(filename))
+ {
+ if (!wxRenameFile(filename, backupFilename))
+ {
+ wxCopyFile(filename, backupFilename);
+ wxRemoveFile(filename);
+ }
+ }
+ }
+ else
+ {
+ if (wxFileExists(filename))
+ wxRemoveFile(filename);
+ }
+
+ // Finally, copy the temporary file to the proper filename
+ if (!wxRenameFile(tempFilename, filename))
+ {
+ wxCopyFile(tempFilename, filename);
+ wxRemoveFile(tempFilename);
+ }
+
+ Modify(FALSE);
+ ((ctConfigToolView*)GetFirstView())->OnChangeFilename();
+ SetDocumentSaved(TRUE);
+ SetFilename(filename);
+ wxGetApp().GetSettings().m_lastFilename = filename;
+ } else
+ {
+ SetFilename(strOldPath);
+ }
+ wxGetApp().GetMainFrame()->UpdateFrameTitle();
+ return saved;
+}
+
+// Open the document
+bool ctConfigToolDoc::OnOpenDocument(const wxString& filename)
+{
+ wxBusyCursor cursor;
+
+ bool opened = DoOpen(filename);
+
+ if (opened)
+ {
+ SetFilename(filename);
+ wxGetApp().GetSettings().m_lastFilename = filename;
+
+ ((ctConfigToolView*)GetFirstView())->OnChangeFilename();
+
+ RefreshDependencies();
+
+ // ctConfigToolHint hint(NULL, ctFilenameChanged);
+ ctConfigToolHint hint(NULL, ctInitialUpdate);
+ UpdateAllViews (NULL, & hint);
+ }
+
+ SetDocumentSaved(TRUE); // Necessary or it will pop up the Save As dialog
+
+ return opened;
+}
+
+/// Save the settings file
+bool ctConfigToolDoc::DoSave(const wxString& filename)
+{
+ wxFileOutputStream stream(filename);
+ if (!stream.Ok())
+ return FALSE;
+
+ stream << wxT("\n");
+ stream << wxT("");
+
+ DoSave(m_topItem, stream, 1);
+
+ stream << wxT("\n\n");
+
+ return TRUE;
+}
+
+inline static void OutputIndentation(wxOutputStream& stream, int indent)
+{
+ wxString str = wxT("\n");
+ for (int i = 0; i < indent; i++)
+ str << wxT(' ') << wxT(' ');
+ stream << str ;
+}
+
+/// Recursive helper function for file saving
+bool ctConfigToolDoc::DoSave(ctConfigItem* item, wxOutputStream& stream, int indent)
+{
+ OutputIndentation(stream, indent*2);
+
+ wxString name(item->GetName());
+ wxString s;
+ wxString typeStr;
+ if (item->GetType() == ctTypeGroup)
+ typeStr = wxT("group");
+ else if (item->GetType() == ctTypeCheckGroup)
+ typeStr = wxT("check-group");
+ else if (item->GetType() == ctTypeRadioGroup)
+ typeStr = wxT("radio-group");
+ else if (item->GetType() == ctTypeString)
+ typeStr = wxT("string");
+ else if (item->GetType() == ctTypeBoolCheck)
+ typeStr = wxT("bool-check");
+ else if (item->GetType() == ctTypeBoolRadio)
+ typeStr = wxT("bool-radio");
+ else if (item->GetType() == ctTypeInteger)
+ typeStr = wxT("integer");
+ else
+ typeStr = wxT("unknown");
+
+ stream << wxT("");
+
+ indent ++;
+
+ OutputIndentation(stream, indent*2);
+ if (item->IsActive())
+ stream << wxT("1");
+ else
+ stream << wxT("0");
+ OutputIndentation(stream, indent*2);
+ if (item->IsEnabled())
+ stream << wxT("1");
+ else
+ stream << wxT("0");
+
+ // Output properties
+ wxNode* node = item->GetProperties().GetList().GetFirst();
+ while (node)
+ {
+ ctProperty* prop = (ctProperty*) node->GetData();
+ OutputIndentation(stream, indent*2);
+ stream << wxT("<") << prop->GetName() ;
+
+ if (prop->IsCustom())
+ {
+ stream << wxT(" custom=\"true\"");
+ stream << wxT(" type=\"") << prop->GetVariant().GetType() << wxT("\"");
+ stream << wxT(" editor-type=\"") << prop->GetEditorType() << wxT("\"");
+ stream << wxT(" description=\"") << prop->GetDescription() << wxT("\"");
+ if (prop->GetChoices().GetCount() > 0)
+ {
+ wxString choices;
+ ctConfigItem::ArrayToString(prop->GetChoices(), choices);
+ stream << wxT(" choices=\"") << choices << wxT("\"");
+ }
+ }
+
+ stream << wxT(">");
+
+ stream << ctEscapeHTMLCharacters(prop->GetVariant().GetString()) ;
+ stream << wxT("") << prop->GetName() << wxT(">");
+
+ node = node->Next();
+ }
+
+ // Output children
+ node = item->GetChildren().GetFirst();
+ while (node)
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ DoSave(child, stream, indent);
+
+ node = node->Next();
+ }
+
+ indent --;
+
+ OutputIndentation(stream, indent*2);
+ stream << wxT("");
+
+ return TRUE;
+}
+
+/// Open the settings file
+bool ctConfigToolDoc::DoOpen(const wxString& filename)
+{
+ wxSimpleHtmlParser parser;
+ if (parser.ParseFile(filename))
+ {
+ ctConfigToolHint hint(NULL, ctClear);
+ UpdateAllViews (NULL, & hint);
+ m_topItem = NULL;
+
+ if (parser.GetTopLevelTag()->GetChildren())
+ {
+ wxSimpleHtmlTag* settingsTag = parser.GetTopLevelTag()->GetChildren()->FindTag(wxT("settings"));
+ if (settingsTag && settingsTag->GetChildren())
+ {
+ wxSimpleHtmlTag* firstSettingTag = settingsTag->GetChildren();
+ if (firstSettingTag)
+ DoOpen(firstSettingTag, NULL);
+ return TRUE;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static bool GetHtmlBoolValue(const wxString& value)
+{
+ if (value == wxT("true") || value == wxT("TRUE") || value == wxT("1"))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static int GetHtmlIntegerValue(const wxString& value)
+{
+ return wxAtoi(value);
+}
+
+static double GetHtmlDoubleValue(const wxString& value)
+{
+ return wxAtof(value);
+}
+
+bool ctConfigToolDoc::DoOpen(wxSimpleHtmlTag* tag, ctConfigItem* parent)
+{
+ ctConfigItem* newItem = NULL;
+ if (tag->NameIs(wxT("setting")))
+ {
+ wxSimpleHtmlAttribute* attr = tag->FindAttribute(wxT("type"));
+ if (attr)
+ {
+ ctConfigType type = ctTypeUnknown;
+ wxString typeStr(attr->GetValue());
+ if (typeStr == wxT("group"))
+ type = ctTypeGroup;
+ else if (typeStr == wxT("option-group") || typeStr == wxT("check-group"))
+ type = ctTypeCheckGroup;
+ else if (typeStr == wxT("radio-group"))
+ type = ctTypeRadioGroup;
+ else if (typeStr == wxT("bool-check"))
+ type = ctTypeBoolCheck;
+ else if (typeStr == wxT("bool-radio"))
+ type = ctTypeBoolRadio;
+ else if (typeStr == wxT("string"))
+ type = ctTypeString;
+ else if (typeStr == wxT("integer"))
+ type = ctTypeInteger;
+ else
+ {
+ wxLogError(wxT("Unknown type %s"), (const wxChar*) typeStr);
+ }
+ if (type != ctTypeUnknown)
+ {
+ newItem = new ctConfigItem(parent, type, wxT(""));
+ newItem->InitProperties();
+ if (!parent)
+ SetTopItem(newItem);
+ }
+ }
+ }
+ wxSimpleHtmlTag* childTag = tag->GetChildren();
+
+ while (childTag)
+ {
+ if (childTag->GetType() == wxSimpleHtmlTag_Open)
+ {
+ if (childTag->GetName() == wxT("setting"))
+ {
+ DoOpen(childTag, newItem);
+ }
+ else if (childTag->GetName() == wxT("name"))
+ {
+ if (newItem)
+ {
+ wxString name(childTag->GetNext()->GetTagText());
+ newItem->SetName(name);
+ }
+ }
+ else if (childTag->GetName() == wxT("active"))
+ {
+ if (newItem)
+ newItem->SetActive(GetHtmlBoolValue(childTag->GetNext()->GetTagText()));
+ }
+ else if (childTag->GetName() == wxT("enabled"))
+ {
+ if (newItem)
+ newItem->Enable(GetHtmlBoolValue(childTag->GetNext()->GetTagText()));
+ }
+ else
+ {
+ if (newItem)
+ {
+ ctProperty* prop = newItem->GetProperties().FindProperty(childTag->GetName());
+ if (!prop)
+ {
+ // A custom property, else an obsolete
+ // property that we should ignore.
+ wxString isCustom;
+ if (childTag->GetAttributeValue(isCustom, wxT("custom")) &&
+ isCustom == wxT("true"))
+ {
+ prop = new ctProperty;
+
+ wxString name(childTag->GetName());
+ wxString type(wxT("string"));
+ wxString choices;
+ wxString editorType(wxT("string"));
+ wxString description(wxT(""));
+ childTag->GetAttributeValue(type, wxT("type"));
+ childTag->GetAttributeValue(type, wxT("editor-type"));
+ childTag->GetAttributeValue(type, wxT("choices"));
+ childTag->GetAttributeValue(description, wxT("description"));
+
+ if (type == wxT("bool"))
+ prop->GetVariant() = wxVariant((bool) FALSE, name);
+ else if (type == wxT("double"))
+ prop->GetVariant() = wxVariant((double) 0.0, name);
+ else if (type == wxT("long"))
+ prop->GetVariant() = wxVariant((long) 0, name);
+ else
+ prop->GetVariant() = wxVariant(wxT(""), name);
+ prop->SetDescription(description);
+ prop->SetCustom(TRUE);
+ prop->SetEditorType(editorType);
+ if (!choices.IsEmpty())
+ {
+ wxArrayString arr;
+ ctConfigItem::StringToArray(choices, arr);
+ prop->SetChoices(arr);
+ }
+ newItem->GetProperties().AddProperty(prop);
+ }
+ }
+ if (prop)
+ {
+ if (prop->GetVariant().GetType() == wxT("string"))
+ prop->GetVariant() = childTag->GetNext()->GetTagText();
+ else if (prop->GetVariant().GetType() == wxT("long"))
+ prop->GetVariant() = (long) GetHtmlIntegerValue(childTag->GetNext()->GetTagText());
+ else if (prop->GetVariant().GetType() == wxT("bool"))
+ prop->GetVariant() = (bool) GetHtmlBoolValue(childTag->GetNext()->GetTagText());
+ else if (prop->GetVariant().GetType() == wxT("double"))
+ prop->GetVariant() = (double) GetHtmlDoubleValue(childTag->GetNext()->GetTagText());
+ }
+ }
+ }
+ }
+ childTag = childTag->GetNext();
+ }
+ return TRUE;
+}
+
+/// Clear dependencies
+void ctConfigToolDoc::ClearDependencies(ctConfigItem* item)
+{
+ if (!item)
+ item = GetTopItem();
+
+ item->GetDependents().Clear();
+ for ( wxNode* node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ ClearDependencies(child);
+ }
+}
+
+/// Refresh dependencies
+void ctConfigToolDoc::RefreshDependencies()
+{
+ ClearDependencies(GetTopItem());
+ RefreshDependencies(GetTopItem());
+}
+
+/// Refresh dependencies
+void ctConfigToolDoc::RefreshDependencies(ctConfigItem* item)
+{
+ wxArrayString requiresArr;
+ wxString requires = item->GetPropertyString(wxT("requires"));
+ wxString precludes = item->GetPropertyString(wxT("precludes"));
+ wxString enabledIf = item->GetPropertyString(wxT("enabled-if"));
+ wxString enabledIfNot = item->GetPropertyString(wxT("enabled-if-not"));
+ wxString context = item->GetPropertyString(wxT("context"));
+
+ if (!requires.IsEmpty())
+ item->StringToArray(requires, requiresArr);
+
+ if (!precludes.IsEmpty())
+ item->StringToArray(precludes, requiresArr);
+
+ if (!enabledIfNot.IsEmpty())
+ item->StringToArray(enabledIfNot, requiresArr);
+
+ if (!enabledIf.IsEmpty())
+ item->StringToArray(enabledIf, requiresArr);
+
+ // Add the parent to the list of dependencies, if the
+ // parent is a check or radio group.
+ ctConfigItem* parent = item->GetParent();
+ if (parent &&
+ (parent->GetType() == ctTypeCheckGroup ||
+ parent->GetType() == ctTypeRadioGroup))
+ requiresArr.Add(parent->GetName());
+
+ // Also look in 'context' since these items
+ // are another kind of dependency (switching to
+ // a different platform may cause the dependencies
+ // to be evaluated differently).
+ if (!context.IsEmpty())
+ item->StringToArray(context, requiresArr);
+
+ size_t i;
+ for (i = 0; i < requiresArr.GetCount(); i++)
+ {
+ wxString itemName(requiresArr[i]);
+ ctConfigItem* otherItem = GetTopItem()->FindItem(itemName);
+ if (otherItem && !otherItem->GetDependents().Member(item))
+ {
+ otherItem->GetDependents().Append(item);
+ }
+ }
+ for ( wxNode* node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ RefreshDependencies(child);
+ }
+}
+
+/// Generate the text of a setup.h
+wxString ctConfigToolDoc::GenerateSetup()
+{
+ wxString str;
+ str << wxT("/*\n * setup.h\n * Generated by wxConfigTool\n *\n */\n\n");
+
+ GenerateSetup(GetTopItem(), str);
+
+ return str;
+}
+
+/// Helper function
+void ctConfigToolDoc::GenerateSetup(ctConfigItem* item, wxString& str)
+{
+ // Generate the setup.h entries for this item
+ wxString name = item->GetName();
+
+ // We don't process the platform choice
+ if (item->GetName() == wxT("Platform"))
+ return;
+
+ if (item->IsInActiveContext() &&
+ (item->GetType() == ctTypeCheckGroup ||
+ item->GetType() == ctTypeRadioGroup ||
+ item->GetType() == ctTypeBoolCheck ||
+ item->GetType() == ctTypeBoolRadio))
+ {
+ // TODO: write description
+ wxString name = item->GetName();
+ if (name.Left(6) == wxT("wxUSE_") ||
+ name == wxT("REMOVE_UNUSED_ARG") || // Hack alert: change to wxUSE_UNUSED_ARG_REMOVAL
+ name.Find(wxT("COMPATIBILITY")) != wxNOT_FOUND)
+ {
+ str << wxT("#define ") << name ;
+ if (item->IsEnabled())
+ str << wxT(" 1");
+ else
+ str << wxT(" 0");
+ str << wxT("\n\n");
+ }
+ }
+
+ for ( wxNode* node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ GenerateSetup(child, str);
+ }
+}
+
+
+/// Generate a configure command
+wxString ctConfigToolDoc::GenerateConfigureCommand()
+{
+ wxString str;
+ str << wxT("# configurewx\n# Generated by wxConfigTool\n\n");
+
+ wxString path = GetFrameworkDir(TRUE);
+ bool makeUnix = TRUE;
+ if (!path.IsEmpty())
+ {
+ if (makeUnix)
+ path += wxT("/");
+ else
+ path += wxFILE_SEP_PATH ;
+ }
+
+ str << path << wxT("configure");
+
+ // Find the platform option to use
+ ctConfigItem* platformsFolder = GetTopItem()->FindItem(wxT("Platform"));
+ if (platformsFolder)
+ {
+ for ( wxNode* node = platformsFolder->GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ if (child->GetType() == ctTypeBoolRadio && child->IsEnabled())
+ {
+ wxString configureCommand = child->GetPropertyString(wxT("configure-command"));
+ if (!configureCommand.IsEmpty())
+ str << wxT(" ") << configureCommand;
+ }
+ }
+ }
+
+ GenerateConfigureCommand(GetTopItem(), str);
+ return str;
+}
+
+/// Helper function
+void ctConfigToolDoc::GenerateConfigureCommand(ctConfigItem* item, wxString& str)
+{
+ // We don't process the platform group, since we've
+ // already done so.
+ if (item->GetName() == wxT("Platform"))
+ return;
+
+ if (item->IsInActiveContext() &&
+ (item->GetType() == ctTypeCheckGroup ||
+ item->GetType() == ctTypeRadioGroup ||
+ item->GetType() == ctTypeBoolCheck ||
+ item->GetType() == ctTypeBoolRadio))
+ {
+ wxString name = item->GetName();
+ wxString configureCommand = item->GetPropertyString(wxT("configure-command"));
+ if (!configureCommand.IsEmpty())
+ {
+ if (!item->IsEnabled())
+ {
+ // Replace 'enable' with 'disable' if this
+ // option is off.
+ configureCommand.Replace(wxT("--enable-"), wxT("--disable-"));
+ configureCommand.Replace(wxT("--with-"), wxT("--without-"));
+ }
+ ctProperty* prop = item->GetProperties().FindProperty(wxT("builtin"));
+ if (prop && prop->GetVariant().GetType() == wxT("bool"))
+ {
+ bool builtin = prop->GetVariant().GetBool();
+ str << wxT(" ") << configureCommand;
+ if (builtin)
+ str << wxT("=builtin");
+ else
+ str << wxT("=sys");
+ }
+ else
+ {
+ ctProperty* prop = item->GetProperties().FindProperty(wxT("value"));
+ if (prop && prop->GetVariant().GetType() == wxT("string"))
+ {
+ wxString val = prop->GetVariant().GetString();
+ if (item->IsEnabled() && !val.IsEmpty())
+ {
+ str << wxT(" ") << configureCommand;
+ str << wxT("=\"") << val << wxT("\"");
+ }
+ // If the string is empty, ignore this parameter,
+ // since it's obviously intended to be supplied
+ // only if there's a string to use and it's enabled.
+ }
+ else
+ {
+ str << wxT(" ") << configureCommand;
+ }
+ }
+ }
+ }
+
+ for ( wxNode* node = item->GetChildren().GetFirst(); node; node = node->GetNext() )
+ {
+ ctConfigItem* child = (ctConfigItem*) node->GetData();
+ GenerateConfigureCommand(child, str);
+ }
+}
+
+/// Gets the current framework directory
+wxString ctConfigToolDoc::GetFrameworkDir(bool makeUnix)
+{
+ wxString path = wxGetApp().GetSettings().m_frameworkDir;
+ if (wxGetApp().GetSettings().m_useEnvironmentVariable)
+ {
+ // Should probably allow other variables
+ // to be used, and maybe expand variables within m_frameworkDir
+ path = wxGetenv(wxT("WXWIN"));
+#ifdef __WXMSW__
+ if (makeUnix)
+ path.Replace(wxT("\\"), wxT("/"));
+#endif
+ }
+ return path;
+}
+
+
+/*
+ * Implements a document editing command.
+ */
+
+ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId,
+ ctConfigItem* activeState, ctConfigItem* savedState,
+ ctConfigItem* parent, ctConfigItem* insertBefore,
+ bool ignoreFirstTime): wxCommand(TRUE, name)
+{
+ m_activeState = activeState;
+ m_savedState = savedState;
+ m_ignoreThis = ignoreFirstTime;
+ m_cmdId = cmdId;
+ m_properties = NULL;
+ m_parent = parent;
+ m_insertBefore = insertBefore;
+}
+
+ctConfigCommand::ctConfigCommand(const wxString& name, int cmdId,
+ ctConfigItem* activeState, ctProperties* properties,
+ bool ignoreFirstTime): wxCommand(TRUE, name)
+{
+ m_activeState = activeState;
+ m_savedState = NULL;
+ m_properties = properties;
+ m_ignoreThis = ignoreFirstTime;
+ m_cmdId = cmdId;
+ m_properties = properties;
+ m_parent = NULL;
+ m_insertBefore = NULL;
+}
+
+ctConfigCommand::~ctConfigCommand()
+{
+ if (m_savedState)
+ delete m_savedState;
+ if (m_properties)
+ delete m_properties;
+}
+
+bool ctConfigCommand::Do()
+{
+ return DoAndUndo(TRUE);
+}
+
+bool ctConfigCommand::Undo()
+{
+ return DoAndUndo(FALSE);
+}
+
+// Combine Do and Undo into one
+bool ctConfigCommand::DoAndUndo(bool doCmd)
+{
+ switch (m_cmdId)
+ {
+ case ctCMD_CUT:
+ {
+ if (doCmd)
+ {
+ wxASSERT(m_savedState == NULL);
+ wxASSERT(m_activeState != NULL);
+
+ ctConfigItem* newItem = m_activeState->DeepClone();
+ ctConfigToolDoc* doc = m_activeState->GetDocument();
+
+ // This will delete the old clipboard contents, if any.
+ doc->SetClipboardItem(newItem);
+
+ m_parent = m_activeState->GetParent();
+ m_insertBefore = m_activeState->FindNextSibling();
+
+ m_activeState->Detach();
+ m_savedState = m_activeState;
+ m_activeState = NULL;
+
+ m_savedState->GetDocument()->Modify(TRUE);
+ ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
+ view->OnChangeFilename();
+ }
+ else
+ {
+ wxASSERT(m_savedState != NULL);
+ wxASSERT(m_activeState == NULL);
+
+ m_savedState->GetDocument()->Modify(TRUE);
+ m_savedState->Attach(m_parent, m_insertBefore);
+ ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
+ view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
+ m_activeState = m_savedState;
+ m_savedState = NULL;
+ m_parent = NULL;
+ m_insertBefore = NULL;
+ view->OnChangeFilename();
+ }
+ break;
+ }
+ case ctCMD_PASTE:
+ {
+ if (doCmd)
+ {
+ wxASSERT(m_savedState != NULL);
+ wxASSERT(m_activeState == NULL);
+
+ m_savedState->GetDocument()->Modify(TRUE);
+ m_savedState->Attach(m_parent, m_insertBefore);
+ ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
+ view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId());
+ m_activeState = m_savedState;
+ m_savedState = NULL;
+ view->OnChangeFilename();
+ }
+ else
+ {
+ wxASSERT(m_savedState == NULL);
+ wxASSERT(m_activeState != NULL);
+
+ m_activeState->GetDocument()->Modify(TRUE);
+ ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView();
+ m_activeState->Detach();
+ m_savedState = m_activeState;
+ m_activeState = NULL;
+ view->OnChangeFilename();
+ }
+ break;
+ }
+ case ctCMD_NEW_ELEMENT:
+ {
+ if (doCmd)
+ {
+ wxASSERT(m_savedState != NULL);
+ wxASSERT(m_activeState == NULL);
+
+ m_savedState->GetDocument()->Modify(TRUE);
+ m_savedState->Attach(m_parent, m_insertBefore);
+ ctConfigToolView* view = (ctConfigToolView*) m_savedState->GetDocument()->GetFirstView();
+ view->AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), m_savedState);
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->SelectItem(m_savedState->GetTreeItemId());
+
+ m_activeState = m_savedState;
+ m_savedState = NULL;
+ }
+ else
+ {
+ wxASSERT(m_savedState == NULL);
+ wxASSERT(m_activeState != NULL);
+
+ m_activeState->GetDocument()->Modify(TRUE);
+ m_activeState->Detach();
+ m_savedState = m_activeState;
+ m_activeState = NULL;
+ }
+ break;
+ }
+ case ctCMD_APPLY_PROPERTY:
+ {
+ wxASSERT(m_properties != NULL);
+ wxASSERT(m_activeState != NULL);
+
+ // Don't update the properties editor first time
+ // around since it will be done one property at a time
+ // initially (and no property editor update required)
+ if (!m_ignoreThis)
+ {
+ // Just swap the saved and current properties.
+ ctProperties propsTemp = m_activeState->GetProperties() ;
+ m_activeState->GetProperties() = (* m_properties);
+ (* m_properties) = propsTemp;
+
+ // Apply only those that need applying
+ // (those properties in activeState that are not in propsTemp)
+ wxNode* node = m_activeState->GetProperties().GetList().GetFirst();
+ while (node)
+ {
+ ctProperty* prop = (ctProperty*) node->GetData();
+ ctProperty* otherProp = propsTemp.FindProperty(prop->GetName());
+ if (otherProp && ((*prop) != (*otherProp)))
+ {
+ m_activeState->ApplyProperty(prop, otherProp->GetVariant());
+ }
+ node = node->GetNext();
+ }
+ m_activeState->GetDocument()->Modify(TRUE);
+ ctConfigToolView* view = (ctConfigToolView*) m_activeState->GetDocument()->GetFirstView();
+ if (view)
+ {
+ ctConfigToolHint hint(NULL, ctValueChanged);
+ m_activeState->GetDocument()->UpdateAllViews (NULL, & hint);
+ }
+ }
+ m_ignoreThis = FALSE;
+
+ break;
+ }
+ }
+ return TRUE;
+}
+
diff --git a/utils/configtool/src/configtooldoc.h b/utils/configtool/src/configtooldoc.h
new file mode 100644
index 0000000000..72baa93f61
--- /dev/null
+++ b/utils/configtool/src/configtooldoc.h
@@ -0,0 +1,149 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtooldoc.h
+// Purpose: Document class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CT_CONFIGTOOLDOC_H_
+#define _CT_CONFIGTOOLDOC_H_
+
+#ifdef __GNUG__
+#pragma interface "configtooldoc.cpp"
+#endif
+
+#include "wx/docview.h"
+#include "wx/cmdproc.h"
+
+#include "configitem.h"
+
+class wxSimpleHtmlTag;
+
+/*!
+ * ctConfigToolDoc
+ */
+
+class ctConfigToolDoc: public wxDocument
+{
+ DECLARE_DYNAMIC_CLASS(ctConfigToolDoc)
+public:
+ ctConfigToolDoc();
+ ~ctConfigToolDoc();
+
+//// Overrides
+ virtual bool OnCreate(const wxString& path, long flags);
+ virtual bool OnOpenDocument(const wxString& filename);
+ virtual bool OnSaveDocument(const wxString& filename);
+ virtual bool OnNewDocument() { return TRUE; }
+ virtual bool OnCloseDocument() ;
+ virtual bool Save(); // Overridden only to correct bug in wxWindows, docview.cpp
+
+//// Accessors
+
+ /// Returns the top item.
+ ctConfigItem* GetTopItem() const { return m_topItem; }
+
+ /// Sets the top item.
+ void SetTopItem(ctConfigItem* item) { m_topItem = item; }
+
+ /// Returns the clipboard item.
+ ctConfigItem* GetClipboardItem() const { return m_clipboardItem; }
+
+ /// Sets the clipboard item.
+ void SetClipboardItem(ctConfigItem* item) ;
+
+ /// Clears the clipboard item.
+ void ClearClipboard() ;
+
+ /// Gets the current framework directory
+ wxString GetFrameworkDir(bool makeUnix);
+
+//// Operations
+
+ /// Add items
+ void AddItems();
+
+ /// Delete items
+ void DeleteItems();
+
+ /// Save the settings file
+ bool DoSave(const wxString& filename);
+
+ /// Recursive helper function for file saving
+ bool DoSave(ctConfigItem* item, wxOutputStream& stream, int indent);
+
+ /// Open the settings file
+ bool DoOpen(const wxString& filename);
+
+ /// Helper for file opening.
+ bool DoOpen(wxSimpleHtmlTag* tag, ctConfigItem* parent);
+
+ /// Refresh dependencies
+ void RefreshDependencies();
+ void RefreshDependencies(ctConfigItem* item);
+
+ /// Clear dependencies
+ void ClearDependencies(ctConfigItem* item);
+
+ /// Generate the text of a setup.h
+ wxString GenerateSetup();
+
+ /// Helper function
+ void GenerateSetup(ctConfigItem* item, wxString& str);
+
+ /// Generate a configure command
+ wxString GenerateConfigureCommand();
+
+ /// Helper function
+ void GenerateConfigureCommand(ctConfigItem* item, wxString& str);
+
+protected:
+ ctConfigItem* m_topItem;
+ ctConfigItem* m_clipboardItem;
+};
+
+
+/*!
+ * Implements a document editing command.
+ * We only need to store one state at a time,
+ * since we don't have (or need) multiple selection.
+ */
+
+#define ctCMD_NEW_ELEMENT 1
+#define ctCMD_PASTE 2
+#define ctCMD_CUT 3
+#define ctCMD_APPLY_PROPERTY 4
+
+class ctConfigCommand: public wxCommand
+{
+public:
+ ctConfigCommand(const wxString& name, int cmdId,
+ ctConfigItem* activeState, ctConfigItem* savedState,
+ ctConfigItem* parent = NULL, ctConfigItem* insertBefore = NULL,
+ bool ignoreFirstTime = FALSE);
+ ctConfigCommand(const wxString& name, int cmdId,
+ ctConfigItem* activeState, ctProperties* properties,
+ bool ignoreFirstTime = FALSE);
+ ~ctConfigCommand();
+
+ bool Do();
+ bool Undo();
+ bool DoAndUndo(bool doCmd); // Combine Do and Undo into one
+
+protected:
+ ctConfigItem* m_activeState;
+ ctConfigItem* m_savedState;
+ ctProperties* m_properties;
+ bool m_ignoreThis; // Ignore 1st Do because we already did it
+ int m_cmdId;
+ ctConfigItem* m_parent;
+ ctConfigItem* m_insertBefore;
+};
+
+
+#endif
+ // _CT_CONFIGTOOLDOC_H_
diff --git a/utils/configtool/src/configtoolview.cpp b/utils/configtool/src/configtoolview.cpp
new file mode 100644
index 0000000000..10cb368559
--- /dev/null
+++ b/utils/configtool/src/configtoolview.cpp
@@ -0,0 +1,967 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtoolview.cpp
+// Purpose: View class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+ #pragma implementation "configtoolview.cpp"
+#endif
+
+// Includes other headers for precompiled compilation
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/wfstream.h"
+
+#include "configtoolview.h"
+#include "configtooldoc.h"
+#include "configtree.h"
+#include "wxconfigtool.h"
+#include "mainframe.h"
+#include "propeditor.h"
+#include "utils.h"
+#include "custompropertydialog.h"
+
+IMPLEMENT_DYNAMIC_CLASS(ctConfigToolView, wxView)
+
+BEGIN_EVENT_TABLE(ctConfigToolView, wxView)
+ EVT_MENU(ctID_ADD_ITEM_CHECKBOX, ctConfigToolView::OnAddCheckBoxItem)
+ EVT_MENU(ctID_ADD_ITEM_RADIOBUTTON, ctConfigToolView::OnAddRadioButtonItem)
+ EVT_MENU(ctID_ADD_ITEM_GROUP, ctConfigToolView::OnAddGroupItem)
+ EVT_MENU(ctID_ADD_ITEM_CHECK_GROUP, ctConfigToolView::OnAddCheckGroupItem)
+ EVT_MENU(ctID_ADD_ITEM_RADIO_GROUP, ctConfigToolView::OnAddRadioGroupItem)
+ EVT_MENU(ctID_ADD_ITEM_STRING, ctConfigToolView::OnAddStringItem)
+ EVT_MENU(ctID_RENAME_ITEM, ctConfigToolView::OnRenameItem)
+ EVT_MENU(ctID_DELETE_ITEM, ctConfigToolView::OnDeleteItem)
+
+ EVT_MENU(wxID_COPY, ctConfigToolView::OnCopy)
+ EVT_MENU(wxID_CUT, ctConfigToolView::OnCut)
+ EVT_MENU(wxID_PASTE, ctConfigToolView::OnPaste)
+
+ EVT_UPDATE_UI(wxID_COPY, ctConfigToolView::OnUpdateCopy)
+ EVT_UPDATE_UI(wxID_CUT, ctConfigToolView::OnUpdateCut)
+ EVT_UPDATE_UI(wxID_PASTE, ctConfigToolView::OnUpdatePaste)
+
+ EVT_MENU(ctID_ITEM_HELP, ctConfigToolView::OnItemHelp)
+
+ EVT_UPDATE_UI(ctID_ADD_ITEM_CHECKBOX, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_ADD_ITEM_RADIOBUTTON, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_ADD_ITEM_GROUP, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_ADD_ITEM_CHECK_GROUP, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_ADD_ITEM_RADIO_GROUP, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_ADD_ITEM_STRING, ctConfigToolView::OnUpdateAddItem)
+ EVT_UPDATE_UI(ctID_RENAME_ITEM, ctConfigToolView::OnUpdateCut)
+ EVT_UPDATE_UI(ctID_DELETE_ITEM, ctConfigToolView::OnUpdateCut)
+ EVT_UPDATE_UI(ctID_ITEM_HELP, ctConfigToolView::OnUpdateItemHelp)
+
+ EVT_MENU(ctID_TREE_COPY, ctConfigToolView::OnContextCopy)
+ EVT_MENU(ctID_TREE_CUT, ctConfigToolView::OnContextCut)
+ EVT_MENU(ctID_TREE_PASTE_BEFORE, ctConfigToolView::OnContextPasteBefore)
+ EVT_MENU(ctID_TREE_PASTE_AFTER, ctConfigToolView::OnContextPasteAfter)
+ EVT_MENU(ctID_TREE_PASTE_AS_CHILD, ctConfigToolView::OnContextPasteAsChild)
+ EVT_UPDATE_UI(ctID_TREE_COPY, ctConfigToolView::OnUpdateContextCopy)
+ EVT_UPDATE_UI(ctID_TREE_CUT, ctConfigToolView::OnUpdateContextCut)
+ EVT_UPDATE_UI(ctID_TREE_PASTE_BEFORE, ctConfigToolView::OnUpdateContextPasteBefore)
+ EVT_UPDATE_UI(ctID_TREE_PASTE_AFTER, ctConfigToolView::OnUpdateContextPasteAfter)
+ EVT_UPDATE_UI(ctID_TREE_PASTE_AS_CHILD, ctConfigToolView::OnUpdateContextPasteAsChild)
+
+ EVT_MENU(ctID_ADD_CUSTOM_PROPERTY, ctConfigToolView::OnAddCustomProperty)
+ EVT_MENU(ctID_EDIT_CUSTOM_PROPERTY, ctConfigToolView::OnEditCustomProperty)
+ EVT_MENU(ctID_DELETE_CUSTOM_PROPERTY, ctConfigToolView::OnDeleteCustomProperty)
+ EVT_UPDATE_UI(ctID_ADD_CUSTOM_PROPERTY, ctConfigToolView::OnUpdateAddCustomProperty)
+ EVT_UPDATE_UI(ctID_EDIT_CUSTOM_PROPERTY, ctConfigToolView::OnUpdateEditCustomProperty)
+ EVT_UPDATE_UI(ctID_DELETE_CUSTOM_PROPERTY, ctConfigToolView::OnUpdateDeleteCustomProperty)
+
+ EVT_NOTEBOOK_PAGE_CHANGED(-1, ctConfigToolView::OnTabSelect)
+
+ EVT_MENU(ctID_SAVE_SETUP_FILE, ctConfigToolView::OnSaveSetupFile)
+ EVT_MENU(ctID_SAVE_CONFIGURE_COMMAND, ctConfigToolView::OnSaveConfigureCommand)
+ EVT_UPDATE_UI(ctID_SAVE_SETUP_FILE, ctConfigToolView::OnUpdateSaveSetupFile)
+ EVT_UPDATE_UI(ctID_SAVE_CONFIGURE_COMMAND, ctConfigToolView::OnUpdateSaveConfigureCommand)
+END_EVENT_TABLE()
+
+ctConfigToolView::ctConfigToolView()
+{
+}
+
+// What to do when a view is created. Creates actual
+// windows for displaying the view.
+bool ctConfigToolView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
+{
+ wxGetApp().GetDocManager()->ActivateView(this, TRUE);
+ wxGetApp().GetMainFrame()->SetDocument((ctConfigToolDoc*) doc);
+ wxGetApp().GetMainFrame()->GetSetupPage()->SetDocument((ctConfigToolDoc*) doc) ;
+ wxGetApp().GetMainFrame()->GetConfigurePage()->SetDocument((ctConfigToolDoc*) doc) ;
+
+ return TRUE;
+}
+
+void ctConfigToolView::OnDraw(wxDC *dc)
+{
+}
+
+void ctConfigToolView::OnUpdate(wxView *WXUNUSED(sender), wxObject *hintObj)
+{
+ ctConfigToolDoc* doc = wxDynamicCast(GetDocument(), ctConfigToolDoc);
+ ctConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
+ if (!treeCtrl)
+ return;
+
+ wxASSERT (doc != NULL);
+
+ ctConfigItem* selItem = NULL;
+
+ wxTreeItemId sel = treeCtrl->GetSelection();
+ if (sel.IsOk())
+ {
+ ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(sel);
+ if (data)
+ selItem = data->GetConfigItem() ;
+ }
+
+ ctConfigToolHint* hint = (ctConfigToolHint*) hintObj;
+ int hintOp = ctNoHint;
+ if (hint)
+ hintOp = hint->m_op;
+
+ switch (hintOp)
+ {
+ case ctInitialUpdate:
+ {
+ if (doc && doc->GetTopItem())
+ {
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->DeleteAllItems();
+ AddItems(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), doc->GetTopItem());
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Expand(doc->GetTopItem()->GetTreeItemId());
+ }
+ }
+ break;
+ case ctSelChanged:
+ {
+ if (selItem)
+ {
+ wxGetApp().GetMainFrame()->GetPropertyEditor()->ShowItem(selItem);
+ }
+ }
+ break;
+ case ctAllSaved:
+ {
+ // TODO: update windows and frame title
+ }
+ break;
+ case ctFilenameChanged:
+ {
+ wxGetApp().GetMainFrame()->UpdateFrameTitle();
+ }
+ break;
+ case ctClear:
+ {
+ // TODO: update windows
+ treeCtrl->DeleteAllItems();
+ wxGetApp().GetMainFrame()->GetPropertyEditor()->ShowItem(NULL);
+ break;
+ }
+ case ctValueChanged:
+ {
+ // ctConfigItem& ti = *(ctConfigItem *)hint->m_item;
+ wxGetApp().GetMainFrame()->GetPropertyEditor()->ShowItem(selItem);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+// Clean up windows used for displaying the view.
+bool ctConfigToolView::OnClose(bool deleteWindow)
+{
+ if (!GetDocument()->Close())
+ return FALSE;
+
+ ctConfigToolHint hint(NULL, ctClear);
+ GetDocument()->UpdateAllViews (NULL, & hint);
+
+ wxGetApp().GetDocManager()->ActivateView(this, FALSE);
+
+ Activate(FALSE);
+
+ wxGetApp().GetMainFrame()->SetDocument(NULL);
+ wxGetApp().GetMainFrame()->GetSetupPage()->SetDocument(NULL) ;
+ wxGetApp().GetMainFrame()->GetConfigurePage()->SetDocument(NULL) ;
+
+ return TRUE;
+}
+
+void ctConfigToolView::OnChangeFilename()
+{
+ if (wxGetApp().GetTopWindow() && GetDocument())
+ {
+ wxString docTitle(wxFileNameFromPath(GetDocument()->GetFilename()));
+ wxStripExtension(docTitle);
+ GetDocument()->SetTitle(docTitle);
+
+ wxString name(GetDocument()->GetFilename());
+ wxStripExtension(name);
+
+ wxString title;
+
+ wxString modifiedMarker;
+ if (GetDocument()->IsModified())
+ modifiedMarker = wxT("*");
+
+ title = docTitle + modifiedMarker + wxString(wxT(" - ")) + wxGetApp().GetSettings().GetAppName() ;
+
+ ((wxFrame*) wxGetApp().GetTopWindow())->SetTitle(title);
+ }
+}
+
+// General disabler
+void ctConfigToolView::OnUpdateDisable(wxUpdateUIEvent& event)
+{
+ event.Enable( FALSE );
+}
+
+void ctConfigToolView::OnUpdateAddItem(wxUpdateUIEvent& event)
+{
+ event.Enable( TRUE );
+}
+
+/// Add item and its children to the tree
+void ctConfigToolView::AddItems(ctConfigTreeCtrl* treeControl, ctConfigItem* item)
+{
+ SyncItem(treeControl, item);
+
+ int count = item->GetChildCount();
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ ctConfigItem* child = item->GetChild(i);
+ AddItems(treeControl, child);
+ }
+}
+
+/// Gets the tree item in sync with the item
+void ctConfigToolView::SyncItem(ctConfigTreeCtrl* treeControl, ctConfigItem* item)
+{
+ if (!item->GetTreeItemId().IsOk())
+ {
+ if (!item->GetParent())
+ {
+ item->SetTreeItem(treeControl->AddRoot(_(""), -1, -1, new ctTreeItemData(item)));
+ }
+ else
+ {
+ // Find the item to insert the new item after.
+ ctConfigItem* previousItem = item->FindPreviousSibling();
+ if (previousItem && previousItem->GetTreeItemId().IsOk())
+ {
+ item->SetTreeItem(treeControl->InsertItem(item->GetParent()->GetTreeItemId(),
+ previousItem->GetTreeItemId(),
+ item->GetName(), -1, -1, new ctTreeItemData(item)));
+ }
+ else if (!previousItem && item->GetParent()->GetChildCount() > 1
+ )
+ {
+ // Insert at the beginning
+ item->SetTreeItem(treeControl->InsertItem(item->GetParent()->GetTreeItemId(),
+ (size_t) 0, // Insert at first position
+ item->GetName(), -1, -1, new ctTreeItemData(item)));
+ }
+ else
+ {
+ item->SetTreeItem(treeControl->AppendItem(item->GetParent()->GetTreeItemId(),
+ item->GetName(), -1, -1, new ctTreeItemData(item)));
+ }
+ }
+ }
+
+ if (item->GetTreeItemId().IsOk())
+ {
+ treeControl->SetItemText(item->GetTreeItemId(), item->GetName());
+
+ int iconId = 0;
+
+ if (item->GetType() == ctTypeGroup)
+ {
+ iconId = treeControl->GetIconTable().GetIconId(wxT("Group"), 0, item->IsActive());
+ }
+ else if (item->GetType() == ctTypeCheckGroup)
+ {
+ iconId = treeControl->GetIconTable().GetIconId(wxT("CheckGroup"), item->IsEnabled() ? 0 : 1, item->IsActive());
+ }
+ else if (item->GetType() == ctTypeRadioGroup)
+ {
+ iconId = treeControl->GetIconTable().GetIconId(wxT("RadioGroup"), item->IsEnabled() ? 0 : 1, item->IsActive());
+ }
+ else if (item->GetType() == ctTypeBoolCheck)
+ {
+ iconId = treeControl->GetIconTable().GetIconId(wxT("Checkbox"), item->IsEnabled() ? 0 : 1, item->IsActive());
+ }
+ else if (item->GetType() == ctTypeBoolRadio)
+ {
+ iconId = treeControl->GetIconTable().GetIconId(wxT("Radiobutton"), item->IsEnabled() ? 0 : 1, item->IsActive());
+ }
+ treeControl->SetItemImage(item->GetTreeItemId(), iconId, wxTreeItemIcon_Normal);
+ treeControl->SetItemImage(item->GetTreeItemId(), iconId, wxTreeItemIcon_Selected);
+
+ if (treeControl->GetSelection() == item->GetTreeItemId())
+ {
+ if (wxGetApp().GetMainFrame()->GetPropertyEditor()->GetItem())
+ wxGetApp().GetMainFrame()->GetPropertyEditor()->UpdateTitle();
+ }
+ }
+}
+
+/// Clicked an icon
+void ctConfigToolView::OnIconLeftDown(ctConfigTreeCtrl* treeControl, ctConfigItem* item)
+{
+ if (!item->IsActive())
+ return;
+
+ if (item->GetType() == ctTypeCheckGroup ||
+ item->GetType() == ctTypeBoolCheck ||
+ item->GetType() == ctTypeBoolRadio ||
+ item->GetType() == ctTypeRadioGroup
+ )
+ {
+ // Don't toggle a radio button that's already
+ // enabled.
+ if ((item->GetType() == ctTypeBoolRadio || item->GetType() == ctTypeRadioGroup)
+ && item->IsEnabled())
+ return;
+
+ item->Enable(!item->IsEnabled());
+
+ GetDocument()->Modify(TRUE);
+ OnChangeFilename();
+
+ SyncItem(treeControl, item);
+
+ wxList considered;
+ item->PropagateChange(considered);
+ if ((item->GetType() == ctTypeBoolRadio || item->GetType() == ctTypeRadioGroup) && item->IsEnabled())
+ {
+ item->PropagateRadioButton(considered);
+ }
+ }
+}
+
+/// Returns the selected config item, if any.
+ctConfigItem* ctConfigToolView::GetSelection()
+{
+ wxTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetConfigTreeCtrl();
+ if (!treeCtrl)
+ return NULL;
+
+ wxTreeItemId sel = treeCtrl->GetSelection();
+ if (sel.IsOk())
+ {
+ ctTreeItemData* data = (ctTreeItemData*) treeCtrl->GetItemData(sel);
+ if (data)
+ return data->GetConfigItem() ;
+ }
+ return NULL;
+}
+
+/// Add a checkbox item
+void ctConfigToolView::OnAddCheckBoxItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeBoolCheck, _("New checkbox item"));
+}
+
+/// Add a radiobutton item
+void ctConfigToolView::OnAddRadioButtonItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeBoolRadio, _("New radio button item"));
+}
+
+/// Add a group item
+void ctConfigToolView::OnAddGroupItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeGroup, _("New group item"));
+}
+
+/// Add a group option item
+void ctConfigToolView::OnAddCheckGroupItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeCheckGroup, _("New check group item"));
+}
+
+/// Add a group option item
+void ctConfigToolView::OnAddRadioGroupItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeRadioGroup, _("New radio group item"));
+}
+
+/// Add a string item
+void ctConfigToolView::OnAddStringItem(wxCommandEvent& event)
+{
+ AddItem(ctTypeString, _("New string item"));
+}
+
+/// Add an item
+void ctConfigToolView::AddItem(ctConfigType type, const wxString& msg)
+{
+ ctConfigItem* sel = GetSelection();
+ if (sel)
+ {
+ wxString name = wxGetTextFromUser(_("Please enter a name for the new item."),
+ msg, wxT(""));
+ if (!name.IsEmpty())
+ {
+ ctConfigItem* parent ;
+ ctConfigItem* insertBefore ;
+ if (sel->CanHaveChildren())
+ {
+ parent = sel;
+ insertBefore = NULL;
+ }
+ else
+ {
+ parent = sel->GetParent();
+ insertBefore = sel->FindNextSibling();
+ }
+
+ ctConfigItem* newItem = new ctConfigItem(NULL, type, name);
+ newItem->InitProperties();
+
+ newItem->GetDocument()->GetCommandProcessor()->Submit(
+ new ctConfigCommand(msg, ctCMD_NEW_ELEMENT, NULL, newItem,
+ parent, insertBefore));
+ }
+ }
+}
+
+/// Delete an item
+void ctConfigToolView::OnDeleteItem(wxCommandEvent& event)
+{
+ ctConfigItem* sel = GetSelection();
+ if (sel)
+ {
+ wxString msg;
+ msg.Printf(_("Delete %s?"), sel->GetName());
+ if (wxYES == wxMessageBox(msg, _("Delete item"), wxICON_QUESTION|wxYES_NO))
+ {
+ wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->Delete(sel->GetTreeItemId());
+ }
+ }
+}
+
+/// Rename an item
+void ctConfigToolView::OnRenameItem(wxCommandEvent& event)
+{
+ ctConfigItem* sel = GetSelection();
+ if (sel)
+ {
+ wxString name = wxGetTextFromUser(_("Please enter a new name for the item."),
+ _("Rename item"), sel->GetName());
+ if (!name.IsEmpty())
+ {
+ sel->SetName(name);
+ SyncItem(wxGetApp().GetMainFrame()->GetConfigTreeCtrl(), sel);
+
+ ctConfigToolHint hint(NULL, ctSelChanged);
+ GetDocument()->UpdateAllViews (NULL, & hint);
+ }
+ }
+}
+
+/// Copy an item to the clipboard
+void ctConfigToolView::OnCopy(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ if (sel)
+ {
+ doc->SetClipboardItem(sel->DeepClone());
+ }
+}
+
+/// Copy an item to the clipboard and cut the item
+void ctConfigToolView::OnCut(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ if (sel)
+ {
+ {
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Cut Config Item"), ctCMD_CUT,
+ sel, (ctConfigItem*) NULL);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+ }
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnPaste(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ if (sel && doc->GetClipboardItem())
+ {
+ ctConfigItem* parent ;
+ ctConfigItem* insertBefore ;
+ if (sel->CanHaveChildren())
+ {
+ parent = sel;
+ insertBefore = NULL;
+ }
+ else
+ {
+ parent = sel->GetParent();
+ insertBefore = sel->FindNextSibling();
+ }
+
+ ctConfigItem* newItem = doc->GetClipboardItem()->DeepClone();
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Paste Config Item"), ctCMD_PASTE,
+ NULL, newItem, parent, insertBefore);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+/// Update for copy command
+void ctConfigToolView::OnUpdateCopy(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ event.Enable( doc && GetSelection() && GetSelection()->GetParent() );
+}
+
+/// Update for cut
+void ctConfigToolView::OnUpdateCut(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ event.Enable( doc && GetSelection() && GetSelection()->GetParent() );
+}
+
+/// Update for paste
+void ctConfigToolView::OnUpdatePaste(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ event.Enable( doc && doc->GetClipboardItem() && GetSelection() );
+}
+
+/// Copy an item to the clipboard
+void ctConfigToolView::OnContextCopy(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ if (doc && sel)
+ {
+ doc->SetClipboardItem(sel->DeepClone());
+ }
+}
+
+/// Copy an item to the clipboard and cut the item
+void ctConfigToolView::OnContextCut(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ if (sel)
+ {
+ {
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Cut Config Item"), ctCMD_CUT,
+ sel, (ctConfigItem*) NULL);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+ }
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnContextPasteBefore(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ if (sel && doc->GetClipboardItem())
+ {
+ ctConfigItem* parent = sel->GetParent();
+ ctConfigItem* insertBefore = sel;
+
+ ctConfigItem* newItem = doc->GetClipboardItem()->DeepClone();
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Paste Config Item"), ctCMD_PASTE,
+ NULL, newItem, parent, insertBefore);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnContextPasteAfter(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ if (sel && doc->GetClipboardItem())
+ {
+ ctConfigItem* parent = sel->GetParent();
+ ctConfigItem* insertBefore = sel->FindNextSibling();
+
+ ctConfigItem* newItem = doc->GetClipboardItem()->DeepClone();
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Paste Config Item"), ctCMD_PASTE,
+ NULL, newItem, parent, insertBefore);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnContextPasteAsChild(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ if (sel && doc->GetClipboardItem())
+ {
+ if (sel->CanHaveChildren())
+ {
+ ctConfigItem* parent = sel;
+ ctConfigItem* insertBefore = NULL;
+
+ ctConfigItem* newItem = doc->GetClipboardItem()->DeepClone();
+ ctConfigCommand* cmd = new ctConfigCommand(wxT("Paste Config Item"), ctCMD_PASTE,
+ NULL, newItem, parent, insertBefore);
+ doc->GetCommandProcessor()->Submit(cmd);
+ }
+ }
+}
+
+/// Copy an item to the clipboard
+void ctConfigToolView::OnUpdateContextCopy(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ event.Enable( doc && sel && sel->GetParent() );
+}
+
+/// Copy an item to the clipboard and cut the item
+void ctConfigToolView::OnUpdateContextCut(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ event.Enable( doc && sel && sel->GetParent() );
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnUpdateContextPasteBefore(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ event.Enable( doc && sel && sel->GetParent() && doc->GetClipboardItem() );
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnUpdateContextPasteAfter(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ event.Enable( doc && sel && sel->GetParent() && doc->GetClipboardItem() );
+}
+
+/// Paste an item from the clipboard to the tree
+void ctConfigToolView::OnUpdateContextPasteAsChild(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = wxGetApp().GetMainFrame()->GetConfigTreeCtrl()->GetContextItem();
+ event.Enable( doc && sel && sel->CanHaveChildren() && doc->GetClipboardItem() );
+}
+
+/// Item help
+void ctConfigToolView::OnItemHelp(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ if ( doc && GetSelection() )
+ {
+ wxString helpTopic = GetSelection()->GetPropertyString(wxT("help-topic"));
+ if (!helpTopic.IsEmpty())
+ {
+ wxGetApp().GetReferenceHelpController().DisplaySection(helpTopic);
+ }
+ }
+}
+
+/// Item help update
+void ctConfigToolView::OnUpdateItemHelp(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ event.Enable( doc && GetSelection() );
+}
+
+/// Add a custom property
+void ctConfigToolView::OnAddCustomProperty(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ ctPropertyEditor* editor = wxGetApp().GetMainFrame()->GetPropertyEditor();
+ if (doc && sel && editor)
+ {
+ ctCustomPropertyDialog dialog(wxGetApp().GetMainFrame(),
+ -1, _("Add a custom property"));
+ if (dialog.ShowModal() == wxID_OK)
+ {
+ wxString name = dialog.GetPropertyName();
+ wxString type = dialog.GetPropertyType();
+ wxString descr = dialog.GetPropertyDescription();
+ wxString editorType = dialog.GetEditorType();
+ wxArrayString choices = dialog.GetChoices();
+
+ if (sel->GetProperties().FindProperty(name))
+ {
+ wxMessageBox(_("Sorry, this name already exists."), _T("Add custom property"),
+ wxOK|wxICON_INFORMATION);
+ return;
+ }
+ ctProperty* property = new ctProperty;
+ if (type == wxT("bool"))
+ property->GetVariant() = wxVariant((bool) FALSE, name);
+ else if (type == wxT("double"))
+ property->GetVariant() = wxVariant((double) 0.0, name);
+ else if (type == wxT("long"))
+ property->GetVariant() = wxVariant((long) 0, name);
+ else
+ property->GetVariant() = wxVariant(wxT(""), name);
+ property->SetCustom(TRUE);
+ property->SetDescription(descr);
+ property->SetChoices(choices);
+ property->SetEditorType(editorType);
+
+ sel->GetProperties().AddProperty(property);
+ editor->ShowItem(sel);
+ OnChangeFilename();
+ }
+ }
+}
+
+/// Edit a custom property
+void ctConfigToolView::OnEditCustomProperty(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ ctPropertyEditor* editor = wxGetApp().GetMainFrame()->GetPropertyEditor();
+ if (doc && sel && editor)
+ {
+ int row;
+ ctProperty* property = editor->FindSelectedProperty(row) ;
+ if (property && property->IsCustom())
+ {
+ wxString oldName = property->GetName();
+ wxString oldDescription = property->GetDescription();
+ wxString oldType = property->GetVariant().GetType();
+ wxString oldEditorType = property->GetEditorType();
+ wxArrayString oldChoices = property->GetChoices();
+
+ ctCustomPropertyDialog dialog(wxGetApp().GetMainFrame(),
+ -1, _("Edit custom property"));
+ dialog.SetPropertyName(oldName);
+ dialog.SetPropertyType(oldType);
+ dialog.SetPropertyDescription(oldDescription);
+ if (dialog.ShowModal() == wxID_OK)
+ {
+ wxString name = dialog.GetPropertyName();
+ wxString type = dialog.GetPropertyType();
+ wxString editorType = dialog.GetEditorType();
+ wxArrayString choices = dialog.GetChoices();
+ wxString descr = dialog.GetPropertyDescription();
+
+ if (name != oldName && sel->GetProperties().FindProperty(name))
+ {
+ wxMessageBox(_("Sorry, this name already exists."), _T("Add custom property"),
+ wxOK|wxICON_INFORMATION);
+ return;
+ }
+ if (type != oldType)
+ {
+ if (type == wxT("bool"))
+ property->GetVariant() = wxVariant((bool) FALSE, name);
+ else if (type == wxT("double"))
+ property->GetVariant() = wxVariant((double) 0.0, name);
+ else if (type == wxT("long"))
+ property->GetVariant() = wxVariant((long) 0, name);
+ else
+ property->GetVariant() = wxVariant(wxT(""), name);
+ }
+ if (name != oldName)
+ property->GetVariant().SetName(name);
+
+ if (choices != oldChoices)
+ property->SetChoices(choices);
+
+ if (editorType != oldEditorType)
+ property->SetEditorType(editorType);
+
+ if (name != oldName)
+ property->GetVariant().SetName(name);
+
+ property->SetCustom(TRUE);
+
+ if (descr != oldDescription)
+ property->SetDescription(descr);
+
+ editor->ShowItem(sel);
+ OnChangeFilename();
+ }
+ }
+ }
+}
+
+/// Delete a custom property
+void ctConfigToolView::OnDeleteCustomProperty(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ ctPropertyEditor* editor = wxGetApp().GetMainFrame()->GetPropertyEditor();
+ if (doc && sel && editor)
+ {
+ int row;
+ ctProperty* property = editor->FindSelectedProperty(row) ;
+ if (property && property->IsCustom())
+ {
+ wxString name(property->GetName());
+ wxString msg;
+ msg.Printf(_("Delete custom property '%s'?"), (const wxChar*) name);
+ if (wxYES == wxMessageBox(msg, _("Delete property"), wxICON_EXCLAMATION|wxYES_NO))
+ {
+ sel->GetProperties().RemoveProperty(property);
+ editor->ShowItem(sel);
+ delete property;
+ OnChangeFilename();
+ }
+ }
+ }
+}
+
+/// Add a custom property: update event
+void ctConfigToolView::OnUpdateAddCustomProperty(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ event.Enable( doc && GetSelection() && GetSelection()->GetParent() );
+}
+
+/// Edit a custom property: update event
+void ctConfigToolView::OnUpdateEditCustomProperty(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ ctPropertyEditor* editor = wxGetApp().GetMainFrame()->GetPropertyEditor();
+ int row;
+ event.Enable( doc && sel && sel->GetParent() && editor &&
+ editor->FindSelectedProperty(row) &&
+ editor->FindSelectedProperty(row)->IsCustom() );
+}
+
+/// Delete a custom property: update event
+void ctConfigToolView::OnUpdateDeleteCustomProperty(wxUpdateUIEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctConfigItem* sel = GetSelection();
+ ctPropertyEditor* editor = wxGetApp().GetMainFrame()->GetPropertyEditor();
+ int row;
+ event.Enable( doc && sel && sel->GetParent() && editor &&
+ editor->FindSelectedProperty(row) &&
+ editor->FindSelectedProperty(row)->IsCustom() );
+}
+
+/// Regenerate setup.h and configure command
+void ctConfigToolView::RegenerateSetup()
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ ctOutputWindow* setupPage = wxGetApp().GetMainFrame()->GetSetupPage() ;
+ ctOutputWindow* configurePage = wxGetApp().GetMainFrame()->GetConfigurePage() ;
+
+ wxString setupStr = doc->GenerateSetup();
+ wxString configureStr = doc->GenerateConfigureCommand();
+
+ setupPage->SetText(setupStr);
+ configurePage->SetText(configureStr);
+}
+
+/// Regenerate if selected a tab
+void ctConfigToolView::OnTabSelect(wxNotebookEvent& event)
+{
+ if (wxGetApp().GetMainFrame()->GetMainNotebook() != event.GetEventObject())
+ {
+ event.Skip();
+ return;
+ }
+
+ if (event.GetSelection() > 0)
+ {
+ RegenerateSetup();
+ }
+}
+
+void ctConfigToolView::OnSaveSetupFile(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ wxString setupStr = doc->GenerateSetup();
+
+ wxString filename = _T("setup.h");
+ wxString path = doc->GetFrameworkDir(FALSE);
+ wxString wildcard = _T("Header files (*.h)|*.h|All files (*.*)|*.*");
+
+ wxFileDialog dialog(wxTheApp->GetTopWindow(),
+ _("Save Setup File As"),
+ path, filename ,
+ wildcard, wxSAVE|wxOVERWRITE_PROMPT);
+
+ if (dialog.ShowModal() == wxID_OK)
+ {
+ wxString fullPath = dialog.GetPath();
+
+ // TODO: save last saved path in settings.
+
+ wxFileOutputStream stream(fullPath);
+ if (!stream.Ok())
+ {
+ wxMessageBox(_("Sorry, could not save this file."), _("Save Setup File"), wxICON_EXCLAMATION|wxOK);
+ return;
+ }
+
+ stream << setupStr;
+ }
+}
+
+void ctConfigToolView::OnSaveConfigureCommand(wxCommandEvent& event)
+{
+ ctConfigToolDoc* doc = (ctConfigToolDoc*) GetDocument();
+ wxString configureStr = doc->GenerateConfigureCommand();
+
+ wxString filename = _T("configurewx.sh");
+ wxString path = doc->GetFrameworkDir(FALSE);
+ wxString wildcard = _T("Shell script files (*.sh)|*.sh|All files (*.*)|*.*");
+
+ wxFileDialog dialog(wxTheApp->GetTopWindow(),
+ _("Save Configure Command File As"),
+ path, filename ,
+ wildcard, wxSAVE|wxOVERWRITE_PROMPT);
+
+ if (dialog.ShowModal() == wxID_OK)
+ {
+ wxString fullPath = dialog.GetPath();
+
+ // TODO: save last saved path in settings.
+
+ wxFileOutputStream stream(fullPath);
+ if (!stream.Ok())
+ {
+ wxMessageBox(_("Sorry, could not save this file."), _("Save Configure Command File"), wxICON_EXCLAMATION|wxOK);
+ return;
+ }
+
+ stream << configureStr;
+ }
+}
+
+void ctConfigToolView::OnUpdateSaveSetupFile(wxUpdateUIEvent& event)
+{
+ event.Enable(TRUE);
+}
+
+void ctConfigToolView::OnUpdateSaveConfigureCommand(wxUpdateUIEvent& event)
+{
+ event.Enable(TRUE);
+}
diff --git a/utils/configtool/src/configtoolview.h b/utils/configtool/src/configtoolview.h
new file mode 100644
index 0000000000..85e9e58a50
--- /dev/null
+++ b/utils/configtool/src/configtoolview.h
@@ -0,0 +1,225 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtoolview.h
+// Purpose: View class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CT_CONFIGTOOLVIEW_H_
+#define _CT_CONFIGTOOLVIEW_H_
+
+#ifdef __GNUG__
+#pragma interface "configtoolview.cpp"
+#endif
+
+#include "wx/docview.h"
+#include "wx/treectrl.h"
+#include "configitem.h"
+
+class ctConfigTreeCtrl;
+class WXDLLEXPORT wxNotebookEvent;
+
+/*
+ * ctConfigToolView
+ */
+
+class ctConfigItem;
+class ctConfigToolView: public wxView
+{
+ DECLARE_DYNAMIC_CLASS(ctConfigToolView)
+public:
+ ctConfigToolView();
+ ~ctConfigToolView() {};
+
+//// Overrides
+
+ bool OnCreate(wxDocument *doc, long flags);
+ void OnDraw(wxDC *dc);
+ void OnUpdate(wxView *sender, wxObject *hint = (wxObject *) NULL);
+ bool OnClose(bool deleteWindow = TRUE);
+ void OnChangeFilename();
+
+//// Operations
+
+ /// Gets the tree item in sync with the item.
+ void SyncItem(ctConfigTreeCtrl* treeControl, ctConfigItem* item);
+
+ /// Add item and its children to the tree
+ void AddItems(ctConfigTreeCtrl* treeControl, ctConfigItem* item);
+
+ /// Clicked an icon
+ void OnIconLeftDown(ctConfigTreeCtrl* treeControl, ctConfigItem* item);
+
+ /// Add an item
+ void AddItem(ctConfigType type, const wxString& msg);
+
+ /// Regenerate setup.h and configure command
+ void RegenerateSetup();
+
+//// Accessors
+
+ /// Returns the selected config item, if any.
+ ctConfigItem* GetSelection();
+
+//// Event handlers
+
+ /// General disabler
+ void OnUpdateDisable(wxUpdateUIEvent& event);
+
+ /// Enable add item menu items
+ void OnUpdateAddItem(wxUpdateUIEvent& event);
+
+ /// Add a checkbox item
+ void OnAddCheckBoxItem(wxCommandEvent& event);
+
+ /// Add a radiobutton item
+ void OnAddRadioButtonItem(wxCommandEvent& event);
+
+ /// Add a group item
+ void OnAddGroupItem(wxCommandEvent& event);
+
+ /// Add a check group item
+ void OnAddCheckGroupItem(wxCommandEvent& event);
+
+ /// Add a radio group item
+ void OnAddRadioGroupItem(wxCommandEvent& event);
+
+ /// Add a string item
+ void OnAddStringItem(wxCommandEvent& event);
+
+ /// Delete an item
+ void OnDeleteItem(wxCommandEvent& event);
+
+ /// Rename an item
+ void OnRenameItem(wxCommandEvent& event);
+
+ /// Copy an item to the clipboard
+ void OnCopy(wxCommandEvent& event);
+
+ /// Copy an item to the clipboard and cut the item
+ void OnCut(wxCommandEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnPaste(wxCommandEvent& event);
+
+ /// Item help
+ void OnItemHelp(wxCommandEvent& event);
+
+ /// Update for copy command
+ void OnUpdateCopy(wxUpdateUIEvent& event);
+
+ /// Update for cut
+ void OnUpdateCut(wxUpdateUIEvent& event);
+
+ /// Update for paste
+ void OnUpdatePaste(wxUpdateUIEvent& event);
+
+ /// Update for item help
+ void OnUpdateItemHelp(wxUpdateUIEvent& event);
+
+ // Context menu events
+
+ /// Copy an item to the clipboard
+ void OnContextCopy(wxCommandEvent& event);
+
+ /// Copy an item to the clipboard and cut the item
+ void OnContextCut(wxCommandEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnContextPasteBefore(wxCommandEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnContextPasteAfter(wxCommandEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnContextPasteAsChild(wxCommandEvent& event);
+
+ /// Copy an item to the clipboard
+ void OnUpdateContextCopy(wxUpdateUIEvent& event);
+
+ /// Copy an item to the clipboard and cut the item
+ void OnUpdateContextCut(wxUpdateUIEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnUpdateContextPasteBefore(wxUpdateUIEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnUpdateContextPasteAfter(wxUpdateUIEvent& event);
+
+ /// Paste an item from the clipboard to the tree
+ void OnUpdateContextPasteAsChild(wxUpdateUIEvent& event);
+
+ // Custom property events
+
+ /// Add a custom property
+ void OnAddCustomProperty(wxCommandEvent& event);
+
+ /// Edit a custom property
+ void OnEditCustomProperty(wxCommandEvent& event);
+
+ /// Delete a custom property
+ void OnDeleteCustomProperty(wxCommandEvent& event);
+
+ /// Add a custom property: update event
+ void OnUpdateAddCustomProperty(wxUpdateUIEvent& event);
+
+ /// Edit a custom property: update event
+ void OnUpdateEditCustomProperty(wxUpdateUIEvent& event);
+
+ /// Delete a custom property: update event
+ void OnUpdateDeleteCustomProperty(wxUpdateUIEvent& event);
+
+ // Notebook events
+
+ /// Regenerate if selected a tab
+ void OnTabSelect(wxNotebookEvent& event);
+
+ /// Saving setup file
+ void OnSaveSetupFile(wxCommandEvent& event);
+
+ /// Save configure command file
+ void OnSaveConfigureCommand(wxCommandEvent& event);
+
+ /// Saving setup file update handler
+ void OnUpdateSaveSetupFile(wxUpdateUIEvent& event);
+
+ /// Save configure command file update handler
+ void OnUpdateSaveConfigureCommand(wxUpdateUIEvent& event);
+
+DECLARE_EVENT_TABLE()
+
+protected:
+};
+
+/*
+ * ctConfigToolHint
+ *
+ * Hint to pass to UpdateAllViews
+ *
+ */
+
+// Update hint symbols
+#define ctNoHint 0
+#define ctAllSaved 1
+#define ctClear 2
+#define ctValueChanged 3
+#define ctSelChanged 4
+#define ctFilenameChanged 5
+#define ctInitialUpdate 6
+
+class ctConfigItem;
+class ctConfigToolHint: public wxObject
+{
+public:
+ ctConfigToolHint(ctConfigItem* item, int op) { m_item = item; m_op = op; }
+
+ ctConfigItem* m_item;
+ int m_op;
+};
+
+#endif
+ // _CT_CONFIGTOOLVIEW_H_
diff --git a/utils/configtool/src/configtree.cpp b/utils/configtool/src/configtree.cpp
new file mode 100644
index 0000000000..3da10101fb
--- /dev/null
+++ b/utils/configtool/src/configtree.cpp
@@ -0,0 +1,229 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtree.h
+// Purpose: wxWindows Configuration Tool tree class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-03
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "configtree.h"
+#endif
+
+// Includes other headers for precompiled compilation
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/imaglist.h"
+#include "wx/cshelp.h"
+
+// Include XPM icons
+#include "bitmaps/folder1.xpm"
+
+#include "bitmaps/closedfolder.xpm"
+#include "bitmaps/closedfolder_dis.xpm"
+
+#include "bitmaps/checked.xpm"
+#include "bitmaps/checked_dis.xpm"
+#include "bitmaps/unchecked.xpm"
+#include "bitmaps/unchecked_dis.xpm"
+
+#include "bitmaps/radioon.xpm"
+#include "bitmaps/radioon_dis.xpm"
+#include "bitmaps/radiooff.xpm"
+#include "bitmaps/radiooff_dis.xpm"
+
+#include "bitmaps/checkedfolder.xpm"
+#include "bitmaps/checkedfolder_dis.xpm"
+#include "bitmaps/uncheckedfolder.xpm"
+#include "bitmaps/uncheckedfolder_dis.xpm"
+
+#include "bitmaps/radiofolderon.xpm"
+#include "bitmaps/radiofolderon_dis.xpm"
+#include "bitmaps/radiofolderoff.xpm"
+#include "bitmaps/radiofolderoff_dis.xpm"
+
+#include "configtree.h"
+#include "configtooldoc.h"
+#include "configtoolview.h"
+#include "wxconfigtool.h"
+#include "mainframe.h"
+
+/*
+ * ctConfigTreeCtrl
+ */
+
+IMPLEMENT_CLASS(ctConfigTreeCtrl, wxTreeCtrl)
+
+BEGIN_EVENT_TABLE(ctConfigTreeCtrl, wxTreeCtrl)
+ EVT_MOUSE_EVENTS(ctConfigTreeCtrl::OnMouseEvent)
+ EVT_CHAR(ctConfigTreeCtrl::OnKeyDown)
+ EVT_TREE_SEL_CHANGED(-1, ctConfigTreeCtrl::OnSelChanged)
+ EVT_HELP(-1, ctConfigTreeCtrl::OnHelp)
+END_EVENT_TABLE()
+
+ctConfigTreeCtrl::ctConfigTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt,
+ const wxSize& sz, long style):
+wxTreeCtrl(parent, id, pt, sz, style)
+{
+ LoadIcons();
+
+ m_contextMenu = NULL;
+ m_contextMenu = new wxMenu;
+
+ m_contextMenu->Append(ctID_TREE_PASTE_BEFORE, _("Paste &before this option"));
+ m_contextMenu->Append(ctID_TREE_PASTE_AFTER, _("Paste &after this option"));
+ m_contextMenu->Append(ctID_TREE_PASTE_AS_CHILD, _("Paste as &child of this option"));
+ m_contextMenu->AppendSeparator();
+ m_contextMenu->Append(ctID_TREE_COPY, _("C&opy"));
+ m_contextMenu->Append(ctID_TREE_CUT, _("Cu&t"));
+
+ SetHelpText(_("This shows configuration settings that you can enable and disable."));
+}
+
+// Load the icons and initialize the tree
+void ctConfigTreeCtrl::LoadIcons()
+{
+ m_imageList = new wxImageList(16, 16, TRUE);
+ m_iconTable.SetImageList(m_imageList);
+ SetImageList(m_imageList);
+
+ m_iconTable.AddInfo("Group", wxIcon(closedfolder_xpm), 0, TRUE);
+ m_iconTable.AddInfo("Group", wxIcon(closedfolder_dis_xpm), 0, FALSE);
+
+ m_iconTable.AddInfo("Checkbox", wxIcon(checked_xpm), 0, TRUE);
+ m_iconTable.AddInfo("Checkbox", wxIcon(checked_dis_xpm), 0, FALSE);
+ m_iconTable.AddInfo("Checkbox", wxIcon(unchecked_xpm), 1, TRUE);
+ m_iconTable.AddInfo("Checkbox", wxIcon(unchecked_dis_xpm), 1, FALSE);
+
+ m_iconTable.AddInfo("CheckGroup", wxIcon(checkedfolder_xpm), 0, TRUE);
+ m_iconTable.AddInfo("CheckGroup", wxIcon(checkedfolder_dis_xpm), 0, FALSE);
+ m_iconTable.AddInfo("CheckGroup", wxIcon(uncheckedfolder_xpm), 1, TRUE);
+ m_iconTable.AddInfo("CheckGroup", wxIcon(uncheckedfolder_dis_xpm), 1, FALSE);
+
+ m_iconTable.AddInfo("RadioGroup", wxIcon(radiofolderon_xpm), 0, TRUE);
+ m_iconTable.AddInfo("RadioGroup", wxIcon(radiofolderon_dis_xpm), 0, FALSE);
+ m_iconTable.AddInfo("RadioGroup", wxIcon(radiofolderoff_xpm), 1, TRUE);
+ m_iconTable.AddInfo("RadioGroup", wxIcon(radiofolderoff_dis_xpm), 1, FALSE);
+
+ m_iconTable.AddInfo("Radiobutton", wxIcon(radioon_xpm), 0, TRUE);
+ m_iconTable.AddInfo("Radiobutton", wxIcon(radioon_dis_xpm), 0, FALSE);
+ m_iconTable.AddInfo("Radiobutton", wxIcon(radiooff_xpm), 1, TRUE);
+ m_iconTable.AddInfo("Radiobutton", wxIcon(radiooff_dis_xpm), 1, FALSE);
+}
+
+ctConfigTreeCtrl::~ctConfigTreeCtrl()
+{
+ SetImageList(NULL);
+ delete m_imageList;
+
+ delete m_contextMenu;
+}
+
+void ctConfigTreeCtrl::OnSelChanged(wxTreeEvent& event)
+{
+ ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
+ if (doc)
+ {
+ ctConfigToolHint hint(NULL, ctSelChanged);
+ doc->UpdateAllViews(NULL, & hint);
+ }
+}
+
+void ctConfigTreeCtrl::OnMouseEvent(wxMouseEvent& event)
+{
+ int flags = 0;
+ wxTreeItemId item = HitTest(wxPoint(event.GetX(), event.GetY()), flags);
+
+ if (event.LeftDown())
+ {
+ if (flags & wxTREE_HITTEST_ONITEMICON)
+ {
+ ctTreeItemData* data = (ctTreeItemData*) GetItemData(item);
+ ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
+ if (doc)
+ {
+ ctConfigToolView* view = wxDynamicCast(doc->GetFirstView(), ctConfigToolView);
+ if (view)
+ view->OnIconLeftDown(this, data->GetConfigItem());
+ }
+ }
+ }
+ else if (event.RightDown())
+ {
+ if ((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
+ (flags & wxTREE_HITTEST_ONITEMICON) ||
+ (flags & wxTREE_HITTEST_ONITEMINDENT) ||
+ (flags & wxTREE_HITTEST_ONITEMLABEL))
+ {
+ ctTreeItemData* data = (ctTreeItemData*) GetItemData(item);
+ ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
+ if (doc && data)
+ {
+ m_contextItem = data->GetConfigItem();
+ PopupMenu(m_contextMenu, event.GetX(), event.GetY());
+ }
+ }
+ }
+
+ event.Skip();
+}
+
+void ctConfigTreeCtrl::OnKeyDown(wxKeyEvent& event)
+{
+ wxTreeItemId id = GetSelection();
+ if (event.GetKeyCode() == WXK_SPACE)
+ {
+ if (id.IsOk())
+ {
+ ctConfigItem* item = ((ctTreeItemData*) GetItemData(id))->GetConfigItem();
+ ctConfigToolDoc* doc = wxGetApp().GetMainFrame()->GetDocument();
+ if (doc)
+ {
+ ctConfigToolView* view = wxDynamicCast(doc->GetFirstView(), ctConfigToolView);
+ if (view)
+ view->OnIconLeftDown(this, item);
+ }
+ }
+ }
+ else
+ {
+ event.Skip();
+ }
+}
+
+// Show help for this window
+void ctConfigTreeCtrl::OnHelp(wxHelpEvent& event)
+{
+ wxPoint pt = ScreenToClient(event.GetPosition());
+ int flags = 0;
+ wxTreeItemId id = HitTest(pt, flags);
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider && id > 0)
+ {
+ ctConfigItem* item = ((ctTreeItemData*) GetItemData(id))->GetConfigItem();
+ if (item)
+ {
+ wxString helpTopic = item->GetPropertyString(wxT("help-topic"));
+ if (!helpTopic.IsEmpty())
+ {
+ wxGetApp().GetReferenceHelpController().DisplaySection(helpTopic);
+ return;
+ }
+ }
+ }
+
+ event.Skip();
+}
+
+ctTreeItemData::~ctTreeItemData()
+{
+ if (m_configItem) delete m_configItem;
+}
+
diff --git a/utils/configtool/src/configtree.h b/utils/configtool/src/configtree.h
new file mode 100644
index 0000000000..57e7d057e5
--- /dev/null
+++ b/utils/configtool/src/configtree.h
@@ -0,0 +1,91 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: configtree.h
+// Purpose: wxWindows Configuration Tool tree class
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-03
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef _CT_CONFIGTREE_H_
+#define _CT_CONFIGTREE_H_
+
+#ifdef __GNUG__
+#pragma interface "configtree.cpp"
+#endif
+
+#include "wx/wx.h"
+#include "wx/treectrl.h"
+
+#include "configitem.h"
+#include "utils.h"
+
+/*!
+ * ctTreeItemData
+ * Holds the ctConfigItem for each tree item.
+ */
+
+class ctTreeItemData : public wxTreeItemData
+{
+public:
+ ctTreeItemData(ctConfigItem* item) : m_configItem(item) { }
+ ~ctTreeItemData() ;
+
+ ctConfigItem *GetConfigItem() const { return m_configItem; }
+ void SetConfigItem(ctConfigItem *item) { m_configItem = item; }
+
+private:
+ ctConfigItem* m_configItem;
+};
+
+
+/*!
+ * ctConfigTreeCtrl
+ * The options hierarchy viewer.
+ */
+
+class ctConfigTreeCtrl: public wxTreeCtrl
+{
+ DECLARE_CLASS(ctConfigTreeCtrl)
+public:
+ ctConfigTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pt = wxDefaultPosition,
+ const wxSize& sz = wxDefaultSize, long style = wxTR_HAS_BUTTONS);
+ ~ctConfigTreeCtrl();
+
+//// Event handlers
+ void OnMouseEvent(wxMouseEvent& event);
+ void OnSelChanged(wxTreeEvent& event);
+ void OnHelp(wxHelpEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
+
+//// Accessors
+
+ /// Get the table of icons
+ wxIconTable& GetIconTable() { return m_iconTable; }
+
+ /// Get the context menu
+ wxMenu* GetMenu() { return m_contextMenu; }
+
+ /// Get the item associated with the context menu events
+ ctConfigItem* GetContextItem() { return m_contextItem; }
+
+//// Operations
+
+ /// Loads the icons.
+ void LoadIcons();
+
+protected:
+ wxImageList* m_imageList;
+ wxIconTable m_iconTable;
+ wxMenu* m_contextMenu;
+ // The item associated with the context menu events
+ ctConfigItem* m_contextItem;
+
+ DECLARE_EVENT_TABLE()
+};
+
+#endif
+// _CT_CONFIGTREE_H_
diff --git a/utils/configtool/src/custompropertydialog.cpp b/utils/configtool/src/custompropertydialog.cpp
new file mode 100644
index 0000000000..ef631a4474
--- /dev/null
+++ b/utils/configtool/src/custompropertydialog.cpp
@@ -0,0 +1,261 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: custompropertydialog.cpp
+// Purpose: Custom property dialog
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation custompropertydialog.h
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "custompropertydialog.h"
+
+////@begin XPM images
+////@end XPM images
+
+/*!
+ * ctCustomPropertyDialog type definition
+ */
+
+IMPLEMENT_CLASS( ctCustomPropertyDialog, wxDialog )
+
+/*!
+ * ctCustomPropertyDialog event table definition
+ */
+
+BEGIN_EVENT_TABLE( ctCustomPropertyDialog, wxDialog )
+
+////@begin ctCustomPropertyDialog event table entries
+ EVT_UPDATE_UI( ID_PROPERTY_CHOICES, ctCustomPropertyDialog::OnUpdatePropertyChoices )
+
+ EVT_BUTTON( ID_PROPERTY_CHOICE_ADD, ctCustomPropertyDialog::OnPropertyChoiceAdd )
+ EVT_UPDATE_UI( ID_PROPERTY_CHOICE_ADD, ctCustomPropertyDialog::OnUpdatePropertyChoiceAdd )
+
+ EVT_BUTTON( ID_PROPERTY_CHOICE_REMOVE, ctCustomPropertyDialog::OnPropertyChoiceRemove )
+ EVT_UPDATE_UI( ID_PROPERTY_CHOICE_REMOVE, ctCustomPropertyDialog::OnUpdatePropertyChoiceRemove )
+
+////@end ctCustomPropertyDialog event table entries
+
+END_EVENT_TABLE()
+
+/*!
+ * ctCustomPropertyDialog constructor
+ */
+
+ctCustomPropertyDialog::ctCustomPropertyDialog( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+ m_type = wxT("string");
+
+ wxDialog::Create( parent, id, caption, pos, size, style );
+
+ CreateControls();
+}
+
+/*!
+ * Control creation for ctCustomPropertyDialog
+ */
+
+void ctCustomPropertyDialog::CreateControls()
+{
+////@begin ctCustomPropertyDialog content construction
+
+ ctCustomPropertyDialog* item1 = this;
+
+ wxBoxSizer* item2 = new wxBoxSizer(wxVERTICAL);
+ item1->SetSizer(item2);
+ item1->SetAutoLayout(TRUE);
+
+ wxBoxSizer* item3 = new wxBoxSizer(wxVERTICAL);
+ item2->Add(item3, 1, wxGROW|wxALL, 5);
+
+ wxStaticText* item4 = new wxStaticText(item1, wxID_STATIC, _("&Enter name, type and description for your custom property."), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item4, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxStaticText* item5 = new wxStaticText(item1, wxID_STATIC, _("&Name:"), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item5, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxTextCtrl* item6 = new wxTextCtrl(item1, ID_CUSTOMPROPERTYNAME, _(""), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item6, 0, wxGROW|wxALL, 5);
+
+ wxBoxSizer* item7 = new wxBoxSizer(wxHORIZONTAL);
+ item3->Add(item7, 0, wxGROW, 5);
+
+ wxBoxSizer* item8 = new wxBoxSizer(wxVERTICAL);
+ item7->Add(item8, 1, wxGROW, 5);
+
+ wxStaticText* item9 = new wxStaticText(item1, wxID_STATIC, _("&Data type:"), wxDefaultPosition, wxDefaultSize, 0);
+ item8->Add(item9, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxString item10Strings[] = {
+ _("string"),
+ _("bool"),
+ _("double"),
+ _("long")
+ };
+ wxChoice* item10 = new wxChoice(item1, ID_CUSTOMPROPERTYTYPE, wxDefaultPosition, wxDefaultSize, 4, item10Strings, 0);
+ item10->SetStringSelection(_("string"));
+ item8->Add(item10, 1, wxGROW|wxALL, 5);
+
+ wxBoxSizer* item11 = new wxBoxSizer(wxVERTICAL);
+ item7->Add(item11, 0, wxALIGN_CENTER_VERTICAL, 5);
+
+ wxStaticText* item12 = new wxStaticText(item1, wxID_STATIC, _("&Editor type:"), wxDefaultPosition, wxDefaultSize, 0);
+ item11->Add(item12, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxString item13Strings[] = {
+ _("string"),
+ _("choice"),
+ _("bool"),
+ _("float"),
+ _("integer"),
+ _("configitems")
+ };
+ wxChoice* item13 = new wxChoice(item1, ID_CUSTOMPROPERTYEDITORTYPE, wxDefaultPosition, wxDefaultSize, 6, item13Strings, 0);
+ item13->SetStringSelection(_("string"));
+ item11->Add(item13, 1, wxGROW|wxALL, 5);
+
+ wxStaticBox* item14Static = new wxStaticBox(item1, -1, _("Choices"));
+ wxStaticBoxSizer* item14 = new wxStaticBoxSizer(item14Static, wxHORIZONTAL);
+ item3->Add(item14, 0, wxGROW|wxALL, 5);
+
+ wxString* item15Strings = NULL;
+ wxListBox* item15 = new wxListBox(item1, ID_PROPERTY_CHOICES, wxDefaultPosition, wxDefaultSize, 0, item15Strings, wxLB_SINGLE);
+ item14->Add(item15, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxBoxSizer* item16 = new wxBoxSizer(wxVERTICAL);
+ item14->Add(item16, 0, wxALIGN_CENTER_VERTICAL, 5);
+
+ wxButton* item17 = new wxButton(item1, ID_PROPERTY_CHOICE_ADD, _("&Add..."), wxDefaultPosition, wxDefaultSize, 0);
+ item16->Add(item17, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+ wxButton* item18 = new wxButton(item1, ID_PROPERTY_CHOICE_REMOVE, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0);
+ item16->Add(item18, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+ wxStaticText* item19 = new wxStaticText(item1, wxID_STATIC, _("&Description:"), wxDefaultPosition, wxDefaultSize, 0);
+ item3->Add(item19, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);
+
+ wxTextCtrl* item20 = new wxTextCtrl(item1, ID_CUSTOMPROPERTYDESCRIPTION, _(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH);
+ item3->Add(item20, 1, wxGROW|wxALL, 5);
+
+ wxBoxSizer* item21 = new wxBoxSizer(wxHORIZONTAL);
+ item3->Add(item21, 0, wxGROW|wxALL, 5);
+
+ item21->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item23 = new wxButton(item1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0);
+ item21->Add(item23, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item24 = new wxButton(item1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0);
+ item21->Add(item24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ wxButton* item25 = new wxButton(item1, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, 0);
+ item21->Add(item25, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+ GetSizer()->Fit(this);
+ GetSizer()->SetSizeHints(this);
+ Centre();
+////@end ctCustomPropertyDialog content construction
+
+ // Add validators
+ FindWindow(ID_CUSTOMPROPERTYNAME)->SetValidator(wxGenericValidator(& m_name));
+ FindWindow(ID_CUSTOMPROPERTYTYPE)->SetValidator(wxGenericValidator(& m_type));
+ FindWindow(ID_CUSTOMPROPERTYEDITORTYPE)->SetValidator(wxGenericValidator(& m_editorType));
+ FindWindow(ID_CUSTOMPROPERTYDESCRIPTION)->SetValidator(wxGenericValidator(& m_description));
+}
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool ctCustomPropertyDialog::ShowToolTips()
+{
+ return TRUE;
+}
+
+/*!
+ * Update event handler for ID_PROPERTY_CHOICES
+ */
+
+void ctCustomPropertyDialog::OnUpdatePropertyChoices( wxUpdateUIEvent& event )
+{
+ wxChoice* choice = (wxChoice* ) FindWindow(ID_CUSTOMPROPERTYTYPE);
+ event.Enable( choice->GetSelection() > -1 && choice->GetStringSelection() == wxT("choice") );
+}
+
+/*!
+ * Event handler for ID_PROPERTY_CHOICE_ADD
+ */
+
+void ctCustomPropertyDialog::OnPropertyChoiceAdd( wxCommandEvent& event )
+{
+ wxChoice* choice = (wxChoice* ) FindWindow(ID_CUSTOMPROPERTYTYPE);
+ if ( choice->GetSelection() > -1 && choice->GetStringSelection() == wxT("choice") )
+ {
+ wxString str = wxGetTextFromUser(_T("New choice"), _("Add choice"));
+ if (!str.IsEmpty())
+ {
+ wxListBox* listBox = (wxListBox* ) FindWindow(ID_PROPERTY_CHOICES);
+ listBox->Append(str);
+ m_choices.Add(str);
+ }
+ }
+}
+
+/*!
+ * Update event handler for ID_PROPERTY_CHOICE_ADD
+ */
+
+void ctCustomPropertyDialog::OnUpdatePropertyChoiceAdd( wxUpdateUIEvent& event )
+{
+ wxChoice* choice = (wxChoice* ) FindWindow(ID_CUSTOMPROPERTYEDITORTYPE);
+ event.Enable( choice->GetSelection() > -1 && choice->GetStringSelection() == wxT("choice") );
+}
+
+/*!
+ * Event handler for ID_PROPERTY_CHOICE_REMOVE
+ */
+
+void ctCustomPropertyDialog::OnPropertyChoiceRemove( wxCommandEvent& event )
+{
+ wxChoice* choice = (wxChoice* ) FindWindow(ID_CUSTOMPROPERTYEDITORTYPE);
+ wxListBox* listBox = (wxListBox* ) FindWindow(ID_PROPERTY_CHOICES);
+ if (listBox->GetSelection() > -1)
+ {
+ listBox->Delete(listBox->GetSelection());
+ m_choices.Remove(listBox->GetSelection());
+ }
+}
+
+/*!
+ * Update event handler for ID_PROPERTY_CHOICE_REMOVE
+ */
+
+void ctCustomPropertyDialog::OnUpdatePropertyChoiceRemove( wxUpdateUIEvent& event )
+{
+ wxChoice* choice = (wxChoice* ) FindWindow(ID_CUSTOMPROPERTYEDITORTYPE);
+ wxListBox* listBox = (wxListBox* ) FindWindow(ID_PROPERTY_CHOICES);
+ event.Enable( choice->GetSelection() > -1 && choice->GetStringSelection() == wxT("choice") &&
+ listBox->GetSelection() > -1 );
+}
+
+void ctCustomPropertyDialog::SetChoices(const wxArrayString& choices)
+{
+ wxListBox* listBox = (wxListBox* ) FindWindow(ID_PROPERTY_CHOICES);
+ size_t i, len = choices.GetCount();
+ for (i = 0; i < len; i++)
+ listBox->Append(m_choices[i]);
+}
diff --git a/utils/configtool/src/custompropertydialog.h b/utils/configtool/src/custompropertydialog.h
new file mode 100644
index 0000000000..ffaff8f859
--- /dev/null
+++ b/utils/configtool/src/custompropertydialog.h
@@ -0,0 +1,113 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: custompropertydialog.h
+// Purpose: Custom property dialog
+// Author: Julian Smart
+// Modified by:
+// Created: 2003-06-04
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence:
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CUSTOMPROPERTYDIALOG_H_
+#define _CUSTOMPROPERTYDIALOG_H_
+
+#ifdef __GNUG__
+#pragma interface custompropertydialog.cpp
+#endif
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_CUSTOMPROPERTYDIALOG 10000
+#define ID_CUSTOMPROPERTYNAME 10003
+#define ID_CUSTOMPROPERTYTYPE 10002
+#define ID_CUSTOMPROPERTYEDITORTYPE 10008
+#define ID_PROPERTY_CHOICES 10001
+#define ID_PROPERTY_CHOICE_ADD 10005
+#define ID_PROPERTY_CHOICE_REMOVE 10006
+#define ID_CUSTOMPROPERTYDESCRIPTION 10004
+////@end control identifiers
+
+/*!
+ * ctCustomPropertyDialog class declaration
+ */
+
+class ctCustomPropertyDialog: public wxDialog
+{
+public:
+ /// Constructor
+ ctCustomPropertyDialog( wxWindow* parent, wxWindowID id = -1, const wxString& caption = _("Edit Custom Property"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU );
+
+ /// Creates the controls and sizers
+ void CreateControls();
+
+////@begin ctCustomPropertyDialog event handler declarations
+
+ /// Update event handler for ID_PROPERTY_CHOICES
+ void OnUpdatePropertyChoices( wxUpdateUIEvent& event );
+
+ /// Event handler for ID_PROPERTY_CHOICE_ADD
+ void OnPropertyChoiceAdd( wxCommandEvent& event );
+
+ /// Update event handler for ID_PROPERTY_CHOICE_ADD
+ void OnUpdatePropertyChoiceAdd( wxUpdateUIEvent& event );
+
+ /// Event handler for ID_PROPERTY_CHOICE_REMOVE
+ void OnPropertyChoiceRemove( wxCommandEvent& event );
+
+ /// Update event handler for ID_PROPERTY_CHOICE_REMOVE
+ void OnUpdatePropertyChoiceRemove( wxUpdateUIEvent& event );
+
+////@end ctCustomPropertyDialog event handler declarations
+
+////@begin ctCustomPropertyDialog member function declarations
+
+////@end ctCustomPropertyDialog member function declarations
+
+ /// Should we show tooltips?
+ static bool ShowToolTips();
+
+ void SetPropertyName(const wxString& name) { m_name = name; }
+ wxString GetPropertyName() { return m_name; }
+
+ void SetPropertyType(const wxString& type) { m_type = type; }
+ wxString GetPropertyType() { return m_type; }
+
+ void SetEditorType(const wxString& type) { m_editorType = type; }
+ wxString GetEditorType() { return m_editorType; }
+
+ void SetPropertyDescription(const wxString& descr) { m_description = descr; }
+ wxString GetPropertyDescription() { return m_description; }
+
+ void SetChoices(const wxArrayString& choices) ;
+ wxArrayString GetChoices() { return m_choices; }
+
+ DECLARE_CLASS( ctCustomPropertyDialog )
+ DECLARE_EVENT_TABLE()
+
+ wxString m_name;
+ wxString m_type;
+ wxString m_description;
+ wxString m_editorType;
+ wxArrayString m_choices;
+};
+
+#endif
+ // _CUSTOMPROPERTYDIALOG_H_
diff --git a/utils/configtool/src/htmlparser.cpp b/utils/configtool/src/htmlparser.cpp
new file mode 100644
index 0000000000..a07089fb5a
--- /dev/null
+++ b/utils/configtool/src/htmlparser.cpp
@@ -0,0 +1,989 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: htmlparser.cpp
+// Purpose: Simple HTML parser
+// Author: Julian Smart
+// Modified by:
+// Created: 2002-09-25
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+#ifdef __GNUG__
+ #pragma implementation "htmlparser.h"
+#endif
+
+#include "wx/wx.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/textfile.h"
+#include "wx/wfstream.h"
+#include "wx/txtstrm.h"
+
+#include
+
+#include "htmlparser.h"
+
+/// Useful insertion operators for wxOutputStream.
+static wxOutputStream& operator <<(wxOutputStream& stream, const wxString& s)
+{
+ wxTextOutputStream txt(stream); // This is to make sure the line-ending is native!
+
+ txt.WriteString(s);
+ return stream;
+}
+
+#if 0 // Gives warning because not used...
+static wxOutputStream& operator <<(wxOutputStream& stream, long l)
+{
+ wxString str;
+ str.Printf("%ld", l);
+ return stream << str;
+}
+
+static wxOutputStream& operator <<(wxOutputStream& stream, const char c)
+{
+ wxString str;
+ str.Printf("%c", c);
+ return stream << str;
+}
+#endif // 0
+
+/*
+ * wxSimpleHtmlAttribute
+ * Representation of an attribute
+ */
+
+wxSimpleHtmlParser::wxSimpleHtmlParser()
+{
+ m_topLevel = NULL;
+ m_pos = 0;
+}
+
+
+wxSimpleHtmlParser::~wxSimpleHtmlParser()
+{
+ Clear();
+}
+
+bool wxSimpleHtmlParser::ParseFile(const wxString& filename)
+{
+ wxTextFile textFile;
+
+ if (textFile.Open(filename))
+ {
+ wxString text;
+ wxString line;
+ int i;
+ int count = textFile.GetLineCount();
+ for (i = 0; i < count; i++)
+ {
+ if (i == 0)
+ line = textFile.GetFirstLine();
+ else
+ line = textFile.GetNextLine();
+
+ text += line;
+ if (i != (count - 1))
+ text += wxT("\n");
+ }
+
+#if 0
+ for ( line = textFile.GetFirstLine(); !textFile.Eof(); line = textFile.GetNextLine() )
+ {
+ text += line;
+ if (!textFile.Eof())
+ text += wxT("\n");
+ }
+#endif
+
+ return ParseString(text);
+ }
+ else
+ return FALSE;
+}
+
+bool wxSimpleHtmlParser::ParseString(const wxString& str)
+{
+ Clear();
+
+ m_pos = 0;
+ m_text = str;
+ m_length = str.Length();
+
+ m_topLevel = new wxSimpleHtmlTag(wxT("TOPLEVEL"), wxSimpleHtmlTag_TopLevel);
+
+ bool bResult = ParseHtml(m_topLevel);
+
+ wxASSERT(bResult); // Failed to parse the TAGs.
+ // Hint: Check if every open tag has a close tag!
+
+ return bResult;
+}
+
+// Main recursive parsing function
+bool wxSimpleHtmlParser::ParseHtml(wxSimpleHtmlTag* parent)
+{
+ if (!parent)
+ return FALSE;
+
+ while (!Eof())
+ {
+ EatWhitespace();
+ if (IsComment())
+ {
+ ParseComment();
+ }
+ else if (IsDirective())
+ {
+ wxSimpleHtmlTag* tag = ParseDirective();
+ if (tag)
+ parent->AppendTag(tag);
+ }
+ else if (IsXMLDeclaration())
+ {
+ wxSimpleHtmlTag* tag = ParseXMLDeclaration();
+ if (tag)
+ parent->AppendTag(tag);
+ }
+ else if (IsTagClose())
+ {
+ wxSimpleHtmlTag* tag = ParseTagClose();
+ if (tag)
+ {
+ if (IsCloseTagNeeded(tag->GetName()))
+ {
+ if (!parent->GetParent())
+ return FALSE;
+ parent->GetParent()->AppendTag(tag);
+ return TRUE;
+ }
+ else
+ parent->AppendTag(tag);
+ }
+ }
+ else if (IsTagStartBracket(GetChar(m_pos)))
+ {
+ wxSimpleHtmlTag* tag = ParseTagHeader();
+ if (tag)
+ parent->AppendTag(tag);
+
+ if (IsCloseTagNeeded(tag->GetName()))
+ {
+ if (!ParseHtml(tag))
+ return FALSE; // Something didn't go ok, so don't continue.
+ }
+ }
+ else
+ {
+ // Just a text string
+ wxString text;
+ ParseText(text);
+
+ wxSimpleHtmlTag* tag = new wxSimpleHtmlTag(wxT("TEXT"), wxSimpleHtmlTag_Text);
+ tag->SetText(text);
+ if(parent->GetParent())
+ parent->GetParent()->AppendTag(tag);
+ else
+ parent->AppendTag(tag); // When this occurs it is probably the
+ // empty lines at the end of the file...
+ }
+ }
+ return TRUE;
+}
+
+// Plain text, up until an angled bracket
+bool wxSimpleHtmlParser::ParseText(wxString& text)
+{
+ while (!Eof() && GetChar(m_pos) != wxT('<'))
+ {
+ text += GetChar(m_pos);
+ m_pos ++;
+ }
+ DecodeSpecialChars(text);
+ return TRUE;
+}
+
+wxSimpleHtmlTag* wxSimpleHtmlParser::ParseTagHeader()
+{
+ if (IsTagStartBracket(GetChar(m_pos)))
+ {
+ m_pos ++;
+ EatWhitespace();
+
+ wxString word;
+ ReadWord(word, TRUE);
+
+ EatWhitespace();
+
+ wxSimpleHtmlTag* tag = new wxSimpleHtmlTag(word, wxSimpleHtmlTag_Open);
+
+ ParseAttributes(tag);
+
+ EatWhitespace();
+
+ if (IsTagEndBracket(GetChar(m_pos)))
+ m_pos ++;
+
+ return tag;
+ }
+ else
+ return NULL;
+}
+
+wxSimpleHtmlTag* wxSimpleHtmlParser::ParseTagClose()
+{
+ Matches(wxT(""), TRUE);
+
+ EatWhitespace();
+
+ wxString word;
+ ReadWord(word, TRUE);
+
+ EatWhitespace();
+ m_pos ++;
+
+ wxSimpleHtmlTag* tag = new wxSimpleHtmlTag(word, wxSimpleHtmlTag_Close);
+ return tag;
+}
+
+bool wxSimpleHtmlParser::ParseAttributes(wxSimpleHtmlTag* tag)
+{
+ // Parse attributes of a tag header until we reach >
+ while (!IsTagEndBracket(GetChar(m_pos)) && !Eof())
+ {
+ EatWhitespace();
+
+ wxString attrName, attrValue;
+
+ if (IsString())
+ {
+ ReadString(attrName, TRUE);
+ tag->AppendAttribute(attrName, wxEmptyString);
+ }
+ else if (IsNumeric(GetChar(m_pos)))
+ {
+ ReadNumber(attrName, TRUE);
+ tag->AppendAttribute(attrName, wxEmptyString);
+ }
+ else
+ {
+ // Try to read an attribute name/value pair, or at least a name
+ // without the value
+ ReadLiteral(attrName, TRUE);
+ EatWhitespace();
+
+ if (GetChar(m_pos) == wxT('='))
+ {
+ m_pos ++;
+ EatWhitespace();
+
+ if (IsString())
+ ReadString(attrValue, TRUE);
+ else if (!Eof() && !IsTagEndBracket(GetChar(m_pos)))
+ ReadLiteral(attrValue, TRUE);
+ }
+ if (!attrName.IsEmpty())
+ tag->AppendAttribute(attrName, attrValue);
+ }
+ }
+ return TRUE;
+}
+
+// e.g.
+wxSimpleHtmlTag* wxSimpleHtmlParser::ParseDirective()
+{
+ Matches(wxT("
+wxSimpleHtmlTag* wxSimpleHtmlParser::ParseXMLDeclaration()
+{
+ Matches(wxT(""), TRUE);
+
+ EatWhitespace();
+
+ wxString word;
+ ReadWord(word, TRUE);
+
+ EatWhitespace();
+
+ wxSimpleHtmlTag* tag = new wxSimpleHtmlTag(word, wxSimpleHtmlTag_XMLDeclaration);
+
+ ParseAttributes(tag);
+
+ EatWhitespace();
+
+ if (IsTagEndBracket(GetChar(m_pos)))
+ m_pos ++;
+
+ return tag;
+}
+
+bool wxSimpleHtmlParser::ParseComment()
+{
+ // Eat the comment tag start
+ Matches(wxT(""), TRUE))
+ {
+ m_pos ++;
+ }
+
+ return TRUE;
+}
+
+bool wxSimpleHtmlParser::EatWhitespace()
+{
+ while (!Eof() && IsWhitespace(GetChar(m_pos)))
+ m_pos ++;
+ return TRUE;
+}
+
+bool wxSimpleHtmlParser::EatWhitespace(int& pos)
+{
+ while (!Eof(pos) && IsWhitespace(GetChar(pos)))
+ pos ++;
+ return TRUE;
+}
+
+bool wxSimpleHtmlParser::ReadString(wxString& str, bool eatIt)
+{
+ int pos = m_pos;
+ if (GetChar(pos) == (int) '"')
+ {
+ pos ++;
+ while (!Eof(pos) && GetChar(pos) != (int) '"')
+ {
+ // TODO: how are quotes escaped in HTML?
+ str += (wxChar) GetChar(pos);
+ pos ++;
+ }
+ if (GetChar(pos) == (int) '"')
+ pos ++;
+ if (eatIt)
+ m_pos = pos;
+ DecodeSpecialChars(str);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+bool wxSimpleHtmlParser::ReadWord(wxString& str, bool eatIt)
+{
+ int pos = m_pos;
+
+ if (!IsAlpha(GetChar(pos)))
+ return FALSE;
+
+ str += (wxChar) GetChar(pos) ;
+ pos ++;
+
+ while (!Eof(pos) && IsWordChar(GetChar(pos)))
+ {
+ str += (wxChar) GetChar(pos);
+ pos ++;
+ }
+ if (eatIt)
+ m_pos = pos;
+ DecodeSpecialChars(str);
+ return TRUE;
+}
+
+bool wxSimpleHtmlParser::ReadNumber(wxString& str, bool eatIt)
+{
+ int pos = m_pos;
+
+ if (!IsNumeric(GetChar(pos)))
+ return FALSE;
+
+ str += (wxChar) GetChar(pos) ;
+ pos ++;
+
+ while (!Eof(pos) && IsNumeric(GetChar(pos)))
+ {
+ str += (wxChar) GetChar(pos);
+ pos ++;
+ }
+ if (eatIt)
+ m_pos = pos;
+ DecodeSpecialChars(str);
+ return TRUE;
+}
+
+// Could be number, string, whatever, but read up until whitespace or end of tag (but not a quoted string)
+bool wxSimpleHtmlParser::ReadLiteral(wxString& str, bool eatIt)
+{
+ int pos = m_pos;
+
+ while (!Eof(pos) && !IsWhitespace(GetChar(pos)) && !IsTagEndBracket(GetChar(pos)) && GetChar(pos) != wxT('='))
+ {
+ str += GetChar(pos);
+ pos ++;
+ }
+ if (eatIt)
+ m_pos = pos;
+ DecodeSpecialChars(str);
+ return TRUE;
+}
+
+bool wxSimpleHtmlParser::IsComment()
+{
+ return Matches(wxT("