Mercurial > hg > svcore
comparison data/model/EventCommands.h @ 1741:9d82b164f264 by-id
Work on commands, and some other model updates
author | Chris Cannam |
---|---|
date | Thu, 27 Jun 2019 13:08:10 +0100 |
parents | 86bbccb79c9b |
children | 52705a328b34 |
comparison
equal
deleted
inserted
replaced
1740:fe3f7f8df3a3 | 1741:9d82b164f264 |
---|---|
16 #ifndef SV_EVENT_COMMANDS_H | 16 #ifndef SV_EVENT_COMMANDS_H |
17 #define SV_EVENT_COMMANDS_H | 17 #define SV_EVENT_COMMANDS_H |
18 | 18 |
19 #include "base/Event.h" | 19 #include "base/Event.h" |
20 #include "base/Command.h" | 20 #include "base/Command.h" |
21 #include "base/ById.h" | |
21 | 22 |
22 /** | 23 /** |
23 * Interface for classes that can be modified through these commands | 24 * Interface for classes that can be modified through these commands |
24 */ | 25 */ |
25 class EventEditable | 26 class EventEditable |
27 public: | 28 public: |
28 virtual void add(Event e) = 0; | 29 virtual void add(Event e) = 0; |
29 virtual void remove(Event e) = 0; | 30 virtual void remove(Event e) = 0; |
30 }; | 31 }; |
31 | 32 |
33 template <typename Base> | |
34 class WithEditable | |
35 { | |
36 typedef typename Base::Id Id; | |
37 Id m_id; | |
38 | |
39 protected: | |
40 WithEditable(Id id) : m_id(id) { } | |
41 | |
42 std::shared_ptr<EventEditable> getEditable() { | |
43 auto base = StaticById<Base, Id>::get(m_id); | |
44 if (!base) return {}; // acceptable - item has expired | |
45 auto editable = std::dynamic_pointer_cast<EventEditable>(base); | |
46 if (!editable) { | |
47 SVCERR << "WARNING: Id passed to EventEditable command is not that of an EventEditable" << endl; | |
48 } | |
49 return editable; | |
50 } | |
51 }; | |
52 | |
32 /** | 53 /** |
33 * Command to add an event to an editable containing events, with undo. | 54 * Command to add an event to an editable containing events, with |
55 * undo. The template parameter must be a type that can be | |
56 * dynamic_cast to EventEditable and that has a ById store. | |
34 */ | 57 */ |
35 class AddEventCommand : public Command | 58 template <typename Base> |
59 class AddEventCommand : public Command, | |
60 public WithEditable<Base> | |
36 { | 61 { |
37 public: | 62 public: |
38 AddEventCommand(EventEditable *editable, const Event &e, QString name) : | 63 AddEventCommand(typename Base::Id editable, const Event &e, QString name) : |
39 m_editable(editable), m_event(e), m_name(name) { } | 64 WithEditable<Base>(editable), m_event(e), m_name(name) { } |
40 | 65 |
41 QString getName() const override { return m_name; } | 66 QString getName() const override { return m_name; } |
42 Event getEvent() const { return m_event; } | 67 Event getEvent() const { return m_event; } |
43 | 68 |
44 void execute() override { m_editable->add(m_event); } | 69 void execute() override { |
45 void unexecute() override { m_editable->remove(m_event); } | 70 auto editable = getEditable(); |
71 if (editable) editable->add(m_event); | |
72 } | |
73 void unexecute() override { | |
74 auto editable = getEditable(); | |
75 if (editable) editable->remove(m_event); | |
76 } | |
46 | 77 |
47 private: | 78 private: |
48 EventEditable *m_editable; | |
49 Event m_event; | 79 Event m_event; |
50 QString m_name; | 80 QString m_name; |
81 using WithEditable<Base>::getEditable; | |
51 }; | 82 }; |
52 | 83 |
53 /** | 84 /** |
54 * Command to remove an event from an editable containing events, with | 85 * Command to remove an event from an editable containing events, with |
55 * undo. | 86 * undo. The template parameter must be a type that implements |
87 * EventBase and that has a ById store. | |
56 */ | 88 */ |
57 class RemoveEventCommand : public Command | 89 template <typename Base> |
90 class RemoveEventCommand : public Command, | |
91 public WithEditable<Base> | |
58 { | 92 { |
59 public: | 93 public: |
60 RemoveEventCommand(EventEditable *editable, const Event &e, QString name) : | 94 RemoveEventCommand(typename Base::Id editable, const Event &e, QString name) : |
61 m_editable(editable), m_event(e), m_name(name) { } | 95 WithEditable<Base>(editable), m_event(e), m_name(name) { } |
62 | 96 |
63 QString getName() const override { return m_name; } | 97 QString getName() const override { return m_name; } |
64 Event getEvent() const { return m_event; } | 98 Event getEvent() const { return m_event; } |
65 | 99 |
66 void execute() override { m_editable->remove(m_event); } | 100 void execute() override { |
67 void unexecute() override { m_editable->add(m_event); } | 101 auto editable = getEditable(); |
102 if (editable) editable->remove(m_event); | |
103 } | |
104 void unexecute() override { | |
105 auto editable = getEditable(); | |
106 if (editable) editable->add(m_event); | |
107 } | |
68 | 108 |
69 private: | 109 private: |
70 EventEditable *m_editable; | |
71 Event m_event; | 110 Event m_event; |
72 QString m_name; | 111 QString m_name; |
112 using WithEditable<Base>::getEditable; | |
73 }; | 113 }; |
74 | 114 |
75 /** | 115 /** |
76 * Command to add or remove a series of events to or from an editable, | 116 * Command to add or remove a series of events to or from an editable, |
77 * with undo. Creates and immediately executes a sub-command for each | 117 * with undo. Creates and immediately executes a sub-command for each |
78 * add/remove requested. Consecutive add/remove pairs for the same | 118 * add/remove requested. Consecutive add/remove pairs for the same |
79 * point are collapsed. | 119 * point are collapsed. The template parameter must be a type that |
120 * implements EventBase and that has a ById store. | |
80 */ | 121 */ |
122 template <typename Base> | |
81 class ChangeEventsCommand : public MacroCommand | 123 class ChangeEventsCommand : public MacroCommand |
82 { | 124 { |
125 typedef typename Base::Id Id; | |
126 | |
83 public: | 127 public: |
84 ChangeEventsCommand(EventEditable *editable, QString name) : | 128 ChangeEventsCommand(Id editable, QString name) : |
85 MacroCommand(name), m_editable(editable) { } | 129 MacroCommand(name), m_editable(editable) { } |
86 | 130 |
87 void add(Event e) { | 131 void add(Event e) { |
88 addCommand(new AddEventCommand(m_editable, e, getName()), true); | 132 addCommand(new AddEventCommand<Base>(m_editable, e, getName()), |
133 true); | |
89 } | 134 } |
90 void remove(Event e) { | 135 void remove(Event e) { |
91 addCommand(new RemoveEventCommand(m_editable, e, getName()), true); | 136 addCommand(new RemoveEventCommand<Base>(m_editable, e, getName()), |
137 true); | |
92 } | 138 } |
93 | 139 |
94 /** | 140 /** |
95 * Stack an arbitrary other command in the same sequence. | 141 * Stack an arbitrary other command in the same sequence. |
96 */ | 142 */ |
118 if (m_commands.empty()) { | 164 if (m_commands.empty()) { |
119 MacroCommand::addCommand(command); | 165 MacroCommand::addCommand(command); |
120 return; | 166 return; |
121 } | 167 } |
122 | 168 |
123 RemoveEventCommand *r = | 169 RemoveEventCommand<Base> *r = |
124 dynamic_cast<RemoveEventCommand *>(command); | 170 dynamic_cast<RemoveEventCommand<Base> *>(command); |
125 AddEventCommand *a = | 171 AddEventCommand<Base> *a = |
126 dynamic_cast<AddEventCommand *>(*m_commands.rbegin()); | 172 dynamic_cast<AddEventCommand<Base> *>(*m_commands.rbegin()); |
127 if (r && a) { | 173 if (r && a) { |
128 if (a->getEvent() == r->getEvent()) { | 174 if (a->getEvent() == r->getEvent()) { |
129 deleteCommand(a); | 175 deleteCommand(a); |
130 return; | 176 return; |
131 } | 177 } |
132 } | 178 } |
133 | 179 |
134 MacroCommand::addCommand(command); | 180 MacroCommand::addCommand(command); |
135 } | 181 } |
136 | 182 |
137 EventEditable *m_editable; | 183 Id m_editable; |
138 }; | 184 }; |
139 | 185 |
140 #endif | 186 #endif |