Blazor.Diagrams
Blazor.Diagrams copied to clipboard
User Actions Feature
Give the possibility for:
- The library users to define some actions the users can do
- The UI users to click on buttons that show on top of elements (nodes, links, ...) in order to trigger those actions
Examples of must-have actions:
- Delete the selected element
- Start dragging a new portless link
- Show the boundary of the selected element
Example in draw.io:
May I recommend that you adopt the command pattern (GoF). Command pattern - Wikipedia
Take for example the current DeleteSelectionBehavior
The behavior listens to the key down event for the associated key press, and the code to the action the delete is in the behavior’s keydown event
Now let’s say I want to add a menu option in my client UI to delete selected nodes. There is no way I can reuse the behavior’s Diagram_KeyDown event. It is private and takes a KeyboardEventArgs.
So, by separating the invokers (in this case the behavior) and creating another class for the command (the action of deletion), you would have something more flexible.
The DeleteSelectionBehavior accepts a command class in the constructor and if matches the delete key, calls the command’s execute method.
So, in my UI, I can now also call the delete command's execute method. In some future date, if you change the command to delete something else that derives from SelectableModel – I don’t need to make any changes in my code.
Now you could go a step further. The changed DeleteSelectionBehavior now just connects the keystroke and the command. It can renamed as keystrokeBehavior that accepts a keystroke and ideally an interface for a command, or perhaps, it refences a dictionary of keys/command interfaces for all the keystrokes. Keystrokes no longer need to be set in various options – it is part of the creating and registering the behaviors.
Now as a user, I can write my own commands and bind it to a keystroke using the supplied keystrokeBehavior class.
(As an aside, I would also let users supply the code to register behaviors – rather than have a set registered and the user unregister the ones they don’t like and register new ones. Less messy.)
Now, for example, a user could create their own DeleteCommand, derived from yours, and display a “do you want to delete” dialog, and still reference your underlying delete command.
A command interface, let’s call it ICommand, can also have other properties such as enable and an enabled changed action.
The Maui ICommand is defined thus:
public interface ICommand { public void Execute (Object parameter); public bool CanExecute (Object parameter); public event EventHandler CanExecuteChanged; }
See https://docs.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/commanding#icommands
(Just to clear, I am not suggesting you reference System.Windows.Input – just have a similar interface.)
This will be useful for the selection behaviour– when models are selected/deselected, a list of ICommands have their CanExecuteChanged events raised and the UI reacts accordingly. Thus if no models are selected, all the UI elements that require selected models are disabled.
Hello! I appreciate your opinion, thank you for taking the time to write that.
The command pattern does feel a little bit weird in the frontend, especially for UI actions that can be as complex as API calls and anything the library users want to do really. I don't want to use that pattern for this specific feature because it's not really needed, all actions are button clicks so a delegate or something will work just fine.
What I do like, however, is your generic shortcut behavior with the commands pattern. Something like this would be great to handle all shortcut use cases. This can easily let users assign commands to shortcuts.
The more I think about it, the more it does make sense to have commands as actions...