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

📄 mvctree.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 3 页
字号:
        self.editcomp.Bind(wx.EVT_KEY_UP, self._key)
        self.editcomp.Bind(wx.EVT_LEFT_DOWN, self._mdown)
        self.editcomp.CaptureMouse()

    def CanEdit(self, node):
        return isinstance(node, FileWrapper)

    def EndEdit(self, commit):
        if not self.tree._EditEnding(self.treenode.data):
            return
        if commit:
            node = self.treenode.data
            try:
                os.rename(node.path + os.sep + node.fileName, node.path + os.sep + self.editcomp.GetValue())
                node.fileName = self.editcomp.GetValue()
            except:
                traceback.print_exc()
        self.editcomp.ReleaseMouse()
        self.editcomp.Destroy()
        del self.editcomp
        self.tree.Refresh()


    def _key(self, evt):
        if evt.KeyCode() == wx.WXK_RETURN:
            self.EndEdit(True)
        elif evt.KeyCode() == wx.WXK_ESCAPE:
            self.EndEdit(False)
        else:
            evt.Skip()

    def _mdown(self, evt):
        if evt.IsButton():
            x, y = evt.GetPosition()
            w, h = self.editcomp.GetSize()
            if x < 0 or y < 0 or x > w or y > h:
                self.EndEdit(False)


class FileWrapper:
    """
    Node class for FSTreeModel.
    """
    def __init__(self, path, fileName):
        self.path = path
        self.fileName = fileName

    def __str__(self):
        return self.fileName

class FSTreeModel(BasicTreeModel):
    """
    This treemodel models the filesystem starting from a given path.
    """
    def __init__(self, path):
        BasicTreeModel.__init__(self)
        fw = FileWrapper(path, path.split(os.sep)[-1])
        self._Build(path, fw)
        self.SetRoot(fw)
        self._editable = True
    def _Build(self, path, fileWrapper):
        for name in os.listdir(path):
            fw = FileWrapper(path, name)
            self.AddChild(fileWrapper, fw)
            childName = path + os.sep + name
            if os.path.isdir(childName):
                self._Build(childName, fw)

    def IsEditable(self, node):
        return self._editable

    def SetEditable(self, node, bool):
        self._editable = bool

class LateFSTreeModel(FSTreeModel):
    """
    This treemodel models the filesystem starting from a given path.
    It retrieves the directory list as requested.
    """
    def __init__(self, path):
        BasicTreeModel.__init__(self)
        name = path.split(os.sep)[-1]
        pathpart = path[:-len(name)]
        fw = FileWrapper(pathpart, name)
        self._Build(path, fw)
        self.SetRoot(fw)
        self._editable = True
        self.children = {}
        self.parents = {}
    def _Build(self, path, parent):
        ppath = parent.path + os.sep + parent.fileName
        if not os.path.isdir(ppath):
            return
        for name in os.listdir(ppath):
            fw = FileWrapper(ppath, name)
            self.AddChild(parent, fw)
    def GetChildCount(self, node):
        if self.children.has_key(node):
            return FSTreeModel.GetChildCount(self, node)
        else:
            self._Build(node.path, node)
            return FSTreeModel.GetChildCount(self, node)

    def IsLeaf(self, node):
        return not os.path.isdir(node.path + os.sep + node.fileName)

class StrTextConverter(TextConverter):
    def Convert(self, node):
        return str(node.data)

class NullTransform(Transform):
    def GetSize(self):
        return tuple(self.size)

    def Transform(self, node, offset, rotation):
        self.size = [0,0]
        list = self.tree.GetLayoutEngine().GetNodeList()
        for node in list:
            node.projx = node.x + offset[0]
            node.projy = node.y + offset[1]
            if node.projx > self.size[0]:
                self.size[0] = node.projx
            if node.projy > self.size[1]:
                self.size[1] = node.projy

