MultiOngoingCommandDispatcher.hpp
1 #pragma once
2 #include <score/command/Dispatchers/ICommandDispatcher.hpp>
3 #include <score/command/Dispatchers/SendStrategy.hpp>
4 
5 // Creates commands on a list and keep updating the latest command
6 // up to the next new command.
7 namespace RollbackStrategy
8 {
9 struct Simple
10 {
11  static void
12  rollback(const score::DocumentContext& ctx, const std::vector<score::Command*>& cmds)
13  {
14  for(int i = cmds.size() - 1; i >= 0; --i)
15  {
16  cmds[i]->undo(ctx);
17  }
18  }
19 };
20 }
21 
33 {
34 public:
36  : ICommandDispatcher{stack}
37  {
38  }
39 
40  ~MultiOngoingCommandDispatcher() { cleanup(); }
41 
42  void submit(score::Command* cmd)
43  {
44  stack().disableActions();
45  cmd->redo(stack().context());
46  m_cmds.push_back(cmd);
47  }
48 
49  void submitQuiet(score::Command* cmd)
50  {
51  stack().disableActions();
52  m_cmds.push_back(cmd);
53  }
54 
55  template <typename TheCommand, typename... Args>
56  void submit(Args&&... args)
57  {
58  if(m_cmds.empty())
59  {
60  stack().disableActions();
61  auto cmd = new TheCommand(std::forward<Args>(args)...);
62  cmd->redo(stack().context());
63  m_cmds.push_back(cmd);
64  }
65  else
66  {
67  score::Command* last = m_cmds.back();
68  if(last->key() == TheCommand::static_key())
69  {
70  safe_cast<TheCommand*>(last)->update(std::forward<Args>(args)...);
71  safe_cast<TheCommand*>(last)->redo(stack().context());
72  }
73  else
74  {
75  auto cmd = new TheCommand(std::forward<Args>(args)...);
76  cmd->redo(stack().context());
77  m_cmds.push_back(cmd);
78  }
79  }
80  }
81 
82  // Give it something that behaves like AggregateCommand
83  template <typename CommitCommand>
84  void commit()
85  {
86  if(!m_cmds.empty())
87  {
88  auto theCmd = new CommitCommand;
89  for(auto& cmd : m_cmds)
90  {
91  theCmd->addCommand(cmd);
92  }
93 
94  SendStrategy::Quiet::send(stack(), theCmd);
95  m_cmds.clear();
96 
97  stack().enableActions();
98  }
99  }
100 
101  template <typename RollbackStrategy>
102  void rollback()
103  {
104  RollbackStrategy::rollback(stack().context(), m_cmds);
105 
106  cleanup();
107  m_cmds.clear();
108 
109  stack().enableActions();
110  }
111 
112 private:
113  void cleanup()
114  {
115  std::for_each(m_cmds.rbegin(), m_cmds.rend(), [](auto cmd) { delete cmd; });
116  }
117 
118  std::vector<score::Command*> m_cmds;
119 };
The ICommandDispatcher class.
Definition: ICommandDispatcher.hpp:21
The MultiOngoingCommandDispatcher class.
Definition: MultiOngoingCommandDispatcher.hpp:33
The Command class.
Definition: Command.hpp:34
A small abstraction layer over the score::CommandStack.
Definition: CommandStackFacade.hpp:20
Definition: MultiOngoingCommandDispatcher.hpp:10
Definition: DocumentContext.hpp:18