1// pgviewobj.m is the custom view object for the pgview program. PGView 2// receives 132 byte character arrays filled with PostScript code. PGView 3// saves these buffers in a Storage object. When the PGPLOT program 4// executes a flushpg operation, this stored data is then sent to the 5// display. 6// 7// 1999-Feb-20 - Update for OpenStep - [AFT] 8// 1992-Mar-09 - [AFT] 9//--- 10#import "pgviewobj.h" 11 12@implementation pgviewobj 13 14- initWithFrame:(NSRect)frameRect 15{ 16 [super initWithFrame:frameRect]; 17 18// Create an enclosing window and bring it upfront 19 myWindow = [[NSWindow alloc] initWithContentRect:frameRect 20 styleMask:NSResizableWindowMask| 21 (NSMiniaturizableWindowMask | NSClosableWindowMask) 22 backing:NSBackingStoreBuffered 23 defer:NO]; 24 [myWindow setContentView:self]; 25 [myWindow setBackgroundColor:[NSColor whiteColor]]; 26 [myWindow setReleasedWhenClosed:YES]; 27 [myWindow setTitle:@"PGPLOT Viewer"]; 28 [myWindow display]; 29 [myWindow orderFront:self]; 30 31// Save portrait/landscape flag 32 if( frameRect.size.width > frameRect.size.height) { 33 lwtype=0; 34 } else { 35 lwtype=1; 36 } 37 38// Needed to do PostScript scaling 39 [self scaleUnitSquareToSize:NSMakeSize(0.1, 0.1)]; 40 prevw = [self bounds].size.width; 41 prevh = [self bounds].size.height; 42 43// PostScript data sent from PGPLOT will be stored in psdata. 44 psdata = [Storage newCount:0 45 elementSize:132 46 description:"[132c]"]; 47 nplot=0; 48 49// Allocate private graphics state, so things like the current color 50// setting will be preserved between different calls to drawSelf. 51 [self allocateGState]; 52 53 return self; 54} 55 56- (void)drawRect:(NSRect)rect 57{ 58 DPSContext ctxt; 59 NSRect bounds; 60 int i; 61 62 if ( nplot > 0) { 63 bounds=[self bounds]; 64 if( prevw != bounds.size.width || prevh != bounds.size.height) { 65 [self scaleUnitSquareToSize:NSMakeSize(bounds.size.width/prevw, 66 bounds.size.height/prevh)]; 67 prevw = bounds.size.width; 68 prevh = bounds.size.height; 69 } 70 71 ctxt= DPSGetCurrentContext(); 72 for(i=0; i<nplot; i++) { 73 DPSPrintf(ctxt, "%s\n", (char *) [psdata elementAt:i]); 74 } 75 } 76 return; 77} 78 79- (void)dealloc 80{ 81printf("in dealloc\n"); 82 [psdata free]; 83 [super dealloc]; 84 return; 85} 86 87- (void)endPrologue 88// This routine sends the PGPLOT defines to the print job. 89{ 90 DPSContext ctxt; 91 92 ctxt= DPSGetCurrentContext(); 93 [self pgplotDefs:ctxt]; 94 [super endPrologue]; 95 return; 96} 97 98- (void) pgplotDefs: (DPSContext) ctxt 99{ 100 DPSPrintf(ctxt, 101 "/l {moveto rlineto currentpoint stroke moveto} bind def\n"); 102 DPSPrintf(ctxt, 103 "/c {rlineto currentpoint stroke moveto} bind def\n"); 104 DPSPrintf(ctxt, 105 "/d {moveto 0 0 rlineto currentpoint stroke moveto} bind def\n"); 106 DPSPrintf(ctxt,"/SLW {5 mul setlinewidth} bind def\n"); 107 DPSPrintf(ctxt,"/BP {newpath moveto} bind def\n"); 108 DPSPrintf(ctxt,"/LP /rlineto load def\n"); 109 DPSPrintf(ctxt,"/EP {rlineto closepath eofill} bind def\n"); 110 return; 111} 112 113- (void) beginp 114{ 115 DPSContext ctxt; 116 117 if([NSApp isHidden]) { 118 [NSApp unhideWithoutActivation]; 119 } 120 [myWindow setDocumentEdited:YES]; 121 [self lockFocus]; 122 ctxt= DPSGetCurrentContext(); 123 DPSPrintf(ctxt,"cleardictstack\n"); 124 [self pgplotDefs:ctxt]; 125 [self unlockFocus]; 126 [myWindow orderFrontRegardless]; 127 [psdata empty]; 128 nplot=0; 129 130 return; 131} 132 133- (void) endp 134{ 135 [myWindow setDocumentEdited:NO]; 136 return; 137} 138 139- (void) flushpg 140{ 141 DPSContext ctxt; 142 int i, ibeg; 143 144 if ([psdata count] > nplot) { 145 [self lockFocus]; 146 ibeg=nplot; 147 nplot = [psdata count]; 148 ctxt= DPSGetCurrentContext(); 149 for(i=ibeg; i<nplot; i++) { 150 DPSPrintf(ctxt, "%s\n", (char *) [psdata elementAt:i]); 151 } 152 PScurrentgstate([self gState]); 153 PSpop(); 154 [myWindow flushWindow]; 155 [self unlockFocus]; 156 } 157 return; 158} 159 160- (void) gettype: (int *) iwtype; 161{ 162 *iwtype=lwtype; 163 return; 164} 165 166- (void) getwind: (int *) ixdim by: (int *) iydim 167 color: (int *) icol scale: (int *) imag 168{ 169 *ixdim= (int) ([self bounds].size.width+0.5); 170 *iydim= (int) ([self bounds].size.height+0.5); 171 *icol = [self shouldDrawColor]; 172 *imag=10; 173 return; 174} 175 176- (void) pscode: (char *) cbuf 177{ 178 [psdata addElement:(void *) cbuf]; 179 return; 180} 181 182- (void) readcursor: (NSPoint *) aPoint char: (int *) ichar 183 cursor: (NSCursor *) crossCursor 184{ 185 char cbuf[8]; 186 NSEvent *nextEvent; 187 NSModalSession session; 188 NSPoint curPoint; 189 NSRect hitRect; 190 NSView *mysuper; 191 BOOL qinside, qloop; 192 193// Since pgview is not the active application, it cannot read the 194// the keyboard. The following code forces pgview to become the 195// active application. 196 [NSApp activateIgnoringOtherApps:YES]; 197 198// Calculate the coordinates of the view in the window coordinate system. 199 mysuper = [self superview]; 200 hitRect = [self convertRect:[self frame] fromView:mysuper]; 201 202 [myWindow makeKeyAndOrderFront:self]; 203 curPoint = [myWindow mouseLocationOutsideOfEventStream]; 204 qinside=[self mouse:curPoint inRect:hitRect]; 205 [self addTrackingRect:hitRect 206 owner:self 207 userData:nil 208 assumeInside:qinside]; 209 210 [self lockFocus]; 211 if(qinside) [crossCursor set]; 212 213// If I don't use a Modal loop, then sometimes a busy cursor occurs. 214// The modal loop is the only way I know how to prevent this, sorry. 215 session = [NSApp beginModalSessionForWindow:myWindow]; 216 [NSApp runModalSession:session]; 217 218 qloop=YES; 219 do { 220 nextEvent=[myWindow nextEventMatchingMask: 221 NSLeftMouseDownMask| NSLeftMouseUpMask | 222 NSKeyDownMask | NSKeyUpMask | 223 NSMouseEnteredMask | NSMouseExitedMask]; 224 225 switch ([nextEvent type]) { 226 case NSLeftMouseDown: 227 case NSKeyDown: 228// Ignore down events. 229 break; 230 case NSLeftMouseUp: 231 case NSKeyUp: 232// Only process events if mouse is inside the current view. 233 if(qinside) { 234 if([nextEvent type]==NSKeyUp) { 235 [[nextEvent characters] getCString:cbuf maxLength:8]; 236 *ichar= (int) cbuf[0]; 237 curPoint = [myWindow mouseLocationOutsideOfEventStream]; 238 } else { 239 *ichar= 65; 240 curPoint=[nextEvent locationInWindow]; 241 } 242// First convert from pixel coordinate in the window system to view 243 curPoint = [mysuper convertPoint:curPoint fromView:[mysuper superview]]; 244// Now convert from pixel to scaled coordinate 245 curPoint = [self convertPoint:curPoint fromView:mysuper]; 246 *aPoint = curPoint; 247 qloop=NO; 248 } 249 break; 250 case NSMouseEntered: 251 qinside = YES; 252 [crossCursor set]; 253 break; 254 case NSMouseExited: 255 qinside = NO; 256 [[NSCursor arrowCursor] set]; 257 break; 258 default: 259printf("PGView--mystery event type=%d flags=%d window=%u\n", 260 [nextEvent type], [nextEvent modifierFlags], [nextEvent windowNumber]); 261 break; 262 } 263 264 } while (qloop); 265 266 [NSApp endModalSession:session]; 267 [[NSCursor arrowCursor] set]; 268 [self unlockFocus]; 269 270// I have not found a nice way to return control the last active application. 271// This kludge does the job, but flashes the window on and off the screen. 272// [NSApp hide:self]; 273// [NSApp unhideWithoutActivation]; 274 [NSApp deactivate]; 275 return; 276} 277 278@end 279