1use gdk;
6use glib::object::Cast;
7use glib::object::IsA;
8use glib::signal::connect_raw;
9use glib::signal::SignalHandlerId;
10use glib::translate::*;
11use glib::GString;
12use glib::StaticType;
13use glib::ToValue;
14use glib::Value;
15use glib_sys;
16use gobject_sys;
17use gtk_sys;
18use std::boxed::Box as Box_;
19use std::fmt;
20use std::mem::transmute;
21use Border;
22use CssSection;
23use JunctionSides;
24use StateFlags;
25#[cfg(any(feature = "v3_20", feature = "dox"))]
26use StyleContextPrintFlags;
27use StyleProvider;
28use TextDirection;
29use WidgetPath;
30
31glib_wrapper! {
32 pub struct StyleContext(Object<gtk_sys::GtkStyleContext, gtk_sys::GtkStyleContextClass, StyleContextClass>);
33
34 match fn {
35 get_type => || gtk_sys::gtk_style_context_get_type(),
36 }
37}
38
39impl StyleContext {
40 pub fn new() -> StyleContext {
41 assert_initialized_main_thread!();
42 unsafe { from_glib_full(gtk_sys::gtk_style_context_new()) }
43 }
44
45 pub fn add_provider_for_screen<P: IsA<StyleProvider>>(
46 screen: &gdk::Screen,
47 provider: &P,
48 priority: u32,
49 ) {
50 skip_assert_initialized!();
51 unsafe {
52 gtk_sys::gtk_style_context_add_provider_for_screen(
53 screen.to_glib_none().0,
54 provider.as_ref().to_glib_none().0,
55 priority,
56 );
57 }
58 }
59
60 pub fn remove_provider_for_screen<P: IsA<StyleProvider>>(screen: &gdk::Screen, provider: &P) {
61 skip_assert_initialized!();
62 unsafe {
63 gtk_sys::gtk_style_context_remove_provider_for_screen(
64 screen.to_glib_none().0,
65 provider.as_ref().to_glib_none().0,
66 );
67 }
68 }
69
70 pub fn reset_widgets(screen: &gdk::Screen) {
71 assert_initialized_main_thread!();
72 unsafe {
73 gtk_sys::gtk_style_context_reset_widgets(screen.to_glib_none().0);
74 }
75 }
76}
77
78impl Default for StyleContext {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84pub struct StyleContextBuilder {
85 direction: Option<TextDirection>,
86 paint_clock: Option<gdk::FrameClock>,
87 parent: Option<StyleContext>,
88 screen: Option<gdk::Screen>,
89}
90
91impl StyleContextBuilder {
92 pub fn new() -> Self {
93 Self {
94 direction: None,
95 paint_clock: None,
96 parent: None,
97 screen: None,
98 }
99 }
100
101 pub fn build(self) -> StyleContext {
102 let mut properties: Vec<(&str, &dyn ToValue)> = vec![];
103 if let Some(ref direction) = self.direction {
104 properties.push(("direction", direction));
105 }
106 if let Some(ref paint_clock) = self.paint_clock {
107 properties.push(("paint-clock", paint_clock));
108 }
109 if let Some(ref parent) = self.parent {
110 properties.push(("parent", parent));
111 }
112 if let Some(ref screen) = self.screen {
113 properties.push(("screen", screen));
114 }
115 glib::Object::new(StyleContext::static_type(), &properties)
116 .expect("object new")
117 .downcast()
118 .expect("downcast")
119 }
120
121 pub fn direction(mut self, direction: TextDirection) -> Self {
122 self.direction = Some(direction);
123 self
124 }
125
126 pub fn paint_clock(mut self, paint_clock: &gdk::FrameClock) -> Self {
127 self.paint_clock = Some(paint_clock.clone());
128 self
129 }
130
131 pub fn parent(mut self, parent: &StyleContext) -> Self {
132 self.parent = Some(parent.clone());
133 self
134 }
135
136 pub fn screen(mut self, screen: &gdk::Screen) -> Self {
137 self.screen = Some(screen.clone());
138 self
139 }
140}
141
142pub const NONE_STYLE_CONTEXT: Option<&StyleContext> = None;
143
144pub trait StyleContextExt: 'static {
145 fn add_class(&self, class_name: &str);
146
147 fn add_provider<P: IsA<StyleProvider>>(&self, provider: &P, priority: u32);
148
149 #[cfg_attr(feature = "v3_16", deprecated)]
152 fn get_background_color(&self, state: StateFlags) -> gdk::RGBA;
153
154 fn get_border(&self, state: StateFlags) -> Border;
155
156 #[cfg_attr(feature = "v3_16", deprecated)]
157 fn get_border_color(&self, state: StateFlags) -> gdk::RGBA;
158
159 fn get_color(&self, state: StateFlags) -> gdk::RGBA;
160
161 fn get_frame_clock(&self) -> Option<gdk::FrameClock>;
162
163 fn get_junction_sides(&self) -> JunctionSides;
164
165 fn get_margin(&self, state: StateFlags) -> Border;
166
167 fn get_padding(&self, state: StateFlags) -> Border;
168
169 fn get_parent(&self) -> Option<StyleContext>;
170
171 fn get_path(&self) -> Option<WidgetPath>;
172
173 fn get_scale(&self) -> i32;
174
175 fn get_screen(&self) -> Option<gdk::Screen>;
176
177 fn get_section(&self, property: &str) -> Option<CssSection>;
178
179 fn get_state(&self) -> StateFlags;
180
181 fn has_class(&self, class_name: &str) -> bool;
188
189 fn list_classes(&self) -> Vec<GString>;
190
191 fn lookup_color(&self, color_name: &str) -> Option<gdk::RGBA>;
192
193 fn remove_class(&self, class_name: &str);
194
195 fn remove_provider<P: IsA<StyleProvider>>(&self, provider: &P);
196
197 fn restore(&self);
198
199 fn save(&self);
200
201 #[cfg_attr(feature = "v3_18", deprecated)]
202 fn set_background<P: IsA<gdk::Window>>(&self, window: &P);
203
204 fn set_frame_clock(&self, frame_clock: &gdk::FrameClock);
205
206 fn set_junction_sides(&self, sides: JunctionSides);
207
208 fn set_parent<P: IsA<StyleContext>>(&self, parent: Option<&P>);
209
210 fn set_path(&self, path: &WidgetPath);
211
212 fn set_scale(&self, scale: i32);
213
214 fn set_screen(&self, screen: &gdk::Screen);
215
216 fn set_state(&self, flags: StateFlags);
217
218 #[cfg(any(feature = "v3_20", feature = "dox"))]
219 fn to_string(&self, flags: StyleContextPrintFlags) -> GString;
220
221 fn get_property_direction(&self) -> TextDirection;
222
223 fn set_property_direction(&self, direction: TextDirection);
224
225 fn get_property_paint_clock(&self) -> Option<gdk::FrameClock>;
226
227 fn set_property_paint_clock(&self, paint_clock: Option<&gdk::FrameClock>);
228
229 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
230
231 fn connect_property_direction_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
232
233 fn connect_property_paint_clock_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
234
235 fn connect_property_parent_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
236
237 fn connect_property_screen_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
238}
239
240impl<O: IsA<StyleContext>> StyleContextExt for O {
241 fn add_class(&self, class_name: &str) {
242 unsafe {
243 gtk_sys::gtk_style_context_add_class(
244 self.as_ref().to_glib_none().0,
245 class_name.to_glib_none().0,
246 );
247 }
248 }
249
250 fn add_provider<P: IsA<StyleProvider>>(&self, provider: &P, priority: u32) {
251 unsafe {
252 gtk_sys::gtk_style_context_add_provider(
253 self.as_ref().to_glib_none().0,
254 provider.as_ref().to_glib_none().0,
255 priority,
256 );
257 }
258 }
259
260 fn get_background_color(&self, state: StateFlags) -> gdk::RGBA {
265 unsafe {
266 let mut color = gdk::RGBA::uninitialized();
267 gtk_sys::gtk_style_context_get_background_color(
268 self.as_ref().to_glib_none().0,
269 state.to_glib(),
270 color.to_glib_none_mut().0,
271 );
272 color
273 }
274 }
275
276 fn get_border(&self, state: StateFlags) -> Border {
277 unsafe {
278 let mut border = Border::uninitialized();
279 gtk_sys::gtk_style_context_get_border(
280 self.as_ref().to_glib_none().0,
281 state.to_glib(),
282 border.to_glib_none_mut().0,
283 );
284 border
285 }
286 }
287
288 fn get_border_color(&self, state: StateFlags) -> gdk::RGBA {
289 unsafe {
290 let mut color = gdk::RGBA::uninitialized();
291 gtk_sys::gtk_style_context_get_border_color(
292 self.as_ref().to_glib_none().0,
293 state.to_glib(),
294 color.to_glib_none_mut().0,
295 );
296 color
297 }
298 }
299
300 fn get_color(&self, state: StateFlags) -> gdk::RGBA {
301 unsafe {
302 let mut color = gdk::RGBA::uninitialized();
303 gtk_sys::gtk_style_context_get_color(
304 self.as_ref().to_glib_none().0,
305 state.to_glib(),
306 color.to_glib_none_mut().0,
307 );
308 color
309 }
310 }
311
312 fn get_frame_clock(&self) -> Option<gdk::FrameClock> {
313 unsafe {
314 from_glib_none(gtk_sys::gtk_style_context_get_frame_clock(
315 self.as_ref().to_glib_none().0,
316 ))
317 }
318 }
319
320 fn get_junction_sides(&self) -> JunctionSides {
321 unsafe {
322 from_glib(gtk_sys::gtk_style_context_get_junction_sides(
323 self.as_ref().to_glib_none().0,
324 ))
325 }
326 }
327
328 fn get_margin(&self, state: StateFlags) -> Border {
329 unsafe {
330 let mut margin = Border::uninitialized();
331 gtk_sys::gtk_style_context_get_margin(
332 self.as_ref().to_glib_none().0,
333 state.to_glib(),
334 margin.to_glib_none_mut().0,
335 );
336 margin
337 }
338 }
339
340 fn get_padding(&self, state: StateFlags) -> Border {
341 unsafe {
342 let mut padding = Border::uninitialized();
343 gtk_sys::gtk_style_context_get_padding(
344 self.as_ref().to_glib_none().0,
345 state.to_glib(),
346 padding.to_glib_none_mut().0,
347 );
348 padding
349 }
350 }
351
352 fn get_parent(&self) -> Option<StyleContext> {
353 unsafe {
354 from_glib_none(gtk_sys::gtk_style_context_get_parent(
355 self.as_ref().to_glib_none().0,
356 ))
357 }
358 }
359
360 fn get_path(&self) -> Option<WidgetPath> {
361 unsafe {
362 from_glib_none(gtk_sys::gtk_style_context_get_path(
363 self.as_ref().to_glib_none().0,
364 ))
365 }
366 }
367
368 fn get_scale(&self) -> i32 {
369 unsafe { gtk_sys::gtk_style_context_get_scale(self.as_ref().to_glib_none().0) }
370 }
371
372 fn get_screen(&self) -> Option<gdk::Screen> {
373 unsafe {
374 from_glib_none(gtk_sys::gtk_style_context_get_screen(
375 self.as_ref().to_glib_none().0,
376 ))
377 }
378 }
379
380 fn get_section(&self, property: &str) -> Option<CssSection> {
381 unsafe {
382 from_glib_none(gtk_sys::gtk_style_context_get_section(
383 self.as_ref().to_glib_none().0,
384 property.to_glib_none().0,
385 ))
386 }
387 }
388
389 fn get_state(&self) -> StateFlags {
390 unsafe {
391 from_glib(gtk_sys::gtk_style_context_get_state(
392 self.as_ref().to_glib_none().0,
393 ))
394 }
395 }
396
397 fn has_class(&self, class_name: &str) -> bool {
410 unsafe {
411 from_glib(gtk_sys::gtk_style_context_has_class(
412 self.as_ref().to_glib_none().0,
413 class_name.to_glib_none().0,
414 ))
415 }
416 }
417
418 fn list_classes(&self) -> Vec<GString> {
419 unsafe {
420 FromGlibPtrContainer::from_glib_container(gtk_sys::gtk_style_context_list_classes(
421 self.as_ref().to_glib_none().0,
422 ))
423 }
424 }
425
426 fn lookup_color(&self, color_name: &str) -> Option<gdk::RGBA> {
427 unsafe {
428 let mut color = gdk::RGBA::uninitialized();
429 let ret = from_glib(gtk_sys::gtk_style_context_lookup_color(
430 self.as_ref().to_glib_none().0,
431 color_name.to_glib_none().0,
432 color.to_glib_none_mut().0,
433 ));
434 if ret {
435 Some(color)
436 } else {
437 None
438 }
439 }
440 }
441
442 fn remove_class(&self, class_name: &str) {
443 unsafe {
444 gtk_sys::gtk_style_context_remove_class(
445 self.as_ref().to_glib_none().0,
446 class_name.to_glib_none().0,
447 );
448 }
449 }
450
451 fn remove_provider<P: IsA<StyleProvider>>(&self, provider: &P) {
452 unsafe {
453 gtk_sys::gtk_style_context_remove_provider(
454 self.as_ref().to_glib_none().0,
455 provider.as_ref().to_glib_none().0,
456 );
457 }
458 }
459
460 fn restore(&self) {
461 unsafe {
462 gtk_sys::gtk_style_context_restore(self.as_ref().to_glib_none().0);
463 }
464 }
465
466 fn save(&self) {
467 unsafe {
468 gtk_sys::gtk_style_context_save(self.as_ref().to_glib_none().0);
469 }
470 }
471
472 fn set_background<P: IsA<gdk::Window>>(&self, window: &P) {
473 unsafe {
474 gtk_sys::gtk_style_context_set_background(
475 self.as_ref().to_glib_none().0,
476 window.as_ref().to_glib_none().0,
477 );
478 }
479 }
480
481 fn set_frame_clock(&self, frame_clock: &gdk::FrameClock) {
482 unsafe {
483 gtk_sys::gtk_style_context_set_frame_clock(
484 self.as_ref().to_glib_none().0,
485 frame_clock.to_glib_none().0,
486 );
487 }
488 }
489
490 fn set_junction_sides(&self, sides: JunctionSides) {
491 unsafe {
492 gtk_sys::gtk_style_context_set_junction_sides(
493 self.as_ref().to_glib_none().0,
494 sides.to_glib(),
495 );
496 }
497 }
498
499 fn set_parent<P: IsA<StyleContext>>(&self, parent: Option<&P>) {
500 unsafe {
501 gtk_sys::gtk_style_context_set_parent(
502 self.as_ref().to_glib_none().0,
503 parent.map(|p| p.as_ref()).to_glib_none().0,
504 );
505 }
506 }
507
508 fn set_path(&self, path: &WidgetPath) {
509 unsafe {
510 gtk_sys::gtk_style_context_set_path(
511 self.as_ref().to_glib_none().0,
512 path.to_glib_none().0,
513 );
514 }
515 }
516
517 fn set_scale(&self, scale: i32) {
518 unsafe {
519 gtk_sys::gtk_style_context_set_scale(self.as_ref().to_glib_none().0, scale);
520 }
521 }
522
523 fn set_screen(&self, screen: &gdk::Screen) {
524 unsafe {
525 gtk_sys::gtk_style_context_set_screen(
526 self.as_ref().to_glib_none().0,
527 screen.to_glib_none().0,
528 );
529 }
530 }
531
532 fn set_state(&self, flags: StateFlags) {
533 unsafe {
534 gtk_sys::gtk_style_context_set_state(self.as_ref().to_glib_none().0, flags.to_glib());
535 }
536 }
537
538 #[cfg(any(feature = "v3_20", feature = "dox"))]
539 fn to_string(&self, flags: StyleContextPrintFlags) -> GString {
540 unsafe {
541 from_glib_full(gtk_sys::gtk_style_context_to_string(
542 self.as_ref().to_glib_none().0,
543 flags.to_glib(),
544 ))
545 }
546 }
547
548 fn get_property_direction(&self) -> TextDirection {
549 unsafe {
550 let mut value = Value::from_type(<TextDirection as StaticType>::static_type());
551 gobject_sys::g_object_get_property(
552 self.to_glib_none().0 as *mut gobject_sys::GObject,
553 b"direction\0".as_ptr() as *const _,
554 value.to_glib_none_mut().0,
555 );
556 value.get().unwrap()
557 }
558 }
559
560 fn set_property_direction(&self, direction: TextDirection) {
561 unsafe {
562 gobject_sys::g_object_set_property(
563 self.to_glib_none().0 as *mut gobject_sys::GObject,
564 b"direction\0".as_ptr() as *const _,
565 Value::from(&direction).to_glib_none().0,
566 );
567 }
568 }
569
570 fn get_property_paint_clock(&self) -> Option<gdk::FrameClock> {
571 unsafe {
572 let mut value = Value::from_type(<gdk::FrameClock as StaticType>::static_type());
573 gobject_sys::g_object_get_property(
574 self.to_glib_none().0 as *mut gobject_sys::GObject,
575 b"paint-clock\0".as_ptr() as *const _,
576 value.to_glib_none_mut().0,
577 );
578 value.get()
579 }
580 }
581
582 fn set_property_paint_clock(&self, paint_clock: Option<&gdk::FrameClock>) {
583 unsafe {
584 gobject_sys::g_object_set_property(
585 self.to_glib_none().0 as *mut gobject_sys::GObject,
586 b"paint-clock\0".as_ptr() as *const _,
587 Value::from(paint_clock).to_glib_none().0,
588 );
589 }
590 }
591
592 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
593 unsafe extern "C" fn changed_trampoline<P, F: Fn(&P) + 'static>(
594 this: *mut gtk_sys::GtkStyleContext,
595 f: glib_sys::gpointer,
596 ) where
597 P: IsA<StyleContext>,
598 {
599 let f: &F = &*(f as *const F);
600 f(&StyleContext::from_glib_borrow(this).unsafe_cast())
601 }
602 unsafe {
603 let f: Box_<F> = Box_::new(f);
604 connect_raw(
605 self.as_ptr() as *mut _,
606 b"changed\0".as_ptr() as *const _,
607 Some(transmute(changed_trampoline::<Self, F> as usize)),
608 Box_::into_raw(f),
609 )
610 }
611 }
612
613 fn connect_property_direction_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
614 unsafe extern "C" fn notify_direction_trampoline<P, F: Fn(&P) + 'static>(
615 this: *mut gtk_sys::GtkStyleContext,
616 _param_spec: glib_sys::gpointer,
617 f: glib_sys::gpointer,
618 ) where
619 P: IsA<StyleContext>,
620 {
621 let f: &F = &*(f as *const F);
622 f(&StyleContext::from_glib_borrow(this).unsafe_cast())
623 }
624 unsafe {
625 let f: Box_<F> = Box_::new(f);
626 connect_raw(
627 self.as_ptr() as *mut _,
628 b"notify::direction\0".as_ptr() as *const _,
629 Some(transmute(notify_direction_trampoline::<Self, F> as usize)),
630 Box_::into_raw(f),
631 )
632 }
633 }
634
635 fn connect_property_paint_clock_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
636 unsafe extern "C" fn notify_paint_clock_trampoline<P, F: Fn(&P) + 'static>(
637 this: *mut gtk_sys::GtkStyleContext,
638 _param_spec: glib_sys::gpointer,
639 f: glib_sys::gpointer,
640 ) where
641 P: IsA<StyleContext>,
642 {
643 let f: &F = &*(f as *const F);
644 f(&StyleContext::from_glib_borrow(this).unsafe_cast())
645 }
646 unsafe {
647 let f: Box_<F> = Box_::new(f);
648 connect_raw(
649 self.as_ptr() as *mut _,
650 b"notify::paint-clock\0".as_ptr() as *const _,
651 Some(transmute(notify_paint_clock_trampoline::<Self, F> as usize)),
652 Box_::into_raw(f),
653 )
654 }
655 }
656
657 fn connect_property_parent_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
658 unsafe extern "C" fn notify_parent_trampoline<P, F: Fn(&P) + 'static>(
659 this: *mut gtk_sys::GtkStyleContext,
660 _param_spec: glib_sys::gpointer,
661 f: glib_sys::gpointer,
662 ) where
663 P: IsA<StyleContext>,
664 {
665 let f: &F = &*(f as *const F);
666 f(&StyleContext::from_glib_borrow(this).unsafe_cast())
667 }
668 unsafe {
669 let f: Box_<F> = Box_::new(f);
670 connect_raw(
671 self.as_ptr() as *mut _,
672 b"notify::parent\0".as_ptr() as *const _,
673 Some(transmute(notify_parent_trampoline::<Self, F> as usize)),
674 Box_::into_raw(f),
675 )
676 }
677 }
678
679 fn connect_property_screen_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
680 unsafe extern "C" fn notify_screen_trampoline<P, F: Fn(&P) + 'static>(
681 this: *mut gtk_sys::GtkStyleContext,
682 _param_spec: glib_sys::gpointer,
683 f: glib_sys::gpointer,
684 ) where
685 P: IsA<StyleContext>,
686 {
687 let f: &F = &*(f as *const F);
688 f(&StyleContext::from_glib_borrow(this).unsafe_cast())
689 }
690 unsafe {
691 let f: Box_<F> = Box_::new(f);
692 connect_raw(
693 self.as_ptr() as *mut _,
694 b"notify::screen\0".as_ptr() as *const _,
695 Some(transmute(notify_screen_trampoline::<Self, F> as usize)),
696 Box_::into_raw(f),
697 )
698 }
699 }
700}
701
702impl fmt::Display for StyleContext {
703 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
704 write!(f, "StyleContext")
705 }
706}