Skip to content

Commit e6de7fc

Browse files
authored
RichText: Invalidate layout on Env change (#1907)
1 parent 2cda55d commit e6de7fc

File tree

6 files changed

+59
-3
lines changed

6 files changed

+59
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ You can find its changes [documented below](#070---2021-01-01).
9797
- X11 backend now supports changing cursors ([#1755] by [@Maan2003])
9898
- X11 backend now uses the platform locale ([#1756] by [@Maan2003])
9999
- `Either` and `Tab` widgets were still propagating events to hidden widgets ([#1860] by [@lisael])
100+
- RichText: Invalidate layout on Env change ([#1907] by [@Maan2003])
100101

101102
### Visual
102103

@@ -780,6 +781,7 @@ Last release without a changelog :(
780781
[#1884]: https://github.com/linebender/druid/pull/1884
781782
[#1885]: https://github.com/linebender/druid/pull/1885
782783
[#1886]: https://github.com/linebender/druid/pull/1886
784+
[#1907]: https://github.com/linebender/druid/pull/1907
783785

784786
[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
785787
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0

druid/src/text/attribute.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use std::ops::Range;
1919
use crate::piet::{Color, FontFamily, FontStyle, FontWeight, TextAttribute as PietAttr};
2020
use crate::{Command, Env, FontDescriptor, KeyOrValue};
2121

22+
use super::EnvUpdateCtx;
23+
2224
/// A clickable range of text with an associated [`Command`].
2325
#[derive(Debug, Clone)]
2426
pub struct Link {
@@ -179,6 +181,20 @@ impl AttributeSpans {
179181
items.sort_by(|a, b| a.0.start.cmp(&b.0.start));
180182
items
181183
}
184+
185+
pub(crate) fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
186+
self.size
187+
.iter()
188+
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
189+
|| self
190+
.fg_color
191+
.iter()
192+
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
193+
|| self
194+
.font_descriptor
195+
.iter()
196+
.any(|span_attr| ctx.env_key_changed(&span_attr.attr))
197+
}
182198
}
183199

184200
impl<T: Clone> SpanSet<T> {

druid/src/text/layout.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use std::ops::Range;
1818
use std::rc::Rc;
1919

20-
use super::{Link, TextStorage};
20+
use super::{EnvUpdateCtx, Link, TextStorage};
2121
use crate::kurbo::{Line, Point, Rect, Size};
2222
use crate::piet::{
2323
Color, PietText, PietTextLayout, Text as _, TextAlignment, TextAttribute, TextLayout as _,
@@ -347,6 +347,11 @@ impl<T: TextStorage> TextLayout<T> {
347347
.text_size_override
348348
.as_ref()
349349
.map(|k| ctx.env_key_changed(k))
350+
.unwrap_or(false)
351+
|| self
352+
.text
353+
.as_ref()
354+
.map(|text| text.env_update(&EnvUpdateCtx::for_update(ctx)))
350355
.unwrap_or(false);
351356

352357
if rebuild {

druid/src/text/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ pub use self::movement::movement;
4949
pub use input_component::{EditSession, TextComponent};
5050
pub use input_methods::ImeHandlerRef;
5151
pub use rich_text::{AttributesAdder, RichText, RichTextBuilder};
52-
pub use storage::{ArcStr, TextStorage};
52+
pub use storage::{ArcStr, EnvUpdateCtx, TextStorage};
5353

5454
pub(crate) use input_methods::TextFieldRegistration;

druid/src/text/rich_text.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::ops::{Range, RangeBounds};
1818
use std::sync::Arc;
1919

2020
use super::attribute::Link;
21-
use super::{Attribute, AttributeSpans, TextStorage};
21+
use super::{Attribute, AttributeSpans, EnvUpdateCtx, TextStorage};
2222
use crate::piet::{
2323
util, Color, FontFamily, FontStyle, FontWeight, PietTextLayoutBuilder, TextLayoutBuilder,
2424
TextStorage as PietTextStorage,
@@ -93,6 +93,10 @@ impl TextStorage for RichText {
9393
builder
9494
}
9595

96+
fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
97+
self.attrs.env_update(ctx)
98+
}
99+
96100
fn links(&self) -> &[Link] {
97101
&self.links
98102
}

druid/src/text/storage.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
1717
use std::sync::Arc;
1818

19+
use crate::env::KeyLike;
1920
use crate::piet::{PietTextLayoutBuilder, TextStorage as PietTextStorage};
2021
use crate::{Data, Env};
2122

2223
use super::attribute::Link;
24+
use crate::UpdateCtx;
2325

2426
/// A type that represents text that can be displayed.
2527
pub trait TextStorage: PietTextStorage + Data {
@@ -30,6 +32,13 @@ pub trait TextStorage: PietTextStorage + Data {
3032
builder
3133
}
3234

35+
/// This is called whenever the Env changes and should return true
36+
/// if the layout should be rebuilt.
37+
#[allow(unused_variables)]
38+
fn env_update(&self, ctx: &EnvUpdateCtx) -> bool {
39+
false
40+
}
41+
3342
/// Any additional [`Link`] attributes on this text.
3443
///
3544
/// If this `TextStorage` object manages link attributes, it should implement this
@@ -45,6 +54,26 @@ pub trait TextStorage: PietTextStorage + Data {
4554
}
4655
}
4756

57+
/// Provides information about keys change for more fine grained invalidation
58+
pub struct EnvUpdateCtx<'a, 'b>(&'a UpdateCtx<'a, 'b>);
59+
60+
impl<'a, 'b> EnvUpdateCtx<'a, 'b> {
61+
/// Create an EnvChangeCtx for Widget::update
62+
pub(crate) fn for_update(ctx: &'a UpdateCtx<'a, 'b>) -> Self {
63+
Self(ctx)
64+
}
65+
66+
/// Returns `true` if the given key has changed since the last [`env_update`]
67+
/// call.
68+
///
69+
/// See [`UpdateCtx::env_key_changed`] for more details.
70+
///
71+
/// [`env_update`]: (TextStorage::env_update)
72+
pub fn env_key_changed<T>(&self, key: &impl KeyLike<T>) -> bool {
73+
self.0.env_key_changed(key)
74+
}
75+
}
76+
4877
/// A reference counted string slice.
4978
///
5079
/// This is a data-friendly way to represent strings in druid. Unlike `String`

0 commit comments

Comments
 (0)