d068cd5eacc177e4d834e1402f97beb042de30df
[lsystem3d.git] / src / gui.cpp
1 // Copyright (C) 2006 Erik Dahlberg
2 //
3 // This file is part of LSystem3d.
4 //
5 // LSystem3D is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // LSystem3D is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with LSystem3D; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
22 #include <map>
23 #include <string>
24
25 #include "fx.h"
26
27 #include "gui.h"
28 #include "lindenmayersystem.h"
29 #include "lsystemparameters.h"
30 #include "renderingsurface.h"
31
32
33
34 // message map
35 FXDEFMAP(GUI) GUIMap[] =
36 {
37 FXMAPFUNC(SEL_COMMAND, GUI::ID_GENERATE, GUI::onGenerateButtonPressed)
38 };
39
40 // macro to set up class implementation
41 FXIMPLEMENT(GUI, FXMainWindow, GUIMap, ARRAYNUMBER(GUIMap))
42
43
44
45 /**
46 * Constructor
47 * @param application the FOX application object
48 * @param renderingSurface the rendering surface
49 * @param lsystem the Lindenmayer-system
50 */
51 GUI::GUI(FXApp *application, RenderingSurface *renderingSurface, LindenmayerSystem *lsystem) : FXMainWindow(application, "LSystem3D" , NULL, NULL, DECOR_ALL, 920, 100, 0, 0)
52 {
53 _lsystem = lsystem;
54 _renderingSurface = renderingSurface;
55
56
57 // create the widgets
58
59 // the main frame
60 FXVerticalFrame *mainFrame = new FXVerticalFrame(this, LAYOUT_FILL_X);
61
62 // axiom
63 FXHorizontalFrame *axiomFrame = new FXHorizontalFrame(mainFrame, LAYOUT_FILL_X);
64 new FXLabel(axiomFrame, "Axiom:");
65 _axiomTextField = new FXTextField(axiomFrame, 10, NULL, 0, LAYOUT_FILL_X);
66
67 // rules
68 FXHorizontalFrame *rulesFrame = new FXHorizontalFrame(mainFrame, LAYOUT_FILL_X);
69 new FXLabel(rulesFrame, "Rules:");
70 _rulesText = new FXText(rulesFrame, NULL, 0, LAYOUT_FILL_X);
71 _rulesText->setVisibleColumns(30);
72 _rulesText->setVisibleRows(10);
73
74 // angle
75 FXHorizontalFrame *angleFrame = new FXHorizontalFrame(mainFrame);
76 new FXLabel(angleFrame, "Angle:");
77 _angleRealSpinner = new FXRealSpinner(angleFrame, 5);
78
79 // iterations
80 FXHorizontalFrame *iterationsFrame = new FXHorizontalFrame(mainFrame);
81 new FXLabel(iterationsFrame, "Iterations:");
82 _iterationsSpinner = new FXSpinner(iterationsFrame, 5);
83
84 // diameter
85 FXHorizontalFrame *diameterFrame = new FXHorizontalFrame(mainFrame);
86 new FXLabel(diameterFrame, "Diameter:");
87 _diameterRealSpinner = new FXRealSpinner(diameterFrame, 5);
88 _diameterRealSpinner->setValue(0.2);
89 _diameterRealSpinner->setIncrement(0.1);
90
91 // diameter factor
92 new FXLabel(diameterFrame, "Factor:");
93 _diameterFactorRealSpinner = new FXRealSpinner(diameterFrame, 5);
94 _diameterFactorRealSpinner->setValue(0.8);
95 _diameterFactorRealSpinner->setIncrement(0.1);
96
97 // separator
98 new FXHorizontalSeparator(mainFrame, SEPARATOR_RIDGE | LAYOUT_FILL_X);
99
100 // generate
101 new FXButton(mainFrame, "&Generate", NULL, this, GUI::ID_GENERATE);
102
103
104
105 // load L-system parameters from file and sync with GUI
106
107 _lsystemParameters.load(_lsystem, "lsystem.xml");
108
109 // axiom
110 _axiomTextField->setText(_lsystem->getAxiom().c_str());
111
112 // rules
113 map<string,string> allRulesSrc = _lsystem->getRules();
114 string allRulesDst;
115 for (map<string,string>::iterator currentRule = allRulesSrc.begin();
116 currentRule != allRulesSrc.end();
117 currentRule++)
118 {
119 // one rule
120 string rule = currentRule->first + "=" + currentRule->second + '\n';
121 allRulesDst += rule.c_str();
122 }
123 _rulesText->setText(allRulesDst.c_str(), allRulesDst.size());
124
125 // angle
126 _angleRealSpinner->setValue(_lsystem->getAngle());
127
128 // iterations
129 _iterationsSpinner->setValue(_lsystem->getNumIterations());
130 }
131
132
133
134 /**
135 * Create and initialize the window
136 */
137 void GUI::create()
138 {
139 // create the window and make it appear
140 FXMainWindow::create();
141 show();
142 }
143
144
145
146 /**
147 * Called by the system when the "generate"-button is pressed
148 * @param sender the sender object
149 * @param selector message type and id
150 * @param data event related data
151 * @return
152 */
153 long GUI::onGenerateButtonPressed(FXObject *sender, FXSelector selector, void *data)
154 {
155 // clear L-system
156 _lsystem->clear();
157
158
159 // load data from widgets into L-system
160
161 // axiom
162 _lsystem->setAxiom(_axiomTextField->getText().text());
163
164 // rules
165 string ruleSet = _rulesText->getText().text();
166 string currentRule;
167 string ruleName;
168 bool newRule = true;
169 for (int i = 0; i < ruleSet.size(); i++)
170 {
171 if (newRule)
172 {
173 // get rule name
174 ruleName = ruleSet[i];
175 i += 2;
176 newRule = false;
177 }
178
179 if (ruleSet[i] != '\n' || i == ruleSet.size() - 1)
180 {
181 // part of current rule
182 currentRule += ruleSet[i];
183 }
184
185 if (ruleSet[i] == '\n' || i == ruleSet.size() - 1)
186 {
187 // end of rule
188 _lsystem->setRule(ruleName, currentRule);
189 ruleName.clear();
190 currentRule.clear();
191 newRule = true;
192 }
193 }
194
195 // angle
196 _lsystem->setAngle(_angleRealSpinner->getValue());
197
198 // iterations
199 _lsystem->setNumIterations(_iterationsSpinner->getValue());
200
201 // diameter
202 _lsystem->setDiameter(_diameterRealSpinner->getValue());
203
204 // diameter factor
205 _lsystem->setDiameterFactor(_diameterFactorRealSpinner->getValue());
206
207
208 // generate and render L-system to screen
209 _lsystem->generate();
210 _renderingSurface->draw();
211 }