Initial porting to the new component API.
[tagua/yd.git] / src / graphicalgame.cpp
blob192317f65db4e60838ba1a34a674fc9dce6fc013
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>
13 #include <core/color.h>
14 #include <core/moveserializer.h>
15 #include <core/state.h>
16 #include <core/validator.h>
17 #include <core/variant.h>
19 #include "graphicalgame.h"
20 #include "game.h"
21 #include "game_p.h"
22 #include "mastersettings.h"
23 #include "graphicalsystem.h"
24 #include "movelist_table.h"
25 #include "decoratedmove.h"
26 #include "entities/userentity.h"
27 #include <iostream>
29 using namespace GamePrivate; // is this ok?
31 template <typename Enum>
32 inline void setFlag(QFlags<Enum>& flag, Enum e, bool value) {
33 if (value)
34 flag |= e;
35 else
36 flag &= ~e;
40 class CtrlAction {
41 Game* m_game;
42 bool m_done;
43 Index m_index;
44 public:
45 CtrlAction(Game* game)
46 : m_game(game)
47 , m_index(game->index()) {
48 m_done = m_game->back();
51 void forfait() { m_done = false; }
53 ~CtrlAction() {
54 if (m_done) m_game->goTo(m_index);
58 GraphicalGame::GraphicalGame(GraphicalSystem* graphical,
59 MoveList::Table* m)
60 : Game(graphical->variant())
61 , m_graphical(graphical)
62 , m_movelist(m)
63 , m_anim_sequence(false) {
64 m_action_state = 0;
66 m_decorator = requestComponent<IMoveSerializer>(
67 graphical->variant(), "move_serializer/decorated");
69 if(m_movelist) {
70 m_movelist->reset();
71 // FIXME restore move list layout
72 m_movelist->setLayoutStyle(0 /*graphical->m_variant->moveListLayout()*/);
73 m_movelist->setNotifier( static_cast<MoveList::Notifier*>(this) );
74 m_movelist->show();
76 settings().onChange(this, "settingsChanged", "Loader::Theme");
77 settingsChanged();
80 GraphicalGame::~GraphicalGame() {
81 if(m_movelist) {
82 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
84 m_movelist->setNotifier(NULL, false);
88 void GraphicalGame::settingsChanged() {
89 m_anim_sequence = settings().flag("animations", true)
90 && settings()("animations").flag("sequence", true);
91 m_anim_sequence_max = settings()("animations")("sequence")[QString("max")] | 10;
94 void GraphicalGame::onAdded(const Index& ix) {
95 onAddedInternal(ix);
96 updateActionState();
99 void GraphicalGame::onAddedInternal(const Index& ix, bool confirm_promotion) {
100 if(!m_movelist)
101 return;
103 int at;
104 History *vec = fetchRef(ix, &at);
105 if(!vec) {
106 ERROR("invalid index " << ix);
107 return;
110 m_movelist->remove(ix, confirm_promotion); //clear existing, if any
112 Index index = ix;
113 for(int i=at;i<(int)vec->size();i++) {
114 Entry* e = &(*vec)[i];
115 StatePtr prev = position(index.prev());
116 DecoratedMove mv(
117 (e->move != Move() && prev) ?
118 m_decorator->serialize(e->move, prev.get()) :
119 (e->position ? "(-)" : "???"));
121 int turn = prev ? prev->turn()->index() : (index.totalNumMoves()+1)%2;
123 //mv += " " + QString::number(turn);
124 m_movelist->setMove(index, turn, mv, e->comment, confirm_promotion);
126 for (Variations::const_iterator it = e->variations.begin();
127 it != e->variations.end(); ++it)
128 onAddedInternal(index.next(it->first), confirm_promotion);
129 for (VComments::const_iterator it = e->vcomments.begin();
130 it != e->vcomments.end(); ++it)
131 m_movelist->setVComment(index, it->first, it->second, confirm_promotion);
133 index = index.next();
137 void GraphicalGame::onEntryChanged(const Index& at, int propagate) {
138 if(at <= Index(0)) {
139 Entry* e = fetch(at);
140 if(!e)
141 return;
142 if(at == current && e->position)
143 m_graphical->warp(e->move, e->position);
144 return;
147 if(m_movelist) {
148 Entry* e = fetch(at);
149 if(!e)
150 return;
152 Entry* pe = fetch(at.prev());
154 StatePtr last_pos;
155 if (pe) last_pos = pe->position;
157 DecoratedMove mv(
158 (e->move != Move() && last_pos) ?
159 m_decorator->serialize(e->move, last_pos.get()) :
160 (e->position ? "(-)" : "???"));
162 int turn = last_pos ?
163 last_pos->turn()->index() :
164 (at.totalNumMoves()+1)%2;
166 m_movelist->setMove(at, turn, mv, e->comment);
167 if(at == current && e->position)
168 m_graphical->warp(e->move, e->position);
170 // when an entry changes, chances are that we get some more information about the
171 // next ones as well
172 if(propagate) {
173 onEntryChanged(at.next(), propagate-1);
174 for (Variations::const_iterator it = e->variations.begin();
175 it != e->variations.end(); ++it)
176 onEntryChanged(at.next(it->first), propagate-1);
181 void GraphicalGame::onRemoved(const Index& i) {
182 if(m_movelist)
183 m_movelist->remove(i);
184 updateActionState();
187 void GraphicalGame::onPromoteVariation(const Index& i, int v) {
188 if(m_movelist) {
189 m_movelist->promoteVariation(i,v);
190 onAddedInternal(i.next(), true);
191 onAddedInternal(i.next(v), true);
192 VComments vc = fetch(i)->vcomments;
193 VComments::const_iterator it = vc.find(v);
194 if(it != vc.end())
195 m_movelist->setVComment(i, v, it->second, true);
196 m_movelist->select(current, true);
198 updateActionState();
201 void GraphicalGame::onSetComment(const Index& i, const QString& s) {
202 if(m_movelist)
203 m_movelist->setComment(i, s);
206 void GraphicalGame::onSetVComment(const Index& i, int v, const QString& s) {
207 if(m_movelist)
208 m_movelist->setVComment(i, v, s);
211 void GraphicalGame::updateActionState() {
212 ActionState old_state = m_action_state;
213 setFlag(m_action_state, BACK, current != 0);
214 setFlag(m_action_state, BEGIN, current != 0);
215 Entry* next_entry = fetch(current.next());
216 setFlag(m_action_state, FORWARD, next_entry);
217 setFlag(m_action_state, END, next_entry);
218 if (old_state != m_action_state)
219 onActionStateChange();
222 void GraphicalGame::onCurrentIndexChanged(const Index& old_c) {
223 if (m_ctrl) m_ctrl->forfait();
225 if(m_movelist)
226 m_movelist->select(current);
228 updateActionState();
230 Entry *oe = fetch(old_c);
231 Entry *e = fetch(current);
232 std::pair<int, int> steps = old_c.stepsTo(current);
234 if(!e || !e->position)
235 return;
237 if(!oe || !oe->position) {
238 m_graphical->warp(move(), position());
239 return;
242 bool can_animate = (steps.first+steps.second <= 1) || (m_anim_sequence
243 && (steps.first+steps.second <= m_anim_sequence_max));
245 if(can_animate)
246 for(int i=1;i<=steps.first;i++)
247 if( move(old_c.prev(i-1)) == Move() ||
248 !position(old_c.prev(i))) {
249 can_animate = false;
250 break;
253 if(can_animate)
254 for(int i=steps.second-1;i>=0;i--)
255 if( move(current.prev(i)) == Move() ||
256 !position(current.prev(i))) {
257 can_animate = false;
258 break;
261 if(can_animate) {
262 for(int i=1;i<=steps.first;i++)
263 m_graphical->back( move(old_c.prev(i)), move(old_c.prev(i-1)), position(old_c.prev(i)));
264 for(int i=steps.second-1;i>=0;i--)
265 m_graphical->forward( move(current.prev(i)), position(current.prev(i)));
267 else
268 m_graphical->warp( move(), position());
270 // set m_action_state
274 void GraphicalGame::onAvailableUndo(bool e) {
275 setFlag(m_action_state, UNDO, e);
276 onActionStateChange();
279 void GraphicalGame::onAvailableRedo(bool e) {
280 setFlag(m_action_state, REDO, e);
281 onActionStateChange();
284 void GraphicalGame::onUserSelectMove(const Index& i) {
285 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
286 if (entity->goTo(i))
287 return;
289 // fallback
290 goTo(i);
293 void GraphicalGame::onUserSetComment(const Index& i, QString s) {
294 setComment(i, s);
297 void GraphicalGame::onUserSetVComment(const Index& i, int v, QString s) {
298 setVComment(i, v, s);
301 void GraphicalGame::onUserClearVariations(const Index& i) {
302 clearVariations(i);
305 void GraphicalGame::onUserTruncate(const Index& i) {
306 if (i == index())
307 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
308 if (entity->truncate())
309 return;
311 // fallback
312 truncate(i);
315 void GraphicalGame::onUserPromoteVariation(const Index& i) {
316 if (i == index())
317 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
318 if (entity->promoteVariation())
319 return;
321 // fallback
322 promoteVariation(i);
325 void GraphicalGame::onUserRemoveVariation(const Index& i) {
326 removeVariation(i);
329 void GraphicalGame::onUserUndo() {
330 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
331 if (entity->undo())
332 return;
334 // fallback
335 undo();
338 void GraphicalGame::onUserRedo() {
339 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
340 if (entity->redo())
341 return;
343 // fallback
344 redo();
347 void GraphicalGame::onDetachNotifier() {
348 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
350 m_movelist = NULL;
353 void GraphicalGame::createCtrlAction() {
354 m_ctrl = boost::shared_ptr<CtrlAction>(new CtrlAction(this));
357 void GraphicalGame::destroyCtrlAction() {
358 m_ctrl.reset();
361 void GraphicalGame::setActionStateObserver(
362 const boost::shared_ptr<ActionStateObserver>& obs) {
363 m_action_state_observer = obs;
366 void GraphicalGame::onActionStateChange() {
367 m_action_state_observer->notifyActionStateChange(m_action_state);
370 ActionStateObserver::~ActionStateObserver() { }