--- /dev/null
+// Copyright (C) 2006 Erik Dahlberg
+//
+// This file is part of LSystem3d.
+//
+// LSystem3D is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// LSystem3D is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with LSystem3D; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+
+
+#include <map>
+#include <string>
+
+#include "fx.h"
+
+#include "gui.h"
+#include "lindenmayersystem.h"
+#include "lsystemparameters.h"
+#include "renderingsurface.h"
+
+
+
+// message map
+FXDEFMAP(GUI) GUIMap[] =
+{
+ FXMAPFUNC(SEL_COMMAND, GUI::ID_GENERATE, GUI::onGenerateButtonPressed)
+};
+
+// macro to set up class implementation
+FXIMPLEMENT(GUI, FXMainWindow, GUIMap, ARRAYNUMBER(GUIMap))
+
+
+
+/**
+ * Constructor
+ * @param application the FOX application object
+ * @param renderingSurface the rendering surface
+ * @param lsystem the Lindenmayer-system
+ */
+GUI::GUI(FXApp *application, RenderingSurface *renderingSurface, LindenmayerSystem *lsystem) : FXMainWindow(application, "LSystem3D" , NULL, NULL, DECOR_ALL, 920, 100, 0, 0)
+{
+ _lsystem = lsystem;
+ _renderingSurface = renderingSurface;
+
+
+ // create the widgets
+
+ // the main frame
+ FXVerticalFrame *mainFrame = new FXVerticalFrame(this, LAYOUT_FILL_X);
+
+ // axiom
+ FXHorizontalFrame *axiomFrame = new FXHorizontalFrame(mainFrame, LAYOUT_FILL_X);
+ new FXLabel(axiomFrame, "Axiom:");
+ _axiomTextField = new FXTextField(axiomFrame, 10, NULL, 0, LAYOUT_FILL_X);
+
+ // rules
+ FXHorizontalFrame *rulesFrame = new FXHorizontalFrame(mainFrame, LAYOUT_FILL_X);
+ new FXLabel(rulesFrame, "Rules:");
+ _rulesText = new FXText(rulesFrame, NULL, 0, LAYOUT_FILL_X);
+ _rulesText->setVisibleColumns(30);
+ _rulesText->setVisibleRows(10);
+
+ // angle
+ FXHorizontalFrame *angleFrame = new FXHorizontalFrame(mainFrame);
+ new FXLabel(angleFrame, "Angle:");
+ _angleRealSpinner = new FXRealSpinner(angleFrame, 5);
+
+ // iterations
+ FXHorizontalFrame *iterationsFrame = new FXHorizontalFrame(mainFrame);
+ new FXLabel(iterationsFrame, "Iterations:");
+ _iterationsSpinner = new FXSpinner(iterationsFrame, 5);
+
+ // diameter
+ FXHorizontalFrame *diameterFrame = new FXHorizontalFrame(mainFrame);
+ new FXLabel(diameterFrame, "Diameter:");
+ _diameterRealSpinner = new FXRealSpinner(diameterFrame, 5);
+ _diameterRealSpinner->setValue(0.2);
+ _diameterRealSpinner->setIncrement(0.1);
+
+ // diameter factor
+ new FXLabel(diameterFrame, "Factor:");
+ _diameterFactorRealSpinner = new FXRealSpinner(diameterFrame, 5);
+ _diameterFactorRealSpinner->setValue(0.8);
+ _diameterFactorRealSpinner->setIncrement(0.1);
+
+ // separator
+ new FXHorizontalSeparator(mainFrame, SEPARATOR_RIDGE | LAYOUT_FILL_X);
+
+ // generate
+ new FXButton(mainFrame, "&Generate", NULL, this, GUI::ID_GENERATE);
+
+
+
+ // load L-system parameters from file and sync with GUI
+
+ _lsystemParameters.load(_lsystem, "lsystem.xml");
+
+ // axiom
+ _axiomTextField->setText(_lsystem->getAxiom().c_str());
+
+ // rules
+ map<string,string> allRulesSrc = _lsystem->getRules();
+ string allRulesDst;
+ for (map<string,string>::iterator currentRule = allRulesSrc.begin();
+ currentRule != allRulesSrc.end();
+ currentRule++)
+ {
+ // one rule
+ string rule = currentRule->first + "=" + currentRule->second + '\n';
+ allRulesDst += rule.c_str();
+ }
+ _rulesText->setText(allRulesDst.c_str(), allRulesDst.size());
+
+ // angle
+ _angleRealSpinner->setValue(_lsystem->getAngle());
+
+ // iterations
+ _iterationsSpinner->setValue(_lsystem->getNumIterations());
+}
+
+
+
+/**
+ * Create and initialize the window
+ */
+void GUI::create()
+{
+ // create the window and make it appear
+ FXMainWindow::create();
+ show();
+}
+
+
+
+/**
+ * Called by the system when the "generate"-button is pressed
+ * @param sender the sender object
+ * @param selector message type and id
+ * @param data event related data
+ * @return
+ */
+long GUI::onGenerateButtonPressed(FXObject *sender, FXSelector selector, void *data)
+{
+ // clear L-system
+ _lsystem->clear();
+
+
+ // load data from widgets into L-system
+
+ // axiom
+ _lsystem->setAxiom(_axiomTextField->getText().text());
+
+ // rules
+ string ruleSet = _rulesText->getText().text();
+ string currentRule;
+ string ruleName;
+ bool newRule = true;
+ for (int i = 0; i < ruleSet.size(); i++)
+ {
+ if (newRule)
+ {
+ // get rule name
+ ruleName = ruleSet[i];
+ i += 2;
+ newRule = false;
+ }
+
+ if (ruleSet[i] != '\n' || i == ruleSet.size() - 1)
+ {
+ // part of current rule
+ currentRule += ruleSet[i];
+ }
+
+ if (ruleSet[i] == '\n' || i == ruleSet.size() - 1)
+ {
+ // end of rule
+ _lsystem->setRule(ruleName, currentRule);
+ ruleName.clear();
+ currentRule.clear();
+ newRule = true;
+ }
+ }
+
+ // angle
+ _lsystem->setAngle(_angleRealSpinner->getValue());
+
+ // iterations
+ _lsystem->setNumIterations(_iterationsSpinner->getValue());
+
+ // diameter
+ _lsystem->setDiameter(_diameterRealSpinner->getValue());
+
+ // diameter factor
+ _lsystem->setDiameterFactor(_diameterFactorRealSpinner->getValue());
+
+
+ // generate and render L-system to screen
+ _lsystem->generate();
+ _renderingSurface->draw();
+}