11#include " application/MainWindow.h"
22
3+ #include < QFormLayout>
4+ #include < QGroupBox>
5+ #include < QHBoxLayout>
36#include < QLabel>
47#include < QPushButton>
58#include < QTimer>
@@ -28,6 +31,19 @@ QString stateToString(safecrowd::engine::EngineState state) {
2831 return " Unknown" ;
2932}
3033
34+ QLabel* createBodyLabel (const QString& text, QWidget* parent) {
35+ auto * label = new QLabel (text, parent);
36+ label->setWordWrap (true );
37+ label->setTextFormat (Qt::RichText);
38+ return label;
39+ }
40+
41+ QLabel* createValueLabel (QWidget* parent) {
42+ auto * label = new QLabel (" -" , parent);
43+ label->setTextInteractionFlags (Qt::TextSelectableByMouse);
44+ return label;
45+ }
46+
3147} // namespace
3248
3349namespace safecrowd ::application {
@@ -36,64 +52,159 @@ MainWindow::MainWindow(safecrowd::domain::SafeCrowdDomain& domain, QWidget* pare
3652 : QMainWindow(parent),
3753 domain_ (domain) {
3854 auto * centralWidget = new QWidget (this );
39- auto * layout = new QVBoxLayout (centralWidget);
40- statusLabel_ = new QLabel (this );
41-
42- auto * startButton = new QPushButton (" Start" , this );
43- auto * pauseButton = new QPushButton (" Pause" , this );
44- auto * stopButton = new QPushButton (" Stop" , this );
45-
46- layout->addWidget (statusLabel_);
47- layout->addWidget (startButton);
48- layout->addWidget (pauseButton);
49- layout->addWidget (stopButton);
55+ auto * rootLayout = new QHBoxLayout (centralWidget);
56+ rootLayout->setContentsMargins (18 , 18 , 18 , 18 );
57+ rootLayout->setSpacing (16 );
58+
59+ auto * workspaceGroup = new QGroupBox (" Project Workspace" , centralWidget);
60+ auto * workspaceLayout = new QVBoxLayout (workspaceGroup);
61+ workspaceLayout->setSpacing (12 );
62+ workspaceLayout->addWidget (createBodyLabel (
63+ " <b>1. Import & Validate</b><br/>"
64+ " DXF and facility topology import, review, and manual correction will surface here." ,
65+ workspaceGroup));
66+ workspaceLayout->addWidget (createBodyLabel (
67+ " <b>2. Scenario Editor</b><br/>"
68+ " Baseline and variation authoring stay in the same workspace but outside the run panel." ,
69+ workspaceGroup));
70+ workspaceLayout->addWidget (createBodyLabel (
71+ " <b>3. Results & Recommendation</b><br/>"
72+ " Run summaries, comparison, export, and recommendation remain downstream of persisted artifacts." ,
73+ workspaceGroup));
74+ workspaceLayout->addStretch ();
75+
76+ auto * workspaceColumn = new QVBoxLayout ();
77+ workspaceColumn->setSpacing (16 );
78+ workspaceColumn->addWidget (createBodyLabel (
79+ " <b>SafeCrowd Workspace Prototype</b><br/>"
80+ " This shell now mirrors the documented workflow. Only playback control is wired live today; "
81+ " the rest of the workspace is reserved so future application features land in explicit sections." ,
82+ centralWidget));
83+
84+ auto * runControlGroup = new QGroupBox (" Run Control Panel" , centralWidget);
85+ auto * runControlLayout = new QVBoxLayout (runControlGroup);
86+ runControlLayout->setSpacing (10 );
87+ runControlLayout->addWidget (createBodyLabel (
88+ " Playback control remains the active path into the current runtime prototype." ,
89+ runControlGroup));
90+
91+ auto * buttonLayout = new QHBoxLayout ();
92+ startButton_ = new QPushButton (" Start Playback" , runControlGroup);
93+ pauseButton_ = new QPushButton (" Pause Playback" , runControlGroup);
94+ stopButton_ = new QPushButton (" Stop Playback" , runControlGroup);
95+ buttonLayout->addWidget (startButton_);
96+ buttonLayout->addWidget (pauseButton_);
97+ buttonLayout->addWidget (stopButton_);
98+ runControlLayout->addLayout (buttonLayout);
99+ runControlLayout->addWidget (createBodyLabel (
100+ " <b>Planned next:</b> execution readiness checks, repeat runs, and variation selection." ,
101+ runControlGroup));
102+
103+ auto * runtimeStatusGroup = new QGroupBox (" Runtime Status" , centralWidget);
104+ auto * runtimeStatusLayout = new QFormLayout (runtimeStatusGroup);
105+ runtimeStatusLayout->setLabelAlignment (Qt::AlignLeft);
106+ runtimeStatusLayout->setFormAlignment (Qt::AlignTop | Qt::AlignLeft);
107+
108+ runtimeStateValue_ = createValueLabel (runtimeStatusGroup);
109+ frameValue_ = createValueLabel (runtimeStatusGroup);
110+ fixedStepValue_ = createValueLabel (runtimeStatusGroup);
111+ alphaValue_ = createValueLabel (runtimeStatusGroup);
112+ runValue_ = createValueLabel (runtimeStatusGroup);
113+ variationValue_ = createValueLabel (runtimeStatusGroup);
114+
115+ runtimeStatusLayout->addRow (" Engine state" , runtimeStateValue_);
116+ runtimeStatusLayout->addRow (" Rendered frames" , frameValue_);
117+ runtimeStatusLayout->addRow (" Fixed steps" , fixedStepValue_);
118+ runtimeStatusLayout->addRow (" Interpolation alpha" , alphaValue_);
119+ runtimeStatusLayout->addRow (" Current run" , runValue_);
120+ runtimeStatusLayout->addRow (" Variation" , variationValue_);
121+
122+ auto * resultsGroup = new QGroupBox (" Results Pipeline" , centralWidget);
123+ auto * resultsLayout = new QVBoxLayout (resultsGroup);
124+ resultsLayout->setSpacing (12 );
125+ resultsLayout->addWidget (createBodyLabel (
126+ " <b>Run Results Panel</b><br/>"
127+ " Single-run and variation summaries will read persisted artifacts first." ,
128+ resultsGroup));
129+ resultsLayout->addWidget (createBodyLabel (
130+ " <b>Comparison View</b><br/>"
131+ " Baseline versus alternative comparisons stay separate from live runtime state." ,
132+ resultsGroup));
133+ resultsLayout->addWidget (createBodyLabel (
134+ " <b>Export & Recommendation</b><br/>"
135+ " Artifact export and recommendation evidence remain downstream consumers of saved results." ,
136+ resultsGroup));
137+
138+ workspaceColumn->addWidget (runControlGroup);
139+ workspaceColumn->addWidget (runtimeStatusGroup);
140+ workspaceColumn->addWidget (resultsGroup);
141+ workspaceColumn->addStretch ();
142+
143+ rootLayout->addWidget (workspaceGroup, 5 );
144+ rootLayout->addLayout (workspaceColumn, 7 );
50145
51146 tickTimer_ = new QTimer (this );
52147 tickTimer_->setInterval (16 );
53148
54- connect (startButton , &QPushButton::clicked, this , [this ]() { startSimulation (); });
55- connect (pauseButton , &QPushButton::clicked, this , [this ]() { pauseSimulation (); });
56- connect (stopButton , &QPushButton::clicked, this , [this ]() { stopSimulation (); });
149+ connect (startButton_ , &QPushButton::clicked, this , [this ]() { startSimulation (); });
150+ connect (pauseButton_ , &QPushButton::clicked, this , [this ]() { pauseSimulation (); });
151+ connect (stopButton_ , &QPushButton::clicked, this , [this ]() { stopSimulation (); });
57152 connect (tickTimer_, &QTimer::timeout, this , [this ]() { tickSimulation (); });
58153
59154 setCentralWidget (centralWidget);
60- setWindowTitle (" SafeCrowd" );
61- resize (420 , 220 );
155+ setWindowTitle (" SafeCrowd Workspace " );
156+ resize (980 , 560 );
62157
63- refreshStatusLabel ();
158+ refreshRuntimePanel ();
64159}
65160
66161void MainWindow::startSimulation () {
67162 domain_.start ();
68163 tickTimer_->start ();
69- refreshStatusLabel ();
164+ refreshRuntimePanel ();
70165}
71166
72167void MainWindow::pauseSimulation () {
73168 domain_.pause ();
74169 tickTimer_->stop ();
75- refreshStatusLabel ();
170+ refreshRuntimePanel ();
76171}
77172
78173void MainWindow::stopSimulation () {
79174 domain_.stop ();
80175 tickTimer_->stop ();
81- refreshStatusLabel ();
176+ refreshRuntimePanel ();
82177}
83178
84179void MainWindow::tickSimulation () {
85180 domain_.update (1.0 / 60.0 );
86- refreshStatusLabel ();
181+ refreshRuntimePanel ();
87182}
88183
89- void MainWindow::refreshStatusLabel () {
184+ void MainWindow::refreshRuntimePanel () {
185+ using safecrowd::engine::EngineState;
186+
90187 const auto summary = domain_.summary ();
91- statusLabel_->setText (
92- QString (" State: %1\n Frames: %2\n Fixed Steps: %3\n Alpha: %4" )
93- .arg (stateToString (summary.state ))
94- .arg (summary.frameIndex )
95- .arg (summary.fixedStepIndex )
96- .arg (summary.alpha , 0 , ' f' , 2 ));
188+ runtimeStateValue_->setText (stateToString (summary.state ));
189+ frameValue_->setText (QString::number (summary.frameIndex ));
190+ fixedStepValue_->setText (QString::number (summary.fixedStepIndex ));
191+ alphaValue_->setText (QString::number (summary.alpha , ' f' , 2 ));
192+
193+ if (summary.state == EngineState::Running || summary.state == EngineState::Paused) {
194+ runValue_->setText (" Prototype run 1 / 1" );
195+ } else if (summary.frameIndex > 0 || summary.fixedStepIndex > 0 ) {
196+ runValue_->setText (" Last prototype run retained" );
197+ } else {
198+ runValue_->setText (" Ready for first run" );
199+ }
200+
201+ variationValue_->setText (" Baseline placeholder (domain wiring pending)" );
202+
203+ const bool isRunning = summary.state == EngineState::Running;
204+ const bool isPaused = summary.state == EngineState::Paused;
205+ startButton_->setEnabled (!isRunning);
206+ pauseButton_->setEnabled (isRunning);
207+ stopButton_->setEnabled (isRunning || isPaused || summary.frameIndex > 0 || summary.fixedStepIndex > 0 );
97208}
98209
99210} // namespace safecrowd::application
0 commit comments