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

Fix ctrl z textfield #11421

Merged
merged 17 commits into from
Jul 8, 2024
Merged

Fix ctrl z textfield #11421

merged 17 commits into from
Jul 8, 2024

Conversation

koppor
Copy link
Member

@koppor koppor commented Jun 24, 2024

Fixes #11420

However, this is a hard one. Do we need to implement undo/redo for textfields for ourselves?

Mandatory checks

  • Change in CHANGELOG.md described in a way that is understandable for the average user (if applicable)
  • Tests created for changes (if applicable)
  • Manually tested changed features in running JabRef (always required)
  • Screenshots added in PR description (for UI changes)
  • Checked developer's documentation: Is the information available and up to date? If not, I outlined it in this pull request.
  • Checked documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request to the documentation repository.

@Siedlerchr
Copy link
Member

This was working until recently. I wonder what happend to it.

I would suggest adding a text field to the reproducer and try it out

@Siedlerchr
Copy link
Member

Siedlerchr commented Jul 7, 2024

ctrl + y still produces exception when I play around with multiple crtl+z and ctrl+y in comment field

javax.swing.undo.CannotRedoException
	at java.desktop/javax.swing.undo.UndoManager.tryUndoOrRedo(UndoManager.java:469)
	at java.desktop/javax.swing.undo.UndoManager.redo(UndoManager.java:453)
	at [email protected]/org.jabref.gui.undo.CountingUndoManager.redo(CountingUndoManager.java:37)
	at [email protected]/org.jabref.gui.undo.RedoAction.execute(RedoAction.java:21)
	at [email protected]/org.jabref.gui.actions.JabRefAction.lambda$new$1(JabRefAction.java:25)
	at [email protected]/org.controlsfx.control.action.Action.handle(Action.java:423)
	at [email protected]/org.controlsfx.control.action.Action.handle(Action.java:64)
	at [email protected]/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at [email protected]/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at [email protected]/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at [email protected]/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at [email protected]/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at [email protected]/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at [email protected]/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at [email protected]/javafx.event.Event.fireEvent(Event.java:198)
	at [email protected]/javafx.scene.control.MenuItem.fire(MenuItem.java:459)
	at [email protected]/com.sun.javafx.scene.control.GlobalMenuAdapter.lambda$bindMenuItemProperties$2(GlobalMenuAdapter.java:150)
	at [email protected]/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at [email protected]/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at [email protected]/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at [email protected]/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at [email protected]/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at [email protected]/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at [email protected]/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at [email protected]/javafx.event.Event.fireEvent(Event.java:198)
	at [email protected]/javafx.scene.control.MenuItem.fire(MenuItem.java:459)
	at [email protected]/com.sun.javafx.tk.quantum.GlassSystemMenu$1.action(GlassSystemMenu.java:237)

@koppor
Copy link
Member Author

koppor commented Jul 7, 2024

ctrl + y still produces exception when I play around with multiple crtl+z and ctrl+y in comment field

This is not the original issue. The original issue is an NPE. - I will look into that nevertheless.

Update: The thing triggered according to the exception is a menu item; not through the text field.

@koppor
Copy link
Member Author

koppor commented Jul 7, 2024

javax.swing.undo.CannotRedoException
at java.desktop/javax.swing.undo.UndoManager.tryUndoOrRedo(UndoManager.java:469)

Nice find! Was because of my OO refactoring. I did not copy the full branch for RedoAction. 😅

@koppor koppor changed the title WIP: Fix ctrl z textfield Fix ctrl z textfield Jul 7, 2024
@koppor koppor marked this pull request as ready for review July 7, 2024 15:06
@koppor
Copy link
Member Author

koppor commented Jul 7, 2024

Follow up:

  • Have menu items disabled if there is no undo / redo
  • Implement undo/redo for "Clear, Change Case, Normalize"

@calixtus
Copy link
Member

calixtus commented Jul 7, 2024

Please do not verschlimmbesser the undoredo stuff anymore. Small refactorings ok, but the whole concept of undo/redo has to be redone.

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

Please do not verschlimmbesser the undoredo stuff anymore. Small refactorings ok, but the whole concept of undo/redo has to be redone.

