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

📄 foldpanelbar.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
        elif event.Entering() and self._foldIcons:
            pt = event.GetPosition()
            rect = self.GetRect()

            drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
            if vertical and pt.x > drw or not vertical and \
               pt.y < (self._iconHeight + self._rightIndent):
                self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
            else:
                self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))

        elif event.Leaving():
            self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))

        elif event.Moving():
            pt = event.GetPosition()
            rect = self.GetRect()

            drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)           
            if vertical and pt.x > drw or not vertical and \
               pt.y < (self._iconHeight + self._rightIndent):
                self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
            else:
                self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
                
        # send the collapse, expand event to the parent
        
        if send_event:
            event = CaptionBarEvent(wxEVT_CAPTIONBAR)
            event.SetId(self.GetId())
            event.SetEventObject(self)
            event.SetBar(self)
            self.GetEventHandler().ProcessEvent(event)
        

    def OnChar(self, event):
        """ Unused Methods. Any Ideas?!?"""
        # TODO: Anything here?
        event.Skip()


    def DoGetBestSize(self):
        """
        Returns the best size for this panel, based upon the font
        assigned to this window, and the caption string
        """
        
        if self.IsVertical():
            x, y = self.GetTextExtent(self._caption)
        else:
            y, x = self.GetTextExtent(self._caption)

        if x < self._iconWidth:
            x = self._iconWidth

        if y < self._iconHeight:
            y = self._iconHeight

        # TODO: The extra FPB_EXTRA_X constants should be adjustable as well

        return wx.Size(x + FPB_EXTRA_X, y + FPB_EXTRA_Y)


    def DrawVerticalGradient(self, dc, rect):
        """ Gradient fill from colour 1 to colour 2 with top to bottom. """

        if  rect.height < 1 or rect.width < 1:
            return

        dc.SetPen(wx.TRANSPARENT_PEN)

        # calculate gradient coefficients
        col2 = self._style.GetSecondColour()
        col1 = self._style.GetFirstColour()

        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())

        flrect = float(rect.height)

        rstep = float((r2 - r1)) / flrect
        gstep = float((g2 - g1)) / flrect
        bstep = float((b2 - b1)) / flrect

        rf, gf, bf = 0, 0, 0

        for y in range(rect.y, rect.y + rect.height):
            currCol = (r1 + rf, g1 + gf, b1 + bf)
                
            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
            dc.DrawRectangle(rect.x, rect.y + (y - rect.y), rect.width, rect.height)
            rf = rf + rstep
            gf = gf + gstep
            bf = bf + bstep


    def DrawHorizontalGradient(self, dc, rect):
        """ Gradient fill from colour 1 to colour 2 with left to right. """

        if rect.height < 1 or rect.width < 1:
            return

        dc.SetPen(wx.TRANSPARENT_PEN)

        # calculate gradient coefficients
        col2 = self._style.GetSecondColour()
        col1 = self._style.GetFirstColour()

        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())

        flrect = float(rect.width)

        rstep = float((r2 - r1)) / flrect
        gstep = float((g2 - g1)) / flrect
        bstep = float((b2 - b1)) / flrect

        rf, gf, bf = 0, 0, 0
        
        for x in range(rect.x, rect.x + rect.width):
            currCol = (r1 + rf, g1 + gf, b1 + bf)
                
            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
            dc.DrawRectangle(rect.x + (x - rect.x), rect.y, 1, rect.height)
            rf = rf + rstep
            gf = gf + gstep
            bf = bf + bstep


    def DrawSingleColour(self, dc, rect):
        """ Single colour fill. This is the most easy one to find. """

        if rect.height < 1 or rect.width < 1:
            return

        dc.SetPen(wx.TRANSPARENT_PEN)

        # draw simple rectangle
        dc.SetBrush(wx.Brush(self._style.GetFirstColour(), wx.SOLID))
        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
        

    def DrawSingleRectangle(self, dc, rect):
        """ Single rectangle. This is the most easy one to find. """
        
        if rect.height < 2 or rect.width < 1:
            return

        # single frame, set up internal fill colour

        if self._style.GetCaptionStyle() == CAPTIONBAR_RECTANGLE:
            color = self.GetParent().GetBackgroundColour()
            br = wx.Brush(color, wx.SOLID)
        else:
            color = self._style.GetFirstColour()
            br = wx.Brush(color, wx.SOLID)

        # setup the pen frame

        pen = wx.Pen(self._style.GetSecondColour())
        dc.SetPen(pen)
        dc.SetBrush(br)
        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height - 1)

        bgpen = wx.Pen(self.GetParent().GetBackgroundColour())
        dc.SetPen(bgpen)
        dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width,
                    rect.y + rect.height - 1)


    def OnSize(self, event):
        """ Handles the size events for the CaptionBar."""

        if not self._controlCreated:
            event.Skip()
            return
        
        size = event.GetSize()

        if self._foldIcons:

            # What I am doing here is simply invalidating the part of the window
            # exposed. So when I make a rect with as width the newly exposed part,
            # and the x,y of the old window size origin, I don't need a bitmap
            # calculation in it, or do I ? The bitmap needs redrawing anyway. 
            # Leave it like this until I figured it out.

            # set rect to redraw as old bitmap area which is entitled to redraw

            rect = wx.Rect(size.GetWidth() - self._iconWidth - self._rightIndent, 0,
                           self._iconWidth + self._rightIndent,
                           self._iconWidth + self._rightIndent)
            
            # adjust rectangle when more is slided so we need to redraw all
            # the old stuff but not all (ugly flickering)

            diffX = size.GetWidth() - self._oldSize.GetWidth()
            
            if diffX > 1:
                
                # adjust the rect with all the crap to redraw

                rect.SetWidth(rect.GetWidth() + diffX + 10)
                rect.SetX(rect.GetX() - diffX - 10)

            self.RefreshRect(rect)
            
        else:
            
            rect = self.GetRect()
            self.RefreshRect(rect)

        self._oldSize = size
        

    def RedrawIconBitmap(self):
        """ Redraws the icons (if they exists). """

        if self._foldIcons:
        
            # invalidate the bitmap area and force a redraw

            rect = self.GetRect()

            rect.SetX(rect.GetWidth() - self._iconWidth - self._rightIndent)
            rect.SetWidth(self._iconWidth + self._rightIndent)
            self.RefreshRect(rect)


