mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-28 18:32:50 +00:00
Added Palette:sort() and SortPalette class.
Implemented "Sort" command in palette editor.
This commit is contained in:
parent
a5645bf577
commit
ec30837631
@ -62,4 +62,49 @@
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
|
||||
<window text="Sort Criteria" name="sort_criteria">
|
||||
<box vertical="true">
|
||||
<box horizontal="true">
|
||||
|
||||
<box vertical="true" expansive="true">
|
||||
<separator text="Available:" left="true" horizontal="true" />
|
||||
<view maxsize="true">
|
||||
<listbox name="available_criteria">
|
||||
<listitem text="RGB Red" />
|
||||
<listitem text="RGB Green" />
|
||||
<listitem text="RGB Blue" />
|
||||
<listitem text="HSV Hue" />
|
||||
<listitem text="HSV Saturation" />
|
||||
<listitem text="HSV Value" />
|
||||
</listbox>
|
||||
</view>
|
||||
<separator text="Direction:" left="true" horizontal="true" />
|
||||
<radio name="asc" text="Ascending" group="1" />
|
||||
<radio name="des" text="Descending" group="1" />
|
||||
</box>
|
||||
<box vertical="true">
|
||||
<button name="insert_criteria" text=">>" />
|
||||
<button name="remove_criteria" text="<<" />
|
||||
</box>
|
||||
<box vertical="true" expansive="true" minwidth="150">
|
||||
<separator text="Sort by:" left="true" horizontal="true" />
|
||||
<view maxsize="true" expansive="true">
|
||||
<listbox name="selected_criteria" />
|
||||
</view>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<separator horizontal="true" />
|
||||
|
||||
<box horizontal="true">
|
||||
<box horizontal="true" expansive="true" />
|
||||
<box horizontal="true" homogeneous="true">
|
||||
<button text="&OK" name="ok_button" magnetic="true" width="60" />
|
||||
<button text="&Cancel" />
|
||||
</box>
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
|
||||
</jinete>
|
||||
|
@ -403,10 +403,198 @@ static void ramp_command(JWidget widget)
|
||||
delete dst_palette;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Sort Options Begin
|
||||
|
||||
struct SortDlgData
|
||||
{
|
||||
Widget* available_criteria;
|
||||
Widget* selected_criteria;
|
||||
Widget* insert_criteria;
|
||||
Widget* remove_criteria;
|
||||
Widget* asc;
|
||||
Widget* des;
|
||||
Widget* ok_button;
|
||||
};
|
||||
|
||||
static bool insert_criteria_hook(Widget* widget, void* data);
|
||||
static bool remove_criteria_hook(Widget* widget, void* data);
|
||||
static bool sort_by_criteria(Palette* palette, JList selected_listitems);
|
||||
|
||||
static void sort_command(JWidget widget)
|
||||
{
|
||||
SortDlgData data;
|
||||
|
||||
try {
|
||||
// Load the sort criteria window
|
||||
FramePtr dlg(load_widget("palette_editor.xml", "sort_criteria"));
|
||||
|
||||
get_widgets(dlg,
|
||||
"available_criteria", &data.available_criteria,
|
||||
"selected_criteria", &data.selected_criteria,
|
||||
"insert_criteria", &data.insert_criteria,
|
||||
"remove_criteria", &data.remove_criteria,
|
||||
"asc", &data.asc,
|
||||
"des", &data.des,
|
||||
"ok_button", &data.ok_button, NULL);
|
||||
|
||||
// Selected Ascending by default
|
||||
data.asc->setSelected(true);
|
||||
|
||||
HOOK(data.insert_criteria, JI_SIGNAL_BUTTON_SELECT, insert_criteria_hook, &data);
|
||||
HOOK(data.remove_criteria, JI_SIGNAL_BUTTON_SELECT, remove_criteria_hook, &data);
|
||||
|
||||
// Select "Value" and insert it as default selected criteria
|
||||
jlistbox_select_index(data.available_criteria, 5);
|
||||
insert_criteria_hook(data.insert_criteria, (void*)&data);
|
||||
|
||||
// Open the window
|
||||
dlg->open_window_fg();
|
||||
|
||||
if (dlg->get_killer() == data.ok_button) {
|
||||
Palette* palette = new Palette(*get_current_palette());
|
||||
|
||||
sort_by_criteria(palette, data.selected_criteria->children);
|
||||
set_new_palette(palette);
|
||||
|
||||
delete palette;
|
||||
}
|
||||
}
|
||||
catch (ase_exception& e) {
|
||||
e.show();
|
||||
}
|
||||
}
|
||||
|
||||
static bool insert_criteria_hook(Widget* widget, void* _data)
|
||||
{
|
||||
SortDlgData* data = (SortDlgData*)_data;
|
||||
|
||||
// Move the selected item to the
|
||||
Widget* item = jlistbox_get_selected_child(data->available_criteria);
|
||||
if (item) {
|
||||
std::string new_criteria(item->getText());
|
||||
new_criteria += " - ";
|
||||
new_criteria += (data->asc->isSelected() ? data->asc->getText():
|
||||
data->des->getText());
|
||||
|
||||
// Remove the criteria
|
||||
int removed_index = jlistbox_get_selected_index(data->available_criteria);
|
||||
jwidget_remove_child(data->available_criteria, item);
|
||||
|
||||
int count = jlistbox_get_items_count(data->available_criteria);
|
||||
if (count > 0) {
|
||||
jlistbox_select_index(data->available_criteria,
|
||||
removed_index < count ? removed_index: count-1);
|
||||
}
|
||||
|
||||
// Add to the selected criteria
|
||||
item->setText(new_criteria.c_str());
|
||||
jwidget_add_child(data->selected_criteria, item);
|
||||
jlistbox_select_child(data->selected_criteria, item);
|
||||
|
||||
// Relayout
|
||||
data->available_criteria->setBounds(data->available_criteria->getBounds()); // TODO layout()
|
||||
data->selected_criteria->setBounds(data->selected_criteria->getBounds()); // TODO layout()
|
||||
data->available_criteria->dirty();
|
||||
data->selected_criteria->dirty();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool remove_criteria_hook(Widget* widget, void* _data)
|
||||
{
|
||||
SortDlgData* data = (SortDlgData*)_data;
|
||||
|
||||
// Move the selected item to the
|
||||
Widget* item = jlistbox_get_selected_child(data->selected_criteria);
|
||||
if (item) {
|
||||
std::string criteria_text(item->getText());
|
||||
int index = criteria_text.find('-');
|
||||
criteria_text = criteria_text.substr(0, index-1);
|
||||
|
||||
// Remove from the selected criteria
|
||||
int removed_index = jlistbox_get_selected_index(data->selected_criteria);
|
||||
jwidget_remove_child(data->selected_criteria, item);
|
||||
|
||||
int count = jlistbox_get_items_count(data->selected_criteria);
|
||||
if (count > 0) {
|
||||
jlistbox_select_index(data->selected_criteria,
|
||||
removed_index < count ? removed_index: count-1);
|
||||
}
|
||||
|
||||
// Add to the available criteria
|
||||
item->setText(criteria_text.c_str());
|
||||
jwidget_add_child(data->available_criteria, item);
|
||||
jlistbox_select_child(data->available_criteria, item);
|
||||
|
||||
// Relayout
|
||||
data->available_criteria->setBounds(data->available_criteria->getBounds()); // TODO layout()
|
||||
data->selected_criteria->setBounds(data->selected_criteria->getBounds()); // TODO layout()
|
||||
data->available_criteria->dirty();
|
||||
data->selected_criteria->dirty();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sort_by_criteria(Palette* palette, JList selected_listitems)
|
||||
{
|
||||
SortPalette* sort_palette = NULL;
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(selected_listitems, link) {
|
||||
Widget* item = (Widget*)link->data;
|
||||
std::string item_text = item->getText();
|
||||
SortPalette::Channel channel = SortPalette::HSV_Value;
|
||||
bool ascending = false;
|
||||
|
||||
if (item_text.find("RGB") != std::string::npos) {
|
||||
if (item_text.find("Red") != std::string::npos) {
|
||||
channel = SortPalette::RGB_Red;
|
||||
}
|
||||
else if (item_text.find("Green") != std::string::npos) {
|
||||
channel = SortPalette::RGB_Green;
|
||||
}
|
||||
else if (item_text.find("Blue") != std::string::npos) {
|
||||
channel = SortPalette::RGB_Blue;
|
||||
}
|
||||
}
|
||||
else if (item_text.find("HSV") != std::string::npos) {
|
||||
if (item_text.find("Hue") != std::string::npos) {
|
||||
channel = SortPalette::HSV_Hue;
|
||||
}
|
||||
else if (item_text.find("Saturation") != std::string::npos) {
|
||||
channel = SortPalette::HSV_Saturation;
|
||||
}
|
||||
else if (item_text.find("Value") != std::string::npos) {
|
||||
channel = SortPalette::HSV_Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (item_text.find("Ascending") != std::string::npos)
|
||||
ascending = true;
|
||||
else
|
||||
ascending = false;
|
||||
|
||||
SortPalette* chain = new SortPalette(channel, ascending);
|
||||
if (sort_palette)
|
||||
sort_palette->addChain(chain);
|
||||
else
|
||||
sort_palette = chain;
|
||||
}
|
||||
|
||||
if (sort_palette) {
|
||||
palette->sort(0, palette->size()-1, sort_palette);
|
||||
delete sort_palette;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sort Options End
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void quantize_command(JWidget widget)
|
||||
{
|
||||
const CurrentSpriteReader& sprite(UIContext::instance());
|
||||
|
@ -232,6 +232,114 @@ void Palette::makeRectRamp(int from, int to, int columns)
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Sort
|
||||
|
||||
SortPalette::SortPalette(Channel channel, bool ascending)
|
||||
{
|
||||
m_channel = channel;
|
||||
m_ascending = ascending;
|
||||
m_chain = NULL;
|
||||
}
|
||||
|
||||
SortPalette::~SortPalette()
|
||||
{
|
||||
delete m_chain;
|
||||
}
|
||||
|
||||
void SortPalette::addChain(SortPalette* chain)
|
||||
{
|
||||
if (m_chain)
|
||||
m_chain->addChain(chain);
|
||||
else
|
||||
m_chain = chain;
|
||||
}
|
||||
|
||||
bool SortPalette::operator()(ase_uint32 c1, ase_uint32 c2)
|
||||
{
|
||||
int value1 = 0, value2 = 0;
|
||||
|
||||
switch (m_channel) {
|
||||
|
||||
case SortPalette::RGB_Red:
|
||||
value1 = _rgba_getr(c1);
|
||||
value2 = _rgba_getr(c2);
|
||||
break;
|
||||
|
||||
case SortPalette::RGB_Green:
|
||||
value1 = _rgba_getg(c1);
|
||||
value2 = _rgba_getg(c2);
|
||||
break;
|
||||
|
||||
case SortPalette::RGB_Blue:
|
||||
value1 = _rgba_getb(c1);
|
||||
value2 = _rgba_getb(c2);
|
||||
break;
|
||||
|
||||
case SortPalette::HSV_Hue:
|
||||
case SortPalette::HSV_Saturation:
|
||||
case SortPalette::HSV_Value: {
|
||||
int h1, s1, v1;
|
||||
int h2, s2, v2;
|
||||
h1 = _rgba_getr(c1);
|
||||
s1 = _rgba_getg(c1);
|
||||
v1 = _rgba_getb(c1);
|
||||
h2 = _rgba_getr(c2);
|
||||
s2 = _rgba_getg(c2);
|
||||
v2 = _rgba_getb(c2);
|
||||
rgb_to_hsv_int(&h1, &s1, &v1);
|
||||
rgb_to_hsv_int(&h2, &s2, &v2);
|
||||
|
||||
switch (m_channel) {
|
||||
case SortPalette::HSV_Hue:
|
||||
value1 = h1;
|
||||
value2 = h2;
|
||||
break;
|
||||
case SortPalette::HSV_Saturation:
|
||||
value1 = s1;
|
||||
value2 = s2;
|
||||
break;
|
||||
case SortPalette::HSV_Value:
|
||||
value1 = v1;
|
||||
value2 = v2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!m_ascending)
|
||||
std::swap(value1, value2);
|
||||
|
||||
if (value1 < value2) {
|
||||
return true;
|
||||
}
|
||||
else if (value1 == value2) {
|
||||
if (m_chain)
|
||||
return m_chain->operator()(c1, c2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T, class Ptr>
|
||||
struct ptr_wrapper {
|
||||
Ptr* ptr;
|
||||
ptr_wrapper(Ptr* ptr) : ptr(ptr) { }
|
||||
|
||||
bool operator()(T a, T b) {
|
||||
return ptr->operator()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
void Palette::sort(int from, int to, SortPalette* sort_palette)
|
||||
{
|
||||
std::sort(m_colors.begin() + from,
|
||||
m_colors.begin() + to + 1,
|
||||
ptr_wrapper<ase_uint32, SortPalette>(sort_palette));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pal The ASE color palette to copy.
|
||||
* @param rgb An Allegro's PALETTE.
|
||||
|
@ -24,6 +24,31 @@
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
class SortPalette
|
||||
{
|
||||
public:
|
||||
enum Channel {
|
||||
RGB_Red,
|
||||
RGB_Green,
|
||||
RGB_Blue,
|
||||
HSV_Hue,
|
||||
HSV_Saturation,
|
||||
HSV_Value,
|
||||
};
|
||||
|
||||
SortPalette(Channel channel, bool ascending);
|
||||
~SortPalette();
|
||||
|
||||
void addChain(SortPalette* chain);
|
||||
|
||||
bool operator()(ase_uint32 c1, ase_uint32 c2);
|
||||
|
||||
private:
|
||||
Channel m_channel;
|
||||
bool m_ascending;
|
||||
SortPalette* m_chain;
|
||||
};
|
||||
|
||||
class Palette : public GfxObj
|
||||
{
|
||||
public:
|
||||
@ -56,6 +81,7 @@ public:
|
||||
void makeHorzRamp(int from, int to);
|
||||
void makeVertRamp(int from, int to, int columns);
|
||||
void makeRectRamp(int from, int to, int columns);
|
||||
void sort(int from, int to, SortPalette* sort_palette);
|
||||
|
||||
void toAllegro(RGB* rgb) const;
|
||||
void fromAllegro(const RGB* rgb);
|
||||
|
Loading…
x
Reference in New Issue
Block a user