mirror of https://github.com/bsnes-emu/bsnes.git
196 lines
7.6 KiB
C++
Executable File
196 lines
7.6 KiB
C++
Executable File
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) {
|
|
signed selection = -1;
|
|
if(auto position = self->selection()) selection = position();
|
|
if(selection == self->listBox->selection) return;
|
|
self->listBox->selection = selection;
|
|
if(self->onChange) self->onChange();
|
|
}
|
|
|
|
static void ListBox_tick(GtkCellRendererToggle *cell, gchar *path_string, ListBox *self) {
|
|
unsigned index = strunsigned(path_string);
|
|
self->setChecked(index, !self->checked(index));
|
|
if(self->onTick) self->onTick(index);
|
|
}
|
|
|
|
void ListBox::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const string &text) {
|
|
listBox->selection = -1;
|
|
object->widget = gtk_scrolled_window_new(0, 0);
|
|
widget->parent = &parent;
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
|
|
gtk_widget_set_size_request(object->widget, width, height);
|
|
|
|
lstring list;
|
|
list.split("\t", string("\t", text));
|
|
|
|
GType *v = (GType*)malloc(list.size() * sizeof(GType));
|
|
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);
|
|
free(v);
|
|
|
|
object->subWidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(listBox->store));
|
|
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
|
|
g_object_unref(G_OBJECT(listBox->store));
|
|
|
|
for(unsigned i = 0; i < list.size(); i++) {
|
|
if(i == 0) {
|
|
listBox->column[i].renderer = gtk_cell_renderer_toggle_new();
|
|
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]);
|
|
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_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), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this);
|
|
|
|
if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
|
|
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
|
|
gtk_widget_show(object->subWidget);
|
|
gtk_widget_show(object->widget);
|
|
}
|
|
|
|
void ListBox::setFocused() {
|
|
gtk_widget_grab_focus(object->subWidget);
|
|
}
|
|
|
|
void ListBox::setHeaderVisible(bool 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) {
|
|
Widget::setFont(font);
|
|
unsigned columns = 1;
|
|
while(true) {
|
|
if(gtk_tree_view_get_column(GTK_TREE_VIEW(object->subWidget), columns) == 0) break;
|
|
columns++;
|
|
}
|
|
for(unsigned i = 0; i < columns; i++) {
|
|
gtk_widget_modify_font(listBox->column[i].label, font.font->font);
|
|
}
|
|
}
|
|
|
|
void ListBox::reset() {
|
|
listBox->selection = -1;
|
|
gtk_list_store_clear(GTK_LIST_STORE(listBox->store));
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(object->subWidget), GTK_TREE_MODEL(listBox->store));
|
|
//reset gtk_scrolled_window scrollbar position to 0,0 (top-left), as ListBox is now empty
|
|
gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(object->widget), 0);
|
|
gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(object->widget), 0);
|
|
}
|
|
|
|
void ListBox::resizeColumnsToContent() {
|
|
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(object->subWidget));
|
|
}
|
|
|
|
void ListBox::addItem(const string &text) {
|
|
lstring list;
|
|
list.split("\t", text);
|
|
GtkTreeIter iter;
|
|
gtk_list_store_append(listBox->store, &iter);
|
|
unsigned index = 1;
|
|
foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
|
|
}
|
|
|
|
void ListBox::setItem(unsigned row, const string &text) {
|
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
|
|
GtkTreeIter iter;
|
|
for(unsigned i = 0; i <= row; i++) {
|
|
if(i == 0) gtk_tree_model_get_iter_first(model, &iter);
|
|
else gtk_tree_model_iter_next(model, &iter);
|
|
}
|
|
|
|
lstring list;
|
|
list.split("\t", text);
|
|
unsigned index = 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() {
|
|
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(object->subWidget));
|
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
|
|
GtkTreeIter iter;
|
|
if(gtk_tree_model_get_iter_first(model, &iter) == false) return { false, 0 };
|
|
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return { true, 0 };
|
|
for(unsigned i = 1;; i++) {
|
|
if(gtk_tree_model_iter_next(model, &iter) == false) return { false, 0 };
|
|
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return { true, i };
|
|
}
|
|
return { false, 0 };
|
|
}
|
|
|
|
void ListBox::setSelection(unsigned row) {
|
|
signed current = -1;
|
|
if(auto position = selection()) current = position();
|
|
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(object->subWidget));
|
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
|
|
gtk_tree_selection_unselect_all(selection);
|
|
|
|
GtkTreeIter iter;
|
|
if(gtk_tree_model_get_iter_first(model, &iter) == false) return;
|
|
if(row == 0) {
|
|
gtk_tree_selection_select_iter(selection, &iter);
|
|
return;
|
|
}
|
|
for(unsigned i = 1;; i++) {
|
|
if(gtk_tree_model_iter_next(model, &iter) == false) return;
|
|
if(row == i) {
|
|
gtk_tree_selection_select_iter(selection, &iter);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
ListBox::ListBox() {
|
|
listBox = new ListBox::Data;
|
|
listBox->checkable = false;
|
|
}
|