Changeset 11207:8145a5984767 in orange


Ignore:
Timestamp:
11/28/12 12:31:29 (17 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Fixed anchor point layout order reset while dragging (creating) a new link.

Location:
Orange/OrangeCanvas
Files:
5 edited

Legend:

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

    r11186 r11207  
    55 
    66from xml.sax.saxutils import escape 
    7  
    8 import numpy 
    97 
    108from PyQt4.QtGui import ( 
     
    2321from ...registry import NAMED_COLORS 
    2422from ...resources import icon_loader 
     23from .utils import uniform_linear_layout 
    2524 
    2625 
     
    282281        self.__dottedStroke = None 
    283282 
    284         self.__layoutRequested = False 
    285  
    286283    def parentNodeItem(self): 
    287284        """Return a parent `NodeItem` or `None` if this anchor's 
     
    403400        del self.__pointPositions[index] 
    404401 
    405         self.__scheduleDelayedLayout() 
    406  
    407402    def anchorPoints(self): 
    408403        """Return a list of anchor points. 
     
    421416        """ 
    422417        if self.__pointPositions != positions: 
    423             self.__pointPositions = positions 
     418            self.__pointPositions = list(positions) 
    424419 
    425420            self.__updatePositions() 
    426421 
    427422    def anchorPositions(self): 
    428         """Return the positions of anchor points as a list floats where 
     423        """Return the positions of anchor points as a list of floats where 
    429424        each float is between 0 and 1 and specifies where along the anchor 
    430425        path does the point lie (0 is at start 1 is at the end). 
    431426 
    432427        """ 
    433         return self.__pointPositions 
     428        return list(self.__pointPositions) 
    434429 
    435430    def shape(self): 
     
    448443        return QGraphicsPathItem.hoverLeaveEvent(self, event) 
    449444 
    450     def __scheduleDelayedLayout(self): 
    451         if not self.__layoutRequested: 
    452             self.__layoutRequested = True 
    453             QTimer.singleShot(0, self.__updatePositions) 
    454  
    455445    def __updatePositions(self): 
    456446        """Update anchor points positions. 
     
    459449            pos = self.__anchorPath.pointAtPercent(t) 
    460450            point.setPos(pos) 
    461  
    462         self.__layoutRequested = False 
    463451 
    464452 
     
    587575 
    588576 
    589 def linspace(count): 
    590     return map(float, numpy.linspace(0.0, 1.0, count + 2, endpoint=True)[1:-1]) 
    591  
    592  
    593577class NodeItem(QGraphicsObject): 
    594578    """An widget node item in the canvas. 
     
    840824 
    841825        anchor = AnchorPoint() 
    842         self.inputAnchorItem.addAnchor(anchor) 
    843  
    844         self.inputAnchorItem.setAnchorPositions( 
    845             linspace(self.inputAnchorItem.count()) 
    846         ) 
     826        self.inputAnchorItem.addAnchor(anchor, position=1.0) 
     827 
     828        positions = self.inputAnchorItem.anchorPositions() 
     829        positions = uniform_linear_layout(positions) 
     830        self.inputAnchorItem.setAnchorPositions(positions) 
    847831 
    848832        return anchor 
     
    853837        self.inputAnchorItem.removeAnchor(anchor) 
    854838 
    855         self.inputAnchorItem.setAnchorPositions( 
    856             linspace(self.inputAnchorItem.count()) 
    857         ) 
     839        positions = self.inputAnchorItem.anchorPositions() 
     840        positions = uniform_linear_layout(positions) 
     841        self.inputAnchorItem.setAnchorPositions(positions) 
    858842 
    859843    def newOutputAnchor(self): 
     
    864848 
    865849        anchor = AnchorPoint(self) 
    866         self.outputAnchorItem.addAnchor(anchor) 
    867  
    868         self.outputAnchorItem.setAnchorPositions( 
    869             linspace(self.outputAnchorItem.count()) 
    870         ) 
     850        self.outputAnchorItem.addAnchor(anchor, position=1.0) 
     851 
     852        positions = self.outputAnchorItem.anchorPositions() 
     853        positions = uniform_linear_layout(positions) 
     854        self.outputAnchorItem.setAnchorPositions(positions) 
    871855 
    872856        return anchor 
     
    877861        self.outputAnchorItem.removeAnchor(anchor) 
    878862 
    879         self.outputAnchorItem.setAnchorPositions( 
    880             linspace(self.outputAnchorItem.count()) 
    881         ) 
     863        positions = self.outputAnchorItem.anchorPositions() 
     864        positions = uniform_linear_layout(positions) 
     865        self.outputAnchorItem.setAnchorPositions(positions) 
    882866 
    883867    def inputAnchors(self): 
  • Orange/OrangeCanvas/canvas/items/utils.py

    r11203 r11207  
    9999 
    100100    return TypedSignalMapper 
     101 
     102 
     103def linspace(count): 
     104    """Return `count` evenly spaced points from 0..1 interval excluding 
     105    both end points, e.g. `linspace(3) == [0.25, 0.5, 0.75]`. 
     106 
     107    """ 
     108    return map(float, numpy.linspace(0.0, 1.0, count + 2, endpoint=True)[1:-1]) 
     109 
     110 
     111def uniform_linear_layout(points): 
     112    """Layout the points (a list of floats in 0..1 range) in a uniform 
     113    linear space while preserving the existing sorting order. 
     114 
     115    """ 
     116    indices = numpy.argsort(points) 
     117    space = numpy.asarray(linspace(len(points))) 
     118 
     119    # invert the indices 
     120    indices = invert_permutation_indices(indices) 
     121#    assert((numpy.argsort(points) == numpy.argsort(space[indices])).all()) 
     122    points = space[indices] 
     123 
     124    return points.tolist() 
     125 
     126 
     127def invert_permutation_indices(indices): 
     128    """Invert the permutation giver by indices. 
     129    """ 
     130    inverted = [0] * len(indices) 
     131    for i, index in enumerate(indices): 
     132        inverted[index] = i 
     133    return inverted 
  • Orange/OrangeCanvas/canvas/layout.py

    r11180 r11207  
    77import numpy 
    88 
     9import sip 
     10 
    911from PyQt4.QtGui import QGraphicsObject 
    1012from PyQt4.QtCore import QRectF, QLineF, QTimer 
    1113 
    1214from .items import NodeItem, LinkItem, SourceAnchorItem, SinkAnchorItem 
    13 from .items.nodeitem import linspace 
    14 from .items.utils import typed_signal_mapper 
     15from .items.utils import typed_signal_mapper, invert_permutation_indices, \ 
     16                         linspace 
    1517 
    1618LinkItemSignalMapper = typed_signal_mapper(LinkItem) 
     
    6466 
    6567        for anchor_item in anchors: 
     68            if sip.isdeleted(anchor_item): 
     69                continue 
     70 
    6671            points = anchor_item.anchorPoints() 
    6772            anchor_pos = anchor_item.mapToScene(anchor_item.pos()) 
     
    7782            indices = list(numpy.argsort(others_angle)) 
    7883            # Invert the indices. 
    79             indices = [indices.index(i) for i in range(len(indices))] 
     84            indices = invert_permutation_indices(indices) 
    8085 
    8186            positions = numpy.array(linspace(len(points))) 
  • Orange/OrangeCanvas/canvas/scene.py

    r11202 r11207  
    390390        """Remove a link (:class:`LinkItem`) from the scene. 
    391391        """ 
     392        # Invalidate the anchor layout. 
     393        self.__anchor_layout.invalidateAnchorItem( 
     394            item.sourceItem.outputAnchorItem 
     395        ) 
     396        self.__anchor_layout.invalidateAnchorItem( 
     397            item.sinkItem.inputAnchorItem 
     398        ) 
     399 
    392400        self.__link_items.remove(item) 
    393401 
     
    395403        item.removeLink() 
    396404        self.removeItem(item) 
     405 
    397406        self.link_item_removed.emit(item) 
    398407 
  • Orange/OrangeCanvas/preview/scanner.py

    r11189 r11207  
    8181    tmp_scene = scene.CanvasScene() 
    8282    tmp_scene.set_scheme(scheme) 
     83 
     84    # Force the anchor point layout. 
     85    tmp_scene.anchor_layout().activate() 
     86 
    8387    svg = scene.grab_svg(tmp_scene) 
    8488    tmp_scene.clear() 
Note: See TracChangeset for help on using the changeset viewer.