mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Some improvements to the color selection UI (#1019)
* Tab and Shift+Tab keys cycle through RGB/HSB text fields * Sliders don't get the keyboard focus (only text fields) * Up/Down keys increase/decrease the text field value
This commit is contained in:
parent
54da860a00
commit
f985e6c6c0
@ -251,10 +251,10 @@ PaletteEntryEditor::PaletteEntryEditor()
|
||||
, m_selfPalChange(false)
|
||||
, m_fromPalette(0, 0)
|
||||
{
|
||||
m_colorType.addItem("RGB");
|
||||
m_colorType.addItem("HSB");
|
||||
m_changeMode.addItem("Abs");
|
||||
m_changeMode.addItem("Rel");
|
||||
m_colorType.addItem("RGB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSB")->setFocusStop(false);
|
||||
m_changeMode.addItem("Abs")->setFocusStop(false);
|
||||
m_changeMode.addItem("Rel")->setFocusStop(false);
|
||||
|
||||
m_topBox.setBorder(gfx::Border(0));
|
||||
m_topBox.setChildSpacing(0);
|
||||
|
@ -58,11 +58,11 @@ ColorPopup::ColorPopup(bool canPin)
|
||||
, m_canPin(canPin)
|
||||
, m_disableHexUpdate(false)
|
||||
{
|
||||
m_colorType.addItem("Index");
|
||||
m_colorType.addItem("RGB");
|
||||
m_colorType.addItem("HSB");
|
||||
m_colorType.addItem("Gray");
|
||||
m_colorType.addItem("Mask");
|
||||
m_colorType.addItem("Index")->setFocusStop(false);
|
||||
m_colorType.addItem("RGB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSB")->setFocusStop(false);
|
||||
m_colorType.addItem("Gray")->setFocusStop(false);
|
||||
m_colorType.addItem("Mask")->setFocusStop(false);
|
||||
|
||||
m_topBox.setBorder(gfx::Border(0));
|
||||
m_topBox.setChildSpacing(0);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/ui/skin/skin_slider_property.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/scoped_value.h"
|
||||
#include "ui/box.h"
|
||||
#include "ui/entry.h"
|
||||
#include "ui/graphics.h"
|
||||
@ -84,26 +85,100 @@ namespace {
|
||||
|
||||
class ColorEntry : public Entry {
|
||||
public:
|
||||
ColorEntry() : Entry(4, "0") {
|
||||
ColorEntry(Slider* absSlider, Slider* relSlider)
|
||||
: Entry(4, "0")
|
||||
, m_absSlider(absSlider)
|
||||
, m_relSlider(relSlider)
|
||||
, m_recent_focus(false) {
|
||||
}
|
||||
|
||||
private:
|
||||
int minValue() const {
|
||||
if (m_absSlider->isVisible())
|
||||
return m_absSlider->getMinValue();
|
||||
else if (m_relSlider->isVisible())
|
||||
return m_relSlider->getMinValue();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maxValue() const {
|
||||
if (m_absSlider->isVisible())
|
||||
return m_absSlider->getMaxValue();
|
||||
else if (m_relSlider->isVisible())
|
||||
return m_relSlider->getMaxValue();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool onProcessMessage(Message* msg) override {
|
||||
switch (msg->type()) {
|
||||
|
||||
case kFocusEnterMessage:
|
||||
m_recent_focus = true;
|
||||
break;
|
||||
|
||||
case kKeyDownMessage:
|
||||
if (Entry::onProcessMessage(msg))
|
||||
return true;
|
||||
// Process focus movement key here because if our
|
||||
// CustomizedGuiManager catches this kKeyDownMessage it will
|
||||
// process it as a shortcut to switch the Timeline.
|
||||
else if (manager()->processFocusMovementMessage(msg))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
if (hasFocus()) {
|
||||
int scancode = static_cast<KeyMessage*>(msg)->scancode();
|
||||
|
||||
switch (scancode) {
|
||||
// Enter just remove the focus
|
||||
case kKeyEnter:
|
||||
case kKeyEnterPad:
|
||||
releaseFocus();
|
||||
return true;
|
||||
|
||||
case kKeyDown:
|
||||
case kKeyUp: {
|
||||
int value = textInt();
|
||||
if (scancode == kKeyDown)
|
||||
--value;
|
||||
else
|
||||
++value;
|
||||
|
||||
setTextf("%d", MID(minValue(), value, maxValue()));
|
||||
selectAllText();
|
||||
|
||||
onChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process focus movement key here because if our
|
||||
// CustomizedGuiManager catches this kKeyDownMessage it
|
||||
// will process it as a shortcut to switch the Timeline.
|
||||
//
|
||||
// Note: The default ui::Manager handles focus movement
|
||||
// shortcuts only for foreground windows.
|
||||
// TODO maybe that should change
|
||||
if (hasFocus() &&
|
||||
manager()->processFocusMovementMessage(msg))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return Entry::onProcessMessage(msg);
|
||||
|
||||
bool result = Entry::onProcessMessage(msg);
|
||||
|
||||
if (msg->type() == kMouseDownMessage && m_recent_focus) {
|
||||
m_recent_focus = false;
|
||||
selectAllText();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Slider* m_absSlider;
|
||||
Slider* m_relSlider;
|
||||
|
||||
// TODO remove this calling setFocus() in
|
||||
// Widget::onProcessMessage() instead of
|
||||
// Manager::handleWindowZOrder()
|
||||
bool m_recent_focus;
|
||||
};
|
||||
|
||||
}
|
||||
@ -115,6 +190,7 @@ ColorSliders::ColorSliders()
|
||||
: Widget(kGenericWidget)
|
||||
, m_grid(3, false)
|
||||
, m_mode(Absolute)
|
||||
, m_lockEntry(-1)
|
||||
{
|
||||
addChild(&m_grid);
|
||||
m_grid.setChildSpacing(0);
|
||||
@ -161,7 +237,7 @@ void ColorSliders::addSlider(Channel channel, const char* labelText, int min, in
|
||||
Label* label = new Label(labelText);
|
||||
Slider* absSlider = new Slider(min, max, 0);
|
||||
Slider* relSlider = new Slider(min-max, max-min, 0);
|
||||
Entry* entry = new ColorEntry();
|
||||
Entry* entry = new ColorEntry(absSlider, relSlider);
|
||||
|
||||
m_label.push_back(label);
|
||||
m_absSlider.push_back(absSlider);
|
||||
@ -180,6 +256,8 @@ void ColorSliders::addSlider(Channel channel, const char* labelText, int min, in
|
||||
HBox* box = new HBox();
|
||||
box->addChild(absSlider);
|
||||
box->addChild(relSlider);
|
||||
absSlider->setFocusStop(false);
|
||||
relSlider->setFocusStop(false);
|
||||
absSlider->setExpansive(true);
|
||||
relSlider->setExpansive(true);
|
||||
relSlider->setVisible(false);
|
||||
@ -218,6 +296,8 @@ void ColorSliders::onSliderChange(int i)
|
||||
|
||||
void ColorSliders::onEntryChange(int i)
|
||||
{
|
||||
base::ScopedValue<int> lock(m_lockEntry, i, m_lockEntry);
|
||||
|
||||
// Update the slider related to the changed entry widget.
|
||||
int value = m_entry[i]->textInt();
|
||||
|
||||
@ -245,10 +325,15 @@ void ColorSliders::onControlChange(int i)
|
||||
// Updates the entry related to the changed slider widget.
|
||||
void ColorSliders::updateEntryText(int entryIndex)
|
||||
{
|
||||
if (m_lockEntry == entryIndex)
|
||||
return;
|
||||
|
||||
Slider* slider = (m_mode == Absolute ? m_absSlider[entryIndex]:
|
||||
m_relSlider[entryIndex]);
|
||||
|
||||
m_entry[entryIndex]->setTextf("%d", slider->getValue());
|
||||
if (m_entry[entryIndex]->hasFocus())
|
||||
m_entry[entryIndex]->selectAllText();
|
||||
}
|
||||
|
||||
void ColorSliders::updateSlidersBgColor(const app::Color& color)
|
||||
|
@ -72,6 +72,7 @@ namespace app {
|
||||
std::vector<Channel> m_channel;
|
||||
ui::Grid m_grid;
|
||||
Mode m_mode;
|
||||
int m_lockEntry;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -14,21 +14,41 @@
|
||||
#include "app/ui/hex_color_entry.h"
|
||||
#include "base/hex.h"
|
||||
#include "gfx/border.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
|
||||
HexColorEntry::CustomEntry::CustomEntry()
|
||||
: Entry(16, "")
|
||||
{
|
||||
}
|
||||
|
||||
bool HexColorEntry::CustomEntry::onProcessMessage(ui::Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
case kMouseDownMessage:
|
||||
setFocusStop(true);
|
||||
requestFocus();
|
||||
break;
|
||||
case kFocusLeaveMessage:
|
||||
setFocusStop(false);
|
||||
break;
|
||||
}
|
||||
return Entry::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
HexColorEntry::HexColorEntry()
|
||||
: Box(HORIZONTAL)
|
||||
, m_label("#")
|
||||
, m_entry(16, "")
|
||||
{
|
||||
addChild(&m_label);
|
||||
addChild(&m_entry);
|
||||
|
||||
m_entry.Change.connect(&HexColorEntry::onEntryChange, this);
|
||||
m_entry.setFocusStop(false);
|
||||
|
||||
initTheme();
|
||||
|
||||
|
@ -30,8 +30,15 @@ namespace app {
|
||||
void onEntryChange();
|
||||
|
||||
private:
|
||||
class CustomEntry : public ui::Entry {
|
||||
public:
|
||||
CustomEntry();
|
||||
private:
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
};
|
||||
|
||||
ui::Label m_label;
|
||||
ui::Entry m_entry;
|
||||
CustomEntry m_entry;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -32,6 +32,7 @@ PopupWindowPin::PopupWindowPin(const std::string& text, ClickBehavior clickBehav
|
||||
{
|
||||
SkinTheme* theme = SkinTheme::instance();
|
||||
|
||||
m_pin.setFocusStop(false);
|
||||
m_pin.Click.connect(&PopupWindowPin::onPinClick, this);
|
||||
m_pin.setIconInterface(
|
||||
new ButtonIconImpl(theme->parts.unpinned(),
|
||||
|
@ -895,9 +895,13 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
|
||||
if (iconInterface)
|
||||
paintIcon(widget, g, iconInterface, icon.x, icon.y);
|
||||
|
||||
// draw focus
|
||||
if (look != WithoutBordersLook && widget->hasFocus())
|
||||
// Draw focus
|
||||
if (look != WithoutBordersLook &&
|
||||
(widget->hasFocus() || (iconInterface &&
|
||||
widget->text().empty() &&
|
||||
widget->hasMouseOver()))) {
|
||||
drawRect(g, bounds, parts.checkFocus().get(), gfx::ColorNone);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinTheme::paintGrid(PaintEvent& ev)
|
||||
|
Loading…
x
Reference in New Issue
Block a user