Skip to content

Conversation

0lione
Copy link
Contributor

@0lione 0lione commented Mar 25, 2024

When pressing Esc while drawing a relationship caused an exception instead of cancelling the animation.

PR Type

What kind of change does this PR introduce?

  • Bug fix
  • Feature
  • Chore (refactoring, formatting, local variables, other cleanup)
  • Documentation content changes

What is the current behavior?

When the user presses Esc while connecting any 2 elements with a relationship the Pointer shortcut is invoked and nothing is done to handle the key pressed, so when we already have a relationship established and press Esc while disconnecting one of the handles nothing happens to the relationship and the handle continues to be red.

Issue Number: 2736 & 3154

What is the new behavior?

Now when we press Esc we invoke a handler that will check if the handle we were moving is connected or not, if it is not then we disconnect that handle and we unselect the connection, if it is connected or the selected object is not a connection we just unselect it. The key aspect is that this handle is called before we invoke the Pointer shortcut.

Does this PR introduce a breaking change?

  • Yes
  • No

When pressing Esc while drawing a relationship caused an exception
instead of cancelling the animation.
@github-actions github-actions bot added the python Pull requests that update Python code label Mar 25, 2024
@amolenaar
Copy link
Member

Hi @0lione,

Thanks a lot for this PR. At first glance it looks good. I need a bit of time for a more in-depth review.

Copy link
Member

@amolenaar amolenaar left a comment

Choose a reason for hiding this comment

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

This looks good.

Just a few comments regarding naming.

Maybe it's possible to create a separate Gtk.EventControllerKey in the item_tool() function (it should return a tuple of controllers then), so they can share a single state object (as is done here). Then there's no need to maintain that state on the presentation objects themselves.

But if you feel that complicates things, that's also fine.

@amolenaar
Copy link
Member

@0lione Can you run pre-commit on your changes? That should help you resolve the linting errors.

@0lione
Copy link
Contributor Author

0lione commented Mar 31, 2024

This looks good.

Just a few comments regarding naming.

Maybe it's possible to create a separate Gtk.EventControllerKey in the item_tool() function (it should return a tuple of controllers then), so they can share a single state object (as is done here). Then there's no need to maintain that state on the presentation objects themselves.

But if you feel that complicates things, that's also fine.

Could you elaborate on that? I'm not understanding what you want me to do.

@0lione 0lione requested a review from amolenaar April 1, 2024 23:39
@amolenaar
Copy link
Member

Sorry for the late reply.

What I meant was that it may be possible to keep the whole cancel logic in itemtool.py.

# gaphor/diagram/tools/itemtool.py

class DragState:
    def __init__(self):
        self.dragging = False


def item_tool(event_manager) -> tuple[Gtk.GestureDrag, Gtk.EventControllerKey]:
    state = DragState()
    gesture = _item_tool()
    gesture.connect_after("drag-begin", on_drag_begin, event_manager, state)
    gesture.connect_after("drag-update", on_drag_update)
    gesture.connect_after("drag-end", on_drag_end, state)

    key_ctrl = Gtk.EventControllerKey.new()
    key_ctrl.connect("key-pressed", key_pressed, event_manager, state)
    return gesture, key_ctrl

...

def key_pressed(ctrl, keyval, keycode, _state, event_manager, state):
    if state.dragging and keyval == Gdk.KEY_Escape:
        Transaction.mark_rollback()

(may need to make gaphor.transaction.Transaction.mark_rollback() a class method)

I think what it should do, is roll back the transaction. Then the handle should be nicely be reverted to its old position and everything should be as before the drag operation started.

@0lione

This comment was marked as outdated.

@0lione
Copy link
Contributor Author

0lione commented Apr 17, 2024

Okay I got it working using the transaction rollback but I had to do some changes to the transactional_tool function so the rollback could work. I also had to change the PlacementState because whenever we pressed any key while placing a connection the "drag-end" event was never called. Hope the modifications are satisfactory, if not feel free to provide feedback on what changes you'd like to see

@amolenaar
Copy link
Member

I've been playing with your PR a bit. This problem is a lot harder than I expected.
The problem is indeed, that when you press any key during a drag operation, the drag is cancelled and we end up with an inconsistent state, because our transactions are not properly closed. This causes errors during undo, for example.

I think you're on the right track, by adding a key-pressed handler to transactional_tool.

I've been fiddling a bit around with that. I found that if we cancel (reset) all transactions as soon as a key press is recorded, we can roll back the transaction and let the tools do their cleanup.

Due to limitations in the GitHub interface (I was not able to create a PR from this repo to yours), I created a PR here. I did not need the key-pressed handlers for item and placement tools anymore. I think we should give this some thorough testing, though.

@0lione can you review the changes I did in #3254, please?

@danyeaw danyeaw merged commit bb2272a into gaphor:main Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
python Pull requests that update Python code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ends are not detached in a relationship when cancelling out the animation Cancelling out of drawing a relationship causes an exception
3 participants