Make MainWindow::newGame code more readable.
[tagua/yd.git] / src / graphicalgame.cpp
blob22e4c7540a0ba0fb90da969e79efbc330f65286f
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 "graphicalgame.h"
13 #include <KDebug>
15 #include "game.h"
16 #include "game_p.h"
17 #include "mastersettings.h"
18 #include "graphicalsystem.h"
19 #include "movelist_table.h"
20 #include "decoratedmove.h"
21 #include "entities/userentity.h"
23 using namespace GamePrivate; // is this ok?
25 template <typename Enum>
26 inline void setFlag(QFlags<Enum>& flag, Enum e, bool value) {
27 if (value)
28 flag |= e;
29 else
30 flag &= ~e;
34 class CtrlAction {
35 Game* m_game;
36 bool m_done;
37 Index m_index;
38 public:
39 CtrlAction(Game* game)
40 : m_game(game)
41 , m_index(game->index()) {
42 m_done = m_game->back();
45 void forfait() { m_done = false; }
47 ~CtrlAction() {
48 if (m_done) m_game->goTo(m_index);
52 GraphicalGame::GraphicalGame(GraphicalSystem* graphical,
53 MoveList::Table* m)
54 : Game()
55 , m_graphical(graphical)
56 , m_movelist(m)
57 , m_anim_sequence(false) {
58 m_action_state = 0;
59 if(m_movelist) {
60 m_movelist->reset();
61 m_movelist->setLayoutStyle(graphical->m_variant->moveListLayout());
62 m_movelist->setNotifier( static_cast<MoveList::Notifier*>(this) );
63 m_movelist->show();
65 settings().onChange(this, "settingsChanged", "Loader::Theme");
66 settingsChanged();
69 GraphicalGame::~GraphicalGame() {
70 if(m_movelist) {
71 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
73 m_movelist->setNotifier(NULL, false);
77 void GraphicalGame::settingsChanged() {
78 m_anim_sequence = settings().flag("animations", true)
79 && settings()("animations").flag("sequence", true);
80 m_anim_sequence_max = settings()("animations")("sequence")[QString("max")] | 10;
83 void GraphicalGame::onAdded(const Index& ix) {
84 onAddedInternal(ix);
85 updateActionState();
88 void GraphicalGame::onAddedInternal(const Index& ix, bool confirm_promotion) {
89 if(!m_movelist)
90 return;
92 int at;
93 History *vec = fetchRef(ix, &at);
94 if(!vec) {
95 kError() << "invalid index " << ix;
96 return;
99 m_movelist->remove(ix, confirm_promotion); //clear existing, if any
101 Index index = ix;
102 for(int i=at;i<(int)vec->size();i++) {
103 Entry* e = &(*vec)[i];
104 PositionPtr prev = position(index.prev());
105 DecoratedMove mv(
106 (e->move && prev) ?
107 e->move->toString("decorated", prev) :
108 (e->position ? "(-)" : "???"));
110 int turn = prev ? prev->turn() : (index.totalNumMoves()+1)%2;
111 //mv += " " + QString::number(turn);
112 m_movelist->setMove(index, turn, mv, e->comment, confirm_promotion);
114 for (Variations::const_iterator it = e->variations.begin();
115 it != e->variations.end(); ++it)
116 onAddedInternal(index.next(it->first), confirm_promotion);
117 for (VComments::const_iterator it = e->vcomments.begin();
118 it != e->vcomments.end(); ++it)
119 m_movelist->setVComment(index, it->first, it->second, confirm_promotion);
121 index = index.next();
125 void GraphicalGame::onEntryChanged(const Index& at, int propagate) {
126 if(at <= Index(0)) {
127 Entry* e = fetch(at);
128 if(!e)
129 return;
130 if(at == current && e->position)
131 m_graphical->warp(e->move, e->position);
132 return;
135 if(m_movelist) {
136 Entry* e = fetch(at);
137 if(!e)
138 return;
140 Entry* pe = fetch(at.prev());
142 AbstractPosition::Ptr last_pos;
143 if (pe) last_pos = pe->position;
145 DecoratedMove mv(
146 (e->move && last_pos) ?
147 e->move->toString("decorated", last_pos) :
148 (e->position ? "(-)" : "???"));
149 int turn = last_pos ? last_pos->turn() : (at.totalNumMoves()+1)%2;
150 m_movelist->setMove(at, turn, mv, e->comment);
151 if(at == current && e->position)
152 m_graphical->warp(e->move, e->position);
154 // when an entry changes, chances are that we get some more information about the
155 // next ones as well
156 if(propagate) {
157 onEntryChanged(at.next(), propagate-1);
158 for (Variations::const_iterator it = e->variations.begin();
159 it != e->variations.end(); ++it)
160 onEntryChanged(at.next(it->first), propagate-1);
165 void GraphicalGame::onRemoved(const Index& i) {
166 if(m_movelist)
167 m_movelist->remove(i);
168 updateActionState();
171 void GraphicalGame::onPromoteVariation(const Index& i, int v) {
172 if(m_movelist) {
173 m_movelist->promoteVariation(i,v);
174 onAddedInternal(i.next(), true);
175 onAddedInternal(i.next(v), true);
176 VComments vc = fetch(i)->vcomments;
177 VComments::const_iterator it = vc.find(v);
178 if(it != vc.end())
179 m_movelist->setVComment(i, v, it->second, true);
180 m_movelist->select(current, true);
182 updateActionState();
185 void GraphicalGame::onSetComment(const Index& i, const QString& s) {
186 if(m_movelist)
187 m_movelist->setComment(i, s);
190 void GraphicalGame::onSetVComment(const Index& i, int v, const QString& s) {
191 if(m_movelist)
192 m_movelist->setVComment(i, v, s);
195 void GraphicalGame::updateActionState() {
196 ActionState old_state = m_action_state;
197 setFlag(m_action_state, BACK, current != 0);
198 setFlag(m_action_state, BEGIN, current != 0);
199 Entry* next_entry = fetch(current.next());
200 setFlag(m_action_state, FORWARD, next_entry);
201 setFlag(m_action_state, END, next_entry);
202 if (old_state != m_action_state)
203 onActionStateChange();
206 void GraphicalGame::onCurrentIndexChanged(const Index& old_c) {
207 if (m_ctrl) m_ctrl->forfait();
209 if(m_movelist)
210 m_movelist->select(current);
212 updateActionState();
214 Entry *oe = fetch(old_c);
215 Entry *e = fetch(current);
216 std::pair<int, int> steps = old_c.stepsTo(current);
218 if(!e || !e->position)
219 return;
221 if(!oe || !oe->position) {
222 m_graphical->warp(move(), position());
223 return;
226 bool can_animate = (steps.first+steps.second <= 1) || (m_anim_sequence
227 && (steps.first+steps.second <= m_anim_sequence_max));
229 if(can_animate)
230 for(int i=1;i<=steps.first;i++)
231 if( !move(old_c.prev(i-1)) || !position(old_c.prev(i))) {
232 can_animate = false;
233 break;
236 if(can_animate)
237 for(int i=steps.second-1;i>=0;i--)
238 if( !move(current.prev(i)) || !position(current.prev(i))) {
239 can_animate = false;
240 break;
243 if(can_animate) {
244 for(int i=1;i<=steps.first;i++)
245 m_graphical->back( move(old_c.prev(i)), move(old_c.prev(i-1)), position(old_c.prev(i)));
246 for(int i=steps.second-1;i>=0;i--)
247 m_graphical->forward( move(current.prev(i)), position(current.prev(i)));
249 else
250 m_graphical->warp( move(), position());
252 // set m_action_state
256 void GraphicalGame::onAvailableUndo(bool e) {
257 setFlag(m_action_state, UNDO, e);
258 onActionStateChange();
261 void GraphicalGame::onAvailableRedo(bool e) {
262 setFlag(m_action_state, REDO, e);
263 onActionStateChange();
266 void GraphicalGame::onUserSelectMove(const Index& i) {
267 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
268 if (entity->goTo(i))
269 return;
271 // fallback
272 goTo(i);
275 void GraphicalGame::onUserSetComment(const Index& i, QString s) {
276 setComment(i, s);
279 void GraphicalGame::onUserSetVComment(const Index& i, int v, QString s) {
280 setVComment(i, v, s);
283 void GraphicalGame::onUserClearVariations(const Index& i) {
284 clearVariations(i);
287 void GraphicalGame::onUserTruncate(const Index& i) {
288 if (i == index())
289 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
290 if (entity->truncate())
291 return;
293 // fallback
294 truncate(i);
297 void GraphicalGame::onUserPromoteVariation(const Index& i) {
298 if (i == index())
299 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
300 if (entity->promoteVariation())
301 return;
303 // fallback
304 promoteVariation(i);
307 void GraphicalGame::onUserRemoveVariation(const Index& i) {
308 removeVariation(i);
311 void GraphicalGame::onUserUndo() {
312 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
313 if (entity->undo())
314 return;
316 // fallback
317 undo();
320 void GraphicalGame::onUserRedo() {
321 if (boost::shared_ptr<UserEntity> entity = m_listener_entity.lock())
322 if (entity->redo())
323 return;
325 // fallback
326 redo();
329 void GraphicalGame::onDetachNotifier() {
330 Q_ASSERT(m_movelist->getNotifier() == static_cast<MoveList::Notifier*>(this));
332 m_movelist = NULL;
335 void GraphicalGame::createCtrlAction() {
336 m_ctrl = boost::shared_ptr<CtrlAction>(new CtrlAction(this));
339 void GraphicalGame::destroyCtrlAction() {
340 m_ctrl.reset();
343 void GraphicalGame::setActionStateObserver(
344 const boost::shared_ptr<ActionStateObserver>& obs) {
345 m_action_state_observer = obs;
348 void GraphicalGame::onActionStateChange() {
349 m_action_state_observer->notifyActionStateChange(m_action_state);
352 ActionStateObserver::~ActionStateObserver() { }