1// Aseprite
2// Copyright (C) 2018-2022 Igara Studio S.A.
3// Copyright (C) 2001-2017 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/ui/timeline/ani_controls.h"
13
14#include "app/commands/command.h"
15#include "app/commands/commands.h"
16#include "app/i18n/strings.h"
17#include "app/modules/editors.h"
18#include "app/ui/editor/editor.h"
19#include "app/ui/keyboard_shortcuts.h"
20#include "app/ui/skin/skin_theme.h"
21#include "app/ui_context.h"
22#include "ui/tooltips.h"
23
24#include <algorithm>
25#include <cstdarg>
26#include <cstdio>
27#include <cstring>
28
29namespace app {
30
31using namespace app::skin;
32using namespace ui;
33
34enum AniAction {
35 ACTION_FIRST,
36 ACTION_PREV,
37 ACTION_PLAY,
38 ACTION_NEXT,
39 ACTION_LAST,
40 ACTIONS
41};
42
43AniControls::AniControls(TooltipManager* tooltipManager)
44 : ButtonSet(5)
45{
46 auto theme = SkinTheme::get(this);
47
48 addItem(theme->parts.aniFirst());
49 addItem(theme->parts.aniPrevious());
50 addItem(theme->parts.aniPlay());
51 addItem(theme->parts.aniNext());
52 addItem(theme->parts.aniLast());
53 ItemChange.connect([this]{ onClickButton(); });
54
55 setTriggerOnMouseUp(true);
56 setTransparent(true);
57
58 for (int i=0; i<ACTIONS; ++i)
59 tooltipManager->addTooltipFor(getItem(i), getTooltipFor(i), BOTTOM);
60
61 getItem(ACTION_PLAY)->enableFlags(CTRL_RIGHT_CLICK);
62
63 InitTheme.connect(
64 [this]{
65 auto theme = SkinTheme::get(this);
66 setBgColor(theme->colors.workspace());
67 });
68}
69
70void AniControls::updateUsingEditor(Editor* editor)
71{
72 auto theme = SkinTheme::get(this);
73 getItem(ACTION_PLAY)->setIcon(
74 (editor && editor->isPlaying() ?
75 theme->parts.aniStop():
76 theme->parts.aniPlay()));
77}
78
79void AniControls::onClickButton()
80{
81 int item = selectedItem();
82 deselectItems();
83
84 Command* cmd = Commands::instance()->byId(getCommandId(item));
85 if (cmd) {
86 UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
87 updateUsingEditor(current_editor);
88 }
89}
90
91void AniControls::onRightClick(Item* item)
92{
93 ButtonSet::onRightClick(item);
94
95 if (item == getItem(ACTION_PLAY) && current_editor)
96 current_editor->showAnimationSpeedMultiplierPopup(
97 Preferences::instance().editor.playOnce,
98 Preferences::instance().editor.playAll, true);
99}
100
101const char* AniControls::getCommandId(int index) const
102{
103 switch (index) {
104 case ACTION_FIRST: return CommandId::GotoFirstFrame();
105 case ACTION_PREV: return CommandId::GotoPreviousFrame();
106 case ACTION_PLAY: return CommandId::PlayAnimation();
107 case ACTION_NEXT: return CommandId::GotoNextFrame();
108 case ACTION_LAST: return CommandId::GotoLastFrame();
109 }
110 ASSERT(false);
111 return nullptr;
112}
113
114std::string AniControls::getTooltipFor(int index) const
115{
116 std::string tooltip;
117
118 Command* cmd = Commands::instance()->byId(getCommandId(index));
119 if (cmd) {
120 tooltip = cmd->friendlyName();
121
122 KeyPtr key = KeyboardShortcuts::instance()->command(cmd->id().c_str());
123 if (!key || key->accels().empty())
124 key = KeyboardShortcuts::instance()->command(cmd->id().c_str(),
125 Params(),
126 KeyContext::Normal);
127 if (key && !key->accels().empty()) {
128 tooltip += "\n\n" + Strings::ani_controls_shortcut() + " ";
129 tooltip += key->accels().front().toString();
130 }
131
132 if (index == ACTION_PLAY) {
133 tooltip += "\n\n" + Strings::ani_controls_right_click();
134 }
135 }
136
137 return tooltip;
138}
139
140} // namespace app
141