[comp.sys.next] Creating a customview

u-sgreen%peruvian.utah.edu@cs.utah.edu (Scott Greenman) (03/13/91)

Could some kind soul out there in netter-netter land please give me some tips
on how to get started creating a custom view.  All that I want it to do is
to display the contents of a tiff file.  The view will be the docview of a
scrollview.  I have been programming my NeXT for several months now but
everything I've done up to this point has been with the objects supplied.

If there are any simple examples that would point me in the right direction,
they would also be much appreciated.  I've tried to look at the Draw source,
but soon get over my head.

Thanks for any help

Scott Greenman
Univ of Utah

aozer@next.com (Ali Ozer) (03/13/91)

In article <1991Mar12.125312.1336@hellgate.utah.edu> Scott Greenman writes:
>Could some kind soul out there in netter-netter land please give me some tips
>on how to get started creating a custom view.  All that I want it to do is
>to display the contents of a tiff file.  The view will be the docview of a
>scrollview.

When you scroll, the ScrollView displays the exposed areas by sending
drawSelf:: to its docview. A view properly written to display itself in its
drawSelf:: method will work just fine as a docview. Thus all you need is
a view which can display a TIFF file in its drawSelf::.

Typically you want scrolling to be fast; thus you would want 
the drawSelf:: method to display the TIFF file without having to reread it or 
reimage it. One way to do that would be to read the TIFF file and cache it 
then then display the requested portions in the drawSelf:: method. 
A possible implementation would be the CachedImageView class, shown below:


// .h file
#import <appkit/View.h>
@interface CachedImageView : View {
    id image;
}
- setImageFile:(const char *)fileName;
- drawSelf:(NXRect *)rects :(int)rectCount
- free;
@end


// .m file
#import "CachedImageView.h"
#import <appkit/NXImage.h>
#import <appkit/TextField.h>
#import <appkit/color.h>

@implementation CachedImageView

- setImageFile:(const char *)fileName
{
    [image free];       // Free the previous image (msg to nil obj is noop)
    image = [[NXImage allocFromZone:[self zone]] initFromFile:fileName];
    [image setScalable:YES];
    [image setSize:&(bounds.size)];
    [self display];
    return self;
}

- drawSelf:(NXRect *)rects :(int)rectCount
{
    NXSetColor (NX_COLORWHITE);	// We fill with white and display the image
				// with sover so that images with transparency
				// look fine on all machines and on screen
				// windows don't get fat.
    NXRectFillList (rects, rectCount);
    if (rectCount == 3) {	// Use last two rectangles
        rects++;
        [image composite:NX_SOVER fromRect:rects toPoint:&(rects->origin)];
        rects++;
    }
    [image composite:NX_SOVER fromRect:rects toPoint:&(rects->origin)];
    return self;
}

- free
{
    [image free];
    return [super free];
}

// Just for easy testing; we can hook up a TextField to this view.

- takeStringValueFrom:sender
{
    [self setImageFile:[sender stringValue]];
    return self;
}

@end

Load this class into IB (as CachedImageView), drag out an instance of
custom view, change its class to CachedImageView, and then group it in
a ScrollView.  Then you can make the ScrollView smaller or your View larger
depending on what you need. For testing, you can connect a TextField to
the takeStringValueFrom: method. As written above, this class assumes the View
is a fixed size (the size you specified in IB), and that the image should
be scaled to fit it. What's left as an exercise to the reader is having the
view change its size depending on the size of the image (which it can obtain
through getSize:).

The above code will work with EPS files as well.

One other possible implementation, which might be more appropriate for a
view which doesn't need to scroll, might be to avoid caching but instead
image the file in drawSelf::.  You could then use an instance of
NXBitmapImageRep, and send it a draw (or drawIn:) whenever drawSelf:: is
called.  Thus drawSelf:: is much slower, but for a View which doesn't get
drawn often this might be better.

Ali, Ali_Ozer@NeXT.com