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