Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

New text integration #1182

Merged
merged 1 commit into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ You can find its changes [documented below](#060---2020-06-01).
- `Command::to` and `Command::target` to set and get a commands target. ([#1185] by [@finnerale])
- `Menu` commands can now choose a custom target. ([#1185] by [@finnerale])
- `Movement::StartOfDocument`, `Movement::EndOfDocument`. ([#1092] by [@sysint64])
- `TextLayout` type simplifies drawing text ([#1182] by [@cmyr])

### Changed

Expand Down Expand Up @@ -418,6 +419,7 @@ Last release without a changelog :(
[#1171]: https://github.com/linebender/druid/pull/1171
[#1172]: https://github.com/linebender/druid/pull/1172
[#1173]: https://github.com/linebender/druid/pull/1173
[#1182]: https://github.com/linebender/druid/pull/1185
[#1185]: https://github.com/linebender/druid/pull/1185
[#1092]: https://github.com/linebender/druid/pull/1092

Expand Down
4 changes: 2 additions & 2 deletions druid-shell/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ x11 = ["x11rb", "nix", "cairo-sys-rs"]
[dependencies]
# NOTE: When changing the piet or kurbo versions, ensure that
# the kurbo version included in piet is compatible with the kurbo version specified here.
piet-common = "0.2.0-pre2"
piet-common = "0.2.0-pre3"
kurbo = "0.6.3"

log = "0.4.11"
Expand Down Expand Up @@ -79,5 +79,5 @@ version = "0.3.44"
features = ["Window", "MouseEvent", "CssStyleDeclaration", "WheelEvent", "KeyEvent", "KeyboardEvent"]

[dev-dependencies]
piet-common = { version = "0.2.0-pre2", features = ["png"] }
piet-common = { version = "0.2.0-pre3", features = ["png"] }
simple_logger = { version = "1.9.0", default-features = false }
26 changes: 13 additions & 13 deletions druid/examples/custom_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
//! An example of a custom drawing widget.

use druid::kurbo::BezPath;
use druid::piet::{FontFamily, ImageFormat, InterpolationMode, Text, TextLayoutBuilder};
use druid::piet::{FontFamily, ImageFormat, InterpolationMode};
use druid::widget::prelude::*;
use druid::{Affine, AppLauncher, Color, LocalizedString, Point, Rect, WindowDesc};
use druid::{
Affine, AppLauncher, Color, FontDescriptor, LocalizedString, Point, Rect, TextLayout,
WindowDesc,
};

struct CustomWidget;

Expand Down Expand Up @@ -54,7 +57,7 @@ impl Widget<String> for CustomWidget {
// The paint method gets called last, after an event flow.
// It goes event -> update -> layout -> paint, and each method can influence the next.
// Basically, anything that changes the appearance of a widget causes a paint.
fn paint(&mut self, ctx: &mut PaintCtx, data: &String, _env: &Env) {
fn paint(&mut self, ctx: &mut PaintCtx, data: &String, env: &Env) {
// Let's draw a picture with Piet!

// Clear the whole widget with the color of your choice
Expand All @@ -81,21 +84,18 @@ impl Widget<String> for CustomWidget {
let fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);
ctx.fill(rect, &fill_color);

// Text is easy, if you ignore all these unwraps. Just pick a font and a size.
// Here's where we actually use the UI state
let layout = ctx
.text()
.new_text_layout(data.as_str())
.font(FontFamily::SYSTEM_UI, 24.0)
.text_color(fill_color)
.build()
.unwrap();
// Text is easy; in real use TextLayout should be stored in the widget
// and reused.
let mut layout = TextLayout::new(data.as_str());
layout.set_font(FontDescriptor::new(FontFamily::SERIF).with_size(24.0));
layout.set_text_color(fill_color);
layout.rebuild_if_needed(&mut ctx.text(), env);

// Let's rotate our text slightly. First we save our current (default) context:
ctx.with_save(|ctx| {
// Now we can rotate the context (or set a clip path, for instance):
ctx.transform(Affine::rotate(0.1));
ctx.draw_text(&layout, (80.0, 40.0));
layout.draw(ctx, (80.0, 40.0));
});
// When we exit with_save, the original context's rotation is restored

Expand Down
27 changes: 15 additions & 12 deletions druid/examples/styled_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@

use druid::widget::{Checkbox, Flex, Label, MainAxisAlignment, Painter, Parse, Stepper, TextBox};
use druid::{
theme, AppLauncher, ArcStr, Color, Data, Key, Lens, LensExt, LensWrap, LocalizedString,
PlatformError, RenderContext, Widget, WidgetExt, WindowDesc,
theme, AppLauncher, Color, Data, FontDescriptor, FontFamily, Key, Lens, LensExt, LensWrap,
LocalizedString, PlatformError, RenderContext, Widget, WidgetExt, WindowDesc,
};
use std::fmt::Display;

// This is a custom key we'll use with Env to set and get our text size.
const MY_CUSTOM_TEXT_SIZE: Key<f64> = Key::new("styled_text.custom_text_size");
const MY_CUSTOM_FONT: Key<ArcStr> = Key::new("styled_text.custom_font");
// This is a custom key we'll use with Env to set and get our font.
const MY_CUSTOM_FONT: Key<FontDescriptor> = Key::new("styled_text.custom_font");

#[derive(Clone, Lens, Data)]
struct AppData {
Expand Down Expand Up @@ -73,7 +72,7 @@ fn ui_builder() -> impl Widget<AppData> {
});

// This is druid's default text style.
// It's set by theme::LABEL_COLOR, theme::TEXT_SIZE_NORMAL, and theme::FONT_NAME
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {}", data)).lens(AppData::text);

Expand All @@ -88,19 +87,19 @@ fn ui_builder() -> impl Widget<AppData> {
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{}", data))
.with_text_color(theme::PRIMARY_LIGHT)
.with_text_size(MY_CUSTOM_TEXT_SIZE)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
env.set(MY_CUSTOM_TEXT_SIZE, data.size);
if data.mono {
env.set(MY_CUSTOM_FONT, "monospace");
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
env.set(MY_CUSTOM_FONT, env.get(theme::FONT_NAME));
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});

let stepper = Stepper::new()
Expand All @@ -118,7 +117,10 @@ fn ui_builder() -> impl Widget<AppData> {

let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);

let input = TextBox::new().fix_width(200.0).lens(AppData::text);
let input = TextBox::new()
.with_text_size(38.0)
.fix_width(200.0)
.lens(AppData::text);

Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
Expand All @@ -131,4 +133,5 @@ fn ui_builder() -> impl Widget<AppData> {
.with_child(mono_checkbox)
.with_spacer(8.0)
.with_child(input.padding(5.0))
.debug_widget_id()
}
50 changes: 22 additions & 28 deletions druid/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ use std::collections::{HashMap, VecDeque};
use crate::bloom::Bloom;
use crate::contexts::ContextState;
use crate::kurbo::{Affine, Insets, Point, Rect, Shape, Size, Vec2};
use crate::piet::{FontFamily, PietTextLayout, RenderContext, Text, TextLayout, TextLayoutBuilder};
use crate::util::ExtendDrain;
use crate::{
BoxConstraints, Color, Command, Data, Env, Event, EventCtx, InternalEvent, InternalLifeCycle,
LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx, Region, Target, TimerToken, UpdateCtx, Widget,
WidgetId,
LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx, Region, RenderContext, Target, TextLayout,
TimerToken, UpdateCtx, Widget, WidgetId,
};

/// Our queue type
Expand All @@ -51,7 +50,7 @@ pub struct WidgetPod<T, W> {
env: Option<Env>,
inner: W,
// stashed layout so we don't recompute this when debugging
debug_widget_text: Option<PietTextLayout>,
debug_widget_text: TextLayout,
}

/// Generic state for all widgets in the hierarchy.
Expand Down Expand Up @@ -145,7 +144,7 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
old_data: None,
env: None,
inner,
debug_widget_text: None,
debug_widget_text: TextLayout::new(""),
}
}

Expand Down Expand Up @@ -429,7 +428,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
}

fn make_widget_id_layout_if_needed(&mut self, id: WidgetId, ctx: &mut PaintCtx, env: &Env) {
if self.debug_widget_text.is_none() {
if self.debug_widget_text.needs_rebuild() {
// switch text color based on background, this is meh and that's okay
let border_color = env.get_debug_color(id.to_raw());
let (r, g, b, _) = border_color.as_rgba8();
Expand All @@ -439,34 +438,29 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
} else {
Color::BLACK
};

let id_string = id.to_raw().to_string();
self.debug_widget_text = ctx
.text()
.new_text_layout(id_string)
.font(FontFamily::SYSTEM_UI, 10.0)
.text_color(text_color)
.build()
.ok();
self.debug_widget_text.set_text(id_string);
self.debug_widget_text.set_text_size(10.0);
self.debug_widget_text.set_text_color(text_color);
self.debug_widget_text
.rebuild_if_needed(&mut ctx.text(), env);
}
}

fn debug_paint_widget_ids(&self, ctx: &mut PaintCtx, env: &Env) {
// we clone because we need to move it for paint_with_z_index
let text = self.debug_widget_text.clone();
if let Some(text) = text {
let text_size = text.size();
let origin = ctx.size().to_vec2() - text_size.to_vec2();
let border_color = env.get_debug_color(ctx.widget_id().to_raw());
self.debug_paint_layout_bounds(ctx, env);

ctx.paint_with_z_index(ctx.depth(), move |ctx| {
let origin = Point::new(origin.x.max(0.0), origin.y.max(0.0));
let text_rect = Rect::from_origin_size(origin, text_size);
ctx.fill(text_rect, &border_color);
ctx.draw_text(&text, origin);
})
}
let text_size = text.size();
let origin = ctx.size().to_vec2() - text_size.to_vec2();
let border_color = env.get_debug_color(ctx.widget_id().to_raw());
self.debug_paint_layout_bounds(ctx, env);

ctx.paint_with_z_index(ctx.depth(), move |ctx| {
let origin = Point::new(origin.x.max(0.0), origin.y.max(0.0));
let text_rect = Rect::from_origin_size(origin, text_size);
ctx.fill(text_rect, &border_color);
text.draw(ctx, origin);
})
}

fn debug_paint_layout_bounds(&self, ctx: &mut PaintCtx, env: &Env) {
Expand Down Expand Up @@ -1008,7 +1002,7 @@ mod tests {
state: &mut state,
};

let env = Env::default();
let env = crate::theme::init();

widget.lifecycle(&mut ctx, &LifeCycle::WidgetAdded, &None, &env);
assert!(ctx.widget_state.children.may_contain(&ID_1));
Expand Down
4 changes: 2 additions & 2 deletions druid/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct EnvImpl {
///
/// [`ValueType`]: trait.ValueType.html
/// [`Env`]: struct.Env.html
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Key<T> {
key: &'static str,
value_type: PhantomData<*const T>,
Expand Down Expand Up @@ -120,7 +120,7 @@ pub enum Value {
///
/// [`Key<T>`]: struct.Key.html
/// [`Env`]: struct.Env.html
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum KeyOrValue<T> {
/// A concrete [`Value`] of type `T`.
///
Expand Down
2 changes: 1 addition & 1 deletion druid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ pub use lens::{Lens, LensExt, LensWrap};
pub use localization::LocalizedString;
pub use menu::{sys as platform_menus, ContextMenu, MenuDesc, MenuItem};
pub use mouse::MouseEvent;
pub use text::FontDescriptor;
pub use text::{FontDescriptor, TextLayout};
pub use widget::{Widget, WidgetExt, WidgetId};
pub use win_handler::DruidHandler;
pub use window::{Window, WindowId};
Expand Down
Loading