1from Cocoa import * 2from Quartz import * 3import objc 4 5import math 6 7ShadowOffsetChanged = "ShadowOffsetChanged" 8 9class ShadowOffsetView (NSView): 10 _offset = objc.ivar(type=CGSize.__typestr__) 11 _scale = objc.ivar(type=objc._C_FLT) 12 13 14 def scale(self): 15 return self._scale 16 17 def setScale_(self, scale): 18 self._scale = scale 19 20 def offset(self): 21 return CGSizeMake(self._offset.width * self._scale, self._offset.height * self._scale) 22 23 def setOffset_(self, offset): 24 offset = CGSizeMake(offset.width / self._scale, offset.height / self._scale); 25 if self._offset != offset: 26 self._offset = offset; 27 self.setNeedsDisplay_(True) 28 29 def isOpaque(self): 30 return False 31 32 def setOffsetFromPoint_(self, point): 33 bounds = self.bounds() 34 offset = CGSize( 35 width = (point.x - NSMidX(bounds)) / (NSWidth(bounds) / 2), 36 height = (point.y - NSMidY(bounds)) / (NSHeight(bounds) / 2)) 37 radius = math.sqrt(offset.width * offset.width + offset.height * offset.height) 38 if radius > 1: 39 offset.width /= radius; 40 offset.height /= radius; 41 42 if self._offset != offset: 43 self._offset = offset; 44 self.setNeedsDisplay_(True) 45 NSNotificationCenter.defaultCenter().postNotificationName_object_(ShadowOffsetChanged, self) 46 47 def mouseDown_(self, event): 48 point = self.convertPoint_fromView_(event.locationInWindow(), None) 49 self.setOffsetFromPoint_(point) 50 51 def mouseDragged_(self, event): 52 point = self.convertPoint_fromView_(event.locationInWindow(), None) 53 self.setOffsetFromPoint_(point) 54 55 def drawRect_(self, rect): 56 bounds = self.bounds() 57 x = NSMinX(bounds) 58 y = NSMinY(bounds) 59 w = NSWidth(bounds) 60 h = NSHeight(bounds) 61 r = min(w / 2, h / 2) 62 63 context = NSGraphicsContext.currentContext().graphicsPort() 64 65 CGContextTranslateCTM(context, x + w/2, y + h/2) 66 67 CGContextAddArc(context, 0, 0, r, 0, math.pi, True) 68 CGContextClip(context) 69 70 CGContextSetGrayFillColor(context, 0.910, 1) 71 CGContextFillRect(context, CGRectMake(-w/2, -h/2, w, h)) 72 73 CGContextAddArc(context, 0, 0, r, 0, 2*math.pi, True) 74 CGContextSetGrayStrokeColor(context, 0.616, 1) 75 CGContextStrokePath(context) 76 77 CGContextAddArc(context, 0, -2, r, 0, 2*math.pi, True) 78 CGContextSetGrayStrokeColor(context, 0.784, 1) 79 CGContextStrokePath(context) 80 81 CGContextMoveToPoint(context, 0, 0) 82 CGContextAddLineToPoint(context, r * self._offset.width, r * self._offset.height) 83 84 CGContextSetLineWidth(context, 2) 85 CGContextSetGrayStrokeColor(context, 0.33, 1) 86 CGContextStrokePath(context) 87