score-plugin-scenario/Scenario/Palette/Tools/SmartTool.hpp
1 #pragma once
2 #include <Scenario/Palette/Tools/ScenarioToolState.hpp>
3 #include <Scenario/Palette/Tools/StateSelection.hpp>
4 #include <Scenario/Palette/Tools/States/ResizeSlotState.hpp>
5 #include <Scenario/Palette/Tools/States/ScenarioSelectionState.hpp>
6 #include <Scenario/Palette/Transitions/IntervalTransitions.hpp>
7 #include <Scenario/Palette/Transitions/SlotTransitions.hpp>
8 #include <Scenario/Palette/Transitions/StateTransitions.hpp>
9 #include <Scenario/Process/Algorithms/StandardDisplacementPolicy.hpp>
10 
11 #include <score/selection/SelectionDispatcher.hpp>
12 
13 namespace Scenario
14 {
15 class ToolPalette;
16 
17 // TODO Generic smart tool with variadic...
18 template <
19  typename Scenario_T, typename ToolPalette_T, typename View_T,
20  typename MoveIntervalWrapper_T, typename MoveLeftBraceWrapper_T,
21  typename MoveRightBraceWrapper_T, typename MoveEventWrapper_T,
22  typename MoveTimeSyncWrapper_T>
23 class SmartTool final : public ToolBase<ToolPalette_T>
24 {
25 public:
26  SmartTool(ToolPalette_T& sm)
27  : ToolBase<ToolPalette_T>{sm}
28  {
29  auto sub = new QState{&this->localSM()};
30  sub->setChildMode(QState::ParallelStates);
31 
32  // Selection
33  m_state = new SelectionState<ToolPalette_T, View_T>{
34  this->m_palette.context().context.selectionStack, this->m_palette,
35  this->m_palette.presenter().view(), sub};
36 
37  this->localSM().setInitialState(sub);
38 
39  // Other actions; they are in //.
40  auto actionsState = new QState(sub);
41  {
42  auto waitState = new QState(actionsState);
43  actionsState->setInitialState(waitState);
44 
45  auto mov_i = MoveIntervalWrapper_T::template make<Scenario_T, ToolPalette_T>(
46  this->m_palette, waitState, *actionsState);
47  auto mov_lb = MoveLeftBraceWrapper_T::template make<Scenario_T, ToolPalette_T>(
48  this->m_palette, waitState, *actionsState);
49  auto mov_rb = MoveRightBraceWrapper_T::template make<Scenario_T, ToolPalette_T>(
50  this->m_palette, waitState, *actionsState);
51  auto mov_e = MoveEventWrapper_T::template make<Scenario_T, ToolPalette_T>(
52  this->m_palette, waitState, *actionsState);
53  auto mov_ts = MoveTimeSyncWrapper_T::template make<Scenario_T, ToolPalette_T>(
54  this->m_palette, waitState, *actionsState);
55 
56  if constexpr(!std::is_same_v<decltype(mov_i), std::nullptr_t>)
57  {
58  score::make_transition<ClickOnState_Transition<Scenario_T>>(
59  mov_i, mov_e, *mov_e);
60  score::make_transition<ClickOnState_Transition<Scenario_T>>(
61  mov_ts, mov_e, *mov_e);
62  score::make_transition<ClickOnState_Transition<Scenario_T>>(
63  mov_lb, mov_e, *mov_e);
64  score::make_transition<ClickOnState_Transition<Scenario_T>>(
65  mov_rb, mov_e, *mov_e);
66 
67  score::make_transition<ClickOnInterval_Transition<Scenario_T>>(
68  mov_ts, mov_i, *mov_i);
69  score::make_transition<ClickOnInterval_Transition<Scenario_T>>(
70  mov_e, mov_i, *mov_i);
71  score::make_transition<ClickOnInterval_Transition<Scenario_T>>(
72  mov_lb, mov_i, *mov_i);
73  score::make_transition<ClickOnInterval_Transition<Scenario_T>>(
74  mov_rb, mov_i, *mov_i);
75  }
77  auto resizeSlot = new ResizeSlotState<Scenario_T, ToolPalette_T>{
78  this->m_palette.context().context.commandStack, this->m_palette, actionsState};
79 
80  score::make_transition<ClickOnSlotHandle_Transition>(
81  waitState, resizeSlot, *resizeSlot);
82 
83  resizeSlot->addTransition(resizeSlot, finishedState(), waitState);
84  }
85 
86  this->localSM().start();
87  }
88 
89  void on_pressed(QPointF scene, Scenario::Point sp)
90  {
91  using namespace std;
92 
93  this->mapTopItem(
94  this->itemUnderMouse(scene),
95  [&](const Id<StateModel>& id) // State
96  {
97  const auto& elt = this->m_palette.presenter().state(id);
98 
99  Selection sel;
100  doStateSelection(sel, elt.model(), this->m_palette.model());
101 
102  m_state->dispatcher.select(filterSelections(
103  sel, this->m_palette.model().selectedChildren(), m_state->multiSelection()));
104 
105  this->localSM().postEvent(new ClickOnState_Event{id, sp});
106  m_nothingPressed = false;
107  },
108  [&](const Id<EventModel>& id) // Event
109  {
110  const auto& elt = this->m_palette.presenter().event(id);
111 
112  m_state->dispatcher.select(filterSelections(
113  &elt.model(), this->m_palette.model().selectedChildren(),
114  m_state->multiSelection()));
115 
116  this->localSM().postEvent(new ClickOnEvent_Event{id, sp});
117  m_nothingPressed = false;
118  },
119  [&](const Id<TimeSyncModel>& id) // TimeSync
120  {
121  const auto& elt = this->m_palette.presenter().timeSync(id);
122 
123  m_state->dispatcher.select(filterSelections(
124  &elt.model(), this->m_palette.model().selectedChildren(),
125  m_state->multiSelection()));
126  this->localSM().postEvent(new ClickOnTimeSync_Event{id, sp});
127  m_nothingPressed = false;
128  },
129  [&](const Id<IntervalModel>& id) // Interval
130  {
131  const auto& model = this->m_palette.model().interval(id);
132 
133  if(!model.selection.get())
134  {
135  m_state->dispatcher.select(filterSelections(
136  &model, this->m_palette.model().selectedChildren(),
137  m_state->multiSelection()));
138  }
139  this->localSM().postEvent(new ClickOnInterval_Event{id, sp});
140  m_nothingPressed = false;
141  },
142  [&](const Id<IntervalModel>& id) // LeftBrace
143  {
144  const auto& elt = this->m_palette.presenter().interval(id);
145 
146  if(!elt.isSelected())
147  {
148  m_state->dispatcher.select(filterSelections(
149  &elt.model(), this->m_palette.model().selectedChildren(),
150  m_state->multiSelection()));
151  }
152 
153  this->localSM().postEvent((new ClickOnLeftBrace_Event{id, sp}));
154  m_nothingPressed = false;
155  },
156  [&](const Id<IntervalModel>& id) // RightBrace
157  {
158  const auto& elt = this->m_palette.presenter().interval(id);
159 
160  if(!elt.isSelected())
161  {
162  m_state->dispatcher.select(filterSelections(
163  &elt.model(), this->m_palette.model().selectedChildren(),
164  m_state->multiSelection()));
165  }
166 
167  this->localSM().postEvent((new ClickOnRightBrace_Event{id, sp}));
168  m_nothingPressed = false;
169  },
170  [&](const SlotPath& slot) // Slot handle
171  {
172  this->localSM().postEvent(new ClickOnSlotHandle_Event{slot});
173  m_nothingPressed = false;
174  },
175  [&]() {
176  this->localSM().postEvent(new score::Press_Event);
177  m_nothingPressed = true;
178  });
179 
180  m_moved = false;
181  }
182 
183  void on_moved(QPointF scene, Scenario::Point sp)
184  {
185  if(m_nothingPressed)
186  {
187  this->localSM().postEvent(new score::Move_Event);
188  }
189  else
190  {
191  m_moved = true;
192  this->mapTopItem(
193  this->itemUnderMouse(scene),
194  [&](const Id<StateModel>& id) {
195  this->localSM().postEvent(new MoveOnState_Event{id, sp});
196  }, // state
197  [&](const Id<EventModel>& id) {
198  this->localSM().postEvent(new MoveOnEvent_Event{id, sp});
199  }, // event
200  [&](const Id<TimeSyncModel>& id) {
201  this->localSM().postEvent(new MoveOnTimeSync_Event{id, sp});
202  }, // timesync
203  [&](const Id<IntervalModel>& id) {
204  this->localSM().postEvent(new MoveOnInterval_Event{id, sp});
205  }, // interval
206  [&](const Id<IntervalModel>& id) {
207  this->localSM().postEvent(new MoveOnLeftBrace_Event{id, sp});
208  }, // LeftBrace
209  [&](const Id<IntervalModel>& id) {
210  this->localSM().postEvent(new MoveOnRightBrace_Event{id, sp});
211  }, // RightBrace
212  [&](const SlotPath& slot) {
213  this->localSM().postEvent(new MoveOnSlotHandle_Event{slot});
214  }, // Slot handle
215  [&]() { this->localSM().postEvent(new MoveOnNothing_Event{sp}); });
216  }
217  }
218 
219  void on_released(QPointF scene, Scenario::Point sp)
220  {
221  if(m_nothingPressed)
222  {
223  this->localSM().postEvent(new score::Release_Event); // select
224  m_nothingPressed = false;
225 
226  return;
227  }
228  if(m_moved) // then don't change selection
229  {
230  this->localSM().postEvent(new ReleaseOnNothing_Event{sp});
231  m_nothingPressed = false;
232 
233  return;
234  }
235 
236  this->mapTopItem(
237  this->itemUnderMouse(scene),
238  [&](const Id<StateModel>& id) // State
239  {
240  this->localSM().postEvent(new ReleaseOnState_Event{id, sp});
241  },
242  [&](const Id<EventModel>& id) // Event
243  {
244  this->localSM().postEvent(new ReleaseOnEvent_Event{id, sp});
245  },
246  [&](const Id<TimeSyncModel>& id) // TimeSync
247  {
248  this->localSM().postEvent(new ReleaseOnTimeSync_Event{id, sp});
249  },
250  [&](const Id<IntervalModel>& id) // Interval
251  {
252  this->localSM().postEvent(new ReleaseOnInterval_Event{id, sp});
253  },
254  [&](const Id<IntervalModel>& id) // LeftBrace
255  {
256  this->localSM().postEvent(new ReleaseOnLeftBrace_Event{id, sp});
257  },
258  [&](const Id<IntervalModel>& id) // RightBrace
259  {
260  this->localSM().postEvent(new ReleaseOnRightBrace_Event{id, sp});
261  },
262  [&](const SlotPath& slot) // Slot handle
263  { this->localSM().postEvent(new ReleaseOnSlotHandle_Event{slot}); },
264  [&]() {
265  this->localSM().postEvent(new ReleaseOnNothing_Event{sp}); // end of move
266  });
267  }
268 
269  void on_cancel() override { GraphicsSceneTool<Point>::on_cancel(); }
270 
271  auto& selectionState() const { return *m_state; }
272 
273 private:
274  SelectionState<ToolPalette_T, View_T>* m_state{};
275 
276  bool m_nothingPressed{true};
277  bool m_moved{false};
278 };
279 }
Definition: GraphicsSceneTool.hpp:11
Definition: score-plugin-scenario/Scenario/Palette/Tools/SmartTool.hpp:24
SmartTool(ToolPalette_T &sm)
Definition: score-plugin-scenario/Scenario/Palette/Tools/SmartTool.hpp:26
Definition: ScenarioToolState.hpp:49
Definition: Selection.hpp:12
The id_base_t class.
Definition: Identifier.hpp:57
Main plug-in of score.
Definition: score-plugin-dataflow/Dataflow/PortItem.hpp:14
Definition: ScenarioPoint.hpp:13
Definition: StateMachineUtils.hpp:18