CocoaDev

Edit AllPages

Does anyone know how to make the rectangular selection box (commonly known as “the walking ants”)? Which Cocoa classes and methods might be helpful? I have a custom view in which I would like the user to be able to click and drag a rectangular selection box. – AlexanderD


I think it’s worth pointing out that Mac OS X seems to be moving away from marching ants. Finder, Sketch, iPhoto all use a simple rectangle to indicate selection. I would probably stick with that kind of approach myself.

I’m not sure what the question is here, so I’ll touch on a bunch of topics that will hopefully become the starting point of a more complete solution.

1) In order to have a selection box, you must have something to select. That is, something that contains a bunch of objects. This container is most likely an NSView. The objects you are selecting may themselves be NSViews, or they could be composited by NSCells by the containing view. For simplicity, let’s assume we have only one view; that view keeps track of the selectable items and draws them using NSCells.

2) You will need to track the click and drag event. This is commonly done in mouseDown: like so

// borrowed from the source to Sketch NSRect SKTRectFromPoints(NSPoint point1, NSPoint point2) { return NSMakeRect(((point1.x <= point2.x) ? point1.x : point2.x), ((point1.y <= point2.y) ? point1.y : point2.y), ((point1.x <= point2.x) ? point2.x - point1.x : point1.x - point2.x), ((point1.y <= point2.y) ? point2.y - point1.y : point1.y - point2.y)); }

3) You will need to draw the selection. Add that to your drawRect method.

4) Again, if you want the selection to march, you’ll need animation timers:

And that’s about it. You should be able to fill in the blanks yourself. Let us know how the animation thing works out, although again I suggest avoiding it altogether. Really, it looks cheesy when compared with the rest of the Aqua interface. See SketchApp for a concrete example of modern rubberbanding.

– MikeTrent

Mike,

Thank you so much, all this is very helpful. I guess you are right about the marching ants being retro, a good semi-transparent grey line should be sufficient. Anyway, it will take me a while to digest all this information. –AlexanderD


See also: SketchApp RubberBanding

Isn’t there a method in cocoa to do the selection? I have done a simple app where you can zoom in on a part of the picture by selecting, and I had to do the selection-rectangle myself, like the above example. Is there not a way to access the selection method of iPhoto, or the method of Screen Captures? – EnglaBenny (sorry for being anon!)

Dear anonymous. “Isn’t there a method in cocoa to do the selection?” No. I discuss this in point #1 above. There are many, many ways to design an application and Cocoa can’t anticipate all of them. But a selection is basically a rectangle (point #3) and a tracking loop (point #2), so I don’t think this is really a big deal. Heck, Cocoa even helps you with dashed-line offsets (point #4) … I’m not sure how this could be this any easier and still be useful for a wide variety of ProgrammingPatterns. “Is there not a way to access the selection method of iPhoto, or the method of Screen Captures?” Again, the idea of selection is application specific. That is, the very notion that you have something to select is specific to an application, so selection is also specific to that application. Therefore iPhoto and others all have their own selection logic embedded within themselves; there’s no (practical) way to “access” this.– MikeTrent

Perhaps anonymous was thinking of NSHighlightRect – AngelaBrett

I don’t know, therefore I ask – EnglaBenny/anonymous

Anonymous isn’t a problem. I just wanted to make the break between question and answer clear w/o using a line. – MikeTrent

I changed [mAntTimer invalidateTimer]; to [mAntTimer invalidate]; (typo i presume) and added one line to read

	[self setNeedsDisplayInRect: NSIntegralRect(mSelectionRect) ];	// erase previous
	mSelectionRect = getRectFromPoints(origPoint, curPoint);
	[self setNeedsDisplayInRect:mSelectionRect];

to eliminate strange shadowing of the marquee. PaulCD.

Thanks all, this was tremendously helpful. For a while, I had marching half-ants, the inner halves moved, the outer halves didn’t. The solution was to make a new rectangle, bigger than mSelectionRect by half of the path width on every side, and redisplay with handleAntAnimationTimer using this new rectangle. Robin Forder.