Skip to content
API Documentation
BastionGuard™
IconManager.vala
Go to the documentation of this file.
1/*
2 * IconManager.vala
3 *
4 * Copyright 2012-2018 Tony George <teejeetech@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 *
22 */
23
24
25using Gtk;
26using Gee;
27using Cairo;
28
29using TeeJee.Logging;
34using TeeJee.System;
35using TeeJee.Misc;
36
37public class IconManager : GLib.Object {
38
39 public static Gtk.IconTheme theme;
40
41 public static Gee.ArrayList<string> search_paths = new Gee.ArrayList<string>();
42
43 // Set this to true when dark theme is active so lookup_image uses white icons,
44 // false for light theme (black icons). Updated by MainWindow.load_css().
45 public static bool use_dark = false;
46
47 public const int SHIELD_ICON_SIZE = 64;
48
49 public const string GENERIC_ICON_IMAGE = "image-x-generic";
50 public const string GENERIC_ICON_IMAGE_MISSING = "image-missing";
51 public const string GENERIC_ICON_VIDEO = "video-x-generic";
52 public const string GENERIC_ICON_FILE = "text-x-preview";
53 public const string GENERIC_ICON_ARCHIVE_FILE = "package-x-generic";
54 public const string GENERIC_ICON_DIRECTORY = "folder";
55 public const string GENERIC_ICON_ISO = "media-cdrom";
56 public const string GENERIC_ICON_PDF = "application-pdf";
57
58 public const string ICON_HARDDRIVE = "drive-harddisk";
59
60 public const string SHIELD_LIVE= "media-optical";
61 public const string SHIELD_LOW = "bastionguard-backup-shield-low";
62 public const string SHIELD_MED = "bastionguard-backup-shield-med";
63 public const string SHIELD_HIGH = "bastionguard-backup-shield-high";
64
65 public static void init(string[] args, string app_name){
66
67 log_debug("IconManager: init()");
68
69 search_paths = new Gee.ArrayList<string>();
70
71 string[] extra_paths = {
72 "/usr/share/%s/images-dark".printf(app_name),
73 "/usr/share/%s/images-light".printf(app_name),
74 "/usr/local/share/%s/images-dark".printf(app_name),
75 "/usr/local/share/%s/images-light".printf(app_name),
76 "/usr/share/%s/images".printf(app_name),
77 "/usr/local/share/%s/images".printf(app_name),
78 "/usr/share/pixmaps",
79 "/usr/local/share/pixmaps",
80 GLib.Path.build_filename(GLib.Environment.get_user_data_dir(), app_name, "images-dark"),
81 GLib.Path.build_filename(GLib.Environment.get_user_data_dir(), app_name, "images-light"),
82 GLib.Path.build_filename(GLib.Environment.get_user_data_dir(), app_name, "images"),
83 GLib.Path.build_filename(GLib.Environment.get_current_dir(), "src", "share", app_name, "images-dark"),
84 GLib.Path.build_filename(GLib.Environment.get_current_dir(), "src", "share", app_name, "images-light"),
85 GLib.Path.build_filename(GLib.Environment.get_current_dir(), "src", "share", app_name, "images"),
86 GLib.Path.build_filename(GLib.Environment.get_current_dir(), "src", "share", "pixmaps"),
87 GLib.Path.build_filename(GLib.Environment.get_current_dir(), "icons")
88 };
89 foreach (var path in extra_paths) {
90 if (dir_exists(path) && !search_paths.contains(path)) {
91 search_paths.add(path);
92 log_debug("found images directory: %s".printf(path));
93 }
94 }
95
97 }
98
99 public static void refresh_icon_theme(){
100
101 if (!GTK_INITIALIZED) { return; }
102
103 var display = Gdk.Display.get_default();
104 if (display == null) { return; }
105 theme = Gtk.IconTheme.get_for_display(display);
106 foreach(string path in search_paths){
107 theme.add_search_path(path);
108 }
109 }
110
111 public static Gdk.Pixbuf? lookup(string icon_name, int icon_size, bool symbolic = false, bool use_hardcoded = false, int scale = 1){
112 // Pick the theme-specific subfolder first (images-dark/ or images-light/)
113 string theme_folder = use_dark ? "images-dark" : "images-light";
114 string[] resource_candidates = {
115 "images/" + theme_folder + "/" + icon_name + ".svg",
116 "images/" + theme_folder + "/" + icon_name + ".png",
117 "images/" + icon_name + ".png",
118 "images/" + icon_name + ".svg",
119 "images/" + icon_name,
120 "icons/" + icon_name + ".png",
121 "pixmaps/" + icon_name + ".png",
122 "icons/hicolor/128x128/apps/" + icon_name + ".png",
123 "icons/hicolor/96x96/apps/" + icon_name + ".png",
124 "icons/hicolor/64x64/apps/" + icon_name + ".png",
125 "icons/hicolor/48x48/apps/" + icon_name + ".png",
126 "icons/hicolor/32x32/apps/" + icon_name + ".png",
127 "icons/hicolor/24x24/apps/" + icon_name + ".png",
128 "icons/hicolor/22x22/apps/" + icon_name + ".png",
129 "icons/hicolor/16x16/apps/" + icon_name + ".png"
130 };
131
132 Gdk.Pixbuf? pixbuf = null;
133 if (icon_name.length == 0){ return null; }
134
135 foreach (var rel in resource_candidates) {
137 try {
138 pixbuf = new Gdk.Pixbuf.from_resource_at_scale(ResourceHelper.resource_prefix() + "/" + rel, icon_size, icon_size, true);
139 if (pixbuf != null) return pixbuf;
140 } catch (Error e) {
141 // ignore and continue with filesystem fallback
142 }
143 }
144 }
145
146 string? resolved = ResourceHelper.resolve_icon_file(icon_name);
147 if (resolved != null) {
148 pixbuf = load_pixbuf_from_file(resolved, icon_size);
149 if (pixbuf != null) return pixbuf;
150 }
151
152 foreach(string search_path in search_paths){
153 foreach(string ext in new string[] { ".svg", ".png", ".jpg", ".gif"}){
154 string img_file = path_combine(search_path, icon_name + ext);
155 if (file_exists(img_file)){
156 pixbuf = load_pixbuf_from_file(img_file, icon_size);
157 if (pixbuf != null){ return pixbuf; }
158 }
159 }
160 }
161
162 return null;
163 }
164
165
166 public static Gdk.Pixbuf? lookup_gicon(GLib.Icon gicon, int icon_size){
167 return lookup(GENERIC_ICON_FILE, icon_size, false);
168 }
169
170
171public static Gtk.Image lookup_image(string icon_name, int icon_size, bool symbolic = false, bool use_hardcoded = false){
172
173 var image = new Gtk.Image();
174 image.set_pixel_size(icon_size);
175 if (icon_name.length == 0){
176 image.set_from_icon_name(GENERIC_ICON_IMAGE_MISSING);
177 return image;
178 }
179
180 Gdk.Pixbuf? pix = lookup(icon_name, icon_size, symbolic, use_hardcoded, image.get_scale_factor());
181 if (pix != null){
182 image.set_from_pixbuf(pix);
183 } else {
184 image.set_from_icon_name(icon_name);
185 }
186 return image;
187 }
188
189 public static Gtk.Button button_from_icon(string icon_name, int icon_size, string? tooltip = null){
190 var btn = new Gtk.Button();
191 btn.set_child(lookup_image(icon_name, icon_size));
192 if (tooltip != null) btn.tooltip_text = tooltip;
193 return btn;
194 }
195
196 public static Cairo.Surface? lookup_surface(string icon_name, int icon_size, int scale = 1, bool symbolic = false, bool use_hardcoded = false){
197 return null;
198 }
199
200 public static Gdk.Pixbuf? add_emblem (Gdk.Pixbuf pixbuf, string icon_name, int emblem_size, bool emblem_symbolic, Gtk.CornerType corner_type) {
201
202 if (icon_name.length == 0){ return pixbuf; }
203
204 Gdk.Pixbuf? emblem = null;
205
206 var SMALL_EMBLEM_COLOR = Gdk.RGBA();
207 SMALL_EMBLEM_COLOR.parse("#000000");
208 SMALL_EMBLEM_COLOR.alpha = 1.0f;
209
210 var EMBLEM_PADDING = 1;
211
212 emblem = lookup(icon_name, emblem_size, emblem_symbolic, true);
213 if (emblem == null) {
214 return pixbuf;
215 }
216
217 if (emblem == null)
218 return pixbuf;
219
220 var offset_x = EMBLEM_PADDING;
221
222 if ((corner_type == Gtk.CornerType.BOTTOM_RIGHT) || (corner_type == Gtk.CornerType.TOP_RIGHT)){
223 offset_x = pixbuf.width - emblem.width - EMBLEM_PADDING ;
224 }
225
226 var offset_y = EMBLEM_PADDING;
227
228 if ((corner_type == Gtk.CornerType.BOTTOM_LEFT) || (corner_type == Gtk.CornerType.BOTTOM_RIGHT)){
229 offset_y = pixbuf.height - emblem.height - EMBLEM_PADDING ;
230 }
231
232 var emblemed = pixbuf.copy();
233
234 emblem.composite(emblemed,
235 offset_x, offset_y,
236 emblem_size, emblem_size,
237 offset_x, offset_y,
238 1.0, 1.0,
239 Gdk.InterpType.BILINEAR, 255);
240
241 return emblemed;
242 }
243
244 public static Gdk.Pixbuf? add_overlay(Gdk.Pixbuf pixbuf_base, Gdk.Pixbuf pixbuf_overlay) {
245
246 int offset_x = (pixbuf_base.width - pixbuf_overlay.width) / 2 ;
247
248 var offset_y = (pixbuf_base.height - pixbuf_overlay.height) / 2 ;
249
250 var emblemed = pixbuf_base.copy();
251
252 pixbuf_overlay.composite(emblemed,
253 offset_x, offset_y,
254 pixbuf_overlay.width, pixbuf_overlay.height,
255 offset_x, offset_y,
256 1.0, 1.0,
257 Gdk.InterpType.BILINEAR, 255);
258
259 return emblemed;
260 }
261
262 public static Gdk.Pixbuf? resize_icon(Gdk.Pixbuf pixbuf_image, int icon_size) {
263
264 //log_debug("resize_icon()");
265
266 var pixbuf_empty = new Gdk.Pixbuf(Gdk.Colorspace.RGB, true, 8, icon_size, icon_size);
267 pixbuf_empty.fill(0x00000000);
268
269 //log_debug("pixbuf_empty: %d, %d".printf(pixbuf_empty.width, pixbuf_empty.height));
270
271 var pixbuf_resized = add_overlay(pixbuf_empty, pixbuf_image);
272
273 //log_debug("pixbuf_resized: %d, %d".printf(pixbuf_resized.width, pixbuf_resized.height));
274
275 //copy_pixbuf_options(pixbuf_image, pixbuf_resized);
276
277 return pixbuf_resized;
278 }
279
280 public static Gdk.Pixbuf? add_transparency (Gdk.Pixbuf pixbuf, int opacity = 130) {
281
282 var trans = pixbuf.copy();
283 trans.fill((uint32) 0xFFFFFF00);
284
285 //log_debug("add_transparency");
286
287 int width = pixbuf.get_width();
288 int height = pixbuf.get_height();
289 pixbuf.composite(trans, 0, 0, width, height, 0, 0, 1.0, 1.0, Gdk.InterpType.BILINEAR, opacity);
290
291 return trans;
292 }
293
294 public static Gdk.Pixbuf? load_pixbuf_from_file(string file_path, int icon_size){
295
296 Gdk.Pixbuf? pixbuf = null;
297
298 int width, height;
299 Gdk.Pixbuf.get_file_info(file_path, out width, out height);
300
301 if ((width <= icon_size) && (height <= icon_size)){
302 try{
303 // load without scaling
304 pixbuf = new Gdk.Pixbuf.from_file(file_path);
305 // pad to requested size
306 pixbuf = resize_icon(pixbuf, icon_size);
307 // return
308 if (pixbuf != null){ return pixbuf; }
309 }
310 catch (Error e){
311 // ignore
312 }
313 }
314 else {
315 try{
316 // load with scaling - scale down to requested box
317 pixbuf = new Gdk.Pixbuf.from_file_at_scale(file_path, icon_size, icon_size, true);
318 // pad to requested size
319 pixbuf = resize_icon(pixbuf, icon_size);
320 // return
321 if (pixbuf != null){ return pixbuf; }
322 }
323 catch (Error e){
324 // ignore
325 }
326 }
327
328 return null;
329 }
330}
bool GTK_INITIALIZED
Definition Main.vala:37
const string ICON_HARDDRIVE
static bool use_dark
const string GENERIC_ICON_PDF
static Gdk.? Pixbuf lookup(string icon_name, int icon_size, bool symbolic=false, bool use_hardcoded=false, int scale=1)
static Gdk.? Pixbuf lookup_gicon(GLib.Icon gicon, int icon_size)
static Cairo.? Surface lookup_surface(string icon_name, int icon_size, int scale=1, bool symbolic=false, bool use_hardcoded=false)
const string GENERIC_ICON_DIRECTORY
const string GENERIC_ICON_VIDEO
const string SHIELD_MED
const string SHIELD_LIVE
const string GENERIC_ICON_FILE
static void init(string[] args, string app_name)
const string SHIELD_LOW
static Gdk.? Pixbuf load_pixbuf_from_file(string file_path, int icon_size)
const string SHIELD_HIGH
const string GENERIC_ICON_ISO
static Gtk.IconTheme theme
static void refresh_icon_theme()
const int SHIELD_ICON_SIZE
const string GENERIC_ICON_IMAGE_MISSING
static Gdk.? Pixbuf add_transparency(Gdk.Pixbuf pixbuf, int opacity=130)
static Gdk.? Pixbuf add_overlay(Gdk.Pixbuf pixbuf_base, Gdk.Pixbuf pixbuf_overlay)
static Gdk.? Pixbuf resize_icon(Gdk.Pixbuf pixbuf_image, int icon_size)
static Gee.ArrayList< string > search_paths
static Gtk.Button button_from_icon(string icon_name, int icon_size, string? tooltip=null)
static Gtk.Image lookup_image(string icon_name, int icon_size, bool symbolic=false, bool use_hardcoded=false)
static Gdk.? Pixbuf add_emblem(Gdk.Pixbuf pixbuf, string icon_name, int emblem_size, bool emblem_symbolic, Gtk.CornerType corner_type)
const string GENERIC_ICON_ARCHIVE_FILE
const string GENERIC_ICON_IMAGE
static bool resource_exists(string rel)
static ? string resolve_icon_file(string icon_name)
static string resource_prefix()
bool file_exists(string file_path)
string path_combine(string path1, string path2)
bool dir_exists(string dir_path)
void log_debug(string message)