Add relative mode in Palette Editor

This commit is contained in:
David Capello 2015-05-10 22:53:36 -03:00
parent 9fc7b993d4
commit 525e473fb5
4 changed files with 279 additions and 117 deletions

View File

@ -72,16 +72,21 @@ protected:
void onColorSlidersChange(ColorSlidersChangeEvent& ev);
void onColorHexEntryChange(const app::Color& color);
void onColorTypeButtonClick(Event& ev);
void onAbsoluteButtonClick(Event& ev);
void onRelativeButtonClick(Event& ev);
private:
void selectColorType(app::Color::Type type);
void setPaletteEntry(const app::Color& color);
void setPaletteEntryChannel(const app::Color& color, ColorSliders::Channel channel);
void setAbsolutePaletteEntryChannel(ColorSliders::Channel channel, const app::Color& color);
void setRelativePaletteEntryChannel(ColorSliders::Channel channel, int delta);
void setNewPalette(Palette* palette, const char* operationName);
void updateCurrentSpritePalette(const char* operationName);
void updateColorBar();
void onPalChange();
void resetRelativeInfo();
app::Color::Type m_type;
Box m_vbox;
Box m_topBox;
Box m_bottomBox;
@ -89,6 +94,8 @@ private:
RadioButton m_hsvButton;
HexColorEntry m_hexColorEntry;
Label m_entryLabel;
RadioButton m_absButton;
RadioButton m_relButton;
RgbSliders m_rgbSliders;
HsvSliders m_hsvSliders;
@ -111,6 +118,10 @@ private:
bool m_selfPalChange;
ScopedConnection m_palChangeConn;
// Palette used for relative changes.
Palette m_fromPalette;
std::map<ColorSliders::Channel, int> m_relDeltas;
};
static PaletteEntryEditor* g_window = NULL;
@ -227,17 +238,21 @@ bool PaletteEditorCommand::onChecked(Context* context)
PaletteEntryEditor::PaletteEntryEditor()
: Window(WithTitleBar, "Palette Editor (F4)")
, m_type(app::Color::MaskType)
, m_vbox(JI_VERTICAL)
, m_topBox(JI_HORIZONTAL)
, m_bottomBox(JI_HORIZONTAL)
, m_rgbButton("RGB", 1, kButtonWidget)
, m_hsvButton("HSB", 1, kButtonWidget)
, m_entryLabel("")
, m_absButton("Abs", 2, kButtonWidget)
, m_relButton("Rel", 2, kButtonWidget)
, m_disableHexUpdate(false)
, m_redrawTimer(250, this)
, m_redrawAll(false)
, m_implantChange(false)
, m_selfPalChange(false)
, m_fromPalette(0, Palette::MaxColors)
{
m_topBox.setBorder(gfx::Border(0));
m_topBox.child_spacing = 0;
@ -245,12 +260,17 @@ PaletteEntryEditor::PaletteEntryEditor()
setup_mini_look(&m_rgbButton);
setup_mini_look(&m_hsvButton);
setup_mini_look(&m_absButton);
setup_mini_look(&m_relButton);
// Top box
m_topBox.addChild(&m_rgbButton);
m_topBox.addChild(&m_hsvButton);
m_topBox.addChild(&m_hexColorEntry);
m_topBox.addChild(&m_entryLabel);
m_topBox.addChild(new BoxFiller);
m_topBox.addChild(&m_absButton);
m_topBox.addChild(&m_relButton);
// Main vertical box
m_vbox.addChild(&m_topBox);
@ -261,11 +281,14 @@ PaletteEntryEditor::PaletteEntryEditor()
m_rgbButton.Click.connect(&PaletteEntryEditor::onColorTypeButtonClick, this);
m_hsvButton.Click.connect(&PaletteEntryEditor::onColorTypeButtonClick, this);
m_absButton.Click.connect(&PaletteEntryEditor::onAbsoluteButtonClick, this);
m_relButton.Click.connect(&PaletteEntryEditor::onRelativeButtonClick, this);
m_rgbSliders.ColorChange.connect(&PaletteEntryEditor::onColorSlidersChange, this);
m_hsvSliders.ColorChange.connect(&PaletteEntryEditor::onColorSlidersChange, this);
m_hexColorEntry.ColorChange.connect(&PaletteEntryEditor::onColorHexEntryChange, this);
m_absButton.setSelected(true);
selectColorType(app::Color::RgbType);
// We hook fg/bg color changes (by eyedropper mainly) to update the selected entry color
@ -382,13 +405,19 @@ void PaletteEntryEditor::onFgBgColorChange(const app::Color& color)
{
if (color.isValid() && color.getType() == app::Color::IndexType) {
setColor(color);
resetRelativeInfo();
}
}
void PaletteEntryEditor::onColorSlidersChange(ColorSlidersChangeEvent& ev)
{
setColor(ev.getColor());
setPaletteEntryChannel(ev.getColor(), ev.getModifiedChannel());
setColor(ev.color());
if (ev.mode() == ColorSliders::Absolute)
setAbsolutePaletteEntryChannel(ev.channel(), ev.color());
else
setRelativePaletteEntryChannel(ev.channel(), ev.delta());
updateCurrentSpritePalette("Color Change");
updateColorBar();
}
@ -415,6 +444,19 @@ void PaletteEntryEditor::onColorTypeButtonClick(Event& ev)
else if (source == &m_hsvButton) selectColorType(app::Color::HsvType);
}
void PaletteEntryEditor::onAbsoluteButtonClick(Event& ev)
{
m_rgbSliders.setMode(ColorSliders::Absolute);
m_hsvSliders.setMode(ColorSliders::Absolute);
}
void PaletteEntryEditor::onRelativeButtonClick(Event& ev)
{
m_rgbSliders.setMode(ColorSliders::Relative);
m_hsvSliders.setMode(ColorSliders::Relative);
resetRelativeInfo();
}
void PaletteEntryEditor::setPaletteEntry(const app::Color& color)
{
PaletteView* palView = ColorBar::instance()->getPaletteView();
@ -432,7 +474,7 @@ void PaletteEntryEditor::setPaletteEntry(const app::Color& color)
}
}
void PaletteEntryEditor::setPaletteEntryChannel(const app::Color& color, ColorSliders::Channel channel)
void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel channel, const app::Color& color)
{
PaletteView* palView = ColorBar::instance()->getPaletteView();
PalettePicks entries;
@ -447,14 +489,16 @@ void PaletteEntryEditor::setPaletteEntryChannel(const app::Color& color, ColorSl
Palette* palette = get_current_palette();
for (int c=0; c<palette->size(); c++) {
if (entries[c]) {
if (!entries[c])
continue;
// Get the current RGB values of the palette entry
src_color = palette->getEntry(c);
r = rgba_getr(src_color);
g = rgba_getg(src_color);
b = rgba_getb(src_color);
switch (color.getType()) {
switch (m_type) {
case app::Color::RgbType:
// Modify one entry
@ -520,13 +564,75 @@ void PaletteEntryEditor::setPaletteEntryChannel(const app::Color& color, ColorSl
palette->setEntry(c, doc::rgba(r, g, b, 255));
}
}
void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel channel, int delta)
{
PaletteView* palView = ColorBar::instance()->getPaletteView();
PalettePicks entries;
palView->getSelectedEntries(entries);
// Update modified delta
m_relDeltas[channel] = delta;
uint32_t src_color;
int r, g, b;
Palette* palette = get_current_palette();
for (int c=0; c<palette->size(); c++) {
if (!entries[c])
continue;
// Get the current RGB values of the palette entry
src_color = m_fromPalette.getEntry(c);
r = rgba_getr(src_color);
g = rgba_getg(src_color);
b = rgba_getb(src_color);
switch (m_type) {
case app::Color::RgbType:
r = MID(0, r+m_relDeltas[ColorSliders::Red], 255);
g = MID(0, g+m_relDeltas[ColorSliders::Green], 255);
b = MID(0, b+m_relDeltas[ColorSliders::Blue], 255);
break;
case app::Color::HsvType: {
// Convert RGB to HSV
Hsv hsv(Rgb(r, g, b));
double h = hsv.hue()+m_relDeltas[ColorSliders::Hue];
double s = 100.0*hsv.saturation()+m_relDeltas[ColorSliders::Saturation];
double v = 100.0*hsv.value()+m_relDeltas[ColorSliders::Value];
if (h < 0.0) h += 360.0;
else if (h > 360.0) h -= 360.0;
hsv.hue (MID(0.0, h, 360.0));
hsv.saturation(MID(0.0, s, 100.0) / 100.0);
hsv.value (MID(0.0, v, 100.0) / 100.0);
// Convert HSV back to RGB
Rgb rgb(hsv);
r = rgb.red();
g = rgb.green();
b = rgb.blue();
break;
}
}
palette->setEntry(c, doc::rgba(r, g, b, 255));
}
}
void PaletteEntryEditor::selectColorType(app::Color::Type type)
{
m_type = type;
m_rgbSliders.setVisible(type == app::Color::RgbType);
m_hsvSliders.setVisible(type == app::Color::HsvType);
resetRelativeInfo();
switch (type) {
case app::Color::RgbType: m_rgbButton.setSelected(true); break;
case app::Color::HsvType: m_hsvButton.setSelected(true); break;
@ -602,11 +708,21 @@ void PaletteEntryEditor::onPalChange()
if (index >= 0)
setColor(app::Color::fromIndex(index));
resetRelativeInfo();
// Redraw the window
invalidate();
}
}
void PaletteEntryEditor::resetRelativeInfo()
{
m_rgbSliders.resetRelativeSliders();
m_hsvSliders.resetRelativeSliders();
get_current_palette()->copyColorsTo(&m_fromPalette);
m_relDeltas.clear();
}
Command* CommandFactory::createPaletteEditorCommand()
{
return new PaletteEditorCommand;

View File

@ -166,8 +166,8 @@ void ColorSelector::onPaletteViewIndexChange(int index, ui::MouseButtons buttons
void ColorSelector::onColorSlidersChange(ColorSlidersChangeEvent& ev)
{
setColorWithSignal(ev.getColor());
findBestfitIndex(ev.getColor());
setColorWithSignal(ev.color());
findBestfitIndex(ev.color());
}
void ColorSelector::onColorHexEntryChange(const app::Color& color)

View File

@ -83,6 +83,7 @@ namespace {
ColorSliders::ColorSliders()
: Widget(kGenericWidget)
, m_grid(3, false)
, m_mode(Absolute)
{
addChild(&m_grid);
}
@ -98,6 +99,26 @@ void ColorSliders::setColor(const app::Color& color)
updateSlidersBgColor(color);
}
void ColorSliders::setMode(Mode mode)
{
m_mode = mode;
for (Slider* slider : m_absSlider)
slider->setVisible(mode == Absolute);
for (Slider* slider : m_relSlider)
slider->setVisible(mode == Relative);
resetRelativeSliders();
layout();
}
void ColorSliders::resetRelativeSliders()
{
for (Slider* slider : m_relSlider)
slider->setValue(0);
}
void ColorSliders::onPreferredSize(PreferredSizeEvent& ev)
{
ev.setPreferredSize(m_grid.getPreferredSize());
@ -106,38 +127,49 @@ void ColorSliders:: onPreferredSize(PreferredSizeEvent& ev)
void ColorSliders::addSlider(Channel channel, const char* labelText, int min, int max)
{
Label* label = new Label(labelText);
Slider* slider = new Slider(min, max, 0);
Entry* entry = new Entry(3, "0");
Slider* absSlider = new Slider(min, max, 0);
Slider* relSlider = new Slider(min-max, max-min, 0);
Entry* entry = new Entry(4, "0");
m_label.push_back(label);
m_slider.push_back(slider);
m_absSlider.push_back(absSlider);
m_relSlider.push_back(relSlider);
m_entry.push_back(entry);
m_channel.push_back(channel);
slider->setProperty(SkinSliderPropertyPtr(new SkinSliderProperty(new ColorSliderBgPainter(channel))));
slider->setDoubleBuffered(true);
absSlider->setProperty(SkinSliderPropertyPtr(new SkinSliderProperty(new ColorSliderBgPainter(channel))));
absSlider->setDoubleBuffered(true);
slider->Change.connect(Bind<void>(&ColorSliders::onSliderChange, this, m_slider.size()-1));
absSlider->Change.connect(Bind<void>(&ColorSliders::onSliderChange, this, m_absSlider.size()-1));
relSlider->Change.connect(Bind<void>(&ColorSliders::onSliderChange, this, m_relSlider.size()-1));
entry->EntryChange.connect(Bind<void>(&ColorSliders::onEntryChange, this, m_entry.size()-1));
HBox* box = new HBox();
box->addChild(absSlider);
box->addChild(relSlider);
absSlider->setExpansive(true);
relSlider->setExpansive(true);
relSlider->setVisible(false);
m_grid.addChildInCell(label, 1, 1, JI_LEFT | JI_MIDDLE);
m_grid.addChildInCell(slider, 1, 1, JI_HORIZONTAL | JI_VERTICAL | JI_EXPANSIVE);
m_grid.addChildInCell(box, 1, 1, JI_HORIZONTAL | JI_VERTICAL | JI_EXPANSIVE);
m_grid.addChildInCell(entry, 1, 1, JI_LEFT | JI_MIDDLE);
}
void ColorSliders::setSliderValue(int sliderIndex, int value)
void ColorSliders::setAbsSliderValue(int sliderIndex, int value)
{
Slider* slider = m_slider[sliderIndex];
slider->setValue(value);
m_absSlider[sliderIndex]->setValue(value);
updateEntryText(sliderIndex);
}
int ColorSliders::getSliderValue(int sliderIndex) const
int ColorSliders::getAbsSliderValue(int sliderIndex) const
{
Slider* slider = m_slider[sliderIndex];
return m_absSlider[sliderIndex]->getValue();
}
return slider->getValue();
int ColorSliders::getRelSliderValue(int sliderIndex) const
{
return m_relSlider[sliderIndex]->getValue();
}
void ColorSliders::onSliderChange(int i)
@ -151,11 +183,9 @@ void ColorSliders::onEntryChange(int i)
// Update the slider related to the changed entry widget.
int value = m_entry[i]->getTextInt();
value = MID(m_slider[i]->getMinValue(),
value,
m_slider[i]->getMaxValue());
m_slider[i]->setValue(value);
Slider* slider = (m_mode == Absolute ? m_absSlider[i]: m_relSlider[i]);
value = MID(slider->getMinValue(), value, slider->getMaxValue());
slider->setValue(value);
onControlChange(i);
}
@ -169,20 +199,24 @@ void ColorSliders::onControlChange(int i)
updateSlidersBgColor(color);
// Fire ColorChange() signal
ColorSlidersChangeEvent ev(color, m_channel[i], this);
ColorSlidersChangeEvent ev(m_channel[i], m_mode,
color, m_relSlider[i]->getValue(), this);
ColorChange(ev);
}
// Updates the entry related to the changed slider widget.
void ColorSliders::updateEntryText(int entryIndex)
{
m_entry[entryIndex]->setTextf("%d", m_slider[entryIndex]->getValue());
Slider* slider = (m_mode == Absolute ? m_absSlider[entryIndex]:
m_relSlider[entryIndex]);
m_entry[entryIndex]->setTextf("%d", slider->getValue());
}
void ColorSliders::updateSlidersBgColor(const app::Color& color)
{
for (size_t i = 0; i < m_slider.size(); ++i)
updateSliderBgColor(m_slider[i], color);
for (size_t i = 0; i < m_absSlider.size(); ++i)
updateSliderBgColor(m_absSlider[i], color);
}
void ColorSliders::updateSliderBgColor(Slider* slider, const app::Color& color)
@ -207,16 +241,16 @@ RgbSliders::RgbSliders()
void RgbSliders::onSetColor(const app::Color& color)
{
setSliderValue(0, color.getRed());
setSliderValue(1, color.getGreen());
setSliderValue(2, color.getBlue());
setAbsSliderValue(0, color.getRed());
setAbsSliderValue(1, color.getGreen());
setAbsSliderValue(2, color.getBlue());
}
app::Color RgbSliders::getColorFromSliders()
{
return app::Color::fromRgb(getSliderValue(0),
getSliderValue(1),
getSliderValue(2));
return app::Color::fromRgb(getAbsSliderValue(0),
getAbsSliderValue(1),
getAbsSliderValue(2));
}
//////////////////////////////////////////////////////////////////////
@ -232,16 +266,16 @@ HsvSliders::HsvSliders()
void HsvSliders::onSetColor(const app::Color& color)
{
setSliderValue(0, color.getHue());
setSliderValue(1, color.getSaturation());
setSliderValue(2, color.getValue());
setAbsSliderValue(0, color.getHue());
setAbsSliderValue(1, color.getSaturation());
setAbsSliderValue(2, color.getValue());
}
app::Color HsvSliders::getColorFromSliders()
{
return app::Color::fromHsv(getSliderValue(0),
getSliderValue(1),
getSliderValue(2));
return app::Color::fromHsv(getAbsSliderValue(0),
getAbsSliderValue(1),
getAbsSliderValue(2));
}
//////////////////////////////////////////////////////////////////////
@ -255,13 +289,13 @@ GraySlider::GraySlider()
void GraySlider::onSetColor(const app::Color& color)
{
setSliderValue(0, color.getGray());
setAbsSliderValue(0, color.getGray());
}
app::Color GraySlider::getColorFromSliders()
{
return app::Color::fromGray(getSliderValue(0));
return app::Color::fromGray(getAbsSliderValue(0));
}
} // namespace app

View File

@ -32,11 +32,14 @@ namespace app {
enum Channel { Red, Green, Blue,
Hue, Saturation, Value,
Gray };
enum Mode { Absolute, Relative };
ColorSliders();
~ColorSliders();
void setColor(const app::Color& color);
void setMode(Mode mode);
void resetRelativeSliders();
// Signals
Signal1<void, ColorSlidersChangeEvent&> ColorChange;
@ -46,8 +49,9 @@ namespace app {
// For derived classes
void addSlider(Channel channel, const char* labelText, int min, int max);
void setSliderValue(int sliderIndex, int value);
int getSliderValue(int sliderIndex) const;
void setAbsSliderValue(int sliderIndex, int value);
int getAbsSliderValue(int sliderIndex) const;
int getRelSliderValue(int sliderIndex) const;
virtual void onSetColor(const app::Color& color) = 0;
virtual app::Color getColorFromSliders() = 0;
@ -62,17 +66,18 @@ namespace app {
void updateSliderBgColor(ui::Slider* slider, const app::Color& color);
std::vector<ui::Label*> m_label;
std::vector<ui::Slider*> m_slider;
std::vector<ui::Slider*> m_absSlider;
std::vector<ui::Slider*> m_relSlider;
std::vector<ui::Entry*> m_entry;
std::vector<Channel> m_channel;
ui::Grid m_grid;
Mode m_mode;
};
//////////////////////////////////////////////////////////////////////
// Derived-classes
class RgbSliders : public ColorSliders
{
class RgbSliders : public ColorSliders {
public:
RgbSliders();
@ -81,8 +86,7 @@ namespace app {
virtual app::Color getColorFromSliders() override;
};
class HsvSliders : public ColorSliders
{
class HsvSliders : public ColorSliders {
public:
HsvSliders();
@ -91,8 +95,7 @@ namespace app {
virtual app::Color getColorFromSliders() override;
};
class GraySlider : public ColorSliders
{
class GraySlider : public ColorSliders {
public:
GraySlider();
@ -104,21 +107,30 @@ namespace app {
//////////////////////////////////////////////////////////////////////
// Events
class ColorSlidersChangeEvent : public ui::Event
{
class ColorSlidersChangeEvent : public ui::Event {
public:
ColorSlidersChangeEvent(const app::Color& color, ColorSliders::Channel channel, ui::Component* source)
ColorSlidersChangeEvent(ColorSliders::Channel channel,
ColorSliders::Mode mode,
const app::Color& color,
int delta,
ui::Component* source)
: Event(source)
, m_channel(channel)
, m_mode(mode)
, m_color(color)
, m_channel(channel) { }
, m_delta(delta) {
}
app::Color getColor() const { return m_color; }
ColorSliders::Channel getModifiedChannel() const { return m_channel; }
ColorSliders::Channel channel() const { return m_channel; }
ColorSliders::Mode mode() const { return m_mode; }
app::Color color() const { return m_color; }
int delta() const { return m_delta; }
private:
app::Color m_color;
ColorSliders::Channel m_channel;
ColorSliders::Mode m_mode;
app::Color m_color;
int m_delta;
};
} // namespace app