Action Replay UI elements [GTK]
Goodness, was messing around with GTK to get it to all work out such a pain. Not completely happy with the scroll not expanding to fit text as is it added, but at least everything is functional.
This commit is contained in:
parent
9f18dfbb5f
commit
497b3983d3
|
@ -849,6 +849,16 @@ bool CHEATS::remove(const size_t pos)
|
|||
return didRemoveItem;
|
||||
}
|
||||
|
||||
void CHEATS::toggle(bool enabled, const size_t pos)
|
||||
{
|
||||
this->_list[pos].enabled = (enabled) ? 1 : 0;
|
||||
}
|
||||
|
||||
void CHEATS::toggle(u8 enabled, const size_t pos)
|
||||
{
|
||||
this->toggle((enabled != 0), pos);
|
||||
}
|
||||
|
||||
void CHEATS::getListReset()
|
||||
{
|
||||
this->_currentGet = 0;
|
||||
|
|
|
@ -119,6 +119,9 @@ public:
|
|||
bool update_CB(char *code, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool remove(const size_t pos);
|
||||
|
||||
void toggle(bool enabled, const size_t pos);
|
||||
void toggle(u8 enablbed, const size_t pos);
|
||||
|
||||
void getListReset();
|
||||
bool getList(CHEATS_LIST *cheat);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include "cheatsGTK.h"
|
||||
#include "cheatSystem.h"
|
||||
#include "utilsGTK.h"
|
||||
#include "main.h"
|
||||
#include "desmume.h"
|
||||
|
||||
|
@ -98,10 +99,7 @@ enabled_toggled(GtkCellRendererToggle * cell,
|
|||
|
||||
gtk_tree_model_get(store, &iter, COLUMN_INDEX, &ii, -1);
|
||||
|
||||
cheats->copyItemFromIndex(ii, tempCheatItem);
|
||||
|
||||
cheats->update(tempCheatItem.size, tempCheatItem.code[0][0], tempCheatItem.code[0][1], tempCheatItem.description,
|
||||
cheatEnabled, ii);
|
||||
cheats->toggle(cheatEnabled, ii);
|
||||
|
||||
gtk_list_store_set(GTK_LIST_STORE(store), &iter, COLUMN_ENABLED, guiEnabled, -1);
|
||||
|
||||
|
@ -159,10 +157,14 @@ static void cheat_list_modify_cheat(GtkCellRendererText * cell,
|
|||
}
|
||||
gtk_list_store_set(GTK_LIST_STORE(store), &iter, column, v, -1);
|
||||
} else if (column == COLUMN_DESC){
|
||||
cheats->update(cheat.size, cheat.code[0][0], cheat.code[0][1],
|
||||
g_strdup(new_text), cheat.enabled, ii);
|
||||
cheats->setDescription(g_strdup(new_text), ii);
|
||||
gtk_list_store_set(GTK_LIST_STORE(store), &iter, column,
|
||||
g_strdup(new_text), -1);
|
||||
} else if (column == COLUMN_AR) {
|
||||
bool isValid = cheats->update_AR(g_strdup(new_text), cheat.description, cheat.enabled, ii);
|
||||
if (isValid) {
|
||||
gtk_list_store_set(GTK_LIST_STORE(store), &iter, column, g_strdup(new_text), -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -225,7 +227,7 @@ static void cheat_list_add_cheat_AR(GtkWidget * widget, gpointer data)
|
|||
#define NEW_AR "00000000 00000000"
|
||||
GtkListStore *store = (GtkListStore *) data;
|
||||
GtkTreeIter iter;
|
||||
cheats->add_AR("00000000 00000000", g_strdup(NEW_DESC), false);
|
||||
cheats->add_AR(g_strdup(NEW_AR), g_strdup(NEW_DESC), false);
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
COLUMN_INDEX, cheats->getListSize() - 1,
|
||||
|
@ -282,7 +284,7 @@ static void cheat_list_address_to_hex(GtkTreeViewColumn * column,
|
|||
g_object_set(renderer, "text", hex_addr, NULL);
|
||||
}
|
||||
|
||||
static void cheat_list_add_columns(GtkTreeView * tree, GtkListStore * store)
|
||||
static void cheat_list_add_columns(GtkTreeView * tree, GtkListStore * store, u8 cheat_type)
|
||||
{
|
||||
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
|
||||
|
@ -300,7 +302,10 @@ static void cheat_list_add_columns(GtkTreeView * tree, GtkListStore * store)
|
|||
attrib = "active";
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
if (cheat_type == CHEAT_TYPE_INTERNAL)
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
else if (cheat_type == CHEAT_TYPE_AR)
|
||||
renderer = desmume_cell_renderer_ndtext_new();
|
||||
g_object_set(renderer, "editable", TRUE, NULL);
|
||||
g_signal_connect(renderer, "edited",
|
||||
G_CALLBACK(cheat_list_modify_cheat), model);
|
||||
|
@ -321,19 +326,25 @@ static void cheat_list_add_columns(GtkTreeView * tree, GtkListStore * store)
|
|||
attrib = "text";
|
||||
break;
|
||||
}
|
||||
gint c = columnTable[ii].column;
|
||||
column =
|
||||
gtk_tree_view_column_new_with_attributes(columnTable[ii].
|
||||
caption, renderer,
|
||||
attrib, columnTable[ii].column,
|
||||
attrib, c,
|
||||
NULL);
|
||||
if (columnTable[ii].column == COLUMN_HI) {
|
||||
gtk_tree_view_column_set_cell_data_func(column, renderer,
|
||||
cheat_list_address_to_hex,
|
||||
NULL, NULL);
|
||||
}
|
||||
g_object_set_data(G_OBJECT(renderer), "column",
|
||||
GINT_TO_POINTER(columnTable[ii].column));
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
|
||||
if (c == COLUMN_HI && cheat_type == CHEAT_TYPE_INTERNAL) {
|
||||
gtk_tree_view_column_set_cell_data_func(column, renderer,
|
||||
cheat_list_address_to_hex,
|
||||
NULL, NULL);
|
||||
}
|
||||
if (c == COLUMN_ENABLED || c == COLUMN_DESC ||
|
||||
((c == COLUMN_SIZE || c == COLUMN_HI || c == COLUMN_LO) &&
|
||||
cheat_type == CHEAT_TYPE_INTERNAL) ||
|
||||
(c == COLUMN_AR && cheat_type == CHEAT_TYPE_AR)) {
|
||||
g_object_set_data(G_OBJECT(renderer), "column",
|
||||
GINT_TO_POINTER(columnTable[ii].column));
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -356,16 +367,35 @@ static GtkListStore *cheat_list_populate()
|
|||
GtkTreeIter iter;
|
||||
cheats->copyItemFromIndex(ii, cheat);
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
COLUMN_INDEX, ii,
|
||||
COLUMN_TYPE, cheat.type,
|
||||
COLUMN_ENABLED, cheat.enabled,
|
||||
COLUMN_SIZE, cheat.size+1,
|
||||
COLUMN_AR, g_strdup("00000000 00000000"),
|
||||
COLUMN_HI, cheat.code[0][0],
|
||||
COLUMN_LO, cheat.code[0][1],
|
||||
COLUMN_DESC, cheat.description,
|
||||
-1);
|
||||
if (cheat.type == CHEAT_TYPE_INTERNAL) {
|
||||
gtk_list_store_set(store, &iter,
|
||||
COLUMN_INDEX, ii,
|
||||
COLUMN_TYPE, cheat.type,
|
||||
COLUMN_ENABLED, cheat.enabled,
|
||||
COLUMN_SIZE, cheat.size+1,
|
||||
COLUMN_HI, cheat.code[0][0],
|
||||
COLUMN_LO, cheat.code[0][1],
|
||||
COLUMN_DESC, cheat.description,
|
||||
-1);
|
||||
} else if (cheat.type == CHEAT_TYPE_AR) {
|
||||
u32 cheat_len = cheat.num;
|
||||
char *cheat_str = (char *) malloc (18*cheat_len);
|
||||
cheat_str[0] = '\0';
|
||||
|
||||
for (u32 jj = 0; jj < cheat_len; jj++) {
|
||||
gchar *tmp = g_strdup_printf("%08X %08X\n", cheat.code[jj][0], cheat.code[jj][1]);
|
||||
g_strlcat(cheat_str, tmp, 18*cheat_len);
|
||||
}
|
||||
cheat_str[18*cheat_len - 1] = '\0'; // Remove the trailing '\n'
|
||||
|
||||
gtk_list_store_set(store, &iter,
|
||||
COLUMN_INDEX, ii,
|
||||
COLUMN_TYPE, cheat.type,
|
||||
COLUMN_ENABLED, cheat.enabled,
|
||||
COLUMN_AR, g_strdup(cheat_str),
|
||||
COLUMN_DESC, cheat.description,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
@ -419,14 +449,14 @@ static void cheat_list_create_ui()
|
|||
|
||||
button = gtk_button_new_with_label("Add Action Replay cheat");
|
||||
gtk_container_add(GTK_CONTAINER(hbbox),button);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (cheat_list_add_cheat_ar), store);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (cheat_list_add_cheat_AR), store);
|
||||
|
||||
button = gtk_button_new_with_label("Remove Action Replay cheat");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (cheat_list_remove_cheat), GTK_TREE_VIEW(tree_ar));
|
||||
gtk_container_add(GTK_CONTAINER(hbbox),button);
|
||||
|
||||
cheat_list_add_columns(GTK_TREE_VIEW(tree_raw), store);
|
||||
cheat_list_add_columns(GTK_TREE_VIEW(tree_ar), store);
|
||||
cheat_list_add_columns(GTK_TREE_VIEW(tree_raw), store, CHEAT_TYPE_INTERNAL);
|
||||
cheat_list_add_columns(GTK_TREE_VIEW(tree_ar), store, CHEAT_TYPE_AR);
|
||||
|
||||
/* Setup the selection handler */
|
||||
GtkTreeSelection *select;
|
||||
|
|
|
@ -21,6 +21,7 @@ desmume_src = [
|
|||
'tools/ioregsView.cpp',
|
||||
'cheatsGTK.cpp',
|
||||
'main.cpp',
|
||||
'utilsGTK.cpp',
|
||||
gresource,
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "utilsGTK.h"
|
||||
|
||||
/*
|
||||
A C++ implementation of a GtkCellRendererText subclass which handles
|
||||
newline-delimited text and allows for editing that text with the ability
|
||||
for users to add newlines, based off of a GPLv2+ Python implementation here:
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/issues/175#note_487323
|
||||
*/
|
||||
|
||||
/*
|
||||
DESMUME_ENTRY_ND:
|
||||
An object similar to an Entry, but which allows for newlines to be
|
||||
inserted by holding Shift, Ctrl, or Alt along with pressing Enter.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *scroll;
|
||||
GtkWidget *editor;
|
||||
gboolean editing_canceled;
|
||||
} DesmumeEntryNdPrivate;
|
||||
|
||||
typedef enum {
|
||||
PROP_EDITING_CANCELED = 1,
|
||||
ENTRY_ND_NUM_PROP,
|
||||
} DesmumeEntryNdProperty;
|
||||
|
||||
static GParamSpec *entry_nd_properties[ENTRY_ND_NUM_PROP] = { NULL, };
|
||||
|
||||
// Declared here to statisfy the type creation macro, but defined further down.
|
||||
static void desmume_entry_nd_editable_init(GtkEditableInterface *iface);
|
||||
static void desmume_entry_nd_cell_editable_init(GtkCellEditableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (DesmumeEntryNd, desmume_entry_nd, GTK_TYPE_EVENT_BOX,
|
||||
G_ADD_PRIVATE (DesmumeEntryNd)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, desmume_entry_nd_editable_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE, desmume_entry_nd_cell_editable_init))
|
||||
|
||||
static void desmume_entry_nd_set_property(GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DesmumeEntryNd *entry_nd = DESMUME_ENTRY_ND (object);
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
|
||||
switch ((DesmumeEntryNdProperty) property_id) {
|
||||
case PROP_EDITING_CANCELED:
|
||||
if (priv->editing_canceled != g_value_get_boolean(value)) {
|
||||
priv->editing_canceled = g_value_get_boolean(value);
|
||||
g_object_notify(object, "editing-canceled");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_get_property(GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DesmumeEntryNd *entry_nd = DESMUME_ENTRY_ND (object);
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
|
||||
switch ((DesmumeEntryNdProperty) property_id) {
|
||||
case PROP_EDITING_CANCELED:
|
||||
g_value_set_boolean(value, priv->editing_canceled);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean desmume_entry_nd_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
||||
{
|
||||
DesmumeEntryNd *entry_nd = (DesmumeEntryNd *) data;
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
|
||||
// Allow the editor to decide how to handle the key event, except key events
|
||||
// which its parent TextView needs to handle itself
|
||||
gboolean doPropagate = GDK_EVENT_PROPAGATE;
|
||||
guint kv = event->keyval;
|
||||
guint mod = event->state;
|
||||
|
||||
if ((kv == GDK_KEY_Return || kv == GDK_KEY_KP_Enter || kv == GDK_KEY_ISO_Enter) &&
|
||||
!(mod & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK))) {
|
||||
// Enter + Ctrl, Shift, or Mod1 (commonly Alt), enter a newline in the
|
||||
// editor, but otherwise act as confirm for the TextView
|
||||
priv->editing_canceled = FALSE;
|
||||
doPropagate = GDK_EVENT_STOP;
|
||||
gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry_nd));
|
||||
// TODO: Why does GTK have to be so annoying with a critical error on valid data here? :(
|
||||
//gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry_nd));
|
||||
} else if (kv == GDK_KEY_Escape) {
|
||||
priv->editing_canceled = TRUE;
|
||||
doPropagate = GDK_EVENT_STOP;
|
||||
// gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry_nd));
|
||||
// gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry_nd));
|
||||
}
|
||||
return doPropagate;
|
||||
}
|
||||
|
||||
static gboolean desmume_entry_nd_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
|
||||
{
|
||||
GtkTextView *editor = (GtkTextView *) widget;
|
||||
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS(editor);
|
||||
klass->button_press_event(widget, event);
|
||||
// We have explicitly how to handle mouse button events, so do not propagate.
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_class_init(DesmumeEntryNdClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
object_class->set_property = desmume_entry_nd_set_property;
|
||||
object_class->get_property = desmume_entry_nd_get_property;
|
||||
|
||||
entry_nd_properties[PROP_EDITING_CANCELED] =
|
||||
g_param_spec_boolean("editing-canceled", "Editing Canceled",
|
||||
"The edit was canceled", FALSE, G_PARAM_READWRITE);
|
||||
g_object_class_install_properties (object_class, ENTRY_ND_NUM_PROP, entry_nd_properties);
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_init(DesmumeEntryNd *entry_nd)
|
||||
{
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
|
||||
priv->scroll = gtk_scrolled_window_new(NULL, NULL);
|
||||
priv->editor = gtk_text_view_new();
|
||||
gtk_text_view_set_editable(GTK_TEXT_VIEW(priv->editor), TRUE);
|
||||
gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(priv->editor), FALSE);
|
||||
|
||||
g_signal_connect (priv->editor, "key-press-event",
|
||||
G_CALLBACK (desmume_entry_nd_key_press), entry_nd);
|
||||
g_signal_connect (priv->editor, "button-press-event",
|
||||
G_CALLBACK (desmume_entry_nd_button_press), NULL);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(priv->scroll), priv->editor);
|
||||
gtk_container_add(GTK_CONTAINER(entry_nd), priv->scroll);
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_start_editing(GtkCellEditable *cell_editable, GdkEvent *event)
|
||||
{
|
||||
DesmumeEntryNd *entry_nd = DESMUME_ENTRY_ND(cell_editable);
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
|
||||
gtk_widget_show_all(GTK_WIDGET(entry_nd));
|
||||
gtk_widget_grab_focus(GTK_WIDGET(priv->editor));
|
||||
|
||||
// Highlight the entirety of the editor's text
|
||||
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->editor));
|
||||
GtkTextIter start, end;
|
||||
gtk_text_buffer_get_bounds(buf, &start, &end);
|
||||
gtk_text_buffer_select_range(buf, &start, &end);
|
||||
}
|
||||
|
||||
static gchar* desmume_entry_nd_get_text(DesmumeEntryNd *entry_nd)
|
||||
{
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->editor));
|
||||
GtkTextIter start, end;
|
||||
gtk_text_buffer_get_bounds(buf, &start, &end);
|
||||
|
||||
return gtk_text_buffer_get_text (buf, &start, &end, TRUE);
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_set_text(DesmumeEntryNd *entry_nd, const gchar* text)
|
||||
{
|
||||
DesmumeEntryNdPrivate *priv;
|
||||
priv = (DesmumeEntryNdPrivate *)desmume_entry_nd_get_instance_private(entry_nd);
|
||||
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->editor));
|
||||
gtk_text_buffer_set_text(buf, text, strlen(text));
|
||||
}
|
||||
|
||||
static void desmume_entry_nd_editable_init(GtkEditableInterface *iface) {}
|
||||
|
||||
static void desmume_entry_nd_cell_editable_init(GtkCellEditableIface *iface)
|
||||
{
|
||||
iface->start_editing = desmume_entry_nd_start_editing;
|
||||
}
|
||||
|
||||
GtkWidget *desmume_entry_nd_new()
|
||||
{
|
||||
return (GtkWidget *) g_object_new(DESMUME_TYPE_ENTRY_ND, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
DESMUME_CELL_RENDERER_ND_TEXT:
|
||||
A subclass of GtkCellRendererText which creates our DesmumeEntryNd instead
|
||||
of a GtkEntry, which allows a cell in a TreeView to accepts newlines.
|
||||
*/
|
||||
|
||||
G_DEFINE_TYPE (DesmumeCellRendererNdtext, desmume_cell_renderer_ndtext, GTK_TYPE_CELL_RENDERER_TEXT)
|
||||
|
||||
static void desmume_cell_renderer_ndtext_editing_done(GtkCellEditable *entry_nd, gpointer data)
|
||||
{
|
||||
gboolean canceled;
|
||||
g_object_get(entry_nd, "editing-canceled", &canceled, NULL);
|
||||
if (!canceled) {
|
||||
const gchar *path = (gchar *) g_object_get_data (G_OBJECT (entry_nd), "full-text");
|
||||
const gchar *new_text = desmume_entry_nd_get_text (DESMUME_ENTRY_ND(entry_nd));
|
||||
|
||||
guint signal_id = g_signal_lookup("edited", DESMUME_TYPE_CELL_RENDERER_NDTEXT);
|
||||
g_signal_emit(data, signal_id, 0, path, new_text);
|
||||
}
|
||||
gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(entry_nd));
|
||||
}
|
||||
|
||||
static GtkCellEditable *desmume_cell_renderer_ndtext_start_editing(
|
||||
GtkCellRenderer* cell, GdkEvent *event,
|
||||
GtkWidget *widget, const gchar *path,
|
||||
const GdkRectangle *background_area,
|
||||
const GdkRectangle *cell_area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
DesmumeCellRendererNdtext *ndtext = DESMUME_CELL_RENDERER_NDTEXT (cell);
|
||||
gboolean editable;
|
||||
g_object_get(G_OBJECT(ndtext), "editable" , &editable, NULL);
|
||||
if (!editable)
|
||||
return NULL;
|
||||
|
||||
gchar *text;
|
||||
g_object_get(G_OBJECT(ndtext), "text", &text, NULL);
|
||||
|
||||
GtkWidget *entry_nd = desmume_entry_nd_new();
|
||||
if (text != NULL)
|
||||
desmume_entry_nd_set_text(DESMUME_ENTRY_ND (entry_nd), text);
|
||||
g_object_set_data_full(G_OBJECT (entry_nd), "full-text", g_strdup(path), g_free);
|
||||
|
||||
g_signal_connect(entry_nd, "editing-done",
|
||||
G_CALLBACK(desmume_cell_renderer_ndtext_editing_done), ndtext);
|
||||
return GTK_CELL_EDITABLE(entry_nd);
|
||||
}
|
||||
|
||||
static void desmume_cell_renderer_ndtext_class_init(DesmumeCellRendererNdtextClass *klass) {
|
||||
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
|
||||
cell_class->start_editing = desmume_cell_renderer_ndtext_start_editing;
|
||||
}
|
||||
static void desmume_cell_renderer_ndtext_init(DesmumeCellRendererNdtext* ndtext) {}
|
||||
|
||||
GtkCellRenderer *desmume_cell_renderer_ndtext_new()
|
||||
{
|
||||
return GTK_CELL_RENDERER(g_object_new(DESMUME_TYPE_CELL_RENDERER_NDTEXT, NULL));
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __UTILS_GTK_H__
|
||||
#define __UTILS_GTK_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define DESMUME_TYPE_ENTRY_ND (desmume_entry_nd_get_type ())
|
||||
G_DECLARE_FINAL_TYPE(DesmumeEntryNd, desmume_entry_nd, DESMUME, ENTRY_ND, GtkEventBox)
|
||||
|
||||
struct _DesmumeEntryNd
|
||||
{
|
||||
GtkEventBox parent;
|
||||
};
|
||||
|
||||
struct _DesmumeEntryNdClass
|
||||
{
|
||||
GtkEventBoxClass *parent_class;
|
||||
};
|
||||
|
||||
GType desmume_entry_nd_get_type (void) G_GNUC_CONST;
|
||||
GtkEventBox *entry_nd_new(void);
|
||||
|
||||
#define DESMUME_TYPE_CELL_RENDERER_NDTEXT (desmume_cell_renderer_ndtext_get_type ())
|
||||
G_DECLARE_FINAL_TYPE(DesmumeCellRendererNdtext, desmume_cell_renderer_ndtext,
|
||||
DESMUME, CELL_RENDERER_NDTEXT, GtkCellRendererText)
|
||||
|
||||
struct _DesmumeCellRendererNdtext
|
||||
{
|
||||
GtkCellRendererText parent;
|
||||
};
|
||||
|
||||
struct _DesmumeCellRendererNdtextClass
|
||||
{
|
||||
GtkCellRendererTextClass *parent_class;
|
||||
};
|
||||
|
||||
GType desmume_cell_renderer_ndtext_get_type (void) G_GNUC_CONST;
|
||||
GtkCellRenderer *desmume_cell_renderer_ndtext_new(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /*__UTILS_GTK_H__*/
|
Loading…
Reference in New Issue