Merge pull request #2536 from meithecatte/editor-clipping
text_editor: Avoid rendering text outside the border
This commit is contained in:
commit
6d6f354b42
3 changed files with 44 additions and 34 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Point, Radians, Size, Vector};
|
use crate::{Padding, Point, Radians, Size, Vector};
|
||||||
|
|
||||||
/// An axis-aligned rectangle.
|
/// An axis-aligned rectangle.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
|
|
@ -220,12 +220,26 @@ impl Rectangle<f32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands the [`Rectangle`] a given amount.
|
/// Expands the [`Rectangle`] a given amount.
|
||||||
pub fn expand(self, amount: f32) -> Self {
|
pub fn expand(self, padding: impl Into<Padding>) -> Self {
|
||||||
|
let padding = padding.into();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
x: self.x - amount,
|
x: self.x - padding.left,
|
||||||
y: self.y - amount,
|
y: self.y - padding.top,
|
||||||
width: self.width + amount * 2.0,
|
width: self.width + padding.horizontal(),
|
||||||
height: self.height + amount * 2.0,
|
height: self.height + padding.vertical(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shrinks the [`Rectangle`] a given amount.
|
||||||
|
pub fn shrink(self, padding: impl Into<Padding>) -> Self {
|
||||||
|
let padding = padding.into();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
x: self.x + padding.left,
|
||||||
|
y: self.y + padding.top,
|
||||||
|
width: self.width - padding.horizontal(),
|
||||||
|
height: self.height - padding.vertical(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use iced::highlighter;
|
use iced::highlighter;
|
||||||
use iced::keyboard;
|
use iced::keyboard;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, horizontal_space, pick_list, row, text,
|
self, button, column, container, horizontal_space, pick_list, row, text,
|
||||||
text_editor, tooltip,
|
text_editor, tooltip,
|
||||||
};
|
};
|
||||||
use iced::{Center, Element, Fill, Font, Subscription, Task, Theme};
|
use iced::{Center, Element, Fill, Font, Subscription, Task, Theme};
|
||||||
|
|
@ -49,13 +49,16 @@ impl Editor {
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
is_dirty: false,
|
is_dirty: false,
|
||||||
},
|
},
|
||||||
Task::perform(
|
Task::batch([
|
||||||
load_file(format!(
|
Task::perform(
|
||||||
"{}/src/main.rs",
|
load_file(format!(
|
||||||
env!("CARGO_MANIFEST_DIR")
|
"{}/src/main.rs",
|
||||||
)),
|
env!("CARGO_MANIFEST_DIR")
|
||||||
Message::FileOpened,
|
)),
|
||||||
),
|
Message::FileOpened,
|
||||||
|
),
|
||||||
|
widget::focus_next(),
|
||||||
|
]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -729,7 +729,7 @@ where
|
||||||
defaults: &renderer::Style,
|
defaults: &renderer::Style,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor: mouse::Cursor,
|
cursor: mouse::Cursor,
|
||||||
viewport: &Rectangle,
|
_viewport: &Rectangle,
|
||||||
) {
|
) {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
|
|
@ -768,20 +768,14 @@ where
|
||||||
style.background,
|
style.background,
|
||||||
);
|
);
|
||||||
|
|
||||||
let position = bounds.position()
|
let text_bounds = bounds.shrink(self.padding);
|
||||||
+ Vector::new(self.padding.left, self.padding.top);
|
|
||||||
|
|
||||||
if internal.editor.is_empty() {
|
if internal.editor.is_empty() {
|
||||||
if let Some(placeholder) = self.placeholder.clone() {
|
if let Some(placeholder) = self.placeholder.clone() {
|
||||||
renderer.fill_text(
|
renderer.fill_text(
|
||||||
Text {
|
Text {
|
||||||
content: placeholder.into_owned(),
|
content: placeholder.into_owned(),
|
||||||
bounds: bounds.size()
|
bounds: text_bounds.size(),
|
||||||
- Size::new(
|
|
||||||
self.padding.right,
|
|
||||||
self.padding.bottom,
|
|
||||||
),
|
|
||||||
|
|
||||||
size: self
|
size: self
|
||||||
.text_size
|
.text_size
|
||||||
.unwrap_or_else(|| renderer.default_size()),
|
.unwrap_or_else(|| renderer.default_size()),
|
||||||
|
|
@ -791,24 +785,21 @@ where
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
shaping: text::Shaping::Advanced,
|
shaping: text::Shaping::Advanced,
|
||||||
},
|
},
|
||||||
position,
|
text_bounds.position(),
|
||||||
style.placeholder,
|
style.placeholder,
|
||||||
*viewport,
|
text_bounds,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
renderer.fill_editor(
|
renderer.fill_editor(
|
||||||
&internal.editor,
|
&internal.editor,
|
||||||
position,
|
text_bounds.position(),
|
||||||
defaults.text_color,
|
defaults.text_color,
|
||||||
*viewport,
|
text_bounds,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let translation = Vector::new(
|
let translation = text_bounds.position() - Point::ORIGIN;
|
||||||
bounds.x + self.padding.left,
|
|
||||||
bounds.y + self.padding.top,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(focus) = state.focus.as_ref() {
|
if let Some(focus) = state.focus.as_ref() {
|
||||||
match internal.editor.cursor() {
|
match internal.editor.cursor() {
|
||||||
|
|
@ -826,11 +817,13 @@ where
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(clipped_cursor) = bounds.intersection(&cursor) {
|
if let Some(clipped_cursor) =
|
||||||
|
text_bounds.intersection(&cursor)
|
||||||
|
{
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
renderer::Quad {
|
renderer::Quad {
|
||||||
bounds: Rectangle {
|
bounds: Rectangle {
|
||||||
x: clipped_cursor.x.floor(),
|
x: clipped_cursor.x,
|
||||||
y: clipped_cursor.y,
|
y: clipped_cursor.y,
|
||||||
width: clipped_cursor.width,
|
width: clipped_cursor.width,
|
||||||
height: clipped_cursor.height,
|
height: clipped_cursor.height,
|
||||||
|
|
@ -843,7 +836,7 @@ where
|
||||||
}
|
}
|
||||||
Cursor::Selection(ranges) => {
|
Cursor::Selection(ranges) => {
|
||||||
for range in ranges.into_iter().filter_map(|range| {
|
for range in ranges.into_iter().filter_map(|range| {
|
||||||
bounds.intersection(&(range + translation))
|
text_bounds.intersection(&(range + translation))
|
||||||
}) {
|
}) {
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
renderer::Quad {
|
renderer::Quad {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue