6

Is there an open-source library for Cocoa to create a window following iTunes' style? That is the window controls are laid out vertically instead of horizontally:

sample iTunes window

I find it space-saving and good for utility-type applications that doesn't need a window title.

adib
  • 8,285
  • 6
  • 52
  • 91
  • 11
    I find it annoying and against Apple Design Guidelines. I really wish they wouldn't keep doing it. It sets a bad example. – JeremyP Nov 29 '10 at 16:57

3 Answers3

9

This quickly hacked away NSWindow delegate should get you started:

//VerticalTrafficLightsWindowDelegate.h

#import <Cocoa/Cocoa.h>

@interface VerticalTrafficLightsWindowDelegate : NSObject <NSWindowDelegate> {
    NSWindow *window;
}

@property (assign) IBOutlet NSWindow *window;

- (void)verticalizeButtonsForWindow:(NSWindow *)aWindow;

@end

//VerticalTrafficLightsWindowDelegate.m

#import "VerticalTrafficLightsWindowDelegate.h"

@implementation VerticalTrafficLightsWindowDelegate

@synthesize window;

- (void)awakeFromNib {
    [self verticalizeButtonsForWindow:window];
}

- (void)windowDidResize:(NSNotification *)notification {
    [self verticalizeButtonsForWindow:window];
}

- (void)verticalizeButtonsForWindow:(NSWindow *)aWindow {
    NSArray *contentSuperViews = [[[aWindow contentView] superview] subviews];

    NSView *closeButton = [contentSuperViews objectAtIndex:0];
    NSRect closeButtonFrame = [closeButton frame];

    NSView *minimizeButton = [contentSuperViews objectAtIndex:2];
    NSRect minimizeButtonFrame = [minimizeButton frame];

    NSView *zoomButton = [contentSuperViews objectAtIndex:1];
    NSRect zoomButtonFrame = [zoomButton frame];

    [minimizeButton setFrame:NSMakeRect(closeButtonFrame.origin.x, closeButtonFrame.origin.y - 20.0, minimizeButtonFrame.size.width, minimizeButtonFrame.size.height)];
    [zoomButton setFrame:NSMakeRect(closeButtonFrame.origin.x, closeButtonFrame.origin.y - 40.0, zoomButtonFrame.size.width, zoomButtonFrame.size.height)];
}

@end

However I got to say that just like JeremyP I can only hope Apple's not going to spread this any wider in OS X.

Regexident
  • 29,441
  • 10
  • 93
  • 100
  • indeed, I just hope the same. those controls are ugly. – Cesar A. Rivas Nov 30 '10 at 05:04
  • This does work, but is fairly ugly. You'd also have to extend the size of the titlebar, but I suspect that iTunes is just using the Cocoa equivalent of an NSToolbar to do it's work. But then we also need the traffic lights in small size ;) – Tristan Dec 08 '10 at 16:25
  • To visually match iTunes you obviously have to use a unified textured window. Further more, if you look at how iTunes' window UI is set up (UI Browser), you'll see, that iTunes uses no toolbar at all! And those traffic buttons should not be elements of a toolbar anyway, imho. Those are superordinate functions of a window, and are non-related to its content (vs. toolbar icons). ( Okay, zoom is kind of content-related, but you get the point, don't you? ;) ) – Regexident Dec 09 '10 at 11:29
2

Just a modified version based on @Regexident 's for new macOS. The view hierarchy changed for new macOS UI, so the original version does not work. The modified code is as follows (works on macOS 10.13):

- (void)verticalizeButtonsForWindow:(NSWindow *)aWindow {
    // New view hierarchy.
    NSView *titleBarContainerView = aWindow.contentView.superview.subviews[1];
    titleBarContainerView.frame = NSMakeRect(titleBarContainerView.frame.origin.x, titleBarContainerView.frame.origin.y - 60.0 + titleBarContainerView.frame.size.height, titleBarContainerView.frame.size.width, 60.0);
    NSView *titleBarView = titleBarContainerView.subviews[0];
    titleBarView.frame = NSMakeRect(0.0, 0.0, titleBarView.frame.size.width, 60.0);
    NSArray *titleBarSubviews = titleBarView.subviews;

    NSView *closeButton = [titleBarSubviews objectAtIndex:0];
    NSRect closeButtonFrame = [closeButton frame];

    NSView *minimizeButton = [titleBarSubviews objectAtIndex:2];
    NSRect minimizeButtonFrame = [minimizeButton frame];

    NSView *zoomButton = [titleBarSubviews objectAtIndex:1];
    NSRect zoomButtonFrame = [zoomButton frame];

    // Coordinate changed: add instead of minus.
    [minimizeButton setFrame:NSMakeRect(closeButtonFrame.origin.x, closeButtonFrame.origin.y + 20.0, minimizeButtonFrame.size.width, minimizeButtonFrame.size.height)];
    [zoomButton setFrame:NSMakeRect(closeButtonFrame.origin.x, closeButtonFrame.origin.y + 40.0, zoomButtonFrame.size.width, zoomButtonFrame.size.height)];
}

Result screenshot: enter image description here

Zhigang An
  • 296
  • 2
  • 13
1

You'll probably have to subclass NSWindow, NSView and do the window and buttons drawing yourself.

Oh and just wanted to add that you lose some quite important details doing custom drawing. Since the drawing is done in the main thread and your main thread might get busy doing some heavy important task blocking the main thread execution for a while, user won't be able to move the window and they button mouse over animation won't work.

Unless of course you implement mouse listening events in another thread, do the drawing there, lock focus... What I meant was - don't bother unless you really think this will make your app much better :)

Aidynskas
  • 101
  • 3