Refactored touch carets (de)init.
This commit is contained in:
parent
33be98e7db
commit
c643a38bd8
|
@ -99,7 +99,7 @@ impl Text {
|
|||
self.widget_builder().push_build_action(|wgt| {
|
||||
let child = nodes::render_text();
|
||||
let child = nodes::render_caret(child);
|
||||
let child = nodes::touch_caret(child);
|
||||
let child = nodes::touch_carets(child);
|
||||
let child = nodes::render_overlines(child);
|
||||
let child = nodes::render_strikethroughs(child);
|
||||
let child = nodes::render_underlines(child);
|
||||
|
|
|
@ -2013,7 +2013,7 @@ pub fn render_caret(child: impl UiNode) -> impl UiNode {
|
|||
/// An Ui node that renders the touch carets and implement interaction.
|
||||
///
|
||||
/// Caret visuals defined by [`CARET_TOUCH_SHAPE_VAR`].
|
||||
pub fn touch_caret(child: impl UiNode) -> impl UiNode {
|
||||
pub fn touch_carets(child: impl UiNode) -> impl UiNode {
|
||||
// is [child] or [child, SelectionLeft, SelectionRight] or [child, Insert]
|
||||
let children = vec![child.boxed()];
|
||||
|
||||
|
@ -2022,82 +2022,64 @@ pub fn touch_caret(child: impl UiNode) -> impl UiNode {
|
|||
match_node_list(children, move |c, op| match op {
|
||||
UiNodeOp::Init => {
|
||||
WIDGET.sub_var(&CARET_TOUCH_SHAPE_VAR);
|
||||
let r_txt = ResolvedText::get();
|
||||
|
||||
let caret = r_txt.caret.lock();
|
||||
if caret.index.is_some() {
|
||||
let children = c.children();
|
||||
|
||||
let s = CARET_TOUCH_SHAPE_VAR.get();
|
||||
if caret.selection_index.is_some() {
|
||||
children.push(s(CaretShape::SelectionLeft));
|
||||
children.push(s(CaretShape::SelectionRight));
|
||||
} else {
|
||||
children.push(s(CaretShape::Insert));
|
||||
}
|
||||
}
|
||||
}
|
||||
UiNodeOp::Deinit => {
|
||||
c.deinit_all();
|
||||
c.children().truncate(1);
|
||||
}
|
||||
UiNodeOp::Update { updates } => {
|
||||
let r_txt = ResolvedText::get();
|
||||
|
||||
let caret = r_txt.caret.lock();
|
||||
if caret.index.is_some() {
|
||||
if caret.selection_index.is_some() {
|
||||
let children = c.children();
|
||||
if children.len() != 3 {
|
||||
if children.len() == 2 {
|
||||
children.remove(1).deinit();
|
||||
}
|
||||
|
||||
let s = CARET_TOUCH_SHAPE_VAR.get();
|
||||
children.push(s(CaretShape::SelectionLeft));
|
||||
children.push(s(CaretShape::SelectionRight));
|
||||
}
|
||||
} // !!: Improve this, and add else case
|
||||
}
|
||||
|
||||
if let Some(s) = CARET_TOUCH_SHAPE_VAR.get_new() {
|
||||
let children = c.children();
|
||||
|
||||
if children.len() >= 2 {
|
||||
children[1].deinit();
|
||||
|
||||
if children.len() == 2 {
|
||||
children[1] = s(CaretShape::Insert);
|
||||
} else {
|
||||
debug_assert_eq!(children.len(), 3);
|
||||
|
||||
children[2].deinit();
|
||||
|
||||
children[1] = s(CaretShape::SelectionLeft);
|
||||
children[2] = s(CaretShape::SelectionRight);
|
||||
|
||||
children[2].init();
|
||||
}
|
||||
|
||||
children[1].init();
|
||||
|
||||
WIDGET.layout().render();
|
||||
children[0].update(updates);
|
||||
|
||||
c.delegated();
|
||||
UiNodeOp::Update { .. } => {
|
||||
if CARET_TOUCH_SHAPE_VAR.is_new() {
|
||||
for caret in &mut c.children()[1..] {
|
||||
caret.deinit();
|
||||
}
|
||||
c.children().truncate(1);
|
||||
|
||||
WIDGET.layout();
|
||||
}
|
||||
}
|
||||
UiNodeOp::Layout { wl, final_size } => {
|
||||
let children = c.children();
|
||||
let r_txt = ResolvedText::get();
|
||||
c.delegated();
|
||||
|
||||
let children = c.children();
|
||||
*final_size = children[0].layout(wl);
|
||||
|
||||
let caret = r_txt.caret.lock();
|
||||
let mut expected_len = 1; // 1 child
|
||||
if caret.index.is_some() && FOCUS.focused().with(|p| matches!(p, Some(p) if p.widget_id() == WIDGET.id())) {
|
||||
if caret.selection_index.is_some() {
|
||||
expected_len = 3;
|
||||
} else {
|
||||
expected_len = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if expected_len != children.len() {
|
||||
// children.len changed OR caret shape changed
|
||||
|
||||
for caret in &mut children[1..] {
|
||||
caret.deinit();
|
||||
}
|
||||
children.truncate(1);
|
||||
|
||||
let shape = CARET_TOUCH_SHAPE_VAR.get();
|
||||
if expected_len == 2 {
|
||||
children.push(shape(CaretShape::Insert));
|
||||
} else if expected_len == 3 {
|
||||
children.push(shape(CaretShape::SelectionLeft));
|
||||
children.push(shape(CaretShape::SelectionRight));
|
||||
}
|
||||
|
||||
for caret in &mut children[1..] {
|
||||
caret.init();
|
||||
}
|
||||
|
||||
WIDGET.render();
|
||||
}
|
||||
|
||||
for (caret, size) in children[1..].iter_mut().zip(&mut sizes) {
|
||||
*size = caret.layout(wl);
|
||||
}
|
||||
|
||||
c.delegated();
|
||||
}
|
||||
UiNodeOp::Render { frame } => {
|
||||
let _ = frame;
|
||||
|
|
|
@ -1152,7 +1152,7 @@ pub fn caret_color(child: impl UiNode, color: impl IntoVar<Rgba>) -> impl UiNode
|
|||
|
||||
/// Defines custom caret shapes for touch caret.
|
||||
///
|
||||
/// The `caret` node is not interactive, interaction is implemented by [`nodes::touch_caret`], it must
|
||||
/// The `caret` node is not interactive, interaction is implemented by [`nodes::touch_carets`], it must
|
||||
/// render the visual and layout to the size of the interaction area.
|
||||
///
|
||||
/// The caret is aligned depending on the shape, `CaretShape::SelectionLeft` aligns the top-right of the shape
|
||||
|
@ -1160,7 +1160,7 @@ pub fn caret_color(child: impl UiNode, color: impl IntoVar<Rgba>) -> impl UiNode
|
|||
/// of the shape to the top-right of the last line selection rectangle, `CaretShape::Insert` aligns the top-center
|
||||
/// of the shape with the insert position.
|
||||
///
|
||||
/// [`nodes::touch_caret`]: super::nodes::touch_caret
|
||||
/// [`nodes::touch_carets`]: super::nodes::touch_carets
|
||||
#[property(CONTEXT, default(CARET_TOUCH_SHAPE_VAR), widget_impl(TextEditMix<P>))]
|
||||
pub fn caret_touch_shape(child: impl UiNode, shape: impl IntoVar<WidgetFn<CaretShape>>) -> impl UiNode {
|
||||
with_context_var(child, CARET_TOUCH_SHAPE_VAR, shape)
|
||||
|
|
Loading…
Reference in New Issue