style: apply cargo fmt across the crate (A20)
The repo never enforced rustfmt, so formatting had drifted broadly. This is a single mechanical `cargo fmt` pass over the whole crate (no behavioral change; lib suite green, 493 passed). Going forward fmt should be enforced (planned CI fmt --check step). Part of the 0.6.1 hygiene pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+70
-75
@@ -9,8 +9,8 @@ use iced::advanced::widget::{self, Widget};
|
||||
use iced::advanced::{Layout, Shell};
|
||||
use iced::widget::text_input;
|
||||
use iced::{
|
||||
alignment, Background, Border, Color, Element, Event, Length, Padding,
|
||||
Pixels, Point, Rectangle, Shadow, Size, Vector,
|
||||
Background, Border, Color, Element, Event, Length, Padding, Pixels, Point, Rectangle, Shadow,
|
||||
Size, Vector, alignment,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -27,11 +27,7 @@ pub fn copy_selection(value: &str, start: usize, end: usize) -> Option<String> {
|
||||
(start != end).then(|| value.select(start, end).to_string())
|
||||
}
|
||||
|
||||
pub fn cut_selection(
|
||||
value: &str,
|
||||
start: usize,
|
||||
end: usize,
|
||||
) -> (Edit, Option<String>) {
|
||||
pub fn cut_selection(value: &str, start: usize, end: usize) -> (Edit, Option<String>) {
|
||||
let mut value = text_input::Value::new(value);
|
||||
let (start, end) = normalized_range(&value, start, end);
|
||||
|
||||
@@ -80,18 +76,13 @@ pub fn select_all_range(value: &str) -> (usize, usize) {
|
||||
(0, value.len())
|
||||
}
|
||||
|
||||
fn normalized_range(
|
||||
value: &text_input::Value,
|
||||
start: usize,
|
||||
end: usize,
|
||||
) -> (usize, usize) {
|
||||
fn normalized_range(value: &text_input::Value, start: usize, end: usize) -> (usize, usize) {
|
||||
let len = value.len();
|
||||
|
||||
(start.min(end).min(len), start.max(end).min(len))
|
||||
}
|
||||
|
||||
type InputStyleFn<'a, Theme> =
|
||||
Rc<dyn Fn(&Theme, text_input::Status) -> text_input::Style + 'a>;
|
||||
type InputStyleFn<'a, Theme> = Rc<dyn Fn(&Theme, text_input::Status) -> text_input::Style + 'a>;
|
||||
|
||||
pub fn context_input<'a, Message, Theme, Renderer>(
|
||||
placeholder: &str,
|
||||
@@ -119,12 +110,8 @@ where
|
||||
.locked(true)
|
||||
}
|
||||
|
||||
pub struct ContextInput<
|
||||
'a,
|
||||
Message,
|
||||
Theme = iced::Theme,
|
||||
Renderer = iced::Renderer,
|
||||
> where
|
||||
pub struct ContextInput<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer>
|
||||
where
|
||||
Theme: text_input::Catalog,
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
@@ -137,8 +124,7 @@ pub struct ContextInput<
|
||||
style: Option<InputStyleFn<'a, Theme>>,
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer>
|
||||
ContextInput<'a, Message, Theme, Renderer>
|
||||
impl<'a, Message, Theme, Renderer> ContextInput<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone + 'a,
|
||||
Theme: text_input::Catalog + 'a,
|
||||
@@ -172,16 +158,13 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_input(
|
||||
mut self,
|
||||
on_input: impl Fn(String) -> Message + 'a,
|
||||
) -> Self {
|
||||
let on_input: Rc<dyn Fn(String) -> Message + 'a> =
|
||||
Rc::new(on_input);
|
||||
pub fn on_input(mut self, on_input: impl Fn(String) -> Message + 'a) -> Self {
|
||||
let on_input: Rc<dyn Fn(String) -> Message + 'a> = Rc::new(on_input);
|
||||
let input_callback = Rc::clone(&on_input);
|
||||
|
||||
self.input =
|
||||
self.input.on_input(move |value| input_callback.as_ref()(value));
|
||||
self.input = self
|
||||
.input
|
||||
.on_input(move |value| input_callback.as_ref()(value));
|
||||
self.on_input = Some(on_input);
|
||||
self
|
||||
}
|
||||
@@ -196,16 +179,13 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_paste(
|
||||
mut self,
|
||||
on_paste: impl Fn(String) -> Message + 'a,
|
||||
) -> Self {
|
||||
let on_paste: Rc<dyn Fn(String) -> Message + 'a> =
|
||||
Rc::new(on_paste);
|
||||
pub fn on_paste(mut self, on_paste: impl Fn(String) -> Message + 'a) -> Self {
|
||||
let on_paste: Rc<dyn Fn(String) -> Message + 'a> = Rc::new(on_paste);
|
||||
let paste_callback = Rc::clone(&on_paste);
|
||||
|
||||
self.input =
|
||||
self.input.on_paste(move |value| paste_callback.as_ref()(value));
|
||||
self.input = self
|
||||
.input
|
||||
.on_paste(move |value| paste_callback.as_ref()(value));
|
||||
self.on_paste = Some(on_paste);
|
||||
self
|
||||
}
|
||||
@@ -235,18 +215,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn line_height(
|
||||
mut self,
|
||||
line_height: impl Into<text::LineHeight>,
|
||||
) -> Self {
|
||||
pub fn line_height(mut self, line_height: impl Into<text::LineHeight>) -> Self {
|
||||
self.input = self.input.line_height(line_height);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn align_x(
|
||||
mut self,
|
||||
alignment: impl Into<alignment::Horizontal>,
|
||||
) -> Self {
|
||||
pub fn align_x(mut self, alignment: impl Into<alignment::Horizontal>) -> Self {
|
||||
self.input = self.input.align_x(alignment);
|
||||
self
|
||||
}
|
||||
@@ -379,11 +353,9 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
tree.state.downcast_mut::<ContextInputState>().menu =
|
||||
cursor.position().map(|anchor| MenuState {
|
||||
anchor,
|
||||
selection,
|
||||
});
|
||||
tree.state.downcast_mut::<ContextInputState>().menu = cursor
|
||||
.position()
|
||||
.map(|anchor| MenuState { anchor, selection });
|
||||
|
||||
shell.capture_event();
|
||||
shell.request_redraw();
|
||||
@@ -477,8 +449,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer>
|
||||
From<ContextInput<'a, Message, Theme, Renderer>>
|
||||
impl<'a, Message, Theme, Renderer> From<ContextInput<'a, Message, Theme, Renderer>>
|
||||
for Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone + 'a,
|
||||
@@ -516,12 +487,7 @@ enum MenuAction {
|
||||
}
|
||||
|
||||
impl MenuAction {
|
||||
const ALL: [Self; 4] = [
|
||||
Self::Cut,
|
||||
Self::Copy,
|
||||
Self::Paste,
|
||||
Self::SelectAll,
|
||||
];
|
||||
const ALL: [Self; 4] = [Self::Cut, Self::Copy, Self::Paste, Self::SelectAll];
|
||||
|
||||
fn label(self) -> &'static str {
|
||||
match self {
|
||||
@@ -564,8 +530,7 @@ where
|
||||
cursor: mouse::Cursor,
|
||||
) {
|
||||
let active_style = input_style(theme, self.style.as_ref(), text_input::Status::Active);
|
||||
let hovered_style =
|
||||
input_style(theme, self.style.as_ref(), text_input::Status::Hovered);
|
||||
let hovered_style = input_style(theme, self.style.as_ref(), text_input::Status::Hovered);
|
||||
let bounds = layout.bounds();
|
||||
let viewport = Rectangle::INFINITE;
|
||||
|
||||
@@ -640,9 +605,7 @@ where
|
||||
) {
|
||||
match event {
|
||||
Event::Keyboard(iced::keyboard::Event::KeyPressed {
|
||||
key: iced::keyboard::Key::Named(
|
||||
iced::keyboard::key::Named::Escape,
|
||||
),
|
||||
key: iced::keyboard::Key::Named(iced::keyboard::key::Named::Escape),
|
||||
..
|
||||
}) => {
|
||||
self.close(shell);
|
||||
@@ -718,11 +681,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
fn hit_action(
|
||||
&self,
|
||||
bounds: Rectangle,
|
||||
position: Point,
|
||||
) -> Option<MenuAction> {
|
||||
fn hit_action(&self, bounds: Rectangle, position: Point) -> Option<MenuAction> {
|
||||
if !bounds.contains(position) {
|
||||
return None;
|
||||
}
|
||||
@@ -932,12 +891,48 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn locked_menu_allows_copy_and_select_all_only() {
|
||||
assert!(!menu_action_enabled(MenuAction::Cut, true, true, false, true));
|
||||
assert!(menu_action_enabled(MenuAction::Copy, true, true, false, true));
|
||||
assert!(!menu_action_enabled(MenuAction::Paste, true, true, false, true));
|
||||
assert!(menu_action_enabled(MenuAction::SelectAll, true, true, false, true));
|
||||
assert!(!menu_action_enabled(
|
||||
MenuAction::Cut,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
));
|
||||
assert!(menu_action_enabled(
|
||||
MenuAction::Copy,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
));
|
||||
assert!(!menu_action_enabled(
|
||||
MenuAction::Paste,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
));
|
||||
assert!(menu_action_enabled(
|
||||
MenuAction::SelectAll,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
));
|
||||
|
||||
assert!(!menu_action_enabled(MenuAction::Copy, false, true, false, true));
|
||||
assert!(!menu_action_enabled(MenuAction::SelectAll, false, false, false, true));
|
||||
assert!(!menu_action_enabled(
|
||||
MenuAction::Copy,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
));
|
||||
assert!(!menu_action_enabled(
|
||||
MenuAction::SelectAll,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+46
-116
@@ -3,16 +3,15 @@ use iced::advanced::layout;
|
||||
use iced::advanced::mouse;
|
||||
use iced::advanced::renderer;
|
||||
use iced::advanced::text::{self as advanced_text, Paragraph, Span};
|
||||
use iced::advanced::widget::tree::{self, Tree};
|
||||
use iced::advanced::widget::Widget;
|
||||
use iced::advanced::widget::tree::{self, Tree};
|
||||
use iced::advanced::{Layout, Shell};
|
||||
use iced::widget::text::{
|
||||
self as widget_text, Alignment, Catalog, LineHeight, Shaping, Style, StyleFn,
|
||||
Wrapping,
|
||||
self as widget_text, Alignment, Catalog, LineHeight, Shaping, Style, StyleFn, Wrapping,
|
||||
};
|
||||
use iced::{
|
||||
alignment, Background, Border, Color, Element, Event, Length, Pixels, Point,
|
||||
Rectangle, Size, Vector, keyboard,
|
||||
Background, Border, Color, Element, Event, Length, Pixels, Point, Rectangle, Size, Vector,
|
||||
alignment, keyboard,
|
||||
};
|
||||
|
||||
const DRAG_THRESHOLD: f32 = 3.0;
|
||||
@@ -28,11 +27,7 @@ const HIT_SEARCH_STEPS: usize = 24;
|
||||
// widget's per-line offsets would stop being global and selection/copy across
|
||||
// lines would break — revisit then.
|
||||
|
||||
pub fn selected_substring(
|
||||
text: &str,
|
||||
anchor: usize,
|
||||
cursor: usize,
|
||||
) -> Option<String> {
|
||||
pub fn selected_substring(text: &str, anchor: usize, cursor: usize) -> Option<String> {
|
||||
let (start, end) = normalized_byte_range(text, anchor, cursor);
|
||||
|
||||
(start != end).then(|| text[start..end].to_owned())
|
||||
@@ -42,11 +37,7 @@ pub fn select_all(text: &str) -> (usize, usize) {
|
||||
(0, text.len())
|
||||
}
|
||||
|
||||
fn normalized_byte_range(
|
||||
text: &str,
|
||||
anchor: usize,
|
||||
cursor: usize,
|
||||
) -> (usize, usize) {
|
||||
fn normalized_byte_range(text: &str, anchor: usize, cursor: usize) -> (usize, usize) {
|
||||
let start = clamp_to_char_boundary(text, anchor.min(cursor));
|
||||
let end = clamp_to_char_boundary(text, anchor.max(cursor));
|
||||
|
||||
@@ -75,13 +66,8 @@ where
|
||||
SelectableRichText::with_spans(spans)
|
||||
}
|
||||
|
||||
pub struct SelectableRichText<
|
||||
'a,
|
||||
Link,
|
||||
Message,
|
||||
Theme = iced::Theme,
|
||||
Renderer = iced::Renderer,
|
||||
> where
|
||||
pub struct SelectableRichText<'a, Link, Message, Theme = iced::Theme, Renderer = iced::Renderer>
|
||||
where
|
||||
Link: Clone + 'static,
|
||||
Theme: Catalog,
|
||||
Renderer: advanced_text::Renderer,
|
||||
@@ -101,8 +87,7 @@ pub struct SelectableRichText<
|
||||
selection_color: Color,
|
||||
}
|
||||
|
||||
impl<'a, Link, Message, Theme, Renderer>
|
||||
SelectableRichText<'a, Link, Message, Theme, Renderer>
|
||||
impl<'a, Link, Message, Theme, Renderer> SelectableRichText<'a, Link, Message, Theme, Renderer>
|
||||
where
|
||||
Link: Clone + 'static,
|
||||
Theme: Catalog,
|
||||
@@ -127,9 +112,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_spans(
|
||||
spans: impl AsRef<[Span<'a, Link, Renderer::Font>]> + 'a,
|
||||
) -> Self {
|
||||
pub fn with_spans(spans: impl AsRef<[Span<'a, Link, Renderer::Font>]> + 'a) -> Self {
|
||||
Self {
|
||||
spans: Box::new(spans),
|
||||
..Self::new()
|
||||
@@ -166,10 +149,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn align_y(
|
||||
mut self,
|
||||
alignment: impl Into<alignment::Vertical>,
|
||||
) -> Self {
|
||||
pub fn align_y(mut self, alignment: impl Into<alignment::Vertical>) -> Self {
|
||||
self.align_y = alignment.into();
|
||||
self
|
||||
}
|
||||
@@ -179,10 +159,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_link_click(
|
||||
mut self,
|
||||
on_link_click: impl Fn(Link) -> Message + 'a,
|
||||
) -> Self {
|
||||
pub fn on_link_click(mut self, on_link_click: impl Fn(Link) -> Message + 'a) -> Self {
|
||||
self.on_link_click = Some(Box::new(on_link_click));
|
||||
self
|
||||
}
|
||||
@@ -356,26 +333,16 @@ where
|
||||
}
|
||||
|
||||
for (index, span) in spans.iter().enumerate() {
|
||||
let is_hovered_link = self.on_link_click.is_some()
|
||||
&& Some(index) == self.hovered_link;
|
||||
let is_hovered_link = self.on_link_click.is_some() && Some(index) == self.hovered_link;
|
||||
|
||||
if span.highlight.is_some()
|
||||
|| span.underline
|
||||
|| span.strikethrough
|
||||
|| is_hovered_link
|
||||
{
|
||||
if span.highlight.is_some() || span.underline || span.strikethrough || is_hovered_link {
|
||||
let regions = state.paragraph.span_bounds(index);
|
||||
|
||||
if let Some(highlight) = span.highlight {
|
||||
for bounds in ®ions {
|
||||
let bounds = Rectangle::new(
|
||||
bounds.position()
|
||||
- Vector::new(
|
||||
span.padding.left,
|
||||
span.padding.top,
|
||||
),
|
||||
bounds.size()
|
||||
+ Size::new(span.padding.x(), span.padding.y()),
|
||||
bounds.position() - Vector::new(span.padding.left, span.padding.top),
|
||||
bounds.size() + Size::new(span.padding.x(), span.padding.y()),
|
||||
);
|
||||
|
||||
renderer.fill_quad(
|
||||
@@ -390,26 +357,17 @@ where
|
||||
}
|
||||
|
||||
if span.underline || span.strikethrough || is_hovered_link {
|
||||
let size = span
|
||||
.size
|
||||
.or(self.size)
|
||||
.unwrap_or(renderer.default_size());
|
||||
let size = span.size.or(self.size).unwrap_or(renderer.default_size());
|
||||
|
||||
let line_height = span
|
||||
.line_height
|
||||
.unwrap_or(self.line_height)
|
||||
.to_absolute(size);
|
||||
|
||||
let color = span
|
||||
.color
|
||||
.or(style.color)
|
||||
.unwrap_or(defaults.text_color);
|
||||
let color = span.color.or(style.color).unwrap_or(defaults.text_color);
|
||||
|
||||
let baseline = translation
|
||||
+ Vector::new(
|
||||
0.0,
|
||||
size.0 + (line_height.0 - size.0) / 2.0,
|
||||
);
|
||||
let baseline =
|
||||
translation + Vector::new(0.0, size.0 + (line_height.0 - size.0) / 2.0);
|
||||
|
||||
if span.underline || is_hovered_link {
|
||||
for bounds in ®ions {
|
||||
@@ -497,13 +455,10 @@ where
|
||||
state.dragging = true;
|
||||
state.press_position = Some(position);
|
||||
state.span_pressed = self.hovered_link;
|
||||
state.selection = state
|
||||
.paragraph
|
||||
.hit_test(position)
|
||||
.map(|hit| {
|
||||
let offset = hit.cursor().min(flat_text.len());
|
||||
(offset, offset)
|
||||
});
|
||||
state.selection = state.paragraph.hit_test(position).map(|hit| {
|
||||
let offset = hit.cursor().min(flat_text.len());
|
||||
(offset, offset)
|
||||
});
|
||||
shell.capture_event();
|
||||
shell.request_redraw();
|
||||
} else if state.active || state.selection.is_some() {
|
||||
@@ -521,8 +476,7 @@ where
|
||||
&& let Some(hit) = state.paragraph.hit_test(position)
|
||||
&& let Some((anchor, _)) = state.selection
|
||||
{
|
||||
state.selection =
|
||||
Some((anchor, hit.cursor().min(flat_text.len())));
|
||||
state.selection = Some((anchor, hit.cursor().min(flat_text.len())));
|
||||
shell.request_redraw();
|
||||
}
|
||||
}
|
||||
@@ -540,16 +494,14 @@ where
|
||||
&& let Some(hit) = state.paragraph.hit_test(position)
|
||||
&& let Some((anchor, _)) = state.selection
|
||||
{
|
||||
state.selection =
|
||||
Some((anchor, hit.cursor().min(flat_text.len())));
|
||||
state.selection = Some((anchor, hit.cursor().min(flat_text.len())));
|
||||
}
|
||||
|
||||
if !dragged {
|
||||
if let (Some(on_link_clicked), Some(span)) =
|
||||
(&self.on_link_click, state.span_pressed)
|
||||
&& Some(span) == self.hovered_link
|
||||
&& let Some(link) =
|
||||
spans.get(span).and_then(|span| span.link.clone())
|
||||
&& let Some(link) = spans.get(span).and_then(|span| span.link.clone())
|
||||
{
|
||||
shell.publish(on_link_clicked(link));
|
||||
}
|
||||
@@ -570,25 +522,22 @@ where
|
||||
physical_key,
|
||||
modifiers,
|
||||
..
|
||||
}) if state.active && modifiers.command() => {
|
||||
match key.to_latin(*physical_key) {
|
||||
Some('c') | Some('C') => {
|
||||
if let Some((anchor, cursor)) = state.selection
|
||||
&& let Some(selected) =
|
||||
selected_substring(&flat_text, anchor, cursor)
|
||||
{
|
||||
clipboard.write(clipboard::Kind::Standard, selected);
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
Some('a') | Some('A') => {
|
||||
state.selection = Some(select_all(&flat_text));
|
||||
}) if state.active && modifiers.command() => match key.to_latin(*physical_key) {
|
||||
Some('c') | Some('C') => {
|
||||
if let Some((anchor, cursor)) = state.selection
|
||||
&& let Some(selected) = selected_substring(&flat_text, anchor, cursor)
|
||||
{
|
||||
clipboard.write(clipboard::Kind::Standard, selected);
|
||||
shell.capture_event();
|
||||
shell.request_redraw();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Some('a') | Some('A') => {
|
||||
state.selection = Some(select_all(&flat_text));
|
||||
shell.capture_event();
|
||||
shell.request_redraw();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -657,14 +606,8 @@ where
|
||||
};
|
||||
|
||||
if state.spans != config.spans {
|
||||
state.paragraph =
|
||||
Renderer::Paragraph::with_spans(text_with_spans());
|
||||
state.spans = config
|
||||
.spans
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Span::to_static)
|
||||
.collect();
|
||||
state.paragraph = Renderer::Paragraph::with_spans(text_with_spans());
|
||||
state.spans = config.spans.iter().cloned().map(Span::to_static).collect();
|
||||
} else {
|
||||
match state.paragraph.compare(advanced_text::Text {
|
||||
content: (),
|
||||
@@ -682,8 +625,7 @@ where
|
||||
state.paragraph.resize(bounds);
|
||||
}
|
||||
advanced_text::Difference::Shape => {
|
||||
state.paragraph =
|
||||
Renderer::Paragraph::with_spans(text_with_spans());
|
||||
state.paragraph = Renderer::Paragraph::with_spans(text_with_spans());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,13 +703,7 @@ fn selection_rect_for_line<P: Paragraph>(
|
||||
})
|
||||
}
|
||||
|
||||
fn x_for_offset<P: Paragraph>(
|
||||
paragraph: &P,
|
||||
y: f32,
|
||||
offset: usize,
|
||||
left: f32,
|
||||
right: f32,
|
||||
) -> f32 {
|
||||
fn x_for_offset<P: Paragraph>(paragraph: &P, y: f32, offset: usize, left: f32, right: f32) -> f32 {
|
||||
let mut low = left;
|
||||
let mut high = right.max(left);
|
||||
|
||||
@@ -787,10 +723,7 @@ fn x_for_offset<P: Paragraph>(
|
||||
high
|
||||
}
|
||||
|
||||
fn visual_lines<P: Paragraph>(
|
||||
paragraph: &P,
|
||||
span_count: usize,
|
||||
) -> Vec<Rectangle> {
|
||||
fn visual_lines<P: Paragraph>(paragraph: &P, span_count: usize) -> Vec<Rectangle> {
|
||||
let mut lines: Vec<Rectangle> = Vec::new();
|
||||
|
||||
for span in 0..span_count {
|
||||
@@ -820,10 +753,7 @@ fn union(a: Rectangle, b: Rectangle) -> Rectangle {
|
||||
let right = (a.x + a.width).max(b.x + b.width);
|
||||
let bottom = (a.y + a.height).max(b.y + b.height);
|
||||
|
||||
Rectangle::new(
|
||||
Point::new(left, top),
|
||||
Size::new(right - left, bottom - top),
|
||||
)
|
||||
Rectangle::new(Point::new(left, top), Size::new(right - left, bottom - top))
|
||||
}
|
||||
|
||||
fn clamped_position(cursor: mouse::Cursor, bounds: Rectangle) -> Option<Point> {
|
||||
|
||||
Reference in New Issue
Block a user