ActionState notification fixes.
[tagua/yd.git] / src / graphicalgame.cpp
blob8cb5eddce70a27fdca161a8ca6ad5e8f09207610
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #include <iostream>
12 #include "graphicalgame.h"
13 #include "game.h"
14 #include "game_p.h"
15 #include "mastersettings.h"
16 #include "graphicalsystem.h"
17 #include "movelist_table.h"
18 #include "decoratedmove.h"
19 #include "entities/userentity.h"
20 #include <iostream>
22 using namespace GamePrivate; // is this ok?
24 template <typename Enum>
25 inline void setFlag(QFlags<Enum>& flag, Enum e, bool value) {
26 if (value)
27 flag |= e;
28 else
29 flag &= ~e;
33 class CtrlAction {
34 Game* m_game;
35 bool m_done;
36 Index m_index;
37 public:
38 CtrlAction(Game* game)
39 : m_game(game)
40 , m_index(game->index()) {
41 m_done = m_game->back();
44 void forfait() { m_done = false; }
46 ~CtrlAction() {
47 if (m_done) m_game->goTo(m_index);
51 GraphicalGame::GraphicalGame(GraphicalSystem* graphical,
52 MoveList::Table* m)
53 : Game()
54 , m_graphical(graphical)
55 , m_movelist(m)
56 , m_anim_sequence(false) {
57 m_action_state = 0;
58 if(m_movelist) {
59 m_movelist->reset();
60 m_movelist->setLayoutStyle(graphical->m_variant->moveListLayout());
61 m_movelist->setNotifier( static_cast<MoveList::Notifier*>(this) );
62 m_movelist->show();
64 settings().onChange(this, "settingsChanged", "Loader::Theme");
65 settingsChanged();
68 GraphicalGame::~GraphicalGame() {
69 if(m_movelist) {
70 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
72 m_movelist->setNotifier(NULL, false);
76 void GraphicalGame::settingsChanged() {
77 m_anim_sequence = settings().flag("animations", true)
78 && settings()("animations").flag("sequence", true);
79 m_anim_sequence_max = settings()("animations")("sequence")[QString("max")] | 10;
82 void GraphicalGame::onAdded(const Index& ix) {
83 onAddedInternal(ix);
86 void GraphicalGame::onAddedInternal(const Index& ix, bool confirm_promotion) {
87 if(!m_movelist)
88 return;
90 int at;
91 History *vec = fetchRef(ix, &at);
92 if(!vec) {
93 ERROR("invalid index " << ix);
94 return;
97 m_movelist->remove(ix, confirm_promotion); //clear existing, if any
99 Index index = ix;
100 for(int i=at;i<(int)vec->size();i++) {
101 Entry* e = &(*vec)[i];
102 PositionPtr prev = position(index.prev());
103 DecoratedMove mv(
104 (e->move && prev) ?
105 e->move->toString("decorated", prev) :
106 (e->position ? "(-)" : "???"));
108 int turn = prev ? prev->turn() : (index.totalNumMoves()+1)%2;
109 //mv += " " + QString::number(turn);
110 m_movelist->setMove(index, turn, mv, e->comment, confirm_promotion);
112 for (Variations::const_iterator it = e->variations.begin();
113 it != e->variations.end(); ++it)
114 onAddedInternal(index.next(it->first), confirm_promotion);
115 for (VComments::const_iterator it = e->vcomments.begin();
116 it != e->vcomments.end(); ++it)
117 m_movelist->setVComment(index, it->first, it->second, confirm_promotion);
119 index = index.next();
123 void GraphicalGame::onEntryChanged(const Index& at, int propagate) {
124 if(at <= Index(0)) {
125 Entry* e = fetch(at);
126 if(!e)
127 return;
128 if(at == current && e->position)
129 m_graphical->warp(e->move, e->position);
130 return;
133 if(m_movelist) {
134 Entry* e = fetch(at);
135 if(!e)
136 return;
138 Entry* pe = fetch(at.prev());
140 AbstractPosition::Ptr last_pos;
141 if (pe) last_pos = pe->position;
143 DecoratedMove mv(
144 (e->move && last_pos) ?
145 e->move->toString("decorated", last_pos) :
146 (e->position ? "(-)" : "???"));
147 int turn = last_pos ? last_pos->turn() : (at.totalNumMoves()+1)%2;
148 m_movelist->setMove(at, turn, mv, e->comment);
149 if(at == current && e->position)
150 m_graphical->warp(e->move, e->position);
152 // when an entry changes, chances are that we get some more information about the
153 // next ones as well
154 if(propagate) {
155 onEntryChanged(at.next(), propagate-1);
156 for (Variations::const_iterator it = e->variations.begin();
157 it != e->variations.end(); ++it)
158 onEntryChanged(at.next(it->first), propagate-1);
163 void GraphicalGame::onRemoved(const Index& i) {
164 if(m_movelist)
165 m_movelist->remove(i);
168 void GraphicalGame::onPromoteVariation(const Index& i, int v) {
169 if(m_movelist) {
170 m_movelist->promoteVariation(i,v);
171 onAddedInternal(i.next(), true);
172 onAddedInternal(i.next(v), true);
173 VComments vc = fetch(i)->vcomments;
174 VComments::const_iterator it = vc.find(v);
175 if(it != vc.end())
176 m_movelist->setVComment(i, v, it->second, true);
177 m_movelist->select(current, true);
181 void GraphicalGame::onSetComment(const Index& i, const QString& s) {
182 if(m_movelist)
183 m_movelist->setComment(i, s);
186 void GraphicalGame::onSetVComment(const Index& i, int v, const QString& s) {
187 if(m_movelist)
188 m_movelist->setVComment(i, v, s);
191 void GraphicalGame::onCurrentIndexChanged(const Index& old_c) {
192 if (m_ctrl) m_ctrl->forfait();
194 if(m_movelist)
195 m_movelist->select(current);
197 Entry *oe = fetch(old_c);
198 Entry *e = fetch(current);
199 std::pair<int, int> steps = old_c.stepsTo(current);
201 if(!e || !e->position)
202 return;
204 if(!oe || !oe->position) {
205 m_graphical->warp(move(), position());
206 return;
209 bool can_animate = (steps.first+steps.second <= 1) || (m_anim_sequence
210 && (steps.first+steps.second <= m_anim_sequence_max));
212 if(can_animate)
213 for(int i=1;i<=steps.first;i++)
214 if( !move(old_c.prev(i-1)) || !position(old_c.prev(i))) {
215 can_animate = false;
216 break;
219 if(can_animate)
220 for(int i=steps.second-1;i>=0;i--)
221 if( !move(current.prev(i)) || !position(current.prev(i))) {
222 can_animate = false;
223 break;
226 if(can_animate) {
227 for(int i=1;i<=steps.first;i++)
228 m_graphical->back( move(old_c.prev(i)), move(old_c.prev(i-1)), position(old_c.prev(i)));
229 for(int i=steps.second-1;i>=0;i--)
230 m_graphical->forward( move(current.prev(i)), position(current.prev(i)));
232 else
233 m_graphical->warp( move(), position());
235 // set m_action_state
236 ActionState old_state = m_action_state;
237 setFlag(m_action_state, BACK, current != 0);
238 setFlag(m_action_state, BEGIN, current != 0);
239 Entry* next_entry = fetch(current.next());
240 setFlag(m_action_state, FORWARD, next_entry);
241 setFlag(m_action_state, END, next_entry);
242 if (old_state != m_action_state)
243 onActionStateChange();
246 void GraphicalGame::onAvailableUndo(bool e) {
247 setFlag(m_action_state, UNDO, e);
248 onActionStateChange();
249 if(m_movelist)
250 m_movelist->enableUndo(e);
253 void GraphicalGame::onAvailableRedo(bool e) {
254 setFlag(m_action_state, REDO, e);
255 onActionStateChange();
256 if(m_movelist)
257 m_movelist->enableRedo(e);
260 void GraphicalGame::onUserSelectMove(const Index& i) {
261 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
262 if (entity->goTo(i))
263 return;
265 // fallback
266 goTo(i);
269 void GraphicalGame::onUserSetComment(const Index& i, QString s) {
270 setComment(i, s);
273 void GraphicalGame::onUserSetVComment(const Index& i, int v, QString s) {
274 setVComment(i, v, s);
277 void GraphicalGame::onUserClearVariations(const Index& i) {
278 clearVariations(i);
281 void GraphicalGame::onUserTruncate(const Index& i) {
282 if (i == index())
283 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
284 if (entity->truncate())
285 return;
287 // fallback
288 truncate(i);
291 void GraphicalGame::onUserPromoteVariation(const Index& i) {
292 if (i == index())
293 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
294 if (entity->promoteVariation())
295 return;
297 // fallback
298 promoteVariation(i);
301 void GraphicalGame::onUserRemoveVariation(const Index& i) {
302 removeVariation(i);
305 void GraphicalGame::onUserUndo() {
306 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
307 if (entity->undo())
308 return;
310 // fallback
311 undo();
314 void GraphicalGame::onUserRedo() {
315 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
316 if (entity->redo())
317 return;
319 // fallback
320 redo();
323 void GraphicalGame::onDetachNotifier() {
324 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
326 m_movelist = NULL;
329 void GraphicalGame::createCtrlAction() {
330 m_ctrl = boost::shared_ptr<CtrlAction>(new CtrlAction(this));
333 void GraphicalGame::destroyCtrlAction() {
334 m_ctrl.reset();
337 void GraphicalGame::setActionStateObserver(
338 const boost::shared_ptr<ActionStateObserver>& obs) {
339 m_action_state_observer = obs;
342 void GraphicalGame::onActionStateChange() {
343 m_action_state_observer->notifyActionStateChange(m_action_state);
346 ActionStateObserver::~ActionStateObserver() { }