nkeynes@964: /** nkeynes@964: * $Id$ nkeynes@964: * nkeynes@964: * Construct and maintain the main window under cocoa. nkeynes@964: * nkeynes@964: * Copyright (c) 2008 Nathan Keynes. nkeynes@964: * nkeynes@964: * This program is free software; you can redistribute it and/or modify nkeynes@964: * it under the terms of the GNU General Public License as published by nkeynes@964: * the Free Software Foundation; either version 2 of the License, or nkeynes@964: * (at your option) any later version. nkeynes@964: * nkeynes@964: * This program is distributed in the hope that it will be useful, nkeynes@964: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@964: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@964: * GNU General Public License for more details. nkeynes@964: */ nkeynes@964: nkeynes@964: #include "cocoaui/cocoaui.h" nkeynes@964: #include "lxdream.h" nkeynes@964: #include "dreamcast.h" nkeynes@964: #include "gdrom/gdrom.h" nkeynes@964: #include nkeynes@1028: #include nkeynes@964: nkeynes@964: @interface NSWindow (OSX10_5_and_later) nkeynes@964: #ifndef CGFLOAT_DEFINED nkeynes@964: # ifdef __LP64__ nkeynes@964: typedef double CGFloat; nkeynes@964: # else nkeynes@964: typedef float CGFloat; nkeynes@964: # endif nkeynes@964: #endif nkeynes@964: - (void)setAutorecalculatesContentBorderThickness:(BOOL)b forEdge:(NSRectEdge)e; nkeynes@964: - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e; nkeynes@964: @end nkeynes@964: nkeynes@964: nkeynes@964: #if NSAppKitVersionNumber > NSAppKitVersionNumber10_4 nkeynes@964: nkeynes@964: #endif nkeynes@964: nkeynes@964: #define STATUSBAR_HEIGHT 25 nkeynes@964: #define STATUS_TEXT_HEIGHT 22 nkeynes@964: nkeynes@964: @interface LxdreamToolbarDelegate : NSObject { nkeynes@964: NSArray *identifiers; nkeynes@964: NSArray *defaults; nkeynes@964: NSDictionary *items; nkeynes@964: } nkeynes@964: - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label nkeynes@964: tooltip: (NSString *)tooltip nkeynes@964: icon: (NSString *)icon action: (SEL) action; nkeynes@964: @end nkeynes@964: nkeynes@964: @implementation LxdreamToolbarDelegate nkeynes@964: - (id) init nkeynes@964: { nkeynes@964: NSToolbarItem *mount = [self createToolbarItem: @"GdromMount" label: @"Open Image" nkeynes@964: tooltip: @"Mount a cdrom disc" icon: @"tb-cdrom" nkeynes@964: action: @selector(mount_action:)]; nkeynes@964: NSToolbarItem *reset = [self createToolbarItem: @"Reset" label: @"Reset" nkeynes@964: tooltip: @"Reset dreamcast" icon: @"tb-reset" nkeynes@964: action: @selector(reset_action:)]; nkeynes@964: NSToolbarItem *pause = [self createToolbarItem: @"Pause" label: @"Pause" nkeynes@964: tooltip: @"Pause dreamcast" icon: @"tb-pause" nkeynes@964: action: @selector(pause_action:)]; nkeynes@964: NSToolbarItem *run = [self createToolbarItem: @"Run" label: @"Resume" nkeynes@964: tooltip: @"Resume" icon: @"tb-run" nkeynes@964: action: @selector(run_action:)]; nkeynes@964: NSToolbarItem *load = [self createToolbarItem: @"LoadState" label: @"Load State..." nkeynes@964: tooltip: @"Load an lxdream save state" icon: @"tb-load" nkeynes@964: action: @selector(load_action:)]; nkeynes@964: NSToolbarItem *save = [self createToolbarItem: @"SaveState" label: @"Save State..." nkeynes@964: tooltip: @"Create an lxdream save state" icon: @"tb-save" nkeynes@964: action: @selector(save_action:)]; nkeynes@964: NSToolbarItem *prefs = [self createToolbarItem: @"Preferences" label: @"Preferences..." nkeynes@964: tooltip: @"Edit preferences" icon: @"tb-preferences" nkeynes@964: action: @selector(preferences_action:)]; nkeynes@964: [pause setEnabled: NO]; nkeynes@964: identifiers = nkeynes@964: [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run", @"LoadState", @"SaveState", @"Preferences", nil ]; nkeynes@964: defaults = nkeynes@964: [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run", nkeynes@964: NSToolbarSeparatorItemIdentifier, @"LoadState", @"SaveState", nkeynes@964: NSToolbarFlexibleSpaceItemIdentifier, @"Preferences", nil ]; nkeynes@964: NSArray *values = [NSArray arrayWithObjects: mount, reset, pause, run, load, save, prefs, nil ]; nkeynes@964: items = [NSDictionary dictionaryWithObjects: values forKeys: identifiers]; nkeynes@964: return self; nkeynes@964: } nkeynes@964: nkeynes@964: - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label nkeynes@964: tooltip: (NSString *)tooltip icon: (NSString *)icon action: (SEL) action nkeynes@964: { nkeynes@964: NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier: id]; nkeynes@964: [item setLabel: label]; nkeynes@964: [item setToolTip: tooltip]; nkeynes@964: [item setTarget: [NSApp delegate]]; nkeynes@964: NSString *iconFile = [[NSBundle mainBundle] pathForResource:icon ofType:@"png"]; nkeynes@964: NSImage *image = [[NSImage alloc] initWithContentsOfFile: iconFile]; nkeynes@964: [item setImage: image]; nkeynes@964: [item setAction: action]; nkeynes@964: return item; nkeynes@964: } nkeynes@964: nkeynes@964: - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar nkeynes@964: { nkeynes@964: return identifiers; nkeynes@964: } nkeynes@964: nkeynes@964: - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar nkeynes@964: { nkeynes@964: return defaults; nkeynes@964: } nkeynes@964: nkeynes@964: - (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar nkeynes@964: { nkeynes@964: return [NSArray arrayWithObjects: @"Pause", @"Run", nil]; nkeynes@964: } nkeynes@964: nkeynes@964: - (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier nkeynes@964: willBeInsertedIntoToolbar:(BOOL)flag nkeynes@964: { nkeynes@964: return [items objectForKey: itemIdentifier]; nkeynes@964: } nkeynes@964: @end nkeynes@964: nkeynes@964: @implementation LxdreamMainWindow nkeynes@964: - (id)initWithContentRect:(NSRect)videoRect nkeynes@964: { nkeynes@964: NSRect contentRect = NSMakeRect(videoRect.origin.x,videoRect.origin.y, nkeynes@964: videoRect.size.width,videoRect.size.height+STATUSBAR_HEIGHT); nkeynes@964: if( [super initWithContentRect: contentRect nkeynes@964: styleMask: ( NSTitledWindowMask | NSClosableWindowMask | nkeynes@964: NSMiniaturizableWindowMask | NSResizableWindowMask | nkeynes@964: NSUnifiedTitleAndToolbarWindowMask ) nkeynes@964: backing: NSBackingStoreBuffered defer: NO ] == nil ) { nkeynes@964: return nil; nkeynes@964: } else { nkeynes@964: useGrab = NO; nkeynes@964: isGrabbed = NO; nkeynes@964: video = (LxdreamVideoView *)video_osx_create_drawable(); nkeynes@964: [video setFrameOrigin: NSMakePoint(0.0,STATUSBAR_HEIGHT)]; nkeynes@964: [video setDelegate: self]; nkeynes@964: nkeynes@964: status = nkeynes@964: [[NSTextField alloc] initWithFrame: NSMakeRect(0.0,0.0,videoRect.size.width,STATUS_TEXT_HEIGHT)]; nkeynes@964: [status setStringValue: @"Idle"]; nkeynes@964: [status setEditable: NO]; nkeynes@964: [status setDrawsBackground: NO]; nkeynes@964: [status setBordered: NO]; nkeynes@964: [[self contentView] addSubview: video]; nkeynes@964: [[self contentView] addSubview: status]; nkeynes@964: [self makeFirstResponder: video]; nkeynes@964: nkeynes@964: if( [self respondsToSelector:@selector(setAutorecalculatesContentBorderThickness:forEdge:)] ) nkeynes@964: [self setAutorecalculatesContentBorderThickness: NO forEdge: NSMinYEdge ]; nkeynes@964: if( [self respondsToSelector:@selector(setContentBorderThickness:forEdge:)] ) nkeynes@964: [self setContentBorderThickness: STATUSBAR_HEIGHT forEdge: NSMinYEdge]; nkeynes@964: nkeynes@964: // Share the app delegate for the purposes of keeping it in one place nkeynes@964: [self setDelegate: [NSApp delegate]]; nkeynes@964: [self setContentMinSize: contentRect.size]; nkeynes@964: [self setAcceptsMouseMovedEvents: YES]; nkeynes@964: [self updateTitle]; nkeynes@964: nkeynes@964: NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier: @"LxdreamToolbar"]; nkeynes@964: [toolbar setDelegate: [[LxdreamToolbarDelegate alloc] init]]; nkeynes@964: [toolbar setDisplayMode: NSToolbarDisplayModeIconOnly]; nkeynes@964: [toolbar setSizeMode: NSToolbarSizeModeSmall]; nkeynes@964: [toolbar setSelectedItemIdentifier: @"Pause"]; nkeynes@964: [self setToolbar: toolbar]; nkeynes@964: return self; nkeynes@964: } nkeynes@964: } nkeynes@964: nkeynes@964: - (void)updateTitle nkeynes@964: { nkeynes@964: NSString *title; nkeynes@964: const char *disc_title = gdrom_get_current_disc_title(); nkeynes@964: if( disc_title == NULL ) { nkeynes@1098: title = [NSString stringWithFormat: @"%s - ", lxdream_package_name]; nkeynes@964: } else { nkeynes@964: title = [NSString stringWithFormat: @"%s - %s", lxdream_package_name, disc_title]; nkeynes@964: } nkeynes@964: [self setTitle: title]; nkeynes@964: } nkeynes@964: nkeynes@964: - (void)setStatusText: (const gchar *)text nkeynes@964: { nkeynes@964: if( isGrabbed ) { nkeynes@964: gchar buf[128]; nkeynes@964: snprintf( buf, sizeof(buf), "%s %s", text, _("(Press to release grab)") ); nkeynes@964: NSString *s = [NSString stringWithUTF8String: buf]; nkeynes@964: [status setStringValue: s]; nkeynes@964: } else { nkeynes@964: NSString *s = [NSString stringWithUTF8String: text]; nkeynes@964: [status setStringValue: s]; nkeynes@964: } nkeynes@964: } nkeynes@964: - (void)setRunning:(BOOL)isRunning nkeynes@964: { nkeynes@964: if( isRunning ) { nkeynes@964: [[self toolbar] setSelectedItemIdentifier: @"Run"]; nkeynes@964: [self setStatusText: _("Running")]; nkeynes@964: } else { nkeynes@964: [[self toolbar] setSelectedItemIdentifier: @"Pause"]; nkeynes@964: [self setStatusText: _("Stopped")]; nkeynes@964: } nkeynes@964: } nkeynes@1028: - (BOOL)isFullscreen nkeynes@1028: { nkeynes@1028: return isFullscreen; nkeynes@1028: } nkeynes@1028: - (void)setFullscreen:(BOOL)full nkeynes@1028: { nkeynes@1028: if( full != isFullscreen ) { nkeynes@1028: isFullscreen = full; nkeynes@1028: nkeynes@1028: if( full ) { nkeynes@1028: savedFrame = [self frame]; nkeynes@1028: SetSystemUIMode( kUIModeAllHidden, 0 ); nkeynes@1028: NSRect screenRect = [[NSScreen mainScreen] frame]; nkeynes@1028: screenRect.size.height += STATUSBAR_HEIGHT; nkeynes@1028: screenRect.origin.y -= STATUSBAR_HEIGHT; nkeynes@1028: NSRect targetRect = [self frameRectForContentRect: screenRect]; nkeynes@1028: [self setFrame: targetRect display: YES]; nkeynes@1028: } else { nkeynes@1028: SetSystemUIMode( kUIModeNormal, 0 ); nkeynes@1028: [self setFrame: savedFrame display: YES]; nkeynes@1028: } nkeynes@1028: } nkeynes@1028: } nkeynes@964: - (BOOL)isGrabbed nkeynes@964: { nkeynes@964: return isGrabbed; nkeynes@964: } nkeynes@964: - (void)setIsGrabbed:(BOOL)grab nkeynes@964: { nkeynes@964: if( grab != isGrabbed ) { nkeynes@964: isGrabbed = grab; nkeynes@964: [self setRunning: dreamcast_is_running() ? YES : NO]; nkeynes@964: nkeynes@964: if( isGrabbed ) { nkeynes@964: [NSCursor hide]; nkeynes@964: CGAssociateMouseAndMouseCursorPosition(NO); nkeynes@964: } else { nkeynes@964: [NSCursor unhide]; nkeynes@964: CGAssociateMouseAndMouseCursorPosition(YES); nkeynes@964: } nkeynes@964: [video setIsGrabbed: isGrabbed]; nkeynes@964: } nkeynes@964: } nkeynes@964: - (void)setUseGrab:(BOOL)grab nkeynes@964: { nkeynes@964: if( grab != useGrab ) { nkeynes@964: if( !grab && isGrabbed ) { nkeynes@964: [self setIsGrabbed: NO]; nkeynes@964: } nkeynes@964: useGrab = grab; nkeynes@964: } nkeynes@964: } nkeynes@964: nkeynes@964: - (id)viewRequestedGrab: (id)sender nkeynes@964: { nkeynes@964: if( useGrab ) { nkeynes@964: [self setIsGrabbed: YES]; nkeynes@964: } nkeynes@964: return useGrab ? self : nil; nkeynes@964: } nkeynes@964: - (id)viewRequestedUngrab: (id)sender nkeynes@964: { nkeynes@964: [self setIsGrabbed: NO]; nkeynes@964: return useGrab ? self : nil; nkeynes@964: } nkeynes@1028: - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)aScreen nkeynes@1028: { nkeynes@1028: return frameRect; nkeynes@1028: } nkeynes@964: @end nkeynes@964: nkeynes@964: LxdreamMainWindow *cocoa_gui_create_main_window() nkeynes@964: { nkeynes@964: NSRect contentRect = {{0,0},{640,480}}; nkeynes@964: return [[LxdreamMainWindow alloc] initWithContentRect: contentRect]; nkeynes@964: }