Update to v070r08 release.

byuu says:

- all three ports of phoenix gain the ability to use
  ListBox::setCheckable(), checked(row), setChecked(row, checked
  = true);
- cheat editor updated to take advantage of this

Some fun differences between the implementations. Windows was the least
flexible, it only lets you have a check at the start of each item.
Luckily that's all I need for my purposes so it'll work. It's also a lot
easier, as now I don't need a ton of extra code to try and set
per-column checkboxes. Now both Windows and Qt can put text into the
first item with the checkbox, but GTK+ cannot. Further, Qt needs this
because even if you hide the checkbox column, it still tries to search
for typed text from the checkbox column. GTK+ does this too, but unlike
GTK+, Qt lacks an API call to set the search column. Since my code
basically has to change this in real-time since you have to call the
setProperty functions after create(), this means I always set up the
checkbox columns regardless of whether or not they are used. For Qt,
I had to work around this and it'll be an annoying edge case if you try
and use setCheckable(true) and then setCheckable(false), because Qt has
no way to clear the checkboxes from an item once you've enabled them for
the first time. But without doing it this way, there's no way for eg the
ROM file loader to allow type-searching, so that's the way I do it.
Windows works the same, and GTK+ has a separate column (hidden from the
phoenix API standpoint) for the checkboxes, with no column header label
text.

All in all, a major hassle, but it was the only really major GUI hit
from leaving Qt, aside from the horror that's going to be the debugger,
which needs all kinds of highly specialized controls.
This commit is contained in:
Tim Allen
2010-10-04 16:33:49 +11:00
parent 440a59c879
commit 5286481d8d
23 changed files with 254 additions and 156 deletions

View File

