3

I'm working on drawing application and I want to provide grid with snap to grid functionality. I'm trying to find the right way how to do that (ideally some design pattern), but I'm quite confused about the right class which should be responsible for that.

I have editor class which has an active tool object. Editor is listening to all user actions (mouse click, mouse move and so on..) and passes them to the active tool object. Active tool object then handles those events and renders shape based on its state (first click activates the tool, then it listens to mouse move and draws preview of the shape and second click creates the shape in my model class).

I'm thinking about using the Intercepting Filter pattern - every event will go through filter first and the result will be passed to active tool then. I guess that could work for object creation, but what to do with move and resize actions? Those depend on actual object which is being moved/resized.

  • Forget about the design patterns for awhile, just think about math and information. – whatsisname Feb 24 '16 at 5:32
  • From math point of view it is pretty simple. You just round the coordinates to closest multiple of the grid size. – Klinki Feb 24 '16 at 8:34
1

As your mouse pointer moves across the grid, the UI framework should be sending events to your application that end up in the grid's view object, telling it where the pointer is.

What you need is an object that intercepts the event and passes a new or altered event to your grid object. It will inspect the mouse event, grab its coordinates, then calculate new coordinates that snap to a configurable grid. It generates a new event and substitutes it instead of the original one to the grid object. If the event type is not a mouse move event, then simply pass it through without modifying it.

Your grid class should contain logic to paint a small marker where it thinks the mouse is pointing, to indicate to the user where the mouse is snapping to.

Every UI framework is different, but the general idea of "event came in, I can consume it, modify/replace it, or ignore it" is a fairly common one. The semantics of how to achieve those actions certainly is different, so it is difficult to say for sure how it would be implemented.

One method that may work is to create an invisible GUI element that contains your grid and is the exact same dimensions. Most framework pass events from the top down by calculating the stack of elements that exist at a given point, starting at the parent level (e.g. window frame), moving through the middle (e.g. panels/panes/group elements) and ending at the child level (the individual GUI element that usually is the one using the event). You could have the grid's parent alter mouse events as they pass through.

By ignoring events that are not related to mouse movement you can allow move/resize events to pass through: being the grid's parent object, it should move and resize for free when its child performs those actions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.