-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #411 from justvanrossum/macos1010-compat
Use old version of vanillaTabs to work around broken layout on macOS 10.10
- Loading branch information
Showing
2 changed files
with
166 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |