Skip to content

Commit 11df21e

Browse files
committed
[refactor] extract paint code from Ui/Context to new struct Painter
1 parent 5c14a15 commit 11df21e

18 files changed

+333
-309
lines changed

egui/src/containers/collapsing_header.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl State {
8787
*p = rect.center() + v;
8888
}
8989

90-
ui.add_paint_cmd(PaintCmd::Path {
90+
ui.painter().add(PaintCmd::Path {
9191
path: Path::from_point_loop(&points),
9292
closed: true,
9393
fill: None,
@@ -219,7 +219,7 @@ impl CollapsingHeader {
219219
state.toggle(ui);
220220
}
221221

222-
let where_to_put_background = ui.paint_list_len();
222+
let bg_index = ui.painter().add(PaintCmd::Noop);
223223

224224
{
225225
let (mut icon_rect, _) = ui.style().icon_rectangles(interact.rect);
@@ -234,15 +234,16 @@ impl CollapsingHeader {
234234
state.paint_icon(ui, &icon_interact);
235235
}
236236

237-
ui.add_galley(
237+
let painter = ui.painter();
238+
painter.add_galley(
238239
text_pos,
239240
galley,
240241
label.text_style,
241-
Some(ui.style().interact(&interact).stroke_color),
242+
ui.style().interact(&interact).stroke_color,
242243
);
243244

244-
ui.insert_paint_cmd(
245-
where_to_put_background,
245+
painter.set(
246+
bg_index,
246247
PaintCmd::Rect {
247248
corner_radius: ui.style().interact(&interact).corner_radius,
248249
fill: ui.style().interact(&interact).bg_fill,

egui/src/containers/frame.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Frame container
22
3-
use crate::{paint::*, *};
3+
use crate::{layers::PaintCmdIdx, paint::*, *};
44

55
#[derive(Clone, Debug, Default)]
66
pub struct Frame {
@@ -62,15 +62,15 @@ impl Frame {
6262
pub struct Prepared {
6363
pub frame: Frame,
6464
outer_rect_bounds: Rect,
65-
where_to_put_background: usize,
65+
where_to_put_background: PaintCmdIdx,
6666
pub content_ui: Ui,
6767
}
6868

6969
impl Frame {
7070
pub fn begin(self, ui: &mut Ui) -> Prepared {
7171
let outer_rect_bounds = ui.available();
7272
let inner_rect = outer_rect_bounds.shrink2(self.margin);
73-
let where_to_put_background = ui.paint_list_len();
73+
let where_to_put_background = ui.painter().add(PaintCmd::Noop);
7474
let content_ui = ui.child_ui(inner_rect);
7575
Prepared {
7676
frame: self,
@@ -105,7 +105,7 @@ impl Prepared {
105105
..
106106
} = self;
107107

108-
ui.insert_paint_cmd(
108+
ui.painter().set(
109109
where_to_put_background,
110110
PaintCmd::Rect {
111111
corner_radius: frame.corner_radius,

egui/src/containers/resize.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl Resize {
226226
// so we must follow the contents:
227227

228228
state.desired_size = state.desired_size.max(state.last_content_size);
229-
state.desired_size = ui.round_vec_to_pixels(state.desired_size);
229+
state.desired_size = ui.painter().round_vec_to_pixels(state.desired_size);
230230

231231
// We are as large as we look
232232
ui.allocate_space(state.desired_size);
@@ -240,7 +240,7 @@ impl Resize {
240240
if self.outline && corner_interact.is_some() {
241241
let rect = Rect::from_min_size(content_ui.top_left(), state.desired_size);
242242
let rect = rect.expand(2.0); // breathing room for content
243-
ui.add_paint_cmd(paint::PaintCmd::Rect {
243+
ui.painter().add(paint::PaintCmd::Rect {
244244
rect,
245245
corner_radius: 3.0,
246246
fill: None,
@@ -259,12 +259,12 @@ impl Resize {
259259
ui.memory().resize.insert(id, state);
260260

261261
if ui.ctx().style().debug_resize {
262-
ui.ctx().debug_rect(
262+
ui.ctx().debug_painter().debug_rect(
263263
Rect::from_min_size(content_ui.top_left(), state.desired_size),
264264
color::GREEN,
265265
"desired_size",
266266
);
267-
ui.ctx().debug_rect(
267+
ui.ctx().debug_painter().debug_rect(
268268
Rect::from_min_size(content_ui.top_left(), state.last_content_size),
269269
color::LIGHT_BLUE,
270270
"last_content_size",
@@ -277,11 +277,13 @@ fn paint_resize_corner(ui: &mut Ui, interact: &InteractInfo) {
277277
let color = ui.style().interact(interact).stroke_color;
278278
let width = ui.style().interact(interact).stroke_width;
279279

280-
let corner = ui.round_pos_to_pixels(interact.rect.right_bottom());
280+
let painter = ui.painter();
281+
282+
let corner = painter.round_pos_to_pixels(interact.rect.right_bottom());
281283
let mut w = 2.0;
282284

283285
while w < 12.0 {
284-
ui.add_paint_cmd(paint::PaintCmd::line_segment(
286+
painter.add(paint::PaintCmd::line_segment(
285287
[pos2(corner.x - w, corner.y), pos2(corner.x, corner.y - w)],
286288
color,
287289
width,

egui/src/containers/scroll_area.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,14 @@ impl Prepared {
268268
let handle_fill = style.interact(&interact).fill;
269269
let handle_outline = style.interact(&interact).rect_outline;
270270

271-
ui.add_paint_cmd(paint::PaintCmd::Rect {
271+
ui.painter().add(paint::PaintCmd::Rect {
272272
rect: outer_scroll_rect,
273273
corner_radius,
274274
fill: Some(ui.style().dark_bg_color),
275275
outline: None,
276276
});
277277

278-
ui.add_paint_cmd(paint::PaintCmd::Rect {
278+
ui.painter().add(paint::PaintCmd::Rect {
279279
rect: handle_rect.expand(-2.0),
280280
corner_radius,
281281
fill: Some(handle_fill),

egui/src/containers/window.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ fn paint_frame_interaction(
511511
path.add_circle_quadrant(pos2(max.x - cr, min.y + cr), cr, 3.0);
512512
path.add_line_segment([pos2(max.x, min.y + cr), pos2(max.x, max.y - cr)]);
513513
}
514-
ui.add_paint_cmd(PaintCmd::Path {
514+
ui.painter().add(PaintCmd::Path {
515515
path,
516516
closed: false,
517517
fill: None,
@@ -614,7 +614,7 @@ impl TitleBar {
614614
let left = outer_rect.left();
615615
let right = outer_rect.right();
616616
let y = content_rect.top() + ui.style().item_spacing.y * 0.5;
617-
ui.add_paint_cmd(PaintCmd::LineSegment {
617+
ui.painter().add(PaintCmd::LineSegment {
618618
points: [pos2(left, y), pos2(right, y)],
619619
style: ui.style().interact.inactive.rect_outline.unwrap(),
620620
});
@@ -650,12 +650,12 @@ fn close_button(ui: &mut Ui, rect: Rect) -> InteractInfo {
650650

651651
let stroke_color = ui.style().interact(&interact).stroke_color;
652652
let stroke_width = ui.style().interact(&interact).stroke_width;
653-
ui.add_paint_cmd(PaintCmd::line_segment(
653+
ui.painter().add(PaintCmd::line_segment(
654654
[rect.left_top(), rect.right_bottom()],
655655
stroke_color,
656656
stroke_width,
657657
));
658-
ui.add_paint_cmd(PaintCmd::line_segment(
658+
ui.painter().add(PaintCmd::line_segment(
659659
[rect.right_top(), rect.left_bottom()],
660660
stroke_color,
661661
stroke_width,

egui/src/context.rs

+17-102
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::Arc;
22

33
use {ahash::AHashMap, parking_lot::Mutex};
44

5-
use crate::{layout::align_rect, paint::*, *};
5+
use crate::{paint::*, *};
66

77
#[derive(Clone, Copy, Default)]
88
struct PaintStats {
@@ -234,7 +234,7 @@ impl Context {
234234

235235
/// Generate a id from the given source.
236236
/// If it is not unique, an error will be printed at the given position.
237-
pub fn make_unique_id<IdSource>(&self, source: IdSource, pos: Pos2) -> Id
237+
pub fn make_unique_id<IdSource>(self: &Arc<Self>, source: IdSource, pos: Pos2) -> Id
238238
where
239239
IdSource: std::hash::Hash + std::fmt::Debug + Copy,
240240
{
@@ -246,19 +246,25 @@ impl Context {
246246
}
247247

248248
/// If the given Id is not unique, an error will be printed at the given position.
249-
pub fn register_unique_id(&self, id: Id, source_name: impl std::fmt::Debug, pos: Pos2) -> Id {
249+
pub fn register_unique_id(
250+
self: &Arc<Self>,
251+
id: Id,
252+
source_name: impl std::fmt::Debug,
253+
pos: Pos2,
254+
) -> Id {
250255
if let Some(clash_pos) = self.used_ids.lock().insert(id, pos) {
256+
let painter = self.debug_painter();
251257
if clash_pos.distance(pos) < 4.0 {
252-
self.show_error(
258+
painter.error(
253259
pos,
254260
&format!("use of non-unique ID {:?} (name clash?)", source_name),
255261
);
256262
} else {
257-
self.show_error(
263+
painter.error(
258264
clash_pos,
259265
&format!("first use of non-unique ID {:?} (name clash?)", source_name),
260266
);
261-
self.show_error(
267+
painter.error(
262268
pos,
263269
&format!(
264270
"second use of non-unique ID {:?} (name clash?)",
@@ -422,103 +428,12 @@ impl Context {
422428
}
423429
}
424430
}
431+
}
425432

426-
// ---------------------------------------------------------------------
427-
428-
pub fn show_error(&self, pos: Pos2, text: impl Into<String>) {
429-
let text = text.into();
430-
let align = (Align::Min, Align::Min);
431-
let layer = Layer::debug();
432-
let text_style = TextStyle::Monospace;
433-
let font = &self.fonts()[text_style];
434-
let galley = font.layout_multiline(text, f32::INFINITY);
435-
let rect = align_rect(Rect::from_min_size(pos, galley.size), align);
436-
self.add_paint_cmd(
437-
layer,
438-
PaintCmd::Rect {
439-
corner_radius: 0.0,
440-
fill: Some(color::gray(0, 240)),
441-
outline: Some(LineStyle::new(1.0, color::RED)),
442-
rect: rect.expand(2.0),
443-
},
444-
);
445-
self.add_galley(layer, rect.min, galley, text_style, Some(color::RED));
446-
}
447-
448-
pub fn debug_text(&self, pos: Pos2, text: impl Into<String>) {
449-
let text = text.into();
450-
let layer = Layer::debug();
451-
let align = (Align::Min, Align::Min);
452-
self.floating_text(
453-
layer,
454-
pos,
455-
text,
456-
TextStyle::Monospace,
457-
align,
458-
Some(color::YELLOW),
459-
);
460-
}
461-
462-
pub fn debug_rect(&self, rect: Rect, color: Color, name: impl Into<String>) {
463-
let text = format!("{} {:?}", name.into(), rect);
464-
let layer = Layer::debug();
465-
self.add_paint_cmd(
466-
layer,
467-
PaintCmd::Rect {
468-
corner_radius: 0.0,
469-
fill: None,
470-
outline: Some(LineStyle::new(2.0, color)),
471-
rect,
472-
},
473-
);
474-
let align = (Align::Min, Align::Min);
475-
let text_style = TextStyle::Monospace;
476-
self.floating_text(layer, rect.min, text, text_style, align, Some(color));
477-
}
478-
479-
/// Show some text anywhere on screen.
480-
/// To center the text at the given position, use `align: (Center, Center)`.
481-
pub fn floating_text(
482-
&self,
483-
layer: Layer,
484-
pos: Pos2,
485-
text: String,
486-
text_style: TextStyle,
487-
align: (Align, Align),
488-
text_color: Option<Color>,
489-
) -> Rect {
490-
let font = &self.fonts()[text_style];
491-
let galley = font.layout_multiline(text, f32::INFINITY);
492-
let rect = align_rect(Rect::from_min_size(pos, galley.size), align);
493-
self.add_galley(layer, rect.min, galley, text_style, text_color);
494-
rect
495-
}
496-
497-
/// Already layed out text.
498-
pub fn add_galley(
499-
&self,
500-
layer: Layer,
501-
pos: Pos2,
502-
galley: font::Galley,
503-
text_style: TextStyle,
504-
color: Option<Color>,
505-
) {
506-
let color = color.unwrap_or_else(|| self.style().text_color);
507-
self.add_paint_cmd(
508-
layer,
509-
PaintCmd::Text {
510-
pos,
511-
galley,
512-
text_style,
513-
color,
514-
},
515-
);
516-
}
517-
518-
pub fn add_paint_cmd(&self, layer: Layer, paint_cmd: PaintCmd) {
519-
self.graphics()
520-
.layer(layer)
521-
.push((Rect::everything(), paint_cmd))
433+
/// ## Painting
434+
impl Context {
435+
pub fn debug_painter(self: &Arc<Self>) -> Painter {
436+
Painter::new(self.clone(), Layer::debug(), self.rect())
522437
}
523438
}
524439

egui/src/demos/app.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ impl BoxPainting {
469469
outline: Some(LineStyle::new(self.stroke_width, gray(255, 255))),
470470
});
471471
}
472-
ui.add_paint_cmds(cmds);
472+
ui.painter().extend(cmds);
473473
}
474474
}
475475

@@ -498,7 +498,8 @@ impl Painting {
498498
let rect = ui.allocate_space(ui.available_finite().size());
499499
let interact = ui.interact(rect, ui.id(), Sense::drag());
500500
let rect = interact.rect;
501-
ui.set_clip_rect(ui.clip_rect().intersect(rect)); // Make sure we don't paint out of bounds
501+
let clip_rect = ui.clip_rect().intersect(rect); // Make sure we don't paint out of bounds
502+
let painter = Painter::new(ui.ctx().clone(), ui.layer(), clip_rect);
502503

503504
if self.lines.is_empty() {
504505
self.lines.push(vec![]);
@@ -520,7 +521,7 @@ impl Painting {
520521
for line in &self.lines {
521522
if line.len() >= 2 {
522523
let points: Vec<Pos2> = line.iter().map(|p| rect.min + *p).collect();
523-
ui.add_paint_cmd(PaintCmd::Path {
524+
painter.add(PaintCmd::Path {
524525
path: Path::from_open_points(&points),
525526
closed: false,
526527
outline: Some(LineStyle::new(2.0, LIGHT_GRAY)),

0 commit comments

Comments
 (0)