📄 foldpanelbar.py
字号:
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 + -