File: PGView.m

package info (click to toggle)
pgplot5 5.2-8
  • links: PTS
  • area: non-free
  • in suites: slink
  • size: 6,268 kB
  • ctags: 5,900
  • sloc: fortran: 37,938; ansic: 18,809; sh: 1,136; objc: 532; perl: 443; makefile: 271; pascal: 233; tcl: 178; awk: 51; csh: 25
file content (277 lines) | stat: -rw-r--r-- 7,639 bytes parent folder | download | duplicates (15)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// PGView is the custom view object for the pgview program.  PGView
// receives 132 byte character arrays filled with PostScript code.  PGView
// saves these buffers in a Storage object.  When the PGPLOT program
// executes a flush operation, this stored data is then sent to the
// display.
//
// 1992-Mar-9 - [AFT]
//---
#import "PGView.h"
#import <appkit/Application.h>
#import <appkit/NXCursor.h>
#import <appkit/Window.h>
#import <objc/Storage.h>
#import <dpsclient/wraps.h>    // for PSxxxx routines

@implementation PGView

- initFrame:(const NXRect *) frameRect
{
      id       myWindow;

      [super initFrame:frameRect];

// Create an enclosing window and bring it upfront
    
      myWindow = [[Window alloc] initContent:frameRect
            style:NX_RESIZEBARSTYLE
            backing:NX_BUFFERED
            buttonMask:(NX_MINIATURIZEBUTTONMASK | NX_CLOSEBUTTONMASK)
            defer:NO];
      [myWindow setContentView:self];
      [myWindow setBackgroundGray:NX_WHITE];
      [myWindow setFreeWhenClosed:YES];
      [[[window setTitle:"PGPLOT Viewer"] display] orderFront:self];

// Save portrait/landscape flag
      if( frameRect->size.width > frameRect->size.height) {
         lwtype=0;
      } else {
         lwtype=1;
      }

// Needed to do PostScript scaling
      [self scale:0.1 :0.1];
      prevw = bounds.size.width;
      prevh = bounds.size.height;

// Buffer is used to store PostScript data
      psdata = [Storage newCount:1
                elementSize:132
                description:"[132c]"];
      iflush=0;
      nbuf=0;
      nplot=0;

// Allocate private graphics state, so things like the current color
// setting will be preserved between different calls to drawSelf.
      [self notifyToInitGState:YES];
      [self allocateGState];

      return self;
}

- drawSelf:(const NXRect *) rects :(int)rectCount
{
      char  *ctmp;
      int   i, ibeg;

      ctxt= DPSGetCurrentContext();
      if ([psdata count] > 0) {

         if( prevw != bounds.size.width || prevh != bounds.size.height) {
            [self scale:bounds.size.width/prevw
                       :bounds.size.height/prevh];
            prevw = bounds.size.width;
            prevh = bounds.size.height;
         }

// If PGPLOT sent a 'flush' message, then only send new data to sceen.
         if( iflush>0 ) {
            ibeg=nplot;
         } else {
            ibeg=0;
         }

         nplot = nbuf;
         for(i=ibeg; i<nplot; i++) {
            ctmp = (char *) [psdata elementAt:i];
//printf("drawSelf--%s\n", ctmp);
            DPSPrintf(ctxt, "%s\n", ctmp);
         }
// Preserve current graphic state for next call.
         if( iflush>0 ) {
            PScurrentgstate([self gState]);
            PSpop();
         }
      }
      return self;
}

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

- endPrologue
// This routine sends the PGPLOT defines to the print job.
{
      ctxt= DPSGetCurrentContext();
      [self pgplotDefs];
      return [super endPrologue];
}

- pgplotDefs
{
      DPSPrintf(ctxt,
      "/l {moveto rlineto currentpoint stroke moveto} bind def\n");
      DPSPrintf(ctxt,
      "/c {rlineto currentpoint stroke moveto} bind def\n");
      DPSPrintf(ctxt,
      "/d {moveto 0 0 rlineto currentpoint stroke moveto} bind def\n");
      DPSPrintf(ctxt,"/SLW {5 mul setlinewidth} bind def\n");
      DPSPrintf(ctxt,"/BP {newpath moveto} bind def\n");
      DPSPrintf(ctxt,"/LP /rlineto load def\n");
      DPSPrintf(ctxt,"/EP {rlineto closepath eofill} bind def\n");
      return self;
}

