Add UI to modify `FontTweak` live (#5125)
This will make it easier to get nice sizing and vertical alignments of fonts
This commit is contained in:
parent
e31b44f1a5
commit
f4ed394a85
|
|
@ -4,9 +4,15 @@ use std::{borrow::Cow, cell::RefCell, panic::Location, sync::Arc, time::Duration
|
||||||
|
|
||||||
use containers::area::AreaState;
|
use containers::area::AreaState;
|
||||||
use epaint::{
|
use epaint::{
|
||||||
emath, emath::TSTransform, mutex::RwLock, pos2, stats::PaintStats, tessellator, text::Fonts,
|
emath::{self, TSTransform},
|
||||||
util::OrderedFloat, vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2,
|
mutex::RwLock,
|
||||||
Rect, TessellationOptions, TextureAtlas, TextureId, Vec2,
|
pos2,
|
||||||
|
stats::PaintStats,
|
||||||
|
tessellator,
|
||||||
|
text::Fonts,
|
||||||
|
util::OrderedFloat,
|
||||||
|
vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect,
|
||||||
|
TessellationOptions, TextureAtlas, TextureId, Vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -2817,6 +2823,10 @@ impl Context {
|
||||||
let prev_options = self.options(|o| o.clone());
|
let prev_options = self.options(|o| o.clone());
|
||||||
let mut options = prev_options.clone();
|
let mut options = prev_options.clone();
|
||||||
|
|
||||||
|
ui.collapsing("🔠 Font tweak", |ui| {
|
||||||
|
self.fonts_tweak_ui(ui);
|
||||||
|
});
|
||||||
|
|
||||||
options.ui(ui);
|
options.ui(ui);
|
||||||
|
|
||||||
if options != prev_options {
|
if options != prev_options {
|
||||||
|
|
@ -2824,6 +2834,23 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fonts_tweak_ui(&self, ui: &mut Ui) {
|
||||||
|
let mut font_definitions = self.write(|ctx| ctx.font_definitions.clone());
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
for (name, data) in &mut font_definitions.font_data {
|
||||||
|
ui.collapsing(name, |ui| {
|
||||||
|
if data.tweak.ui(ui).changed() {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
self.set_fonts(font_definitions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Show the state of egui, including its input and output.
|
/// Show the state of egui, including its input and output.
|
||||||
pub fn inspection_ui(&self, ui: &mut Ui) {
|
pub fn inspection_ui(&self, ui: &mut Ui) {
|
||||||
use crate::containers::CollapsingHeader;
|
use crate::containers::CollapsingHeader;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::{collections::BTreeMap, ops::RangeInclusive, sync::Arc};
|
use std::{collections::BTreeMap, ops::RangeInclusive, sync::Arc};
|
||||||
|
|
||||||
use epaint::{Rounding, Shadow, Stroke};
|
use epaint::{text::FontTweak, Rounding, Shadow, Stroke};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ecolor::Color32,
|
ecolor::Color32,
|
||||||
|
|
@ -2498,3 +2498,48 @@ impl Widget for &mut crate::Frame {
|
||||||
.response
|
.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Widget for &mut FontTweak {
|
||||||
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
|
let original: FontTweak = *self;
|
||||||
|
|
||||||
|
let mut response = Grid::new("font_tweak")
|
||||||
|
.num_columns(2)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
let FontTweak {
|
||||||
|
scale,
|
||||||
|
y_offset_factor,
|
||||||
|
y_offset,
|
||||||
|
baseline_offset_factor,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
ui.label("Scale");
|
||||||
|
let speed = *scale * 0.01;
|
||||||
|
ui.add(DragValue::new(scale).range(0.01..=10.0).speed(speed));
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("y_offset_factor");
|
||||||
|
ui.add(DragValue::new(y_offset_factor).speed(-0.0025));
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("y_offset");
|
||||||
|
ui.add(DragValue::new(y_offset).speed(-0.02));
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("baseline_offset_factor");
|
||||||
|
ui.add(DragValue::new(baseline_offset_factor).speed(-0.0025));
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
if ui.button("Reset").clicked() {
|
||||||
|
*self = Default::default();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.response;
|
||||||
|
|
||||||
|
if *self != original {
|
||||||
|
response.mark_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1404,7 +1404,7 @@ impl Ui {
|
||||||
///
|
///
|
||||||
/// If this is called multiple times per frame for the same [`crate::ScrollArea`], the deltas will be summed.
|
/// If this is called multiple times per frame for the same [`crate::ScrollArea`], the deltas will be summed.
|
||||||
///
|
///
|
||||||
/// /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`]
|
/// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`]
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use egui::{Align, Vec2};
|
/// # use egui::{Align, Vec2};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
struct GlyphInfo {
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
// What fonts it is available in
|
||||||
|
fonts: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FontBook {
|
pub struct FontBook {
|
||||||
filter: String,
|
filter: String,
|
||||||
font_id: egui::FontId,
|
font_id: egui::FontId,
|
||||||
named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>,
|
available_glyphs: BTreeMap<egui::FontFamily, BTreeMap<char, GlyphInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FontBook {
|
impl Default for FontBook {
|
||||||
|
|
@ -11,7 +18,7 @@ impl Default for FontBook {
|
||||||
Self {
|
Self {
|
||||||
filter: Default::default(),
|
filter: Default::default(),
|
||||||
font_id: egui::FontId::proportional(18.0),
|
font_id: egui::FontId::proportional(18.0),
|
||||||
named_chars: Default::default(),
|
available_glyphs: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +44,7 @@ impl crate::View for FontBook {
|
||||||
|
|
||||||
ui.label(format!(
|
ui.label(format!(
|
||||||
"The selected font supports {} characters.",
|
"The selected font supports {} characters.",
|
||||||
self.named_chars
|
self.available_glyphs
|
||||||
.get(&self.font_id.family)
|
.get(&self.font_id.family)
|
||||||
.map(|map| map.len())
|
.map(|map| map.len())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
|
@ -67,8 +74,8 @@ impl crate::View for FontBook {
|
||||||
});
|
});
|
||||||
|
|
||||||
let filter = &self.filter;
|
let filter = &self.filter;
|
||||||
let named_chars = self
|
let available_glyphs = self
|
||||||
.named_chars
|
.available_glyphs
|
||||||
.entry(self.font_id.family.clone())
|
.entry(self.font_id.family.clone())
|
||||||
.or_insert_with(|| available_characters(ui, self.font_id.family.clone()));
|
.or_insert_with(|| available_characters(ui, self.font_id.family.clone()));
|
||||||
|
|
||||||
|
|
@ -78,8 +85,11 @@ impl crate::View for FontBook {
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
ui.spacing_mut().item_spacing = egui::Vec2::splat(2.0);
|
ui.spacing_mut().item_spacing = egui::Vec2::splat(2.0);
|
||||||
|
|
||||||
for (&chr, name) in named_chars {
|
for (&chr, glyph_info) in available_glyphs {
|
||||||
if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() {
|
if filter.is_empty()
|
||||||
|
|| glyph_info.name.contains(filter)
|
||||||
|
|| *filter == chr.to_string()
|
||||||
|
{
|
||||||
let button = egui::Button::new(
|
let button = egui::Button::new(
|
||||||
egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
|
egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
|
||||||
)
|
)
|
||||||
|
|
@ -89,7 +99,10 @@ impl crate::View for FontBook {
|
||||||
ui.label(
|
ui.label(
|
||||||
egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
|
egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
|
||||||
);
|
);
|
||||||
ui.label(format!("{}\nU+{:X}\n\nClick to copy", name, chr as u32));
|
ui.label(format!(
|
||||||
|
"{}\nU+{:X}\n\nFound in: {:?}\n\nClick to copy",
|
||||||
|
glyph_info.name, chr as u32, glyph_info.fonts
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
if ui.add(button).on_hover_ui(tooltip_ui).clicked() {
|
if ui.add(button).on_hover_ui(tooltip_ui).clicked() {
|
||||||
|
|
@ -102,15 +115,23 @@ impl crate::View for FontBook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap<char, String> {
|
fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap<char, GlyphInfo> {
|
||||||
ui.fonts(|f| {
|
ui.fonts(|f| {
|
||||||
f.lock()
|
f.lock()
|
||||||
.fonts
|
.fonts
|
||||||
.font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters
|
.font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters
|
||||||
.characters()
|
.characters()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|chr| !chr.is_whitespace() && !chr.is_ascii_control())
|
.filter(|(chr, _fonts)| !chr.is_whitespace() && !chr.is_ascii_control())
|
||||||
.map(|&chr| (chr, char_name(chr)))
|
.map(|(chr, fonts)| {
|
||||||
|
(
|
||||||
|
*chr,
|
||||||
|
GlyphInfo {
|
||||||
|
name: char_name(*chr),
|
||||||
|
fonts: fonts.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use emath::{vec2, Vec2};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mutex::{Mutex, RwLock},
|
mutex::{Mutex, RwLock},
|
||||||
text::FontTweak,
|
text::FontTweak,
|
||||||
TextureAtlas,
|
TextureAtlas,
|
||||||
};
|
};
|
||||||
use emath::{vec2, Vec2};
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -330,7 +332,7 @@ pub struct Font {
|
||||||
fonts: Vec<Arc<FontImpl>>,
|
fonts: Vec<Arc<FontImpl>>,
|
||||||
|
|
||||||
/// Lazily calculated.
|
/// Lazily calculated.
|
||||||
characters: Option<BTreeSet<char>>,
|
characters: Option<BTreeMap<char, Vec<String>>>,
|
||||||
|
|
||||||
replacement_glyph: (FontIndex, GlyphInfo),
|
replacement_glyph: (FontIndex, GlyphInfo),
|
||||||
pixels_per_point: f32,
|
pixels_per_point: f32,
|
||||||
|
|
@ -398,12 +400,14 @@ impl Font {
|
||||||
self.glyph_info(crate::text::PASSWORD_REPLACEMENT_CHAR);
|
self.glyph_info(crate::text::PASSWORD_REPLACEMENT_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All supported characters.
|
/// All supported characters, and in which font they are available in.
|
||||||
pub fn characters(&mut self) -> &BTreeSet<char> {
|
pub fn characters(&mut self) -> &BTreeMap<char, Vec<String>> {
|
||||||
self.characters.get_or_insert_with(|| {
|
self.characters.get_or_insert_with(|| {
|
||||||
let mut characters = BTreeSet::new();
|
let mut characters: BTreeMap<char, Vec<String>> = Default::default();
|
||||||
for font in &self.fonts {
|
for font in &self.fonts {
|
||||||
characters.extend(font.characters());
|
for chr in font.characters() {
|
||||||
|
characters.entry(chr).or_default().push(font.name.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
characters
|
characters
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ pub struct FontTweak {
|
||||||
/// Shift font's glyphs downwards by this fraction of the font size (in points).
|
/// Shift font's glyphs downwards by this fraction of the font size (in points).
|
||||||
/// this is only a visual effect and does not affect the text layout.
|
/// this is only a visual effect and does not affect the text layout.
|
||||||
///
|
///
|
||||||
|
/// Affects larger font sizes more.
|
||||||
|
///
|
||||||
/// A positive value shifts the text downwards.
|
/// A positive value shifts the text downwards.
|
||||||
/// A negative value shifts it upwards.
|
/// A negative value shifts it upwards.
|
||||||
///
|
///
|
||||||
|
|
@ -168,6 +170,8 @@ pub struct FontTweak {
|
||||||
/// Shift font's glyphs downwards by this amount of logical points.
|
/// Shift font's glyphs downwards by this amount of logical points.
|
||||||
/// this is only a visual effect and does not affect the text layout.
|
/// this is only a visual effect and does not affect the text layout.
|
||||||
///
|
///
|
||||||
|
/// Affects all font sizes equally.
|
||||||
|
///
|
||||||
/// Example value: `2.0`.
|
/// Example value: `2.0`.
|
||||||
pub y_offset: f32,
|
pub y_offset: f32,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,7 @@ fn replace_last_glyph_with_overflow_character(
|
||||||
|
|
||||||
/// Horizontally aligned the text on a row.
|
/// Horizontally aligned the text on a row.
|
||||||
///
|
///
|
||||||
/// /// Ignores the Y coordinate.
|
/// Ignores the Y coordinate.
|
||||||
fn halign_and_justify_row(
|
fn halign_and_justify_row(
|
||||||
point_scale: PointScale,
|
point_scale: PointScale,
|
||||||
row: &mut Row,
|
row: &mut Row,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue