mirror of
https://github.com/aseprite/aseprite.git
synced 2024-12-27 21:19:18 +00:00
StatusBar: Improve animation buttons style using a ButtonSet
Also now the play button changes to a stop button when the animation is begin played.
This commit is contained in:
parent
4fe1e9771e
commit
82c485a054
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -259,21 +259,12 @@
|
||||
<part id="mini_scrollbar_thumb" x="64" y="192" w1="3" w2="2" w3="3" h1="3" h2="2" h3="3" />
|
||||
<part id="tooltip" x="112" y="64" w1="5" w2="6" w3="5" h1="5" h2="5" h3="6" />
|
||||
<part id="tooltip_arrow" x="128" y="64" w1="5" w2="6" w3="5" h1="5" h2="5" h3="6" />
|
||||
<part id="ani_first" x="144" y="192" w="8" h="8" />
|
||||
<part id="ani_first_selected" x="144" y="200" w="8" h="8" />
|
||||
<part id="ani_first_disabled" x="144" y="192" w="8" h="8" />
|
||||
<part id="ani_previous" x="160" y="192" w="8" h="8" />
|
||||
<part id="ani_previous_selected" x="160" y="200" w="8" h="8" />
|
||||
<part id="ani_previous_disabled" x="168" y="192" w="8" h="8" />
|
||||
<part id="ani_play" x="176" y="192" w="8" h="8" />
|
||||
<part id="ani_play_selected" x="176" y="200" w="8" h="8" />
|
||||
<part id="ani_play_disabled" x="184" y="192" w="8" h="8" />
|
||||
<part id="ani_next" x="192" y="192" w="8" h="8" />
|
||||
<part id="ani_next_selected" x="192" y="200" w="8" h="8" />
|
||||
<part id="ani_next_disabled" x="200" y="192" w="8" h="8" />
|
||||
<part id="ani_last" x="208" y="192" w="8" h="8" />
|
||||
<part id="ani_last_selected" x="208" y="200" w="8" h="8" />
|
||||
<part id="ani_last_disabled" x="216" y="192" w="8" h="8" />
|
||||
<part id="ani_first" x="144" y="192" w="5" h="5" />
|
||||
<part id="ani_previous" x="152" y="192" w="5" h="5" />
|
||||
<part id="ani_play" x="160" y="192" w="5" h="5" />
|
||||
<part id="ani_stop" x="168" y="192" w="5" h="5" />
|
||||
<part id="ani_next" x="176" y="192" w="5" h="5" />
|
||||
<part id="ani_last" x="184" y="192" w="5" h="5" />
|
||||
<part id="target_one" x="144" y="224" w="32" h="16" />
|
||||
<part id="target_one_selected" x="144" y="240" w="32" h="16" />
|
||||
<part id="target_frames" x="176" y="224" w="32" h="16" />
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "app/context_access.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -60,6 +61,9 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
current_editor->stop();
|
||||
else
|
||||
current_editor->play();
|
||||
|
||||
// TODO this is an ugly hack, StatusBar should observe Editor changes
|
||||
StatusBar::instance()->updateUsingEditor(current_editor);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createPlayAnimationCommand()
|
||||
|
@ -87,7 +87,7 @@ void ButtonSet::Item::onPaint(ui::PaintEvent& ev)
|
||||
if (m_icon) {
|
||||
g->drawRgbaSurface(m_icon,
|
||||
rc.x + rc.w/2 - m_icon->width()/2,
|
||||
rc.y + rc.h/2 - m_icon->height()/2);
|
||||
rc.y + rc.h/2 - m_icon->height()/2 - 1*guiscale());
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,12 +98,16 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
|
||||
case ui::kMouseDownMessage:
|
||||
captureMouse();
|
||||
buttonSet()->setSelectedItem(this);
|
||||
buttonSet()->onItemChange();
|
||||
if (!buttonSet()->m_triggerOnMouseUp)
|
||||
buttonSet()->onItemChange();
|
||||
break;
|
||||
|
||||
case ui::kMouseUpMessage:
|
||||
if (hasCapture())
|
||||
if (hasCapture()) {
|
||||
releaseMouse();
|
||||
if (buttonSet()->m_triggerOnMouseUp)
|
||||
buttonSet()->onItemChange();
|
||||
}
|
||||
break;
|
||||
|
||||
case ui::kMouseMoveMessage:
|
||||
@ -135,6 +139,7 @@ void ButtonSet::Item::onPreferredSize(ui::PreferredSizeEvent& ev)
|
||||
ButtonSet::ButtonSet(int columns)
|
||||
: Grid(columns, false)
|
||||
, m_offerCapture(true)
|
||||
, m_triggerOnMouseUp(false)
|
||||
{
|
||||
noBorderNoChildSpacing();
|
||||
}
|
||||
@ -195,6 +200,11 @@ void ButtonSet::setOfferCapture(bool state)
|
||||
m_offerCapture = state;
|
||||
}
|
||||
|
||||
void ButtonSet::setTriggerOnMouseUp(bool state)
|
||||
{
|
||||
m_triggerOnMouseUp = state;
|
||||
}
|
||||
|
||||
void ButtonSet::onItemChange()
|
||||
{
|
||||
ItemChange();
|
||||
|
@ -42,6 +42,7 @@ namespace app {
|
||||
void deselectItems();
|
||||
|
||||
void setOfferCapture(bool state);
|
||||
void setTriggerOnMouseUp(bool state);
|
||||
|
||||
Signal0<void> ItemChange;
|
||||
|
||||
@ -52,6 +53,7 @@ namespace app {
|
||||
Item* findSelectedItem() const;
|
||||
|
||||
bool m_offerCapture;
|
||||
bool m_triggerOnMouseUp;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -114,20 +114,11 @@ namespace app {
|
||||
SKIN_PART_NESW(PART_TOOLTIP_ARROW),
|
||||
|
||||
PART_ANI_FIRST,
|
||||
PART_ANI_FIRST_SELECTED,
|
||||
PART_ANI_FIRST_DISABLED,
|
||||
PART_ANI_PREVIOUS,
|
||||
PART_ANI_PREVIOUS_SELECTED,
|
||||
PART_ANI_PREVIOUS_DISABLED,
|
||||
PART_ANI_PLAY,
|
||||
PART_ANI_PLAY_SELECTED,
|
||||
PART_ANI_PLAY_DISABLED,
|
||||
PART_ANI_STOP,
|
||||
PART_ANI_NEXT,
|
||||
PART_ANI_NEXT_SELECTED,
|
||||
PART_ANI_NEXT_DISABLED,
|
||||
PART_ANI_LAST,
|
||||
PART_ANI_LAST_SELECTED,
|
||||
PART_ANI_LAST_DISABLED,
|
||||
|
||||
PART_TARGET_ONE,
|
||||
PART_TARGET_ONE_SELECTED,
|
||||
|
@ -225,20 +225,11 @@ SkinTheme::SkinTheme()
|
||||
sheet_mapping["tooltip"] = PART_TOOLTIP_NW;
|
||||
sheet_mapping["tooltip_arrow"] = PART_TOOLTIP_ARROW_NW;
|
||||
sheet_mapping["ani_first"] = PART_ANI_FIRST;
|
||||
sheet_mapping["ani_first_selected"] = PART_ANI_FIRST_SELECTED;
|
||||
sheet_mapping["ani_first_disabled"] = PART_ANI_FIRST_DISABLED;
|
||||
sheet_mapping["ani_previous"] = PART_ANI_PREVIOUS;
|
||||
sheet_mapping["ani_previous_selected"] = PART_ANI_PREVIOUS_SELECTED;
|
||||
sheet_mapping["ani_previous_disabled"] = PART_ANI_PREVIOUS_DISABLED;
|
||||
sheet_mapping["ani_play"] = PART_ANI_PLAY;
|
||||
sheet_mapping["ani_play_selected"] = PART_ANI_PLAY_SELECTED;
|
||||
sheet_mapping["ani_play_disabled"] = PART_ANI_PLAY_DISABLED;
|
||||
sheet_mapping["ani_stop"] = PART_ANI_STOP;
|
||||
sheet_mapping["ani_next"] = PART_ANI_NEXT;
|
||||
sheet_mapping["ani_next_selected"] = PART_ANI_NEXT_SELECTED;
|
||||
sheet_mapping["ani_next_disabled"] = PART_ANI_NEXT_DISABLED;
|
||||
sheet_mapping["ani_last"] = PART_ANI_LAST;
|
||||
sheet_mapping["ani_last_selected"] = PART_ANI_LAST_SELECTED;
|
||||
sheet_mapping["ani_last_disabled"] = PART_ANI_LAST_DISABLED;
|
||||
sheet_mapping["target_one"] = PART_TARGET_ONE;
|
||||
sheet_mapping["target_one_selected"] = PART_TARGET_ONE_SELECTED;
|
||||
sheet_mapping["target_frames"] = PART_TARGET_FRAMES;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/commands/params.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_access.h"
|
||||
#include "app/document_range.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gfx.h"
|
||||
@ -20,6 +21,7 @@
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/settings/settings.h"
|
||||
#include "app/tools/tool.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/keyboard_shortcuts.h"
|
||||
@ -30,11 +32,11 @@
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/bind.h"
|
||||
#include "gfx/size.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "gfx/size.h"
|
||||
#include "she/font.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/ui.h"
|
||||
@ -90,7 +92,6 @@ private:
|
||||
};
|
||||
|
||||
static void slider_change_hook(Slider* slider);
|
||||
static void ani_button_command(Button* widget, AniAction action);
|
||||
|
||||
static WidgetType statusbar_type()
|
||||
{
|
||||
@ -153,19 +154,6 @@ StatusBar::StatusBar()
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||
setBgColor(theme->getColorById(kStatusBarFace));
|
||||
|
||||
#define BUTTON_NEW(name, text, action) \
|
||||
{ \
|
||||
(name) = new Button(text); \
|
||||
setup_mini_look(name); \
|
||||
(name)->Click.connect(Bind<void>(&ani_button_command, (name), action)); \
|
||||
}
|
||||
|
||||
#define ICON_NEW(name, icon, action) \
|
||||
{ \
|
||||
BUTTON_NEW((name), "", (action)); \
|
||||
set_gfxicon_to_button((name), icon, icon##_SELECTED, icon##_DISABLED, JI_CENTER | JI_MIDDLE); \
|
||||
}
|
||||
|
||||
this->setFocusStop(true);
|
||||
|
||||
m_timeout = 0;
|
||||
@ -191,29 +179,25 @@ StatusBar::StatusBar()
|
||||
setup_mini_look(m_currentFrame);
|
||||
setup_mini_look(m_newFrame);
|
||||
|
||||
ICON_NEW(m_b_first, PART_ANI_FIRST, ACTION_FIRST);
|
||||
ICON_NEW(m_b_prev, PART_ANI_PREVIOUS, ACTION_PREV);
|
||||
ICON_NEW(m_b_play, PART_ANI_PLAY, ACTION_PLAY);
|
||||
ICON_NEW(m_b_next, PART_ANI_NEXT, ACTION_NEXT);
|
||||
ICON_NEW(m_b_last, PART_ANI_LAST, ACTION_LAST);
|
||||
m_buttonSet = new ButtonSet(5);
|
||||
m_buttonSet->setTriggerOnMouseUp(true);
|
||||
m_buttonSet->addItem(theme->get_part(PART_ANI_FIRST));
|
||||
m_buttonSet->addItem(theme->get_part(PART_ANI_PREVIOUS));
|
||||
m_buttonSet->addItem(theme->get_part(PART_ANI_PLAY));
|
||||
m_buttonSet->addItem(theme->get_part(PART_ANI_NEXT));
|
||||
m_buttonSet->addItem(theme->get_part(PART_ANI_LAST));
|
||||
m_buttonSet->ItemChange.connect(Bind(&StatusBar::onPlayButton, this));
|
||||
|
||||
m_slider->Change.connect(Bind<void>(&slider_change_hook, m_slider));
|
||||
m_slider->setMinSize(gfx::Size(ui::display_w()/5, 0));
|
||||
|
||||
box1->setBorder(gfx::Border(2, 1, 2, 2)*guiscale());
|
||||
box2->noBorderNoChildSpacing();
|
||||
|
||||
box4->addChild(m_currentFrame);
|
||||
box4->addChild(m_newFrame);
|
||||
|
||||
box2->addChild(m_b_first);
|
||||
box2->addChild(m_b_prev);
|
||||
box2->addChild(m_b_play);
|
||||
box2->addChild(m_b_next);
|
||||
box2->addChild(m_b_last);
|
||||
|
||||
box1->addChild(box4);
|
||||
box1->addChild(box2);
|
||||
box1->addChild(m_buttonSet);
|
||||
box1->addChild(m_slider);
|
||||
|
||||
m_commandsBox = box1;
|
||||
@ -222,13 +206,10 @@ StatusBar::StatusBar()
|
||||
}
|
||||
|
||||
App::instance()->CurrentToolChange.connect(&StatusBar::onCurrentToolChange, this);
|
||||
UIContext::instance()->addObserver(this);
|
||||
}
|
||||
|
||||
StatusBar::~StatusBar()
|
||||
{
|
||||
UIContext::instance()->removeObserver(this);
|
||||
|
||||
for (Progress* bar : m_progress)
|
||||
delete bar;
|
||||
|
||||
@ -255,7 +236,7 @@ void StatusBar::clearText()
|
||||
bool StatusBar::setStatusText(int msecs, const char *format, ...)
|
||||
{
|
||||
// TODO this call should be in an observer of the "current frame" property changes.
|
||||
updateCurrentFrame();
|
||||
updateCurrentFrame(current_editor);
|
||||
|
||||
if ((ui::clock() > m_timeout) || (msecs > 0)) {
|
||||
char buf[256]; // TODO warning buffer overflow
|
||||
@ -491,10 +472,11 @@ void StatusBar::onPaint(ui::PaintEvent& ev)
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBar::onSetActiveDocument(doc::Document* document)
|
||||
void StatusBar::updateUsingEditor(Editor* editor)
|
||||
{
|
||||
updateFromDocument();
|
||||
updateCurrentFrame();
|
||||
updateFromDocument(editor);
|
||||
updateCurrentFrame(editor);
|
||||
updatePlayButton(editor);
|
||||
}
|
||||
|
||||
bool StatusBar::CustomizedTipWindow::onProcessMessage(Message* msg)
|
||||
@ -535,37 +517,39 @@ static void slider_change_hook(Slider* slider)
|
||||
}
|
||||
}
|
||||
|
||||
static void ani_button_command(Button* widget, AniAction action)
|
||||
void StatusBar::onPlayButton()
|
||||
{
|
||||
Command* cmd = NULL;
|
||||
int item = m_buttonSet->selectedItem();
|
||||
m_buttonSet->deselectItems();
|
||||
|
||||
switch (action) {
|
||||
//case ACTION_LAYER: cmd = CommandsModule::instance()->getCommandByName(CommandId::LayerProperties); break;
|
||||
Command* cmd = nullptr;
|
||||
switch (item) {
|
||||
case ACTION_FIRST: cmd = CommandsModule::instance()->getCommandByName(CommandId::GotoFirstFrame); break;
|
||||
case ACTION_PREV: cmd = CommandsModule::instance()->getCommandByName(CommandId::GotoPreviousFrame); break;
|
||||
case ACTION_PLAY: cmd = CommandsModule::instance()->getCommandByName(CommandId::PlayAnimation); break;
|
||||
case ACTION_NEXT: cmd = CommandsModule::instance()->getCommandByName(CommandId::GotoNextFrame); break;
|
||||
case ACTION_LAST: cmd = CommandsModule::instance()->getCommandByName(CommandId::GotoLastFrame); break;
|
||||
}
|
||||
|
||||
if (cmd)
|
||||
if (cmd) {
|
||||
UIContext::instance()->executeCommand(cmd);
|
||||
updatePlayButton(current_editor);
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBar::updateFromDocument()
|
||||
void StatusBar::updateFromDocument(Editor* editor)
|
||||
{
|
||||
try {
|
||||
if (UIContext::instance()->activeDocument()) {
|
||||
const ContextReader reader(UIContext::instance());
|
||||
if (editor && editor->document()) {
|
||||
const DocumentReader reader(editor->document());
|
||||
m_commandsBox->setVisible(true);
|
||||
|
||||
// Cel opacity
|
||||
const Cel* cel;
|
||||
if (reader.sprite()->supportAlpha() &&
|
||||
reader.layer() &&
|
||||
reader.layer()->isImage() &&
|
||||
!reader.layer()->isBackground() &&
|
||||
(cel = reader.cel())) {
|
||||
if (editor->sprite()->supportAlpha() &&
|
||||
editor->layer() &&
|
||||
editor->layer()->isImage() &&
|
||||
!editor->layer()->isBackground() &&
|
||||
(cel = editor->layer()->cel(editor->frame()))) {
|
||||
m_slider->setValue(MID(0, cel->opacity(), 255));
|
||||
m_slider->setEnabled(true);
|
||||
}
|
||||
@ -584,18 +568,25 @@ void StatusBar::updateFromDocument()
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBar::updateCurrentFrame()
|
||||
void StatusBar::updateCurrentFrame(Editor* editor)
|
||||
{
|
||||
DocumentLocation location = UIContext::instance()->activeLocation();
|
||||
if (location.sprite())
|
||||
m_currentFrame->setTextf("%d", location.frame()+1);
|
||||
if (editor && editor->sprite())
|
||||
m_currentFrame->setTextf("%d", editor->frame()+1);
|
||||
}
|
||||
|
||||
void StatusBar::updatePlayButton(Editor* editor)
|
||||
{
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
||||
m_buttonSet->getItem(ACTION_PLAY)->setIcon(
|
||||
theme->get_part(
|
||||
(editor && editor->isPlaying()) ? PART_ANI_STOP: PART_ANI_PLAY));
|
||||
}
|
||||
|
||||
void StatusBar::newFrame()
|
||||
{
|
||||
Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::NewFrame);
|
||||
UIContext::instance()->executeCommand(cmd);
|
||||
updateCurrentFrame();
|
||||
updateCurrentFrame(current_editor);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "app/color.h"
|
||||
#include "base/observers.h"
|
||||
#include "doc/context_observer.h"
|
||||
#include "doc/layer_index.h"
|
||||
#include "ui/base.h"
|
||||
#include "ui/link_label.h"
|
||||
@ -29,6 +28,8 @@ namespace ui {
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class ButtonSet;
|
||||
class Editor;
|
||||
class StatusBar;
|
||||
|
||||
namespace tools {
|
||||
@ -50,8 +51,7 @@ namespace app {
|
||||
double m_pos;
|
||||
};
|
||||
|
||||
class StatusBar : public ui::Widget
|
||||
, public doc::ContextObserver {
|
||||
class StatusBar : public ui::Widget {
|
||||
static StatusBar* m_instance;
|
||||
public:
|
||||
static StatusBar* instance() { return m_instance; }
|
||||
@ -66,6 +66,8 @@ namespace app {
|
||||
void showColor(int msecs, const char* text, const Color& color, int alpha);
|
||||
void showTool(int msecs, tools::Tool* tool);
|
||||
|
||||
void updateUsingEditor(Editor* editor);
|
||||
|
||||
// Methods to add and remove progress bars
|
||||
Progress* addProgress();
|
||||
void removeProgress(Progress* progress);
|
||||
@ -75,15 +77,13 @@ namespace app {
|
||||
void onPreferredSize(ui::PreferredSizeEvent& ev) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
|
||||
// ContextObserver impl
|
||||
void onSetActiveDocument(doc::Document* document) override;
|
||||
|
||||
private:
|
||||
void onCurrentToolChange();
|
||||
void updateFromDocument();
|
||||
void updateFromLayer();
|
||||
void updateCurrentFrame();
|
||||
void updateFromDocument(Editor* editor);
|
||||
void updateCurrentFrame(Editor* editor);
|
||||
void updatePlayButton(Editor* editor);
|
||||
void newFrame();
|
||||
void onPlayButton();
|
||||
|
||||
enum State { SHOW_TEXT, SHOW_COLOR, SHOW_TOOL };
|
||||
|
||||
@ -107,11 +107,7 @@ namespace app {
|
||||
ui::Slider* m_slider; // Opacity slider
|
||||
ui::Entry* m_currentFrame; // Current frame and go to frame entry
|
||||
ui::Button* m_newFrame; // Button to create a new frame
|
||||
ui::Button* m_b_first; // Go to first frame
|
||||
ui::Button* m_b_prev; // Go to previous frame
|
||||
ui::Button* m_b_play; // Play animation
|
||||
ui::Button* m_b_next; // Go to next frame
|
||||
ui::Button* m_b_last; // Go to last frame
|
||||
ButtonSet* m_buttonSet;
|
||||
|
||||
// Tip window
|
||||
class CustomizedTipWindow;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/preview_editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/ui/workspace.h"
|
||||
#include "app/ui/workspace_tabs.h"
|
||||
@ -97,6 +98,7 @@ void UIContext::setActiveView(DocumentView* docView)
|
||||
|
||||
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
||||
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
||||
StatusBar::instance()->updateUsingEditor(current_editor);
|
||||
|
||||
// Change the image-type of color bar.
|
||||
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
||||
|
Loading…
Reference in New Issue
Block a user