1// Aseprite
2// Copyright (C) 2001-2018 David Capello
3//
4// This program is distributed under the terms of
5// the End-User License Agreement for Aseprite.
6
7#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
11#include "app/cmd/remove_frame.h"
12
13#include "app/cmd/remove_cel.h"
14#include "app/doc.h"
15#include "app/doc_event.h"
16#include "doc/cels_range.h"
17#include "doc/sprite.h"
18
19namespace app {
20namespace cmd {
21
22using namespace doc;
23
24RemoveFrame::RemoveFrame(Sprite* sprite, frame_t frame)
25 : WithSprite(sprite)
26 , m_frame(frame)
27 , m_firstTime(true)
28 , m_frameRemoved(false)
29{
30 m_frameDuration = sprite->frameDuration(frame);
31 for (Cel* cel : sprite->cels(m_frame))
32 m_seq.add(new cmd::RemoveCel(cel));
33}
34
35void RemoveFrame::onExecute()
36{
37 Sprite* sprite = this->sprite();
38 Doc* doc = static_cast<Doc*>(sprite->document());
39
40 if (m_firstTime) {
41 m_firstTime = false;
42 m_seq.execute(context());
43 }
44 else
45 m_seq.redo();
46
47 int oldTotalFrames = sprite->totalFrames();
48
49 sprite->removeFrame(m_frame);
50 sprite->incrementVersion();
51
52 // True when the number of total frames changed (e.g. this can be
53 // false only then we try to delete the last frame and only frame in
54 // the sprite).
55 m_frameRemoved = (oldTotalFrames != sprite->totalFrames());
56
57 // Notify observers.
58 DocEvent ev(doc);
59 ev.sprite(sprite);
60 ev.frame(m_frame);
61 doc->notify_observers<DocEvent&>(&DocObserver::onRemoveFrame, ev);
62}
63
64void RemoveFrame::onUndo()
65{
66 Sprite* sprite = this->sprite();
67 Doc* doc = static_cast<Doc*>(sprite->document());
68
69 if (m_frameRemoved)
70 sprite->addFrame(m_frame);
71 sprite->setFrameDuration(m_frame, m_frameDuration);
72 sprite->incrementVersion();
73 m_seq.undo();
74
75 // Notify observers about the new frame.
76 DocEvent ev(doc);
77 ev.sprite(sprite);
78 ev.frame(m_frame);
79 doc->notify_observers<DocEvent&>(&DocObserver::onAddFrame, ev);
80}
81
82} // namespace cmd
83} // namespace app
84