Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rethink two-step caret movement #4341

Closed
scofalik opened this issue Apr 18, 2018 · 2 comments
Closed

Rethink two-step caret movement #4341

scofalik opened this issue Apr 18, 2018 · 2 comments
Labels
package:engine resolution:expired This issue was closed due to lack of feedback. status:discussion status:stale type:improvement This issue reports a possible enhancement of an existing feature.

Comments

@scofalik
Copy link
Contributor

This is a follow-up after the PR with improvements to two-step caret movement, which unfortunately left code complicated and a little hacked. I think that at this point we all agree that we need to return to this subject and maybe start from scratch. I am repasting my post from the PR ckeditor/ckeditor5-engine#1406.

Proposal

Personally, I think that we might be better dropping "override/restore" gravity as it brings a lot of complications. Dropping this solution and managing attributes directly through writer API may simplify this feature. Additionally, we will get rid of weird situations, where gravity overriding might do more than we'd like to, for example:

<$text linkHref="foo.html">foo{}</$text><$text bold="true">bar</$text>

If we override gravity to the ride, we start typing bold. Is it correct? Maybe - I am not saying it is not. But it is more mess and potential problems.

This feature seems like it shouldn't really be that difficult, though I guess that we made it too complicated by using wrong tool (gravity) to approach it.

Finally, even though we use selection gravity, we still use writer API to directly add or remove attributes from the selection anyway!

I have a feeling that there are just three things that should be taken into consideration:

  1. Does the selection has the attribute?
  2. Will the selection "leave the attribute"?
  3. Will the selection "enter the attribute"?

Which leads to those three scenarios:

  1. Has attribute + is leaving -> Remove the attribute, prevent caret move.
  2. Doesn't have attribute + is entering -> Add the attribute, prevent caret move.
  3. If approaching from the right side, remove the attribute when approaching the attribute (because the gravity is to the left). This, however, is tricky*.

How would it work for different cases?

Between attributes:

<$text attribute="1">fo{}o</$text><$text attribute="2">bar</$text>

-> not leaving or entering
<$text attribute="1">foo{}</$text><$text attribute="2">bar</$text>

-> has attribute + is leaving, remove attribute, prevent caret move
<$text attribute="1">foo</$text>{}<$text attribute="2">bar</$text>

-> does not have attribute + is entering, add attribute, prevent caret move
<$text attribute="1">foo</$text><$text attribute="2">{}bar</$text>

-> not leaving or entering
<$text attribute="1">foo</$text><$text attribute="2">b{}ar</$text>

<- not leaving or entering
<$text attribute="1">foo</$text><$text attribute="2">{}bar</$text>

<- has attribute + is leaving, remove attribute, prevent caret move
<$text attribute="1">foo</$text>{}<$text attribute="2">bar</$text>

<- does not have attribute + is entering, add attribute, prevent caret move
<$text attribute="1">foo{}</$text><$text attribute="2">bar</$text>

<- not leaving or entering
<$text attribute="1">fo{}o</$text><$text attribute="2">bar</$text>

Inside multiple attributes using 2SCM:
The trick is to handle each attribute separately and cancel handling if one of them was handled. So the keydown event should be stopped after 2SCM is used.

<$text a="1" b="2">fo{}o</$text>bar

-> not leaving or entering
<$text a="1" b="2">foo{}</$text>bar

-> has attribute a + is leaving, remove attribute, prevent caret move
<$text a="1" b="2">foo</$text><$text b="2">{}</$text>bar

-> has attribute b + is leaving, remove attribute, prevent caret move
<$text a="1" b="2">foo</$text>{}bar

-> not leaving or entering
<$text a="1" b="2">foo</$text>b{}ar

The beginning of an element:

<paragraph><$text a="1">f{}oo</$text></paragraph>

<- not leaving or entering
<paragraph><$text a="1">{}foo</$text></paragraph>

<- has attribute + is leaving, remove attribute, prevent caret move
<paragraph>{}<$text a="1">foo</$text></paragraph>

