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:
David Capello 2015-04-07 02:29:33 -03:00
parent 4fe1e9771e
commit 82c485a054
10 changed files with 84 additions and 106 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -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" />

View File

@ -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()

View File

@ -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();

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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());