3 #include <Scenario/Commands/Scenario/Displacement/MoveEventMeta.hpp>
4 #include <Scenario/Commands/Scenario/Merge/MergeEvents.hpp>
5 #include <Scenario/Document/Event/EventPresenter.hpp>
6 #include <Scenario/Document/Event/EventView.hpp>
7 #include <Scenario/Document/Interval/Temporal/TemporalIntervalPresenter.hpp>
8 #include <Scenario/Document/Interval/Temporal/TemporalIntervalView.hpp>
9 #include <Scenario/Document/State/StatePresenter.hpp>
10 #include <Scenario/Document/State/StateView.hpp>
11 #include <Scenario/Document/TimeSync/TimeSyncPresenter.hpp>
12 #include <Scenario/Document/TimeSync/TimeSyncView.hpp>
13 #include <Scenario/Document/TimeSync/TriggerView.hpp>
14 #include <Scenario/Palette/ScenarioPaletteBaseStates.hpp>
15 #include <Scenario/Palette/Tools/ScenarioRollbackStrategy.hpp>
16 #include <Scenario/Palette/Transitions/AnythingTransitions.hpp>
17 #include <Scenario/Palette/Transitions/EventTransitions.hpp>
18 #include <Scenario/Palette/Transitions/IntervalTransitions.hpp>
19 #include <Scenario/Palette/Transitions/NothingTransitions.hpp>
20 #include <Scenario/Palette/Transitions/TimeSyncTransitions.hpp>
21 #include <Scenario/Process/Algorithms/Accessors.hpp>
23 #include <score/command/Dispatchers/MultiOngoingCommandDispatcher.hpp>
24 #include <score/locking/ObjectLocker.hpp>
26 #include <QApplication>
27 #include <QFinalState>
41 , m_movingDispatcher{stack}
43 this->setObjectName(
"MoveIntervalState");
44 using namespace Scenario::Command;
45 auto finalState =
new QFinalState{
this};
47 auto mainState =
new QState{
this};
49 auto pressed =
new QState{mainState};
50 auto released =
new QState{mainState};
51 auto moving =
new QState{mainState};
54 mainState->setInitialState(pressed);
55 released->addTransition(finalState);
58 = score::make_transition<MoveOnAnything_Transition<Scenario::ProcessModel>>(
59 pressed, moving, *
this);
60 QObject::connect(t_pressed, &QAbstractTransition::triggered, [&]() {
61 auto& scenar = stateMachine.model();
62 m_initialClick = this->currentPoint;
63 if(!this->clickedInterval)
66 auto& cst = scenario.interval(*this->clickedInterval);
67 auto& sev = Scenario::startEvent(cst, scenario);
68 auto& eev = Scenario::endEvent(cst, scenario);
70 m_intervalInitialPoint = {cst.date(), cst.heightPercentage()};
71 m_lastDate = m_intervalInitialPoint.date;
73 auto prev_csts = previousNonGraphIntervals(sev, scenar);
74 if(!prev_csts.empty())
78 for(
const auto& cst_id : prev_csts)
80 const auto& other_date = scenar.interval(cst_id).date();
87 this->m_pressedPrevious = t + TimeVal::fromMsecs(10);
91 this->m_pressedPrevious = std::nullopt;
94 this->m_startEventCanBeMerged = previousIntervals(sev, scenar).empty();
95 this->m_endEventCanBeMerged = nextIntervals(eev, scenar).empty();
98 score::make_transition<ReleaseOnAnything_Transition>(pressed, finalState);
99 score::make_transition<MoveOnAnything_Transition<Scenario::ProcessModel>>(
100 moving, moving, *
this);
101 score::make_transition<ReleaseOnAnything_Transition>(moving, released);
103 QObject::connect(moving, &QState::entered, [&] {
104 auto& scenario = stateMachine.model();
105 if(!this->clickedInterval)
107 auto& cst = scenario.interval(*this->clickedInterval);
110 auto& sst = Scenario::startState(cst, scenario);
111 auto& sev = Scenario::parentEvent(sst, scenario);
112 auto& sts = Scenario::parentTimeSync(sev, scenario);
114 if(qApp->keyboardModifiers() & Qt::ShiftModifier)
116 if(&sts == &scenario.startTimeSync())
119 m_lastDate = m_intervalInitialPoint.date
120 + (this->currentPoint.date - m_initialClick.date);
121 if(this->m_pressedPrevious)
122 m_lastDate = std::max(m_lastDate, *this->m_pressedPrevious);
124 m_lastDate = stateMachine.magnetic().getPosition(&sts, m_lastDate);
125 m_lastDate = std::max(m_lastDate, TimeVal{});
129 m_lastDate = m_intervalInitialPoint.date;
139 this->m_movingDispatcher.template submit<Command::MoveEventMeta>(
140 this->m_scenario, sev.id(), m_lastDate,
141 m_intervalInitialPoint.y + (this->currentPoint.y - m_initialClick.y),
142 stateMachine.editionSettings().expandMode(),
143 stateMachine.editionSettings().lockMode(), cst.startState());
146 QObject::connect(released, &QState::entered, [&]() {
147 if(!this->clickedInterval)
149 auto& cst = scenario.interval(*this->clickedInterval);
152 auto& sst = Scenario::startState(cst, scenario);
153 auto& sev = Scenario::parentEvent(sst, scenario);
154 auto& sts = Scenario::parentTimeSync(sev, scenario);
156 if(qApp->keyboardModifiers() & Qt::ShiftModifier)
158 if(&sts == &scenario.startTimeSync())
161 if(this->m_startEventCanBeMerged)
163 merge(cst, Scenario::startState(cst, m_scenario), m_lastDate);
174 m_movingDispatcher.template commit<Command::MoveIntervalMacro>();
175 m_pressedPrevious = {};
179 auto rollbackState =
new QState{
this};
180 score::make_transition<score::Cancel_Transition>(mainState, rollbackState);
181 rollbackState->addTransition(finalState);
182 QObject::connect(rollbackState, &QState::entered, [&]() {
184 m_pressedPrevious = {};
187 this->setInitialState(mainState);
191 void rollback() { m_movingDispatcher.template rollback<DefaultRollbackStrategy>(); }
195 auto& ev = Scenario::parentEvent(st, m_scenario);
196 auto& ts = Scenario::parentTimeSync(ev, m_scenario);
198 auto& sst_pres = m_sm.presenter().state(st.id());
199 auto& sev_pres = m_sm.presenter().event(ev.id());
200 auto& sts_pres = m_sm.presenter().timeSync(ts.id());
201 auto& itv_pres = m_sm.presenter().interval(cst.id());
203 std::vector<QGraphicsItem*> toIgnore;
204 toIgnore.push_back(sst_pres.view());
205 toIgnore.push_back(sev_pres.view());
206 toIgnore.push_back(sts_pres.view());
207 toIgnore.push_back(&sts_pres.trigger());
208 toIgnore.push_back(itv_pres.view());
209 QGraphicsItem* item = m_sm.itemAt({date, cst.heightPercentage()}, toIgnore);
211 if(
auto stateToMerge = qgraphicsitem_cast<Scenario::StateView*>(item))
214 this->m_movingDispatcher.template submit<Command::MergeEvents>(
215 this->m_scenario, ev.id(),
216 Scenario::parentEvent(stateToMerge->presenter().model().id(), this->m_scenario)
219 else if(
auto eventToMerge = qgraphicsitem_cast<Scenario::EventView*>(item))
222 this->m_movingDispatcher.template submit<Command::MergeEvents>(
223 this->m_scenario, ev.id(), eventToMerge->presenter().model().id());
225 else if(
auto syncToMerge = qgraphicsitem_cast<Scenario::TimeSyncView*>(item))
228 this->m_movingDispatcher.template submit<Command::MergeTimeSyncs>(
229 this->m_scenario, ts.id(), syncToMerge->presenter().model().id());
238 std::optional<TimeVal> m_pressedPrevious;
240 bool m_startEventCanBeMerged{};
241 bool m_endEventCanBeMerged{};
The MultiOngoingCommandDispatcher class.
Definition: MultiOngoingCommandDispatcher.hpp:33
Definition: IntervalModel.hpp:50
Definition: MoveIntervalState.hpp:33
MoveIntervalState(const T &stateMachine, const Scenario::ProcessModel &scenario, const score::CommandStackFacade &stack, score::ObjectLocker &locker, QState *parent)
Definition: MoveIntervalState.hpp:35
The core hierarchical and temporal process of score.
Definition: ScenarioModel.hpp:37
Definition: ScenarioPaletteBaseStates.hpp:20
A small abstraction layer over the score::CommandStack.
Definition: CommandStackFacade.hpp:20
The ObjectLocker class.
Definition: ObjectLocker.hpp:21
Main plug-in of score.
Definition: score-plugin-dataflow/Dataflow/PortItem.hpp:14
Definition: ScenarioPoint.hpp:13
Definition: TimeValue.hpp:21