Skip to content

Commit

Permalink
fix(text): 🐛 input crash caused by DynWidget
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Adoo committed Aug 8, 2023
1 parent b88d783 commit 8f5b422
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 74 deletions.
64 changes: 52 additions & 12 deletions core/src/events/pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,36 +179,35 @@ impl PointerListenerDeclarer {
}

pub fn on_x_times_tap(
mut self,
self,
(times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, false, handler);
self
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, false, handler)
}

pub fn on_x_times_tap_capture(
mut self,
self,
(times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, true, handler);
self
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, true, handler)
}

fn on_x_times_tap_impl(
&mut self,
mut self,
times: usize,
dur: Duration,
capture: bool,
handler: impl FnMut(&mut PointerEvent) + 'static,
) {
) -> Self {
self
.subject()
.filter_map(x_times_tap_map_filter(times, dur, capture))
.subscribe(handler);
self
}
}

impl PointerListener {
impl PointerListenerDeclarer2 {
pub fn on_double_tap(self, handler: impl FnMut(&mut PointerEvent) + 'static) -> Self {
self.on_x_times_tap((2, handler))
}
Expand All @@ -229,16 +228,57 @@ impl PointerListener {
self,
(times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, false, handler);
self
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, false, handler)
}

pub fn on_x_times_tap_capture(
self,
(times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static),
) -> Self {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, true, handler);
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, true, handler)
}

fn on_x_times_tap_impl(
mut self,
times: usize,
dur: Duration,
capture: bool,
handler: impl FnMut(&mut PointerEvent) + 'static,
) -> Self {
self
.subject()
.filter_map(x_times_tap_map_filter(times, dur, capture))
.subscribe(handler);
self
}
}

impl PointerListener {
pub fn on_double_tap(self, handler: impl FnMut(&mut PointerEvent) + 'static) {
self.on_x_times_tap((2, handler))
}

pub fn on_double_tap_capture(self, handler: impl FnMut(&mut PointerEvent) + 'static) {
self.on_x_times_tap_capture((2, handler))
}

pub fn on_triple_tap(self, handler: impl FnMut(&mut PointerEvent) + 'static) {
self.on_x_times_tap((3, handler))
}

pub fn on_triple_tap_capture(self, handler: impl FnMut(&mut PointerEvent) + 'static) {
self.on_x_times_tap_capture((3, handler))
}

pub fn on_x_times_tap(self, (times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static)) {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, false, handler);
}

