From c2272cf1eff3e667c6ea1d255cc9c13c14745872 Mon Sep 17 00:00:00 2001 From: Chris Colbert Date: Wed, 9 Jan 2013 18:57:35 -0500 Subject: [PATCH] Update the splitter implementation to support a stretch factor and a collapse flag. --- enaml/qt/qt_split_item.py | 99 +++++++++++++++++++++++++++++++------ enaml/qt/qt_splitter.py | 26 ++-------- enaml/widgets/split_item.py | 21 +++++--- 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/enaml/qt/qt_split_item.py b/enaml/qt/qt_split_item.py index a3156b44..2f3a6954 100644 --- a/enaml/qt/qt_split_item.py +++ b/enaml/qt/qt_split_item.py @@ -2,29 +2,30 @@ # Copyright (c) 2012, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from .qt.QtGui import QFrame +from .qt.QtGui import QFrame, QSplitter, QLayout from .q_single_widget_layout import QSingleWidgetLayout from .qt_container import QtContainer from .qt_widget import QtWidget class QSplitItem(QFrame): - """ A QFrame subclass which acts as an item QSplitter. + """ A QFrame subclass which acts as an item in a QSplitter. """ - def __init__(self, *args, **kwargs): + def __init__(self, parent=None): """ Initialize a QSplitItem. Parameters ---------- - *args, **kwargs - The position and keyword arguments required to initialize - a QWidget. + parent : QWidget, optional + The parent widget of the split item, or None if it has no + parent. """ - super(QSplitItem, self).__init__(*args, **kwargs) + super(QSplitItem, self).__init__(parent) self._split_widget = None self.setLayout(QSingleWidgetLayout()) + self.layout().setSizeConstraint(QLayout.SetMinAndMaxSize) def splitWidget(self): """ Get the split widget for this split item. @@ -49,6 +50,62 @@ def setSplitWidget(self, widget): self._split_widget = widget self.layout().setWidget(widget) + def stretch(self): + """ Get the stretch factor for this split item. + + Returns + ------- + result : int + The stretch factor for this split item. + + """ + # horizontal and vertical stretch are set to be the same, + # so which one is returned here is irrelevant. + return self.sizePolicy().horizontalStretch() + + def setStretch(self, stretch): + """ Set the stretch factor for this split item. + + Parameters + ---------- + stretch : int + The stretch factor to use for this split item. + + """ + stretch = max(0, stretch) + policy = self.sizePolicy() + policy.setHorizontalStretch(stretch) + policy.setVerticalStretch(stretch) + self.setSizePolicy(policy) + + def collapsible(self): + """ Get whether or not this widget is collapsible. + + Returns + ------- + result : bool + Whether or not this item can be collapsed to zero size. + + """ + parent = self.parentWidget() + if isinstance(parent, QSplitter): + return parent.isCollapsible(parent.indexOf(self)) + return False + + def setCollapsible(self, collapsible): + """ Set whether or not this widget is collapsible. + + Parameters + ---------- + collapsible : bool + Whether or not this item can be collapsed to zero size. + This holds regardless of the minimum size of the item. + + """ + parent = self.parentWidget() + if isinstance(parent, QSplitter): + return parent.setCollapsible(parent.indexOf(self), collapsible) + class QtSplitItem(QtWidget): """ A Qt implementation of an Enaml SplitItem. @@ -68,7 +125,8 @@ def create(self, tree): """ super(QtSplitItem, self).create(tree) - self.set_preferred_size(tree['preferred_size']) + self.set_stretch(tree['stretch']) + self.set_collapsible(tree['collapsible']) def init_layout(self): """ Initialize the layout for the underyling widget. @@ -116,19 +174,30 @@ def child_added(self, child): #-------------------------------------------------------------------------- # Message Handlers #-------------------------------------------------------------------------- - def on_action_set_preferred_size(self, content): - """ Handle the 'set_preferred_size' action from the Enaml widget. + def on_action_set_stretch(self, content): + """ Handle the 'set_stretch' action from the Enaml widget. + + """ + self.set_stretch(content['stretch']) + + def on_action_set_collapsible(self, content): + """ Handle the 'set_collapsible' action from the Enaml widget. """ - self.set_preferred_size(content['preferred_size']) + self.set_collapsible(content['collapsible']) #-------------------------------------------------------------------------- # Widget Update Methods #-------------------------------------------------------------------------- - def set_preferred_size(self, size): - """ Set the preferred size for this item in the splitter. + def set_stretch(self, stretch): + """ Set the stretch factor for the underlying widget. + + """ + self.widget().setStretch(stretch) + + def set_collapsible(self, collapsible): + """ Set the collapsible flag for the underlying widget. """ - # XXX implement me - pass + self.widget().setCollapsible(collapsible) diff --git a/enaml/qt/qt_splitter.py b/enaml/qt/qt_splitter.py index 2efecd61..6ce7c97b 100644 --- a/enaml/qt/qt_splitter.py +++ b/enaml/qt/qt_splitter.py @@ -53,9 +53,6 @@ class QCustomSplitter(QSplitter): #: of the splitter is no longer valid. layoutRequested = Signal() - #-------------------------------------------------------------------------- - # Public API - #-------------------------------------------------------------------------- def createHandle(self): """ A reimplemented virtual method to create splitter handles. @@ -145,7 +142,7 @@ def init_layout(self): # collapsed, the effect of this is to restore the order of event # processing. if sys.platform == 'win32': - widget.splitterMoved.connect(self.on_win32_slider_moved) + widget.splitterMoved.connect(self.on_win32_splitter_moved) #-------------------------------------------------------------------------- # Child Events @@ -173,8 +170,8 @@ def on_layout_requested(self): """ self.size_hint_updated() - def on_win32_slider_moved(self): - """ Handle the 'sliderMoved' signal from the QSplitter. + def on_win32_splitter_moved(self): + """ Handle the 'splitterMoved' signal from the QSplitter. This handler is only connected when running on Windows and it serves to make sure paint events get generated during heavy @@ -217,20 +214,3 @@ def set_live_drag(self, live_drag): """ self.widget().setOpaqueResize(live_drag) - # def set_preferred_sizes(self, sizes): - # """ Set the preferred sizes for the children. - - # For sizes not supplied by the user, either via None values or - # a list which is too short, the current size for that element - # will be used in its place. - - # """ - # widget = self.widget() - # curr_sizes = widget.sizes()[:] - # max_idx = min(len(curr_sizes), len(sizes)) - # for idx in xrange(max_idx): - # size = sizes[idx] - # if size is not None: - # curr_sizes[idx] = size - # widget.setSizes(curr_sizes) - diff --git a/enaml/widgets/split_item.py b/enaml/widgets/split_item.py index 97fa16d1..1e394d71 100644 --- a/enaml/widgets/split_item.py +++ b/enaml/widgets/split_item.py @@ -2,7 +2,7 @@ # Copyright (c) 2012, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from traits.api import Either, Int, Property, cached_property +from traits.api import Any, Bool, Range, Property, cached_property from .container import Container from .widget import Widget @@ -16,13 +16,21 @@ class SplitItem(Widget): instance of Container. """ - #: The preferred size for this item in the splitter, or None if - #: there is no preference for the size. The default is None. - preferred_size = Either(None, Int) + #: The stretch factor for this item. The stretch factor determines + #: how much an item is resized relative to its neighbors when the + #: splitter space is allocated. + stretch = Range(low=0, value=1) + + #: Whether or not the item can be collapsed to zero width by the + #: user. This holds regardless of the minimum size of the item. + collapsible = Bool(True) #: A read only property which returns the split widget. split_widget = Property(depends_on='children') + #: This is a deprecated attribute. It should no longer be used. + preferred_size = Any + #-------------------------------------------------------------------------- # Initialization #-------------------------------------------------------------------------- @@ -31,7 +39,8 @@ def snapshot(self): """ snap = super(SplitItem, self).snapshot() - snap['preferred_size'] = self.preferred_size + snap['stretch'] = self.stretch + snap['collapsible'] = self.collapsible return snap def bind(self): @@ -39,7 +48,7 @@ def bind(self): """ super(SplitItem, self).bind() - self.publish_attributes('preferred_size') + self.publish_attributes('stretch', 'collapsible') #-------------------------------------------------------------------------- # Private API