tProvide Win32 implementation of GtkComboBox - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 9e973bc12da1ce013e292e240f95b9029670d591
(DIR) parent 8c7f7b642b39ac3d7dd10ec9d495787c4f3d6107
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Thu, 26 Nov 2020 22:27:14 -0800
Provide Win32 implementation of GtkComboBox
Diffstat:
M src/gtkport/gtkport.c | 141 +++++++++++++++++++------------
M src/gtkport/gtkport.h | 25 ++++++++++++++++---------
M src/gtkport/gtktypes.h | 5 ++++-
3 files changed, 107 insertions(+), 64 deletions(-)
---
(DIR) diff --git a/src/gtkport/gtkport.c b/src/gtkport/gtkport.c
t@@ -209,15 +209,16 @@ static void gtk_vpaned_set_size(GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_hpaned_set_size(GtkWidget *widget,
GtkAllocation *allocation);
-static void gtk_option_menu_size_request(GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_option_menu_set_size(GtkWidget *widget,
- GtkAllocation *allocation);
-static void gtk_option_menu_realize(GtkWidget *widget);
+static void gtk_combo_box_size_request(GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_combo_box_set_size(GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_combo_box_realize(GtkWidget *widget);
+static void gtk_combo_box_destroy(GtkWidget *widget);
static void gtk_button_set_text(GtkButton *button, gchar *text);
static void gtk_menu_item_set_text(GtkMenuItem *menuitem, gchar *text);
static void gtk_editable_create(GtkWidget *widget);
-static void gtk_option_menu_update_selection(GtkWidget *widget);
+static void gtk_combo_box_update_selection(GtkWidget *widget);
static void gtk_widget_set_focus(GtkWidget *widget);
static void gtk_widget_lose_focus(GtkWidget *widget);
static void gtk_window_update_focus(GtkWindow *window);
t@@ -435,16 +436,17 @@ static GtkClass GtkButtonClass = {
"button", &GtkWidgetClass, sizeof(GtkButton), GtkButtonSignals, NULL
};
-static GtkSignalType GtkOptionMenuSignals[] = {
- {"size_request", gtk_marshal_VOID__GPOIN, gtk_option_menu_size_request},
- {"set_size", gtk_marshal_VOID__GPOIN, gtk_option_menu_set_size},
- {"realize", gtk_marshal_VOID__VOID, gtk_option_menu_realize},
+static GtkSignalType GtkComboBoxSignals[] = {
+ {"size_request", gtk_marshal_VOID__GPOIN, gtk_combo_box_size_request},
+ {"set_size", gtk_marshal_VOID__GPOIN, gtk_combo_box_set_size},
+ {"realize", gtk_marshal_VOID__VOID, gtk_combo_box_realize},
+ {"destroy", gtk_marshal_VOID__VOID, gtk_combo_box_destroy},
{"", NULL, NULL}
};
-static GtkClass GtkOptionMenuClass = {
- "optionmenu", &GtkButtonClass, sizeof(GtkOptionMenu),
- GtkOptionMenuSignals, NULL
+static GtkClass GtkComboxBoxClass = {
+ "combobox", &GtkWidgetClass, sizeof(GtkComboBox),
+ GtkComboBoxSignals, NULL
};
static GtkSignalType GtkToggleButtonSignals[] = {
t@@ -1048,9 +1050,9 @@ static BOOL HandleWinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
retval = klass->wndproc(widget, msg, wParam, lParam, dodef);
}
- if (lParam && klass == &GtkOptionMenuClass &&
+ if (lParam && klass == &GtkComboBoxClass &&
HIWORD(wParam) == CBN_SELENDOK) {
- gtk_option_menu_update_selection(widget);
+ gtk_combo_box_update_selection(widget);
} else if (lParam && HIWORD(wParam) == BN_CLICKED) {
gtk_signal_emit(G_OBJECT(widget), "clicked");
} else
t@@ -4687,54 +4689,82 @@ void gtk_text_buffer_create_tag(GtkTextBuffer *buffer, const gchar *name, ...)
va_end(ap);
}
-GtkWidget *gtk_option_menu_new()
+GtkWidget *gtk_combo_box_new_with_model(GtkTreeModel *model)
{
- GtkOptionMenu *option_menu;
+ GtkComboBox *combo_box;
- option_menu = GTK_OPTION_MENU(GtkNewObject(&GtkOptionMenuClass));
- return GTK_WIDGET(option_menu);
+ combo_box = GTK_COMBO_BOX(GtkNewObject(&GtkComboBoxClass));
+ combo_box->active = -1;
+ combo_box->model_column = -1;
+ gtk_combo_box_set_model(combo_box, model);
+ return GTK_WIDGET(combo_box);
}
-GtkWidget *gtk_option_menu_get_menu(GtkOptionMenu *option_menu)
+void gtk_cell_layout_set_attributes(GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell, ...)
{
- return option_menu->menu;
+ const char *name;
+ va_list args;
+
+ va_start(args, cell);
+ /* Currently we only support the "text" attribute to point to the
+ ListStore column */
+ while ((name = va_arg(args, const char *)) != NULL) {
+ if (strcmp(name, "text") == 0) {
+ cell_layout->model_column = va_arg(args, int);
+ }
+ }
+ va_end(args);
}
-void gtk_option_menu_set_menu(GtkOptionMenu *option_menu, GtkWidget *menu)
+void gtk_combo_box_set_model(GtkComboBox *combo_box, GtkTreeModel *model)
{
- GSList *list;
- GtkMenuItem *menu_item;
HWND hWnd;
- if (!menu)
+ if (!model)
return;
- option_menu->menu = menu;
- hWnd = GTK_WIDGET(option_menu)->hWnd;
+ combo_box->model = model;
+ hWnd = GTK_WIDGET(combo_box)->hWnd;
+ /* For now we work only with a single column of string type */
if (hWnd) {
mySendMessage(hWnd, CB_RESETCONTENT, 0, 0);
- for (list = GTK_MENU_SHELL(menu)->children; list;
- list = g_slist_next(list)) {
- menu_item = GTK_MENU_ITEM(list->data);
- if (menu_item && menu_item->text) {
- myComboBox_AddString(hWnd, menu_item->text);
- }
+ }
+ if (hWnd && combo_box->model_column >= 0) {
+ int nrow;
+ int col = combo_box->model_column;
+ assert(model->coltype[col] == G_TYPE_STRING);
+ for (nrow = 0; nrow < combo_box->model->rows->len; ++nrow) {
+ row = &g_array_index(combo_box->model->rows, GtkListStoreRow, nrow);
+ myComboBox_AddString(hWnd, row->data[col]);
}
- mySendMessage(hWnd, CB_SETCURSEL, (WPARAM)GTK_MENU(menu)->active, 0);
+ mySendMessage(hWnd, CB_SETCURSEL, (WPARAM)combo_box->active, 0);
}
}
-void gtk_option_menu_set_history(GtkOptionMenu *option_menu, guint index)
+GtkTreeModel *gtk_combo_box_get_model(GtkComboBox *combo_box)
{
- GtkWidget *menu;
+ return combo_box->model;
+}
- menu = gtk_option_menu_get_menu(option_menu);
- if (menu)
- gtk_menu_set_active(GTK_MENU(menu), index);
+void gtk_combo_box_set_active(GtkComboBox *combo_box, gint index)
+{
+ combo_box->active = index;
}
-void gtk_option_menu_size_request(GtkWidget *widget,
- GtkRequisition *requisition)
+gboolean gtk_combo_box_get_active_iter(GtkComboBox *combo_box,
+ GtkTreeIter *iter);
+{
+ if (combo_box->active >= 0) {
+ *iter = combo_box->active;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void gtk_combo_box_size_request(GtkWidget *widget,
+ GtkRequisition *requisition)
{
SIZE size;
t@@ -4744,15 +4774,15 @@ void gtk_option_menu_size_request(GtkWidget *widget,
}
}
-void gtk_option_menu_set_size(GtkWidget *widget, GtkAllocation *allocation)
+void gtk_combo_box_set_size(GtkWidget *widget, GtkAllocation *allocation)
{
allocation->height *= 6;
}
-void gtk_option_menu_realize(GtkWidget *widget)
+void gtk_combo_box_realize(GtkWidget *widget)
{
HWND Parent;
- GtkOptionMenu *option_menu = GTK_OPTION_MENU(widget);
+ GtkComboBox *combo_box = GTK_COMBO_BOX(widget);
Parent = gtk_get_parent_hwnd(widget);
GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
t@@ -4761,7 +4791,16 @@ void gtk_option_menu_realize(GtkWidget *widget)
CBS_HASSTRINGS | CBS_DROPDOWNLIST,
0, 0, 0, 0, Parent, NULL, hInst, NULL);
gtk_set_default_font(widget->hWnd);
- gtk_option_menu_set_menu(option_menu, option_menu->menu);
+ gtk_combo_box_set_model(combo_box, combo_box->model);
+}
+
+void gtk_combo_box_destroy(GtkWidget *widget)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX(widget);
+ if (combo_box->model) {
+ gtk_tree_model_free(combo_box->model);
+ }
+ combo_box->model = NULL;
}
void gtk_label_set_text(GtkLabel *label, const gchar *str)
t@@ -4853,11 +4892,9 @@ void gtk_editable_create(GtkWidget *widget)
editable->text = g_string_new("");
}
-void gtk_option_menu_update_selection(GtkWidget *widget)
+void gtk_combo_box_update_selection(GtkWidget *widget)
{
LRESULT lres;
- GtkMenuShell *menu;
- GtkWidget *menu_item;
if (widget->hWnd == NULL)
return;
t@@ -4865,12 +4902,8 @@ void gtk_option_menu_update_selection(GtkWidget *widget)
if (lres == CB_ERR)
return;
- menu = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(widget)));
- if (menu) {
- menu_item = GTK_WIDGET(g_slist_nth_data(menu->children, lres));
- if (menu_item)
- gtk_signal_emit(G_OBJECT(menu_item), "activate");
- }
+ GTK_COMBO_BOX(widget)->active = lres;
+ gtk_signal_emit(G_OBJECT(widget), "changed");
}
void gtk_window_handle_user_size(GtkWindow *window,
(DIR) diff --git a/src/gtkport/gtkport.h b/src/gtkport/gtkport.h
t@@ -229,10 +229,11 @@ struct _GtkButton {
gchar *text;
};
-struct _GtkOptionMenu {
- GtkButton button;
- GtkWidget *menu;
- guint selection;
+struct _GtkComboBox {
+ GtkWidget widget;
+ GtkTreeModel *model;
+ gint model_column;
+ gint active;
};
struct _GtkToggleButton {
t@@ -313,7 +314,8 @@ extern HINSTANCE hInst;
#define GTK_TEXT(obj) ((GtkText *)(obj))
#define GTK_WINDOW(obj) ((GtkWindow *)(obj))
#define GTK_BUTTON(obj) ((GtkButton *)(obj))
-#define GTK_OPTION_MENU(obj) ((GtkOptionMenu *)(obj))
+#define GTK_COMBO_BOX(obj) ((GtkComboBox *)(obj))
+#define GTK_CELL_LAYOUT(obj) ((GtkCellLayout *)(obj))
#define GTK_TOGGLE_BUTTON(obj) ((GtkToggleButton *)(obj))
#define GTK_RADIO_BUTTON(obj) ((GtkRadioButton *)(obj))
#define GTK_CHECK_BUTTON(obj) ((GtkCheckButton *)(obj))
t@@ -499,10 +501,15 @@ void gtk_paned_set_position(GtkPaned *paned, gint position);
GtkWidget *gtk_button_box_new(GtkOrientation orientation);
void gtk_box_set_spacing(GtkBox *box, gint spacing);
#define gtk_button_box_set_layout(box, layout) {}
-GtkWidget *gtk_option_menu_new(void);
-GtkWidget *gtk_option_menu_get_menu(GtkOptionMenu *option_menu);
-void gtk_option_menu_set_menu(GtkOptionMenu *option_menu, GtkWidget *menu);
-void gtk_option_menu_set_history(GtkOptionMenu *option_menu, guint index);
+GtkWidget *gtk_combo_box_new_with_model(GtkTreeModel *model);
+void gtk_combo_box_set_model(GtkComboBox *combo_box, GtkTreeModel *model);
+void gtk_combo_box_set_active(GtkComboBox *combo_box, gint index);
+void gtk_cell_layout_set_attributes(GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell, ...);
+#define gtk_cell_layout_pack_start(layout, renderer, expand) {}
+GtkTreeModel *gtk_combo_box_get_model(GtkComboBox *combo_box);
+gboolean gtk_combo_box_get_active_iter(GtkComboBox *combo_box,
+ GtkTreeIter *iter);
void gtk_label_set_text(GtkLabel *label, const gchar *str);
guint gtk_label_parse_uline(GtkLabel *label, const gchar *str);
const gchar *gtk_label_get_text(GtkLabel *label);
(DIR) diff --git a/src/gtkport/gtktypes.h b/src/gtkport/gtktypes.h
t@@ -84,7 +84,10 @@ typedef struct _GtkPanedChild GtkPanedChild;
typedef struct _GtkPaned GtkPaned;
typedef struct _GtkVPaned GtkVPaned;
typedef struct _GtkHPaned GtkHPaned;
-typedef struct _GtkOptionMenu GtkOptionMenu;
+typedef struct _GtkComboBox GtkComboBox;
+
+/* Currently we only use cell_layout for combo box, so make it a synonym */
+typedef struct _GtkComboBox GtkCellLayout;
struct _GtkAccelGroup {
ACCEL *accel; /* list of ACCEL structures */