Skip to content

Commit

Permalink
Merge pull request #411 from justvanrossum/macos1010-compat
Browse files Browse the repository at this point in the history
Use old version of vanillaTabs to work around broken layout on macOS 10.10
  • Loading branch information
justvanrossum authored May 25, 2024
2 parents 52bd5e6 + 9eb7b22 commit d254c10
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Lib/fontgoggles/mac/mainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import unicodedata2 as unicodedata
import AppKit
import objc
from vanilla import (ActionButton, CheckBox, EditText, Group, List, PopUpButton, SplitView, Tabs,
from vanilla import (ActionButton, CheckBox, EditText, Group, List, PopUpButton, SplitView,
TextBox, TextEditor, VanillaBaseControl, Window, HorizontalLine)
from vanilla.dialogs import getFile
from fontTools.misc.arrayTools import offsetRect
Expand All @@ -22,6 +22,7 @@
from fontgoggles.mac.fontList import FontList, fontItemMinimumSize, fontItemMaximumSize, makeUndoProxy
from fontgoggles.mac.misc import ClassNameIncrementer, makeTextCell
from fontgoggles.mac.sliderGroup import SliderGroup, SliderPlus
from fontgoggles.mac.vanillaTabsOld import Tabs
from fontgoggles.compile.compilerPool import CompilerError
from fontgoggles.misc.decorators import asyncTaskAutoCancel, suppressAndLogException
from fontgoggles.misc.textInfo import TextInfo
Expand Down
164 changes: 164 additions & 0 deletions Lib/fontgoggles/mac/vanillaTabsOld.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
from Foundation import NSObject
from AppKit import NSTabView, NSTabViewItem, NSNoTabsNoBorder, NSFont
from vanilla.vanillaBase import VanillaBaseObject, _breakCycles, _sizeStyleMap, VanillaCallbackWrapper, \
_reverseSizeStyleMap


class VanillaTabItem(VanillaBaseObject):

nsTabViewItemClass = NSTabViewItem

def __init__(self, title):
self._autoLayoutViews = {}
self._tabItem = self.nsTabViewItemClass.alloc().initWithIdentifier_(title)
self._tabItem.setLabel_(title)

def _getContentView(self):
return self._tabItem.view()

def _breakCycles(self):
_breakCycles(self._tabItem.view())
self._autoLayoutViews.clear()


class VanillaTabsDelegate(NSObject):

def tabView_didSelectTabViewItem_(self, tabView, tabViewItem):
if hasattr(self, "_target"):
self._target.action_(tabView.vanillaWrapper())


class Tabs(VanillaBaseObject):

"""
A set of tabs attached to a window. Each tab is capable of containing controls.
.. image:: /_images/Tabs.png
To add a control to a tab, simply set it as an attribute of the tab.
::
from vanilla import Window, Tabs, TextBox
class TabsDemo:
def __init__(self):
self.w = Window((250, 100))
self.w.tabs = Tabs((10, 10, -10, -10), ["Tab One", "Tab Two"])
tab1 = self.w.tabs[0]
tab1.text = TextBox((10, 10, -10, -10), "This is tab 1")
tab2 = self.w.tabs[1]
tab2.text = TextBox((10, 10, -10, -10), "This is tab 2")
self.w.open()
TabsDemo()
No special naming is required for the attributes. However, each attribute
must have a unique name.
To retrieve a particular tab, access it by index::
myTab = self.w.tabs[0]
**posSize** Tuple of form *(left, top, width, height)* or *"auto"* representing the position
and size of the tabs.
**titles** An ordered list of tab titles.
**callback** The method to be called when the user selects a new tab.
**sizeStyle** A string representing the desired size style of the tabs.
The options are:
+-----------+
| "regular" |
+-----------+
| "small" |
+-----------+
| "mini" |
+-----------+
"""

nsTabViewClass = NSTabView
vanillaTabViewItemClass = VanillaTabItem

allFrameAdjustments = {
# The sizeStyle will be part of the
# className used for the lookup here.
"Tabs-mini": (-7, -10, 14, 12),
"Tabs-small": (-7, -10, 14, 13),
"Tabs-regular": (-7, -10, 14, 16),
}

def __init__(self, posSize, titles=["Tab"], callback=None, sizeStyle="regular", showTabs=True):
self._setupView(self.nsTabViewClass, posSize) # hold off on setting callback
self._setSizeStyle(sizeStyle)
self._tabItems = []
for title in titles:
tab = self.vanillaTabViewItemClass(title)
self._tabItems.append(tab)
self._nsObject.addTabViewItem_(tab._tabItem)
if not showTabs:
self._nsObject.setTabViewType_(NSNoTabsNoBorder)
self._nsObject.setDrawsBackground_(False)
# now that the tabs are all set, set the callback.
# this is done because the callback will be called
# while the tabs are being added.
if callback is not None:
self._setCallback(callback)

def getNSTabView(self):
"""
Return the `NSTabView`_ that this object wraps.
.. _NSTabView: https://developer.apple.com/documentation/appkit/nstabview?language=objc
"""
return self._nsObject

def _adjustPosSize(self, frame):
if self._nsObject.tabViewType() == NSNoTabsNoBorder:
return frame
sizeStyle = _reverseSizeStyleMap[self._nsObject.controlSize()]
tabsType = "Tabs-" + sizeStyle
self.frameAdjustments = self.allFrameAdjustments[tabsType]
return super(Tabs, self)._adjustPosSize(frame)

def _setCallback(self, callback):
if callback is not None:
self._target = VanillaCallbackWrapper(callback)
delegate = self._nsObject.delegate()
if delegate is None:
self._delegate = delegate = VanillaTabsDelegate.alloc().init()
self._nsObject.setDelegate_(delegate)
delegate._target = self._target

def _setSizeStyle(self, value):
value = _sizeStyleMap[value]
self._nsObject.setControlSize_(value)
font = NSFont.systemFontOfSize_(NSFont.systemFontSizeForControlSize_(value))
self._nsObject.setFont_(font)

def __getitem__(self, index):
return self._tabItems[index]

def _breakCycles(self):
super(Tabs, self)._breakCycles()
for item in self._tabItems:
item._breakCycles()

def get(self):
"""
Get the index of the selected tab.
"""
item = self._nsObject.selectedTabViewItem()
index = self._nsObject.indexOfTabViewItem_(item)
return index

def set(self, value):
"""
Set the selected tab.
**value** The index of the tab to be selected.
"""
self._nsObject.selectTabViewItemAtIndex_(value)

0 comments on commit d254c10

Please sign in to comment.