* Added help button and dialog.
authorspixx <spixx>
Sat, 11 Nov 2006 11:57:09 +0000 (11:57 +0000)
committerspixx <spixx>
Sat, 11 Nov 2006 11:57:09 +0000 (11:57 +0000)
* Adaptation to new classes Rule/RuleSet.

src/gui.cpp

index d068cd5eacc177e4d834e1402f97beb042de30df..1a8ca9e6af2ed058ea11bdf9f3c4204e2fb0b7c2 100644 (file)
@@ -1,6 +1,6 @@
 // Copyright (C) 2006 Erik Dahlberg
 // 
-// This file is part of LSystem3d.
+// 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
@@ -19,7 +19,7 @@
 
 
 
-#include <map>
+#include <sstream>
 #include <string>
 
 #include "fx.h"
 #include "lindenmayersystem.h"
 #include "lsystemparameters.h"
 #include "renderingsurface.h"
+#include "rule.h"
+#include "ruleset.h"
+
+using namespace std;
 
 
 
 // message map
 FXDEFMAP(GUI) GUIMap[] =
 {
-    FXMAPFUNC(SEL_COMMAND, GUI::ID_GENERATE, GUI::onGenerateButtonPressed)
+    FXMAPFUNC(SEL_COMMAND, GUI::ID_GENERATE, GUI::onGenerateButtonPressed),
+    FXMAPFUNC(SEL_COMMAND, GUI::ID_HELP,     GUI::onHelpButtonPressed)
 };
 
 // macro to set up class implementation
