from Cocoa import *
from Quartz import *

from SampleCIView import SampleCIView

import objc

class CIMicroPaintView  (SampleCIView):
    imageAccumulator    = objc.ivar()
    brushFilter         = objc.ivar()
    compositeFilter     = objc.ivar()
    color               = objc.ivar()
    brushSize           = objc.ivar(objc._C_FLT)


    def initWithFrame_(self, frame):
        self = super(CIMicroPaintView, self).initWithFrame_(frame)
        if self is None:
            return None

        self.brushSize = 25.0
        self.color = NSColor.colorWithDeviceRed_green_blue_alpha_(
                0.0, 0.0, 0.0, 1.0)

        self.brushFilter = CIFilter.filterWithName_("CIRadialGradient")
        self.brushFilter.setDefaults()
        for k, v in (
                ("inputColor1", CIColor.colorWithRed_green_blue_alpha_(
                   0.0, 0.0, 0.0, 0.0)),
                ("inputRadius0", 0.0),
            ):

            self.brushFilter.setValue_forKey_(v, k)

        self.compositeFilter = CIFilter.filterWithName_("CISourceOverCompositing")
        self.compositeFilter.setDefaults()

        return self

    def viewBoundsDidChange_(self, bounds):
        if self.imageAccumulator is not None  and \
                bounds == self.imageAccumulator.extent():
            print "Nothing changed"
            return

        # Create a new accumulator and composite the old one over the it. 

        c = CIImageAccumulator.alloc(
            ).initWithExtent_format_(bounds, kCIFormatRGBA16)
        f = CIFilter.filterWithName_("CIConstantColorGenerator")
        f.setDefaults()
        f.setValue_forKey_(
             CIColor.colorWithRed_green_blue_alpha_(1.0, 1.0, 1.0, 1.0),
             "inputColor")

        if self.imageAccumulator is not None:
            f = CIFilter.filterWithName_("CISourceOverCompositing")
            f.setDefaults()
            f.setValue_forKey_(self.imageAccumulator.image(), "inputImage")
            f.setValue_forKey_(c.image(), "inputBackgroundImage")
            c.setImage_(f.valueForKey_("outputImage"))

        self.imageAccumulator = c
        self.setImage_(self.imageAccumulator.image())

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

        rect = CGRectMake(loc.x-self.brushSize, loc.y-self.brushSize,
            2.0*self.brushSize, 2.0*self.brushSize)
        self.brushFilter.setValue_forKey_(self.brushSize, "inputRadius1")

        cicolor = CIColor.alloc().initWithColor_(self.color)
        self.brushFilter.setValue_forKey_(cicolor, "inputColor0")

        self.brushFilter.setValue_forKey_(
            CIVector.vectorWithX_Y_(loc.x, loc.y),
            "inputCenter")
        
        self.compositeFilter.setValue_forKey_(
            self.brushFilter.valueForKey_("outputImage"), "inputImage")
        self.compositeFilter.setValue_forKey_(
            self.imageAccumulator.image(), "inputBackgroundImage")
        
        self.imageAccumulator.setImage_dirtyRect_(
            self.compositeFilter.valueForKey_("outputImage"), rect)

        self.setImage_dirtyRect_(self.imageAccumulator.image(), rect)

    def mouseDown_(self, event):
        self.mouseDragged_(event)