class Rect:
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
    def __getitem__(self, index):
        return (self.x, self.y, self.width, self.height)[index]

    def __setitem__(self, index, value):
        name = ['x', 'y', 'width', 'height'][index]
        setattr(self, name, value)

    def Contains(self, other):
        if type(other) == type(()):
            other = Rect(other[0], other[1], 0, 0)
        if other.x >= self.x:
            if other.y >= self.y:
                if other.width + other.x <= self.width + self.x:
                    if other.height + other.y  <= self.height + self.y:
                        return True
        return False

    def __str__(self):
        return "Rect: " + str([self.x, self.y, self.width, self.height])

class TreeLayout(LayoutEngine):
    def SetHeight(self, num):
        self.NODE_HEIGHT = num

    def __init__(self, tree):
        LayoutEngine.__init__(self, tree)
        self.NODE_STEP = 20
        self.NODE_HEIGHT = 20
        self.nodelist = []

    def Layout(self, node):
        self.nodelist = []
        self.NODE_HEIGHT = self.tree.GetFont().GetPointSize() * 2
        self.layoutwalk(node)

    def GetNodeList(self):
        return self.nodelist

    def layoutwalk(self, node):
        if node == self.tree.currentRoot:
            node.level = 1
            self.lastY = (-self.NODE_HEIGHT)
        node.x = self.NODE_STEP * node.level
        node.y = self.lastY + self.NODE_HEIGHT
        self.lastY = node.y
        self.nodelist.append(node)
        if node.expanded:
            for kid in node.kids:
                kid.level = node.level + 1
                self.layoutwalk(kid)

