mimo42 / mmtabbarview Goto Github PK
View Code? Open in Web Editor NEWA Mac OS X tab bar view that works on 10.9+ with Xcode 9.3+. Pull requests welcomed.
Home Page: http://mimo42.github.com/MMTabBarView/
A Mac OS X tab bar view that works on 10.9+ with Xcode 9.3+. Pull requests welcomed.
Home Page: http://mimo42.github.com/MMTabBarView/
To add Carthage support, please just change the Framework scheme to "Shared".
It seems to have something to do with viewDidEndLiveResize:
for (MMAttachedTabBarButton *aButton in [self attachedButtons]) {
[[aButton indicator] startAnimation:self];
}
[self _checkWindowFrame];
[self update:NO];
}
If you comment out [[aButton indicator] startAnimation:self];
then it no longer freezes.
I'm just trying out the demo, but Mojave tabs don't seem to update their colors properly when the window gains/loses focus. You have to manually move the cursor over the tabs to update their colors. The other styles seem to handle it properly.
This crash started with MacOS 12.3. Using MacOS 12.2.1 is fine. I suspect something to do with the new Universal Control feature introduced in MacOS 12.3.
Create a tab bar and set onlyShowCloseOnHover to YES. Create more than one tab.
_tabBar.onlyShowCloseOnHover = YES;
Moving the mouse over the [x] button in tab bar causes it to crash with a MacOS assertion.
The window has been marked as needing another Display Window pass, but it has already had more Display Window passes than there are views in the window.
Stack dump:
0 CoreFoundation 0x00007ff80ab6c1e3 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff80a8ccc13 objc_exception_throw + 48
2 CoreFoundation 0x00007ff80ab6c04a +[NSException exceptionWithName:reason:userInfo:] + 0
3 AppKit 0x00007ff80d52de5d -[NSWindow(NSDisplayCycle) _postWindowNeedsDisplayUnlessPostingDisabled] + 1716
4 AppKit 0x00007ff80dd7d2bb NSViewSetNeedsUpdateVibrancy + 64
5 AppKit 0x00007ff80d531ba2 -[NSView setNeedsDisplayInRect:] + 212
6 AppKit 0x00007ff80d531ab9 -[NSView setNeedsDisplay:] + 50
7 AppKit 0x00007ff80d54607e -[NSButton updateCell:] + 47
8 MMTabBarView 0x000000010c731eac -[MMRolloverButtonCell mouseExited:] + 108
9 MMTabBarView 0x000000010c731329 -[MMRolloverButton updateTrackingAreas] + 713
10 AppKit 0x00007ff80dd87e0b -[NSView _updateTrackingAreasWithInvalidCursorRects:] + 124
11 AppKit 0x00007ff80dd885ef -[NSView _updateTrackingAreasWithInvalidCursorRects:] + 2144
12 AppKit 0x00007ff80dd885ef -[NSView _updateTrackingAreasWithInvalidCursorRects:] + 2144
13 AppKit 0x00007ff80dd885ef -[NSView _updateTrackingAreasWithInvalidCursorRects:] + 2144
14 AppKit 0x00007ff80dd885ef -[NSView _updateTrackingAreasWithInvalidCursorRects:] + 2144
15 AppKit 0x00007ff80d5e9ef9 _NSWindowDisplayCycleUpdateStructuralRegions + 212
16 AppKit 0x00007ff80d5e646f __NSWindowGetDisplayCycleObserverForUpdateStructuralRegions_block_invoke + 420
17 AppKit 0x00007ff80d5e0577 NSDisplayCycleObserverInvoke + 155
18 AppKit 0x00007ff80d5e0104 NSDisplayCycleFlush + 921
19 AppKit 0x00007ff80d5eb465 __37+[NSDisplayCycle currentDisplayCycle]_block_invoke.18 + 906
20 QuartzCore 0x00007ff811b80382 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 98
21 QuartzCore 0x00007ff811cf4421 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 875
22 QuartzCore 0x00007ff811b7f231 _ZN2CA11Transaction6commitEv + 777
23 AppKit 0x00007ff80d6817f1 __62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke + 285
24 AppKit 0x00007ff80ddc8688 ___NSRunLoopObserverCreateWithHandler_block_invoke + 41
25 CoreFoundation 0x00007ff80aaefe90 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
26 CoreFoundation 0x00007ff80aaefd22 __CFRunLoopDoObservers + 543
27 CoreFoundation 0x00007ff80aaef1b4 __CFRunLoopRun + 840
28 CoreFoundation 0x00007ff80aaee7ac CFRunLoopRunSpecific + 562
29 HIToolbox 0x00007ff813775ce6 RunCurrentEventLoopInMode + 292
30 HIToolbox 0x00007ff813775913 ReceiveNextEventCommon + 283
31 HIToolbox 0x00007ff8137757e5 _BlockUntilNextEventMatchingListInModeWithFilter + 70
32 AppKit 0x00007ff80d5155cd _DPSNextEvent + 927
33 AppKit 0x00007ff80d513c8a -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1394
34 AppKit 0x00007ff80d506339 -[NSApplication run] + 586
35 AppKit 0x00007ff80d4da2b7 NSApplicationMain + 817
Putting a breakpoint on ObjectiveC exceptions. It is thrown in MMRolloverButtonCell.mouseExited when it calls updateCell.
- (void)mouseExited:(NSEvent *)event {
_mouseHovered = NO;
[(NSControl *)self.controlView updateCell:self];
}
When tabs flow into the overflow menu the menu is not released when the MMTabBarController is deallocated. I'd provide a pull request, but my last one hasn't been processed.
I've got it working, but the use of this threw me for a loop when a 10.10.5 user of my application reported an access fault (my fault for not testing on 10.10 first!). Specifically NSViewNoIntrinsicMetric
corrects the deprecated typo NSViewNoInstrinsicMetric
, but according to the header the "correct" version carries the macro NS_AVAILABLE_MAC(10_11)
.
Given that the typo'd version is only commented as deprecated but not formally deprecated, is the intention that MMTabBarView have a deployment target of 10.11 or newer, too? It works perfectly fine on 10.10.5 by going back to the previous constant, and the readme still indicates 10.9+.
I'm happy to issue a PR, but maybe I'm missing something else here.
On Yosemite, we can choose to hide the titlebar of the window and use the new unified look. However there is a rendering issue when using the unified look in full screen, and hiding the toolbar:
In the newWindow: method in DemoWindowController, add the following:
[[newWindowController window] setTitleVisibility:NSWindowTitleHidden];
[[newWindowController window] setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
Make the demo window full screen, and it looks ok:
Hide the toolbar (from the application menu or [Alt]+[Command]+T) and the tabs are no longer visible:
Safari 6 has a new "show all tabs" mode which shows a preview of each tab with a kind of iOS styling. There is an extra button at the far right of the tab bar to trigger this mode, and once open it is navigable with arrow keys to switch between tabs and space bar or return to select.
Safari also supports multitouch gestures to manipulate this part of its tab view. Specifically, you can multi-finger pinch to enter the "show all tabs" mode, and zoom out to select a tab.
Here is a video of the feature in action: http://www.youtube.com/watch?v=_f6roe9vSoc
I may try to develop this myself, and if I succeed I will send in a pull request. But if I don't find time, I think it would be a great feature to add.
I do not like vertical tab bars for many reasons.
That's why MMTabBarView does not completely support vertical tab bars yet.
Should we drop the vertical tab bar support for good?
With demo app based on current master
, the content of the 'Style' popup menu (in configuration drawer) is greyed out.
Observed on macOS 10.15.6, Xcode 11.6
Seems to be caused by commit 9e03810
cc @jeromectm
Mojave-style tabs currently have a blurry drop shadow under the label text that's very visible in Dark Mode, which looks messy. Native tabs do not have that and therefore look a lot cleaner.
From what I can tell the culprit is at the following location:
It applies a global drop shadow to all text labels. When I turn it off locally, the text looks normal and much closer to what native tabs look like. I looked at the other styles too and they still looked fine after I removed the drop shadow code so I think this code could probably be removed, but I'm not sure what the original reasoning behind the drop shadow is (did Apple's Aqua/Metal-style tabs have drop shadows?). I think the drop shadow should at least be turned off for Mojave or other more modern tab styles.
I wan't to listen for mouseDown event for the tabbar, but the event doesn't popup to it's parent view or view controller.
Currently I need to implement this:
- (void)windowDidBecomeKey:(NSNotification *)notification {
[_tabBarView update:NO]; // update without animate
}
…in order to make the overflowPopUpButton clickable after hiding the app and showing again. Same behavior with demo app on 10.8.
To fix, in MMTabBarView.m change isWindowActive method from,
if ([window isKeyWindow]) {
to
if ([window isKeyWindow] || [window isMainWindow]) {
I tried to use this flag in my project to analyze and debug some of my layouts. It crashed at startup with
-[MMSafariTabStyle respondsToSelector:]: message sent to deallocated instance 0x1022447c0
Everything's back ok by toggling off the flag.
Tried with the demo project that comes with the library, and enabling -NSViewShowAlignementRects led to
MMTabBarView Demo(996,0x7fff79112960) malloc: *** error for object 0x100502720: pointer being freed was not allocated
i'm running OS X 10.7.5
XCode: Version 4.6.3 (4H1503)
ARC Yes
thanks in advance for any feedback or support
Two serious issue made this excellent component unuseful.
It only support NSWindowController but can't be embedded in NSViewController that made it unavailable for most apps that requires customised NSView working with NSViewController.
NSTabViewItems must associated with a NSViewController in most situations, see #54, (Support for NSTabViewItems with view controllers under 10.10+).
Test environment:
Xcode 10 on High Sierra (10.13).
Thanks for such an excellent component, but it's not perfect, still needs improvement.
Dragging a tab out of the tab button bar should show a mini-window as dragging image.
This works only for the last tab. For other tabs, this is skipped because no destinationIndexForDraggedItem was set on the tab view during draggingEntered:
As a workaround, I have modified -[MMTabDragAssistant _destinationIndexForButton:atPoint:inTabBarView:] at line 570 to set resultingIndex without testing aPoint against lastFrame:
else if ([self isDragging]) {
if ([tabBarView destinationIndexForDraggedItem] != NSNotFound)
resultingIndex = [tabBarView destinationIndexForDraggedItem];
else {
resultingIndex = [tabBarView numberOfVisibleTabViewItems];
}
}
Now draggingEntered: defaults to setting destinationIndexForDraggedItem to the number of tab items. During draggingExited:, MMTabDragAssistant:932 now considers the tab bar to have participated in the dragging operation.
I have not created a pull request as I am not sure what further implications this change will have.
I am seeing a retain cycle between MMTabBarView and MMTabBarController. It is my understanding that instance variables are strong by default under ARC so _tabBarView is a strong reference back to the MMTabBarView that allocated it and holds a strong pointer to its controller in _controller.
@implementation MMTabBarController
{
MMTabBarView *_tabBarView;
NSMenu *_overflowMenu;
}
@implementation MMTabBarView
{
// control basics
NSTabView *_tabView; // the tab view being navigated
MMOverflowPopUpButton *_overflowPopUpButton; // for too many tabs
MMRolloverButton *_addTabButton;
MMTabBarController *_controller;
Should not __weak be used to make the reference back to the view weak? That is
@implementation MMTabBarController
{
__weak MMTabBarView *_tabBarView;
NSMenu *_overflowMenu;
}
When closing a tab with the close button on the tab, the next (right-side) tab will be moved to the place where the closed tab was. But the close button of the next tab is hidden, because of mouseHovered state is not valid.
"Only show close on hover" was ON.
Tested on OS X 10.8.4.
How do you think about to add this code to the end of -(void)updateTrackingAreas method of MMRolloverButton class?
if ([self mouse:mouseLocation inRect:[self bounds]]) {
[[self cell] mouseEntered:nil];
}
Steps to reproduce the problem:
What is the expected behavior?
The tab bar in the newly created window should be hidden because there is only one tab in that window, and the "hide for single tab" option of that window is checked.
What went wrong?
The tab bar is shown, but there is only one tab in it.
Any other comments?
I think it is a threading issue:
[MMTabBarView setNeedsUpdate:YES]
from - (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView
, which will add a UI update queue to the main thread and set _needsUpdate
to YES
;[MMTabBarView setNeedsUpdate:NO]
from - (void)update:(BOOL)animate
, then the _needsUpdate
will be set to NO
;_needsUpdate
is NO
now, and the main thread will think that there is no need to update the UI and skip the UI update queue.As a result, the "hide for single tab" option is not affecting
Following error when attempting to run a project with MMTabBar added:
dyld: Library not loaded: @rpath/MMTabBarView.framework/Versions/A/MMTabBarView
Referenced from: /Users/USERNAME/Library/Developer/Xcode/DerivedData/Bolt-bqfrgwpsqeiddgdysnnjivceqyqc/Build/Products/Debug/APPNAME.app/Contents/MacOS/APPNAME
Reason: no suitable image found. Did find:
/usr/local/lib/MMTabBarView: stat() failed with errno=13
Thread 1: EXC_BAD_ACCESS
2 issues with a miniwindow tear off.
If you drag a tab out of the main window on (or to) a secondary display where the top of the secondary display is lower than the top of the main display, the new window that's created has the titlebar above the top of the secondary display. You can't drag the new window because you can't get to the titlebar.
If you drag a tab item within its parent tabview to reorder it, the miniwindow appears under the mouse pointer as you move it around as expected. However, if you try to drag the last tab item from one window to another window, the tab item's parent window is closed and no miniwindow appears under the mouse. Drag and dropping does work, you just don't see what you're dragging and dropping.
I haven't noticed any obvious issues with alpha window tear off which is what I'll be using anyway.
Hello.
I tried to adding your beautiful tabs in my project. And nothing. I dont understand, where is an error.
My primitive test project - https://dl.dropboxusercontent.com/u/42518432/tabTest.zip
Could you help me? Thank you very much
Hello everyone! :)
I can't build the demo project with Xcode 8.0 and 7.x.
There is always this error:
dyld: Library not loaded: @rpath/MMTabBarView.framework/Versions/A/MMTabBarView Referenced from: /Users/julian/Library/Developer/Xcode/DerivedData/MMTabBarView_Demo-arjpuxyfsaerygdqyqgswnrdcxgi/Build/Products/Debug/MMTabBarView Demo.app/Contents/MacOS/MMTabBarView Demo Reason: image not found (lldb)
Can anybody help me? Thanks a lot!
I have been trying for 2 hours now and I can not figure out how to install this framework for use in my app. I am a noob, but I really want to use this framework. Can someone provide in depth details of how to install the framework for use in my app? Thanks!
I found that tabViewDidChangeNumberOfTabViewItems: not called after close tab. That leads to setNeedsUpdate: not called
It seems that the identifier field in the NSTabViewItem is used for storing the associated tab's view controller under current OSX releases 10.10+ which conflicts with storing the MMTabBarItem there. Does anyone have a work-around for this? In particular this happens when one assigns to the viewController property of NSTabViewItem. Alternatively, is there a way to have a view controller manage the tab's view without using the viewController property?
In Mojava preview (10.14), tabs don't change appearance when Dark Mode is active, although the font does change.
I'll take a stab at it in the near future if no one else steps up.
If you drag a tab out of its window to the right of the window, the tab is under the cursor as you drag as expected. However, if you drag a tab out of its window towards the left, the tab appears well left of the cursor instead of under it.
When the tabs are set to vertical mode, if you drag a tab it doesn't move with the mouse (vertically). It creates a space at the mouse location on the tab bar and the other tabs move around the gap but the tab that you're dragging stays in the same place. If you drag the tab horizontally out of the tab bar it will then follow the mouse. I was wondering if it could be configured to behave more like the horizontal tab mode where the tab moves along with the mouse cursor.
[email protected] should be named [email protected].
Hi All,
I've been putting together an app using swift and was hoping to use this toolbar - because the built in toolbars are kinda hideous. I haven't found any documentation... which has made it a little difficult, and I've not had good results yet. The demo is awesome, but is in obj-C.
As far as I can tell... I need to add a custom view, set the class to MMTabBarView and then set its tabView property pointed to an existing NSTabView. Is that required? If it is, can I hide that TabView? Also... whats the difference between partnerview and tabview properties? Your demo uses both.
It seems that I then add/remove items from the NSTabView with extra options added to the identifier property in a class (your DemoFakeModel class). Those will then get replicated into the MMTabBarView. Is that right? It doesn't seem to be working for me.
Thx for any advice you can give.
If your delegate prevents a tab view item from being selected with the method [NSTabViewDelegate tabView:shouldSelectTabViewItem:], the tab view selection doesn't change but the tab bar selection does.
To fix this, I had to modify mouseDown: method in MMAttachedTabBarButton.m to not change the state of the previous selected button and the button that was just clicked (PSMTabBarControl doesn't change the state but relies on selectTabViewItem: to do it).
Can I use this Framework in ARC-enabled projects?
An open question...maybe i'm dumb and doing something wrong but...
should -(BOOL)showObjectCount
be a method declared in MMTabBarItem protocol, like the other optional ones?
It doesn't seem to be there and i figured out after an hour of tinkering that this is called on the
tabItem identifier and is expected to return YES in order to show the counter on the attached tab.
-(NSInteger)objectCount
is still called even if the id<MMTabBarItem>
instance doesn't implement the aforementioned method, but the counter is, as a matter of fact, not displayed.
Thanks for any clarifications about that.
Vanni
should add
if ([[self delegate] respondsToSelector:@selector(tabView:toolTipForTabViewItem:)]) { NSString *toolTip = [[self delegate] tabView:[self tabView] toolTipForTabViewItem:item]; [lastButton setToolTip:toolTip]; }
in - (void)setTabViewItemPinnedToOverflowButton:(NSTabViewItem *)item
?
Excellent work BTW. This saved me a lot of time.
This is a feature request.
Use case:
You need to have your tabs ordered. For example, you want to save in your document model that you have tab foo, bar, and foobar in that order. So you come up with some scheme to maintain an index in your model somewhere. Now, when the user slides the tabs, there is no way to notice that this happened and update the model's index to reflect the change.
So is it easy to know that the user is sliding things around from the delegate method:
But there does not appear to be away to know that the user is done and get the final tab reordering.
So the feature request is a simple way to observe that a reordering (sliding) has taken place.
It seems that if there was another delegate method something similar to:
or maybe the delegate method:
that gets called at the appropriate time.
One might even be able to make that case that the delegate:
gets called at the end but seems less than optimal.
There is the opportunity to show the Close button when displaying select tab?
I tried to add
But the program does not work.
Inside MMTabBarView.m change the "removeTabViewItem:" method as follows
(void)removeTabViewItem:(NSTabViewItem *)anItem {
[_tabView removeTabViewItem:anItem];
MMAttachedTabBarButton* button = [self attachedButtonForTabViewItem:anItem];
if(button){
[self removeAttachedButton:button synchronizeTabViewItems:YES];
}
}
or else the NSTabViewItem will not get released when the tab is closed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.