Re: Cocoa/Windows parallel dvlpmt
Re: Cocoa/Windows parallel dvlpmt
- Subject: Re: Cocoa/Windows parallel dvlpmt
- From: Allan Odgaard <email@hidden>
- Date: Tue, 3 Feb 2004 00:29:51 +0100
On 2. Feb 2004, at 18:19, Erez Anzel wrote:
I'm happy (and reassured), John, to hear of your positive experience
with STL and Cocoa. I use STL, mostly for collections (vectors,
specifically) within the C++ core of my app. [...]
STL is so much more than collections -- it's generic algorithms &
functors amongst others... :)
I'm not sure about efficiency: at what level should I draw the line
between Cocoa and STL? For instance, should my MVC model (containing
perhaps as many as 100,000 objects) use an STL vector for those
objects? Or should it keep an NSMutableArray for the Mac, and
something else for Windows?
As implied by my other post, storage should be opaque for most of your
stuff, i.e. you always deal with your objects as a range defined by two
iterators, wether these are NSArray or std::vector iterators should not
matter to the actual algorithm.
Although I'd say, since your model is probably the only thing which can
be platform independent, it should be an STL container (or at least a
container you have the source for, and which can be traversed via STL
conforming iterators).
If an STL vector, then how should I tell each object to draw itself in
the NSView subclass which I (currently) pass it?
There really are a dozen different ways to do that... if you write a
function like the one below to draw a single point:
void draw_point (MyPoint const& p)
{
...
}
You can get it called for each of your points in the model:
std::vector<MyPoint> v = ...;
std::for_each(beginof(points), endof(points), draw_point);
(I can have multiple views, each displaying all of the objects
simultaneously.) When my data changes, I typically iterate first
through the views; each view then tells the model to redraw its
objects, passing it the view so that the objects will know the drawing
scale etc.
This does not sound like MVC -- your model should not know about your
views, nor be able to draw anything!
But to extend on the above, you can write:
void draw_point (NSView* view, MyPoint const& p)
{
...
}
And to redraw all views:
foreach(it, beginof(views), endof(views))
{
[*it lockFocus];
std::for_each(beginof(points), endof(points),
std::bind1st(*it, std::ptr_fun(draw_point)));
[*it unlockFocus];
}
This will iterate over the views, for each of the views it will iterate
over all the points and call draw_point with the current view bound as
the first argument (this is standard STL functionality).
The niec thing here is, if you change the 'views' container to e.g.
contain MFCView (or whatever it is called) you only need to supply a:
void draw_point (MFCView* view, MyPoint const& p)
{
...
}
And this function can instead be used, the rest of the code stays
intact -- that is, the compiler will have two draw_point functions to
choose from, and since ptr_fun is a template function, there is no hint
about which to choose, but we can write a generic function like this:
template <typename _ViewIter, typename _PointIter>
void draw_points_in_views (_PointIter first_point, _PointIter
last_point,
_ViewIter first_view, _ViewIter last_view)
{
typedef typename std::iterator_traits<_ViewIter>::value_type
view_type;
for(; first_view != last_view; ++first_view)
std::for_each(first_point, last_point,
std::bind1st(*it, std::ptr_fun<view_type>(draw_point)));
}
Now we can call:
draw_points_in_views(beginof(points), endof(points),
beginof(views), endof(views));
And it will call draw_point(v, p) for each point in each view, and use
the version of the draw_point function which first argument has the
same type as the elements in the 'views'-container.
It may at first look a little frightening, but when one has adapted to
generic programming, it is hopefully less intimidating ;)
[...] The data object's drawMyself method can call platform-specific
scaling and drawing methods depending upon the platform (determined at
compile time).
You could try to consider a less OO based solution -- as you can see
from the code above, this does IMHO often lead to better separation of
concerns. I.e. instead of having an object method like drawMyself make
a decision about platform and select the proper code, you instead let
the compiler resolve this based on type.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.