1import objc
2from Foundation import *
3from AppKit import *
4from math import pi, sin, cos
5from fieldMath import *
6
7# Convience global variables
8x, y = 0, 1
9llc, sze = 0, 1 # Left Lower Corner, Size
10
11#____________________________________________________________
12class CGraphView(NSView):
13
14    azmuthSlider = objc.IBOutlet()
15    mapOffsetEWSlider = objc.IBOutlet()
16    mapOffsetNSSlider = objc.IBOutlet()
17    mapScaleSlider = objc.IBOutlet()
18    mapVisibleSlider = objc.IBOutlet()
19    azmuthDisplay = objc.IBOutlet()
20    mapOffsetEWDisplay = objc.IBOutlet()
21    mapOffsetNSDisplay = objc.IBOutlet()
22    mapScaleDisplay = objc.IBOutlet()
23
24    def initWithFrame_(self, frame):
25        super(CGraphView, self).initWithFrame_(frame)
26        self.setGridColor()
27        self.setRmsColor()
28        self.setGraphColor()
29        self.graphMargin = 2
30        self.mapImage = 0
31        self.mapRect = 0
32        self.mapVisible = 0.70
33        self.mapScale = 3.0
34        self.mapOffsetEW = 0.27
35        self.mapOffsetNS = 0.40
36        self.mapBaseRadius = 200
37
38        self.lines = 2
39        self.gain = 0.5
40        return self
41
42    def awakeFromNib(self):
43        self.setCrossCursor()
44        self.mapVisibleSlider.setFloatValue_(self.mapVisible)
45        self.setAzmuth(125)
46        self.setMapRect()
47
48    def setCrossCursor(self):
49        crosshairImage = NSImage.imageNamed_("CrossCursor")
50        imageSize = crosshairImage.size()
51        self.crossCursor = NSCursor.alloc().initWithImage_hotSpot_(crosshairImage, (8, 8))
52        rect = self.bounds()
53        self.trackingRect = self.addTrackingRect_owner_userData_assumeInside_(self.bounds(), self, 0, 0)
54
55    def setGridColor(self, color=NSColor.greenColor()):
56        self.gridColor = color
57
58    def setRmsColor(self, color=NSColor.blueColor()):
59        self.rmsColor = color
60
61    def setGraphColor(self, color=NSColor.blackColor()):
62        self.graphColor = color
63
64    def setGain(self, gain, total):
65        self.gain = gain
66        self.totalField = total
67
68    def setLines(self, lines):
69        self.lines = lines
70
71    def setMapImage(self, mapImage):
72        self.mapImage = mapImage
73        self.mapRect = ((0, 0), mapImage.size())
74
75    def setPath(self, path, maxMag):
76        self.path = path
77        self.maxMag = maxMag
78        self.setNeedsDisplay_(1)
79
80
81    def drawRect_(self, rect):
82        frame = self.frame()
83        self.origin = frame[0]
84        self.graphCenter = (frame[sze][x]/2, frame[sze][y]/2)
85        self.graphRadius = (min(frame[sze][x], frame[sze][y]) / 2) - self.graphMargin
86
87        NSColor.whiteColor().set()
88        NSRectFill(self.bounds())
89
90        self.drawMap()
91        self.drawGrid()
92        self.drawRMS()
93        self.drawField()
94
95    def drawMap(self):
96        if self.mapImage == 0:
97            return
98
99        scale = self.mapScale * (self.graphRadius / self.mapBaseRadius) * self.gain / self.totalField
100        xImageSize = scale * self.mapRect[sze][x]
101        yImageSize = scale * self.mapRect[sze][y]
102        xCenterMove = self.graphCenter[x] - self.graphRadius
103        yCenterMove = self.graphCenter[y] - self.graphRadius
104
105        xOffset = -((1 - self.mapOffsetEW) / 2) * xImageSize
106        yOffset = -((1 + self.mapOffsetNS) / 2) * yImageSize
107        xOffset += self.graphRadius + xCenterMove
108        yOffset += self.graphRadius + yCenterMove
109
110        drawInRect = ((xOffset, yOffset), (xImageSize, yImageSize))
111
112        self.mapImage.drawInRect_fromRect_operation_fraction_(drawInRect, self.mapRect, NSCompositeSourceOver, self.mapVisible)
113
114    def drawGrid(self):
115        self.gridColor.set()
116        self.drawCircle(1.0)
117        self.drawAxisLines()
118
119    def drawCircle(self, scale):
120        center = self.graphCenter
121        radius = self.graphRadius*scale
122        x, y = 0, 1
123        if radius >= 1:
124            dotRect = ((center[x]-radius, center[y]-radius), (2*radius, 2*radius))
125            path = NSBezierPath.bezierPathWithOvalInRect_(dotRect)
126            path.stroke()
127
128    def drawRMS(self):
129        self.rmsColor.set()
130        self.drawCircle(self.gain)
131
132    def drawAxisLines(self):
133        center = self.graphCenter
134        radius = self.graphRadius
135        x, y = 0, 1
136        path = NSBezierPath.bezierPath()
137        for i in range(1, self.lines+1):
138            iR = pi / i
139            cosR = cos(iR) * radius
140            sinR = sin(iR) * radius
141
142            path.moveToPoint_((center[x] - cosR, center[y] - sinR))
143            path.lineToPoint_((center[x] + cosR, center[y] + sinR))
144        path.closePath()
145        path.stroke()
146
147    def drawField(self):
148        if self.maxMag:         # Don't want to divide by zero in the pathological case
149            self.graphColor.set()
150            path = self.path.copy()
151
152            transform = NSAffineTransform.transform()
153            transform.rotateByRadians_(-(pi / 2.0) - self.azmuth)
154            path.transformUsingAffineTransform_(transform)
155
156            transform = NSAffineTransform.transform()
157            center = self.graphCenter
158            transform.translateXBy_yBy_(center[0], center[1])
159            transform.scaleBy_(self.graphRadius / self.maxMag)
160            path.transformUsingAffineTransform_(transform)
161
162            path.stroke()
163
164
165#____________________________________________________________
166# Handle GUI values
167    @objc.IBAction
168    def mapVisibleSlider_(self, sender):
169        self.mapVisible = (sender.floatValue())
170        self.setNeedsDisplay_(1)
171
172    @objc.IBAction
173    def azmuthDisplay_(self, sender):
174        self.setAzmuth(sender.floatValue())
175
176    @objc.IBAction
177    def azmuthSlider_(self, sender):
178        self.setAzmuth(sender.floatValue())
179
180    def setAzmuth(self, value):
181        self.azmuth = degToRad(value)
182        self.azmuthSlider.setFloatValue_(value)
183        self.azmuthDisplay.setFloatValue_(value)
184        self.setNeedsDisplay_(1)
185
186    @objc.IBAction
187    def mapScaleDisplay_(self, sender):
188        self.mapScale = sender.floatValue()
189        self.setMapRect()
190
191    @objc.IBAction
192    def mapScaleSlider_(self, sender):
193        self.mapScale = sender.floatValue()
194        self.setMapRect()
195
196    @objc.IBAction
197    def mapOffsetNSDisplay_(self, sender):
198        self.mapOffsetNS = sender.floatValue()
199        self.setMapRect()
200
201    @objc.IBAction
202    def mapOffsetNSSlider_(self, sender):
203        self.mapOffsetNS = sender.floatValue()
204        self.setMapRect()
205
206    @objc.IBAction
207    def mapOffsetEWDisplay_(self, sender):
208        self.mapOffsetEW = sender.floatValue()
209        self.setMapRect()
210
211    @objc.IBAction
212    def mapOffsetEWSlider_(self, sender):
213        self.mapOffsetEW = sender.floatValue()
214        self.setMapRect()
215
216    def mouseUp_(self, event):
217        loc = event.locationInWindow()
218        xLoc = loc[x] - self.origin[x]
219        yLoc = loc[y] - self.origin[y]
220        xDelta = self.graphCenter[x] - xLoc
221        yDelta = self.graphCenter[y] - yLoc
222
223
224        scale = 0.5 * self.mapScale * (self.gain / self.totalField) * (self.graphRadius / self.mapBaseRadius)
225        xOffset = xDelta / (scale * self.mapRect[sze][x])
226        yOffset = yDelta / (scale * self.mapRect[sze][y])
227
228        self.mapOffsetEW += xOffset
229        self.mapOffsetNS -= yOffset
230        self.setMapRect()
231
232    def mouseDown_(self, event):
233        self.crossCursor.set()
234
235
236    def setMapRect(self):
237        self.mapScaleDisplay.setFloatValue_(self.mapScale)
238        self.mapScaleSlider.setFloatValue_(self.mapScale)
239        self.mapOffsetEWDisplay.setFloatValue_(self.mapOffsetEW)
240        self.mapOffsetEWSlider.setFloatValue_(self.mapOffsetEW)
241        self.mapOffsetNSDisplay.setFloatValue_(self.mapOffsetNS)
242        self.mapOffsetNSSlider.setFloatValue_(self.mapOffsetNS)
243        self.setNeedsDisplay_(1)
244
245    def mouseEntered_(self, event):
246        print 'CGraphView: mouseEntered_'
247
248    def mouseExited_(self, event):
249        print 'CGraphView: mouseExited_'
250