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.
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"
22 #include "mastersettings.h"
23 #include "graphicalsystem.h"
24 #include "movelist_table.h"
25 #include "decoratedmove.h"
26 #include "entities/userentity.h"
29 using namespace GamePrivate
; // is this ok?
31 template <typename Enum
>
32 inline void setFlag(QFlags
<Enum
>& flag
, Enum e
, bool value
) {
45 CtrlAction(Game
* game
)
47 , m_index(game
->index()) {
48 m_done
= m_game
->back();
51 void forfait() { m_done
= false; }
54 if (m_done
) m_game
->goTo(m_index
);
58 GraphicalGame::GraphicalGame(GraphicalSystem
* graphical
,
60 : Game(graphical
->variant())
61 , m_graphical(graphical
)
63 , m_anim_sequence(false) {
66 m_decorator
= requestComponent
<IMoveSerializer
>(
67 graphical
->variant(), "move_serializer/decorated");
71 // FIXME restore move list layout
72 m_movelist
->setLayoutStyle(0 /*graphical->m_variant->moveListLayout()*/);
73 m_movelist
->setNotifier( static_cast<MoveList::Notifier
*>(this) );
76 settings().onChange(this, "settingsChanged", "Loader::Theme");
80 GraphicalGame::~GraphicalGame() {
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
) {
99 void GraphicalGame::onAddedInternal(const Index
& ix
, bool confirm_promotion
) {
104 History
*vec
= fetchRef(ix
, &at
);
106 ERROR("invalid index " << ix
);
110 m_movelist
->remove(ix
, confirm_promotion
); //clear existing, if any
113 for(int i
=at
;i
<(int)vec
->size();i
++) {
114 Entry
* e
= &(*vec
)[i
];
115 StatePtr prev
= position(index
.prev());
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
) {
139 Entry
* e
= fetch(at
);
142 if(at
== current
&& e
->position
)
143 m_graphical
->warp(e
->move
, e
->position
);
148 Entry
* e
= fetch(at
);
152 Entry
* pe
= fetch(at
.prev());
155 if (pe
) last_pos
= pe
->position
;
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
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
) {
183 m_movelist
->remove(i
);
187 void GraphicalGame::onPromoteVariation(const Index
& i
, int v
) {
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
);
195 m_movelist
->setVComment(i
, v
, it
->second
, true);
196 m_movelist
->select(current
, true);
201 void GraphicalGame::onSetComment(const Index
& i
, const QString
& s
) {
203 m_movelist
->setComment(i
, s
);
206 void GraphicalGame::onSetVComment(const Index
& i
, int v
, const QString
& s
) {
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();
226 m_movelist
->select(current
);
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
)
237 if(!oe
|| !oe
->position
) {
238 m_graphical
->warp(move(), position());
242 bool can_animate
= (steps
.first
+steps
.second
<= 1) || (m_anim_sequence
243 && (steps
.first
+steps
.second
<= m_anim_sequence_max
));
246 for(int i
=1;i
<=steps
.first
;i
++)
247 if( move(old_c
.prev(i
-1)) == Move() ||
248 !position(old_c
.prev(i
))) {
254 for(int i
=steps
.second
-1;i
>=0;i
--)
255 if( move(current
.prev(i
)) == Move() ||
256 !position(current
.prev(i
))) {
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
)));
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())
293 void GraphicalGame::onUserSetComment(const Index
& i
, QString s
) {
297 void GraphicalGame::onUserSetVComment(const Index
& i
, int v
, QString s
) {
298 setVComment(i
, v
, s
);
301 void GraphicalGame::onUserClearVariations(const Index
& i
) {
305 void GraphicalGame::onUserTruncate(const Index
& i
) {
307 if (boost::shared_ptr
<UserEntity
> entity
= m_listener_entity
.lock())
308 if (entity
->truncate())
315 void GraphicalGame::onUserPromoteVariation(const Index
& i
) {
317 if (boost::shared_ptr
<UserEntity
> entity
= m_listener_entity
.lock())
318 if (entity
->promoteVariation())
325 void GraphicalGame::onUserRemoveVariation(const Index
& i
) {
329 void GraphicalGame::onUserUndo() {
330 if (boost::shared_ptr
<UserEntity
> entity
= m_listener_entity
.lock())
338 void GraphicalGame::onUserRedo() {
339 if (boost::shared_ptr
<UserEntity
> entity
= m_listener_entity
.lock())
347 void GraphicalGame::onDetachNotifier() {
348 Q_ASSERT(m_movelist
->getNotifier() == static_cast<MoveList::Notifier
*>(this));
353 void GraphicalGame::createCtrlAction() {
354 m_ctrl
= boost::shared_ptr
<CtrlAction
>(new CtrlAction(this));
357 void GraphicalGame::destroyCtrlAction() {
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() { }