|
-
Oct 6th, 2010, 03:45 PM
#1
Painting issue, when to draw/erase snap lines
Hi,
I have started to work some more on my 'shape editor'. If you're not familiar with it, just imagine the Visual Studio form designer: a 'canvas' (the form) with a bunch of 'shapes' (the controls) that can be selected, moved, resized, etc.
I have just finished implementing snapping between shapes and the canvas boundaries. But now I am having some slight issues with painting the snap lines.
Just FYI: this is what I mean by snap lines:

The blue lines that indicate that the 'buttons' are snapped to each other, and a purple line indicating that button1 is snapped to the boundary.
My shape editor is based loosely on jmcilhinney's 'manipulating GDI+ drawings' codebank entry, and a central idea in that post is to only draw what is necessary. In other words, when I move a shape I could re-draw the entire canvas, but it is much faster and smoother to only re-draw the old and the new location of the shape. Since nothing else has changed, I don't need to draw the rest. So, I simply invalidate the old bounds and the new bounds, and even with a lot of shapes all moving simultaneously it still feels very smooth.
My snaplines however provide a problem in this approach. I can determine when I need to draw a snap line of course, that is no problem. The problem is when to 'erase' them again.
In code, I simply hold a List(Of SnapLine), and in the Paint event I loop through that list and draw all the snap lines, if any. The list will usually be empty, unless I am snapping a control in which case a few snap lines will be present.
Now, in order to draw a snapline of course I need to invalidate a rectangle around that snapline. This is also not much of a problem. The problem is that, once I do not need to snap, then I do need to draw the entire canvas (once!) to clear all the snaplines. If I don't do this and only draw the shapes then the snaplines will persist until windows decides to repaint my form, which can take a long time.
So basically what I'm doing is this:
- In the MouseMove event of the Canvas, I move the selected shape (there can be multiple but let's assume a single selection).
- In the Move event of the shape, I call a SnapShape method.
- The SnapShape method loops through all other shapes and checks if it should snap to them, and to the boundary.
- If it should snap, it snaps, and one or more snaplines are added to the List(Of SnapLine).
- The parts of the Canvas that show the snaplines are invalidated and repainted.
This all sounds about right, yeah? Well it's not. What if in the previous 'iteration' I have snapped a shape, but now the user released the mouse and the shape is just sitting there. The snaplines should disappear! So I should at least invalidate the entire Canvas once.
I can do that of course, but the question I guess is: when?
I can determine when I need to draw the snaplines (when I snap the shape), but I cannot determine when not to draw it.
You might think something like this (the SnapShape method returns a boolean whether it snapped or not):
Code:
Private Sub Shape_Moved(ByVal sender As Object, ByVal e As EventArgs)
Dim shape = TryCast(sender, Shape)
Dim snapped = Me.SnapShape(shape)
If snapped Then
Me.Invalidate() ' draw the new snaplines
Else
'...?
Me.Invalidate() ' clear the old snaplines
End If
End Sub
See what I mean? I need to Invalidate the canvas in both cases: if it snapped I need to draw the lines, and if it didn't snap I need to erase them.
But this way I am invalidating the canvas EVERY TIME the shape moves! This defeats the entire purpose of invalidating only the regions that changed. Even though nothing changed except the shape location, I am still drawing the entire canvas including all other shapes, which haven't changed at all.
Does anyone know a clever way to handle this? I may be overlooking something obvious, but all I come up with is horribly complicated schemes that probably won't work anyway lol...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|