File indexing completed on 2024-05-12 04:56:39
0001 /*************************************************************************** 0002 * Copyright (C) 2013 by Linuxstopmotion contributors; * 0003 * see the AUTHORS file for details. * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "observernotifier.h" 0022 #include "animation/animationimpl.h" 0023 #include "animation/frame.h" 0024 #include "animation/workspacefile.h" 0025 #include "src/presentation/observer.h" 0026 #include "src/presentation/frontends/frontend.h" 0027 #include "src/foundation/logger.h" 0028 0029 #include <exception> 0030 0031 class FileNameVisitor; 0032 class Scene; 0033 class Sound; 0034 0035 class ObservableOperation { 0036 public: 0037 virtual ~ObservableOperation() { 0038 } 0039 /** 0040 * Performs the operation. 0041 */ 0042 virtual void op(AnimationImpl&) = 0; 0043 /** 0044 * Performs the update on the specified observer. 0045 */ 0046 virtual void update(Observer&) = 0; 0047 }; 0048 0049 void ObserverNotifier::doOp(ObservableOperation& oo) { 0050 oo.op(*del); 0051 // exceptions must not escape from here, or we might lose an object that 0052 // is of importance to the undo system. 0053 for (observers_t::iterator i = observers.begin(); 0054 i != observers.end(); ++i) { 0055 try { 0056 oo.update(**i); 0057 } catch (std::exception& e) { 0058 try { 0059 if (frontend) 0060 frontend->reportWarning(e.what()); 0061 } catch (...) { 0062 } 0063 for (observers_t::iterator i = observers.begin(); 0064 i != observers.end(); ++i) { 0065 (*i)->resync(); 0066 } 0067 } 0068 } 0069 } 0070 0071 ObserverNotifier::~ObserverNotifier() { 0072 delete del; 0073 } 0074 0075 ObserverNotifier::ObserverNotifier(AnimationImpl* delegate, Frontend* fe) 0076 : del(delegate), frontend(fe) { 0077 } 0078 0079 void ObserverNotifier::addObserver(Observer* newObserver) { 0080 observers.push_back(newObserver); 0081 } 0082 0083 void ObserverNotifier::removeObserver(Observer* o) { 0084 for (std::vector<Observer*>::iterator i = observers.begin(); 0085 i != observers.end(); ++i) { 0086 if (*i == o) { 0087 observers.erase(i); 0088 return; 0089 } 0090 } 0091 Logger::get().logWarning("Failed to find Observer to remove"); 0092 } 0093 0094 class AnimationClearer : public ObservableOperation { 0095 public: 0096 AnimationClearer() { 0097 } 0098 void op(AnimationImpl& del) { 0099 del.clear(); 0100 } 0101 void update(Observer& ob) { 0102 ob.updateClear(); 0103 } 0104 }; 0105 0106 void ObserverNotifier::clear() { 0107 AnimationClearer ac; 0108 doOp(ac); 0109 } 0110 0111 int ObserverNotifier::sceneCount() const { 0112 return del->sceneCount(); 0113 } 0114 0115 class SceneAdder : public ObservableOperation { 0116 int n; 0117 Scene* s; 0118 public: 0119 SceneAdder(int where, Scene* sc) : n(where), s(sc) { 0120 } 0121 void op(AnimationImpl& del) { 0122 if (s) 0123 del.addScene(n, s); 0124 else 0125 del.addScene(n); 0126 } 0127 void update(Observer& ob) { 0128 ob.updateNewScene(n); 0129 } 0130 }; 0131 0132 void ObserverNotifier::addScene(int where, Scene* newScene) { 0133 SceneAdder sa(where, newScene); 0134 doOp(sa); 0135 } 0136 0137 void ObserverNotifier::addScene(int where) { 0138 SceneAdder sa(where, 0); 0139 doOp(sa); 0140 } 0141 0142 void ObserverNotifier::preallocateScenes(int count) { 0143 del->preallocateScenes(count); 0144 } 0145 0146 class SceneRemover : public ObservableOperation { 0147 int sc; 0148 public: 0149 Scene* r; 0150 SceneRemover(int from) : sc(from), r(0) { 0151 } 0152 void op(AnimationImpl& del) { 0153 r = del.removeScene(sc); 0154 } 0155 void update(Observer& ob) { 0156 ob.updateRemoveScene(sc); 0157 } 0158 }; 0159 0160 Scene* ObserverNotifier::removeScene(int from) { 0161 SceneRemover sr(from); 0162 doOp(sr); 0163 return sr.r; 0164 } 0165 0166 class SceneMover : public ObservableOperation { 0167 int f; 0168 int t; 0169 public: 0170 SceneMover(int from, int to) : f(from), t(to) { 0171 } 0172 void op(AnimationImpl& del) { 0173 del.moveScene(f, t); 0174 } 0175 void update(Observer& ob) { 0176 ob.updateMoveScene(f, t); 0177 } 0178 }; 0179 0180 void ObserverNotifier::moveScene(int from, int to) { 0181 SceneMover sm(from, to); 0182 doOp(sm); 0183 } 0184 0185 const Scene* ObserverNotifier::getScene(int which) const { 0186 return del->getScene(which); 0187 } 0188 0189 int ObserverNotifier::frameCount(int scene) const { 0190 return del->frameCount(scene); 0191 } 0192 0193 class FrameAdder : public ObservableOperation { 0194 int sc; 0195 int n; 0196 const std::vector<Frame*>& frs; 0197 public: 0198 FrameAdder(int scene, int where, const std::vector<Frame*>& frames) 0199 : sc(scene), n(where), frs(frames) { 0200 } 0201 ~FrameAdder() { 0202 } 0203 void op(AnimationImpl& del) { 0204 del.addFrames(sc, n, frs); 0205 } 0206 void update(Observer& ob) { 0207 int count = frs.size(); 0208 ob.updateAdd(sc, n, count); 0209 } 0210 }; 0211 0212 void ObserverNotifier::addFrame(int scene, int where, Frame* frame) { 0213 std::vector<Frame*> frs; 0214 frs.push_back(frame); 0215 FrameAdder fa(scene, where, frs); 0216 doOp(fa); 0217 } 0218 0219 void ObserverNotifier::addFrames(int scene, int where, 0220 const std::vector<Frame*>& frames) { 0221 FrameAdder fa(scene, where, frames); 0222 doOp(fa); 0223 } 0224 0225 void ObserverNotifier::preallocateFrames(int scene, int count) { 0226 del->preallocateFrames(scene, count); 0227 } 0228 0229 class FrameRemover : public ObservableOperation { 0230 int sc; 0231 int n; 0232 Frame* r; 0233 public: 0234 FrameRemover(int scene, int where) 0235 : sc(scene), n(where), r(0) { 0236 } 0237 ~FrameRemover() { 0238 delete r; 0239 } 0240 Frame* release() { 0241 Frame* v = r; 0242 r = 0; 0243 return v; 0244 } 0245 void op(AnimationImpl& del) { 0246 del.removeFrame(sc, n); 0247 } 0248 void update(Observer& ob) { 0249 ob.updateRemove(sc, n, n); 0250 } 0251 }; 0252 0253 Frame* ObserverNotifier::removeFrame(int scene, int frame) { 0254 FrameRemover fr(scene, frame); 0255 doOp(fr); 0256 return fr.release(); 0257 } 0258 0259 class FramesRemover : public ObservableOperation { 0260 int sc; 0261 int fr; 0262 int c; 0263 std::vector<Frame*>& r; 0264 public: 0265 FramesRemover(int scene, int where, int count, std::vector<Frame*>& out) 0266 : sc(scene), fr(where), c(count), r(out) { 0267 } 0268 ~FramesRemover() { 0269 } 0270 void op(AnimationImpl& del) { 0271 del.removeFrames(sc, fr, c, r); 0272 } 0273 void update(Observer& ob) { 0274 ob.updateRemove(sc, fr, fr + c - 1); 0275 } 0276 }; 0277 0278 void ObserverNotifier::removeFrames(int scene, int frame, int count, 0279 std::vector<Frame*>& out) { 0280 FramesRemover fr(scene, frame, count, out); 0281 doOp(fr); 0282 } 0283 0284 class FrameMover : public ObservableOperation { 0285 int fromSc; 0286 int fromFr; 0287 int c; 0288 int toSc; 0289 int toFr; 0290 public: 0291 FrameMover(int fromScene, int fromFrame, int count, 0292 int toScene, int toFrame) 0293 : fromSc(fromScene), fromFr(fromFrame), c(count), 0294 toSc(toScene), toFr(toFrame) { 0295 } 0296 ~FrameMover() { 0297 } 0298 void op(AnimationImpl& del) { 0299 del.moveFrames(fromSc, fromFr, c, toSc, toFr); 0300 } 0301 void update(Observer& ob) { 0302 ob.updateMove(fromSc, fromFr, c, toSc, toFr); 0303 } 0304 }; 0305 0306 void ObserverNotifier::moveFrames(int fromScene, int fromFrame, int frameCount, 0307 int toScene, int toFrame) { 0308 FrameMover fm(fromScene, fromFrame, frameCount, toScene, toFrame); 0309 doOp(fm); 0310 } 0311 0312 class FrameReplacer : public ObservableOperation { 0313 int sc; 0314 int fr; 0315 WorkspaceFile& image; 0316 public: 0317 FrameReplacer(int scene, int where, WorkspaceFile& newImage) 0318 : sc(scene), fr(where), image(newImage) { 0319 } 0320 ~FrameReplacer() { 0321 } 0322 void op(AnimationImpl& del) { 0323 if (image.path()) 0324 del.replaceImage(sc, fr, image); 0325 } 0326 void update(Observer& ob) { 0327 ob.updateAnimationChanged(sc, fr); 0328 } 0329 }; 0330 0331 void ObserverNotifier::replaceImage(int sceneNumber, int frameNumber, 0332 WorkspaceFile& otherImage) { 0333 FrameReplacer fr(sceneNumber, frameNumber, otherImage); 0334 doOp(fr); 0335 } 0336 0337 int ObserverNotifier::soundCount(int scene, int frame) const { 0338 return del->soundCount(scene, frame); 0339 } 0340 0341 class SoundChanger : public ObservableOperation { 0342 int sc; 0343 int fr; 0344 public: 0345 SoundChanger(int scene, int frame) 0346 : sc(scene), fr(frame) { 0347 } 0348 ~SoundChanger() { 0349 } 0350 void op(AnimationImpl&) { 0351 } 0352 void update(Observer& ob) { 0353 ob.updateSoundChanged(sc, fr); 0354 } 0355 int scene() const { 0356 return sc; 0357 } 0358 int frame() const { 0359 return fr; 0360 } 0361 }; 0362 0363 class SoundAdder : public SoundChanger { 0364 int sn; 0365 Sound* s; 0366 public: 0367 SoundAdder(int scene, int frame, int soundNumber, Sound* sound) 0368 : SoundChanger(scene, frame), sn(soundNumber), s(sound) { 0369 } 0370 void op(AnimationImpl& del) { 0371 del.addSound(scene(), frame(), sn, s); 0372 } 0373 }; 0374 0375 void ObserverNotifier::addSound(int scene, int frame, int soundNumber, 0376 Sound* sound) { 0377 SoundAdder adder(scene, frame, soundNumber, sound); 0378 doOp(adder); 0379 } 0380 0381 class SoundNamer : public SoundChanger { 0382 int sn; 0383 const char* nm; 0384 const char* r; 0385 public: 0386 SoundNamer(int scene, int frame, int soundNumber, const char* name) 0387 : SoundChanger(scene, frame), sn(soundNumber), nm(name), r(0) { 0388 } 0389 void op(AnimationImpl& del) { 0390 r = del.setSoundName(scene(), frame(), sn, nm); 0391 } 0392 const char* returnValue() const { 0393 return r; 0394 } 0395 }; 0396 0397 const char* ObserverNotifier::setSoundName(int scene, int frame, 0398 int soundNumber, const char* soundName) { 0399 SoundNamer sn(scene, frame, soundNumber, soundName); 0400 doOp(sn); 0401 return sn.returnValue(); 0402 } 0403 0404 class SoundRemover : public SoundChanger { 0405 int sn; 0406 Sound* r; 0407 public: 0408 SoundRemover(int scene, int frame, int soundNumber) 0409 : SoundChanger(scene, frame), sn(soundNumber), r(0) { 0410 } 0411 void op(AnimationImpl& del) { 0412 r = del.removeSound(scene(), frame(), sn); 0413 } 0414 Sound* returnValue() const { 0415 return r; 0416 } 0417 }; 0418 0419 Sound* ObserverNotifier::removeSound(int scene, int frame, int soundNumber) { 0420 SoundRemover sr(scene, frame, soundNumber); 0421 doOp(sr); 0422 return sr.returnValue(); 0423 } 0424 0425 void ObserverNotifier::registerFrontend(Frontend* fe) { 0426 frontend = fe; 0427 } 0428 0429 class AnimationResynchronizer : public ObservableOperation { 0430 public: 0431 AnimationResynchronizer() { 0432 } 0433 void op(AnimationImpl&) { 0434 } 0435 void update(Observer& ob) { 0436 ob.resync(); 0437 } 0438 }; 0439 0440 void ObserverNotifier::resync() { 0441 AnimationResynchronizer resyncher; 0442 doOp(resyncher); 0443 } 0444 0445 int ObserverNotifier::soundCount() const { 0446 return del->soundCount(); 0447 } 0448 0449 void ObserverNotifier::playSounds(int scene, int frame, AudioDriver* audioDriver) const { 0450 del->playSounds(scene, frame, audioDriver); 0451 } 0452 0453 void ObserverNotifier::accept(FileNameVisitor& v) const { 0454 del->accept(v); 0455 }