committed by
Max Brunsfeld
co-authored by
Max Brunsfeld
parent
91c2b5825e
commit
33dbbf271e
@@ -11,6 +11,7 @@ mod list;
|
|||||||
mod mouse_event_handler;
|
mod mouse_event_handler;
|
||||||
mod stack;
|
mod stack;
|
||||||
mod svg;
|
mod svg;
|
||||||
|
mod text;
|
||||||
mod uniform_list;
|
mod uniform_list;
|
||||||
|
|
||||||
pub use crate::presenter::ChildView;
|
pub use crate::presenter::ChildView;
|
||||||
@@ -27,6 +28,7 @@ pub use list::*;
|
|||||||
pub use mouse_event_handler::*;
|
pub use mouse_event_handler::*;
|
||||||
pub use stack::*;
|
pub use stack::*;
|
||||||
pub use svg::*;
|
pub use svg::*;
|
||||||
|
pub use text::*;
|
||||||
pub use uniform_list::*;
|
pub use uniform_list::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
use crate::{
|
||||||
|
color::Color,
|
||||||
|
font_cache::FamilyId,
|
||||||
|
fonts::{FontId, TextStyle},
|
||||||
|
geometry::{
|
||||||
|
rect::RectF,
|
||||||
|
vector::{vec2f, Vector2F},
|
||||||
|
},
|
||||||
|
json::{ToJson, Value},
|
||||||
|
text_layout::Line,
|
||||||
|
DebugContext, Element, Event, EventContext, FontCache, LayoutContext, PaintContext,
|
||||||
|
SizeConstraint,
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_json::json;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
|
pub struct Text {
|
||||||
|
text: String,
|
||||||
|
family_id: FamilyId,
|
||||||
|
font_size: f32,
|
||||||
|
style: TextStyle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Text {
|
||||||
|
pub fn new(text: String, family_id: FamilyId, font_size: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
text,
|
||||||
|
family_id,
|
||||||
|
font_size,
|
||||||
|
style: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_style(mut self, style: &TextStyle) -> Self {
|
||||||
|
self.style = style.clone();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_default_color(mut self, color: Color) -> Self {
|
||||||
|
self.style.color = color;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element for Text {
|
||||||
|
type LayoutState = Line;
|
||||||
|
type PaintState = ();
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
constraint: SizeConstraint,
|
||||||
|
cx: &mut LayoutContext,
|
||||||
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
|
let font_id = cx
|
||||||
|
.font_cache
|
||||||
|
.select_font(self.family_id, &self.style.font_properties)
|
||||||
|
.unwrap();
|
||||||
|
let line =
|
||||||
|
cx.text_layout_cache
|
||||||
|
.layout_str(self.text.as_str(), self.font_size, runs.as_slice());
|
||||||
|
|
||||||
|
let size = vec2f(
|
||||||
|
line.width().max(constraint.min.x()).min(constraint.max.x()),
|
||||||
|
cx.font_cache.line_height(font_id, self.font_size).ceil(),
|
||||||
|
);
|
||||||
|
|
||||||
|
(size, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
bounds: RectF,
|
||||||
|
line: &mut Self::LayoutState,
|
||||||
|
cx: &mut PaintContext,
|
||||||
|
) -> Self::PaintState {
|
||||||
|
line.paint(
|
||||||
|
bounds.origin(),
|
||||||
|
RectF::new(vec2f(0., 0.), bounds.size()),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_event(
|
||||||
|
&mut self,
|
||||||
|
_: &Event,
|
||||||
|
_: RectF,
|
||||||
|
_: &mut Self::LayoutState,
|
||||||
|
_: &mut Self::PaintState,
|
||||||
|
_: &mut EventContext,
|
||||||
|
) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug(
|
||||||
|
&self,
|
||||||
|
bounds: RectF,
|
||||||
|
_: &Self::LayoutState,
|
||||||
|
_: &Self::PaintState,
|
||||||
|
cx: &DebugContext,
|
||||||
|
) -> Value {
|
||||||
|
json!({
|
||||||
|
"type": "Label",
|
||||||
|
"bounds": bounds.to_json(),
|
||||||
|
"text": &self.text,
|
||||||
|
"highlight_indices": self.highlight_indices,
|
||||||
|
"font_family": cx.font_cache.family_name(self.family_id).unwrap(),
|
||||||
|
"font_size": self.font_size,
|
||||||
|
"style": self.style.to_json(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::fonts::{Properties as FontProperties, Weight};
|
||||||
|
|
||||||
|
#[crate::test(self)]
|
||||||
|
fn test_layout_label_with_highlights(cx: &mut crate::MutableAppContext) {
|
||||||
|
let menlo = cx.font_cache().load_family(&["Menlo"]).unwrap();
|
||||||
|
let menlo_regular = cx
|
||||||
|
.font_cache()
|
||||||
|
.select_font(menlo, &FontProperties::new())
|
||||||
|
.unwrap();
|
||||||
|
let menlo_bold = cx
|
||||||
|
.font_cache()
|
||||||
|
.select_font(menlo, FontProperties::new().weight(Weight::BOLD))
|
||||||
|
.unwrap();
|
||||||
|
let black = Color::black();
|
||||||
|
let red = Color::new(255, 0, 0, 255);
|
||||||
|
|
||||||
|
let label = Text::new(".αβγδε.ⓐⓑⓒⓓⓔ.abcde.".to_string(), menlo, 12.0)
|
||||||
|
.with_style(&TextStyle {
|
||||||
|
text: TextStyle {
|
||||||
|
color: black,
|
||||||
|
font_properties: Default::default(),
|
||||||
|
},
|
||||||
|
highlight_text: Some(TextStyle {
|
||||||
|
color: red,
|
||||||
|
font_properties: *FontProperties::new().weight(Weight::BOLD),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.with_highlights(vec![
|
||||||
|
".α".len(),
|
||||||
|
".αβ".len(),
|
||||||
|
".αβγδ".len(),
|
||||||
|
".αβγδε.ⓐ".len(),
|
||||||
|
".αβγδε.ⓐⓑ".len(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let runs = label.compute_runs(cx.font_cache().as_ref(), menlo_regular);
|
||||||
|
assert_eq!(
|
||||||
|
runs.as_slice(),
|
||||||
|
&[
|
||||||
|
(".α".len(), menlo_regular, black),
|
||||||
|
("βγ".len(), menlo_bold, red),
|
||||||
|
("δ".len(), menlo_regular, black),
|
||||||
|
("ε".len(), menlo_bold, red),
|
||||||
|
(".ⓐ".len(), menlo_regular, black),
|
||||||
|
("ⓑⓒ".len(), menlo_bold, red),
|
||||||
|
("ⓓⓔ.abcde.".len(), menlo_regular, black),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user