PeriDyno 1.2.1
Loading...
Searching...
No Matches
WMainWindow.cpp
Go to the documentation of this file.
1#include "WMainWindow.h"
2
4#include "NodeFactory.h"
5#include "WLogWidget.h"
6
7
9#include "WSampleWidget.h"
10#include "WSaveWidget.h"
11#include "WSceneDataModel.h"
12#include "WSimulationCanvas.h"
13
14#include <fstream>
15#include <SceneGraph.h>
16
17#include <Wt/WApplication.h>
18#include <Wt/WEnvironment.h>
19#include <Wt/WHBoxLayout.h>
20#include <Wt/WLineEdit.h>
21#include <Wt/WLogger.h>
22#include <Wt/WNavigationBar.h>
23#include <Wt/WPushButton.h>
24#include <Wt/WSuggestionPopup.h>
25#include <Wt/WTableView.h>
26#include <Wt/WVBoxLayout.h>
27
28#define WIDTH_SCALE 0.4
29#define HEIGHT_SCALE 0.75
30
31WMainWindow::WMainWindow() : WContainerWidget()
32{
33 // disable page margin...
34 setMargin(0);
35 auto layout = this->setLayout(std::make_unique<Wt::WBorderLayout>());
36 layout->setContentsMargins(0, 0, 0, 0);
37
38 viewportHeight = Wt::WApplication::instance()->environment().screenHeight();
39 viewportWidth = Wt::WApplication::instance()->environment().screenWidth();
40
41 // init
42 initNavigationBar(layout);
43 initCenterContainer(layout);
44
45 // right panel
46 rightWidget = layout->addWidget(std::make_unique<Wt::WContainerWidget>(), Wt::LayoutPosition::East);
47
48 // create data model
49 mNodeDataModel = std::make_shared<WNodeDataModel>();
50 mModuleDataModel = std::make_shared<WModuleDataModel>();
51 mParameterDataNode = std::make_shared<WParameterDataNode>();
52
53 mParameterDataNode->changeValue().connect(this, &WMainWindow::updateCanvas);
54 mParameterDataNode->changeValue().connect(this, &WMainWindow::updateNodeGraphics);
55}
56
58{
59 Wt::log("warning") << "stop WMainWindows";
60}
61
62void WMainWindow::setScene(std::shared_ptr<dyno::SceneGraph> scene)
63{
64 // try to stop the simulation
65 controlContainer->stop();
66
67 // setup scene graph
68 mScene = scene;
69 mSceneCanvas->setScene(mScene);
70 mNodeDataModel->setScene(mScene);
71 mModuleDataModel->setNode(NULL);
72 controlContainer->setSceneGraph(mScene);
73}
74
75std::shared_ptr<dyno::SceneGraph> WMainWindow::getScene()
76{
77 return mScene;
78}
79
84
86{
87 if (mScene)
88 {
89 mSceneCanvas->update();
90 }
91 Wt::log("info") << "updateCanvas!!!";
92 Wt::log("info") << mScene->getFrameNumber();
93}
94
96{
98 {
99 mNodeFlowWidget->update();
100 }
101 Wt::log("info") << "updateNodeGraphics!!!";
102}
103
104void WMainWindow::onKeyWentDown(const Wt::WKeyEvent& event)
105{
106 if (event.key() == Wt::Key::Delete || event.key() == Wt::Key::Backspace)
107 {
108 mNodeFlowWidget->onKeyWentDown();
109 }
110}
111
112void WMainWindow::initNavigationBar(Wt::WBorderLayout* layout)
113{
114 //create a navigation bar
115 auto naviBar = layout->addWidget(std::make_unique<Wt::WNavigationBar>(), Wt::LayoutPosition::North);
116 naviBar->addStyleClass("main-nav");
117 naviBar->setResponsive(true);
118 naviBar->setTitle("PeriDyno", "https://github.com/peridyno/peridyno");
119 naviBar->setMargin(0);
120}
121
122void WMainWindow::initCenterContainer(Wt::WBorderLayout* layout)
123{
124 // create center
125 auto centerContainer = layout->addWidget(std::make_unique<Wt::WContainerWidget>(), Wt::LayoutPosition::Center);
126 centerContainer->setMargin(0);
127
128 auto centerVbox = centerContainer->setLayout(std::make_unique<Wt::WVBoxLayout>());
129 centerVbox->setContentsMargins(0, 0, 0, 0);
130
131 // add scene canvas
132 mSceneCanvas = centerVbox->addWidget(std::make_unique<WSimulationCanvas>());
133
134 // add scene control
135 controlContainer = centerVbox->addWidget(std::make_unique<WSimulationControl>());
136 controlContainer->setSceneCanvas(mSceneCanvas);
137}
138
139void WMainWindow::initRightPanel(Wt::WContainerWidget* parent)
140{
141 // vertical layout
142 auto layout = rightWidget->setLayout(std::make_unique<Wt::WVBoxLayout>());
143 layout->setContentsMargins(0, 0, 0, 0);
144 parent->setMargin(0);
145
146 auto widget0 = layout->addWidget(std::make_unique<Wt::WContainerWidget>());
147 widget0->resize("100%", "100%");
148 widget0->setMargin(0);
149 tab = widget0->addNew<Wt::WTabWidget>();
150 tab->resize("100%", "100%");
151 tab->addTab(initNodeGraphics(), "NodeGraphics", Wt::ContentLoading::Eager);
152 tab->addTab(initModuleGraphics(), "ModuleGraphics", Wt::ContentLoading::Eager);
153 tab->addTab(initPython(), "Python", Wt::ContentLoading::Lazy);
154 tab->addTab(initSample(), "Sample", Wt::ContentLoading::Lazy);
155 tab->addTab(initSave(), "Save", Wt::ContentLoading::Lazy);
156 tab->addTab(initLog(), "Log", Wt::ContentLoading::Lazy);
157}
158
159void WMainWindow::initAddNodePanel(Wt::WPanel* panel)
160{
161 auto widget3 = panel->setCentralWidget(std::make_unique<Wt::WContainerWidget>());
162 auto layout3 = widget3->setLayout(std::make_unique<Wt::WHBoxLayout>());
163 layout3->setContentsMargins(0, 0, 0, 0);
164
165 Wt::WSuggestionPopup::Options nodeOptions;
166 nodeOptions.highlightBeginTag = "<span class=\"highlight\">";
167 nodeOptions.highlightEndTag = "</span>";
168
169 Wt::WSuggestionPopup* sp = layout3->addChild(std::make_unique<Wt::WSuggestionPopup>(
170 Wt::WSuggestionPopup::generateMatcherJS(nodeOptions),
171 Wt::WSuggestionPopup::generateReplacerJS(nodeOptions)
172 ));
173
174 auto& pages = dyno::NodeFactory::instance()->nodePages();
175 for (auto iPage = pages.begin(); iPage != pages.end(); iPage++)
176 {
177 auto& groups = iPage->second->groups();
178 {
179 for (auto iGroup = groups.begin(); iGroup != groups.end(); iGroup++)
180 {
181 auto& actions = iGroup->second->actions();
182 for (auto action : actions)
183 {
184 sp->addSuggestion(action->caption());
185 }
186 }
187 }
188 }
189
190 auto nodeMap = dyno::Object::getClassMap();
191 for (auto it = nodeMap->begin(); it != nodeMap->end(); ++it)
192 {
193 auto node_obj = dyno::Object::createObject(it->second->m_className);
194 std::shared_ptr<dyno::Node> new_node(dynamic_cast<dyno::Node*>(node_obj));
195 if (new_node == nullptr)
196 {
197 continue;
198 }
199 else
200 {
201 sp->addSuggestion(it->second->m_className);
202 }
203 }
204 auto name = layout3->addWidget(std::make_unique<Wt::WLineEdit>());
205 name->setPlaceholderText("node name");
206
207 sp->forEdit(name);
208
209 auto addNodeButton = layout3->addWidget(std::make_unique<Wt::WPushButton>("Add"));
210
211 addNodeButton->clicked().connect([=] {
212 bool flag = true;
213
214 for (auto iPage = pages.begin(); iPage != pages.end(); iPage++)
215 {
216 auto& groups = iPage->second->groups();
217 {
218 for (auto iGroup = groups.begin(); iGroup != groups.end(); iGroup++)
219 {
220 auto& actions = iGroup->second->actions();
221 for (auto action : actions)
222 {
223 if (action->caption() == name->text().toUTF8())
224 {
225 auto new_node = mScene->addNode(action->action()());
226 new_node->setBlockCoord(Initial_x, Initial_y);
227 Initial_x += 20;
228 Initial_y += 20;
229 name->setText("");
230 mNodeFlowWidget->updateAll();
231 mNodeDataModel->setScene(mScene);
232 flag = false;
233 }
234 }
235 }
236 }
237 }
238
239 if (flag)
240 {
241 auto node_obj = dyno::Object::createObject(name->text().toUTF8());
242 std::shared_ptr<dyno::Node> new_node(dynamic_cast<dyno::Node*>(node_obj));
243 if (new_node != nullptr)
244 {
245 mScene->addNode(new_node);
246 new_node->setBlockCoord(Initial_x, Initial_y);
247 Initial_x += 10;
248 Initial_y += 10;
249 std::cout << Initial_x << std::endl;
250 std::cout << "!!!!!!!!!!!" << std::endl;
251 mNodeFlowWidget->updateAll();
252 mNodeDataModel->setScene(mScene);
253 name->setText("");
254 }
255
256 }
257 });
258
259 auto reorderNodeButton = layout3->addWidget(std::make_unique<Wt::WPushButton>("Reorder"));
260
261 reorderNodeButton->clicked().connect([=] {
262 mNodeFlowWidget->reorderNode();
263 });
264}
265
266std::unique_ptr<Wt::WWidget> WMainWindow::initNodeGraphics()
267{
268 nodeGraphicsWidget = std::make_unique<WNodeGraphics>();
270 if (mScene)
271 {
272 auto painteContainer = nodeGraphicsWidget->nodePanel->setCentralWidget(std::make_unique<Wt::WContainerWidget>());
273 painteContainer->setMargin(0);
274 mNodeFlowWidget = painteContainer->addWidget(std::make_unique<WtNodeFlowWidget>(mScene));
276 }
277
278 // Parameter list
279 auto parameterWidget = nodeGraphicsWidget->layout->addWidget(std::make_unique<Wt::WContainerWidget>());;
280
281
282 //action for selection change
283 mNodeFlowWidget->selectNodeSignal().connect([=](int selectNum)
284 {
285 if (selectNum > 0)
286 {
287 for (auto it = mScene->begin(); it != mScene->end(); it++)
288 {
289 auto m = it.get();
290 if (m->objectId() == selectNum)
291 {
292 mModuleDataModel->setNode(m);
293 mParameterDataNode->setNode(m);
294 mParameterDataNode->createParameterPanel(parameterWidget);
295 mSceneCanvas->selectNode(m);
296 mModuleFlowWidget->setNode(m);
297 mSceneCanvas->update();
298
299 }
300 }
301 }
302 });
303
304 mNodeFlowWidget->updateCanvas().connect([=]()
305 {
306 this->updateCanvas();
307 });
308
309 if (mSceneCanvas)
310 {
311 mSceneCanvas->selectNodeSignal().connect([=](std::shared_ptr<dyno::Node> node)
312 {
313 if (node)
314 {
315 mModuleDataModel->setNode(node);
316 mParameterDataNode->setNode(node);
317 mParameterDataNode->createParameterPanel(parameterWidget);
318
319 mNodeFlowWidget->setSelectNode(node);
320 }
321 });
322
323
324 }
325
326 return std::move(nodeGraphicsWidget);
327}
328
329std::unique_ptr<Wt::WWidget> WMainWindow::initModuleGraphics()
330{
331 moduleGraphicsWidget = std::make_unique<WModuleGraphics>();
333 if (mScene)
334 {
335 auto painteContainer = moduleGraphicsWidget->modulePanel->setCentralWidget(std::make_unique<Wt::WContainerWidget>());
336 painteContainer->setMargin(0);
337 mModuleFlowWidget = painteContainer->addWidget(std::make_unique<WtModuleFlowWidget>(mScene));
339 }
340
341 // Parameter list
342 auto parameterWidget = moduleGraphicsWidget->layout->addWidget(std::make_unique<Wt::WContainerWidget>());;
343
344
345 return std::move(moduleGraphicsWidget);
346
347
348 //auto rootWidget = std::make_unique<Wt::WContainerWidget>();
349 //auto layout = rootWidget->setLayout(std::make_unique<Wt::WVBoxLayout>());
350 //layout->setContentsMargins(0, 0, 0, 0);
351 //rootWidget->setMargin(0);
352 //rootWidget->setWidth(viewportWidth * WIDTH_SCALE);
353
355 //auto panel2 = layout->addWidget(std::make_unique<Wt::WPanel>());
356 //panel2->setTitle("Module List");
357 //panel2->setCollapsible(true);
358 //panel2->setStyleClass("scrollable-content");
359 //auto tableView = panel2->setCentralWidget(std::make_unique<Wt::WTableView>());
360
361 //tableView->setSortingEnabled(false);
362 //tableView->setSelectionMode(Wt::SelectionMode::Single);
363 //tableView->setEditTriggers(Wt::EditTrigger::None);
364 //tableView->setModel(mModuleDataModel);
365
367 //auto panel3 = layout->addWidget(std::make_unique<Wt::WPanel>());
368 //panel3->setTitle("Control Variable");
369 //panel3->setCollapsible(true);
370 //panel3->setStyleClass("scrollable-content");
371
372 //tableView->clicked().connect([=](const Wt::WModelIndex& idx, const Wt::WMouseEvent& evt)
373 // {
374 // auto module = mModuleDataModel->getModule(idx);
375 // mParameterDataNode->setModule(module);
376 // mParameterDataNode->createParameterPanelModule(panel3);
377 // });
378
379 //tableView->doubleClicked().connect([=](const Wt::WModelIndex& idx, const Wt::WMouseEvent& evt)
380 // {
381 // auto mod = mModuleDataModel->getModule(idx);
382 // if (mod->getModuleType() == "VisualModule")
383 // {
384 // Wt::log("info") << mod->getName();
385 // }
386 // });
387
388 //return rootWidget;
389}
390
391std::unique_ptr<Wt::WWidget> WMainWindow::initPython()
392{
394
395 pythonWidget->updateSceneGraph().connect([=](std::shared_ptr<dyno::SceneGraph> scene) {
396 if (scene)
397 {
398 setScene(scene);
399
400 tab->removeTab(tab->widget(0));
401 tab->insertTab(0, initNodeGraphics(), "NodeGraphics", Wt::ContentLoading::Lazy);
402 }
403 });
404
405 return std::unique_ptr<WPythonWidget>(pythonWidget);
406}
407
408std::unique_ptr<Wt::WWidget> WMainWindow::initSample()
409{
410 int maxColumns = viewportWidth * WIDTH_SCALE / 200;
411
412 auto sampleWidget = new WSampleWidget(maxColumns);
413 sampleWidget->setStyleClass("scrollable-content-sample");
414 sampleWidget->setHeight(viewportHeight * HEIGHT_SCALE);
415 sampleWidget->setWidth(viewportWidth * WIDTH_SCALE);
416
417 sampleWidget->clicked().connect([=](Sample* sample)
418 {
419 if (sample != NULL)
420 {
421 //pythonItem->select();
422 std::string path = sample->source();
423 std::ifstream ifs(path);
424 if (ifs.is_open())
425 {
426 std::string content((std::istreambuf_iterator<char>(ifs)),
427 (std::istreambuf_iterator<char>()));
428 pythonWidget->setText(content);
429 pythonWidget->execute(content);
430 //menu->contentsStack()->setCurrentWidget(0);
431 }
432 else
433 {
434 std::string content = "Error: Not Find The Python File";
435 pythonWidget->setText(content);
436 }
437 }
438 });
439
440 return std::unique_ptr<WSampleWidget>(sampleWidget);
441}
442
443std::unique_ptr<Wt::WWidget> WMainWindow::initSave()
444{
445 auto saveWidget = std::make_unique<WSaveWidget>(this, viewportWidth * WIDTH_SCALE / 2);
446 saveWidget->setMargin(10);
447
448 Wt::WApplication::instance()->styleSheet().addRule(
449 ".save-middle",
450 "justify-items: anchor-center;"
451 );
452
453 saveWidget->setStyleClass("save-middle");
454
455 return saveWidget;
456}
457
458std::unique_ptr<Wt::WWidget> WMainWindow::initLog()
459{
460 auto logWidget = new WLogWidget(this);
462
463 auto logMessage = new WLogMessage();
464
465 logMessage->updateText().connect([=](std::string message)
466 {
467 std::ostringstream oss;
468 oss << mScene;
469 std::string filename = oss.str() + ".txt";
470 std::ofstream fileStream(filename, std::ios::out | std::ios::trunc);
471 if (fileStream.is_open()) {
472 fileStream << message;
473 fileStream.close();
474 }
475 else {
476 std::cerr << "Unable to open file for writing." << std::endl;
477 }
478 });
479
480 return std::unique_ptr<WLogWidget>(logWidget);
481}
#define HEIGHT_SCALE
#define WIDTH_SCALE
virtual std::string source() const =0
std::unique_ptr< Wt::WWidget > initPython()
WSimulationCanvas * mSceneCanvas
Definition WMainWindow.h:74
WtModuleFlowWidget * mModuleFlowWidget
Definition WMainWindow.h:77
std::unique_ptr< WModuleGraphics > moduleGraphicsWidget
Definition WMainWindow.h:80
std::shared_ptr< WNodeDataModel > mNodeDataModel
Definition WMainWindow.h:49
Wt::WContainerWidget * rightWidget
Definition WMainWindow.h:82
void onKeyWentDown(const Wt::WKeyEvent &event)
Wt::WTabWidget * tab
Definition WMainWindow.h:84
void updateCanvas()
int viewportHeight
Definition WMainWindow.h:68
std::unique_ptr< WNodeGraphics > nodeGraphicsWidget
Definition WMainWindow.h:79
std::unique_ptr< Wt::WWidget > initLog()
std::unique_ptr< Wt::WWidget > initSample()
std::shared_ptr< dyno::SceneGraph > mScene
Definition WMainWindow.h:71
void initCenterContainer(Wt::WBorderLayout *)
std::unique_ptr< Wt::WWidget > initNodeGraphics()
std::unique_ptr< Wt::WWidget > initModuleGraphics()
void initAddNodePanel(Wt::WPanel *parent)
std::unique_ptr< Wt::WWidget > initSave()
std::shared_ptr< WParameterDataNode > mParameterDataNode
Definition WMainWindow.h:51
void createRightPanel()
WSimulationControl * controlContainer
Definition WMainWindow.h:75
WtNodeFlowWidget * mNodeFlowWidget
Definition WMainWindow.h:76
void initNavigationBar(Wt::WBorderLayout *)
std::shared_ptr< dyno::SceneGraph > getScene()
void initRightPanel(Wt::WContainerWidget *)
WPythonWidget * pythonWidget
Definition WMainWindow.h:78
void setScene(std::shared_ptr< dyno::SceneGraph > scene)
std::shared_ptr< WModuleDataModel > mModuleDataModel
Definition WMainWindow.h:50
void updateNodeGraphics()
int viewportWidth
Definition WMainWindow.h:69
static NodeFactory * instance()
std::map< std::string, std::shared_ptr< NodePage > > & nodePages()
static std::map< std::string, ClassInfo * > * getClassMap()
Definition Object.cpp:42
static Object * createObject(std::string name)
Definition Object.cpp:33