from Cocoa import *
from Quartz import *
import objc

import math

ShadowOffsetChanged = "ShadowOffsetChanged"

class ShadowOffsetView (NSView):
    _offset = objc.ivar(type=CGSize.__typestr__)
    _scale = objc.ivar(type=objc._C_FLT)


    def scale(self):
        return self._scale

    def setScale_(self, scale):
        self._scale = scale

    def offset(self):
        return CGSizeMake(self._offset.width * self._scale, self._offset.height * self._scale)

    def setOffset_(self, offset):
        offset = CGSizeMake(offset.width / self._scale, offset.height / self._scale);
        if self._offset != offset:
            self._offset = offset;
            self.setNeedsDisplay_(True)

    def isOpaque(self):
        return False

    def setOffsetFromPoint_(self, point): 
        bounds = self.bounds()
        offset = CGSize(
            width = (point.x - NSMidX(bounds)) / (NSWidth(bounds) / 2),
            height = (point.y - NSMidY(bounds)) / (NSHeight(bounds) / 2))
        radius = math.sqrt(offset.width * offset.width + offset.height * offset.height)
        if radius > 1:
            offset.width /= radius;
            offset.height /= radius;

        if self._offset != offset:
            self._offset = offset;
            self.setNeedsDisplay_(True)
            NSNotificationCenter.defaultCenter().postNotificationName_object_(ShadowOffsetChanged, self)

    def mouseDown_(self, event):
        point = self.convertPoint_fromView_(event.locationInWindow(), None)
        self.setOffsetFromPoint_(point)

    def mouseDragged_(self, event):
        point = self.convertPoint_fromView_(event.locationInWindow(), None)
        self.setOffsetFromPoint_(point)

    def drawRect_(self, rect):
        bounds = self.bounds()
        x = NSMinX(bounds)
        y = NSMinY(bounds)
        w = NSWidth(bounds)
        h = NSHeight(bounds)
        r = min(w / 2, h / 2)
        
        context = NSGraphicsContext.currentContext().graphicsPort()

        CGContextTranslateCTM(context, x + w/2, y + h/2)

        CGContextAddArc(context, 0, 0, r, 0, math.pi, True)
        CGContextClip(context)

        CGContextSetGrayFillColor(context, 0.910, 1)
        CGContextFillRect(context, CGRectMake(-w/2, -h/2, w, h))

        CGContextAddArc(context, 0, 0, r, 0, 2*math.pi, True)
        CGContextSetGrayStrokeColor(context, 0.616, 1)
        CGContextStrokePath(context)

        CGContextAddArc(context, 0, -2, r, 0, 2*math.pi, True)
        CGContextSetGrayStrokeColor(context, 0.784, 1)
        CGContextStrokePath(context)

        CGContextMoveToPoint(context, 0, 0)
        CGContextAddLineToPoint(context, r * self._offset.width, r * self._offset.height)

        CGContextSetLineWidth(context, 2)
        CGContextSetGrayStrokeColor(context, 0.33, 1)
        CGContextStrokePath(context)
