Today we'll look at last part of this tutorial (Part 4). These tutorials cover the basics of how to implement click-and-drag graphics selection and cropping, like you'll find in many popular applications (e.g.Photoshop, iPhoto, and the Finder). This week we'll add a lasso selection and offer live feedback.
The tutorial emulates a Cocoa project available from Apple. Go check out the original code and come back here ready for some REALbasic coding. NOTE: This demo is made with OS X in mind.
Augment the Interface
Launch REALbasic and open a copy of the last project. To the Window1 interface, add a checkbox labeled . Then, add another entry to PopupMenu2 property: Lasso. The result will look something like this (when tested with Debug-Run):
If you're following along from the last tutorial, you may have to resize the window a bit to accommodate the new checkbox. Now, let's move on to the code.
Add the Code
Double-click the Window Editor of Window1 to open the Code Editor. Choose Edit-New Property to add a property to the window: polyPoints(0) as integer. This array will store a list of points that will make up the outline of the lasso selection.
Next, change the code in the MouseDrag event of Canvas1 to read:
//Canvas1.MouseDrag
dim g as graphics
g=pictureSrc.graphics
if lastx<>x OR lasty<>y then
lastX = X
lastY = Y
g.foreColor=rgb(200,200,200)
g.drawpicture scenery,0,0
g.drawrect startX,startY,lastX-startX,lastY-startY
g=me.graphics
g.foreColor=rgb(200,200,200)
//don't do for lasso type (3)
'if popupMenu2.listindex<>3 then
g.drawpicture scenery,0,0
'end if
//plain style
select case popupMenu1.listindex
case 0
//red
g.foreColor = rgb(255,0,0)
case 1
//green
g.foreColor = rgb(0,255,0)
case 2
//blue
g.foreColor = rgb(0,0,255)
case 3
//grey
g.foreColor = rgb(200,200,200)
end select
select case popupMenu2.listindex
case 0
if startX
<lastX and startY<lastY then g.drawrect startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawrect lastX,lastY,startX-lastX,startY-lastY
elseif startX>lastX then
g.drawrect lastX,startY,startX-lastX,lastY-startY
elseif startY>lastY then
g.drawrect startX,lastY,lastX-startX,startY-lastY
end if
case 1
//Finder style
if startX
<lastX and startY<lastY then g.drawrect startX,startY,lastX-startX,lastY-startY g.drawpicture pictureMask,startX+1,startY+1,lastX-startX-1,lastY-startY-1 elseif startX>
lastX and startY>lastY then
g.drawrect lastX,lastY,startX-lastX,startY-lastY
g.drawpicture pictureMask,lastX+1,lastY+1,startX-lastX-1,startY-lastY-1
elseif startX>lastX then
g.drawrect lastX,startY,startX-lastX,lastY-startY
g.drawpicture pictureMask,lastX+1,startY+1,startX-lastX-1,lastY-startY-1
elseif startY>lastY then
g.drawrect startX,lastY,lastX-startX,startY-lastY
g.drawpicture pictureMask,startX+1,lastY+1,lastX-startX-1,startY-lastY-1
end if
case 2
//iPhoto style
if startX
<lastX and startY<lastY then g.drawrect startX,startY,lastX-startX,lastY-startY g.drawpicture pictureMask,0,0,me.width,me.height g.drawpicture scenery,startX+1,startY+1,lastX-startX-1,lastY-startY-1,startX+1,startY+1,lastX-startX-1,lastY-startY-1 'g.drawpicture scenery,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawrect lastX,lastY,startX-lastX,startY-lastY
g.drawpicture pictureMask,0,0,me.width,me.height
g.drawpicture scenery,lastX+1,lastY+1,startX-lastX-1,startY-lastY-1,lastX+1,lastY+1,startX-lastX-1,startY-lastY-1
elseif startX>lastX then
g.drawrect lastX,startY,startX-lastX,lastY-startY
g.drawpicture pictureMask,0,0,me.width,me.height
g.drawpicture scenery,lastX+1,startY+1,startX-lastX-1,lastY-startY-1,lastX+1,startY+1,startX-lastX-1,lastY-startY-1
elseif startY>lastY then
g.drawrect startX,lastY,lastX-startX,startY-lastY
g.drawpicture pictureMask,0,0,me.width,me.height
g.drawpicture scenery,startX+1,lastY+1,lastX-startX-1,startY-lastY-1,startX+1,lastY+1,lastX-startX-1,startY-lastY-1
end if
case 3
//lasso style
polyPoints.append lastX
polyPoints.append lastY
pictureMask.graphics.drawpicture scenery,0,0
pictureMask.mask.graphics.foreColor=rgb(255,255,255)
pictureMask.mask.graphics.fillrect 0,0,me.width,me.height
pictureMask.mask.graphics.foreColor=rgb(200,200,200)
pictureMask.mask.graphics.fillpolygon polyPoints
pictureMask.mask.graphics.foreColor=rgb(0,0,0)
pictureMask.mask.graphics.drawpolygon polyPoints
select case popupMenu1.listindex
case 0
//red
pictureMask.graphics.foreColor = rgb(255,0,0)
case 1
//green
pictureMask.graphics.foreColor = rgb(0,255,0)
case 2
//blue
pictureMask.graphics.foreColor = rgb(0,0,255)
case 3
//grey
pictureMask.graphics.foreColor = rgb(200,200,200)
end select
pictureMask.graphics.fillpolygon polyPoints
g.drawpicture pictureMask,0,0,me.width,me.height
g.foreColor=pictureMask.graphics.foreColor
g.drawpolygon polyPoints
end select
end if
AutoDraw
Then, navigate to the MouseUp event of Canvas1. Remove the code that you have there in favor of the new code. The code in the MouseDrag and MouseUp events closely matches earlier code with the addition of the lasso selection.
dim g,gg as graphics
g=pictureDest.graphics
gg=canvas2.graphics
g.clearrect 0,0,g.width,g.height
gg.forecolor=rgb(255,255,255)
gg.fillrect 0,0,g.width,g.height
if popupMenu2.listindex<>3 then
if startX
<lastX and startY<lastY then g.drawpicture scenery,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY gg.drawpicture scenery,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawpicture scenery,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
gg.drawpicture scenery,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
elseif startX>lastX then
g.drawpicture scenery,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
gg.drawpicture scenery,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
elseif startY>lastY then
g.drawpicture scenery,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
gg.drawpicture scenery,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
end if
else
//lasso style
if startX
<lastX and startY<lastY then g.drawpicture pictureMask,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY gg.drawpicture pictureMask,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawpicture pictureMask,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
gg.drawpicture pictureMask,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
elseif startX>lastX then
g.drawpicture pictureMask,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
gg.drawpicture pictureMask,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
elseif startY>lastY then
g.drawpicture pictureMask,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
gg.drawpicture pictureMask,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
end if
pictureDest = newpicture(canvas1.width,canvas1.height,32)
pictureDest.graphics.drawpicture scenery,0,0
pictureDest.mask.graphics.foreColor=rgb(255,255,255)
pictureDest.mask.graphics.fillrect 0,0,me.width,me.height
pictureDest.mask.graphics.foreColor=rgb(0,0,0)
pictureDest.mask.graphics.fillpolygon polyPoints
gg.drawpicture pictureDest,0,0,me.width,me.height
DrawMask//refresh
end if
Finally, create a new method named AutoDraw by choosing Edit-New Method. Navigate to this new AutoDraw method and add the following code. This method takes care of continuously updating the display when the new checkbox is selected.
dim g,gg as graphics
if checkBox1.value then
g=pictureDest.graphics
gg=canvas2.graphics
g.clearrect 0,0,g.width,g.height
gg.forecolor=rgb(255,255,255)
gg.fillrect 0,0,g.width,g.height
if popupMenu2.listindex<>3 then
if startX
<lastX and startY<lastY then g.drawpicture scenery,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY gg.drawpicture scenery,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawpicture scenery,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
gg.drawpicture scenery,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
elseif startX>lastX then
g.drawpicture scenery,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
gg.drawpicture scenery,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
elseif startY>lastY then
g.drawpicture scenery,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
gg.drawpicture scenery,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
end if
else
//lasso style
if startX
<lastX and startY<lastY then g.drawpicture pictureMask,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY gg.drawpicture pictureMask,startX,startY,lastX-startX,lastY-startY,startX,startY,lastX-startX,lastY-startY elseif startX>
lastX and startY>lastY then
g.drawpicture pictureMask,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
gg.drawpicture pictureMask,lastX,lastY,startX-lastX,startY-lastY,lastX,lastY,startX-lastX,startY-lastY
elseif startX>lastX then
g.drawpicture pictureMask,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
gg.drawpicture pictureMask,lastX,startY,startX-lastX,lastY-startY,lastX,startY,startX-lastX,lastY-startY
elseif startY>lastY then
g.drawpicture pictureMask,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
gg.drawpicture pictureMask,startX,lastY,lastX-startX,startY-lastY,startX,lastY,lastX-startX,startY-lastY
end if
pictureDest = newpicture(canvas1.width,canvas1.height,32)
pictureDest.graphics.drawpicture scenery,0,0
pictureDest.mask.graphics.foreColor=rgb(255,255,255)
pictureDest.mask.graphics.fillrect 0,0,me.width,me.height
pictureDest.mask.graphics.foreColor=rgb(0,0,0)
pictureDest.mask.graphics.fillpolygon polyPoints
gg.drawpicture pictureDest,0,0,me.width,me.height
'DrawMask//refresh
end if
end if
Select Debug-Run to test your work. Click and drag in the image on the left side of the window to view a cropped version on the right side. Select the new Lasso selection feature to see it in action.
Conclusion
You can download the completed project for this week here. That's it for this multi-part tutorial. Hopefully you learned a trick or two along the way. Next time we'll move on to a new topic. See you then!