/**************************************************************************** Set information for the indicator icons typically shown in the main client window. The parameters tell which sprite to use for the indicator. ****************************************************************************/ void set_indicator_icons(struct sprite *bulb, struct sprite *sol, struct sprite *flake, struct sprite *gov) { gtk_image_set_from_pixbuf(GTK_IMAGE(bulb_label), sprite_get_pixbuf(bulb)); gtk_image_set_from_pixbuf(GTK_IMAGE(sun_label), sprite_get_pixbuf(sol)); gtk_image_set_from_pixbuf(GTK_IMAGE(flake_label), sprite_get_pixbuf(flake)); gtk_image_set_from_pixbuf(GTK_IMAGE(government_label), sprite_get_pixbuf(gov)); }
/**************************************************************** Render worklist cell *****************************************************************/ static void cell_render_func(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *model, GtkTreeIter *it, gpointer data) { gint cid; struct universal target; gtk_tree_model_get(model, it, 0, &cid, -1); target = cid_production(cid); if (GTK_IS_CELL_RENDERER_PIXBUF(rend)) { GdkPixbuf *pix; struct sprite *sprite; if (VUT_UTYPE == target.kind) { sprite = sprite_scale(get_unittype_sprite(tileset, target.value.utype, DIR8_SOUTH, TRUE), max_unit_width, max_unit_height); } else { sprite = get_building_sprite(tileset, target.value.building); } pix = sprite_get_pixbuf(sprite); g_object_set(rend, "pixbuf", pix, NULL); g_object_unref(G_OBJECT(pix)); if (VUT_UTYPE == target.kind) { free_sprite(sprite); } } else { struct city **pcity = data; gint column; char *row[4]; char buf[4][64]; guint i; gboolean useless; for (i = 0; i < ARRAY_SIZE(row); i++) { row[i] = buf[i]; } column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(rend), "column")); get_city_dialog_production_row(row, sizeof(buf[0]), target, *pcity); g_object_set(rend, "text", row[column], NULL); if (NULL != *pcity && VUT_IMPROVEMENT == target.kind) { useless = is_improvement_redundant(*pcity, target.value.building); /* Mark building redundant if we are really certain that there is * no use for it. */ g_object_set(rend, "strikethrough", useless, NULL); } else { g_object_set(rend, "strikethrough", FALSE, NULL); } } }
/************************************************************************** This function is called when the tileset is changed. **************************************************************************/ void tileset_changed(void) { reset_city_dialogs(); reset_unit_table(); blank_max_unit_size(); editgui_tileset_changed(); /* keep the icon of the executable on Windows (see PR#36491) */ #ifndef WIN32_NATIVE gtk_window_set_icon(GTK_WINDOW(toplevel), sprite_get_pixbuf(get_icon_sprite(tileset, ICON_FREECIV))); #endif }
/*************************************************************************** ... ***************************************************************************/ void load_cursors(void) { enum cursor_type cursor; GdkDisplay *display = gdk_display_get_default(); int frame; for (cursor = 0; cursor < CURSOR_LAST; cursor++) { for (frame = 0; frame < NUM_CURSOR_FRAMES; frame++) { int hot_x, hot_y; struct sprite *sprite = get_cursor_sprite(tileset, cursor, &hot_x, &hot_y, frame); GdkPixbuf *pixbuf = sprite_get_pixbuf(sprite); fc_cursors[cursor][frame] = gdk_cursor_new_from_pixbuf(display, pixbuf, hot_x, hot_y); } } }
/************************************************************************** ... **************************************************************************/ GdkPixbuf *get_thumb_pixbuf(int onoff) { return sprite_get_pixbuf(get_treaty_thumb_sprite(tileset, BOOL_VAL(onoff))); }
/************************************************************************** ... **************************************************************************/ void update_info_label( void ) { GtkWidget *label; const struct player *pplayer = client.conn.playing; label = gtk_frame_get_label_widget(GTK_FRAME(main_frame_civ_name)); if (pplayer != NULL) { char nation[MAX_LEN_NAME]; /* Capitalize the first character of the translated nation * plural name so that the frame label looks good. I assume * that in the case that capitalization does not make sense * (e.g. multi-byte characters or no "upper case" form in * the translation language) my_toupper() will just return * the same value as was passed into it. */ sz_strlcpy(nation, nation_plural_for_player(pplayer)); nation[0] = my_toupper(nation[0]); gtk_label_set_text(GTK_LABEL(label), nation); } else { gtk_label_set_text(GTK_LABEL(label), "-"); } gtk_label_set_text(GTK_LABEL(main_label_info), get_info_label_text()); set_indicator_icons(client_research_sprite(), client_warming_sprite(), client_cooling_sprite(), client_government_sprite()); if (NULL != client.conn.playing) { int d = 0; for (; d < client.conn.playing->economic.luxury /10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_LUXURY); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } for (; d < (client.conn.playing->economic.science + client.conn.playing->economic.luxury) / 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_SCIENCE); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } for (; d < 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_GOLD); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } } update_timeout_label(); /* update tooltips. */ gtk_tooltips_set_tip(main_tips, econ_ebox, _("Shows your current luxury/science/tax rates;" "click to toggle them."), ""); gtk_tooltips_set_tip(main_tips, bulb_ebox, get_bulb_tooltip(), ""); gtk_tooltips_set_tip(main_tips, sun_ebox, get_global_warming_tooltip(), ""); gtk_tooltips_set_tip(main_tips, flake_ebox, get_nuclear_winter_tooltip(), ""); gtk_tooltips_set_tip(main_tips, government_ebox, get_government_tooltip(), ""); }
/**************************************************************************** Create a new sprite by cropping and taking only the given portion of the image. source gives the sprite that is to be cropped. x,y, width, height gives the rectangle to be cropped. The pixel at position of the source sprite will be at (0,0) in the new sprite, and the new sprite will have dimensions (width, height). mask gives an additional mask to be used for clipping the new sprite. mask_offset_x, mask_offset_y is the offset of the mask relative to the origin of the source image. The pixel at (mask_offset_x,mask_offset_y) in the mask image will be used to clip pixel (0,0) in the source image which is pixel (-x,-y) in the new image. ****************************************************************************/ struct sprite *crop_sprite(struct sprite *source, int x, int y, int width, int height, struct sprite *mask, int mask_offset_x, int mask_offset_y) { GdkPixbuf *mypixbuf, *sub, *mask_pixbuf; /* First just crop the image. */ if (x < 0) { width += x; x = 0; } if (y < 0) { height += y; y = 0; } width = CLIP(0, width, source->width - x); height = CLIP(0, height, source->height - y); sub = gdk_pixbuf_new_subpixbuf(sprite_get_pixbuf(source), x, y, width, height); mypixbuf = gdk_pixbuf_copy(sub); g_object_unref(sub); /* Now mask. This reduces the alpha of the final image proportional to the * alpha of the mask. Thus if the mask has 50% alpha the final image will * be reduced by 50% alpha. Note that the mask offset is in coordinates * relative to the clipped image not the final image. */ if (mask && (mask_pixbuf = sprite_get_pixbuf(mask)) && gdk_pixbuf_get_has_alpha(mask_pixbuf)) { int x1, y1; /* The mask offset is the offset of the mask relative to the origin * of the original source image. For instance when cropping with * blending sprites the offset is always 0. Here we convert the * coordinates so that they are relative to the origin of the new * (cropped) image. */ mask_offset_x -= x; mask_offset_y -= y; width = CLIP(0, width, mask->width + mask_offset_x); height = CLIP(0, height, mask->height + mask_offset_y); if (!gdk_pixbuf_get_has_alpha(mypixbuf)) { GdkPixbuf *p2 = mypixbuf; mypixbuf = gdk_pixbuf_add_alpha(mypixbuf, FALSE, 0, 0, 0); g_object_unref(p2); } for (x1 = 0; x1 < width; x1++) { for (y1 = 0; y1 < height; y1++) { int mask_x = x1 - mask_offset_x, mask_y = y1 - mask_offset_y; guchar *alpha = gdk_pixbuf_get_pixels(mypixbuf) + y1 * gdk_pixbuf_get_rowstride(mypixbuf) + x1 * gdk_pixbuf_get_n_channels(mypixbuf) + 3; guchar *mask_alpha = gdk_pixbuf_get_pixels(mask_pixbuf) + mask_y * gdk_pixbuf_get_rowstride(mask_pixbuf) + mask_x * gdk_pixbuf_get_n_channels(mask_pixbuf) + 3; *alpha = (*alpha) * (*mask_alpha) / 255; } } } return ctor_sprite(mypixbuf); }
/**************************************************************************** Scales a sprite. If the sprite contains a mask, the mask is scaled as as well. ****************************************************************************/ struct sprite *sprite_scale(struct sprite *src, int new_w, int new_h) { return ctor_sprite(gdk_pixbuf_scale_simple(sprite_get_pixbuf(src), new_w, new_h, GDK_INTERP_BILINEAR)); }
/************************************************************************** Refresh info label **************************************************************************/ void update_info_label(void) { GtkWidget *label; const struct player *pplayer = client.conn.playing; label = gtk_frame_get_label_widget(GTK_FRAME(main_frame_civ_name)); if (pplayer != NULL) { const gchar *name; gunichar c; /* Capitalize the first character of the translated nation * plural name so that the frame label looks good. */ name = nation_plural_for_player(pplayer); c = g_utf8_get_char_validated(name, -1); if ((gunichar) -1 != c && (gunichar) -2 != c) { gchar nation[MAX_LEN_NAME]; gchar *next; gint len; len = g_unichar_to_utf8(g_unichar_toupper(c), nation); nation[len] = '\0'; next = g_utf8_find_next_char(name, NULL); if (NULL != next) { sz_strlcat(nation, next); } gtk_label_set_text(GTK_LABEL(label), nation); } else { gtk_label_set_text(GTK_LABEL(label), name); } } else { gtk_label_set_text(GTK_LABEL(label), "-"); } gtk_label_set_text(GTK_LABEL(main_label_info), get_info_label_text(!gui_gtk2_small_display_layout)); set_indicator_icons(client_research_sprite(), client_warming_sprite(), client_cooling_sprite(), client_government_sprite()); if (NULL != client.conn.playing) { int d = 0; for (; d < client.conn.playing->economic.luxury /10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_LUXURY); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } for (; d < (client.conn.playing->economic.science + client.conn.playing->economic.luxury) / 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_SCIENCE); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } for (; d < 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_GOLD); gtk_image_set_from_pixbuf(GTK_IMAGE(econ_label[d]), sprite_get_pixbuf(sprite)); } } update_timeout_label(); /* update tooltips. */ gtk_widget_set_tooltip_text(econ_ebox, _("Shows your current luxury/science/tax rates; " "click to toggle them.")); gtk_widget_set_tooltip_text(bulb_ebox, get_bulb_tooltip()); gtk_widget_set_tooltip_text(sun_ebox, get_global_warming_tooltip()); gtk_widget_set_tooltip_text(flake_ebox, get_nuclear_winter_tooltip()); gtk_widget_set_tooltip_text(government_ebox, get_government_tooltip()); }