Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeCanvas/canvas/items/annotationitem.py

    r11273 r11401  
    348348    def __updateArrowPath(self): 
    349349        if self.__arrowStyle == ArrowItem.Plain: 
    350             path = self.__arrowPathPlain() 
     350            path = arrow_path_plain(self.__line, self.__lineWidth) 
    351351        else: 
    352             path = self.__arrowPathConcave() 
     352            path = arrow_path_concave(self.__line, self.__lineWidth) 
    353353        self.setPath(path) 
    354354 
    355     def __arrowPathPlain(self): 
    356         line = self.__line 
    357         width = self.__lineWidth 
    358         path = QPainterPath() 
    359         p1, p2 = line.p1(), line.p2() 
    360  
    361         if p1 == p2: 
    362             return path 
    363  
    364         baseline = QLineF(line) 
    365         # Require some minimum length. 
    366         baseline.setLength(max(line.length() - width * 3, width * 3)) 
    367         path.moveTo(baseline.p1()) 
    368         path.lineTo(baseline.p2()) 
    369  
    370         stroker = QPainterPathStroker() 
    371         stroker.setWidth(width) 
    372         path = stroker.createStroke(path) 
    373  
    374         arrow_head_len = width * 4 
    375         arrow_head_angle = 50 
    376         line_angle = line.angle() - 180 
    377  
    378         angle_1 = line_angle - arrow_head_angle / 2.0 
    379         angle_2 = line_angle + arrow_head_angle / 2.0 
    380  
    381         points = [p2, 
    382                   p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), 
    383                   p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), 
    384                   p2] 
    385  
    386         poly = QPolygonF(points) 
    387         path_head = QPainterPath() 
    388         path_head.addPolygon(poly) 
    389         path = path.united(path_head) 
     355 
     356def arrow_path_plain(line, width): 
     357    """ 
     358    Return an :class:`QPainterPath` of a plain looking arrow. 
     359    """ 
     360    path = QPainterPath() 
     361    p1, p2 = line.p1(), line.p2() 
     362 
     363    if p1 == p2: 
    390364        return path 
    391365 
    392     def __arrowPathConcave(self): 
    393         line = self.__line 
    394         width = self.__lineWidth 
    395         path = QPainterPath() 
    396         p1, p2 = line.p1(), line.p2() 
    397  
    398         if p1 == p2: 
    399             return path 
    400  
    401         baseline = QLineF(line) 
    402         # Require some minimum length. 
    403         baseline.setLength(max(line.length() - width * 3, width * 3)) 
    404  
    405         start, end = baseline.p1(), baseline.p2() 
    406         mid = (start + end) / 2.0 
    407         normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2() 
    408  
    409         path.moveTo(start) 
    410         path.lineTo(start + (normal * width / 4.0)) 
    411  
    412         path.quadTo(mid + (normal * width / 4.0), 
    413                     end + (normal * width / 1.5)) 
    414  
    415         path.lineTo(end - (normal * width / 1.5)) 
    416         path.quadTo(mid - (normal * width / 4.0), 
    417                     start - (normal * width / 4.0)) 
    418         path.closeSubpath() 
    419  
    420         arrow_head_len = width * 4 
    421         arrow_head_angle = 50 
    422         line_angle = line.angle() - 180 
    423  
    424         angle_1 = line_angle - arrow_head_angle / 2.0 
    425         angle_2 = line_angle + arrow_head_angle / 2.0 
    426  
    427         points = [p2, 
    428                   p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), 
    429                   baseline.p2(), 
    430                   p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), 
    431                   p2] 
    432  
    433         poly = QPolygonF(points) 
    434         path_head = QPainterPath() 
    435         path_head.addPolygon(poly) 
    436         path = path.united(path_head) 
     366    baseline = QLineF(line) 
     367    # Require some minimum length. 
     368    baseline.setLength(max(line.length() - width * 3, width * 3)) 
     369    path.moveTo(baseline.p1()) 
     370    path.lineTo(baseline.p2()) 
     371 
     372    stroker = QPainterPathStroker() 
     373    stroker.setWidth(width) 
     374    path = stroker.createStroke(path) 
     375 
     376    arrow_head_len = width * 4 
     377    arrow_head_angle = 50 
     378    line_angle = line.angle() - 180 
     379 
     380    angle_1 = line_angle - arrow_head_angle / 2.0 
     381    angle_2 = line_angle + arrow_head_angle / 2.0 
     382 
     383    points = [p2, 
     384              p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), 
     385              p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), 
     386              p2] 
     387 
     388    poly = QPolygonF(points) 
     389    path_head = QPainterPath() 
     390    path_head.addPolygon(poly) 
     391    path = path.united(path_head) 
     392    return path 
     393 
     394 
     395def arrow_path_concave(line, width): 
     396    """ 
     397    Return a :class:`QPainterPath` of a pretty looking arrow. 
     398    """ 
     399    path = QPainterPath() 
     400    p1, p2 = line.p1(), line.p2() 
     401 
     402    if p1 == p2: 
    437403        return path 
     404 
     405    baseline = QLineF(line) 
     406    # Require some minimum length. 
     407    baseline.setLength(max(line.length() - width * 3, width * 3)) 
     408 
     409    start, end = baseline.p1(), baseline.p2() 
     410    mid = (start + end) / 2.0 
     411    normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2() 
     412 
     413    path.moveTo(start) 
     414    path.lineTo(start + (normal * width / 4.0)) 
     415 
     416    path.quadTo(mid + (normal * width / 4.0), 
     417                end + (normal * width / 1.5)) 
     418 
     419    path.lineTo(end - (normal * width / 1.5)) 
     420    path.quadTo(mid - (normal * width / 4.0), 
     421                start - (normal * width / 4.0)) 
     422    path.closeSubpath() 
     423 
     424    arrow_head_len = width * 4 
     425    arrow_head_angle = 50 
     426    line_angle = line.angle() - 180 
     427 
     428    angle_1 = line_angle - arrow_head_angle / 2.0 
     429    angle_2 = line_angle + arrow_head_angle / 2.0 
     430 
     431    points = [p2, 
     432              p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), 
     433              baseline.p2(), 
     434              p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), 
     435              p2] 
     436 
     437    poly = QPolygonF(points) 
     438    path_head = QPainterPath() 
     439    path_head.addPolygon(poly) 
     440    path = path.united(path_head) 
     441    return path 
    438442 
    439443 
     
    465469        self.__shadow.setEnabled(True) 
    466470 
     471        self.__autoAdjustGeometry = True 
     472 
     473    def setAutoAdjustGeometry(self, autoAdjust): 
     474        """ 
     475        If set to `True` then the geometry will be adjusted whenever 
     476        the arrow is changed with `setLine`. Otherwise the geometry 
     477        of the item is only updated so the `line` lies within the 
     478        `geometry()` rect (i.e. it only grows). True by default 
     479 
     480        """ 
     481        self.__autoAdjustGeometry = autoAdjust 
     482        if autoAdjust: 
     483            self.adjustGeometry() 
     484 
     485    def autoAdjustGeometry(self): 
     486        """ 
     487        Should the geometry of the item be adjusted automatically when 
     488        `setLine` is called. 
     489 
     490        """ 
     491        return self.__autoAdjustGeometry 
     492 
    467493    def setLine(self, line): 
    468         """Set the arrow base line (a `QLineF` in object coordinates). 
     494        """ 
     495        Set the arrow base line (a `QLineF` in object coordinates). 
    469496        """ 
    470497        if self.__line != line: 
     
    476503            if geom.isNull() and not line.isNull(): 
    477504                geom = QRectF(0, 0, 1, 1) 
    478             line_rect = QRectF(line.p1(), line.p2()).normalized() 
    479  
    480             if not (geom.contains(line_rect)): 
    481                 geom = geom.united(line_rect) 
    482  
     505 
     506            arrow_shape = arrow_path_concave(line, self.lineWidth()) 
     507            arrow_rect = arrow_shape.boundingRect() 
     508 
     509            if not (geom.contains(arrow_rect)): 
     510                geom = geom.united(arrow_rect) 
     511 
     512            if self.__autoAdjustGeometry: 
     513                # Shrink the geometry if required. 
     514                geom = geom.intersected(arrow_rect) 
     515 
     516            # topLeft can move changing the local coordinates. 
    483517            diff = geom.topLeft() 
    484518            line = QLineF(line.p1() - diff, line.p2() - diff) 
     
    491525 
    492526    def line(self): 
    493         """Return the arrow base line. 
     527        """ 
     528        Return the arrow base line (`QLineF` in object coordinates). 
    494529        """ 
    495530        return QLineF(self.__line) 
    496531 
    497532    def setColor(self, color): 
    498         """Set arrow brush color. 
     533        """ 
     534        Set arrow brush color. 
    499535        """ 
    500536        if self.__color != color: 
     
    503539 
    504540    def color(self): 
    505         """Return the arrow brush color. 
     541        """ 
     542        Return the arrow brush color. 
    506543        """ 
    507544        return QColor(self.__color) 
    508545 
    509546    def setLineWidth(self, lineWidth): 
    510         """Set the arrow line width. 
     547        """ 
     548        Set the arrow line width. 
    511549        """ 
    512550        self.__arrowItem.setLineWidth(lineWidth) 
    513551 
    514552    def lineWidth(self): 
    515         """Return the arrow line width. 
     553        """ 
     554        Return the arrow line width. 
    516555        """ 
    517556        return self.__arrowItem.lineWidth() 
    518557 
    519558    def adjustGeometry(self): 
    520         """Adjust the widget geometry to exactly fit the arrow inside 
     559        """ 
     560        Adjust the widget geometry to exactly fit the arrow inside 
    521561        while preserving the arrow path scene geometry. 
    522562 
     
    552592 
    553593    def __updateBrush(self): 
    554         """Update the arrow brush. 
     594        """ 
     595        Update the arrow brush. 
    555596        """ 
    556597        if self.isSelected(): 
Note: See TracChangeset for help on using the changeset viewer.