Implement logic to have tabs of different sizes in additions pane and in fitting pane

This commit is contained in:
DarkPhoenix
2019-10-02 10:16:36 +03:00
parent 00d480860f
commit ba93467646
3 changed files with 83 additions and 28 deletions

View File

@@ -47,7 +47,7 @@ class AdditionsPane(TogglePanel):
baseSizer = wx.BoxSizer(wx.HORIZONTAL)
pane.SetSizer(baseSizer)
self.notebook = ChromeNotebook(pane, False)
self.notebook = ChromeNotebook(pane, can_add=False, tabWidthMode=1)
self.notebook.SetMinSize((-1, 1000))
baseSizer.Add(self.notebook, 1, wx.EXPAND)

View File

@@ -13,14 +13,16 @@
#
# ===============================================================================
import math
import wx
import wx.lib.newevent
from gui.bitmap_loader import BitmapLoader
from gui.utils import draw
from gui.utils import color as color_utils
from gui.utils import color as color_utils, draw, fonts
from service.fit import Fit
from gui.utils import fonts
_PageChanging, EVT_NOTEBOOK_PAGE_CHANGING = wx.lib.newevent.NewEvent()
_PageChanged, EVT_NOTEBOOK_PAGE_CHANGED = wx.lib.newevent.NewEvent()
@@ -89,11 +91,15 @@ class PageAdding(_PageAdding, VetoAble):
class ChromeNotebook(wx.Panel):
def __init__(self, parent, can_add=True):
def __init__(self, parent, can_add=True, tabWidthMode=0):
"""
Instance of Notebook. Initializes general layout, includes methods
for setting current page, replacing pages, any public function for the
notebook
width modes:
- 0: legacy (all tabs have equal width)
- 1: all tabs take just enough space to fit text
"""
super().__init__(parent, wx.ID_ANY, size=(-1, -1))
@@ -103,7 +109,7 @@ class ChromeNotebook(wx.Panel):
main_sizer = wx.BoxSizer(wx.VERTICAL)
tabs_sizer = wx.BoxSizer(wx.VERTICAL)
self.tabs_container = _TabsContainer(self, can_add=can_add)
self.tabs_container = _TabsContainer(self, can_add=can_add, tabWidthMode=tabWidthMode)
tabs_sizer.Add(self.tabs_container, 0, wx.EXPAND)
if 'wxMSW' in wx.PlatformInfo:
@@ -697,15 +703,15 @@ class _AddRenderer:
class _TabsContainer(wx.Panel):
def __init__(self, parent, pos=(50, 0), size=(100, 22), id=wx.ID_ANY,
can_add=True):
can_add=True, tabWidthMode=0):
"""
Defines the tab container. Handles functions such as tab selection and
dragging, and defines minimum width of tabs (all tabs are of equal
width, which is determined via widest tab). Also handles the tab
preview, if any.
"""
super().__init__(parent, id, pos, size)
self.tabWidthMode = tabWidthMode
self.tabs = []
self.width, self.height = size
@@ -1274,30 +1280,79 @@ class _TabsContainer(wx.Panel):
Adjust tab sizes to ensure that they are all consistent and can fit into
the tab container.
"""
if self.tabWidthMode == 1:
if self.GetTabsCount() > 0:
availableW = self.tab_container_width
overlapSavedW = max(0, len(self.tabs)) * self.inclination * 2
tabsGrouped = {}
for tab in self.tabs:
tabW, _ = tab.GetMinSize()
tabsGrouped.setdefault(math.ceil(tabW), []).append(tab)
clippedTabs = []
clipW = max(tabsGrouped, default=0)
# first we loop through our tabs and calculate the the largest tab. This
# is the size that we will base our calculations off
def getUnclippedW():
unclippedW = 0
for w, tabs in tabsGrouped.items():
unclippedW += w * len(tabs)
return unclippedW
while tabsGrouped:
# Check if we're within width limit
neededW = 0
for w, tabs in tabsGrouped.items():
neededW += w * len(tabs)
if clippedTabs:
neededW += clipW * len(clippedTabs)
if neededW <= availableW + overlapSavedW:
break
# If we're not, extract widest tab group and mark it for clipping
currentTabs = tabsGrouped.pop(max(tabsGrouped))
clippedTabs.extend(currentTabs)
proposedClipWidth = math.floor((availableW + overlapSavedW - getUnclippedW()) / len(clippedTabs))
if not tabsGrouped or proposedClipWidth >= max(tabsGrouped, default=0):
clipW = max(0, proposedClipWidth)
break
else:
clipW = max(tabsGrouped)
# Assign width for unclipped tabs
for w, tabs in tabsGrouped.items():
for tab in tabs:
tab.SetSize((w, self.height))
if clippedTabs:
# Some width remains to be used due to rounding to integer
extraWTotal = availableW + overlapSavedW - getUnclippedW() - clipW * len(clippedTabs)
extraWPerTab = math.ceil(extraWTotal / len(clippedTabs))
# Assign width for clipped tabs
for tab in clippedTabs:
extraW = min(extraWTotal, extraWPerTab)
extraWTotal -= extraW
tab.SetSize((clipW + extraW, self.height))
# update drop shadow based on new sizes
self.UpdateTabFX()
self.UpdateTabsPosition()
else:
# first we loop through our tabs and calculate the the largest tab. This
# is the size that we will base our calculations off
max_width = 100 # Tab should be at least 100
for tab in self.tabs:
mw, _ = tab.GetMinSize() # Tab min size includes tab contents
max_width = max(mw, max_width)
max_width = 100 # Tab should be at least 100
for tab in self.tabs:
mw, _ = tab.GetMinSize() # Tab min size includes tab contents
max_width = max(mw, max_width)
# Divide tab container by number of tabs and add inclination. This will
# return the ideal max size for the containers size
if self.GetTabsCount() > 0:
dx = self.tab_container_width / self.GetTabsCount() + self.inclination * 2
self.tab_min_width = min(dx, max_width)
# Divide tab container by number of tabs and add inclination. This will
# return the ideal max size for the containers size
if self.GetTabsCount() > 0:
dx = self.tab_container_width / self.GetTabsCount() + self.inclination * 2
self.tab_min_width = min(dx, max_width)
# Apply new size to all tabs
for tab in self.tabs:
tab.SetSize((self.tab_min_width, self.height))
# Apply new size to all tabs
for tab in self.tabs:
tab.SetSize((self.tab_min_width, self.height))
if self.GetTabsCount() > 0:
# update drop shadow based on new sizes
self.UpdateTabFX()
if self.GetTabsCount() > 0:
# update drop shadow based on new sizes
self.UpdateTabFX()
self.UpdateTabsPosition()
self.UpdateTabsPosition()
def UpdateTabsPosition(self, skip_tab=None):
tabsWidth = 0

View File

@@ -23,7 +23,7 @@ import gui.builtinViews.emptyView
class MultiSwitch(ChromeNotebook):
def __init__(self, parent):
ChromeNotebook.__init__(self, parent)
ChromeNotebook.__init__(self, parent, can_add=True, tabWidthMode=1)
# self.AddPage() # now handled by mainFrame
self.handlers = handlers = []
for type in TabSpawner.tabTypes: