Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo
2021-08-24 18:16:31 -06:00
committed by Max Brunsfeld
parent 91c2b5825e
commit 33dbbf271e
2 changed files with 168 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ mod list;
mod mouse_event_handler;
mod stack;
mod svg;
mod text;
mod uniform_list;
pub use crate::presenter::ChildView;
@@ -27,6 +28,7 @@ pub use list::*;
pub use mouse_event_handler::*;
pub use stack::*;
pub use svg::*;
pub use text::*;
pub use uniform_list::*;
use crate::{

166
gpui/src/elements/text.rs Normal file
View File

@@ -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),
]
);
}
}