Aim for this PR: Get it working for users. Do as less changes as possible. Keep changes local. If new code is required, add clean code. Do not add hacky code. -- Therefore, I needed to make UndoRedoAction abstract and exchange the hacky if to real classes. (I don't find the name of the resolved anti pattern here)

@calixtus
Copy link
Member

calixtus commented Jul 8, 2024

You can probably remove the now abstract undoredo class anyway and make the undo and the redo class directly extend simplecommand.

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

You can probably remove the now abstract undoredo class anyway and make the undo and the redo class directly extend simplecommand.

Done in 765e643 (#11421). I think, this code duplication is OK...

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

  • Have menu items disabled if there is no undo / redo

Discussed with @calixtus: Very hard. -- I also tried it locally, but the dependency of tab -> undomanger -> canUndo drives me crazy. I was searching for Bindings.andThen. Chain of bindings. But I did not find any solution.

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

* Implement undo/redo for "Clear, Change Case, Normalize"

I checked in this branch. Works.

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

@LoayGhreeb I reply to your comment #11420 (comment) here to be able to track the progress w.r.t. to the code commits. (The commits and the comments are sorted by time in a pull request. Thus, one sees, whether a comment was made before a commit or after one).

Using the menu bar (Edit -> Undo) to undo changes works without any exceptions.

This is good 😅

Another issue, which may or may not be related, is that when updating a field using the context menu (Clear, Change Case, Normalize) and using Ctrl+Z to undo this change, nothing happens and no exception occurs.

I tested it with the latst commit here. Works.

However, when using "Protect Selection" from the context menu, this change is undoable but with the exception.

Works here without exception.

Maybe, you can re-check? 😅

@koppor koppor added this to the 5.14 milestone Jul 8, 2024
Copy link
Contributor

github-actions bot commented Jul 8, 2024

The build for this PR is no longer available. Please visit https://builds.jabref.org/main/ for the latest build.

@LoayGhreeb
Copy link
Collaborator

Maybe, you can re-check? 😅

I tried it, and it works without exceptions. However, can we do some checks before doing the undo/redo to see if the change is related to the focused field and selected entry or not?
Because now, if I add/remove an entry, pressing Ctrl + Z/Y in the text field will remove/restore the entry again.

@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

Maybe, you can re-check? 😅
I tried it, and it works without exceptions. However, can we do some checks before doing the undo/redo to see if the change is related to the focused field and selected entry or not?

Why? I was thinking that there should be one line of redo/undo changes and not some local textfield ones and some "global" ones not realted to the textfield ones?

I think, the behavior of the last release was that an undo of a text field (JavaFX behavior) was recorded as new change event in JabRef's global undo/redo. And then pressing undo from the menu lead to strange effects.

Now, there is only one global undo/redo chain. For sure, if one changes a text field, does somewhere else somethings, than goes back to the text field, types a letter, presses ctrl+Z twice, then the "somethings" are undone.

Because now, if I add/remove an entry, pressing Ctrl + Z/Y in the text field will remove/restore the entry again.

This is the effect of a single global undo/redo stack.

Alternatively, we could "jump" in the undo chain and search for the last action regarding the text field and undo/redo that. -- I would stay back from using JavaFX textfield's local undo/redo (put aside for now that there is an NPE and we are in the need of fix JavaFX again).

@Siedlerchr
Copy link
Member

I'm okay with the current approach.

Comment on lines -18 to -19
private final EventBus eventBus = new EventBus();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

@calixtus
Copy link
Member

calixtus commented Jul 8, 2024

This is the effect of a single global undo/redo stack.

Alternatively, we could "jump" in the undo chain and search for the last action regarding the text field and undo/redo that. -- I would stay back from using JavaFX textfield's local undo/redo (put aside for now that there is an NPE and we are in the need of fix JavaFX again).

This can be resolved maybe by making undo actions in an event stream mergeable. So related edits (like entering a character) can be merged to larger undoables und be undone and redone as a compund (like now)

@calixtus calixtus added this pull request to the merge queue Jul 8, 2024
Merged via the queue into main with commit 3ee825d Jul 8, 2024
22 checks passed
@calixtus calixtus deleted the fix-ctrl-z-textfield branch July 8, 2024 14:48
@koppor
Copy link
Member Author

koppor commented Jul 8, 2024

This is the effect of a single global undo/redo stack.

Alternatively, we could "jump" in the undo chain and search for the last action regarding the text field and undo/redo that. -- I would stay back from using JavaFX textfield's local undo/redo (put aside for now that there is an NPE and we are in the need of fix JavaFX again).

This can be resolved maybe by making undo actions in an event stream mergeable. So related edits (like entering a character) can be merged to larger undoables und be undone and redone as a compund (like now)

In addition, I meant:

  1. Type a in field F1.
  2. Type b in field F2.
  3. Type c in Field F1.
  4. Press Ctrl+Z twice in Field F1.

Loay expects F1 being empty.

Current behavior: F1 contains a and F2 contains nothing.

@calixtus
Copy link
Member

calixtus commented Jul 8, 2024

i see.
i would expect the current behaviour. if you are jumping between fields, then every change has its own compund.

@koppor
Copy link
Member Author

koppor commented Jul 11, 2024

OK, Loay is asking for "Objektbezogenes Undo". The text there does not fully explain how it works with hierarchical objects. It also does not link real-world examples (which makes it a "pattern candidate")

@koppor
Copy link
Member Author

koppor commented Jul 11, 2024

if you are jumping between fields, then every change has its own compund.

We need to craft this. As you outlined. - But maybe we should only append if it is the same operation: add / delete. Replace should be in a new thing.

Meaning:

  • (a, ab) + (ab, abc) ->(a, abc) // both changes were additions, merge second into first
  • (abcd, abcde) + (abcde, abcd) -> (abcd, abcde), (abcde, abcd) // different actions, keep both, no merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ctrl+Z (undo) not working any more
4 participants