@@ -166,14 +166,18 @@ struct Label : Widget {
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
void setFocused(); void setFocused();
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void setFont(Font &font); void setFont(Font &font);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const char *text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const char *text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();

View File

@@ -1,3 +1,10 @@
static void ListBox_activate(ListBox *self) {
signed selection = -1;
if(auto position = self->selection()) selection = position();
self->listBox->selection = selection;
if(self->onActivate) self->onActivate();
}
static void ListBox_change(ListBox *self) { static void ListBox_change(ListBox *self) {
signed selection = -1; signed selection = -1;
if(auto position = self->selection()) selection = position(); if(auto position = self->selection()) selection = position();
@@ -6,11 +13,10 @@ static void ListBox_change(ListBox *self) {
if(self->onChange) self->onChange(); if(self->onChange) self->onChange();
} }
static void ListBox_activate(ListBox *self) { static void ListBox_tick(GtkCellRendererToggle *cell, gchar *path_string, ListBox *self) {
signed selection = -1; unsigned index = strunsigned(path_string);
if(auto position = self->selection()) selection = position(); self->setChecked(index, !self->checked(index));
self->listBox->selection = selection; if(self->onTick) self->onTick(index);
if(self->onActivate) self->onActivate();
} }
void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) { void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text) {
@@ -22,10 +28,10 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
gtk_widget_set_size_request(object->widget, width, height); gtk_widget_set_size_request(object->widget, width, height);
lstring list; lstring list;
list.split("\t", text); list.split("\t", string("\t", text));
GType *v = (GType*)malloc(list.size() * sizeof(GType)); GType *v = (GType*)malloc(list.size() * sizeof(GType));
for(unsigned i = 0; i < list.size(); i++) v[i] = G_TYPE_STRING; for(unsigned i = 0; i < list.size(); i++) v[i] = (i == 0 ? G_TYPE_BOOLEAN : G_TYPE_STRING);
listBox->store = gtk_list_store_newv(list.size(), v); listBox->store = gtk_list_store_newv(list.size(), v);
free(v); free(v);
@@ -33,20 +39,30 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget); gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
g_object_unref(G_OBJECT(listBox->store)); g_object_unref(G_OBJECT(listBox->store));
//alternate color of each row if there is more than one column
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(object->subWidget), list.size() >= 2);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), false);
for(unsigned i = 0; i < list.size(); i++) { for(unsigned i = 0; i < list.size(); i++) {
listBox->column[i].renderer = gtk_cell_renderer_text_new(); if(i == 0) {
listBox->column[i].column = gtk_tree_view_column_new_with_attributes( listBox->column[i].renderer = gtk_cell_renderer_toggle_new();
list[i], listBox->column[i].renderer, "text", i, (void*)0 listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
); "", listBox->column[i].renderer, "active", i, (void*)0
);
gtk_tree_view_column_set_resizable(listBox->column[i].column, false);
gtk_tree_view_column_set_visible(listBox->column[i].column, listBox->checkable);
g_signal_connect(listBox->column[i].renderer, "toggled", G_CALLBACK(ListBox_tick), (gpointer)this);
} else {
listBox->column[i].renderer = gtk_cell_renderer_text_new();
listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
"", listBox->column[i].renderer, "text", i, (void*)0
);
gtk_tree_view_column_set_resizable(listBox->column[i].column, true);
}
listBox->column[i].label = gtk_label_new(list[i]); listBox->column[i].label = gtk_label_new(list[i]);
gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(listBox->column[i].column), listBox->column[i].label); gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(listBox->column[i].column), listBox->column[i].label);
gtk_tree_view_append_column(GTK_TREE_VIEW(object->subWidget), listBox->column[i].column); gtk_tree_view_append_column(GTK_TREE_VIEW(object->subWidget), listBox->column[i].column);
gtk_widget_show(listBox->column[i].label); gtk_widget_show(listBox->column[i].label);
} }
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), false);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(object->subWidget), list.size() >= 3); //>= 2 + one for the checkbox column
gtk_tree_view_set_search_column(GTK_TREE_VIEW(object->subWidget), 1);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "cursor-changed", G_CALLBACK(ListBox_change), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->subWidget), "cursor-changed", G_CALLBACK(ListBox_change), (gpointer)this);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this); g_signal_connect_swapped(G_OBJECT(object->subWidget), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this);
@@ -65,6 +81,11 @@ void ListBox::setHeaderVisible(bool visible) {
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible);
} }
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(object->subWidget) gtk_tree_view_column_set_visible(listBox->column[0].column, checkable);
}
void ListBox::setFont(Font &font) { void ListBox::setFont(Font &font) {
Widget::setFont(font); Widget::setFont(font);
unsigned columns = 1; unsigned columns = 1;
@@ -95,9 +116,8 @@ void ListBox::addItem(const char *text) {
list.split("\t", text); list.split("\t", text);
GtkTreeIter iter; GtkTreeIter iter;
gtk_list_store_append(listBox->store, &iter); gtk_list_store_append(listBox->store, &iter);
for(unsigned i = 0; i < list.size(); i++) { unsigned index = 1;
gtk_list_store_set(listBox->store, &iter, i, (const char*)list[i], -1); foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
}
} }
void ListBox::setItem(unsigned row, const char *text) { void ListBox::setItem(unsigned row, const char *text) {
@@ -110,9 +130,28 @@ void ListBox::setItem(unsigned row, const char *text) {
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) { unsigned index = 1;
gtk_list_store_set(listBox->store, &iter, i, (const char*)list[i], -1); foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
} }
bool ListBox::checked(unsigned row) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
bool state;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, 0, &state, -1);
gtk_tree_path_free(path);
return state;
}
void ListBox::setChecked(unsigned row, bool checked) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
gtk_tree_model_get_iter(model, &iter, path);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1);
gtk_tree_path_free(path);
} }
optional<unsigned> ListBox::selection() { optional<unsigned> ListBox::selection() {
@@ -152,4 +191,5 @@ void ListBox::setSelection(unsigned row) {
ListBox::ListBox() { ListBox::ListBox() {
listBox = new ListBox::Data; listBox = new ListBox::Data;
listBox->checkable = false;
} }

View File

@@ -43,6 +43,7 @@ struct ListBox::Data {
GtkWidget *label; GtkWidget *label;
}; };
linear_vector<GtkColumn> column; linear_vector<GtkColumn> column;
bool checkable;
signed selection; signed selection;
}; };

View File

