As part of my bachelors thesis, I’m trying to develop something akin to a painting program. That means, I have a toolset, be it selection, drawing, highlighting, etc.
I’ll have a canvas that displays my current model, based on a set of rectangles/spheres/polygons I have already drawn and created.
Some tools require the view to react differently based on the tools. Rough Examples:
I have a “New Line” tool. The view now displays points you can connect from when you hover over them.
I have a “Selection” tool. When I hover over an element, it’s entire color changes.
I have a “New Element” tool. When I move my mouse, a shadow of the element follows my cursor until I press the left mouse buttons.
Now, here’s where I’m a little stuck:
All these tools require wildly different behaviour from the view, and not only that, it also requires the view to be dynamic based on calculated properties. I got a few ideas how I could architect my system, but I would rather get nudged into a direction before I do a huge mistake. Here’s my questions and thoughts :
Q: First of all, where would I even put that interactive code? I can’t do it in XML, since it requires calculation, but putting it in the ViewModel is also not correct since the ViewModel is not supposed to know about the View. Thus, do I put it in the Code of the View itself? That also seems kinda strange to me.
Now to my architectural ideas:
Idea 1: I could do a new View + Viewmodel for each tool. When A new tool is selected, the view and viewmodel are simply exchanged in a frame, and all the behaviour is encapsulated inside the new view + ViewModel. However, that seems like it not only tightly couples each View and ViewModel together, it also feels like a lot of boilerplate code.
Idea 2: Each Tool itself has “Command” class based on a ICommand interface that requires a reference to the view as well as every possible option of User Interaction. Then the ViewModel delegates the UserInput onto the current Command, which can then manipulate the given ViewInstance to display things it wants. This however feels very inflexible, as if I’m just delegating the problem from Idea 1 somewhere else, and incapable of future growth. Whenever I want to add a new way for a user to interact, I’d have to go and adjust the interface, and perhaps all underlying commands if I didn’t provide a default implementation.
None of these really satisfy me, and I’m feeling like I’m missing a crucial step for this part of the architecture. I’d gladly appreciate any pointer. Thank you for your time and reading!