# ---------------------------------------------------------------------------------- #
# class FoldPanelBar
# ---------------------------------------------------------------------------------- #

class FoldPanelBar(wx.Panel):
    """
    The FoldPanelBar is a class which can maintain a list of
    collapsable panels.  Once a panel is collapsed, only it's caption
    bar is visible to the user. This will provide more space for the
    other panels, or allow the user to close panels which are not used
    often to get the most out of the work area.

    This control is easy to use. Simply create it as a child for a
    panel or sash window, and populate panels with
    `AddFoldPanel`. Then use the `AddFoldPanelWindow` to add
    `wx.Window` derived controls to the current fold panel. Use
    `AddFoldPanelSeparator` to put separators between the groups of
    controls that need a visual separator to group them
    together. After all is constructed, the user can fold the panels
    by doubleclicking on the bar or single click on the arrow, which
    will indicate the collapsed or expanded state.
    """
    # Define Empty CaptionBar Style
    EmptyCaptionBarStyle = CaptionBarStyle()
    
    def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=FPB_DEFAULT_STYLE, extraStyle=FPB_DEFAULT_EXTRASTYLE): 
        """ Default Class Constructor. """
        
        self._controlCreated = False
        self._extraStyle = extraStyle
        
        # make sure there is any orientation
        if style & FPB_HORIZONTAL != FPB_HORIZONTAL:
            style = style | FPB_VERTICAL

        if style & FPB_HORIZONTAL == 4:
            self._isVertical = False
        else:
            self._isVertical = True

        
        # create the panel (duh!). This causes a size event, which we are going
        # to skip when we are not initialised

        wx.Panel.__init__(self, parent, id, pos, size, style)

        # the fold panel area

        self._foldPanel = wx.Panel(self, wx.ID_ANY, pos, size,
                                   wx.NO_BORDER | wx.TAB_TRAVERSAL)

        self._controlCreated = True
        self._panels = []

        self.Bind(EVT_CAPTIONBAR, self.OnPressCaption)
        self.Bind(wx.EVT_SIZE, self.OnSizePanel)
        

    def AddFoldPanel(self, caption="", collapsed=False, foldIcons=None,
                     cbstyle=EmptyCaptionBarStyle):
        """
        Adds a fold panel to the list of panels.

        If the flag collapsed is set to True, the panel is collapsed
        initially.  The FoldPanel item which is returned, can be used
        as a reference to perform actions upon the fold panel like
        collapsing it, expanding it, or deleting it from the list.

        Use this foldpanel to add windows to it. Please consult
        `AddFoldPanelWindow` and `AddFoldPanelSeparator` to know how
        to add items derived from `wx.Window` to the panels.
        """

        # create a fold panel item, which is first only the caption.
        # the user can now add a panel area which will be folded in
        # when pressed.

        if foldIcons is None:
            foldIcons = wx.ImageList(16, 16)

            bmp = GetExpandedIconBitmap()
            foldIcons.Add(bmp)
            bmp = GetCollapsedIconBitmap()
            foldIcons.Add(bmp)
    
        item = FoldPanelItem(self._foldPanel, -1, caption=caption,
                             foldIcons=foldIcons,
                             collapsed=collapsed, cbstyle=cbstyle)
        
        pos = 0
        if len(self._panels) > 0:
            pos = self._panels[-1].GetItemPos() + self._panels[-1].GetPanelLength()

        item.Reposition(pos)
        self._panels.append(item)

        return item


    def AddFoldPanelWindow(self, panel, window, flags=FPB_ALIGN_WIDTH,
                           Spacing=FPB_DEFAULT_SPACING,
                           leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
                           rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
        """
        Adds a `wx.Window` derived instance to the referenced
        FoldPanel.

        IMPORTANT: Make the window be a child of the FoldPanel. See
        example that follows. The flags to be used are:
        
            * FPB_ALIGN_WIDTH: Which means the wxWindow to be added
              will be aligned to fit the width of the FoldPanel when
              it is resized.  Very handy for sizer items, buttons and
              text boxes.

            * FPB_ALIGN_LEFT: Aligns left instead of fitting the
              width of the child window to be added. Use either this
              one or FPB_ALIGN_WIDTH.

        The wx.Window to be added can be slightly indented from left
        and right so it is more visibly placed in the FoldPanel. Use
        Spacing > 0 to give the control an y offset from the previous
        wx.Window added, use leftSpacing to give it a slight indent
        from the left, and rightSpacing also reserves a little space
        on the right so the wxWindow can be properly placed in the
        FoldPanel.

        The following example adds a FoldPanel to the FoldPanelBar and
        adds two wx.Window derived controls to the FoldPanel::

            # create the FoldPanelBar
            >>> m_pnl = FoldPanelBar(self, wx.ID_ANY, wx.DefaultPosition,
                                     wx.DefaultSize, FPB_DEFAULT_STYLE,
                                     FPB_COLLAPSE_TO_BOTTOM)

            # add a foldpanel to the control. "Test me" is the caption and it is
            # initially not collapsed.
            >>> item = m_pnl.AddFoldPanel("Test me", False)

            # now add a button to the fold panel. Mind that the button should be
            # made child of the FoldPanel and not of the main form.
            >>> m_pnl.AddFoldPanelWindow(item, wx.Button(item, ID_COLLAPSEME,
                                        "Collapse Me"))

            # add a separator between the two controls. This is purely a visual
            # line that can have a certain color and also the indents and width
            # aligning like a control.
            >>> m_pnl.AddFoldPanelSeparator(item)

            # now add a text ctrl. Also very easy. Align this on width so that
            # when the control gets wider the text control also sizes along.
            >>> m_pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),

⌨️ 快捷键说明

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