⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pysketch.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
        self.toolsMenu.Check(menu_LINE,    self.curTool == self.lineIcon)
        self.toolsMenu.Check(menu_RECT,    self.curTool == self.rectIcon)
        self.toolsMenu.Check(menu_ELLIPSE, self.curTool == self.ellipseIcon)
        self.toolsMenu.Check(menu_TEXT,    self.curTool == self.textIcon)

        self.objectMenu.Enable(menu_MOVE_FORWARD,  onlyOne and not front)
        self.objectMenu.Enable(menu_MOVE_TO_FRONT, onlyOne and not front)
        self.objectMenu.Enable(menu_MOVE_BACKWARD, onlyOne and not back)
        self.objectMenu.Enable(menu_MOVE_TO_BACK,  onlyOne and not back)

        # Enable/disable our toolbar icons.

        self.toolbar.EnableTool(wx.ID_NEW,           True)
        self.toolbar.EnableTool(wx.ID_OPEN,          True)
        self.toolbar.EnableTool(wx.ID_SAVE,          canSave)
        self.toolbar.EnableTool(menu_UNDO,          canUndo)
        self.toolbar.EnableTool(menu_DUPLICATE,     selection)
        self.toolbar.EnableTool(menu_MOVE_FORWARD,  onlyOne and not front)
        self.toolbar.EnableTool(menu_MOVE_BACKWARD, onlyOne and not back)


    def _setCurrentTool(self, newToolIcon):
        """ Set the currently selected tool.
        """
        if self.curTool == newToolIcon: return # Nothing to do.

        if self.curTool != None:
            self.curTool.deselect()

        newToolIcon.select()
        self.curTool = newToolIcon


    def _setPenColour(self, colour):
        """ Set the default or selected object's pen colour.
        """
        if len(self.selection) > 0:
            self._saveUndoInfo()
            for obj in self.selection:
                obj.setPenColour(colour)
            self.drawPanel.Refresh()
        else:
            self.penColour = colour
            self.optionIndicator.setPenColour(colour)


    def _setFillColour(self, colour):
        """ Set the default or selected object's fill colour.
        """
        if len(self.selection) > 0:
            self._saveUndoInfo()
            for obj in self.selection:
                obj.setFillColour(colour)
            self.drawPanel.Refresh()
        else:
            self.fillColour = colour
            self.optionIndicator.setFillColour(colour)


    def _setLineSize(self, size):
        """ Set the default or selected object's line size.
        """
        if len(self.selection) > 0:
            self._saveUndoInfo()
            for obj in self.selection:
                obj.setLineSize(size)
            self.drawPanel.Refresh()
        else:
            self.lineSize = size
            self.optionIndicator.setLineSize(size)


    def _saveUndoInfo(self):
        """ Remember the current state of the document, to allow for undo.

            We make a copy of the document's contents, so that we can return to
            the previous contents if the user does something and then wants to
            undo the operation.
        """
        savedContents = []
        for obj in self.contents:
            savedContents.append([obj.getType(), obj.getData()])

        savedSelection = []
        for i in range(len(self.contents)):
            if self.contents[i] in self.selection:
                savedSelection.append(i)

        self.undoInfo = {"contents"  : savedContents,
                         "selection" : savedSelection}


    def _resizeObject(self, obj, anchorPt, oldPt, newPt):
        """ Resize the given object.

            'anchorPt' is the unchanging corner of the object, while the
            opposite corner has been resized.  'oldPt' are the current
            coordinates for this corner, while 'newPt' are the new coordinates.
            The object should fit within the given dimensions, though if the
            new point is less than the anchor point the object will need to be
            moved as well as resized, to avoid giving it a negative size.
        """
        if obj.getType() == obj_TEXT:
            # Not allowed to resize text objects -- they're sized to fit text.
            wx.Bell(); print "4"
            return

        self._saveUndoInfo()

        topLeft  = wx.Point(min(anchorPt.x, newPt.x),
                           min(anchorPt.y, newPt.y))
        botRight = wx.Point(max(anchorPt.x, newPt.x),
                           max(anchorPt.y, newPt.y))

        newWidth  = botRight.x - topLeft.x
        newHeight = botRight.y - topLeft.y

        if obj.getType() == obj_LINE:
            # Adjust the line so that its start and end points match the new
            # overall object size.

            startPt = obj.getStartPt()
            endPt   = obj.getEndPt()

            slopesDown = ((startPt.x < endPt.x) and (startPt.y < endPt.y)) or \
                         ((startPt.x > endPt.x) and (startPt.y > endPt.y))

            # Handle the user flipping the line.

            hFlip = ((anchorPt.x < oldPt.x) and (anchorPt.x > newPt.x)) or \
                    ((anchorPt.x > oldPt.x) and (anchorPt.x < newPt.x))
            vFlip = ((anchorPt.y < oldPt.y) and (anchorPt.y > newPt.y)) or \
                    ((anchorPt.y > oldPt.y) and (anchorPt.y < newPt.y))

            if (hFlip and not vFlip) or (vFlip and not hFlip):
                slopesDown = not slopesDown # Line flipped.

            if slopesDown:
                obj.setStartPt(wx.Point(0, 0))
                obj.setEndPt(wx.Point(newWidth, newHeight))
            else:
                obj.setStartPt(wx.Point(0, newHeight))
                obj.setEndPt(wx.Point(newWidth, 0))

        # Finally, adjust the bounds of the object to match the new dimensions.

        obj.setPosition(topLeft)
        obj.setSize(wx.Size(botRight.x - topLeft.x, botRight.y - topLeft.y))

        self.drawPanel.Refresh()


    def _moveObject(self, offsetX, offsetY):
        """ Move the currently selected object(s) by the given offset.
        """
        self._saveUndoInfo()

        for obj in self.selection:
            pos = obj.getPosition()
            pos.x = pos.x + offsetX
            pos.y = pos.y + offsetY
            obj.setPosition(pos)

        self.drawPanel.Refresh()


    def _buildLineSizePopup(self, lineSize):
        """ Build the pop-up menu used to set the line size.

            'lineSize' is the current line size value.  The corresponding item
            is checked in the pop-up menu.
        """
        menu = wx.Menu()
        menu.Append(id_LINESIZE_0, "no line",      kind=wx.ITEM_CHECK)
        menu.Append(id_LINESIZE_1, "1-pixel line", kind=wx.ITEM_CHECK)
        menu.Append(id_LINESIZE_2, "2-pixel line", kind=wx.ITEM_CHECK)
        menu.Append(id_LINESIZE_3, "3-pixel line", kind=wx.ITEM_CHECK)
        menu.Append(id_LINESIZE_4, "4-pixel line", kind=wx.ITEM_CHECK)
        menu.Append(id_LINESIZE_5, "5-pixel line", kind=wx.ITEM_CHECK)

        if   lineSize == 0: menu.Check(id_LINESIZE_0, True)
        elif lineSize == 1: menu.Check(id_LINESIZE_1, True)
        elif lineSize == 2: menu.Check(id_LINESIZE_2, True)
        elif lineSize == 3: menu.Check(id_LINESIZE_3, True)
        elif lineSize == 4: menu.Check(id_LINESIZE_4, True)
        elif lineSize == 5: menu.Check(id_LINESIZE_5, True)

        self.Bind(wx.EVT_MENU, self._lineSizePopupSelected, id=id_LINESIZE_0, id2=id_LINESIZE_5)

        return menu


    def _lineSizePopupSelected(self, event):
        """ Respond to the user selecting an item from the line size popup menu
        """
        id = event.GetId()
        if   id == id_LINESIZE_0: self._setLineSize(0)
        elif id == id_LINESIZE_1: self._setLineSize(1)
        elif id == id_LINESIZE_2: self._setLineSize(2)
        elif id == id_LINESIZE_3: self._setLineSize(3)
        elif id == id_LINESIZE_4: self._setLineSize(4)
        elif id == id_LINESIZE_5: self._setLineSize(5)
        else:
            wx.Bell(); print "5"
            return

        self.optionIndicator.setLineSize(self.lineSize)


    def _getEventCoordinates(self, event):
        """ Return the coordinates associated with the given mouse event.

            The coordinates have to be adjusted to allow for the current scroll
            position.
        """
        originX, originY = self.drawPanel.GetViewStart()
        unitX, unitY = self.drawPanel.GetScrollPixelsPerUnit()
        return wx.Point(event.GetX() + (originX * unitX),
                       event.GetY() + (originY * unitY))


    def _getObjectAndSelectionHandleAt(self, pt):
        """ Return the object and selection handle at the given point.

            We draw selection handles (small rectangles) around the currently
            selected object(s).  If the given point is within one of the
            selection handle rectangles, we return the associated object and a
            code indicating which selection handle the point is in.  If the
            point isn't within any selection handle at all, we return the tuple
            (None, handle_NONE).
        """
        for obj in self.selection:
            handle = obj.getSelectionHandleContainingPoint(pt.x, pt.y)
            if handle != handle_NONE:
                return obj, handle

        return None, handle_NONE


    def _getObjectAt(self, pt):
        """ Return the first object found which is at the given point.
        """
        for obj in self.contents:
            if obj.objectContainsPoint(pt.x, pt.y):
                return obj
        return None


    def _drawObjectOutline(self, offsetX, offsetY):
        """ Draw an outline of the currently selected object.

            The selected object's outline is drawn at the object's position
            plus the given offset.

            Note that the outline is drawn by *inverting* the window's
            contents, so calling _drawObjectOutline twice in succession will
            restore the window's contents back to what they were previously.
        """
        if len(self.selection) != 1: return

        position = self.selection[0].getPosition()
        size     = self.selection[0].getSize()

        dc = wx.ClientDC(self.drawPanel)
        self.drawPanel.PrepareDC(dc)
        dc.BeginDrawing()
        dc.SetPen(wx.BLACK_DASHED_PEN)
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)

        dc.DrawRectangle(position.x + offsetX, position.y + offsetY,
                         size.width, size.height)

        dc.EndDrawing()


    def _drawVisualFeedback(self, startPt, endPt, type, dashedLine):
        """ Draw visual feedback for a drawing operation.

            The visual feedback consists of a line, ellipse, or rectangle based
            around the two given points.  'type' should be one of the following
            predefined feedback type constants:

                feedback_RECT     ->  draw rectangular feedback.
                feedback_LINE     ->  draw line feedback.
                feedback_ELLIPSE  ->  draw elliptical feedback.

            if 'dashedLine' is True, the feedback is drawn as a dashed rather
            than a solid line.

            Note that the feedback is drawn by *inverting* the window's
            contents, so calling _drawVisualFeedback twice in succession will
            restore the window's contents back to what they were previously.
        """
        dc = wx.ClientDC(self.drawPanel)
        self.drawPanel.PrepareDC(dc)
        dc.BeginDrawing()
        if dashedLine:
            dc.SetPen(wx.BLACK_DASHED_PEN)
        else:
            dc.SetPen(wx.BLACK_PEN)
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)

        if type == feedback_RECT:
            dc.DrawRectangle(startPt.x, startPt.y,
                             endPt.x - startPt.x,
                             endPt.y - startPt.y)
        elif type == feedback_LINE:
            dc.DrawLine(startPt.x, startPt.y, endPt.x, endPt.y)
        elif type == feedback_ELLIPSE:
            dc.DrawEllipse(startPt.x, startPt.y,
                           endPt.x - startPt.x,
                           endPt.y - startPt.y)

        dc.EndDrawing()

