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