@@ -54,52 +59,92 @@ GUI::GUI(FXApp *application, RenderingSurface *renderingSurface, LindenmayerSyst
     _renderingSurface = renderingSurface;
     
     
+    
     // create the widgets
     
     // the main frame
     FXVerticalFrame *mainFrame = new FXVerticalFrame(this, LAYOUT_FILL_X);
     
-    // axiom
+    // axiom text field
     FXHorizontalFrame *axiomFrame = new FXHorizontalFrame(mainFrame, LAYOUT_FILL_X);
     new FXLabel(axiomFrame, "Axiom:");
     _axiomTextField = new FXTextField(axiomFrame, 10, NULL, 0, LAYOUT_FILL_X);
-
-    // rules
+    
+    // rules multiline text field
     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
+    
+    // angle spinner
     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
+    
+    // depth spinner
+    FXHorizontalFrame *depthFrame = new FXHorizontalFrame(mainFrame);
+    new FXLabel(depthFrame, "Depth:");
+    _depthSpinner = new FXSpinner(depthFrame, 5);
+    
+    // diameter spinner
     FXHorizontalFrame *diameterFrame = new FXHorizontalFrame(mainFrame);
     new FXLabel(diameterFrame, "Diameter:");
     _diameterRealSpinner = new FXRealSpinner(diameterFrame, 5);
     _diameterRealSpinner->setValue(0.2);
     _diameterRealSpinner->setIncrement(0.1);
     
-    // diameter factor
+    // diameter factor spinner
     new FXLabel(diameterFrame, "Factor:");
     _diameterFactorRealSpinner = new FXRealSpinner(diameterFrame, 5);
-    _diameterFactorRealSpinner->setValue(0.8);
-    _diameterFactorRealSpinner->setIncrement(0.1);
+    _diameterFactorRealSpinner->setValue(0.9);
+    _diameterFactorRealSpinner->setIncrement(0.01);
     
     // separator
     new FXHorizontalSeparator(mainFrame, SEPARATOR_RIDGE | LAYOUT_FILL_X);
 
-    // generate
+    // generate button
     new FXButton(mainFrame, "&Generate", NULL, this, GUI::ID_GENERATE);
     
+    // help button
+    new FXButton(mainFrame, "&Help", NULL, this, GUI::ID_HELP);
+    
+    // help dialog
+    stringstream helpText;
+    helpText << "Mouse:" << endl
+             << "Left button: Move model in z-plane" << endl
+             << "Middle button: Zoom in/out" << endl
+             << "Right button: Rotate around y-axis" << endl
+             << endl
+             << "Rules:" << endl
+             << "F : Walk forward, leaving a trace" << endl
+             << "A-Z : Replacement rule" << endl
+             << "A(0.33) : Probability factor 0.33 for rule \"A\"" << endl
+             << "= : Rule assignment" << endl
+             << "+ : Turn left" << endl
+             << "- : Turn right" << endl
+             << "&& : Pitch down" << endl
+             << "^ : Pitch up" << endl
+             << "\\ : Roll left" << endl
+             << "/ : Roll right" << endl
+             << "| : Turn around 180 degrees" << endl
+             << "[ : Save state to stack" << endl
+             << "] : Load state from stack" << endl
+             << "{ : Create a planar surface" << endl
+             << "} : Close a planar surface" << endl
+             << "f : One vertex in a planar surface, specified CCW" << endl
+             << "! : Decrement diameter of segment" << endl
+             << "\' : Increment current index to color table" << endl
+             << ", : Decrement current index to color table" << endl
+             << endl
+             << "Example:" << endl
+             << "F(0.33)=[+F/L]/F[-F&&L]F!" << endl
+             << "F(0.33)=F[+F+L]&&F!" << endl
+             << "F(0.34)=F[-F-L]/F!" << endl
+             << "L=,{-f++f-|-f++f-}'";
+    
+    _helpMessageBox = new FXMessageBox(getApp(), "Help", helpText.str().c_str(), NULL, MBOX_OK);
+    
     
     
     // load L-system parameters from file and sync with GUI
@@ -107,26 +152,23 @@ GUI::GUI(FXApp *application, RenderingSurface *renderingSurface, LindenmayerSyst
     _lsystemParameters.load(_lsystem, "lsystem.xml");
     
     // axiom
-    _axiomTextField->setText(_lsystem->getAxiom().c_str());
+    _axiomTextField->setText(_lsystem->getAxiom().getContent().c_str());
     
     // rules
-    map<string,string> allRulesSrc = _lsystem->getRules();
-    string allRulesDst;
-    for (map<string,string>::iterator currentRule = allRulesSrc.begin();
-         currentRule != allRulesSrc.end();
-         currentRule++)
+    rulemap rules = _lsystem->getRules().getRules();
+    string rulesString;    
+    for (rulemap::iterator it = rules.begin(); it != rules.end(); ++it)
     {
-        // one rule
-        string rule = currentRule->first + "=" + currentRule->second + '\n';
-        allRulesDst += rule.c_str();
+        rulesString += it->second.toString();
+        rulesString += '\n';
     }
-    _rulesText->setText(allRulesDst.c_str(), allRulesDst.size());
+    _rulesText->setText(rulesString.c_str(), rulesString.size());
     
     // angle
     _angleRealSpinner->setValue(_lsystem->getAngle());
     
-    // iterations
-    _iterationsSpinner->setValue(_lsystem->getNumIterations());
+    // depth
+    _depthSpinner->setValue(_lsystem->getDepth());
 }
 
 
@@ -144,7 +186,7 @@ void GUI::create()
 
 
 /**
- * Called by the system when the "generate"-button is pressed
+ * 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
@@ -156,47 +198,42 @@ long GUI::onGenerateButtonPressed(FXObject *sender, FXSelector selector, void *d
     _lsystem->clear();
     
     
-    // load data from widgets into L-system
+    // get user input form widgets
     
     // axiom
-    _lsystem->setAxiom(_axiomTextField->getText().text());
+    Rule axiom("axiom", _axiomTextField->getText().text(), 1.0);
+    _lsystem->setAxiom(axiom);
     
     // rules
     string ruleSet = _rulesText->getText().text();
-     string currentRule;
-    string ruleName;
-    bool newRule = true;
+    string currentRule;
     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)
+        if (ruleSet[i] != '\n')
         {
-            // part of current rule
+            // rule component
             currentRule += ruleSet[i];
+            
+            if (i == ruleSet.size() - 1)
+            {
+                // last char in whole rule string
+                _lsystem->setRule(Rule(currentRule));
+                currentRule.clear();
+            }
         }
-        
-        if (ruleSet[i] == '\n' || i == ruleSet.size() - 1)
+        else
         {
-            // end of rule
-            _lsystem->setRule(ruleName, currentRule);
-            ruleName.clear();
+            // last char in current rule
+            _lsystem->setRule(Rule(currentRule));
             currentRule.clear();
-            newRule = true;
         }
     }
 
     // angle
     _lsystem->setAngle(_angleRealSpinner->getValue());
     
-    // iterations
-    _lsystem->setNumIterations(_iterationsSpinner->getValue());
+    // depth
+    _lsystem->setDepth(_depthSpinner->getValue());
     
     // diameter
     _lsystem->setDiameter(_diameterRealSpinner->getValue());
@@ -209,3 +246,17 @@ long GUI::onGenerateButtonPressed(FXObject *sender, FXSelector selector, void *d
     _lsystem->generate();
     _renderingSurface->draw();
 }
+
+
+
+/**
+ * Called by the system when the "Help" button is pressed
+ * @param sender the sender object
+ * @param selector message type and id
+ * @param data event related data
+ * @return 
+ */
+long GUI::onHelpButtonPressed(FXObject *sender, FXSelector selector, void *data)
+{
+    _helpMessageBox->show(PLACEMENT_OWNER);
+}