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 #ifndef APP_UI_TIMELINE_TIMELINE_H_INCLUDED
8 #define APP_UI_TIMELINE_TIMELINE_H_INCLUDED
9 #pragma once
10 
11 #include "app/doc_observer.h"
12 #include "app/docs_observer.h"
13 #include "app/doc_range.h"
14 #include "app/loop_tag.h"
15 #include "app/pref/preferences.h"
16 #include "app/ui/editor/editor_observer.h"
17 #include "app/ui/input_chain_element.h"
18 #include "app/ui/timeline/ani_controls.h"
19 #include "doc/frame.h"
20 #include "doc/layer.h"
21 #include "doc/selected_frames.h"
22 #include "doc/selected_layers.h"
23 #include "doc/sprite.h"
24 #include "obs/connection.h"
25 #include "ui/scroll_bar.h"
26 #include "ui/timer.h"
27 #include "ui/widget.h"
28 
29 #include <vector>
30 
31 namespace doc {
32   class Cel;
33   class Layer;
34   class LayerImage;
35   class Sprite;
36 }
37 
38 namespace ui {
39   class Graphics;
40 }
41 
42 namespace app {
43 
44   namespace skin {
45     class SkinTheme;
46   }
47 
48   using namespace doc;
49 
50   class CommandExecutionEvent;
51   class ConfigureTimelinePopup;
52   class Context;
53   class Doc;
54   class Editor;
55 
56   class Timeline : public ui::Widget,
57                    public ui::ScrollableViewDelegate,
58                    public ContextObserver,
59                    public DocsObserver,
60                    public DocObserver,
61                    public EditorObserver,
62                    public InputChainElement,
63                    public FrameTagProvider {
64   public:
65     typedef DocRange Range;
66 
67     enum State {
68       STATE_STANDBY,
69       STATE_SCROLLING,
70       STATE_SELECTING_LAYERS,
71       STATE_SELECTING_FRAMES,
72       STATE_SELECTING_CELS,
73       STATE_MOVING_SEPARATOR,
74       STATE_MOVING_RANGE,
75       STATE_MOVING_ONIONSKIN_RANGE_LEFT,
76       STATE_MOVING_ONIONSKIN_RANGE_RIGHT,
77       // Changing layers flags states
78       STATE_SHOWING_LAYERS,
79       STATE_HIDING_LAYERS,
80       STATE_LOCKING_LAYERS,
81       STATE_UNLOCKING_LAYERS,
82       STATE_ENABLING_CONTINUOUS_LAYERS,
83       STATE_DISABLING_CONTINUOUS_LAYERS,
84       STATE_EXPANDING_LAYERS,
85       STATE_COLLAPSING_LAYERS,
86     };
87 
88     enum DropOp { kMove, kCopy };
89 
90     Timeline();
91     ~Timeline();
92 
93     void updateUsingEditor(Editor* editor);
94 
sprite()95     Sprite* sprite() { return m_sprite; }
getLayer()96     Layer* getLayer() { return m_layer; }
getFrame()97     frame_t getFrame() { return m_frame; }
98 
getState()99     State getState() const { return m_state; }
100     bool isMovingCel() const;
101 
range()102     Range range() const { return m_range; }
selectedLayers()103     const SelectedLayers& selectedLayers() const { return m_range.selectedLayers(); }
selectedFrames()104     const SelectedFrames& selectedFrames() const { return m_range.selectedFrames(); }
105 
106     void prepareToMoveRange();
107     void moveRange(const Range& range);
108     void setRange(const Range& range);
109 
110     void activateClipboardRange();
111 
112     // Drag-and-drop operations. These actions are used by commands
113     // called from popup menus.
114     void dropRange(DropOp op);
115 
116     // FrameTagProvider impl
117     // Returns the active frame tag depending on the timeline status
118     // E.g. if other frame tags are collapsed, the focused band has
119     // priority and tags in other bands are ignored.
120     FrameTag* getFrameTagByFrame(const frame_t frame,
121                                  const bool getLoopTagIfNone) override;
122 
123     // ScrollableViewDelegate impl
124     gfx::Size visibleSize() const override;
125     gfx::Point viewScroll() const override;
126     void setViewScroll(const gfx::Point& pt) override;
127 
128     void lockRange();
129     void unlockRange();
130 
131   protected:
132     bool onProcessMessage(ui::Message* msg) override;
133     void onInitTheme(ui::InitThemeEvent& ev) override;
134     void onInvalidateRegion(const gfx::Region& region) override;
135     void onSizeHint(ui::SizeHintEvent& ev) override;
136     void onResize(ui::ResizeEvent& ev) override;
137     void onPaint(ui::PaintEvent& ev) override;
138 
139     // DocObserver impl.
140     void onGeneralUpdate(DocEvent& ev) override;
141     void onAddLayer(DocEvent& ev) override;
142     void onAfterRemoveLayer(DocEvent& ev) override;
143     void onAddFrame(DocEvent& ev) override;
144     void onRemoveFrame(DocEvent& ev) override;
145     void onSelectionChanged(DocEvent& ev) override;
146     void onLayerNameChange(DocEvent& ev) override;
147     void onAddFrameTag(DocEvent& ev) override;
148     void onRemoveFrameTag(DocEvent& ev) override;
149 
150     // app::Context slots.
151     void onAfterCommandExecution(CommandExecutionEvent& ev);
152 
153     // ContextObserver impl
154     void onActiveSiteChange(const Site& site) override;
155 
156     // DocsObserver impl.
157     void onRemoveDocument(Doc* document) override;
158 
159     // EditorObserver impl.
160     void onStateChanged(Editor* editor) override;
161     void onAfterFrameChanged(Editor* editor) override;
162     void onAfterLayerChanged(Editor* editor) override;
163     void onDestroyEditor(Editor* editor) override;
164 
165     // InputChainElement impl
166     void onNewInputPriority(InputChainElement* element,
167                             const ui::Message* msg) override;
168     bool onCanCut(Context* ctx) override;
169     bool onCanCopy(Context* ctx) override;
170     bool onCanPaste(Context* ctx) override;
171     bool onCanClear(Context* ctx) override;
172     bool onCut(Context* ctx) override;
173     bool onCopy(Context* ctx) override;
174     bool onPaste(Context* ctx) override;
175     bool onClear(Context* ctx) override;
176     void onCancel(Context* ctx) override;
177 
178   private:
179     struct DrawCelData;
180 
181     struct Hit {
182       int part;
183       layer_t layer;
184       frame_t frame;
185       ObjectId frameTag;
186       bool veryBottom;
187       int band;
188 
189       Hit(int part = 0,
190           layer_t layer = -1,
191           frame_t frame = 0,
192           ObjectId frameTag = NullId,
193           int band = -1);
194       bool operator!=(const Hit& other) const;
195       FrameTag* getFrameTag() const;
196     };
197 
198     struct DropTarget {
199       enum HHit {
200         HNone,
201         Before,
202         After
203       };
204       enum VHit {
205         VNone,
206         Bottom,
207         Top,
208         FirstChild,
209         VeryBottom
210       };
211       DropTarget();
212       DropTarget(const DropTarget& o);
213       bool operator!=(const DropTarget& o) const {
214         return (hhit != o.hhit ||
215                 vhit != o.vhit ||
216                 outside != o.outside);
217       }
218       HHit hhit;
219       VHit vhit;
220       bool outside;
221     };
222 
223     struct Row {
224       Row();
225       Row(Layer* layer,
226           const int level,
227           const LayerFlags inheritedFlags);
228 
layerRow229       Layer* layer() const { return m_layer; }
levelRow230       int level() const { return m_level; }
231 
232       bool parentVisible() const;
233       bool parentEditable() const;
234 
235     private:
236       Layer* m_layer;
237       int m_level;
238       LayerFlags m_inheritedFlags;
239     };
240 
241     bool selectedLayersBounds(const SelectedLayers& layers,
242                               layer_t* first, layer_t* last) const;
243 
244     void setLayer(Layer* layer);
245     void setFrame(frame_t frame, bool byUser);
246     bool allLayersVisible();
247     bool allLayersInvisible();
248     bool allLayersLocked();
249     bool allLayersUnlocked();
250     bool allLayersContinuous();
251     bool allLayersDiscontinuous();
252     void detachDocument();
253     void setCursor(ui::Message* msg, const Hit& hit);
254     void getDrawableLayers(ui::Graphics* g, layer_t* firstLayer, layer_t* lastLayer);
255     void getDrawableFrames(ui::Graphics* g, frame_t* firstFrame, frame_t* lastFrame);
256     void drawPart(ui::Graphics* g, const gfx::Rect& bounds,
257                   const std::string* text,
258                   ui::Style* style,
259                   const bool is_active = false,
260                   const bool is_hover = false,
261                   const bool is_clicked = false,
262                   const bool is_disabled = false);
263     void drawTop(ui::Graphics* g);
264     void drawHeader(ui::Graphics* g);
265     void drawHeaderFrame(ui::Graphics* g, frame_t frame);
266     void drawLayer(ui::Graphics* g, layer_t layerIdx);
267     void drawCel(ui::Graphics* g, layer_t layerIdx, frame_t frame, Cel* cel, DrawCelData* data);
268     void drawCelLinkDecorators(ui::Graphics* g, const gfx::Rect& bounds,
269                                Cel* cel, frame_t frame, bool is_active, bool is_hover,
270                                DrawCelData* data);
271     void drawFrameTags(ui::Graphics* g);
272     void drawRangeOutline(ui::Graphics* g);
273     void drawPaddings(ui::Graphics* g);
274     bool drawPart(ui::Graphics* g, int part, layer_t layer, frame_t frame);
275     void drawClipboardRange(ui::Graphics* g);
276     gfx::Rect getLayerHeadersBounds() const;
277     gfx::Rect getFrameHeadersBounds() const;
278     gfx::Rect getOnionskinFramesBounds() const;
279     gfx::Rect getCelsBounds() const;
280     gfx::Rect getPartBounds(const Hit& hit) const;
281     gfx::Rect getRangeBounds(const Range& range) const;
282     gfx::Rect getRangeClipBounds(const Range& range) const;
283     void invalidateHit(const Hit& hit);
284     void invalidateLayer(const Layer* layer);
285     void invalidateFrame(const frame_t frame);
286     void invalidateRange();
287     void regenerateRows();
288     void regenerateTagBands();
289     int visibleTagBands() const;
290     void updateScrollBars();
291     void updateByMousePos(ui::Message* msg, const gfx::Point& mousePos);
292     Hit hitTest(ui::Message* msg, const gfx::Point& mousePos);
293     Hit hitTestCel(const gfx::Point& mousePos);
294     void setHot(const Hit& hit);
295     void showCel(layer_t layer, frame_t frame);
296     void showCurrentCel();
297     void focusTagBand(int band);
298     void cleanClk();
299     gfx::Size getScrollableSize() const;
300     gfx::Point getMaxScrollablePos() const;
301     layer_t getLayerIndex(const Layer* layer) const;
302     bool isLayerActive(const layer_t layerIdx) const;
303     bool isFrameActive(const frame_t frame) const;
304     bool isCelActive(const layer_t layerIdx, const frame_t frame) const;
305     bool isCelLooselyActive(const layer_t layerIdx, const frame_t frame) const;
306     void updateStatusBar(ui::Message* msg);
307     void updateStatusBarForFrame(const frame_t frame,
308                                  const FrameTag* frameTag,
309                                  const Cel* cel);
310     void updateDropRange(const gfx::Point& pt);
311     void clearClipboardRange();
312     void clearAndInvalidateRange();
313 
314     // The layer of the bottom (e.g. Background layer)
firstLayer()315     layer_t firstLayer() const { return 0; }
316     // The layer of the top.
lastLayer()317     layer_t lastLayer() const { return m_rows.size()-1; }
318 
firstFrame()319     frame_t firstFrame() const { return frame_t(0); }
lastFrame()320     frame_t lastFrame() const { return m_sprite->lastFrame(); }
321 
validLayer(layer_t layer)322     bool validLayer(layer_t layer) const { return layer >= firstLayer() && layer <= lastLayer(); }
validFrame(frame_t frame)323     bool validFrame(frame_t frame) const { return frame >= firstFrame() && frame <= lastFrame(); }
324 
325     int topHeight() const;
326 
327     DocumentPreferences& docPref() const;
328 
329     // Theme/dimensions
330     skin::SkinTheme* skinTheme() const;
331     gfx::Size celBoxSize() const;
332     int headerBoxWidth() const;
333     int headerBoxHeight() const;
334     int layerBoxHeight() const;
335     int frameBoxWidth() const;
336     int outlineWidth() const;
337     int oneTagHeight() const;
338     int calcTagVisibleToFrame(FrameTag* frameTag) const;
339 
340     void updateCelOverlayBounds(const Hit& hit);
341     void drawCelOverlay(ui::Graphics* g);
342     void onThumbnailsPrefChange();
343     void setZoom(const double zoom);
344     void setZoomAndUpdate(const double zoom,
345                           const bool updatePref);
346 
347     double zoom() const;
348     int tagFramesDuration(const FrameTag* frameTag) const;
349     // Calculate the duration of the selected range of frames
350     int selectedFramesDuration() const;
351 
352     void setLayerVisibleFlag(const layer_t layer, const bool state);
353     void setLayerEditableFlag(const layer_t layer, const bool state);
354     void setLayerContinuousFlag(const layer_t layer, const bool state);
355     void setLayerCollapsedFlag(const layer_t layer, const bool state);
356 
357     ui::ScrollBar m_hbar;
358     ui::ScrollBar m_vbar;
359     gfx::Rect m_viewportArea;
360     double m_zoom;
361     Context* m_context;
362     Editor* m_editor;
363     Doc* m_document;
364     Sprite* m_sprite;
365     Layer* m_layer;
366     frame_t m_frame;
367     int m_rangeLocks;
368     Range m_range;
369     Range m_startRange;
370     Range m_dropRange;
371     State m_state;
372 
373     // Data used to display each row in the timeline
374     std::vector<Row> m_rows;
375 
376     // Data used to display frame tags
377     int m_tagBands;
378     int m_tagFocusBand;
379     std::map<FrameTag*, int> m_tagBand;
380 
381     int m_separator_x;
382     int m_separator_w;
383     int m_origFrames;
384     Hit m_hot;       // The 'hot' part is where the mouse is on top of
385     DropTarget m_dropTarget;
386     Hit m_clk; // The 'clk' part is where the mouse's button was pressed (maybe for a drag & drop operation)
387     // Absolute mouse positions for scrolling.
388     gfx::Point m_oldPos;
389     // Configure timeline
390     ConfigureTimelinePopup* m_confPopup;
391     obs::scoped_connection m_ctxConn;
392     obs::connection m_firstFrameConn;
393 
394     // Marching ants stuff to show the range in the clipboard.
395     // TODO merge this with the marching ants of the sprite editor (ui::Editor)
396     ui::Timer m_clipboard_timer;
397     int m_offset_count;
398     bool m_redrawMarchingAntsOnly;
399 
400     bool m_scroll;   // True if the drag-and-drop operation is a scroll operation.
401     bool m_copy;     // True if the drag-and-drop operation is a copy.
402     bool m_fromTimeline;
403 
404     AniControls m_aniControls;
405 
406     // Data used for thumbnails.
407     bool m_thumbnailsOverlayVisible;
408     gfx::Rect m_thumbnailsOverlayInner;
409     gfx::Rect m_thumbnailsOverlayOuter;
410     Hit m_thumbnailsOverlayHit;
411     gfx::Point m_thumbnailsOverlayDirection;
412     obs::connection m_thumbnailsPrefConn;
413 
414     // Temporal data used to move the range.
415     struct MoveRange {
416       layer_t activeRelativeLayer;
417       frame_t activeRelativeFrame;
418     } m_moveRangeData;
419   };
420 
421   class LockTimelineRange {
422   public:
LockTimelineRange(Timeline * timeline)423     LockTimelineRange(Timeline* timeline)
424       : m_timeline(timeline) {
425       m_timeline->lockRange();
426     }
~LockTimelineRange()427     ~LockTimelineRange() {
428       m_timeline->unlockRange();
429     }
430   private:
431     Timeline* m_timeline;
432   };
433 
434 } // namespace app
435 
436 #endif
437