class TreePainter(Painter):
    """
    The default painter class. Uses double-buffering, delegates the painting of nodes and
    lines to helper classes deriving from NodePainter and LinePainter.
    """
    def __init__(self, tree, nodePainter = None, linePainter = None, textConverter = None):
        Painter.__init__(self, tree)
        if not nodePainter:
            nodePainter = TreeNodePainter(self)
        self.nodePainter = nodePainter
        if not linePainter:
            linePainter = TreeLinePainter(self)
        self.linePainter = linePainter
        if not textConverter:
            textConverter = StrTextConverter(self)
        self.textConverter = textConverter
        self.charWidths = []

    def Paint(self, dc, node, doubleBuffered=1, paintBackground=1):
        if not self.charWidths:
            self.charWidths = []
            for i in range(25):
                self.charWidths.append(dc.GetTextExtent("D")[0] * i)
            self.charHeight = dc.GetTextExtent("D")[1]
        self.textpen = wx.Pen(self.GetTextColour(), 1, wx.SOLID)
        self.fgpen = wx.Pen(self.GetForegroundColour(), 1, wx.SOLID)
        self.bgpen = wx.Pen(self.GetBackgroundColour(), 1, wx.SOLID)
        self.linepen = wx.Pen(self.GetLineColour(), 1, wx.SOLID)
        self.dashpen = wx.Pen(self.GetLineColour(), 1, wx.DOT)
        self.textbrush = wx.Brush(self.GetTextColour(), wx.SOLID)
        self.fgbrush = wx.Brush(self.GetForegroundColour(), wx.SOLID)
        self.bgbrush = wx.Brush(self.GetBackgroundColour(), wx.SOLID)
        self.linebrush = wx.Pen(self.GetLineColour(), 1, wx.SOLID)
        treesize = self.tree.GetSize()
        size = self.tree.transform.GetSize()
        size = (max(treesize.width, size[0]+50), max(treesize.height, size[1]+50))
        dc.BeginDrawing()
        if doubleBuffered:
            mem_dc = wx.MemoryDC()
            if not self.GetBuffer():
                self.knobs = []
                self.rectangles = []
                self.bmp = wx.EmptyBitmap(size[0], size[1])
                mem_dc.SelectObject(self.GetBuffer())
                mem_dc.SetPen(self.GetBackgroundPen())
                mem_dc.SetBrush(self.GetBackgroundBrush())
                mem_dc.DrawRectangle(0, 0, size[0], size[1])
                mem_dc.SetFont(self.tree.GetFont())
                self.paintWalk(node, mem_dc)
            else:
                mem_dc.SelectObject(self.GetBuffer())
            xstart, ystart = self.tree.CalcUnscrolledPosition(0,0)
            size = self.tree.GetClientSizeTuple()
            dc.Blit(xstart, ystart, size[0], size[1], mem_dc, xstart, ystart)
        else:
            if node == self.tree.currentRoot:
                self.knobs = []
                self.rectangles = []
            dc.SetPen(self.GetBackgroundPen())
            dc.SetBrush(self.GetBackgroundBrush())
            dc.SetFont(self.tree.GetFont())
            if paintBackground:
                dc.DrawRectangle(0, 0, size[0], size[1])
            if node:
                #Call with not paintBackground because if we are told not to paint the
                #whole background, we have to paint in parts to undo selection coloring.
                pb = paintBackground
                self.paintWalk(node, dc, not pb)
        dc.EndDrawing()

    def GetDashPen(self):
        return self.dashpen

    def SetLinePen(self, pen):
        Painter.SetLinePen(self, pen)
        self.dashpen = wx.Pen(pen.GetColour(), 1, wx.DOT)

    def paintWalk(self, node, dc, paintRects=0):
        self.linePainter.Paint(node.parent, node, dc)
        self.nodePainter.Paint(node, dc, drawRects = paintRects)
        if node.expanded:
            for kid in node.kids:
                if not self.paintWalk(kid, dc, paintRects):
                    return False
            for kid in node.kids:
                px = (kid.projx - self.tree.layout.NODE_STEP) + 5
                py = kid.projy + kid.height/2
                if (not self.tree.model.IsLeaf(kid.data)) or ((kid.expanded or self.tree._assumeChildren) and len(kid.kids)):
                    dc.SetPen(self.linepen)
                    dc.SetBrush(self.bgbrush)
                    dc.DrawRectangle(px -4, py-4, 9, 9)
                    self.knobs.append( (kid, Rect(px -4, py -4, 9, 9)) )
                    dc.SetPen(self.textpen)
                    if not kid.expanded:
                        dc.DrawLine(px, py -2, px, py + 3)
                    dc.DrawLine(px -2, py, px + 3, py)
        if node == self.tree.currentRoot:
            px = (node.projx - self.tree.layout.NODE_STEP) + 5
            py = node.projy + node.height/2
            dc.SetPen(self.linepen)
            dc.SetBrush(self.bgbrush)
            dc.DrawRectangle(px -4, py-4, 9, 9)
            self.knobs.append( (node, Rect(px -4, py -4, 9, 9)) )
            dc.SetPen(self.textpen)
            if not node.expanded:
                dc.DrawLine(px, py -2, px, py + 3)
            dc.DrawLine(px -2, py, px + 3, py)
        return True

    def OnMouse(self, evt):
        Painter.OnMouse(self, evt)

class TreeNodePainter(NodePainter):
    def Paint(self, node, dc, location = None, drawRects = 0):
        text = self.painter.textConverter.Convert(node)
        extent = dc.GetTextExtent(text)
        node.width = extent[0]
        node.height = extent[1]
        if node.selected:
            dc.SetPen(self.painter.GetLinePen())
            dc.SetBrush(self.painter.GetForegroundBrush())
            dc.SetTextForeground(wx.NamedColour("WHITE"))
            dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
        else:
            if drawRects:
                dc.SetBrush(self.painter.GetBackgroundBrush())
                dc.SetPen(self.painter.GetBackgroundPen())
                dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
            dc.SetTextForeground(self.painter.GetTextColour())
        dc.DrawText(text, node.projx, node.projy)
        self.painter.rectangles.append((node, Rect(node.projx, node.projy, node.width, node.height)))