The end of an element:

<paragraph><$text a="1">fo{}o</$text></paragraph>

-> not leaving or entering
<paragraph><$text a="1">foo{}</$text></paragraph>

-> has attribute + is leaving, remove attribute, prevent caret move
<paragraph><$text a="1">foo</$text>{}</paragraph>

Approaching from the right side:

<paragraph><$text a="1">foo</$text>b{}ar</paragraph>

<- approaching from the right side, remove attribute a, remove attribute b
<paragraph><$text a="1" b="2">foo</$text>{}bar</paragraph>

<- does not have attribute a + is entering, add attribute, prevent caret move
<paragraph><$text a="1" b="2">foo</$text><$text a="1">{}</$text>bar</paragraph>

<- does not have attribute b + is entering, add attribute, prevent caret move
<paragraph><$text a="1" b="2">foo{}</$text>bar</paragraph>

<- not leaving or entering
<paragraph><$text a="1" b="2">fo{}o</$text>bar</paragraph>

Other questions regarding the solution

How to check "is leaving" and "is entering"?

This seems easy. We already check if the selection is at attribute boundary so we would just add checking if a proper key was pressed.

Clearing attributes set by 2SCM?

There's a question about clearing attributes set by 2SCM. However, maybe we don't need to do anything?

When the selection is moved through API (keypress, mouse click, directChange == true) then the attributes are cleared anyway. This means that we don't need to care about additional clearing.

* - However this messes up our solution when the caret approaches element from the right because the attribute would be removed first and then selection would clear that. So for that case, we would need more additional handling. I believe it is doable, though.

When the selection is moved because of changes to the model tree (changes in background, collaboration, directChange == false) we don't want those changes to affect selection anyway. The only exception would be if the selection is "removed" or the attribute is removed/changed. This should be doable too.

What about gravity?

Now, as I am thinking about the solution I described, I got an idea. Maybe we could implement gravity managing as an additional separate feature. It would be much simpler. Basically, if a user clicks left arrow key, gravity is set to right, and when a user clicks right arrow key, gravity is set to right.

This would cover two things:

  1. We would not have the described problem in "approach from the right side" scenario.
  2. We (maybe) would give users a better UX for attributes for which we don't want a 2SCM.

How would it work?

fo{}o<$text bold="true">bold</$text>bar

-> keep gravity to the left
foo{}<$text bold="true">bold</$text>bar

-> keep gravity to the left
foo<$text bold="true">b{}old</$text>bar

<- keep gravity to the right
foo<$text bold="true">{}bold</$text>bar

<- keep gravity to the right
fo{}o<$text bold="true">bold</$text>bar

The gravity would be also reset on change:range with directChange set to true.

This is just an idea, I didn't think it through and I didn't think what problems it may bring. Also what problems it may bring in conjunction with 2SCM (although it would fix one issue :)).

@mlewand mlewand transferred this issue from ckeditor/ckeditor5-engine Oct 9, 2019
@mlewand mlewand added this to the backlog milestone Oct 9, 2019
@mlewand mlewand added status:discussion type:improvement This issue reports a possible enhancement of an existing feature. package:engine labels Oct 9, 2019
@pomek pomek removed this from the backlog milestone Feb 21, 2022
@CKEditorBot
Copy link
Collaborator

There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may be relevant, so if you're interested in the solution, leave a comment or reaction under this issue.

@CKEditorBot
Copy link
Collaborator

We've closed your issue due to inactivity over the last year. We understand that the issue may still be relevant. If so, feel free to open a new one (and link this issue to it).

@CKEditorBot CKEditorBot added the resolution:expired This issue was closed due to lack of feedback. label Nov 2, 2023
@CKEditorBot CKEditorBot closed this as not planned Won't fix, can't repro, duplicate, stale Nov 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package:engine resolution:expired This issue was closed due to lack of feedback. status:discussion status:stale type:improvement This issue reports a possible enhancement of an existing feature.
Projects
None yet
Development

No branches or pull requests

4 participants