Loading...
Searching...
No Matches
ScenarioCreationState.hpp
1#pragma once
2#include <Explorer/DocumentPlugin/DeviceDocumentPlugin.hpp>
3#include <Explorer/Explorer/DeviceExplorerModel.hpp>
4
5#include <Scenario/Commands/Scenario/Creations/CreateInterval.hpp>
6#include <Scenario/Commands/Scenario/Creations/CreateInterval_State.hpp>
7#include <Scenario/Commands/Scenario/Creations/CreateInterval_State_Event.hpp>
8#include <Scenario/Commands/Scenario/Creations/CreateInterval_State_Event_TimeSync.hpp>
9#include <Scenario/Commands/Scenario/Creations/CreateSequence.hpp>
10#include <Scenario/Commands/Scenario/Creations/CreationMetaCommand.hpp>
11#include <Scenario/Commands/State/AddMessagesToState.hpp>
12#include <Scenario/Palette/ScenarioPaletteBaseStates.hpp>
13#include <Scenario/Palette/ScenarioPaletteBaseTransitions.hpp>
14#include <Scenario/Palette/Tool.hpp>
15#include <Scenario/Palette/Tools/ScenarioRollbackStrategy.hpp>
16#include <Scenario/Process/Algorithms/Accessors.hpp>
17#include <Scenario/Settings/ScenarioSettingsModel.hpp>
18#include <Scenario/Tools/elementFindingHelper.hpp>
19
20#include <score/application/GUIApplicationContext.hpp>
21#include <score/command/Dispatchers/MultiOngoingCommandDispatcher.hpp>
22#include <score/document/DocumentInterface.hpp>
23#include <score/selection/SelectionDispatcher.hpp>
24
25#include <QDebug>
26
27namespace Scenario
28{
29
30template <int Value>
31class StrongQState : public QState
32{
33public:
34 static constexpr auto value() { return Value; }
35 StrongQState(QState* parent)
36 : QState{parent}
37 {
38 this->setObjectName(debug_StateMachineIDs<Value>());
39 }
40};
41
42template <typename Scenario_T>
43class CreationStateBase : public StateBase<Scenario_T>
44{
45public:
46 using StateBase<Scenario_T>::StateBase;
47
48 QVector<Id<StateModel>> createdStates;
49 QVector<Id<EventModel>> createdEvents;
50 QVector<Id<TimeSyncModel>> createdTimeSyncs;
51 QVector<Id<IntervalModel>> createdIntervals;
52
53 void clearCreatedIds()
54 {
55 createdEvents.clear();
56 createdIntervals.clear();
57 createdTimeSyncs.clear();
58 createdStates.clear();
59 }
60};
61
62// Here to prevent pollution of the CreationState header with the command
63// dispatcher
64template <typename Scenario_T, typename ToolPalette_T>
65class CreationState : public CreationStateBase<Scenario_T>
66{
67public:
69 const ToolPalette_T& sm, const score::CommandStackFacade& stack,
70 const Scenario_T& scenarioPath, QState* parent)
71 : CreationStateBase<Scenario_T>{scenarioPath, parent}
72 , m_parentSM{sm}
73 , m_dispatcher{stack}
74 {
75 }
76
77protected:
78 void createToState_base(const Id<StateModel>& originalState)
79 {
80 if(this->hoveredState)
81 {
82 const bool graphal = isCreatingGraph();
83 const bool differentParents
84 = Scenario::parentEvent(originalState, m_parentSM.model()).timeSync()
85 != Scenario::parentEvent(*this->hoveredState, m_parentSM.model()).timeSync();
86
87 if(graphal && differentParents)
88 {
90 this->m_scenario, originalState, *this->hoveredState, true};
91
92 m_dispatcher.submit(cmd);
93
94 this->createdIntervals.append(cmd->createdInterval());
95 }
96 else
97 {
98 // make sure the hovered corresponding timesync dont have a date prior
99 // to original state date
100 if(getDate(m_parentSM.model(), originalState)
101 < getDate(m_parentSM.model(), *this->hoveredState))
102 {
104 this->m_scenario, originalState, *this->hoveredState};
105
106 m_dispatcher.submit(cmd);
107
108 this->createdIntervals.append(cmd->createdInterval());
109 }
110 }
111 }
112 }
113
114 void createToEvent_base(const Id<StateModel>& originalState)
115 {
116 if(this->hoveredEvent)
117 {
118 const bool graphal = isCreatingGraph();
119 const bool differentParents
120 = Scenario::parentEvent(originalState, m_parentSM.model()).timeSync()
121 != m_parentSM.model().event(*this->hoveredEvent).timeSync();
122 const bool timeIsInOrder = getDate(m_parentSM.model(), originalState)
123 < getDate(m_parentSM.model(), *this->hoveredEvent);
124 // make sure the hovered corresponding timesync dont have a date prior to
125 // original state date
126 if((graphal || timeIsInOrder) && differentParents)
127 {
129 this->m_scenario, originalState, *this->hoveredEvent, this->currentPoint.y,
130 graphal};
131
132 m_dispatcher.submit(cmd);
133
134 this->createdIntervals.append(cmd->createdInterval());
135 this->createdStates.append(cmd->createdState());
136 } // else do nothing
137 }
138 }
139
140 void createToTimeSync_base(const Id<StateModel>& originalState)
141 {
142 if(this->hoveredTimeSync)
143 {
144 const bool graphal = isCreatingGraph();
145 const bool differentParents
146 = Scenario::parentEvent(originalState, m_parentSM.model()).timeSync()
147 != *this->hoveredTimeSync;
148 const bool timeIsInOrder = getDate(m_parentSM.model(), originalState)
149 < getDate(m_parentSM.model(), *this->hoveredTimeSync);
150 // make sure the hovered corresponding timesync dont have a date prior to
151 // original state date
152 if((graphal || timeIsInOrder) && differentParents)
153 {
155 this->m_scenario, originalState, *this->hoveredTimeSync,
156 this->currentPoint.y, graphal};
157
158 m_dispatcher.submit(cmd);
159
160 this->createdStates.append(cmd->createdState());
161 this->createdEvents.append(cmd->createdEvent());
162 this->createdIntervals.append(cmd->createdInterval());
163 }
164 }
165 }
166
167 void createToNothing_base(const Id<StateModel>& originalState)
168 {
169 if(m_parentSM.editionSettings().tool() != Tool::CreateSequence)
170 {
172 this->m_scenario,
173 originalState, // Put there in createInitialState
174 this->currentPoint.date, this->currentPoint.y, isCreatingGraph()};
175
176 m_dispatcher.submit(cmd);
177
178 this->createdStates.append(cmd->createdState());
179 this->createdEvents.append(cmd->createdEvent());
180 this->createdTimeSyncs.append(cmd->createdTimeSync());
181 this->createdIntervals.append(cmd->createdInterval());
182 }
183 else
184 {
185
186 // This
187 auto cmd = Scenario::Command::CreateSequence::make(
188 this->m_parentSM.context().context, this->m_parentSM.model(),
189 originalState, // Put there in createInitialState
190 this->currentPoint.date, this->currentPoint.y);
191
192 m_dispatcher.submitQuiet(cmd);
193
194 this->createdStates.append(cmd->createdState());
195 this->createdEvents.append(cmd->createdEvent());
196 this->createdTimeSyncs.append(cmd->createdTimeSync());
197 this->createdIntervals.append(cmd->createdInterval());
198 }
199 }
200
201 void makeSnapshot()
202 {
203 const score::DocumentContext& ctx = this->m_parentSM.context().context;
204 if(!ctx.app.settings<Scenario::Settings::Model>().getSnapshotOnCreate())
205 return;
206
207 using namespace Command;
208 if(m_parentSM.editionSettings().tool() == Tool::CreateSequence)
209 return;
210
211 if(this->createdStates.empty())
212 return;
213
214 if(!this->createdIntervals.empty())
215 {
216 const auto& cst = m_parentSM.model().intervals.at(this->createdIntervals.last());
217 if(!cst.processes.empty())
218 {
219 // In case of the presence of a sequence, we
220 // only use the sequence's namespace, hence we don't need to make a
221 // snapshot at the end..
222 return;
223 }
224 }
225
226 auto& device_explorer
227 = ctx.template plugin<Explorer::DeviceDocumentPlugin>().explorer();
228
229 State::MessageList messages = getSelectionSnapshot(device_explorer);
230 if(messages.empty())
231 return;
232
233 m_dispatcher.submit(new AddMessagesToState{
234 m_parentSM.model().states.at(this->createdStates.last()), messages});
235 }
236
237 template <typename DestinationState, typename Function>
238 void add_transition(QState* from, DestinationState* to, Function&& fun)
239 {
240 using transition_type = Transition_T<Scenario_T, DestinationState::value()>;
241 auto trans = score::make_transition<transition_type>(from, to, *this);
242 trans->setObjectName(QString::number(DestinationState::value()));
243 QObject::connect(trans, &transition_type::triggered, this, fun);
244 }
245
246 void commit()
247 {
248 this->makeSnapshot();
249 this->m_dispatcher.template commit<Scenario::Command::CreationMetaCommand>();
250
251 // Select all the created elements
252 Selection sel;
253 if(!this->createdStates.empty())
254 {
255 auto& s = this->createdStates.back();
256 auto sp = m_parentSM.model().states.find(s);
257 if(sp == m_parentSM.model().states.end())
258 {
259 qDebug() << "Error: tried to select state but it did not exist";
260 }
261 else
262 {
263 sel.append(*sp);
264 }
265 }
266
267 if(!this->createdIntervals.empty())
268 {
269 auto& i = this->createdIntervals.back();
270 auto ip = m_parentSM.model().intervals.find(i);
271 if(ip == m_parentSM.model().intervals.end())
272 {
273 qDebug() << "Error: tried to select interval but it did not exist";
274 }
275 else
276 {
277 sel.append(*ip);
278 }
279 }
280
281 score::SelectionDispatcher d{this->m_parentSM.context().context.selectionStack};
282 d.select(sel);
283 this->clearCreatedIds();
284 }
285
286 void rollback()
287 {
288 m_dispatcher.template rollback<ScenarioRollbackStrategy>();
289 this->clearCreatedIds();
290 }
291
292 inline bool isCreatingGraph() const noexcept
293 {
294 return this->m_parentSM.editionSettings().tool() == Scenario::Tool::CreateGraph;
295 }
296
297 const ToolPalette_T& m_parentSM;
299
300 Scenario::Point m_clickedPoint{};
301};
302}
The MultiOngoingCommandDispatcher class.
Definition MultiOngoingCommandDispatcher.hpp:33
Definition CreateInterval_State_Event_TimeSync.hpp:30
Definition CreateInterval_State_Event.hpp:26
Definition CreateInterval_State.hpp:26
The CreateEventAfterEventCommand class.
Definition CreateInterval.hpp:33
Definition ScenarioCreationState.hpp:44
Definition ScenarioCreationState.hpp:66
Definition ScenarioSettingsModel.hpp:19
Definition ScenarioPaletteBaseStates.hpp:20
Definition ScenarioCreationState.hpp:32
Definition ScenarioPaletteBaseTransitions.hpp:23
Definition Selection.hpp:12
The id_base_t class.
Definition Identifier.hpp:57
A small abstraction layer over the score::CommandStack.
Definition CommandStackFacade.hpp:20
The SelectionDispatcher class.
Definition SelectionDispatcher.hpp:15
Main plug-in of score.
Definition score-plugin-dataflow/Dataflow/PortItem.hpp:13
Definition ScenarioPoint.hpp:13
T & settings() const
Access a specific Settings model instance.
Definition ApplicationContext.hpp:40
Definition DocumentContext.hpp:18