@@ -16,6 +16,7 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
listBox->setAlternatingRowColors(list.size() >= 2); listBox->setAlternatingRowColors(list.size() >= 2);
listBox->connect(listBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate())); listBox->connect(listBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
listBox->connect(listBox, SIGNAL(itemSelectionChanged()), SLOT(onChange())); listBox->connect(listBox, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
listBox->connect(listBox, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
if(parent.window->defaultFont) listBox->setFont(*parent.window->defaultFont); if(parent.window->defaultFont) listBox->setFont(*parent.window->defaultFont);
listBox->show(); listBox->show();
} }
@@ -24,6 +25,14 @@ void ListBox::setHeaderVisible(bool headerVisible) {
listBox->setHeaderHidden(headerVisible == false); listBox->setHeaderHidden(headerVisible == false);
} }
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(listBox->checkable) {
auto items = listBox->findItems("", Qt::MatchContains);
for(unsigned i = 0; i < items.size(); i++) items[i]->setCheckState(0, Qt::Unchecked);
}
}
void ListBox::reset() { void ListBox::reset() {
listBox->clear(); listBox->clear();
} }
@@ -33,19 +42,36 @@ void ListBox::resizeColumnsToContent() {
} }
void ListBox::addItem(const char *text) { void ListBox::addItem(const char *text) {
object->locked = true;
auto items = listBox->findItems("", Qt::MatchContains); auto items = listBox->findItems("", Qt::MatchContains);
QTreeWidgetItem *item = new QTreeWidgetItem(listBox); QTreeWidgetItem *item = new QTreeWidgetItem(listBox);
if(listBox->checkable) item->setCheckState(0, Qt::Unchecked);
item->setData(0, Qt::UserRole, (unsigned)items.size()); item->setData(0, Qt::UserRole, (unsigned)items.size());
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]); for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]);
object->locked = false;
} }
void ListBox::setItem(unsigned row, const char *text) { void ListBox::setItem(unsigned row, const char *text) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row); QTreeWidgetItem *item = listBox->topLevelItem(row);
lstring list; lstring list;
list.split("\t", text); list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]); for(unsigned i = 0; i < list.size(); i++) item->setText(i, (const char*)list[i]);
object->locked = false;
}
bool ListBox::checked(unsigned row) {
QTreeWidgetItem *item = listBox->topLevelItem(row);
return (item ? item->checkState(0) == Qt::Checked : false);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row);
if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
object->locked = false;
} }
optional<unsigned> ListBox::selection() { optional<unsigned> ListBox::selection() {

View File

@@ -220,12 +220,16 @@ struct Label : Widget {
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const char *text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const char *text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();

View File

@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
** Meta object code from reading C++ file 'qt.moc.hpp' ** Meta object code from reading C++ file 'qt.moc.hpp'
** **
** Created: Sat Oct 2 21:32:41 2010 ** Created: Mon Oct 4 00:53:54 2010
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2) ** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2)
** **
** WARNING! All changes made in this file will be lost! ** WARNING! All changes made in this file will be lost!
@@ -641,7 +641,7 @@ static const uint qt_meta_data_ListBox__Data[] = {
4, // revision 4, // revision
0, // classname 0, // classname
0, 0, // classinfo 0, 0, // classinfo
2, 14, // methods 3, 14, // methods
0, 0, // properties 0, 0, // properties
0, 0, // enums/sets 0, 0, // enums/sets
0, 0, // constructors 0, 0, // constructors
@@ -651,12 +651,14 @@ static const uint qt_meta_data_ListBox__Data[] = {
// slots: signature, parameters, type, tag, flags // slots: signature, parameters, type, tag, flags
15, 14, 14, 14, 0x0a, 15, 14, 14, 14, 0x0a,
28, 14, 14, 14, 0x0a, 28, 14, 14, 14, 0x0a,
44, 39, 14, 14, 0x0a,
0 // eod 0 // eod
}; };
static const char qt_meta_stringdata_ListBox__Data[] = { static const char qt_meta_stringdata_ListBox__Data[] = {
"ListBox::Data\0\0onActivate()\0onChange()\0" "ListBox::Data\0\0onActivate()\0onChange()\0"
"item\0onTick(QTreeWidgetItem*)\0"
}; };
const QMetaObject ListBox::Data::staticMetaObject = { const QMetaObject ListBox::Data::staticMetaObject = {
@@ -690,9 +692,10 @@ int ListBox::Data::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
switch (_id) { switch (_id) {
case 0: onActivate(); break; case 0: onActivate(); break;
case 1: onChange(); break; case 1: onChange(); break;
case 2: onTick((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
default: ; default: ;
} }
_id -= 2; _id -= 3;
} }
return _id; return _id;
} }

View File

@@ -213,8 +213,10 @@ struct ListBox::Data : public QTreeWidget {
public: public:
ListBox &self; ListBox &self;
bool checkable;
Data(ListBox &self) : self(self) { Data(ListBox &self) : self(self) {
checkable = false;
} }
public slots: public slots:
@@ -225,6 +227,10 @@ public slots:
void onChange() { void onChange() {
if(self.object->locked == false && self.onChange) self.onChange(); if(self.object->locked == false && self.onChange) self.onChange();
} }
void onTick(QTreeWidgetItem *item) {
if(self.object->locked == false && self.onTick) self.onTick(item->data(0, Qt::UserRole).toUInt());
}
}; };
struct ProgressBar::Data : public QProgressBar { struct ProgressBar::Data : public QProgressBar {

View File

@@ -6,5 +6,5 @@ void Button::create(Window &parent, unsigned x, unsigned y, unsigned width, unsi
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }

View File

@@ -6,7 +6,7 @@ void CheckBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
bool CheckBox::checked() { bool CheckBox::checked() {

View File

@@ -7,7 +7,7 @@ void ComboBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
//CreateWindow height parameter is the height of the expanded list box; //CreateWindow height parameter is the height of the expanded list box;
//need additional code to override default ComboBox control height //need additional code to override default ComboBox control height

View File

@@ -8,7 +8,7 @@ void EditBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
); );
setText(text); setText(text);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
string EditBox::getText() { string EditBox::getText() {

View File

@@ -6,7 +6,7 @@ void Label::create(Window &parent, unsigned x, unsigned y, unsigned width, unsig
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
setText(text); setText(text);
} }

View File

@@ -7,7 +7,7 @@ void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT); ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT);
lstring list; lstring list;
@@ -34,6 +34,10 @@ void ListBox::setHeaderVisible(bool headerVisible) {
); );
} }
void ListBox::setCheckable(bool checkable) {
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT | (checkable ? LVS_EX_CHECKBOXES : 0));
}
void ListBox::reset() { void ListBox::reset() {
ListView_DeleteAllItems(widget->window); ListView_DeleteAllItems(widget->window);
} }
@@ -54,7 +58,9 @@ void ListBox::addItem(const char *text) {
item.iSubItem = 0; item.iSubItem = 0;
utf16_t wtext(list[0]); utf16_t wtext(list[0]);
item.pszText = wtext; item.pszText = wtext;
object->locked = true;
ListView_InsertItem(widget->window, &item); ListView_InsertItem(widget->window, &item);
object->locked = false;
for(unsigned i = 1; i < list.size(); i++) { for(unsigned i = 1; i < list.size(); i++) {
utf16_t wtext(list[i]); utf16_t wtext(list[i]);
ListView_SetItemText(widget->window, row, i, wtext); ListView_SetItemText(widget->window, row, i, wtext);
@@ -86,6 +92,16 @@ void ListBox::setSelection(unsigned row) {
} }
} }
bool ListBox::checked(unsigned row) {
return ListView_GetCheckState(widget->window, row);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
ListView_SetCheckState(widget->window, row, checked);
object->locked = false;
}
ListBox::ListBox() { ListBox::ListBox() {
listBox = new ListBox::Data; listBox = new ListBox::Data;
listBox->lostFocus = false; listBox->lostFocus = false;

View File

@@ -1,5 +1,5 @@
Action::Action() { Action::Action() {
os.objects.append(this); OS::os->objects.append(this);
action = new Action::Data; action = new Action::Data;
} }

View File

@@ -70,6 +70,7 @@ struct VerticalSlider::Data {
}; };
struct OS::Data { struct OS::Data {
nall::array<Object*> objects;
HFONT proportionalFont; HFONT proportionalFont;
HFONT monospaceFont; HFONT monospaceFont;
}; };
@@ -78,6 +79,7 @@ void Object::unused() {
} }
Object::Object() { Object::Object() {
OS::initialize();
static unsigned guid = 100; static unsigned guid = 100;
object = new Object::Data; object = new Object::Data;
object->id = guid++; object->id = guid++;

View File

@@ -9,7 +9,7 @@ void RadioBox::create(Window &parent, unsigned x, unsigned y, unsigned width, un
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
setChecked(); setChecked();
} }
@@ -24,7 +24,7 @@ void RadioBox::create(RadioBox &parent, unsigned x, unsigned y, unsigned width,
GetParent(radioBox->parent->widget->window), (HMENU)object->id, GetModuleHandle(0), 0 GetParent(radioBox->parent->widget->window), (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(radioBox->parentWindow->window->defaultFont ? radioBox->parentWindow->window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(radioBox->parentWindow->window->defaultFont ? radioBox->parentWindow->window->defaultFont : OS::os->proportionalFont), 0);
} }
bool RadioBox::checked() { bool RadioBox::checked() {

View File

@@ -6,7 +6,7 @@ void TextBox::create(Window &parent, unsigned x, unsigned y, unsigned width, uns
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0 parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
); );
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this); SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : os.os->proportionalFont), 0); SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->proportionalFont), 0);
} }
string TextBox::text() { string TextBox::text() {

View File

@@ -33,8 +33,8 @@ void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height
} }
Widget::Widget() { Widget::Widget() {
os.objects.append(this); OS::os->objects.append(this);
widget = new Widget::Data; widget = new Widget::Data;
widget->window = 0; widget->window = 0;
widget->font = os.os->proportionalFont; widget->font = OS::os->proportionalFont;
} }

