Skip to content

Commit

Permalink
RichText: Invalidate layout on Env change (#1907)
Browse files Browse the repository at this point in the history
  • Loading branch information
maan2003 authored Aug 16, 2021
1 parent 2cda55d commit e6de7fc
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ You can find its changes [documented below](#070---2021-01-01).
- X11 backend now supports changing cursors ([#1755] by [@Maan2003])
- X11 backend now uses the platform locale ([#1756] by [@Maan2003])
- `Either` and `Tab` widgets were still propagating events to hidden widgets ([#1860] by [@lisael])
- RichText: Invalidate layout on Env change ([#1907] by [@Maan2003])

### Visual

Expand Down Expand Up @@ -780,6 +781,7 @@ Last release without a changelog :(
[#1884]: https://github.com/linebender/druid/pull/1884
[#1885]: https://github.com/linebender/druid/pull/1885
[#1886]: https://github.com/linebender/druid/pull/1886
[#1907]: https://github.com/linebender/druid/pull/1907

[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0
Expand Down
16 changes: 16 additions & 0 deletions druid/src/text/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::ops::Range;
use crate::piet::{Color, FontFamily, FontStyle, FontWeight, TextAttribute as PietAttr};
use crate::{Command, Env, FontDescriptor, KeyOrValue};

use super::EnvUpdateCtx;

/// A clickable range of text with an associated [`Command`].
#[derive(Debug, Clone)]
pub struct Link {
Expand Down Expand Up @@ -179,6 +181,20 @@ impl AttributeSpans {
items.sort_by(|a, b| a.0.start.cmp(&b.0.start));
items
}

pub(crate) fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
self.size
.iter()
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
|| self
.fg_color
.iter()
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
|| self
.font_descriptor
.iter()
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
}
}

impl<T: Clone> SpanSet<T> {
Expand Down
7 changes: 6 additions & 1 deletion druid/src/text/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use std::ops::Range;
use std::rc::Rc;

use super::{Link, TextStorage};
use super::{EnvUpdateCtx, Link, TextStorage};
use crate::kurbo::{Line, Point, Rect, Size};
use crate::piet::{
Color, PietText, PietTextLayout, Text as _, TextAlignment, TextAttribute, TextLayout as _,
Expand Down Expand Up @@ -347,6 +347,11 @@ impl<T: TextStorage> TextLayout<T> {
.text_size_override
.as_ref()
.map(|k| ctx.env_key_changed(k))
.unwrap_or(false)
|| self
.text
.as_ref()
.map(|text| text.env_update(&EnvUpdateCtx::for_update(ctx)))
.unwrap_or(false);

if rebuild {
Expand Down
2 changes: 1 addition & 1 deletion druid/src/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ pub use self::movement::movement;
pub use input_component::{EditSession, TextComponent};
pub use input_methods::ImeHandlerRef;
pub use rich_text::{AttributesAdder, RichText, RichTextBuilder};
pub use storage::{ArcStr, TextStorage};
pub use storage::{ArcStr, EnvUpdateCtx, TextStorage};

pub(crate) use input_methods::TextFieldRegistration;
6 changes: 5 additions & 1 deletion druid/src/text/rich_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::ops::{Range, RangeBounds};
use std::sync::Arc;

use super::attribute::Link;
use super::{Attribute, AttributeSpans, TextStorage};
use super::{Attribute, AttributeSpans, EnvUpdateCtx, TextStorage};
use crate::piet::{
util, Color, FontFamily, FontStyle, FontWeight, PietTextLayoutBuilder, TextLayoutBuilder,
TextStorage as PietTextStorage,
Expand Down Expand Up @@ -93,6 +93,10 @@ impl TextStorage for RichText {
builder
}

fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
self.attrs.env_update(ctx)
}

fn links(&self) -> &[Link] {
&self.links
}
Expand Down
29 changes: 29 additions & 0 deletions druid/src/text/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
use std::sync::Arc;

use crate::env::KeyLike;
use crate::piet::{PietTextLayoutBuilder, TextStorage as PietTextStorage};
use crate::{Data, Env};

use super::attribute::Link;
use crate::UpdateCtx;

/// A type that represents text that can be displayed.
pub trait TextStorage: PietTextStorage + Data {
Expand All @@ -30,6 +32,13 @@ pub trait TextStorage: PietTextStorage + Data {
builder
}

/// This is called whenever the Env changes and should return true
/// if the layout should be rebuilt.
#[allow(unused_variables)]
fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
false
}

/// Any additional [`Link`] attributes on this text.
///
/// If this `TextStorage` object manages link attributes, it should implement this
Expand All @@ -45,6 +54,26 @@ pub trait TextStorage: PietTextStorage + Data {
}
}

/// Provides information about keys change for more fine grained invalidation
pub struct EnvUpdateCtx<'a, 'b>(&'a UpdateCtx<'a, 'b>);

impl<'a, 'b> EnvUpdateCtx<'a, 'b> {
/// Create an EnvChangeCtx for Widget::update
pub(crate) fn for_update(ctx: &'a UpdateCtx<'a, 'b>) -> Self {
Self(ctx)
}

/// Returns `true` if the given key has changed since the last [`env_update`]
/// call.
///
/// See [`UpdateCtx::env_key_changed`] for more details.
///
/// [`env_update`]: (TextStorage::env_update)
pub fn env_key_changed<T>(&self, key: &impl KeyLike<T>) -> bool {
self.0.env_key_changed(key)
}
}

/// A reference counted string slice.
///
/// This is a data-friendly way to represent strings in druid. Unlike `String`
Expand Down

0 comments on commit e6de7fc

Please sign in to comment.