def mouseDragged(self, mousePoint, delta):
     if self.snatchedPoint is not None:
         snatchedPoint = self.snatchedPoint
         cut = False
         self._roundedGlyph = IntelGlyph(self._sourceGlyph)
         i1, i2 = self.getRoundedPointIndices(snatchedPoint)
         dx = snatchedPoint[0]-mousePoint[0]
         dy = snatchedPoint[1]-mousePoint[1]
         d = hypot(dx, dy)
         if self.shiftDown:
             d = round(d/5)*5
         d = int(d)
         limit = self.getLimit(snatchedPoint)
         if d > limit:
             d = limit
         if self.shiftDown and self.commandDown:
             d = 0
         if self.optionDown:
             cut = True
         self._roundedGlyph[i1][i2].labels['cornerRadius'] = d
         self._roundedGlyph[i1][i2].labels['cut'] = cut
         self._roundedGlyph.drawCornersByLabels()
         snatchedPoint.labels['cornerRadius'] = d
         snatchedPoint.labels['cut'] = cut
         self.snatchedPoint = snatchedPoint
 def getSelection(self, notification=None):
     glyph = CurrentGlyph()
     if len(glyph.selection) == 0:
         return []
     elif len(glyph.selection) > 0:
         iG = IntelGlyph(glyph)
         if self.currentMode == 'Build':
             selection = iG.getSelection(True)
         elif self.currentMode in ['Break', 'Pit']:
             selection = [point for point in iG.getSelection() if (point.segmentType is not None) and (abs(point.turn()) > pi/18)]
         return selection
 def getSelection(self, notification=None):
     glyph = CurrentGlyph()
     if len(glyph.selection) == 0:
         return []
     elif len(glyph.selection) > 0:
         iG = IntelGlyph(glyph)
         if self.currentMode == 'Build':
             selection = iG.getSelection(True)
         elif self.currentMode in ['Break', 'Pit']:
             selection = [point for point in iG.getSelection() if (point.segmentType is not None) and (abs(point.turn()) > pi/18)]
         return selection
 def breakCorners(self):
     g = CurrentGlyph()
     iG = IntelGlyph(g)
     radius = self.parameters['radius'].get()
     roundness = self.parameters['roundness'].get()
     for contour in iG:
         selection = contour.getSelection()
         for point in selection:
             contour.breakCorner(point, radius, velocity=roundness)
         contour.correctSmoothness()
     return iG
 def pitCorners(self):
     g = CurrentGlyph()
     iG = IntelGlyph(g)
     depth = self.parameters['depth'].get()
     breadth = self.parameters['breadth'].get()
     bottom = self.parameters['bottom'].get()
     for contour in iG:
         selection = contour.getSelection()
         for point in selection:
             contour.pitCorner(point, depth, breadth, bottom)
         contour.removeOverlappingPoints()
         contour.correctSmoothness()
     return iG
 def updateRoundablePoints(self):
     glyph = self._sourceGlyph = self.getGlyph()
     if glyph is not None:
         workingGlyph = IntelGlyph(glyph)
         self._roundedGlyph = IntelGlyph(glyph)
         self._roundedGlyph.drawCornersByLabels()
         roundablePoints = []
         for contour in workingGlyph:
             closed = contour.isClosed
             for point in contour:
                 nextPoint = point.next()
                 previousPoint = point.previous()
                 turnLimit = abs(point.turn()) < (10/180)*pi
                 if (point.segmentType is not None) and \
                     (self.getLimit(point) > 0) and \
                    (closed or (not closed and (not point.isFirst()) and (not point.isLast()))) and \
                    (((previousPoint.segmentType is not None) and (nextPoint.segmentType is not None)) or \
                     ((previousPoint.segmentType is None) and (nextPoint.segmentType is not None) and not turnLimit and not point.smooth) or \
                     ((previousPoint.segmentType is not None) and (nextPoint.segmentType is None) and not turnLimit and not point.smooth)):
                     roundablePoints.append(point)
         self.roundablePoints = roundablePoints
         self._workingGlyph = workingGlyph
 def buildCorners(self):
     g = CurrentGlyph()
     iG = IntelGlyph(g)
     for contour in iG:
         segments = contour.collectSegments()['selection']
         l = len(segments)
         lines, curves = self.checkComposition(segments)
         if l > 1 and lines and curves:
             segments = [segment for segment in segments if len(segment) == 4]
         elif l > 1 and lines and not curves:
             segments = segments[:1] + segments[-1:]
         for segment in reversed(segments):
             contour.buildCorner(segment)
     return iG
