relm4/abstractions/
drawing.rs1use std::cell::RefCell;
6use std::ops::Deref;
7use std::rc::Rc;
8
9use gtk::cairo::{Context, Format, ImageSurface};
10use gtk::prelude::{DrawingAreaExtManual, WidgetExt};
11
12#[derive(Clone, Debug)]
13struct Surface {
14 surface: Rc<RefCell<ImageSurface>>,
15}
16
17impl Surface {
18 fn new(surface: ImageSurface) -> Self {
19 Self {
20 surface: Rc::new(RefCell::new(surface)),
21 }
22 }
23
24 fn get(&self) -> ImageSurface {
25 self.surface.borrow().clone()
26 }
27
28 fn set(&self, surface: &ImageSurface) {
29 *self.surface.borrow_mut() = surface.clone();
30 }
31}
32
33#[derive(Debug)]
34pub struct DrawContext {
37 context: Context,
38 draw_surface: Surface,
39 edit_surface: ImageSurface,
40 drawing_area: gtk::DrawingArea,
41}
42
43impl DrawContext {
44 fn new(
45 draw_surface: &Surface,
46 edit_surface: &ImageSurface,
47 drawing_area: >k::DrawingArea,
48 ) -> Self {
49 Self {
50 context: Context::new(edit_surface).unwrap(),
51 draw_surface: draw_surface.clone(),
52 edit_surface: edit_surface.clone(),
53 drawing_area: drawing_area.clone(),
54 }
55 }
56}
57
58impl Deref for DrawContext {
59 type Target = Context;
60
61 fn deref(&self) -> &Self::Target {
62 &self.context
63 }
64}
65
66impl Drop for DrawContext {
67 fn drop(&mut self) {
68 self.draw_surface.set(&self.edit_surface);
69 self.drawing_area.queue_draw();
70 }
71}
72
73#[derive(Debug)]
75#[must_use]
76pub struct DrawHandler {
77 draw_surface: Surface,
78 edit_surface: ImageSurface,
79 drawing_area: gtk::DrawingArea,
80}
81
82impl Default for DrawHandler {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl DrawHandler {
89 pub fn new() -> Self {
91 Self::new_with_drawing_area(gtk::DrawingArea::default())
92 }
93
94 pub fn new_with_drawing_area(drawing_area: gtk::DrawingArea) -> Self {
96 let draw_surface = Surface::new(ImageSurface::create(Format::ARgb32, 100, 100).unwrap());
97 let edit_surface = ImageSurface::create(Format::ARgb32, 100, 100).unwrap();
98
99 use gtk::glib;
100 drawing_area.set_draw_func(glib::clone!(
101 #[strong]
102 draw_surface,
103 move |_, context, _, _| {
104 if let Err(error) = context.set_source_surface(draw_surface.get(), 0.0, 0.0) {
106 tracing::error!("Cannot set source surface: {:?}", error);
107 }
108
109 if let Err(error) = context.paint() {
110 tracing::error!("Cannot paint: {:?}", error);
111 }
112 }
113 ));
114
115 Self {
116 draw_surface,
117 edit_surface,
118 drawing_area,
119 }
120 }
121
122 #[allow(deprecated)]
126 pub fn get_context(&mut self) -> DrawContext {
127 let allocation = self.drawing_area.allocation();
128 let scale = self.drawing_area.scale_factor();
129 let width = allocation.width() * scale;
130 let height = allocation.height() * scale;
131
132 if (width, height) != (self.edit_surface.width(), self.edit_surface.height()) {
133 match ImageSurface::create(Format::ARgb32, width, height) {
134 Ok(surface) => {
135 surface.set_device_scale(f64::from(scale), f64::from(scale));
136 self.edit_surface = surface;
137 }
138 Err(error) => tracing::error!("Cannot resize image surface: {:?}", error),
139 }
140 }
141 DrawContext::new(&self.draw_surface, &self.edit_surface, &self.drawing_area)
142 }
143
144 #[must_use]
146 pub fn size(&self) -> (i32, i32) {
147 let scale = self.drawing_area.scale_factor();
148 (
149 self.edit_surface.width() / scale,
150 self.edit_surface.height() / scale,
151 )
152 }
153
154 #[must_use]
156 pub fn height(&self) -> i32 {
157 let scale = self.drawing_area.scale_factor();
158 self.edit_surface.height() / scale
159 }
160
161 #[must_use]
163 pub fn width(&self) -> i32 {
164 let scale = self.drawing_area.scale_factor();
165 self.edit_surface.width() / scale
166 }
167
168 #[must_use]
173 pub fn surface_height(&self) -> i32 {
174 self.edit_surface.height()
175 }
176
177 #[must_use]
182 pub fn surface_width(&self) -> i32 {
183 self.edit_surface.width()
184 }
185
186 #[must_use]
188 pub fn drawing_area(&self) -> >k::DrawingArea {
189 &self.drawing_area
190 }
191}