mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-31 15:47:26 +00:00
Android: simplify the text input with SpannableStringBuilder
Also needed some change on the Text item to avoid sending ime callback for intermediate states
This commit is contained in:
parent
2b08de093a
commit
1fb162936e
2 changed files with 171 additions and 88 deletions
|
@ -7,11 +7,13 @@ import android.view.inputmethod.InputConnection;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.Selection;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.view.inputmethod.BaseInputConnection;
|
import android.view.inputmethod.BaseInputConnection;
|
||||||
import android.view.inputmethod.ExtractedText;
|
|
||||||
|
|
||||||
class SlintInputView extends View {
|
class SlintInputView extends View {
|
||||||
private String mText = "";
|
private String mText = "";
|
||||||
|
@ -20,11 +22,38 @@ class SlintInputView extends View {
|
||||||
private String mPreedit = "";
|
private String mPreedit = "";
|
||||||
private int mPreeditOffset;
|
private int mPreeditOffset;
|
||||||
private int mInputType = EditorInfo.TYPE_CLASS_TEXT;
|
private int mInputType = EditorInfo.TYPE_CLASS_TEXT;
|
||||||
|
private SpannableStringBuilder mEditable;
|
||||||
|
|
||||||
|
public class SlintEditable extends SpannableStringBuilder {
|
||||||
|
// private SlintInputView mInputView;
|
||||||
|
|
||||||
|
public SlintEditable() {
|
||||||
|
super(mText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpannableStringBuilder replace(int start, int end, CharSequence tb, int tbstart, int tbend) {
|
||||||
|
super.replace(start, end, tb, tbstart, tbend);
|
||||||
|
mText = toString();
|
||||||
|
mCursorPosition = Selection.getSelectionStart(this);
|
||||||
|
mAnchorPosition = Selection.getSelectionEnd(this);
|
||||||
|
SlintAndroidJavaHelper.updateText(mText, mCursorPosition, mAnchorPosition, "", mCursorPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpan(Object what, int start, int end, int flags) {
|
||||||
|
super.setSpan(what, start, end, flags);
|
||||||
|
mCursorPosition = Selection.getSelectionStart(this);
|
||||||
|
mAnchorPosition = Selection.getSelectionEnd(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SlintInputView(Context context) {
|
public SlintInputView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
|
mEditable = new SlintEditable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,73 +67,18 @@ class SlintInputView extends View {
|
||||||
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI;
|
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI;
|
||||||
outAttrs.initialSelStart = mCursorPosition;
|
outAttrs.initialSelStart = mCursorPosition;
|
||||||
outAttrs.initialSelEnd = mAnchorPosition;
|
outAttrs.initialSelEnd = mAnchorPosition;
|
||||||
return new BaseInputConnection(this, false) {
|
return new BaseInputConnection(this, true) {
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getTextBeforeCursor(int n, int flags) {
|
public Editable getEditable() {
|
||||||
return mText.substring(0, mCursorPosition);
|
return mEditable;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence getTextAfterCursor(int n, int flags) {
|
|
||||||
return mText.substring(mCursorPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence getSelectedText(int flags) {
|
|
||||||
if (mCursorPosition != mAnchorPosition) {
|
|
||||||
return mText.substring(mCursorPosition, mAnchorPosition);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
|
||||||
mText = new StringBuilder(mText).delete(mCursorPosition, mAnchorPosition).insert(mCursorPosition, text)
|
|
||||||
.toString();
|
|
||||||
mPreedit = "";
|
|
||||||
if (newCursorPosition > 0) {
|
|
||||||
mCursorPosition = mCursorPosition + text.length() + newCursorPosition - 1;
|
|
||||||
} else {
|
|
||||||
mCursorPosition = mCursorPosition + newCursorPosition;
|
|
||||||
}
|
|
||||||
mAnchorPosition = mCursorPosition;
|
|
||||||
SlintAndroidJavaHelper.updateText(mText, mCursorPosition, mAnchorPosition, mPreedit, mPreeditOffset);
|
|
||||||
// return super.commitText(text, newCursorPosition);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
|
||||||
mText = new StringBuilder(mText).delete(mCursorPosition - beforeLength, mAnchorPosition + afterLength)
|
|
||||||
.toString();
|
|
||||||
mCursorPosition = mCursorPosition - beforeLength;
|
|
||||||
mAnchorPosition = mCursorPosition;
|
|
||||||
SlintAndroidJavaHelper.updateText(mText, mCursorPosition, mAnchorPosition, mPreedit, mPreeditOffset);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
|
||||||
mPreedit = text.toString();
|
|
||||||
mPreeditOffset = newCursorPosition;
|
|
||||||
SlintAndroidJavaHelper.updateText(mText, mCursorPosition, mAnchorPosition, mPreedit, mPreeditOffset);
|
|
||||||
return super.setComposingText(text, newCursorPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setSelection(int start, int end) {
|
|
||||||
mCursorPosition = start;
|
|
||||||
mAnchorPosition = end;
|
|
||||||
SlintAndroidJavaHelper.updateText(mText, mCursorPosition, mAnchorPosition, mPreedit, mPreeditOffset);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text, int cursorPosition, int anchorPosition, String preedit, int preeditOffset,
|
public void setText(String text, int cursorPosition, int anchorPosition, String preedit, int preeditOffset,
|
||||||
int inputType) {
|
int inputType) {
|
||||||
boolean restart = mInputType != inputType || !mText.equals(text);
|
boolean restart = mInputType != inputType || !mText.equals(text) || mCursorPosition != cursorPosition
|
||||||
boolean update_selection = mCursorPosition != cursorPosition || mAnchorPosition != anchorPosition;
|
|| mAnchorPosition != anchorPosition;
|
||||||
mText = text;
|
mText = text;
|
||||||
mCursorPosition = cursorPosition;
|
mCursorPosition = cursorPosition;
|
||||||
mAnchorPosition = anchorPosition;
|
mAnchorPosition = anchorPosition;
|
||||||
|
@ -112,17 +86,12 @@ class SlintInputView extends View {
|
||||||
mPreeditOffset = preeditOffset;
|
mPreeditOffset = preeditOffset;
|
||||||
mInputType = inputType;
|
mInputType = inputType;
|
||||||
|
|
||||||
InputMethodManager imm = (InputMethodManager) this.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
if (restart) {
|
if (restart) {
|
||||||
|
mEditable = new SlintEditable();
|
||||||
|
Selection.setSelection(mEditable, cursorPosition, anchorPosition);
|
||||||
|
InputMethodManager imm = (InputMethodManager) this.getContext()
|
||||||
|
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
imm.restartInput(this);
|
imm.restartInput(this);
|
||||||
} else if (update_selection) {
|
|
||||||
ExtractedText extractedText = new ExtractedText();
|
|
||||||
extractedText.text = mText;
|
|
||||||
extractedText.startOffset = mPreeditOffset;
|
|
||||||
extractedText.selectionStart = mCursorPosition;
|
|
||||||
extractedText.selectionEnd = mAnchorPosition;
|
|
||||||
imm.updateExtractedText(this, 0, extractedText);
|
|
||||||
imm.updateSelection(this, cursorPosition, anchorPosition, cursorPosition, anchorPosition);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,13 @@ impl Item for TextInput {
|
||||||
self.ensure_focus_and_ime(window_adapter, self_rc);
|
self.ensure_focus_and_ime(window_adapter, self_rc);
|
||||||
|
|
||||||
match click_count % 3 {
|
match click_count % 3 {
|
||||||
0 => self.set_cursor_position(clicked_offset, true, window_adapter, self_rc),
|
0 => self.set_cursor_position(
|
||||||
|
clicked_offset,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
),
|
||||||
1 => self.select_word(window_adapter, self_rc),
|
1 => self.select_word(window_adapter, self_rc),
|
||||||
2 => self.select_paragraph(window_adapter, self_rc),
|
2 => self.select_paragraph(window_adapter, self_rc),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -388,7 +394,14 @@ impl Item for TextInput {
|
||||||
MouseEvent::Released { position, button: PointerEventButton::Middle, .. } => {
|
MouseEvent::Released { position, button: PointerEventButton::Middle, .. } => {
|
||||||
let clicked_offset = self.byte_offset_for_position(position, window_adapter) as i32;
|
let clicked_offset = self.byte_offset_for_position(position, window_adapter) as i32;
|
||||||
self.as_ref().anchor_position_byte_offset.set(clicked_offset);
|
self.as_ref().anchor_position_byte_offset.set(clicked_offset);
|
||||||
self.set_cursor_position(clicked_offset, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
clicked_offset,
|
||||||
|
true,
|
||||||
|
// We trigger the callbacks because paste_clipboard might not if there is no clipboard
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
self.paste_clipboard(window_adapter, self_rc, Clipboard::SelectionClipboard);
|
self.paste_clipboard(window_adapter, self_rc, Clipboard::SelectionClipboard);
|
||||||
}
|
}
|
||||||
MouseEvent::Exit => {
|
MouseEvent::Exit => {
|
||||||
|
@ -405,8 +418,17 @@ impl Item for TextInput {
|
||||||
if pressed > 0 {
|
if pressed > 0 {
|
||||||
let clicked_offset =
|
let clicked_offset =
|
||||||
self.byte_offset_for_position(position, window_adapter) as i32;
|
self.byte_offset_for_position(position, window_adapter) as i32;
|
||||||
|
self.set_cursor_position(
|
||||||
self.set_cursor_position(clicked_offset, true, window_adapter, self_rc);
|
clicked_offset,
|
||||||
|
true,
|
||||||
|
if (pressed - 1) % 3 == 0 {
|
||||||
|
TextChangeNotify::TriggerCallbacks
|
||||||
|
} else {
|
||||||
|
TextChangeNotify::SkipCallbacks
|
||||||
|
},
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
match (pressed - 1) % 3 {
|
match (pressed - 1) % 3 {
|
||||||
0 => (),
|
0 => (),
|
||||||
1 => self.select_word(window_adapter, self_rc),
|
1 => self.select_word(window_adapter, self_rc),
|
||||||
|
@ -439,6 +461,7 @@ impl Item for TextInput {
|
||||||
self,
|
self,
|
||||||
direction,
|
direction,
|
||||||
event.modifiers.into(),
|
event.modifiers.into(),
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
window_adapter,
|
window_adapter,
|
||||||
self_rc,
|
self_rc,
|
||||||
);
|
);
|
||||||
|
@ -581,7 +604,13 @@ impl Item for TextInput {
|
||||||
self.as_ref().text.set(text.into());
|
self.as_ref().text.set(text.into());
|
||||||
let new_cursor_pos = (insert_pos + event.text.len()) as i32;
|
let new_cursor_pos = (insert_pos + event.text.len()) as i32;
|
||||||
self.as_ref().anchor_position_byte_offset.set(new_cursor_pos);
|
self.as_ref().anchor_position_byte_offset.set(new_cursor_pos);
|
||||||
self.set_cursor_position(new_cursor_pos, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
new_cursor_pos,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
|
|
||||||
// Keep the cursor visible when inserting text. Blinking should only occur when
|
// Keep the cursor visible when inserting text. Blinking should only occur when
|
||||||
// nothing is entered or the cursor isn't moved.
|
// nothing is entered or the cursor isn't moved.
|
||||||
|
@ -600,11 +629,29 @@ impl Item for TextInput {
|
||||||
// Set the selection so the call to insert erases it
|
// Set the selection so the call to insert erases it
|
||||||
self.anchor_position_byte_offset.set(cursor.saturating_add(r.start));
|
self.anchor_position_byte_offset.set(cursor.saturating_add(r.start));
|
||||||
self.cursor_position_byte_offset.set(cursor.saturating_add(r.end));
|
self.cursor_position_byte_offset.set(cursor.saturating_add(r.end));
|
||||||
|
if event.text.is_empty() {
|
||||||
|
self.delete_selection(
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
if event.cursor_position.is_none() {
|
||||||
|
TextChangeNotify::TriggerCallbacks
|
||||||
|
} else {
|
||||||
|
// will be updated by the set_cursor_position later
|
||||||
|
TextChangeNotify::SkipCallbacks
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.insert(&event.text, window_adapter, self_rc);
|
self.insert(&event.text, window_adapter, self_rc);
|
||||||
if let Some(cursor) = event.cursor_position {
|
if let Some(cursor) = event.cursor_position {
|
||||||
self.anchor_position_byte_offset.set(event.anchor_position.unwrap_or(cursor));
|
self.anchor_position_byte_offset.set(event.anchor_position.unwrap_or(cursor));
|
||||||
self.set_cursor_position(cursor, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
cursor,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
KeyEventResult::EventAccepted
|
KeyEventResult::EventAccepted
|
||||||
}
|
}
|
||||||
|
@ -842,6 +889,7 @@ impl TextInput {
|
||||||
self: Pin<&Self>,
|
self: Pin<&Self>,
|
||||||
direction: TextCursorDirection,
|
direction: TextCursorDirection,
|
||||||
anchor_mode: AnchorMode,
|
anchor_mode: AnchorMode,
|
||||||
|
trigger_callbacks: TextChangeNotify,
|
||||||
window_adapter: &Rc<dyn WindowAdapter>,
|
window_adapter: &Rc<dyn WindowAdapter>,
|
||||||
self_rc: &ItemRc,
|
self_rc: &ItemRc,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -941,6 +989,7 @@ impl TextInput {
|
||||||
self.set_cursor_position(
|
self.set_cursor_position(
|
||||||
new_cursor_pos as i32,
|
new_cursor_pos as i32,
|
||||||
reset_preferred_x_pos,
|
reset_preferred_x_pos,
|
||||||
|
trigger_callbacks,
|
||||||
window_adapter,
|
window_adapter,
|
||||||
self_rc,
|
self_rc,
|
||||||
);
|
);
|
||||||
|
@ -956,6 +1005,7 @@ impl TextInput {
|
||||||
self: Pin<&Self>,
|
self: Pin<&Self>,
|
||||||
new_position: i32,
|
new_position: i32,
|
||||||
reset_preferred_x_pos: bool,
|
reset_preferred_x_pos: bool,
|
||||||
|
trigger_callbacks: TextChangeNotify,
|
||||||
window_adapter: &Rc<dyn WindowAdapter>,
|
window_adapter: &Rc<dyn WindowAdapter>,
|
||||||
self_rc: &ItemRc,
|
self_rc: &ItemRc,
|
||||||
) {
|
) {
|
||||||
|
@ -968,8 +1018,10 @@ impl TextInput {
|
||||||
if reset_preferred_x_pos {
|
if reset_preferred_x_pos {
|
||||||
self.preferred_x_pos.set(pos.x);
|
self.preferred_x_pos.set(pos.x);
|
||||||
}
|
}
|
||||||
Self::FIELD_OFFSETS.cursor_position_changed.apply_pin(self).call(&(pos,));
|
if trigger_callbacks == TextChangeNotify::TriggerCallbacks {
|
||||||
self.update_ime(window_adapter, self_rc);
|
Self::FIELD_OFFSETS.cursor_position_changed.apply_pin(self).call(&(pos,));
|
||||||
|
self.update_ime(window_adapter, self_rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +1043,13 @@ impl TextInput {
|
||||||
self_rc: &ItemRc,
|
self_rc: &ItemRc,
|
||||||
) {
|
) {
|
||||||
if !self.has_selection() {
|
if !self.has_selection() {
|
||||||
self.move_cursor(step, AnchorMode::KeepAnchor, window_adapter, self_rc);
|
self.move_cursor(
|
||||||
|
step,
|
||||||
|
AnchorMode::KeepAnchor,
|
||||||
|
TextChangeNotify::SkipCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.delete_selection(window_adapter, self_rc, TextChangeNotify::TriggerCallbacks);
|
self.delete_selection(window_adapter, self_rc, TextChangeNotify::TriggerCallbacks);
|
||||||
}
|
}
|
||||||
|
@ -1032,7 +1090,13 @@ impl TextInput {
|
||||||
});
|
});
|
||||||
|
|
||||||
if trigger_callbacks == TextChangeNotify::TriggerCallbacks {
|
if trigger_callbacks == TextChangeNotify::TriggerCallbacks {
|
||||||
self.set_cursor_position(anchor as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
anchor as i32,
|
||||||
|
true,
|
||||||
|
trigger_callbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
Self::FIELD_OFFSETS.edited.apply_pin(self).call(&());
|
Self::FIELD_OFFSETS.edited.apply_pin(self).call(&());
|
||||||
} else {
|
} else {
|
||||||
self.cursor_position_byte_offset.set(anchor as i32);
|
self.cursor_position_byte_offset.set(anchor as i32);
|
||||||
|
@ -1129,7 +1193,13 @@ impl TextInput {
|
||||||
let cursor_pos = cursor_pos + text_to_insert.len();
|
let cursor_pos = cursor_pos + text_to_insert.len();
|
||||||
self.text.set(text.into());
|
self.text.set(text.into());
|
||||||
self.anchor_position_byte_offset.set(cursor_pos as i32);
|
self.anchor_position_byte_offset.set(cursor_pos as i32);
|
||||||
self.set_cursor_position(cursor_pos as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
cursor_pos as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
Self::FIELD_OFFSETS.edited.apply_pin(self).call(&());
|
Self::FIELD_OFFSETS.edited.apply_pin(self).call(&());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,19 +1220,27 @@ impl TextInput {
|
||||||
let safe_end = safe_byte_offset(end, &text);
|
let safe_end = safe_byte_offset(end, &text);
|
||||||
|
|
||||||
self.as_ref().anchor_position_byte_offset.set(safe_start as i32);
|
self.as_ref().anchor_position_byte_offset.set(safe_start as i32);
|
||||||
self.set_cursor_position(safe_end as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
safe_end as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_all(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) {
|
pub fn select_all(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) {
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
TextCursorDirection::StartOfText,
|
TextCursorDirection::StartOfText,
|
||||||
AnchorMode::MoveAnchor,
|
AnchorMode::MoveAnchor,
|
||||||
|
TextChangeNotify::SkipCallbacks,
|
||||||
window_adapter,
|
window_adapter,
|
||||||
self_rc,
|
self_rc,
|
||||||
);
|
);
|
||||||
self.move_cursor(
|
self.move_cursor(
|
||||||
TextCursorDirection::EndOfText,
|
TextCursorDirection::EndOfText,
|
||||||
AnchorMode::KeepAnchor,
|
AnchorMode::KeepAnchor,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
window_adapter,
|
window_adapter,
|
||||||
self_rc,
|
self_rc,
|
||||||
);
|
);
|
||||||
|
@ -1182,7 +1260,13 @@ impl TextInput {
|
||||||
(next_word_boundary(&text, anchor), prev_word_boundary(&text, cursor))
|
(next_word_boundary(&text, anchor), prev_word_boundary(&text, cursor))
|
||||||
};
|
};
|
||||||
self.as_ref().anchor_position_byte_offset.set(new_a as i32);
|
self.as_ref().anchor_position_byte_offset.set(new_a as i32);
|
||||||
self.set_cursor_position(new_c as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
new_c as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_paragraph(
|
fn select_paragraph(
|
||||||
|
@ -1199,7 +1283,13 @@ impl TextInput {
|
||||||
(next_paragraph_boundary(&text, anchor), prev_paragraph_boundary(&text, cursor))
|
(next_paragraph_boundary(&text, anchor), prev_paragraph_boundary(&text, cursor))
|
||||||
};
|
};
|
||||||
self.as_ref().anchor_position_byte_offset.set(new_a as i32);
|
self.as_ref().anchor_position_byte_offset.set(new_a as i32);
|
||||||
self.set_cursor_position(new_c as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
new_c as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(self: Pin<&Self>, w: &Rc<dyn WindowAdapter>, _: &ItemRc) {
|
pub fn copy(self: Pin<&Self>, w: &Rc<dyn WindowAdapter>, _: &ItemRc) {
|
||||||
|
@ -1417,7 +1507,13 @@ impl TextInput {
|
||||||
self.text.set(text.into());
|
self.text.set(text.into());
|
||||||
|
|
||||||
self.anchor_position_byte_offset.set(last.anchor as i32);
|
self.anchor_position_byte_offset.set(last.anchor as i32);
|
||||||
self.set_cursor_position(last.cursor as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
last.cursor as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
UndoItemKind::TextRemove => {
|
UndoItemKind::TextRemove => {
|
||||||
let mut text: String = self.text().into();
|
let mut text: String = self.text().into();
|
||||||
|
@ -1425,7 +1521,13 @@ impl TextInput {
|
||||||
self.text.set(text.into());
|
self.text.set(text.into());
|
||||||
|
|
||||||
self.anchor_position_byte_offset.set(last.anchor as i32);
|
self.anchor_position_byte_offset.set(last.anchor as i32);
|
||||||
self.set_cursor_position(last.cursor as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
last.cursor as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.undo_items.set(items);
|
self.undo_items.set(items);
|
||||||
|
@ -1448,7 +1550,13 @@ impl TextInput {
|
||||||
self.text.set(text.into());
|
self.text.set(text.into());
|
||||||
|
|
||||||
self.anchor_position_byte_offset.set(last.anchor as i32);
|
self.anchor_position_byte_offset.set(last.anchor as i32);
|
||||||
self.set_cursor_position(last.cursor as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
last.cursor as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
UndoItemKind::TextRemove => {
|
UndoItemKind::TextRemove => {
|
||||||
let text: String = self.text().into();
|
let text: String = self.text().into();
|
||||||
|
@ -1457,7 +1565,13 @@ impl TextInput {
|
||||||
self.text.set(text.into());
|
self.text.set(text.into());
|
||||||
|
|
||||||
self.anchor_position_byte_offset.set(last.anchor as i32);
|
self.anchor_position_byte_offset.set(last.anchor as i32);
|
||||||
self.set_cursor_position(last.cursor as i32, true, window_adapter, self_rc);
|
self.set_cursor_position(
|
||||||
|
last.cursor as i32,
|
||||||
|
true,
|
||||||
|
TextChangeNotify::TriggerCallbacks,
|
||||||
|
window_adapter,
|
||||||
|
self_rc,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue