1use cairo;
6use gdk;
7use gdk_pixbuf;
8use gio;
9use glib::object::Cast;
10use glib::object::IsA;
11use glib::signal::connect_raw;
12use glib::signal::SignalHandlerId;
13use glib::translate::*;
14use glib::GString;
15use glib_sys;
16use gtk_sys;
17use std;
18use std::boxed::Box as Box_;
19use std::fmt;
20use std::mem::transmute;
21use std::ptr;
22use Error;
23use IconInfo;
24use IconLookupFlags;
25
26glib_wrapper! {
27 pub struct IconTheme(Object<gtk_sys::GtkIconTheme, gtk_sys::GtkIconThemeClass, IconThemeClass>);
28
29 match fn {
30 get_type => || gtk_sys::gtk_icon_theme_get_type(),
31 }
32}
33
34impl IconTheme {
35 pub fn new() -> IconTheme {
36 assert_initialized_main_thread!();
37 unsafe { from_glib_full(gtk_sys::gtk_icon_theme_new()) }
38 }
39
40 pub fn get_default() -> Option<IconTheme> {
41 assert_initialized_main_thread!();
42 unsafe { from_glib_none(gtk_sys::gtk_icon_theme_get_default()) }
43 }
44
45 pub fn get_for_screen(screen: &gdk::Screen) -> Option<IconTheme> {
46 assert_initialized_main_thread!();
47 unsafe {
48 from_glib_none(gtk_sys::gtk_icon_theme_get_for_screen(
49 screen.to_glib_none().0,
50 ))
51 }
52 }
53}
54
55impl Default for IconTheme {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61pub const NONE_ICON_THEME: Option<&IconTheme> = None;
62
63pub trait IconThemeExt: 'static {
64 fn add_resource_path(&self, path: &str);
65
66 fn append_search_path<P: AsRef<std::path::Path>>(&self, path: P);
67
68 fn get_example_icon_name(&self) -> Option<GString>;
69
70 fn has_icon(&self, icon_name: &str) -> bool;
71
72 fn list_contexts(&self) -> Vec<GString>;
73
74 fn list_icons(&self, context: Option<&str>) -> Vec<GString>;
75
76 fn load_icon(
77 &self,
78 icon_name: &str,
79 size: i32,
80 flags: IconLookupFlags,
81 ) -> Result<Option<gdk_pixbuf::Pixbuf>, Error>;
82
83 fn load_icon_for_scale(
84 &self,
85 icon_name: &str,
86 size: i32,
87 scale: i32,
88 flags: IconLookupFlags,
89 ) -> Result<Option<gdk_pixbuf::Pixbuf>, Error>;
90
91 fn load_surface<P: IsA<gdk::Window>>(
92 &self,
93 icon_name: &str,
94 size: i32,
95 scale: i32,
96 for_window: Option<&P>,
97 flags: IconLookupFlags,
98 ) -> Result<Option<cairo::Surface>, Error>;
99
100 fn lookup_by_gicon<P: IsA<gio::Icon>>(
101 &self,
102 icon: &P,
103 size: i32,
104 flags: IconLookupFlags,
105 ) -> Option<IconInfo>;
106
107 fn lookup_by_gicon_for_scale<P: IsA<gio::Icon>>(
108 &self,
109 icon: &P,
110 size: i32,
111 scale: i32,
112 flags: IconLookupFlags,
113 ) -> Option<IconInfo>;
114
115 fn lookup_icon(&self, icon_name: &str, size: i32, flags: IconLookupFlags) -> Option<IconInfo>;
116
117 fn lookup_icon_for_scale(
118 &self,
119 icon_name: &str,
120 size: i32,
121 scale: i32,
122 flags: IconLookupFlags,
123 ) -> Option<IconInfo>;
124
125 fn prepend_search_path<P: AsRef<std::path::Path>>(&self, path: P);
126
127 fn rescan_if_needed(&self) -> bool;
128
129 fn set_custom_theme(&self, theme_name: Option<&str>);
130
131 fn set_screen(&self, screen: &gdk::Screen);
132
133 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
134}
135
136impl<O: IsA<IconTheme>> IconThemeExt for O {
137 fn add_resource_path(&self, path: &str) {
138 unsafe {
139 gtk_sys::gtk_icon_theme_add_resource_path(
140 self.as_ref().to_glib_none().0,
141 path.to_glib_none().0,
142 );
143 }
144 }
145
146 fn append_search_path<P: AsRef<std::path::Path>>(&self, path: P) {
147 unsafe {
148 gtk_sys::gtk_icon_theme_append_search_path(
149 self.as_ref().to_glib_none().0,
150 path.as_ref().to_glib_none().0,
151 );
152 }
153 }
154
155 fn get_example_icon_name(&self) -> Option<GString> {
156 unsafe {
157 from_glib_full(gtk_sys::gtk_icon_theme_get_example_icon_name(
158 self.as_ref().to_glib_none().0,
159 ))
160 }
161 }
162
163 fn has_icon(&self, icon_name: &str) -> bool {
164 unsafe {
165 from_glib(gtk_sys::gtk_icon_theme_has_icon(
166 self.as_ref().to_glib_none().0,
167 icon_name.to_glib_none().0,
168 ))
169 }
170 }
171
172 fn list_contexts(&self) -> Vec<GString> {
173 unsafe {
174 FromGlibPtrContainer::from_glib_full(gtk_sys::gtk_icon_theme_list_contexts(
175 self.as_ref().to_glib_none().0,
176 ))
177 }
178 }
179
180 fn list_icons(&self, context: Option<&str>) -> Vec<GString> {
181 unsafe {
182 FromGlibPtrContainer::from_glib_full(gtk_sys::gtk_icon_theme_list_icons(
183 self.as_ref().to_glib_none().0,
184 context.to_glib_none().0,
185 ))
186 }
187 }
188
189 fn load_icon(
190 &self,
191 icon_name: &str,
192 size: i32,
193 flags: IconLookupFlags,
194 ) -> Result<Option<gdk_pixbuf::Pixbuf>, Error> {
195 unsafe {
196 let mut error = ptr::null_mut();
197 let ret = gtk_sys::gtk_icon_theme_load_icon(
198 self.as_ref().to_glib_none().0,
199 icon_name.to_glib_none().0,
200 size,
201 flags.to_glib(),
202 &mut error,
203 );
204 if error.is_null() {
205 Ok(from_glib_full(ret))
206 } else {
207 Err(from_glib_full(error))
208 }
209 }
210 }
211
212 fn load_icon_for_scale(
213 &self,
214 icon_name: &str,
215 size: i32,
216 scale: i32,
217 flags: IconLookupFlags,
218 ) -> Result<Option<gdk_pixbuf::Pixbuf>, Error> {
219 unsafe {
220 let mut error = ptr::null_mut();
221 let ret = gtk_sys::gtk_icon_theme_load_icon_for_scale(
222 self.as_ref().to_glib_none().0,
223 icon_name.to_glib_none().0,
224 size,
225 scale,
226 flags.to_glib(),
227 &mut error,
228 );
229 if error.is_null() {
230 Ok(from_glib_full(ret))
231 } else {
232 Err(from_glib_full(error))
233 }
234 }
235 }
236
237 fn load_surface<P: IsA<gdk::Window>>(
238 &self,
239 icon_name: &str,
240 size: i32,
241 scale: i32,
242 for_window: Option<&P>,
243 flags: IconLookupFlags,
244 ) -> Result<Option<cairo::Surface>, Error> {
245 unsafe {
246 let mut error = ptr::null_mut();
247 let ret = gtk_sys::gtk_icon_theme_load_surface(
248 self.as_ref().to_glib_none().0,
249 icon_name.to_glib_none().0,
250 size,
251 scale,
252 for_window.map(|p| p.as_ref()).to_glib_none().0,
253 flags.to_glib(),
254 &mut error,
255 );
256 if error.is_null() {
257 Ok(from_glib_full(ret))
258 } else {
259 Err(from_glib_full(error))
260 }
261 }
262 }
263
264 fn lookup_by_gicon<P: IsA<gio::Icon>>(
265 &self,
266 icon: &P,
267 size: i32,
268 flags: IconLookupFlags,
269 ) -> Option<IconInfo> {
270 unsafe {
271 from_glib_full(gtk_sys::gtk_icon_theme_lookup_by_gicon(
272 self.as_ref().to_glib_none().0,
273 icon.as_ref().to_glib_none().0,
274 size,
275 flags.to_glib(),
276 ))
277 }
278 }
279
280 fn lookup_by_gicon_for_scale<P: IsA<gio::Icon>>(
281 &self,
282 icon: &P,
283 size: i32,
284 scale: i32,
285 flags: IconLookupFlags,
286 ) -> Option<IconInfo> {
287 unsafe {
288 from_glib_full(gtk_sys::gtk_icon_theme_lookup_by_gicon_for_scale(
289 self.as_ref().to_glib_none().0,
290 icon.as_ref().to_glib_none().0,
291 size,
292 scale,
293 flags.to_glib(),
294 ))
295 }
296 }
297
298 fn lookup_icon(&self, icon_name: &str, size: i32, flags: IconLookupFlags) -> Option<IconInfo> {
299 unsafe {
300 from_glib_full(gtk_sys::gtk_icon_theme_lookup_icon(
301 self.as_ref().to_glib_none().0,
302 icon_name.to_glib_none().0,
303 size,
304 flags.to_glib(),
305 ))
306 }
307 }
308
309 fn lookup_icon_for_scale(
310 &self,
311 icon_name: &str,
312 size: i32,
313 scale: i32,
314 flags: IconLookupFlags,
315 ) -> Option<IconInfo> {
316 unsafe {
317 from_glib_full(gtk_sys::gtk_icon_theme_lookup_icon_for_scale(
318 self.as_ref().to_glib_none().0,
319 icon_name.to_glib_none().0,
320 size,
321 scale,
322 flags.to_glib(),
323 ))
324 }
325 }
326
327 fn prepend_search_path<P: AsRef<std::path::Path>>(&self, path: P) {
328 unsafe {
329 gtk_sys::gtk_icon_theme_prepend_search_path(
330 self.as_ref().to_glib_none().0,
331 path.as_ref().to_glib_none().0,
332 );
333 }
334 }
335
336 fn rescan_if_needed(&self) -> bool {
337 unsafe {
338 from_glib(gtk_sys::gtk_icon_theme_rescan_if_needed(
339 self.as_ref().to_glib_none().0,
340 ))
341 }
342 }
343
344 fn set_custom_theme(&self, theme_name: Option<&str>) {
345 unsafe {
346 gtk_sys::gtk_icon_theme_set_custom_theme(
347 self.as_ref().to_glib_none().0,
348 theme_name.to_glib_none().0,
349 );
350 }
351 }
352
353 fn set_screen(&self, screen: &gdk::Screen) {
354 unsafe {
355 gtk_sys::gtk_icon_theme_set_screen(
356 self.as_ref().to_glib_none().0,
357 screen.to_glib_none().0,
358 );
359 }
360 }
361
362 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
363 unsafe extern "C" fn changed_trampoline<P, F: Fn(&P) + 'static>(
364 this: *mut gtk_sys::GtkIconTheme,
365 f: glib_sys::gpointer,
366 ) where
367 P: IsA<IconTheme>,
368 {
369 let f: &F = &*(f as *const F);
370 f(&IconTheme::from_glib_borrow(this).unsafe_cast())
371 }
372 unsafe {
373 let f: Box_<F> = Box_::new(f);
374 connect_raw(
375 self.as_ptr() as *mut _,
376 b"changed\0".as_ptr() as *const _,
377 Some(transmute(changed_trampoline::<Self, F> as usize)),
378 Box_::into_raw(f),
379 )
380 }
381 }
382}
383
384impl fmt::Display for IconTheme {
385 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386 write!(f, "IconTheme")
387 }
388}