1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
""" A Layered panel. """
import warnings
import wx
from traits.api import Dict, Str
from pyface.ui_traits import Image
from .expandable_header import ExpandableHeader
from .image_resource import ImageResource
from .layout_widget import LayoutWidget
class ExpandablePanel(LayoutWidget):
""" An expandable panel. """
# The default style.
STYLE = wx.CLIP_CHILDREN
collapsed_image = Image(ImageResource("mycarat1"))
expanded_image = Image(ImageResource("mycarat2"))
_layers = Dict(Str)
_headers = Dict(Str)
# ------------------------------------------------------------------------
# 'object' interface.
# ------------------------------------------------------------------------
def __init__(self, parent=None, **traits):
""" Creates a new LayeredPanel. """
create = traits.pop("create", None)
# Base class constructor.
super().__init__(parent=parent, **traits)
# Create the toolkit-specific control that represents the widget.
if create:
self.create()
warnings.warn(
"automatic widget creation is deprecated and will be removed "
"in a future Pyface version, code should not pass the create "
"parameter and should instead call create() explicitly",
DeprecationWarning,
stacklevel=2,
)
elif create is not None:
warnings.warn(
"setting create=False is no longer required",
DeprecationWarning,
stacklevel=2,
)
# ------------------------------------------------------------------------
# 'Expandale' interface.
# ------------------------------------------------------------------------
def add_panel(self, name, layer):
""" Adds a layer with the specified name.
All layers are hidden when they are added. Use 'show_layer' to make a
layer visible.
"""
parent = self.control
sizer = self.control.GetSizer()
# Add the heading text.
header = self._create_header(parent, text=name)
sizer.Add(header, 0, wx.EXPAND)
# Add the layer to our sizer.
sizer.Add(layer, 1, wx.EXPAND)
# All layers are hidden when they are added. Use 'show_layer' to make
# a layer visible.
sizer.Show(layer, False)
# fixme: Should we warn if a layer is being overridden?
self._layers[name] = layer
return layer
def remove_panel(self, name):
""" Removes a layer and its header from the container."""
if name not in self._layers:
return
sizer = self.control.GetSizer()
panel = self._layers[name]
header = self._headers[name]
# sizer.Remove(panel)
panel.Destroy()
# sizer.Remove(header)
header.Destroy()
sizer.Layout()
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _create_control(self, parent):
""" Create the toolkit-specific control that represents the widget. """
panel = wx.Panel(parent, -1, style=self.STYLE)
sizer = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(sizer)
panel.SetAutoLayout(True)
return panel
def _create_header(self, parent, text):
""" Creates a panel header. """
sizer = wx.BoxSizer(wx.HORIZONTAL)
panel = wx.Panel(parent, -1, style=wx.CLIP_CHILDREN)
panel.SetSizer(sizer)
panel.SetAutoLayout(True)
# Add the panel header.
heading = ExpandableHeader(panel, title=text)
heading.create()
sizer.Add(heading.control, 1, wx.EXPAND)
# connect observers
heading.observe(self._on_button, "panel_expanded")
heading.observe(self._on_panel_closed, "panel_closed")
# Resize the panel to match the sizer's minimum size.
sizer.Fit(panel)
# hang onto it for when we destroy
self._headers[text] = panel
return panel
# event handlers ----------------------------------------------------
def _on_button(self, event):
""" called when one of the expand/contract buttons is pressed. """
header = event.new
name = header.title
visible = header.state
sizer = self.control.GetSizer()
sizer.Show(self._layers[name], visible)
sizer.Layout()
# fixme: Errrr, maybe we can NOT do this!
w, h = self.control.GetSize().Get()
self.control.SetSize((w + 1, h + 1))
self.control.SetSize((w, h))
def _on_panel_closed(self, event):
""" Called when the close button is clicked in a header. """
header = event.new
name = header.title
self.remove_panel(name)
|