egui_desktop/utils/
resize_handles.rs

1use egui::{
2    Area, Context, CursorIcon, Id, PointerButton, Pos2, ResizeDirection, Sense, Vec2,
3    ViewportCommand,
4};
5
6/// Render invisible viewport resize handles around the window.
7pub fn render_resize_handles(ctx: &Context) {
8    let screen_rect = ctx.screen_rect();
9    let resize_handle_size = 8.0;
10
11    if screen_rect.width() < 100.0 || screen_rect.height() < 100.0 {
12        return;
13    }
14
15    create_resize_handle(
16        ctx,
17        "resize_top",
18        "resize_top_handle",
19        Pos2::new(screen_rect.min.x, screen_rect.min.y),
20        Vec2::new(screen_rect.width(), resize_handle_size),
21        CursorIcon::ResizeVertical,
22        ResizeDirection::North,
23    );
24
25    create_resize_handle(
26        ctx,
27        "resize_bottom",
28        "resize_bottom_handle",
29        Pos2::new(screen_rect.min.x, screen_rect.max.y - resize_handle_size),
30        Vec2::new(screen_rect.width(), resize_handle_size),
31        CursorIcon::ResizeVertical,
32        ResizeDirection::South,
33    );
34
35    create_resize_handle(
36        ctx,
37        "resize_left",
38        "resize_left_handle",
39        Pos2::new(screen_rect.min.x, screen_rect.min.y),
40        Vec2::new(resize_handle_size, screen_rect.height()),
41        CursorIcon::ResizeHorizontal,
42        ResizeDirection::West,
43    );
44
45    create_resize_handle(
46        ctx,
47        "resize_right",
48        "resize_right_handle",
49        Pos2::new(screen_rect.max.x - resize_handle_size, screen_rect.min.y),
50        Vec2::new(resize_handle_size, screen_rect.height()),
51        CursorIcon::ResizeHorizontal,
52        ResizeDirection::East,
53    );
54
55    let corner_size = resize_handle_size * 1.5;
56
57    if screen_rect.width() > corner_size * 2.0 && screen_rect.height() > corner_size * 2.0 {
58        create_resize_handle(
59            ctx,
60            "resize_top_left",
61            "resize_top_left_handle",
62            Pos2::new(screen_rect.min.x, screen_rect.min.y),
63            Vec2::new(corner_size, corner_size),
64            CursorIcon::ResizeNwSe,
65            ResizeDirection::NorthWest,
66        );
67
68        create_resize_handle(
69            ctx,
70            "resize_top_right",
71            "resize_top_right_handle",
72            Pos2::new(screen_rect.max.x - corner_size, screen_rect.min.y),
73            Vec2::new(corner_size, corner_size),
74            CursorIcon::ResizeNeSw,
75            ResizeDirection::NorthEast,
76        );
77
78        create_resize_handle(
79            ctx,
80            "resize_bottom_left",
81            "resize_bottom_left_handle",
82            Pos2::new(screen_rect.min.x, screen_rect.max.y - corner_size),
83            Vec2::new(corner_size, corner_size),
84            CursorIcon::ResizeNeSw,
85            ResizeDirection::SouthWest,
86        );
87
88        create_resize_handle(
89            ctx,
90            "resize_bottom_right",
91            "resize_bottom_right_handle",
92            Pos2::new(
93                screen_rect.max.x - corner_size,
94                screen_rect.max.y - corner_size,
95            ),
96            Vec2::new(corner_size, corner_size),
97            CursorIcon::ResizeNwSe,
98            ResizeDirection::SouthEast,
99        );
100    }
101}
102
103fn create_resize_handle(
104    ctx: &Context,
105    area_id: &str,
106    handle_id: &str,
107    position: Pos2,
108    size: Vec2,
109    cursor_icon: CursorIcon,
110    resize_direction: ResizeDirection,
111) {
112    Area::new(Id::new(area_id))
113        .fixed_pos(position)
114        .show(ctx, |ui| {
115            ui.set_min_size(size);
116            let (_id, response) = ui.allocate_space(size);
117            let interaction_response =
118                ui.interact(response, Id::new(handle_id), Sense::click_and_drag());
119
120            if interaction_response.hovered() {
121                ctx.set_cursor_icon(cursor_icon);
122            }
123
124            if interaction_response.drag_started_by(PointerButton::Primary) {
125                ctx.send_viewport_cmd(ViewportCommand::BeginResize(resize_direction));
126            }
127        });
128}