pub fn on_x_times_tap_capture(
self,
(times, handler): (usize, impl FnMut(&mut PointerEvent) + 'static),
) {
self.on_x_times_tap_impl(times, MULTI_TAP_DURATION, true, handler);
}

fn on_x_times_tap_impl(
Expand Down
2 changes: 1 addition & 1 deletion widgets/src/input/selected_text.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::layout::{Container, Stack};
use ribir_core::prelude::*;

#[derive(Declare)]
#[derive(Declare, Declare2)]
pub(crate) struct SelectedText {
pub(crate) rects: Vec<Rect>,
}
Expand Down
84 changes: 31 additions & 53 deletions widgets/src/input/text_selectable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ pub struct TextSelectable {

impl ComposeChild for TextSelectable {
type Child = State<Text>;
fn compose_child(this: State<Self>, text: Self::Child) -> Widget {
let this = this.into_writable();
widget! {
states {
this: this.clone(),
text: text.into_readonly(),
}
Stack {
id: host,
fit: StackFit::Passthrough,
fn compose_child(mut this: State<Self>, mut text: Self::Child) -> Widget {
fn_widget! {
let mut host = @Stack { fit: StackFit::Passthrough };
let mut selected = @SelectedText {
visible: pipe!($host.has_focus()),
rects: pipe!($this.selected_rect()),
};

@$host {
on_pointer_move: move |e| {
let mut this = $this;
if let CaretState::Selecting(begin, _) = this.caret {
if e.point_type == PointerType::Mouse
&& e.mouse_buttons() == MouseButtons::PRIMARY {
Expand All @@ -36,19 +36,20 @@ impl ComposeChild for TextSelectable {
},
on_pointer_down: move |e| {
let position = e.position();
let cluster = this.helper.cluster_from_pos(position.x, position.y);
let cluster = $this.helper.cluster_from_pos(position.x, position.y);
let begin = if e.with_shift_key() {
match this.caret {
match $this.caret {
CaretState::Caret(begin) |
CaretState::Select(begin, _) |
CaretState::Selecting(begin, _) => begin,
}
} else {
cluster
};
this.caret = CaretState::Selecting(begin, cluster);
$this.caret = CaretState::Selecting(begin, cluster);
},
on_pointer_up: move |_| {
let mut this = $this;
if let CaretState::Selecting(begin, end) = this.caret {
this.caret = if begin == end {
CaretState::Caret(begin)
Expand All @@ -59,34 +60,19 @@ impl ComposeChild for TextSelectable {
},
on_double_tap: move |e| {
let position = e.position();
let cluster = this.helper.cluster_from_pos(position.x, position.y);
let rg = select_word(&text.text, cluster);
this.caret = CaretState::Select(rg.start, rg.end);
let cluster = $this.helper.cluster_from_pos(position.x, position.y);
let rg = select_word(&$text.text, cluster);
$this.caret = CaretState::Select(rg.start, rg.end);
},

on_key_down: move |event| key_handle(&mut this, &text.text, event),
SelectedText {
id: selected,
visible: host.has_focus(),
rects: vec![],
}
DynWidget {
dyns: text.clone(),
on_performed_layout: move |ctx| {
let bound = ctx.layout_clamp().expect("layout info must exit in performed_layout");
this.helper.glyphs = Some(text.text_layout(
AppCtx::typography_store(),
bound.max,
));
this.forget_modifies();
}
}
}
finally {
this.modifies()
.subscribe(move |_| {
selected.rects = this.selected_rect();
});
on_key_down: move |event| key_handle(&mut $this, &$text.text, event),
on_performed_layout: move |e: &mut LifecycleEvent| {
let mut this = $this;
let bound = e.layout_clamp().expect("layout info must exit in performed_layout");
this.helper.glyphs = Some($text.text_layout(bound.max));
this.forget_modifies();
},
@ { selected }
@ { text }
}
}
.into()
Expand All @@ -99,11 +85,7 @@ impl TextSelectable {
fn selected_rect(&self) -> Vec<Rect> { self.helper.selection(&self.caret.select_range()) }
}

fn key_handle(
this: &mut StatefulRef<TextSelectable>,
text: &CowArc<str>,
event: &mut KeyboardEvent,
) {
fn key_handle(this: &mut StateRef<TextSelectable>, text: &CowArc<str>, event: &mut KeyboardEvent) {
let mut deal = false;
if event.with_command_key() {
deal = deal_with_command(this, text, event);
Expand All @@ -115,7 +97,7 @@ fn key_handle(
}

fn deal_with_command(
this: &mut StatefulRef<TextSelectable>,
this: &mut StateRef<TextSelectable>,
text: &CowArc<str>,
event: &mut KeyboardEvent,
) -> bool {
Expand Down Expand Up @@ -143,21 +125,17 @@ fn is_move_by_word(event: &KeyboardEvent) -> bool {
return event.with_ctrl_key();
}

fn move_to_line_begin(this: &mut StatefulRef<TextSelectable>) {
fn move_to_line_begin(this: &mut StateRef<TextSelectable>) {
let (row, _) = this.helper.glyph_position(this.caret.offset());
this.caret = this.helper.cluster_from_glyph_position(row, 0).into();
}

fn move_to_line_end(this: &mut StatefulRef<TextSelectable>) {
fn move_to_line_end(this: &mut StateRef<TextSelectable>) {
let (row, _) = this.helper.glyph_position(this.caret.offset());
this.caret = this.helper.cluster_from_glyph_position(row + 1, 0).into();
}

fn deal_with_selection(
this: &mut StatefulRef<TextSelectable>,
text: &str,
event: &mut KeyboardEvent,
) {
fn deal_with_selection(this: &mut StateRef<TextSelectable>, text: &str, event: &mut KeyboardEvent) {
let old_caret = this.caret;
match event.key {
VirtualKeyCode::Left => {
Expand Down
11 changes: 3 additions & 8 deletions widgets/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct Text {
}

impl Text {
pub fn text_layout(&self, t_store: &TypographyStore, bound: Size) -> VisualGlyphs {
pub fn text_layout(&self, bound: Size) -> VisualGlyphs {
let TextStyle {
font_size,
letter_space,
Expand All @@ -35,8 +35,7 @@ impl Text {

let width: Em = Pixel(bound.width.into()).into();
let height: Em = Pixel(bound.height.into()).into();

t_store.typography(
AppCtx::typography_store().typography(
self.text.substr(..),
font_size,
font_face,
Expand All @@ -54,11 +53,7 @@ impl Text {

impl Render for Text {
fn perform_layout(&self, clamp: BoxClamp, _: &mut LayoutCtx) -> Size {
self
.text_layout(AppCtx::typography_store(), clamp.max)
.visual_rect()
.size
.cast_unit()
self.text_layout(clamp.max).visual_rect().size.cast_unit()
}

#[inline]
Expand Down

0 comments on commit 8f5b422

Please sign in to comment.