[Drawkit] Keeping objects sorted
Graham Cox
graham.cox at bigpond.com
Thu Jul 3 18:22:32 PDT 2008
The guide layer doesn't require sorted guides for what it was designed
to do, so you need to subclass it to keep the guides sorted. You can't
sort an NSArray because it's immutable, but if you're subclassing,
you'll notice that in fact the guide arrays are NSMutableArrays
internally, so they can indeed be sorted "in place". You just need to
use -sortUsingFunction:context: and write a short comparison function,
e.g:
static int cmpGuidePositions (DKGuide* lh, DKGuide* rh, void *context)
{
#pragma unused(context)
float lp = [lh position];
float rp = [rh position];
if (lp < rp)
return NSOrderedAscending;
else if (lp > rp)
return NSOrderedDescending;
else
return NSOrderedSame;
}
You can also sort drawables by position in a similar manner, either by
subclassing the layer on which they live, or just implementing an
external method in a suitable place. Bear in mind that the ordering of
objects in a layer is actually their z-position or stacking order, so
you would be forcing the x and z positions to be the same. You'd need
to grab the objects into a mutable copy, sort them, then put them back
(-setObjects:)
A much better alternative approach would be just to keep another list
of objects sorted by x position, and leave the normal stuff "as is".
Whenever you add an object to the layer, you'd also add it to your
sorted list, and vice versa on removal. Additional lists of objects
ordered in a different way is an efficient way to do things because a)
the objects themselves are not copied, just retained, and the sorting
of the additional list doesn't require any redrawing or other
potentially time-consuming side effects to be triggered - it's your
private list.
The drawback is making sure the lists are synchronised with respect to
the objects they contain. Since there are a number of ways that
objects can get added or removed from layers, a possible approach
would be just to make a new copy of the list of objects every time
that happened. The new notifications suggested by Linan Wang will ease
this operation in the next version, but it's still doable in beta3 by
various means. On balance I'd say subclassing DKObjectDrawingLayer is
probably the best option, so you can simply override the various add/
remove methods to manage your sorted array, then call super for the
normal stuff. The subclass would also own the sorted list so you can
declare methods to simply get the sorted objects or even -
objectNearestToTime: type stuff.
hth,
cheers, Graham
On 4 Jul 2008, at 4:06 am, James Maxwell wrote:
> Hi All,
>
> In my particular app, it would be really helpful if I could keep
> drawn objects sorted by x position.
> Does anyone know a simple and straightforward way of doing that? For
> example, I want my vertical guides to always be sorted by -
> position:, so I can efficiently get the closest guide "before" or
> "after" a particular object (this is a music app, so time runs left
> to right). I also want to do this with my main drawing layer's
> objects - keeping them ordered by x position (i.e., time). Is there
> no simple way to sort an array, like m_vGuides, for example, "in-
> place", without making a new sorted array and assigning it?
More information about the Drawkit
mailing list