initial version
[lsystem3d.git] / src / gui.cpp
diff --git a/src/gui.cpp b/src/gui.cpp
new file mode 100644 (file)
index 0000000..d068cd5
--- /dev/null
@@ -0,0 +1,211 @@
+// 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();
+}