Пример #1
0
    def test_conversion(self):

        a = Pos(10, 15)
        b = Pos(12, 21)

        tmp = a.grid_cr()
        self.assertEquals(tmp.x, 1)
        self.assertEquals(tmp.y, 0)

        tmp = a.view_xy()
        self.assertEquals(tmp.x, 100)
        self.assertEquals(tmp.y, 240)

        a.snap_to_grid()
        self.assertEquals(a.x, 10)
        self.assertEquals(a.y, 0)

        b = Pos(10, 16)

        tmp = b.grid_cr()
        self.assertEquals(tmp.x, 1)
        self.assertEquals(tmp.y, 1)

        tmp = b.view_xy()
        self.assertEquals(tmp.x, 100)
        self.assertEquals(tmp.y, 256)

        b.snap_to_grid()
        self.assertEquals(b.x, 10)
        self.assertEquals(b.y, 16)

        c = Pos(11, 17)

        tmp = c.grid_cr()
        self.assertEquals(tmp.x, 1)
        self.assertEquals(tmp.y, 1)

        tmp = c.view_xy()
        self.assertEquals(tmp.x, 110)
        self.assertEquals(tmp.y, 272)

        c.snap_to_grid()
        self.assertEquals(c.x, 10)
        self.assertEquals(c.y, 16)
Пример #2
0
class Symbol(object):
    """
    Symbol represented by a grid.

    :param id: the component id
    :param dict: the character-grid to create the symbol
    :param ori: orientation (0-3)
    :param mirrored: set to 1 to mirror the symbol vertically
    :param startpos: the upper-left corner (col,row) coordinate of the character-grid
    :param endpos: used in subclasses, e.g. Line
    """

    ORIENTATION = {0: "N", 1: "E", 2: "S", 3: "W"}

    def __init__(self,
                 id=0,
                 grid=None,
                 ori=None,
                 mirrored=None,
                 startpos=None,
                 endpos=None):
        self._id = id
        self._has_pickpoint = True
        if ori is None:
            self._ori = 0
        else:
            self._ori = ori
        if mirrored is None:
            self._mirrored = 0
        else:
            self._mirrored = mirrored
        if grid is None:
            self._grid = self.default
        else:
            self._grid = grid
        if startpos is None:
            self._startpos = Pos(0, 0)
        else:
            self._startpos = startpos
        if endpos is None:
            self._endpos = Pos(0, 0)
        else:
            self._endpos = endpos
        self._is_symbol = True
        self._is_text = False
        self._is_line = False

    def __str__(self):
        str = _("Class: {0} id: {1} ori: {2} startpos: {3}").format(
            self.__class__.__name__, self._id, self.ORIENTATION[self._ori],
            self.startpos)
        return str

    def _representation(self):
        self._repr = dict()
        pos = self._startpos
        incr = Pos(1, 0)
        for row in self.grid:
            pos.x = self._startpos.x
            for char in row:
                if char != ' ':
                    self._repr[pos] = char
                pos += incr
            pos += Pos(0, 1)

    @property
    def name(self):
        return self.__class__.__name__

    @property
    def is_symbol(self):
        return self._is_symbol

    @property
    def is_text(self):
        return self._is_text

    @property
    def is_line(self):
        return self._is_line

    @property
    def has_pickpoint(self):
        return self._has_pickpoint

    @property
    def pickpoint_pos(self):
        """
        Return the pick position.

        Examples, where '.' represents a space character and 'x' the pick-point:
        '.|.....' => 'x|.....'
        '....|..' => '...x|..'
        '|......' => 'x|......'
        '.......' => '.......x' => empty first line not expected, see the component library content

        """
        first_row = self.grid[0]
        found = re.search(r'\S', first_row)
        if found:
            x_offset = found.start()
            x_offset -= 1
        else:
            x_offset = 0
        pos = Pos(self._startpos.x + x_offset, self._startpos.y)
        return pos

    @property
    def id(self):
        return self._id

    @property
    def ori_as_str(self):
        return Symbol.ORIENTATION[self._ori]

    @property
    def ori(self):
        return self._ori

    @ori.setter
    def ori(self, value):
        # orientation can be set as the grid is dynamically selected (in grid() method)
        if value in (0, 1, 2, 3):
            self._ori = value

    @property
    def mirrored(self):
        return self._mirrored

    @mirrored.setter
    def mirrored(self, value):
        """Set to True to show the symbol vertically mirrored, otherwise False."""
        self._mirrored = value

    @property
    def startpos(self):
        return self._startpos

    @startpos.setter
    def startpos(self, value):
        self._startpos = value

    @property
    def endpos(self):
        return self._endpos

    @endpos.setter
    def endpos(self, value):
        self._endpos = value

    @property
    def default(self):
        # default provides one ("N" orientation) grid only
        grid = {'N': [' ___ ', '|__ \\', '  / /', ' |_| ', ' (_) ']}
        return grid

    @property
    def repr(self):
        """
        The representation in ASCII characters of the symbol on a grid.
        :returns a dictionary of positions in grid (col,row) coordinates and the character to be shown on each position.
        """
        return self._repr

    def memo(self):
        """Return entry for the actions as recorded in the memo."""
        str = "{0}:{1},{2},{3},{4}".format(COMPONENT, self._id, self._ori,
                                           self._mirrored, self._startpos)
        return str

    def copy(self):
        ori = copy.deepcopy(self._ori)
        mirrored = copy.deepcopy(self._mirrored)
        startpos = copy.deepcopy(self._startpos)
        endpos = copy.deepcopy(self._endpos)
        return Symbol(id=self._id,
                      grid=self._grid,
                      ori=ori,
                      mirrored=mirrored,
                      startpos=startpos,
                      endpos=endpos)

    @property
    def grid(self):
        try:
            if self._mirrored == 1:
                return self.mirror(self._grid[self.ORIENTATION[self._ori]])
            else:
                return self._grid[self.ORIENTATION[self._ori]]
        except KeyError:
            return self.default[self.ORIENTATION[0]]

    def rotate(self):
        """Return the grid with the next (90 degrees clockwise rotated) orientation for this symbol."""
        self._ori += 1
        self._ori %= 4

        return self.grid

    def draw(self, ctx, pos=None):
        """
        Draw the symbol on the grid canvas.
        :param ctx: the Cairo context
        :param pos: target position in grid canvas (x,y) coordinates
        """
        self._representation()
        if pos is None:
            pos = self._startpos.view_xy()
        offset = pos - self._startpos.view_xy()
        for pos, char in self._repr.items():
            grid_pos = pos.view_xy() + offset
            show_text(ctx, grid_pos.x, grid_pos.y, char)

    def paste(self, grid):
        """Paste the symbol in the target grid at its start position."""
        self._representation()
        for pos, value in self._repr.items():
            grid.set_cell(pos, value)

    def remove(self, grid):
        """Remove the symbol from the target grid."""
        self._representation()
        for pos in self._repr.keys():
            grid.set_cell(pos, CELL_ERASE)

    def mirror(self, grid):
        """Return the symbol grid vertically mirrored."""
        # mirror specific characters
        switcher = {
            '/': '\\',
            '\\': '/',
            '<': '>',
            '>': '<',
            '(': ')',
            ')': '('
        }
        mir_grid = []
        for r, row in enumerate(grid):
            rev = ""
            for c in reversed(row):
                try:
                    rev += switcher[c]
                except KeyError:
                    rev += c
            mir_grid.append(rev)
        return mir_grid