Source code for pyface.sizers.flow
# (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!
import wx
from pyface.timer.api import do_later
# -------------------------------------------------------------------------------
# 'FlowSizer' class:
# -------------------------------------------------------------------------------
[docs]class FlowSizer(wx.PySizer):
# ---------------------------------------------------------------------------
# Initializes the object:
# ---------------------------------------------------------------------------
def __init__(self, orient=wx.HORIZONTAL):
super().__init__()
self._orient = orient
self._frozen = False
self._needed_size = None
# ---------------------------------------------------------------------------
# Calculates the minimum size needed by the sizer:
# ---------------------------------------------------------------------------
[docs] def CalcMin(self):
""" Calculates the minimum size needed by the sizer.
"""
if self._needed_size is not None:
return self._needed_size
horizontal = self._orient == wx.HORIZONTAL
dx = dy = 0
for item in self.GetChildren():
idx, idy = item.CalcMin()
if horizontal:
dy = max(dy, idy)
else:
dx = max(dx, idx)
return wx.Size(dx, dy)
# ---------------------------------------------------------------------------
# Layout the contents of the sizer based on the sizer's current size and
# position:
# ---------------------------------------------------------------------------
[docs] def RecalcSizes(self):
""" Layout the contents of the sizer based on the sizer's current size
and position.
"""
horizontal = self._orient == wx.HORIZONTAL
x, y = self.GetPosition()
dx, dy = self.GetSize().Get()
x0, y0 = x, y
ex = x + dx
ey = y + dy
mdx = mdy = sdx = sdy = 0
visible = True
cur_max = 0
for item in self.GetChildren():
idx, idy = item.CalcMin()
expand = item.GetFlag() & wx.EXPAND
if horizontal:
if (x > x0) and ((x + idx) > ex):
x = x0
y += mdy + sdy
mdy = sdy = 0
if y >= ey:
visible = False
cur_max = max(idy, cur_max)
if expand:
idy = cur_max
if item.IsSpacer():
sdy = max(sdy, idy)
if x == x0:
idx = 0
item.SetDimension(wx.Point(x, y), wx.Size(idx, idy))
item.Show(visible)
x += idx
mdy = max(mdy, idy)
else:
if (y > y0) and ((y + idy) > ey):
y = y0
x += mdx + sdx
mdx = sdx = 0
if x >= ex:
visible = False
cur_max = max(idx, cur_max)
if expand:
idx = cur_max
if item.IsSpacer():
sdx = max(sdx, idx)
if y == y0:
idy = 0
item.SetDimension(wx.Point(x, y), wx.Size(idx, idy))
item.Show(visible)
y += idy
mdx = max(mdx, idx)
if (not visible) and (self._needed_size is None):
max_dx = max_dy = 0
if horizontal:
max_dy = max(dy, y + mdy + sdy - y0)
else:
max_dx = max(dx, x + mdx + sdx - x0)
self._needed_size = wx.Size(max_dx, max_dy)
if not self._frozen:
self._do_parent("_freeze")
do_later(self._do_parent, "_thaw")
else:
self._needed_size = None
# ---------------------------------------------------------------------------
# Prevents the specified window from doing any further screen updates:
# ---------------------------------------------------------------------------
def _freeze(self, window):
""" Prevents the specified window from doing any further screen updates.
"""
window.Freeze()
self._frozen = True
# ---------------------------------------------------------------------------
# Lays out a specified window and then allows it to be updated again:
# ---------------------------------------------------------------------------
def _thaw(self, window):
""" Lays out a specified window and then allows it to be updated again.
"""
window.Layout()
window.Refresh()
if self._frozen:
self._frozen = False
window.Thaw()
# ---------------------------------------------------------------------------
# Does a specified operation on the sizer's parent window:
# ---------------------------------------------------------------------------
def _do_parent(self, method):
""" Does a specified operation on the sizer's parent window.
"""
i = 0
while True:
try:
item = self.GetItem(i)
if item is None:
break
i += 1
except:
return
if item.IsWindow():
getattr(self, method)(item.GetWindow().GetParent())
return