- beginp
{
      [self lockFocus];
      ctxt= DPSGetCurrentContext();
      DPSPrintf(ctxt,"cleardictstack\n");
      [self pgplotDefs];
      [self unlockFocus];

      [psdata empty];
      nbuf=0;
      nplot=0;

      return self;
}

- flush
{
      if ([psdata count] > nplot) {
         iflush=1;
         nbuf=[psdata count];
         [self display];
         iflush=0;
      }
      return self;
}

- gettype: (int *) iwtype;
{
      *iwtype=lwtype;
      return self;
}

- getwind: (int *) ixdim  by: (int *) iydim
      color: (int *) icol  scale: (double *) dmag
{
      *ixdim= (int) (bounds.size.width+0.5);
      *iydim= (int) (bounds.size.height+0.5);
      *icol = [self shouldDrawColor];
      *dmag=10.0;
      return self;
}

- pscode: (char *) cbuf
{
      [psdata addElement:(void *) cbuf];
      return self;
}

- readcursor: (NXPoint *) aPoint char: (int *) ichar
      cursor: (NXCursor *) crossCursor
{
      int      lasact, iwindnum;
      NXEvent  *nextEvent;
      NXModalSession session;
      NXPoint  curPoint;
      NXRect   hitRect;
      BOOL     qinside, qloop;

// Since pgview is not the active application, it cannot read the
// the keyboard.  The following code forces pgview to become the
// active application.
      lasact= [NXApp activateSelf:YES];

// Calculate the coordinates of the view in the window coordinate system.
      [self getFrame:&hitRect];
      [superview convertRect:&hitRect toView:nil];

      [window makeKeyAndOrderFront:self];
      [window getMouseLocation:&curPoint];
      qinside=[self mouse:&curPoint  inRect:&hitRect];
      [window setTrackingRect:&hitRect  inside:qinside  owner:self
         tag:1  left:NO  right:NO];
      iwindnum=[window windowNum];

      [self lockFocus];

// If I don't use a Modal loop, then sometimes a busy cursor occurs.
// The modal loop is the only way I know how to prevent this, sorry.
      [NXApp beginModalSession: &session for:window];
      [NXApp runModalSession: &session];

      PSshowcursor();
      if(qinside) {
         [crossCursor set];
      }
// Following should work, but doesn't
//      [self addCursorRect:&hitRect cursor:crossCursor];

      qloop=YES;
      do {
         nextEvent=[NXApp getNextEvent:
            NX_MOUSEDOWNMASK    | NX_MOUSEUPMASK |
            NX_KEYDOWNMASK      | NX_KEYUPMASK   |
            NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK ];

         switch (nextEvent->type) {
         case NX_MOUSEDOWN:
         case NX_KEYDOWN:
// Ignore down events.
            break;
         case NX_MOUSEUP:
         case NX_KEYUP:
// Only process events if mouse is inside the current view.
            if(qinside) {
               if(nextEvent->type==NX_KEYUP) {
                  *ichar= (int) nextEvent->data.key.charCode;
                  [window getMouseLocation:&curPoint];
               } else {
                  *ichar= 65;
                  curPoint=nextEvent->location;
               }
// First convert from pixel coordinate in the window system to view
               [superview convertPointFromSuperview:&curPoint];
// Now convert from pixel to scaled coordinate
               [self convertPointFromSuperview:&curPoint];
               *aPoint = curPoint;
               qloop=NO;
            }
            break;
         case NX_MOUSEENTERED:
            qinside = YES;
            [crossCursor set];
            break;
         case NX_MOUSEEXITED:
            qinside = NO;
            [NXArrow set];
            break;
         default:
printf("PGView--mystery event type=%d  flags=%d  window=%u\n",
         nextEvent->type, nextEvent->flags, nextEvent->window);
            break;
         }

      } while (qloop);

      [NXArrow set];
      [NXApp endModalSession: &session];
      [self unlockFocus];

// Sending an active:lstact message to NXApp does not always work.  The
// problem occurs if pgview was launched via an 'open -a' statement and
// for the second (and following) cursor reads in pgex15.  The following
// is less 'user friendly' but safer.
      [NXApp deactivateSelf];
      return self;
}

@end