class RoundingTool(BaseEventTool):

    def becomeActive(self):
        self.init()
        # self.testKnob = BaseCornerKnob((100, 100))

    # def becomeInactive(self):
        # self.testKnob.end()

    def init(self):
        self._sourceGlyph = None
        self._workingGlyph = None
        self._roundedGlyph = None
        self.roundablePoints = []
        self.snatchedPoint = None
        self.preview = False
        self.updateRoundablePoints()
        self.draggedRectangle = {'rect':[], 'bounds':[]}
        self.mouseDownPoint = None
        self.pointSelection = []

    def mouseDown(self, mousePoint, clickCount):
        self.mouseDownPoint = mousePoint
        self.pointSelection = []
        if clickCount == 2:
            if self.commandDown and self._sourceGlyph is not None:
                for point in self.roundablePoints:
                    point.labels['cornerRadius'] = 0
                    point.labels['cut'] = False
                    self.writePointLabels(self._sourceGlyph, point)
                self.updateRoundablePoints()
            elif not self.commandDown:
                self.makeRoundedGlyph()
        elif clickCount == 1:
            controlZoneRadius = 8
            roundablePoints = self.roundablePoints
            for point in roundablePoints:
                controlPoint, r = self.getControlPoint(point)
                if abs(controlPoint[0]-mousePoint[0]) <= controlZoneRadius and abs(controlPoint[1]-mousePoint[1]) <= controlZoneRadius:
                    self.snatchedPoint = point
                    break

    def mouseDragged(self, mousePoint, delta):
        if self.snatchedPoint is not None:
            snatchedPoint = self.snatchedPoint
            cut = False
            self._roundedGlyph = IntelGlyph(self._sourceGlyph)
            i1, i2 = self.getRoundedPointIndices(snatchedPoint)
            dx = snatchedPoint[0]-mousePoint[0]
            dy = snatchedPoint[1]-mousePoint[1]
            d = hypot(dx, dy)
            if self.shiftDown:
                d = round(d/5)*5
            d = int(d)
            limit = self.getLimit(snatchedPoint)
            if d > limit:
                d = limit
            if self.shiftDown and self.commandDown:
                d = 0
            if self.optionDown:
                cut = True
            self._roundedGlyph[i1][i2].labels['cornerRadius'] = d
            self._roundedGlyph[i1][i2].labels['cut'] = cut
            self._roundedGlyph.drawCornersByLabels()
            snatchedPoint.labels['cornerRadius'] = d
            snatchedPoint.labels['cut'] = cut
            self.snatchedPoint = snatchedPoint

    # def rightMouseDown(self, point, event):
    #     print "rightMouseDown"

    # def rightMouseDragged(self, point, delta):
    #     print "rightMouseDragged"

    def mouseUp(self, point):
        # if self.snatchedPoint is None:
        #     mouseDownPoint = self.mouseDownPoint
        #     if (self._sourceGlyph is not None) and (mouseDownPoint is not None):
        #         currentGlyph = self._sourceGlyph
        #         xMin = min(mouseDownPoint[0], point[0])
        #         xMax = max(mouseDownPoint[0], point[0])
        #         yMin = min(mouseDownPoint[1], point[1])
        #         yMax = max(mouseDownPoint[1], point[1])
        #         for contour in currentGlyph.contours:
        #             for point in contour.points:
        #                 if pointInRect((point.x, point.y), [xMin, yMin, xMax, yMax]):
        #                     point.selected = True
        #                     self.pointSelection.append(point)
        #         currentGlyph.update()
        #         self.updateRoundablePoints()
        if (self._roundedGlyph is not None) and (self.snatchedPoint is not None):
            snatchedPoint = self.snatchedPoint
            self._roundedGlyph.drawCornersByLabels()
            self.writePointLabels(self._sourceGlyph, snatchedPoint)
            self.snatchedPoint = None
        self.mouseDownPoint = None

    def updateRoundablePoints(self):
        glyph = self._sourceGlyph = self.getGlyph()
        if glyph is not None:
            workingGlyph = IntelGlyph(glyph)
            self._roundedGlyph = IntelGlyph(glyph)
            self._roundedGlyph.drawCornersByLabels()
            roundablePoints = []
            for contour in workingGlyph:
                closed = contour.isClosed
                for point in contour:
                    nextPoint = point.next()
                    previousPoint = point.previous()
                    turnLimit = abs(point.turn()) < (10/180)*pi
                    if (point.segmentType is not None) and \
                        (self.getLimit(point) > 0) and \
                       (closed or (not closed and (not point.isFirst()) and (not point.isLast()))) and \
                       (((previousPoint.segmentType is not None) and (nextPoint.segmentType is not None)) or \
                        ((previousPoint.segmentType is None) and (nextPoint.segmentType is not None) and not turnLimit and not point.smooth) or \
                        ((previousPoint.segmentType is not None) and (nextPoint.segmentType is None) and not turnLimit and not point.smooth)):
                        roundablePoints.append(point)
            self.roundablePoints = roundablePoints
            self._workingGlyph = workingGlyph

    def getControlPoint(self, point):
        direction = point.direction()
        radius = self.getRadius(point)
        return point.polarCoord(direction, radius), radius

    def getRoundedPointIndices(self, point):
        pointIndex = point.index
        contourIndex = point.getParentContour().index
        return contourIndex, pointIndex

    def getRadius(self, point):
        radius = 0
        if point.labels['cornerRadius']:
            radius = int(point.labels['cornerRadius'])
        return radius

    def getLimit(self, point):
        previousPoint = point.previous()
        nextPoint = point.next()
        d = -1
        if previousPoint is not None and nextPoint is not None:
            d1 = point.distance(previousPoint)-float(self.getRadius(previousPoint))
            d2 = point.distance(nextPoint)-float(self.getRadius(nextPoint))
            d = int(min(d1, d2))
        if d < 0: d = 0
        return d

    def writePointLabels(self, glyph, iPoint):
        i1, i2 = self.getRoundedPointIndices(iPoint)
        RPoint = glyph.contours[i1].points[i2]
        RPoint.name = iPoint.labels.write(RPoint.name)

    controlSoftColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(.8, .6, 0, .25)
    controlStrongColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(.8, .6, 0, 0.85)

    def draw(self, scale):
        controlSoftColor = self.controlSoftColor
        controlStrongColor = self.controlStrongColor
        if self._roundedGlyph is not None:
            self._roundedGlyph.drawPreview(scale, styleFill=False, showNodes=False, strokeWidth=2, strokeColor=controlStrongColor)
        for point in self.roundablePoints:
            x, y = point.x, point.y
            (cx, cy), r = self.getControlPoint(point)
            controlSoftColor.set()
            controlStrongColor.setStroke()
            radiusCircle = NSBezierPath.bezierPathWithOvalInRect_(((x-r, y-r), (r*2, r*2)))
            radiusCircle.fill()
            radiusCircle.setLineWidth_(scale)
            radiusCircle.stroke()
            controlStrongColor.set()
            cor = 12*scale
            controlDot = NSBezierPath.bezierPathWithOvalInRect_(((cx-cor, cy-cor), (cor*2, cor*2)))
            controlDot.fill()
            if point.labels['cornerRadius']:
                fill(1)
                fontSize(9*scale)
                _r = str(r)
                textBox(_r, (cx-cor, cy-(cor*1.5), cor*2, cor*2), align='center')
        # if self.isDragging and (self.currentPoint is not None) and (self.mouseDownPoint is not None) and (self.snatchedPoint is None):
        #     fill(.25, .25, .25, .25)
        #     mouseDownPoint = self.mouseDownPoint
        #     currentPoint = self.currentPoint
        #     rect(mouseDownPoint[0], mouseDownPoint[1], currentPoint[0]-mouseDownPoint[0], currentPoint[1]-mouseDownPoint[1])


    def makeRoundedGlyph(self):
        if self._roundedGlyph is not None:
            self._sourceGlyph.prepareUndo('round')
            self._sourceGlyph = self.stripContours(self._sourceGlyph)
            pen = self._sourceGlyph.getPointPen()
            self._roundedGlyph.drawPoints(pen)
            self._sourceGlyph.performUndo()
            self._sourceGlyph.update()
            self.updateRoundablePoints()

    def stripContours(self, glyph):
        for contour in glyph.contours:
            glyph.removeContour(contour)
        return glyph

    def didUndo(self, notification):
        self.updateRoundablePoints()

    # def keyUp(self, event):
    #     print "keyUp"

    # def modifiersChanged(self):
    #     pass

    # def drawBackground(self, scale):
    #     print "drawBackground here"

    #def getDefaultCursor(self):
    #   this will be the cursor default is an arrow
    #   return aNSCursor

    def getToolbarIcon(self):
        return toolbarIcon

    def getToolbarTip(self):
        return "Rounding Tool"

    #notifications

    def viewDidChangeGlyph(self):
        self.init()