Skip to content

Commit

Permalink
feat: make Text widget more reative (#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
shamilsan authored Sep 15, 2024
1 parent 3ca44e6 commit f45093b
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 80 deletions.
49 changes: 43 additions & 6 deletions examples/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ pub fn TextExample() -> impl IntoView {
let letters_read3 = create_rw_signal(0);
let letters_total3 = create_rw_signal(0);

let (lattice, set_lattice) = create_signal(true);
let (reverse, set_reverse) = create_signal(true);
let (shuffle, set_shuffle) = create_signal(true);
let (erase, set_erase) = create_signal(0.3);

let node_ref = create_node_ref();
_ = use_event_listener(document().body(), keydown, move |e| {
if is_active_slide(node_ref) {
Expand All @@ -34,9 +39,9 @@ pub fn TextExample() -> impl IntoView {
view! {
<Slide node_ref=node_ref>
<Row cols=2 padding=30 border_width=4>
<Column stretch=[5, 1, 5]>
<Column stretch=[5, 1, 5, 1]>
<Text
lattice=true
lattice=lattice
word_count=word_count1
words_read=words_read1
letters_read=letters_read1
Expand All @@ -46,19 +51,35 @@ pub fn TextExample() -> impl IntoView {
{"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."}
</Text>
<Label>{words_read1} "w (" {letters_read1} " / " {letters_total1} ")"</Label>
<Text valign=VAlign::Bottom reverse_words=true>
<Text valign=VAlign::Bottom reverse_words=reverse>
{"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}
{"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."}
</Text>
<Row cols=2 spacing=10>
<Button
align=Align::Fill
valign=VAlign::Fill
on_click=move |_| set_lattice.set(!lattice.get())
>
"Lattice"
</Button>
<Button
align=Align::Fill
valign=VAlign::Fill
on_click=move |_| set_reverse.set(!reverse.get())
>
"Reverse"
</Button>
</Row>
</Column>

<Column stretch=[5, 1, 5, 1]>
<Column stretch=[5, 1, 5, 1, 1]>
<Text
font_size=48
bold=true
font="serif"
valign=VAlign::Middle
shuffle_letters=true
shuffle_letters=shuffle
words_read=words_read2
letters_read=letters_read2
letters_total=letters_total2
Expand All @@ -69,7 +90,7 @@ pub fn TextExample() -> impl IntoView {
<Label>{words_read2} "w (" {letters_read2} " / " {letters_total2} ")"</Label>
<Text
font_size=48
erase_top=0.3
erase_top=erase
valign=VAlign::Bottom
words_read=words_read3
letters_read=letters_read3
Expand All @@ -79,6 +100,22 @@ pub fn TextExample() -> impl IntoView {
{"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."}
</Text>
<Label>{words_read3} "w (" {letters_read3} " / " {letters_total3} ")"</Label>
<Row cols=2 spacing=10>
<Button
align=Align::Fill
valign=VAlign::Fill
on_click=move |_| set_shuffle.set(!shuffle.get())
>
"Shuffle"
</Button>
<Button
align=Align::Fill
valign=VAlign::Fill
on_click=move |_| set_erase.set(0.3 - erase.get())
>
"Erase"
</Button>
</Row>
</Column>
</Row>
</Slide>
Expand Down
175 changes: 101 additions & 74 deletions src/widgets/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ pub fn Text(
#[prop(default = 1.4)] indent: f32,
#[prop(default = VAlign::Top)] valign: VAlign,
#[prop(default = Color::PaleGreen)] marker_color: Color,
#[prop(optional)] lattice: bool,
#[prop(optional)] reverse_words: bool,
#[prop(optional)] shuffle_letters: bool,
#[prop(optional)] erase_top: f32,
#[prop(optional)] erase_bottom: f32,
#[prop(optional, into)] lattice: MaybeSignal<bool>,
#[prop(optional, into)] reverse_words: MaybeSignal<bool>,
#[prop(optional, into)] shuffle_letters: MaybeSignal<bool>,
#[prop(optional, into)] erase_top: MaybeSignal<f32>,
#[prop(optional, into)] erase_bottom: MaybeSignal<f32>,
#[prop(optional, into)] words_read: RwSignal<usize>,
#[prop(optional, into)] word_count: RwSignal<usize>,
#[prop(optional, into)] letters_read: RwSignal<usize>,
Expand Down Expand Up @@ -78,52 +78,77 @@ pub fn Text(
letters_total.set(letter_counters.iter().sum());
word_count.set(words.len());

let mut orig_words = words.clone();
if reverse_words {
orig_words.iter_mut().for_each(|word| {
*word = reverse_word(word);
});
}
if shuffle_letters {
orig_words.iter_mut().for_each(|word| {
*word = shuffle_word(word);
});
}
let get_word = move |i: usize, hidden: bool| {
let word: &String = words.get(i).unwrap();
if !hidden && reverse_words.get() {
reverse_word(word)
} else if !hidden && shuffle_letters.get() {
shuffle_word(word)
} else {
word.clone()
}
};

let word = |i, r: &Rect, hidden| {
view! {
<text
visibility=move || { (hidden && i >= words_read.get()).then_some("hidden") }
x=r.x + r.width / 2
y=r.y + r.height / 2
class:has-text-weight-bold=bold
text-anchor="middle"
dominant-baseline="central"
font-size=font_size
style=format!("font-family: {}", font)
fill=color
pointer-events="none"
>
{if hidden { &words[i] } else { &orig_words[i] }}
</text>
let word = {
|i, r: &Rect, hidden: bool| {
view! {
<text
visibility=move || { (hidden && i >= words_read.get()).then_some("hidden") }
x=r.x + r.width / 2
y=r.y + r.height / 2
class:has-text-weight-bold=bold
text-anchor="middle"
dominant-baseline="central"
font-size=font_size
style=format!("font-family: {}", font)
fill=color
pointer-events="none"
>
{move || get_word(i, hidden)}
</text>
}
}
};

let erase = |r: &Rect| {
let rx = r.x;
let ry = r.y;
let rh = r.height;
let rw = r.width;
view! {
{(erase_top > 0.0)
.then(|| {
let h = (erase_top * r.height as f32).round() as i32;
view! { <rect fill="white" x=r.x y=r.y width=r.width height=h></rect> }
})}

{(erase_bottom > 0.0)
.then(|| {
let h = (erase_bottom * r.height as f32).round() as i32;
view! {
<rect fill="white" x=r.x y=r.y + r.height - h width=r.width height=h></rect>
}
})}
{move || {
(erase_top.get() > 0.0)
.then(|| {
let h = (erase_top.get() * rh as f32).round() as i32;
view! {
<rect
fill="white"
pointer-events="none"
x=rx
y=ry
width=rw
height=h
></rect>
}
})
}}

{move || {
(erase_bottom.get() > 0.0)
.then(|| {
let h = (erase_bottom.get() * rh as f32).round() as i32;
view! {
<rect
fill="white"
pointer-events="none"
x=rx
y=ry + rh - h
width=rw
height=h
></rect>
}
})
}}
}
};

Expand Down Expand Up @@ -151,37 +176,39 @@ pub fn Text(
view! {
<g
style:opacity=move || if visible.get() { 1 } else { 0 }
style:visibility=move || { if visible.get() { "visible" } else { "hidden" } }
style:visibility=move || if visible.get() { "visible" } else { "hidden" }
style:transition=transition
>
<rect x=f.x y=f.y width=f.width height=f.height fill="white" on:click=on_click></rect>
{rects.iter().enumerate().map(|(i, r)| word(i, r, false)).collect_view()}
{(erase_top > 0.0 || erase_bottom > 0.0)
.then(|| { rects.iter().map(erase).collect_view() })}

{lattice
.then(|| {
let width = font_size / 2;
let dx = 5 * width;
let count = f.width / dx;
(0..count)
.map(|i| {
view! {
<rect
x=f.x + dx / 2 + i * dx
y=f.y
width=width
height=f.height
rx=width / 2
stroke=color
stroke-width="6"
fill="white"
pointer-events="none"
></rect>
}
})
.collect_view()
})}
{rects.iter().enumerate().map(|(i, r)| word.clone()(i, r, false)).collect_view()}
{rects.iter().map(erase).collect_view()}

{move || {
lattice
.get()
.then(|| {
let width = font_size / 2;
let dx = 5 * width;
let count = f.width / dx;
(0..count)
.map(|i| {
view! {
<rect
x=f.x + dx / 2 + i * dx
y=f.y
width=width
height=f.height
rx=width / 2
stroke=color
stroke-width="6"
fill="white"
pointer-events="none"
></rect>
}
})
.collect_view()
})
}}

{rects
.iter()
Expand All @@ -203,7 +230,7 @@ pub fn Text(
})
.collect_view()}

{rects.iter().enumerate().map(|(i, r)| word(i, r, true)).collect_view()}
{rects.iter().enumerate().map(|(i, r)| word.clone()(i, r, true)).collect_view()}
</g>
}
}
Expand Down

0 comments on commit f45093b

Please sign in to comment.