#----------------------------------------------------------------------------

class DrawingObject:
    """ An object within the drawing panel.

        A pySketch document consists of a front-to-back ordered list of
        DrawingObjects.  Each DrawingObject has the following properties:

            'type'          What type of object this is (text, line, etc).
            'position'      The position of the object within the document.
            'size'          The size of the object within the document.
            'penColour'     The colour to use for drawing the object's outline.
            'fillColour'    Colour to use for drawing object's interior.
            'lineSize'      Line width (in pixels) to use for object's outline.
            'startPt'       The point, relative to the object's position, where
                            an obj_LINE object's line should start.
            'endPt'         The point, relative to the object's position, where
                            an obj_LINE object's line should end.
            'text'          The object's text (obj_TEXT objects only).
            'textFont'      The text object's font name.
            'textSize'      The text object's point size.
            'textBoldface'  If True, this text object will be drawn in
                            boldface.
            'textItalic'    If True, this text object will be drawn in italic.
            'textUnderline' If True, this text object will be drawn underlined.
            """

    # ==================
    # == Constructors ==
    # ==================

    def __init__(self, type, position=wx.Point(0, 0), size=wx.Size(0, 0),
                 penColour=wx.BLACK, fillColour=wx.WHITE, lineSize=1,
                 text=None, startPt=wx.Point(0, 0), endPt=wx.Point(0,0)):
        """ Standard constructor.

            '

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -