From 31e9a9f2b8d22783ee22966ed43516a7fb4ecb37 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 25 Jun 2022 12:00:22 +0300 Subject: [PATCH 50/50] gtk4: Use GtkPicture for unit icons See osdn #44934 Signed-off-by: Marko Lindqvist --- client/gui-gtk-4.0/citydlg.c | 10 ++--- client/gui-gtk-4.0/gui_main.c | 85 ++++++++++++++++++++--------------- client/gui-gtk-4.0/mapview.c | 14 +++--- client/gui-gtk-4.0/mapview.h | 6 +-- client/gui-gtk-4.0/sprite.c | 15 +++++++ client/gui-gtk-4.0/sprite.h | 4 +- 6 files changed, 81 insertions(+), 53 deletions(-) diff --git a/client/gui-gtk-4.0/citydlg.c b/client/gui-gtk-4.0/citydlg.c index d277867412..44b5fe20c7 100644 --- a/client/gui-gtk-4.0/citydlg.c +++ b/client/gui-gtk-4.0/citydlg.c @@ -2193,7 +2193,7 @@ static void city_dialog_update_supported_units(struct city_dialog *pdialog) gtk_button_set_has_frame(GTK_BUTTON(cmd), FALSE); - pix = gtk_image_new(); + pix = gtk_picture_new(); node.pix = pix; node.height = tileset_unit_with_upkeep_height(tileset); @@ -2224,8 +2224,8 @@ static void city_dialog_update_supported_units(struct city_dialog *pdialog) cmd = pnode->cmd; pix = pnode->pix; - put_unit_image_city_overlays(punit, GTK_IMAGE(pix), pnode->height, - punit->upkeep, happy_cost); + put_unit_picture_city_overlays(punit, GTK_PICTURE(pix), pnode->height, + punit->upkeep, happy_cost); if (pnode->left != NULL) { gtk_widget_remove_controller(cmd, pnode->left); @@ -2317,7 +2317,7 @@ static void city_dialog_update_present_units(struct city_dialog *pdialog) gtk_button_set_has_frame(GTK_BUTTON(cmd), FALSE); - pix = gtk_image_new(); + pix = gtk_picture_new(); node.pix = pix; node.height = tileset_full_tile_height(tileset); @@ -2347,7 +2347,7 @@ static void city_dialog_update_present_units(struct city_dialog *pdialog) cmd = pnode->cmd; pix = pnode->pix; - put_unit_image(punit, GTK_IMAGE(pix), pnode->height); + put_unit_picture(punit, GTK_PICTURE(pix), pnode->height); if (pnode->left != NULL) { gtk_widget_remove_controller(cmd, pnode->left); diff --git a/client/gui-gtk-4.0/gui_main.c b/client/gui-gtk-4.0/gui_main.c index 299e735117..7a6a166606 100644 --- a/client/gui-gtk-4.0/gui_main.c +++ b/client/gui-gtk-4.0/gui_main.c @@ -156,9 +156,10 @@ const char *const gui_character_encoding = "UTF-8"; const bool gui_use_transliteration = FALSE; static GMenu *main_menubar = NULL; -static GtkWidget *unit_image_table; -static GtkWidget *unit_image; -static GtkWidget *unit_below_image[MAX_NUM_UNITS_BELOW]; +static GdkPaintable *empty_unit_paintable = NULL; +static GtkWidget *unit_pic_table; +static GtkWidget *unit_pic; +static GtkWidget *unit_below_pic[MAX_NUM_UNITS_BELOW]; static GtkWidget *more_arrow_pixmap; static GtkWidget *more_arrow_pixmap_container; @@ -208,8 +209,8 @@ static void tearoff_callback(GtkWidget *b, gpointer data); static GtkWidget *detached_widget_new(void); static GtkWidget *detached_widget_fill(GtkWidget *tearbox); -static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev, - gpointer data); +static gboolean select_unit_pic_callback(GtkWidget *w, GdkEvent *ev, + gpointer data); static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev, gpointer data); static gboolean quit_dialog_callback(void); @@ -892,10 +893,10 @@ static GtkWidget *detached_widget_fill(GtkWidget *tearbox) It may be called again if the tileset changes. **************************************************************************/ -static void populate_unit_image_table(void) +static void populate_unit_pic_table(void) { int i, width; - GtkWidget *table = unit_image_table; + GtkWidget *table = unit_pic_table; GdkPixbuf *pix; int ttw; @@ -919,26 +920,26 @@ static void populate_unit_image_table(void) /* Top row: the active unit. */ /* Note, we ref this and other widgets here so that we can unref them * in reset_unit_table. */ - unit_image = gtk_image_new(); - g_object_ref(unit_image); - gtk_widget_set_size_request(unit_image, ttw, -1); - gtk_grid_attach(GTK_GRID(table), unit_image, 0, 0, 1, 1); - g_signal_connect(unit_image, "button_press_event", - G_CALLBACK(select_unit_image_callback), + unit_pic = gtk_picture_new(); + g_object_ref(unit_pic); + gtk_widget_set_size_request(unit_pic, ttw, -1); + gtk_grid_attach(GTK_GRID(table), unit_pic, 0, 0, 1, 1); + g_signal_connect(unit_pic, "button_press_event", + G_CALLBACK(select_unit_pic_callback), GINT_TO_POINTER(-1)); if (!GUI_GTK_OPTION(small_display_layout)) { /* Bottom row: other units in the same tile. */ for (i = 0; i < num_units_below; i++) { - unit_below_image[i] = gtk_image_new(); - g_object_ref(unit_below_image[i]); - gtk_widget_set_size_request(unit_below_image[i], ttw, -1); - g_signal_connect(unit_below_image[i], + unit_below_pic[i] = gtk_picture_new(); + g_object_ref(unit_below_pic[i]); + gtk_widget_set_size_request(unit_below_pic[i], ttw, -1); + g_signal_connect(unit_below_pic[i], "button_press_event", - G_CALLBACK(select_unit_image_callback), + G_CALLBACK(select_unit_pic_callback), GINT_TO_POINTER(i)); - gtk_grid_attach(GTK_GRID(table), unit_below_image[i], + gtk_grid_attach(GTK_GRID(table), unit_below_pic[i], i, 1, 1, 1); } } @@ -980,19 +981,19 @@ static void populate_unit_image_table(void) **************************************************************************/ static void free_unit_table(void) { - if (unit_image) { - gtk_grid_remove(GTK_GRID(unit_image_table), unit_image); - g_object_unref(unit_image); + if (unit_pic != NULL) { + gtk_grid_remove(GTK_GRID(unit_pic_table), unit_pic); + g_object_unref(unit_pic); if (!GUI_GTK_OPTION(small_display_layout)) { int i; for (i = 0; i < num_units_below; i++) { - gtk_grid_remove(GTK_GRID(unit_image_table), - unit_below_image[i]); - g_object_unref(unit_below_image[i]); + gtk_grid_remove(GTK_GRID(unit_pic_table), + unit_below_pic[i]); + g_object_unref(unit_below_pic[i]); } } - gtk_grid_remove(GTK_GRID(unit_image_table), + gtk_grid_remove(GTK_GRID(unit_pic_table), more_arrow_pixmap_container); g_object_unref(more_arrow_pixmap); g_object_unref(more_arrow_pixmap_container); @@ -1007,10 +1008,10 @@ void reset_unit_table(void) /* Unreference all of the widgets that we're about to reallocate, thus * avoiding a memory leak. Remove them from the container first, just * to be safe. Note, the widgets are ref'd in - * populate_unit_image_table. */ + * populate_unit_pic_table(). */ free_unit_table(); - populate_unit_image_table(); + populate_unit_pic_table(); /* We have to force a redraw of the units. And we explicitly have * to force a redraw of the focus unit, which is normally only @@ -1441,7 +1442,7 @@ static void setup_widgets(void) gtk_grid_set_row_spacing(GTK_GRID(table), 2); gtk_grid_set_column_spacing(GTK_GRID(table), 2); - unit_image_table = table; + unit_pic_table = table; /* Map canvas, editor toolbar, and scrollbars */ @@ -1880,6 +1881,9 @@ void ui_main(int argc, char **argv) * it from getting destroyed when editinfobox_refresh() * moves widgets around. Free that extra ref here. */ g_object_unref(unit_info_box); + if (empty_unit_paintable != NULL) { + g_object_unref(empty_unit_paintable); + } destroy_server_scans(); free_mapcanvas_and_overview(); @@ -2069,10 +2073,10 @@ void set_unit_icon(int idx, struct unit *punit) fc_assert_ret(idx >= -1 && idx < num_units_below); if (idx == -1) { - w = unit_image; + w = unit_pic; unit_id_top = punit ? punit->id : 0; } else { - w = unit_below_image[idx]; + w = unit_below_pic[idx]; unit_ids[idx] = punit ? punit->id : 0; } @@ -2081,9 +2085,16 @@ void set_unit_icon(int idx, struct unit *punit) } if (punit) { - put_unit_image(punit, GTK_IMAGE(w), -1); + put_unit_picture(punit, GTK_PICTURE(w), -1); } else { - gtk_image_clear(GTK_IMAGE(w)); + if (empty_unit_paintable == NULL) { + /* FIXME: Use proper icon height instead of hardcoded 50 */ + empty_unit_paintable = gdk_paintable_new_empty(tileset_tile_width(tileset), 50); + + /* Add ref to avoid it getting destroyed along any single parent widget. */ + g_object_ref(empty_unit_paintable); + } + gtk_picture_set_paintable(GTK_PICTURE(w), empty_unit_paintable); } } @@ -2121,11 +2132,11 @@ void real_focus_units_changed(void) } /**********************************************************************//** - callback for clicking a unit icon underneath unit info box. - these are the units on the same tile as the focus unit. + Callback for clicking a unit icon underneath unit info box. + these are the units on the same tile as the focus unit. **************************************************************************/ -static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev, - gpointer data) +static gboolean select_unit_pic_callback(GtkWidget *w, GdkEvent *ev, + gpointer data) { int i = GPOINTER_TO_INT(data); struct unit *punit; diff --git a/client/gui-gtk-4.0/mapview.c b/client/gui-gtk-4.0/mapview.c index 10ae7d0190..5ba31d20ad 100644 --- a/client/gui-gtk-4.0/mapview.c +++ b/client/gui-gtk-4.0/mapview.c @@ -459,9 +459,9 @@ void update_city_descriptions(void) } /**********************************************************************//** - Fill image with unit gfx + Fill picture with unit gfx **************************************************************************/ -void put_unit_image(struct unit *punit, GtkImage *p, int height) +void put_unit_picture(struct unit *punit, GtkPicture *p, int height) { struct canvas store = FC_STATIC_CANVAS_INIT; int width; @@ -476,7 +476,7 @@ void put_unit_image(struct unit *punit, GtkImage *p, int height) put_unit(punit, &store, 1.0, 0, 0); - image_set_from_surface(p, store.surface); + picture_set_from_surface(p, store.surface); cairo_surface_destroy(store.surface); } @@ -486,9 +486,9 @@ void put_unit_image(struct unit *punit, GtkImage *p, int height) unit, the proper way to do this is probably something like what Civ II does. (One food/shield/mask drawn N times, possibly one top of itself. -- SKi **************************************************************************/ -void put_unit_image_city_overlays(struct unit *punit, GtkImage *p, - int height, - int *upkeep_cost, int happy_cost) +void put_unit_picture_city_overlays(struct unit *punit, GtkPicture *p, + int height, + int *upkeep_cost, int happy_cost) { struct canvas store = FC_STATIC_CANVAS_INIT; int width = tileset_full_tile_width(tileset); @@ -501,7 +501,7 @@ void put_unit_image_city_overlays(struct unit *punit, GtkImage *p, put_unit_city_overlays(punit, &store, 0, tileset_unit_layout_offset_y(tileset), upkeep_cost, happy_cost); - image_set_from_surface(p, store.surface); + picture_set_from_surface(p, store.surface); cairo_surface_destroy(store.surface); } diff --git a/client/gui-gtk-4.0/mapview.h b/client/gui-gtk-4.0/mapview.h index 379c08decb..7702eefca2 100644 --- a/client/gui-gtk-4.0/mapview.h +++ b/client/gui-gtk-4.0/mapview.h @@ -38,10 +38,10 @@ void map_canvas_draw(GtkDrawingArea *w, cairo_t *cr, void map_canvas_resize(GtkWidget *w, int width, int height, gpointer data); -void put_unit_image(struct unit *punit, GtkImage *p, int height); +void put_unit_picture(struct unit *punit, GtkPicture *p, int height); -void put_unit_image_city_overlays(struct unit *punit, GtkImage *p, - int height, int *upkeep_cost, int happy_cost); +void put_unit_picture_city_overlays(struct unit *punit, GtkPicture *p, + int height, int *upkeep_cost, int happy_cost); void scrollbar_jump_callback(GtkAdjustment *adj, gpointer hscrollbar); void update_map_canvas_scrollbars_size(void); diff --git a/client/gui-gtk-4.0/sprite.c b/client/gui-gtk-4.0/sprite.c index 8c0b8b5dfe..482cb1ac7f 100644 --- a/client/gui-gtk-4.0/sprite.c +++ b/client/gui-gtk-4.0/sprite.c @@ -544,6 +544,21 @@ void image_set_from_surface(GtkImage *image, cairo_surface_t *surf) g_object_unref(pb); } +/************************************************************************//** + Set a GtkPicture from cairo surface. +****************************************************************************/ +void picture_set_from_surface(GtkPicture *pic, cairo_surface_t *surf) +{ + GdkPixbuf *pb; + + pb = surface_get_pixbuf(surf, + cairo_image_surface_get_width(surf), + cairo_image_surface_get_height(surf)); + + gtk_picture_set_pixbuf(pic, pb); + g_object_unref(pb); +} + /************************************************************************//** Return a sprite image of a number. ****************************************************************************/ diff --git a/client/gui-gtk-4.0/sprite.h b/client/gui-gtk-4.0/sprite.h index c9bd0e0759..a0084a64cc 100644 --- a/client/gui-gtk-4.0/sprite.h +++ b/client/gui-gtk-4.0/sprite.h @@ -39,4 +39,6 @@ GdkPixbuf *create_extra_pixbuf(const struct extra_type *pextra); GtkWidget *image_new_from_surface(cairo_surface_t *surf); void image_set_from_surface(GtkImage *image, cairo_surface_t *surf); -#endif /* FC__SPRITE_H */ +void picture_set_from_surface(GtkPicture *image, cairo_surface_t *surf); + +#endif /* FC__SPRITE_H */ -- 2.35.1