View File

@@ -29,14 +29,72 @@ namespace phoenix {
#include "viewport.cpp" #include "viewport.cpp"
#include "messagewindow.cpp" #include "messagewindow.cpp"
OS &os = OS::handle(); OS::Data *OS::os = 0;
Window Window::None; Window Window::None;
static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM); static void OS_keyboardProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
OS& OS::handle() { void OS::initialize() {
static OS os; static bool initialized = false;
return os; if(initialized == true) return;
initialized = true;
InitCommonControls();
CoInitialize(0);
os = new OS::Data;
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
os->monospaceFont = Font_createFont("Courier New", 8, false, false);
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = OS_windowProc;
wc.lpszClassName = L"phoenix_window";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Canvas_windowProc;
wc.lpszClassName = L"phoenix_canvas";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Label_windowProc;
wc.lpszClassName = L"phoenix_label";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Viewport_windowProc;
wc.lpszClassName = L"phoenix_viewport";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
} }
bool OS::pending() { bool OS::pending() {
@@ -268,7 +326,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
unsigned id = LOWORD(wparam); unsigned id = LOWORD(wparam);
HWND control = GetDlgItem(window.widget->window, id); HWND control = GetDlgItem(window.widget->window, id);
if(control == 0) { if(control == 0) {
Object *object_ptr = (Object*)os.findObject(id); Object *object_ptr = (Object*)OS::findObject(id);
if(object_ptr) { if(object_ptr) {
if(dynamic_cast<MenuItem*>(object_ptr)) { if(dynamic_cast<MenuItem*>(object_ptr)) {
MenuItem &menuItem = (MenuItem&)*object_ptr; MenuItem &menuItem = (MenuItem&)*object_ptr;
@@ -334,8 +392,12 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
ListBox &listBox = (ListBox&)*object_ptr; ListBox &listBox = (ListBox&)*object_ptr;
LPNMHDR nmhdr = (LPNMHDR)lparam; LPNMHDR nmhdr = (LPNMHDR)lparam;
LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam; LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam;
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) { if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) { unsigned imagemask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1;
if(imagemask == 0 || imagemask == 1) {
if(listBox.object->locked == false && listBox.onTick) listBox.onTick(nmlistview->iItem);
} else if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
listBox.listBox->lostFocus = true; listBox.listBox->lostFocus = true;
} else { } else {
if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) { if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {
@@ -392,66 +454,8 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
} }
Object* OS::findObject(unsigned id) { Object* OS::findObject(unsigned id) {
foreach(object, objects) { if(object->object->id == id) return object; } foreach(object, os->objects) { if(object->object->id == id) return object; }
return 0; return 0;
} }
OS::OS() {
InitCommonControls();
CoInitialize(0);
os = new OS::Data;
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
os->monospaceFont = Font_createFont("Courier New", 8, false, false);
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = OS_windowProc;
wc.lpszClassName = L"phoenix_window";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Canvas_windowProc;
wc.lpszClassName = L"phoenix_canvas";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Label_windowProc;
wc.lpszClassName = L"phoenix_label";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Viewport_windowProc;
wc.lpszClassName = L"phoenix_viewport";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
}
} }

View File

@@ -178,12 +178,16 @@ struct Label : Widget {
struct ListBox : Widget { struct ListBox : Widget {
nall::function<void ()> onActivate; nall::function<void ()> onActivate;
nall::function<void ()> onChange; nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = ""); void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
void setHeaderVisible(bool headerVisible = true); void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void reset(); void reset();
void resizeColumnsToContent(); void resizeColumnsToContent();
void addItem(const char *text); void addItem(const char *text);
void setItem(unsigned row, const char *text); void setItem(unsigned row, const char *text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection(); nall::optional<unsigned> selection();
void setSelection(unsigned row); void setSelection(unsigned row);
ListBox(); ListBox();
@@ -254,26 +258,21 @@ struct MessageWindow : Object {
}; };
struct OS : Object { struct OS : Object {
bool pending(); static bool pending();
void run(); static void run();
void main(); static void main();
void quit(); static void quit();
unsigned desktopWidth(); static unsigned desktopWidth();
unsigned desktopHeight(); static unsigned desktopHeight();
nall::string folderSelect(Window &parent, const char *path = ""); static nall::string folderSelect(Window &parent, const char *path = "");
nall::string fileOpen(Window &parent, const char *filter, const char *path = ""); static nall::string fileOpen(Window &parent, const char *filter, const char *path = "");
nall::string fileSave(Window &parent, const char *filter, const char *path = ""); static nall::string fileSave(Window &parent, const char *filter, const char *path = "");
//private: //private:
static OS& handle(); static void initialize();
struct Data; struct Data;
Data *os; static Data *os;
Object* findObject(unsigned id); static Object* findObject(unsigned id);
nall::array<Object*> objects;
private:
OS();
friend class Object; friend class Object;
}; };
extern OS &os;
}; };

View File

@@ -1,7 +1,7 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "070.07"; static const char Version[] = "070.08";
static const unsigned SerializerVersion = 13; static const unsigned SerializerVersion = 13;
} }
} }

View File

@@ -5,10 +5,9 @@ void CheatEditor::load(string filename) {
cheatList.reset(); cheatList.reset();
for(unsigned i = 0; i < 128; i++) { for(unsigned i = 0; i < 128; i++) {
cheatList.addItem(""); cheatList.addItem("");
cheatText[i][0] = strunsigned<3, ' '>(i + 1); cheatText[i][CheatSlot] = strunsigned<3, ' '>(i + 1);
cheatText[i][1] = " "; cheatText[i][CheatCode] = "";
cheatText[i][2] = ""; cheatText[i][CheatDesc] = "";
cheatText[i][3] = "";
} }
unsigned n = 0; unsigned n = 0;
@@ -32,9 +31,8 @@ void CheatEditor::load(string filename) {
code.rtrim("+"); code.rtrim("+");
SNES::cheat[n].enabled = enabled; SNES::cheat[n].enabled = enabled;
SNES::cheat[n] = code; SNES::cheat[n] = code;
cheatText[n][1] = (enabled == false ? " " : "*"); cheatText[n][CheatCode] = code;
cheatText[n][2] = code; cheatText[n][CheatDesc] = description;
cheatText[n][3] = description;
if(++n >= 128) break; if(++n >= 128) break;
} }
} }
@@ -48,7 +46,7 @@ void CheatEditor::load(string filename) {
void CheatEditor::save(string filename) { void CheatEditor::save(string filename) {
signed lastSave = -1; signed lastSave = -1;
for(signed i = 127; i >= 0; i--) { for(signed i = 127; i >= 0; i--) {
if(cheatText[i][2] != "" || cheatText[i][3] != "") { if(cheatText[i][CheatCode] != "" || cheatText[i][CheatDesc] != "") {
lastSave = i; lastSave = i;
break; break;
} }
@@ -63,10 +61,10 @@ void CheatEditor::save(string filename) {
fp.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fp.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
fp.print(string("<cartridge sha256=\"", SNES::cartridge.sha256(), "\">\n")); fp.print(string("<cartridge sha256=\"", SNES::cartridge.sha256(), "\">\n"));
for(unsigned i = 0; i <= lastSave; i++) { for(unsigned i = 0; i <= lastSave; i++) {
fp.print(string(" <cheat enabled=\"", cheatText[i][1] == " " ? "false" : "true", "\">\n")); fp.print(string(" <cheat enabled=\"", cheatList.checked(i), "\">\n"));
fp.print(string(" <description><![CDATA[", cheatText[i][3], "]]></description>\n")); fp.print(string(" <description><![CDATA[", cheatText[i][CheatDesc], "]]></description>\n"));
lstring list; lstring list;
list.split("+", cheatText[i][2]); list.split("+", cheatText[i][CheatCode]);
foreach(code, list) { foreach(code, list) {
fp.print(string(" <code>", code, "</code>\n")); fp.print(string(" <code>", code, "</code>\n"));
} }
@@ -89,6 +87,7 @@ void CheatEditor::create() {
cheatList.create(*this, x, y, 500, 250, "Slot\tCode\tDescription"); y += 255; cheatList.create(*this, x, y, 500, 250, "Slot\tCode\tDescription"); y += 255;
cheatList.setHeaderVisible(); cheatList.setHeaderVisible();
cheatList.setCheckable();
codeLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Code(s):"); codeLabel.create(*this, x, y, 80, Style::TextBoxHeight, "Code(s):");
codeEdit.create (*this, x + 80, y, 420, Style::TextBoxHeight); y += Style::TextBoxHeight + 5; codeEdit.create (*this, x + 80, y, 420, Style::TextBoxHeight); y += Style::TextBoxHeight + 5;
@@ -102,8 +101,8 @@ void CheatEditor::create() {
setGeometry(160, 160, 510, y); setGeometry(160, 160, 510, y);
synchronize(); synchronize();
cheatList.onActivate = { &CheatEditor::toggle, this };
cheatList.onChange = { &CheatEditor::synchronize, this }; cheatList.onChange = { &CheatEditor::synchronize, this };
cheatList.onTick = { &CheatEditor::toggle, this };
codeEdit.onChange = descEdit.onChange = { &CheatEditor::bind, this }; codeEdit.onChange = descEdit.onChange = { &CheatEditor::bind, this };
clearAllButton.onTick = { &CheatEditor::clearAll, this }; clearAllButton.onTick = { &CheatEditor::clearAll, this };
clearButton.onTick = { &CheatEditor::clear, this }; clearButton.onTick = { &CheatEditor::clear, this };
@@ -112,8 +111,8 @@ void CheatEditor::create() {
void CheatEditor::synchronize() { void CheatEditor::synchronize() {
clearAllButton.setEnabled(SNES::cartridge.loaded()); clearAllButton.setEnabled(SNES::cartridge.loaded());
if(auto position = cheatList.selection()) { if(auto position = cheatList.selection()) {
codeEdit.setText(cheatText[position()][2]); codeEdit.setText(cheatText[position()][1]);
descEdit.setText(cheatText[position()][3]); descEdit.setText(cheatText[position()][2]);
codeEdit.setEnabled(true); codeEdit.setEnabled(true);
descEdit.setEnabled(true); descEdit.setEnabled(true);
clearButton.setEnabled(true); clearButton.setEnabled(true);
@@ -130,35 +129,28 @@ void CheatEditor::refresh() {
SNES::cheat.synchronize(); SNES::cheat.synchronize();
for(unsigned i = 0; i < 128; i++) { for(unsigned i = 0; i < 128; i++) {
lstring list; lstring list;
list.split("+", cheatText[i][2]); list.split("+", cheatText[i][CheatCode]);
string cheatCode = list[0]; string cheatCode = list[0];
if(list.size() > 1) cheatCode.append("..."); if(list.size() > 1) cheatCode.append("...");
cheatList.setChecked(i, SNES::cheat[i].enabled);
cheatList.setItem(i, string( cheatList.setItem(i, string(
cheatText[i][0], cheatText[i][1], "\t", cheatCode, "\t", cheatText[i][3] cheatText[i][CheatSlot], "\t", cheatCode, "\t", cheatText[i][CheatDesc]
)); ));
} }
cheatList.resizeColumnsToContent(); cheatList.resizeColumnsToContent();
} }
void CheatEditor::toggle() { void CheatEditor::toggle(unsigned row) {
if(auto position = cheatList.selection()) { SNES::cheat[row].enabled = cheatList.checked(row);
if(cheatText[position()][1] == " ") {
cheatText[position()][1] = "*";
SNES::cheat[position()].enabled = true;
} else {
cheatText[position()][1] = " ";
SNES::cheat[position()].enabled = false;
}
}
refresh(); refresh();
} }
void CheatEditor::bind() { void CheatEditor::bind() {
if(auto position = cheatList.selection()) { if(auto position = cheatList.selection()) {
cheatText[position()][2] = codeEdit.text(); cheatText[position()][CheatCode] = codeEdit.text();
cheatText[position()][3] = descEdit.text(); cheatText[position()][CheatDesc] = descEdit.text();
SNES::cheat[position()] = cheatText[position()][2]; SNES::cheat[position()] = cheatText[position()][CheatCode];
refresh(); refresh();
} }
} }
@@ -168,9 +160,9 @@ void CheatEditor::clearAll() {
for(unsigned i = 0; i < 128; i++) { for(unsigned i = 0; i < 128; i++) {
SNES::cheat[i].enabled = false; SNES::cheat[i].enabled = false;
SNES::cheat[i] = ""; SNES::cheat[i] = "";
cheatText[i][1] = " "; cheatList.setChecked(i, false);
cheatText[i][2] = ""; cheatText[i][CheatCode] = "";
cheatText[i][3] = ""; cheatText[i][CheatDesc] = "";
} }
SNES::cheat.synchronize(); SNES::cheat.synchronize();
refresh(); refresh();
@@ -183,9 +175,9 @@ void CheatEditor::clear() {
if(auto position = cheatList.selection()) { if(auto position = cheatList.selection()) {
SNES::cheat[position()].enabled = false; SNES::cheat[position()].enabled = false;
SNES::cheat[position()] = ""; SNES::cheat[position()] = "";
cheatText[position()][1] = " "; cheatList.setChecked(position(), false);
cheatText[position()][2] = ""; cheatText[position()][CheatCode] = "";
cheatText[position()][3] = ""; cheatText[position()][CheatDesc] = "";
SNES::cheat.synchronize(); SNES::cheat.synchronize();
refresh(); refresh();
codeEdit.setText(""); codeEdit.setText("");

View File

@@ -12,10 +12,11 @@ struct CheatEditor : Window {
void create(); void create();
private: private:
string cheatText[128][4]; enum : unsigned { CheatSlot, CheatCode, CheatDesc };
string cheatText[128][3];
void synchronize(); void synchronize();
void refresh(); void refresh();
void toggle(); void toggle(unsigned row);
void bind(); void bind();
void clearAll(); void clearAll();
void clear(); void clear();