class TreeLinePainter(LinePainter):
    def Paint(self, parent, child, dc):
        dc.SetPen(self.painter.GetDashPen())
        px = py = cx = cy = 0
        if parent is None or child == self.painter.tree.currentRoot:
            px = (child.projx - self.painter.tree.layout.NODE_STEP) + 5
            py = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -2
            cx = child.projx
            cy = py
            dc.DrawLine(px, py, cx, cy)
        else:
            px = parent.projx + 5
            py = parent.projy + parent.height
            cx = child.projx -5
            cy = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -3
            dc.DrawLine(px, py, px, cy)
            dc.DrawLine(px, cy, cx, cy)

#>> Event defs
wxEVT_MVCTREE_BEGIN_EDIT = wx.NewEventType() #Start editing. Vetoable.
wxEVT_MVCTREE_END_EDIT = wx.NewEventType() #Stop editing. Vetoable.
wxEVT_MVCTREE_DELETE_ITEM = wx.NewEventType() #Item removed from model.
wxEVT_MVCTREE_ITEM_EXPANDED = wx.NewEventType()
wxEVT_MVCTREE_ITEM_EXPANDING = wx.NewEventType()
wxEVT_MVCTREE_ITEM_COLLAPSED = wx.NewEventType()
wxEVT_MVCTREE_ITEM_COLLAPSING = wx.NewEventType()
wxEVT_MVCTREE_SEL_CHANGED = wx.NewEventType()
wxEVT_MVCTREE_SEL_CHANGING = wx.NewEventType() #Vetoable.
wxEVT_MVCTREE_KEY_DOWN = wx.NewEventType()
wxEVT_MVCTREE_ADD_ITEM = wx.NewEventType() #Item added to model.

EVT_MVCTREE_SEL_CHANGED = wx.PyEventBinder(wxEVT_MVCTREE_SEL_CHANGED, 1)
EVT_MVCTREE_SEL_CHANGING = wx.PyEventBinder(wxEVT_MVCTREE_SEL_CHANGING, 1)
EVT_MVCTREE_ITEM_EXPANDED = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_EXPANDED, 1)
EVT_MVCTREE_ITEM_EXPANDING = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_EXPANDING, 1)
EVT_MVCTREE_ITEM_COLLAPSED = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_COLLAPSED, 1)
EVT_MVCTREE_ITEM_COLLAPSING = wx.PyEventBinder(wxEVT_MVCTREE_ITEM_COLLAPSING, 1)
EVT_MVCTREE_ADD_ITEM = wx.PyEventBinder(wxEVT_MVCTREE_ADD_ITEM, 1)
EVT_MVCTREE_DELETE_ITEM = wx.PyEventBinder(wxEVT_MVCTREE_DELETE_ITEM, 1)
EVT_MVCTREE_KEY_DOWN = wx.PyEventBinder(wxEVT_MVCTREE_KEY_DOWN, 1)

class MVCTreeEvent(wx.PyCommandEvent):
    def __init__(self, type, id, node = None, nodes = None, keyEvent = None, **kwargs):
        apply(wx.PyCommandEvent.__init__, (self, type, id), kwargs)
        self.node = node
        self.nodes = nodes
        self.keyEvent = keyEvent
    def GetNode(self):
        return self.node
    def GetNodes(self):
        return self.nodes
    def getKeyEvent(self):
        return self.keyEvent

class MVCTreeNotifyEvent(MVCTreeEvent):
    def __init__(self, type, id, node = None, nodes = None, **kwargs):
        apply(MVCTreeEvent.__init__, (self, type, id, node, nodes), kwargs)
        self.notify = wx.NotifyEvent(type, id)
    def getNotifyEvent(self):
        return self.notify

class MVCTree(wx.ScrolledWindow):
    """
    The main mvc tree class.
    """
    def __init__(self, parent, id, model = None, layout = None, transform = None,
                 painter = None, *args, **kwargs):
        apply(wx.ScrolledWindow.__init__, (self, parent, id), kwargs)

⌨️ 快捷键说明

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