Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b3e41e4e9c |
36 changed files with 413 additions and 225 deletions
|
@ -152,7 +152,7 @@ impl CollapsingHeader {
|
|||
/// If the label is unique and static this is fine,
|
||||
/// but if it changes or there are several `CollapsingHeader` with the same title
|
||||
/// you need to provide a unique id source with [`Self::id_source`].
|
||||
pub fn new(label: impl ToString) -> Self {
|
||||
pub fn new(label: impl Into<Estring>) -> Self {
|
||||
let label = Label::new(label).wrap(false);
|
||||
let id_source = Id::new(label.text());
|
||||
Self {
|
||||
|
|
|
@ -23,7 +23,7 @@ use epaint::Shape;
|
|||
pub struct ComboBox {
|
||||
id_source: Id,
|
||||
label: Option<Label>,
|
||||
selected_text: String,
|
||||
selected_text: Estring,
|
||||
width: Option<f32>,
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,8 @@ impl ComboBox {
|
|||
}
|
||||
|
||||
/// What we show as the currently selected value
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn selected_text(mut self, selected_text: impl ToString) -> Self {
|
||||
self.selected_text = selected_text.to_string();
|
||||
pub fn selected_text(mut self, selected_text: impl Into<Estring>) -> Self {
|
||||
self.selected_text = selected_text.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -143,11 +142,10 @@ impl ComboBox {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn combo_box<R>(
|
||||
ui: &mut Ui,
|
||||
button_id: Id,
|
||||
selected: impl ToString,
|
||||
selected: impl Into<Estring>,
|
||||
menu_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<Option<R>> {
|
||||
let popup_id = button_id.with("popup");
|
||||
|
@ -158,9 +156,9 @@ fn combo_box<R>(
|
|||
let full_minimum_width = ui.spacing().slider_width;
|
||||
let icon_size = Vec2::splat(ui.spacing().icon_width);
|
||||
|
||||
let galley =
|
||||
ui.fonts()
|
||||
.layout_delayed_color(selected.to_string(), TextStyle::Button, f32::INFINITY);
|
||||
let galley = ui
|
||||
.fonts()
|
||||
.layout_delayed_color(selected, TextStyle::Button, f32::INFINITY);
|
||||
|
||||
let width = galley.size.x + ui.spacing().item_spacing.x + icon_size.x;
|
||||
let width = width.at_least(full_minimum_width);
|
||||
|
|
|
@ -194,7 +194,7 @@ fn show_tooltip_at_avoid<R>(
|
|||
/// egui::show_tooltip_text(ui.ctx(), egui::Id::new("my_tooltip"), "Helpful text");
|
||||
/// }
|
||||
/// ```
|
||||
pub fn show_tooltip_text(ctx: &CtxRef, id: Id, text: impl ToString) -> Option<()> {
|
||||
pub fn show_tooltip_text(ctx: &CtxRef, id: Id, text: impl Into<Estring>) -> Option<()> {
|
||||
show_tooltip(ctx, id, |ui| {
|
||||
ui.add(crate::widgets::Label::new(text));
|
||||
})
|
||||
|
|
|
@ -37,9 +37,8 @@ impl<'open> Window<'open> {
|
|||
/// The window title is used as a unique [`Id`] and must be unique, and should not change.
|
||||
/// This is true even if you disable the title bar with `.title_bar(false)`.
|
||||
/// If you need a changing title, you must call `window.id(…)` with a fixed id.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(title: impl ToString) -> Self {
|
||||
let title = title.to_string();
|
||||
pub fn new(title: impl Into<Estring>) -> Self {
|
||||
let title = title.into();
|
||||
let area = Area::new(&title);
|
||||
let title_label = Label::new(title).text_style(TextStyle::Heading).wrap(false);
|
||||
Self {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{egui_assert, emath::*, Align};
|
||||
use crate::{egui_assert, emath::*, Align, Estring};
|
||||
use std::f32::INFINITY;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -737,7 +737,7 @@ impl Layout {
|
|||
painter: &crate::Painter,
|
||||
region: &Region,
|
||||
stroke: epaint::Stroke,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
) {
|
||||
let cursor = region.cursor;
|
||||
let next_pos = self.next_widget_position(region);
|
||||
|
|
|
@ -352,7 +352,7 @@ pub use emath as math; // historical reasons
|
|||
pub use emath::{lerp, pos2, remap, remap_clamp, vec2, Align, Align2, NumExt, Pos2, Rect, Vec2};
|
||||
pub use epaint::{
|
||||
color, mutex,
|
||||
text::{FontDefinitions, FontFamily, TextStyle},
|
||||
text::{Estring, FontDefinitions, FontFamily, TextStyle},
|
||||
ClippedMesh, Color32, Rgba, Shape, Stroke, Texture, TextureId,
|
||||
};
|
||||
|
||||
|
@ -378,7 +378,9 @@ pub use {
|
|||
};
|
||||
|
||||
pub mod text {
|
||||
pub use epaint::text::{Galley, LayoutJob, LayoutSection, TextFormat, TAB_SIZE};
|
||||
pub use epaint::text::{
|
||||
Galley, LayoutJob, LayoutJobBuilder, LayoutSection, TextFormat, TAB_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -64,7 +64,7 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResp
|
|||
/// Returns `None` if the menu is not open.
|
||||
pub fn menu<R>(
|
||||
ui: &mut Ui,
|
||||
title: impl ToString,
|
||||
title: impl Into<Estring>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> Option<R> {
|
||||
menu_impl(ui, title, Box::new(add_contents))
|
||||
|
@ -104,13 +104,12 @@ pub(crate) fn menu_ui<'c, R>(
|
|||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn menu_impl<'c, R>(
|
||||
ui: &mut Ui,
|
||||
title: impl ToString,
|
||||
title: impl Into<Estring>,
|
||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||
) -> Option<R> {
|
||||
let title = title.to_string();
|
||||
let title = title.into();
|
||||
let bar_id = ui.id();
|
||||
let menu_id = bar_id.with(&title);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
};
|
||||
use epaint::{
|
||||
mutex::Mutex,
|
||||
text::{Fonts, Galley, TextStyle},
|
||||
text::{Estring, Fonts, Galley, TextStyle},
|
||||
Shape, Stroke,
|
||||
};
|
||||
|
||||
|
@ -193,17 +193,10 @@ impl Painter {
|
|||
|
||||
/// ## Debug painting
|
||||
impl Painter {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn debug_rect(&mut self, rect: Rect, color: Color32, text: impl ToString) {
|
||||
pub fn debug_rect(&mut self, rect: Rect, color: Color32, text: impl Into<Estring>) {
|
||||
self.rect_stroke(rect, 0.0, (1.0, color));
|
||||
let text_style = TextStyle::Monospace;
|
||||
self.text(
|
||||
rect.min,
|
||||
Align2::LEFT_TOP,
|
||||
text.to_string(),
|
||||
text_style,
|
||||
color,
|
||||
);
|
||||
self.text(rect.min, Align2::LEFT_TOP, text.into(), text_style, color);
|
||||
}
|
||||
|
||||
pub fn error(&self, pos: Pos2, text: impl std::fmt::Display) -> Rect {
|
||||
|
@ -211,15 +204,14 @@ impl Painter {
|
|||
}
|
||||
|
||||
/// text with a background
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn debug_text(
|
||||
&self,
|
||||
pos: Pos2,
|
||||
anchor: Align2,
|
||||
color: Color32,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
) -> Rect {
|
||||
let galley = self.layout_no_wrap(text.to_string(), TextStyle::Monospace, color);
|
||||
let galley = self.layout_no_wrap(text, TextStyle::Monospace, color);
|
||||
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size));
|
||||
let frame_rect = rect.expand(2.0);
|
||||
self.add(Shape::Rect {
|
||||
|
@ -332,16 +324,15 @@ impl Painter {
|
|||
/// [`Self::layout`] or [`Self::layout_no_wrap`].
|
||||
///
|
||||
/// Returns where the text ended up.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn text(
|
||||
&self,
|
||||
pos: Pos2,
|
||||
anchor: Align2,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
text_color: Color32,
|
||||
) -> Rect {
|
||||
let galley = self.layout_no_wrap(text.to_string(), text_style, text_color);
|
||||
let galley = self.layout_no_wrap(text, text_style, text_color);
|
||||
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size));
|
||||
self.galley(rect.min, galley);
|
||||
rect
|
||||
|
@ -353,7 +344,7 @@ impl Painter {
|
|||
#[inline(always)]
|
||||
pub fn layout(
|
||||
&self,
|
||||
text: String,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
wrap_width: f32,
|
||||
|
@ -367,7 +358,7 @@ impl Painter {
|
|||
#[inline(always)]
|
||||
pub fn layout_no_wrap(
|
||||
&self,
|
||||
text: String,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
) -> std::sync::Arc<Galley> {
|
||||
|
|
|
@ -262,7 +262,7 @@ impl Placer {
|
|||
}
|
||||
|
||||
impl Placer {
|
||||
pub(crate) fn debug_paint_cursor(&self, painter: &crate::Painter, text: impl ToString) {
|
||||
pub(crate) fn debug_paint_cursor(&self, painter: &crate::Painter, text: impl Into<Estring>) {
|
||||
let stroke = Stroke::new(1.0, Color32::DEBUG_COLOR);
|
||||
|
||||
if let Some(grid) = &self.grid {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::{
|
||||
emath::{lerp, Align, Pos2, Rect, Vec2},
|
||||
CursorIcon, PointerButton, NUM_POINTER_BUTTONS,
|
||||
CtxRef, CursorIcon, Estring, Id, LayerId, PointerButton, Sense, Ui, NUM_POINTER_BUTTONS,
|
||||
};
|
||||
use crate::{CtxRef, Id, LayerId, Sense, Ui};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -373,14 +372,14 @@ impl Response {
|
|||
/// For that, use [`Self::on_disabled_hover_text`] instead.
|
||||
///
|
||||
/// If you call this multiple times the tooltips will stack underneath the previous ones.
|
||||
pub fn on_hover_text(self, text: impl ToString) -> Self {
|
||||
pub fn on_hover_text(self, text: impl Into<Estring>) -> Self {
|
||||
self.on_hover_ui(|ui| {
|
||||
ui.add(crate::widgets::Label::new(text));
|
||||
})
|
||||
}
|
||||
|
||||
/// Show this text when hovering if the widget is disabled.
|
||||
pub fn on_disabled_hover_text(self, text: impl ToString) -> Self {
|
||||
pub fn on_disabled_hover_text(self, text: impl Into<Estring>) -> Self {
|
||||
self.on_disabled_hover_ui(|ui| {
|
||||
ui.add(crate::widgets::Label::new(text));
|
||||
})
|
||||
|
|
|
@ -919,7 +919,7 @@ impl DebugOptions {
|
|||
fn slider_vec2<'a>(
|
||||
value: &'a mut Vec2,
|
||||
range: std::ops::RangeInclusive<f32>,
|
||||
text: &'a str,
|
||||
text: &'static str,
|
||||
) -> impl Widget + 'a {
|
||||
move |ui: &mut crate::Ui| {
|
||||
ui.horizontal(|ui| {
|
||||
|
|
|
@ -979,7 +979,7 @@ impl Ui {
|
|||
/// Shortcut for `add(Hyperlink::new(url))`
|
||||
///
|
||||
/// See also [`Hyperlink`].
|
||||
pub fn hyperlink(&mut self, url: impl ToString) -> Response {
|
||||
pub fn hyperlink(&mut self, url: impl Into<Estring>) -> Response {
|
||||
Hyperlink::new(url).ui(self)
|
||||
}
|
||||
|
||||
|
@ -991,7 +991,7 @@ impl Ui {
|
|||
/// ```
|
||||
///
|
||||
/// See also [`Hyperlink`].
|
||||
pub fn hyperlink_to(&mut self, label: impl ToString, url: impl ToString) -> Response {
|
||||
pub fn hyperlink_to(&mut self, label: impl Into<Estring>, url: impl Into<Estring>) -> Response {
|
||||
Hyperlink::new(url).text(label).ui(self)
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ impl Ui {
|
|||
/// See also [`Button`].
|
||||
#[must_use = "You should check if the user clicked this with `if ui.button(…).clicked() { … } "]
|
||||
#[inline(always)]
|
||||
pub fn button(&mut self, text: impl ToString) -> Response {
|
||||
pub fn button(&mut self, text: impl Into<Estring>) -> Response {
|
||||
Button::new(text).ui(self)
|
||||
}
|
||||
|
||||
|
@ -1041,19 +1041,19 @@ impl Ui {
|
|||
///
|
||||
/// Shortcut for `add(Button::new(text).small())`
|
||||
#[must_use = "You should check if the user clicked this with `if ui.small_button(…).clicked() { … } "]
|
||||
pub fn small_button(&mut self, text: impl ToString) -> Response {
|
||||
pub fn small_button(&mut self, text: impl Into<Estring>) -> Response {
|
||||
Button::new(text).small().ui(self)
|
||||
}
|
||||
|
||||
/// Show a checkbox.
|
||||
pub fn checkbox(&mut self, checked: &mut bool, text: impl ToString) -> Response {
|
||||
pub fn checkbox(&mut self, checked: &mut bool, text: impl Into<Estring>) -> Response {
|
||||
Checkbox::new(checked, text).ui(self)
|
||||
}
|
||||
|
||||
/// Show a [`RadioButton`].
|
||||
/// Often you want to use [`Self::radio_value`] instead.
|
||||
#[must_use = "You should check if the user clicked this with `if ui.radio(…).clicked() { … } "]
|
||||
pub fn radio(&mut self, selected: bool, text: impl ToString) -> Response {
|
||||
pub fn radio(&mut self, selected: bool, text: impl Into<Estring>) -> Response {
|
||||
RadioButton::new(selected, text).ui(self)
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1078,7 @@ impl Ui {
|
|||
&mut self,
|
||||
current_value: &mut Value,
|
||||
selected_value: Value,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
) -> Response {
|
||||
let mut response = self.radio(*current_value == selected_value, text);
|
||||
if response.clicked() {
|
||||
|
@ -1092,7 +1092,7 @@ impl Ui {
|
|||
///
|
||||
/// See also [`SelectableLabel`].
|
||||
#[must_use = "You should check if the user clicked this with `if ui.selectable_label(…).clicked() { … } "]
|
||||
pub fn selectable_label(&mut self, checked: bool, text: impl ToString) -> Response {
|
||||
pub fn selectable_label(&mut self, checked: bool, text: impl Into<Estring>) -> Response {
|
||||
SelectableLabel::new(checked, text).ui(self)
|
||||
}
|
||||
|
||||
|
@ -1106,7 +1106,7 @@ impl Ui {
|
|||
&mut self,
|
||||
current_value: &mut Value,
|
||||
selected_value: Value,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
) -> Response {
|
||||
let mut response = self.selectable_label(*current_value == selected_value, text);
|
||||
if response.clicked() {
|
||||
|
@ -1303,7 +1303,7 @@ impl Ui {
|
|||
/// A [`CollapsingHeader`] that starts out collapsed.
|
||||
pub fn collapsing<R>(
|
||||
&mut self,
|
||||
heading: impl ToString,
|
||||
heading: impl Into<Estring>,
|
||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||
) -> CollapsingResponse<R> {
|
||||
CollapsingHeader::new(heading).show(self, add_contents)
|
||||
|
@ -1644,7 +1644,7 @@ impl Ui {
|
|||
|
||||
/// Shows the given text where the next widget is to be placed
|
||||
/// if when [`Context::set_debug_on_hover`] has been turned on and the mouse is hovering the Ui.
|
||||
pub fn trace_location(&self, text: impl ToString) {
|
||||
pub fn trace_location(&self, text: impl Into<Estring>) {
|
||||
let rect = self.max_rect();
|
||||
if self.style().debug.debug_on_hover && self.rect_contains_pointer(rect) {
|
||||
self.placer
|
||||
|
|
|
@ -22,7 +22,7 @@ fn select<T>(b: bool, if_true: T, if_false: T) -> T {
|
|||
/// ```
|
||||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||
pub struct Button {
|
||||
text: String,
|
||||
text: Estring,
|
||||
text_color: Option<Color32>,
|
||||
text_style: Option<TextStyle>,
|
||||
/// None means default for interact
|
||||
|
@ -36,10 +36,9 @@ pub struct Button {
|
|||
}
|
||||
|
||||
impl Button {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(text: impl ToString) -> Self {
|
||||
pub fn new(text: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
text_style: None,
|
||||
fill: None,
|
||||
|
@ -235,17 +234,16 @@ impl Widget for Button {
|
|||
#[derive(Debug)]
|
||||
pub struct Checkbox<'a> {
|
||||
checked: &'a mut bool,
|
||||
text: String,
|
||||
text: Estring,
|
||||
text_color: Option<Color32>,
|
||||
text_style: Option<TextStyle>,
|
||||
}
|
||||
|
||||
impl<'a> Checkbox<'a> {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(checked: &'a mut bool, text: impl ToString) -> Self {
|
||||
pub fn new(checked: &'a mut bool, text: impl Into<Estring>) -> Self {
|
||||
Checkbox {
|
||||
checked,
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
text_style: None,
|
||||
}
|
||||
|
@ -360,17 +358,16 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
#[derive(Debug)]
|
||||
pub struct RadioButton {
|
||||
checked: bool,
|
||||
text: String,
|
||||
text: Estring,
|
||||
text_color: Option<Color32>,
|
||||
text_style: Option<TextStyle>,
|
||||
}
|
||||
|
||||
impl RadioButton {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(checked: bool, text: impl ToString) -> Self {
|
||||
pub fn new(checked: bool, text: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
checked,
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
text_style: None,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::needless_pass_by_value)] // False positives with `impl ToString`
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use crate::*;
|
||||
|
@ -50,8 +48,8 @@ fn set(get_set_value: &mut GetSetValue<'_>, value: f64) {
|
|||
pub struct DragValue<'a> {
|
||||
get_set_value: GetSetValue<'a>,
|
||||
speed: f64,
|
||||
prefix: String,
|
||||
suffix: String,
|
||||
prefix: Estring,
|
||||
suffix: Estring,
|
||||
clamp_range: RangeInclusive<f64>,
|
||||
min_decimals: usize,
|
||||
max_decimals: Option<usize>,
|
||||
|
@ -100,14 +98,14 @@ impl<'a> DragValue<'a> {
|
|||
}
|
||||
|
||||
/// Show a prefix before the number, e.g. "x: "
|
||||
pub fn prefix(mut self, prefix: impl ToString) -> Self {
|
||||
self.prefix = prefix.to_string();
|
||||
pub fn prefix(mut self, prefix: impl Into<Estring>) -> Self {
|
||||
self.prefix = prefix.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a suffix to the number, this can be e.g. a unit ("°" or " m")
|
||||
pub fn suffix(mut self, suffix: impl ToString) -> Self {
|
||||
self.suffix = suffix.to_string();
|
||||
pub fn suffix(mut self, suffix: impl Into<Estring>) -> Self {
|
||||
self.suffix = suffix.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -11,32 +11,29 @@ use crate::*;
|
|||
/// ```
|
||||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||
pub struct Hyperlink {
|
||||
url: String,
|
||||
url: Estring,
|
||||
label: Label,
|
||||
}
|
||||
|
||||
impl Hyperlink {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(url: impl ToString) -> Self {
|
||||
let url = url.to_string();
|
||||
pub fn new(url: impl Into<Estring>) -> Self {
|
||||
let url = url.into();
|
||||
Self {
|
||||
url: url.clone(),
|
||||
label: Label::new(url).sense(Sense::click()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_label_and_url(label: impl Into<Label>, url: impl ToString) -> Self {
|
||||
pub fn from_label_and_url(label: impl Into<Label>, url: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
url: url.to_string(),
|
||||
url: url.into(),
|
||||
label: label.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Show some other text than the url
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn text(mut self, text: impl ToString) -> Self {
|
||||
self.label.text = text.to_string();
|
||||
pub fn text(mut self, text: impl Into<Estring>) -> Self {
|
||||
self.label.text = text.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -63,13 +60,13 @@ impl Widget for Hyperlink {
|
|||
if response.clicked() {
|
||||
let modifiers = ui.ctx().input().modifiers;
|
||||
ui.ctx().output().open_url = Some(crate::output::OpenUrl {
|
||||
url: url.clone(),
|
||||
url: url.to_string(),
|
||||
new_tab: modifiers.any(),
|
||||
});
|
||||
}
|
||||
if response.middle_clicked() {
|
||||
ui.ctx().output().open_url = Some(crate::output::OpenUrl {
|
||||
url: url.clone(),
|
||||
url: url.to_string(),
|
||||
new_tab: true,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use std::sync::Arc;
|
|||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||
pub struct Label {
|
||||
// TODO: not pub
|
||||
pub(crate) text: String,
|
||||
pub(crate) text: Estring,
|
||||
pub(crate) wrap: Option<bool>,
|
||||
pub(crate) text_style: Option<TextStyle>,
|
||||
pub(crate) background_color: Color32,
|
||||
|
@ -32,10 +32,9 @@ pub struct Label {
|
|||
}
|
||||
|
||||
impl Label {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(text: impl ToString) -> Self {
|
||||
pub fn new(text: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
wrap: None,
|
||||
text_style: None,
|
||||
background_color: Color32::TRANSPARENT,
|
||||
|
@ -51,7 +50,7 @@ impl Label {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn text(&self) -> &str {
|
||||
pub(crate) fn text(&self) -> &Estring {
|
||||
&self.text
|
||||
}
|
||||
|
||||
|
@ -211,7 +210,7 @@ impl Label {
|
|||
};
|
||||
|
||||
let job = LayoutJob {
|
||||
text: self.text.clone(), // TODO: avoid clone
|
||||
text: self.text.clone(),
|
||||
sections: vec![LayoutSection {
|
||||
leading_space,
|
||||
byte_range: 0..self.text.len(),
|
||||
|
@ -358,8 +357,20 @@ impl Widget for Label {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Label {
|
||||
fn from(s: &str) -> Label {
|
||||
impl From<&'static str> for Label {
|
||||
fn from(s: &'static str) -> Label {
|
||||
Label::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Estring> for Label {
|
||||
fn from(s: &Estring) -> Label {
|
||||
Label::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Estring> for Label {
|
||||
fn from(s: Estring) -> Label {
|
||||
Label::new(s)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ pub fn reset_button<T: Default + PartialEq>(ui: &mut Ui, value: &mut T) {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
pub fn stroke_ui(ui: &mut crate::Ui, stroke: &mut epaint::Stroke, text: &str) {
|
||||
pub fn stroke_ui(ui: &mut crate::Ui, stroke: &mut epaint::Stroke, text: &'static str) {
|
||||
let epaint::Stroke { width, color } = stroke;
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(DragValue::new(width).speed(0.1).clamp_range(0.0..=5.0))
|
||||
|
@ -108,7 +108,7 @@ pub fn stroke_ui(ui: &mut crate::Ui, stroke: &mut epaint::Stroke, text: &str) {
|
|||
});
|
||||
}
|
||||
|
||||
pub(crate) fn shadow_ui(ui: &mut Ui, shadow: &mut epaint::Shadow, text: &str) {
|
||||
pub(crate) fn shadow_ui(ui: &mut Ui, shadow: &mut epaint::Shadow, text: &'static str) {
|
||||
let epaint::Shadow { extrusion, color } = shadow;
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(text);
|
||||
|
|
|
@ -126,7 +126,7 @@ impl ToString for LineStyle {
|
|||
pub struct HLine {
|
||||
pub(super) y: f64,
|
||||
pub(super) stroke: Stroke,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) style: LineStyle,
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ impl HLine {
|
|||
Self {
|
||||
y: y.into(),
|
||||
stroke: Stroke::new(1.0, Color32::TRANSPARENT),
|
||||
name: String::default(),
|
||||
name: Estring::default(),
|
||||
highlight: false,
|
||||
style: LineStyle::Solid,
|
||||
}
|
||||
|
@ -178,9 +178,8 @@ impl HLine {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +203,7 @@ impl PlotItem for HLine {
|
|||
fn initialize(&mut self, _x_range: RangeInclusive<f64>) {}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
fn color(&self) -> Color32 {
|
||||
|
@ -236,7 +235,7 @@ impl PlotItem for HLine {
|
|||
pub struct VLine {
|
||||
pub(super) x: f64,
|
||||
pub(super) stroke: Stroke,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) style: LineStyle,
|
||||
}
|
||||
|
@ -246,7 +245,7 @@ impl VLine {
|
|||
Self {
|
||||
x: x.into(),
|
||||
stroke: Stroke::new(1.0, Color32::TRANSPARENT),
|
||||
name: String::default(),
|
||||
name: Estring::default(),
|
||||
highlight: false,
|
||||
style: LineStyle::Solid,
|
||||
}
|
||||
|
@ -288,9 +287,8 @@ impl VLine {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +312,7 @@ impl PlotItem for VLine {
|
|||
fn initialize(&mut self, _x_range: RangeInclusive<f64>) {}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
fn color(&self) -> Color32 {
|
||||
|
@ -542,7 +540,7 @@ impl MarkerShape {
|
|||
pub struct Line {
|
||||
pub(super) series: Values,
|
||||
pub(super) stroke: Stroke,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) fill: Option<f32>,
|
||||
pub(super) style: LineStyle,
|
||||
|
@ -602,9 +600,8 @@ impl Line {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +706,7 @@ impl PlotItem for Line {
|
|||
pub struct Polygon {
|
||||
pub(super) series: Values,
|
||||
pub(super) stroke: Stroke,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) fill_alpha: f32,
|
||||
pub(super) style: LineStyle,
|
||||
|
@ -770,9 +767,8 @@ impl Polygon {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -842,20 +838,19 @@ impl PlotItem for Polygon {
|
|||
|
||||
/// Text inside the plot.
|
||||
pub struct Text {
|
||||
pub(super) text: String,
|
||||
pub(super) text: Estring,
|
||||
pub(super) style: TextStyle,
|
||||
pub(super) position: Value,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) color: Color32,
|
||||
pub(super) anchor: Align2,
|
||||
}
|
||||
|
||||
impl Text {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(position: Value, text: impl ToString) -> Self {
|
||||
pub fn new(position: Value, text: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
style: TextStyle::Small,
|
||||
position,
|
||||
name: Default::default(),
|
||||
|
@ -895,9 +890,8 @@ impl Text {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -965,7 +959,7 @@ pub struct Points {
|
|||
pub(super) filled: bool,
|
||||
/// The maximum extent of the marker from its center.
|
||||
pub(super) radius: f32,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) stems: Option<f32>,
|
||||
}
|
||||
|
@ -1026,9 +1020,8 @@ impl Points {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -1221,7 +1214,7 @@ pub struct Arrows {
|
|||
pub(super) origins: Values,
|
||||
pub(super) tips: Values,
|
||||
pub(super) color: Color32,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
pub(super) highlight: bool,
|
||||
}
|
||||
|
||||
|
@ -1254,9 +1247,8 @@ impl Arrows {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -1340,7 +1332,7 @@ pub struct PlotImage {
|
|||
pub(super) bg_fill: Color32,
|
||||
pub(super) tint: Color32,
|
||||
pub(super) highlight: bool,
|
||||
pub(super) name: String,
|
||||
pub(super) name: Estring,
|
||||
}
|
||||
|
||||
impl PlotImage {
|
||||
|
@ -1388,9 +1380,8 @@ impl PlotImage {
|
|||
///
|
||||
/// Multiple plot items may share the same name, in which case they will also share an entry in
|
||||
/// the legend.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn name(mut self, name: impl ToString) -> Self {
|
||||
self.name = name.to_string();
|
||||
pub fn name(mut self, name: impl Into<Estring>) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
enum ProgressBarText {
|
||||
Custom(String),
|
||||
Custom(Estring),
|
||||
Percentage,
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,8 @@ impl ProgressBar {
|
|||
}
|
||||
|
||||
/// A custom text to display on the progress bar.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn text(mut self, text: impl ToString) -> Self {
|
||||
self.text = Some(ProgressBarText::Custom(text.to_string()));
|
||||
pub fn text(mut self, text: impl Into<Estring>) -> Self {
|
||||
self.text = Some(ProgressBarText::Custom(text.into()));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -125,9 +124,9 @@ impl Widget for ProgressBar {
|
|||
}
|
||||
|
||||
if let Some(text_kind) = text {
|
||||
let text = match text_kind {
|
||||
let text: Estring = match text_kind {
|
||||
ProgressBarText::Custom(string) => string,
|
||||
ProgressBarText::Percentage => format!("{}%", (progress * 100.0) as usize),
|
||||
ProgressBarText::Percentage => format!("{}%", (progress * 100.0) as usize).into(),
|
||||
};
|
||||
ui.painter().sub_region(outer_rect).text(
|
||||
outer_rect.left_center() + vec2(ui.spacing().item_spacing.x, 0.0),
|
||||
|
|
|
@ -24,16 +24,15 @@ use crate::*;
|
|||
#[derive(Debug)]
|
||||
pub struct SelectableLabel {
|
||||
selected: bool,
|
||||
text: String,
|
||||
text: Estring,
|
||||
text_style: Option<TextStyle>,
|
||||
}
|
||||
|
||||
impl SelectableLabel {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn new(selected: bool, text: impl ToString) -> Self {
|
||||
pub fn new(selected: bool, text: impl Into<Estring>) -> Self {
|
||||
Self {
|
||||
selected,
|
||||
text: text.to_string(),
|
||||
text: text.into(),
|
||||
text_style: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::needless_pass_by_value)] // False positives with `impl ToString`
|
||||
|
||||
use crate::{widgets::Label, *};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
|
@ -58,9 +56,9 @@ pub struct Slider<'a> {
|
|||
clamp_to_range: bool,
|
||||
smart_aim: bool,
|
||||
show_value: bool,
|
||||
prefix: String,
|
||||
suffix: String,
|
||||
text: String,
|
||||
prefix: Estring,
|
||||
suffix: Estring,
|
||||
text: Estring,
|
||||
text_color: Option<Color32>,
|
||||
min_decimals: usize,
|
||||
max_decimals: Option<usize>,
|
||||
|
@ -115,20 +113,20 @@ impl<'a> Slider<'a> {
|
|||
}
|
||||
|
||||
/// Show a prefix before the number, e.g. "x: "
|
||||
pub fn prefix(mut self, prefix: impl ToString) -> Self {
|
||||
self.prefix = prefix.to_string();
|
||||
pub fn prefix(mut self, prefix: impl Into<Estring>) -> Self {
|
||||
self.prefix = prefix.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a suffix to the number, this can be e.g. a unit ("°" or " m")
|
||||
pub fn suffix(mut self, suffix: impl ToString) -> Self {
|
||||
self.suffix = suffix.to_string();
|
||||
pub fn suffix(mut self, suffix: impl Into<Estring>) -> Self {
|
||||
self.suffix = suffix.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Show a text next to the slider (e.g. explaining what the slider controls).
|
||||
pub fn text(mut self, text: impl ToString) -> Self {
|
||||
self.text = text.to_string();
|
||||
pub fn text(mut self, text: impl Into<Estring>) -> Self {
|
||||
self.text = text.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ impl TextBuffer for String {
|
|||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||
pub struct TextEdit<'t, S: TextBuffer = String> {
|
||||
text: &'t mut S,
|
||||
hint_text: String,
|
||||
hint_text: Estring,
|
||||
id: Option<Id>,
|
||||
id_source: Option<Id>,
|
||||
text_style: Option<TextStyle>,
|
||||
|
@ -302,9 +302,8 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
|
|||
}
|
||||
|
||||
/// Show a faint hint text when the text field is empty.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn hint_text(mut self, hint_text: impl ToString) -> Self {
|
||||
self.hint_text = hint_text.to_string();
|
||||
pub fn hint_text(mut self, hint_text: impl Into<Estring>) -> Self {
|
||||
self.hint_text = hint_text.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
ui.label("the quick brown fox jumps over the lazy dog");
|
||||
})
|
||||
});
|
||||
c.bench_function("label format!", |b| {
|
||||
c.bench_function("label String", |b| {
|
||||
b.iter(|| {
|
||||
ui.label("the quick brown fox jumps over the lazy dog".to_owned());
|
||||
})
|
||||
|
@ -77,20 +77,16 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
b.iter(|| {
|
||||
use egui::epaint::text::{layout, LayoutJob};
|
||||
|
||||
let job = LayoutJob::simple(
|
||||
LOREM_IPSUM_LONG.to_owned(),
|
||||
egui::TextStyle::Body,
|
||||
color,
|
||||
wrap_width,
|
||||
);
|
||||
let job =
|
||||
LayoutJob::simple(LOREM_IPSUM_LONG, egui::TextStyle::Body, color, wrap_width);
|
||||
layout(&fonts, job.into())
|
||||
})
|
||||
});
|
||||
c.bench_function("text_layout_cached", |b| {
|
||||
b.iter(|| fonts.layout(LOREM_IPSUM_LONG.to_owned(), text_style, color, wrap_width))
|
||||
b.iter(|| fonts.layout(LOREM_IPSUM_LONG, text_style, color, wrap_width))
|
||||
});
|
||||
|
||||
let galley = fonts.layout(LOREM_IPSUM_LONG.to_owned(), text_style, color, wrap_width);
|
||||
let galley = fonts.layout(LOREM_IPSUM_LONG, text_style, color, wrap_width);
|
||||
let mut tessellator = egui::epaint::Tessellator::from_options(Default::default());
|
||||
let mut mesh = egui::epaint::Mesh::default();
|
||||
c.bench_function("tessellate_text", |b| {
|
||||
|
|
|
@ -262,7 +262,7 @@ impl ColorTest {
|
|||
&mut self,
|
||||
ui: &mut Ui,
|
||||
tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>,
|
||||
label: &str,
|
||||
label: &'static str,
|
||||
bg_fill: Color32,
|
||||
gradient: &Gradient,
|
||||
) {
|
||||
|
@ -284,7 +284,13 @@ impl ColorTest {
|
|||
}
|
||||
}
|
||||
|
||||
fn vertex_gradient(&mut self, ui: &mut Ui, label: &str, bg_fill: Color32, gradient: &Gradient) {
|
||||
fn vertex_gradient(
|
||||
&mut self,
|
||||
ui: &mut Ui,
|
||||
label: &'static str,
|
||||
bg_fill: Color32,
|
||||
gradient: &Gradient,
|
||||
) {
|
||||
if !self.vertex_gradients {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ impl MemoizedSyntaxHighlighter {
|
|||
.highlight(is_dark_mode, code, language)
|
||||
.unwrap_or_else(|| {
|
||||
LayoutJob::simple(
|
||||
code.into(),
|
||||
code.to_owned(),
|
||||
egui::TextStyle::Monospace,
|
||||
if is_dark_mode {
|
||||
egui::Color32::LIGHT_GRAY
|
||||
|
@ -172,7 +172,7 @@ impl Highligher {
|
|||
use egui::text::{LayoutSection, TextFormat};
|
||||
|
||||
let mut job = LayoutJob {
|
||||
text: text.into(),
|
||||
text: text.to_owned().into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -226,7 +226,7 @@ impl Highligher {
|
|||
fn highlight(&self, is_dark_mode: bool, mut text: &str, _language: &str) -> Option<LayoutJob> {
|
||||
// Extremely simple syntax highlighter for when we compile without syntect
|
||||
|
||||
use egui::text::TextFormat;
|
||||
use egui::text::{LayoutJobBuilder, TextFormat};
|
||||
use egui::Color32;
|
||||
let monospace = egui::TextStyle::Monospace;
|
||||
|
||||
|
@ -265,7 +265,7 @@ impl Highligher {
|
|||
},
|
||||
);
|
||||
|
||||
let mut job = LayoutJob::default();
|
||||
let mut job = LayoutJobBuilder::default();
|
||||
|
||||
while !text.is_empty() {
|
||||
if text.starts_with("//") {
|
||||
|
@ -308,7 +308,7 @@ impl Highligher {
|
|||
}
|
||||
}
|
||||
|
||||
Some(job)
|
||||
Some(job.build())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,10 +90,12 @@ impl super::View for FontBook {
|
|||
|
||||
for (&chr, name) in named_chars {
|
||||
if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() {
|
||||
let button = egui::Button::new(chr).text_style(text_style).frame(false);
|
||||
let button = egui::Button::new(chr.to_string())
|
||||
.text_style(text_style)
|
||||
.frame(false);
|
||||
|
||||
let tooltip_ui = |ui: &mut egui::Ui| {
|
||||
ui.add(egui::Label::new(chr).text_style(text_style));
|
||||
ui.add(egui::Label::new(chr.to_string()).text_style(text_style));
|
||||
ui.label(format!("{}\nU+{:X}\n\nClick to copy", name, chr as u32));
|
||||
};
|
||||
|
||||
|
|
|
@ -329,7 +329,7 @@ impl Tree {
|
|||
)
|
||||
}
|
||||
pub fn ui(&mut self, ui: &mut Ui) -> Action {
|
||||
self.1.ui(ui, 0, "root", &mut self.0)
|
||||
self.1.ui(ui, 0, "root".to_owned(), &mut self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,16 +342,16 @@ impl SubTree {
|
|||
&mut self,
|
||||
ui: &mut Ui,
|
||||
depth: usize,
|
||||
name: &str,
|
||||
name: String,
|
||||
selected_name: &mut String,
|
||||
) -> Action {
|
||||
let response = CollapsingHeader::new(name)
|
||||
let response = CollapsingHeader::new(name.clone())
|
||||
.default_open(depth < 1)
|
||||
.selectable(true)
|
||||
.selected(selected_name.as_str() == name)
|
||||
.show(ui, |ui| self.children_ui(ui, name, depth, selected_name));
|
||||
.show(ui, |ui| self.children_ui(ui, &name, depth, selected_name));
|
||||
if response.header_response.clicked() {
|
||||
*selected_name = name.to_string();
|
||||
*selected_name = name;
|
||||
}
|
||||
response.body_returned.unwrap_or(Action::Keep)
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ impl SubTree {
|
|||
if tree.ui(
|
||||
ui,
|
||||
depth + 1,
|
||||
&format!("{}/{}", parent_name, i),
|
||||
format!("{}/{}", parent_name, i),
|
||||
selected_name,
|
||||
) == Action::Keep
|
||||
{
|
||||
|
@ -401,9 +401,9 @@ impl SubTree {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
fn text_layout_ui(ui: &mut egui::Ui) {
|
||||
use egui::epaint::text::{LayoutJob, TextFormat};
|
||||
use egui::epaint::text::{LayoutJobBuilder, TextFormat};
|
||||
|
||||
let mut job = LayoutJob::default();
|
||||
let mut job = LayoutJobBuilder::default();
|
||||
|
||||
let first_row_indentation = 10.0;
|
||||
|
||||
|
@ -565,6 +565,7 @@ fn text_layout_ui(ui: &mut egui::Ui) {
|
|||
},
|
||||
);
|
||||
|
||||
let mut job = job.build();
|
||||
job.wrap_width = ui.available_width();
|
||||
|
||||
let galley = ui.fonts().layout_job(job);
|
||||
|
|
|
@ -241,7 +241,7 @@ fn example_plot() -> egui::plot::Plot {
|
|||
.data_aspect(1.0)
|
||||
}
|
||||
|
||||
fn doc_link_label<'a>(title: &'a str, search_term: &'a str) -> impl egui::Widget + 'a {
|
||||
fn doc_link_label(title: &'static str, search_term: &'static str) -> impl egui::Widget {
|
||||
let label = format!("{}:", title);
|
||||
let url = format!("https://docs.rs/egui?search={}", search_term);
|
||||
move |ui: &mut egui::Ui| {
|
||||
|
|
|
@ -132,10 +132,12 @@ impl epi::App for HttpApp {
|
|||
}
|
||||
Err(error) => {
|
||||
// This should only happen if the fetch API isn't available or something similar.
|
||||
ui.add(
|
||||
egui::Label::new(if error.is_empty() { "Error" } else { error })
|
||||
.text_color(egui::Color32::RED),
|
||||
);
|
||||
let error = if error.is_empty() {
|
||||
"Error".to_owned()
|
||||
} else {
|
||||
error.clone()
|
||||
};
|
||||
ui.add(egui::Label::new(error).text_color(egui::Color32::RED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +327,7 @@ impl ColoredText {
|
|||
use egui::text::{LayoutJob, LayoutSection, TextFormat};
|
||||
|
||||
let mut job = LayoutJob {
|
||||
text: text.into(),
|
||||
text: text.to_owned().into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ pub fn item_ui(ui: &mut Ui, item: easy_mark::Item<'_>) {
|
|||
}
|
||||
easy_mark::Item::Hyperlink(style, text, url) => {
|
||||
let label = label_from_style(text, &style);
|
||||
ui.add(Hyperlink::from_label_and_url(label, url));
|
||||
ui.add(Hyperlink::from_label_and_url(label, url.to_owned()));
|
||||
}
|
||||
|
||||
easy_mark::Item::Separator => {
|
||||
|
@ -75,7 +75,7 @@ pub fn item_ui(ui: &mut Ui, item: easy_mark::Item<'_>) {
|
|||
}
|
||||
easy_mark::Item::CodeBlock(_language, code) => {
|
||||
let where_to_put_background = ui.painter().add(Shape::Noop);
|
||||
let mut rect = ui.monospace(code).rect;
|
||||
let mut rect = ui.monospace(code.to_owned()).rect;
|
||||
rect = rect.expand(1.0); // looks better
|
||||
rect.max.x = ui.max_rect().max.x;
|
||||
let code_bg_color = ui.visuals().code_bg_color;
|
||||
|
@ -102,7 +102,7 @@ fn label_from_style(text: &str, style: &easy_mark::Style) -> Label {
|
|||
|
||||
let small = small || raised; // Raised text is also smaller
|
||||
|
||||
let mut label = Label::new(text);
|
||||
let mut label = Label::new(text.to_owned());
|
||||
if heading && !small {
|
||||
label = label.heading().strong();
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ impl WrapApp {
|
|||
|
||||
for (anchor, app) in self.apps.iter_mut() {
|
||||
if ui
|
||||
.selectable_label(self.selected_anchor == anchor, app.name())
|
||||
.selectable_label(self.selected_anchor == anchor, app.name().to_owned())
|
||||
.clicked()
|
||||
{
|
||||
self.selected_anchor = anchor.to_owned();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
text::{Fonts, Galley, TextStyle},
|
||||
text::{Estring, Fonts, Galley, TextStyle},
|
||||
Color32, Mesh, Stroke,
|
||||
};
|
||||
use emath::*;
|
||||
|
@ -166,16 +166,15 @@ impl Shape {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn text(
|
||||
fonts: &Fonts,
|
||||
pos: Pos2,
|
||||
anchor: Align2,
|
||||
text: impl ToString,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: Color32,
|
||||
) -> Self {
|
||||
let galley = fonts.layout_no_wrap(text.to_string(), text_style, color);
|
||||
let galley = fonts.layout_no_wrap(text.into(), text_style, color);
|
||||
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size));
|
||||
Self::galley(rect.min, galley)
|
||||
}
|
||||
|
|
173
epaint/src/text/estring.rs
Normal file
173
epaint/src/text/estring.rs
Normal file
|
@ -0,0 +1,173 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
/// An immutable string, backed by either `&'static str` or `Arc<String>`.
|
||||
///
|
||||
/// Wherever you see `impl Into<Estring>` pass either a `String` or
|
||||
/// a `&'static str` (a `"string literal"`).
|
||||
///
|
||||
/// Estring provides fast `Clone`.
|
||||
#[derive(Clone)]
|
||||
pub enum Estring {
|
||||
Static(&'static str),
|
||||
Owned(Arc<str>),
|
||||
}
|
||||
|
||||
impl Estring {
|
||||
#[inline]
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
Self::Static(s) => s,
|
||||
Self::Owned(s) => s,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.as_str().is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.as_str().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Estring {
|
||||
fn default() -> Self {
|
||||
Self::Static("")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::AsRef<str> for Estring {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::borrow::Borrow<str> for Estring {
|
||||
fn borrow(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for Estring {
|
||||
#[inline]
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_str().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Estring {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::Eq for Estring {}
|
||||
|
||||
impl std::cmp::PartialOrd for Estring {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::Ord for Estring {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.as_str().cmp(other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Estring {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Estring {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
impl std::convert::From<&'static str> for Estring {
|
||||
fn from(s: &'static str) -> Self {
|
||||
Self::Static(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<String> for Estring {
|
||||
fn from(s: String) -> Self {
|
||||
Self::Owned(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<&String> for Estring {
|
||||
fn from(s: &String) -> Self {
|
||||
Self::Owned(s.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<&Estring> for Estring {
|
||||
fn from(s: &Estring) -> Self {
|
||||
s.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
impl std::ops::Index<std::ops::Range<usize>> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::Range<usize>) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<std::ops::RangeTo<usize>> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::RangeTo<usize>) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<std::ops::RangeFrom<usize>> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::RangeFrom<usize>) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<std::ops::RangeFull> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::RangeFull) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<std::ops::RangeInclusive<usize>> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::RangeInclusive<usize>) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<std::ops::RangeToInclusive<usize>> for Estring {
|
||||
type Output = str;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: std::ops::RangeToInclusive<usize>) -> &str {
|
||||
self.as_str().index(index)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
mutex::Mutex,
|
||||
text::{
|
||||
font::{Font, FontImpl},
|
||||
Galley, LayoutJob,
|
||||
Estring, Galley, LayoutJob,
|
||||
},
|
||||
Texture, TextureAtlas,
|
||||
};
|
||||
|
@ -330,7 +330,7 @@ impl Fonts {
|
|||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout(
|
||||
&self,
|
||||
text: String,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
wrap_width: f32,
|
||||
|
@ -344,7 +344,7 @@ impl Fonts {
|
|||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_no_wrap(
|
||||
&self,
|
||||
text: String,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: crate::Color32,
|
||||
) -> Arc<Galley> {
|
||||
|
@ -357,7 +357,7 @@ impl Fonts {
|
|||
/// The implementation uses memoization so repeated calls are cheap.
|
||||
pub fn layout_delayed_color(
|
||||
&self,
|
||||
text: String,
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
wrap_width: f32,
|
||||
) -> Arc<Galley> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Everything related to text, fonts, text layout, cursors etc.
|
||||
|
||||
pub mod cursor;
|
||||
mod estring;
|
||||
mod font;
|
||||
mod fonts;
|
||||
mod text_layout;
|
||||
|
@ -10,6 +11,7 @@ mod text_layout_types;
|
|||
pub const TAB_SIZE: usize = 4;
|
||||
|
||||
pub use {
|
||||
estring::Estring,
|
||||
fonts::{FontDefinitions, FontFamily, Fonts, TextStyle},
|
||||
text_layout::layout,
|
||||
text_layout_types::*,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{cursor::*, font::UvRect};
|
||||
use super::{cursor::*, font::UvRect, Estring};
|
||||
use crate::{Color32, Mesh, Stroke, TextStyle};
|
||||
use emath::*;
|
||||
|
||||
|
@ -13,7 +13,7 @@ use emath::*;
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct LayoutJob {
|
||||
/// The complete text of this job, referenced by `LayoutSection`.
|
||||
pub text: String, // TODO: Cow<'static, str>
|
||||
pub text: Estring,
|
||||
|
||||
/// The different section, which can have different fonts, colors, etc.
|
||||
pub sections: Vec<LayoutSection>,
|
||||
|
@ -53,7 +53,13 @@ impl Default for LayoutJob {
|
|||
impl LayoutJob {
|
||||
/// Break on `\n` and at the given wrap width.
|
||||
#[inline]
|
||||
pub fn simple(text: String, text_style: TextStyle, color: Color32, wrap_width: f32) -> Self {
|
||||
pub fn simple(
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: Color32,
|
||||
wrap_width: f32,
|
||||
) -> Self {
|
||||
let text = text.into();
|
||||
Self {
|
||||
sections: vec![LayoutSection {
|
||||
leading_space: 0.0,
|
||||
|
@ -69,7 +75,12 @@ impl LayoutJob {
|
|||
|
||||
/// Does not break on `\n`, but shows the replacement character instead.
|
||||
#[inline]
|
||||
pub fn simple_singleline(text: String, text_style: TextStyle, color: Color32) -> Self {
|
||||
pub fn simple_singleline(
|
||||
text: impl Into<Estring>,
|
||||
text_style: TextStyle,
|
||||
color: Color32,
|
||||
) -> Self {
|
||||
let text = text.into();
|
||||
Self {
|
||||
sections: vec![LayoutSection {
|
||||
leading_space: 0.0,
|
||||
|
@ -87,18 +98,6 @@ impl LayoutJob {
|
|||
pub fn is_empty(&self) -> bool {
|
||||
self.sections.is_empty()
|
||||
}
|
||||
|
||||
/// Helper for adding a new section when building a `LayoutJob`.
|
||||
pub fn append(&mut self, text: &str, leading_space: f32, format: TextFormat) {
|
||||
let start = self.text.len();
|
||||
self.text += text;
|
||||
let byte_range = start..self.text.len();
|
||||
self.sections.push(LayoutSection {
|
||||
leading_space,
|
||||
byte_range,
|
||||
format,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for LayoutJob {
|
||||
|
@ -135,6 +134,37 @@ impl std::cmp::Eq for LayoutJob {}
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Build a [`LayoutJob`] from many small pieces.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct LayoutJobBuilder {
|
||||
text: String,
|
||||
sections: Vec<LayoutSection>,
|
||||
}
|
||||
|
||||
impl LayoutJobBuilder {
|
||||
/// Helper for adding a new section when building a `LayoutJob`.
|
||||
pub fn append(&mut self, text: &str, leading_space: f32, format: TextFormat) {
|
||||
let start = self.text.len();
|
||||
self.text += text;
|
||||
let byte_range = start..self.text.len();
|
||||
self.sections.push(LayoutSection {
|
||||
leading_space,
|
||||
byte_range,
|
||||
format,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn build(self) -> LayoutJob {
|
||||
LayoutJob {
|
||||
text: self.text.into(),
|
||||
sections: self.sections,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LayoutSection {
|
||||
/// Can be used for first row indentation.
|
||||
|
@ -366,7 +396,7 @@ impl Galley {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn text(&self) -> &str {
|
||||
&self.job.text
|
||||
self.job.text.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue