journey/widgets/
diff_pane.rs1use saudade::{Event, EventCtx, Painter, PopupRequest, Rect, Theme, Widget};
12
13use crate::backend::Diff;
14use crate::imagediff::ImageComparison;
15use crate::widgets::{DiffMode, DiffView, ImageDiffView};
16
17pub struct DiffPane {
19 text: DiffView,
20 image: ImageDiffView,
21 showing_image: bool,
22 focused: bool,
23}
24
25impl DiffPane {
26 pub fn new(rect: Rect) -> Self {
27 Self {
28 text: DiffView::new(rect),
29 image: ImageDiffView::new(rect),
30 showing_image: false,
31 focused: false,
32 }
33 }
34
35 pub fn with_font_size(mut self, size: f32) -> Self {
36 self.text = self.text.with_font_size(size);
37 self.image = self.image.with_font_size(size);
38 self
39 }
40
41 pub fn set_diff(&mut self, diff: Diff) {
43 self.text.set_diff(diff);
44 self.set_showing_image(false);
45 }
46
47 pub fn show_image(&mut self, comparison: ImageComparison) {
49 self.image.set_comparison(Some(comparison));
50 self.set_showing_image(true);
51 }
52
53 pub fn showing_image(&self) -> bool {
55 self.showing_image
56 }
57
58 pub fn cycle_image_mode(&mut self) {
61 if self.showing_image {
62 self.image.cycle_mode();
63 }
64 }
65
66 pub fn show_image_side(&mut self, before: bool) {
69 if self.showing_image {
70 self.image.show_side(before);
71 }
72 }
73
74 pub fn set_mode(&mut self, mode: DiffMode) {
77 self.text.set_mode(mode);
78 }
79
80 pub fn take_action(&mut self) -> Option<(usize, usize)> {
83 if self.showing_image {
84 None
85 } else {
86 self.text.take_action()
87 }
88 }
89
90 pub fn is_empty(&self) -> bool {
91 if self.showing_image {
92 self.image.is_empty()
93 } else {
94 self.text.is_empty()
95 }
96 }
97
98 fn set_showing_image(&mut self, showing_image: bool) {
101 if showing_image == self.showing_image {
102 return;
103 }
104 self.showing_image = showing_image;
105 if self.focused {
106 self.text.set_focused(!showing_image);
107 self.image.set_focused(showing_image);
108 }
109 }
110
111 fn active(&self) -> &dyn Widget {
112 if self.showing_image {
113 &self.image
114 } else {
115 &self.text
116 }
117 }
118
119 fn active_mut(&mut self) -> &mut dyn Widget {
120 if self.showing_image {
121 &mut self.image
122 } else {
123 &mut self.text
124 }
125 }
126}
127
128impl Widget for DiffPane {
129 fn bounds(&self) -> Rect {
130 self.active().bounds()
131 }
132
133 fn paint(&mut self, painter: &mut Painter, theme: &Theme) {
134 self.active_mut().paint(painter, theme);
135 }
136
137 fn event(&mut self, event: &Event, ctx: &mut EventCtx) {
138 self.active_mut().event(event, ctx);
139 }
140
141 fn captures_pointer(&self) -> bool {
142 self.active().captures_pointer()
143 }
144
145 fn focusable(&self) -> bool {
146 self.active().focusable()
147 }
148
149 fn set_focused(&mut self, focused: bool) {
150 self.focused = focused;
151 self.active_mut().set_focused(focused);
152 }
153
154 fn focus_first(&mut self) -> bool {
155 self.focused = true;
156 self.active_mut().focus_first()
157 }
158
159 fn layout(&mut self, bounds: Rect) {
160 self.text.layout(bounds);
163 self.image.layout(bounds);
164 }
165
166 fn wants_ticks(&self) -> bool {
167 self.active().wants_ticks()
168 }
169
170 fn popup_request(&self) -> Option<PopupRequest> {
171 self.active().popup_request()
172 }
173}