Added Palette:sort() and SortPalette class.

Implemented "Sort" command in palette editor.
This commit is contained in:
David Capello 2010-06-14 22:53:30 -03:00
parent a5645bf577
commit ec30837631
4 changed files with 367 additions and 0 deletions

View File

@ -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="&gt;&gt;" />
<button name="remove_criteria" text="&lt;&lt;" />
</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="&amp;OK" name="ok_button" magnetic="true" width="60" />
<button text="&amp;Cancel" />
</box>
</box>
</box>
</window>
</jinete>

View File

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

View File

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

View File

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