teksilo_widgets/title_bar/
resize_strip.rs1use std::rc::Rc;
16
17use teksilo_canvas::{Rect, Size, SizeProposal};
18use teksilo_core::event::{EventResponse, PointerButton, WidgetEvent};
19use teksilo_core::widget::{CursorIcon, LayoutContext, PaintContext, Widget, WidgetPlacement};
20use teksilo_core::widget_builder::HandlerSet;
21use teksilo_core::widget_id::WidgetId;
22use teksilo_core::{PlatformTitleBarHost, ResizeEdge};
23
24pub struct ResizeStrip {
29 host: Rc<dyn PlatformTitleBarHost>,
30 edge: ResizeEdge,
31 width: f32,
32 height: f32,
33}
34
35impl std::fmt::Debug for ResizeStrip {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.debug_struct("ResizeStrip")
38 .field("edge", &self.edge)
39 .field("width", &self.width)
40 .field("height", &self.height)
41 .finish_non_exhaustive()
42 }
43}
44
45impl ResizeStrip {
46 pub fn horizontal(
50 host: Rc<dyn PlatformTitleBarHost>,
51 edge: ResizeEdge,
52 thickness: f32,
53 ) -> Self {
54 debug_assert!(matches!(edge, ResizeEdge::Top | ResizeEdge::Bottom));
55 Self {
56 host,
57 edge,
58 width: 0.0,
59 height: thickness,
60 }
61 }
62
63 pub fn vertical(host: Rc<dyn PlatformTitleBarHost>, edge: ResizeEdge, thickness: f32) -> Self {
66 debug_assert!(matches!(edge, ResizeEdge::Left | ResizeEdge::Right));
67 Self {
68 host,
69 edge,
70 width: thickness,
71 height: 0.0,
72 }
73 }
74
75 pub fn corner(host: Rc<dyn PlatformTitleBarHost>, edge: ResizeEdge, size: f32) -> Self {
81 debug_assert!(matches!(
82 edge,
83 ResizeEdge::TopLeft
84 | ResizeEdge::TopRight
85 | ResizeEdge::BottomLeft
86 | ResizeEdge::BottomRight
87 ));
88 Self {
89 host,
90 edge,
91 width: size,
92 height: size,
93 }
94 }
95}
96
97fn cursor_for_edge(edge: ResizeEdge) -> CursorIcon {
98 match edge {
99 ResizeEdge::Top | ResizeEdge::Bottom => CursorIcon::RowResize,
100 ResizeEdge::Left | ResizeEdge::Right => CursorIcon::ColResize,
101 ResizeEdge::TopLeft | ResizeEdge::BottomRight => CursorIcon::NwseResize,
103 ResizeEdge::TopRight | ResizeEdge::BottomLeft => CursorIcon::NeswResize,
105 }
106}
107
108impl Widget for ResizeStrip {
109 fn build(&mut self, ctx: &mut teksilo_core::build_context::BuildContext) -> Vec<WidgetId> {
110 let host = self.host.clone();
111 let edge = self.edge;
112
113 let handlers = HandlerSet::new()
114 .cursor(cursor_for_edge(edge))
115 .on_pointer_event(move |evt, _ctx| {
116 if let WidgetEvent::PointerDown {
117 button: PointerButton::Primary,
118 ..
119 } = evt
120 {
121 let _ = host.begin_resize(edge);
122 return EventResponse::Handled;
123 }
124 EventResponse::Ignored
125 });
126
127 ctx.apply_self_handlers(handlers);
128 Vec::new()
129 }
130
131 fn layout_response(
132 &self,
133 proposal: SizeProposal,
134 _ctx: &LayoutContext,
135 ) -> teksilo_core::widget::LayoutResponse {
136 let w = if self.width > 0.0 {
139 self.width
140 } else {
141 proposal.width.unwrap_or(0.0)
142 };
143 let h = if self.height > 0.0 {
144 self.height
145 } else {
146 proposal.height.unwrap_or(0.0)
147 };
148 Size::new(w, h).into()
149 }
150
151 fn place_children(
152 &self,
153 _bounds: Rect,
154 _proposal: SizeProposal,
155 _children: &mut [WidgetPlacement],
156 _ctx: &LayoutContext,
157 ) {
158 }
159
160 fn paint(&self, _bounds: Rect, _canvas: &mut teksilo_canvas::Canvas, _ctx: &PaintContext) {
161 }
163}