nkeynes@681 | 1 | /**
|
nkeynes@681 | 2 | * $Id$
|
nkeynes@681 | 3 | *
|
nkeynes@681 | 4 | * Construct and maintain the main window under cocoa.
|
nkeynes@681 | 5 | *
|
nkeynes@681 | 6 | * Copyright (c) 2008 Nathan Keynes.
|
nkeynes@681 | 7 | *
|
nkeynes@681 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@681 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@681 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@681 | 11 | * (at your option) any later version.
|
nkeynes@681 | 12 | *
|
nkeynes@681 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@681 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@681 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@681 | 16 | * GNU General Public License for more details.
|
nkeynes@681 | 17 | */
|
nkeynes@681 | 18 |
|
nkeynes@681 | 19 | #include "cocoaui/cocoaui.h"
|
nkeynes@681 | 20 | #include "lxdream.h"
|
nkeynes@786 | 21 | #include "dreamcast.h"
|
nkeynes@837 | 22 | #include "gdrom/gdrom.h"
|
nkeynes@681 | 23 | #include <ApplicationServices/ApplicationServices.h>
|
nkeynes@681 | 24 |
|
nkeynes@757 | 25 | @interface NSWindow (OSX10_5_and_later)
|
nkeynes@757 | 26 | #ifndef CGFLOAT_DEFINED
|
nkeynes@757 | 27 | # ifdef __LP64__
|
nkeynes@757 | 28 | typedef double CGFloat;
|
nkeynes@757 | 29 | # else
|
nkeynes@757 | 30 | typedef float CGFloat;
|
nkeynes@757 | 31 | # endif
|
nkeynes@757 | 32 | #endif
|
nkeynes@757 | 33 | - (void)setAutorecalculatesContentBorderThickness:(BOOL)b forEdge:(NSRectEdge)e;
|
nkeynes@757 | 34 | - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e;
|
nkeynes@757 | 35 | @end
|
nkeynes@757 | 36 |
|
nkeynes@757 | 37 |
|
nkeynes@757 | 38 | #if NSAppKitVersionNumber > NSAppKitVersionNumber10_4
|
nkeynes@757 | 39 |
|
nkeynes@757 | 40 | #endif
|
nkeynes@757 | 41 |
|
nkeynes@705 | 42 | #define STATUSBAR_HEIGHT 25
|
nkeynes@705 | 43 | #define STATUS_TEXT_HEIGHT 22
|
nkeynes@681 | 44 |
|
nkeynes@681 | 45 | @interface LxdreamToolbarDelegate : NSObject {
|
nkeynes@681 | 46 | NSArray *identifiers;
|
nkeynes@681 | 47 | NSArray *defaults;
|
nkeynes@681 | 48 | NSDictionary *items;
|
nkeynes@681 | 49 | }
|
nkeynes@681 | 50 | - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label
|
nkeynes@736 | 51 | tooltip: (NSString *)tooltip
|
nkeynes@736 | 52 | icon: (NSString *)icon action: (SEL) action;
|
nkeynes@681 | 53 | @end
|
nkeynes@681 | 54 |
|
nkeynes@681 | 55 | @implementation LxdreamToolbarDelegate
|
nkeynes@681 | 56 | - (id) init
|
nkeynes@681 | 57 | {
|
nkeynes@681 | 58 | NSToolbarItem *mount = [self createToolbarItem: @"GdromMount" label: @"Open Image"
|
nkeynes@681 | 59 | tooltip: @"Mount a cdrom disc" icon: @"tb-cdrom"
|
nkeynes@681 | 60 | action: @selector(mount_action:)];
|
nkeynes@681 | 61 | NSToolbarItem *reset = [self createToolbarItem: @"Reset" label: @"Reset"
|
nkeynes@681 | 62 | tooltip: @"Reset dreamcast" icon: @"tb-reset"
|
nkeynes@681 | 63 | action: @selector(reset_action:)];
|
nkeynes@681 | 64 | NSToolbarItem *pause = [self createToolbarItem: @"Pause" label: @"Pause"
|
nkeynes@681 | 65 | tooltip: @"Pause dreamcast" icon: @"tb-pause"
|
nkeynes@681 | 66 | action: @selector(pause_action:)];
|
nkeynes@681 | 67 | NSToolbarItem *run = [self createToolbarItem: @"Run" label: @"Resume"
|
nkeynes@736 | 68 | tooltip: @"Resume" icon: @"tb-run"
|
nkeynes@736 | 69 | action: @selector(run_action:)];
|
nkeynes@681 | 70 | NSToolbarItem *load = [self createToolbarItem: @"LoadState" label: @"Load State..."
|
nkeynes@736 | 71 | tooltip: @"Load an lxdream save state" icon: @"tb-load"
|
nkeynes@736 | 72 | action: @selector(load_action:)];
|
nkeynes@681 | 73 | NSToolbarItem *save = [self createToolbarItem: @"SaveState" label: @"Save State..."
|
nkeynes@736 | 74 | tooltip: @"Create an lxdream save state" icon: @"tb-save"
|
nkeynes@736 | 75 | action: @selector(save_action:)];
|
nkeynes@681 | 76 | [pause setEnabled: NO];
|
nkeynes@681 | 77 | identifiers =
|
nkeynes@681 | 78 | [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run", @"LoadState", @"SaveState", nil ];
|
nkeynes@681 | 79 | defaults =
|
nkeynes@681 | 80 | [NSArray arrayWithObjects: @"GdromMount", @"Reset", @"Pause", @"Run",
|
nkeynes@736 | 81 | NSToolbarSeparatorItemIdentifier, @"LoadState", @"SaveState", nil ];
|
nkeynes@681 | 82 | NSArray *values = [NSArray arrayWithObjects: mount, reset, pause, run, load, save, nil ];
|
nkeynes@681 | 83 | items = [NSDictionary dictionaryWithObjects: values forKeys: identifiers];
|
nkeynes@681 | 84 | return self;
|
nkeynes@681 | 85 | }
|
nkeynes@681 | 86 |
|
nkeynes@681 | 87 | - (NSToolbarItem *) createToolbarItem: (NSString *)id label: (NSString *) label
|
nkeynes@736 | 88 | tooltip: (NSString *)tooltip icon: (NSString *)icon action: (SEL) action
|
nkeynes@681 | 89 | {
|
nkeynes@681 | 90 | NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier: id];
|
nkeynes@681 | 91 | [item setLabel: label];
|
nkeynes@681 | 92 | [item setToolTip: tooltip];
|
nkeynes@681 | 93 | [item setTarget: [NSApp delegate]];
|
nkeynes@681 | 94 | NSString *iconFile = [[NSBundle mainBundle] pathForResource:icon ofType:@"png"];
|
nkeynes@681 | 95 | NSImage *image = [[NSImage alloc] initWithContentsOfFile: iconFile];
|
nkeynes@681 | 96 | [item setImage: image];
|
nkeynes@681 | 97 | [item setAction: action];
|
nkeynes@681 | 98 | return item;
|
nkeynes@681 | 99 | }
|
nkeynes@681 | 100 |
|
nkeynes@681 | 101 | - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
|
nkeynes@681 | 102 | {
|
nkeynes@681 | 103 | return identifiers;
|
nkeynes@681 | 104 | }
|
nkeynes@681 | 105 |
|
nkeynes@681 | 106 | - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
|
nkeynes@681 | 107 | {
|
nkeynes@681 | 108 | return defaults;
|
nkeynes@681 | 109 | }
|
nkeynes@681 | 110 |
|
nkeynes@681 | 111 | - (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar
|
nkeynes@681 | 112 | {
|
nkeynes@681 | 113 | return [NSArray arrayWithObjects: @"Pause", @"Run", nil];
|
nkeynes@681 | 114 | }
|
nkeynes@681 | 115 |
|
nkeynes@681 | 116 | - (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier
|
nkeynes@736 | 117 | willBeInsertedIntoToolbar:(BOOL)flag
|
nkeynes@681 | 118 | {
|
nkeynes@736 | 119 | return [items objectForKey: itemIdentifier];
|
nkeynes@681 | 120 | }
|
nkeynes@681 | 121 | @end
|
nkeynes@681 | 122 |
|
nkeynes@681 | 123 | @implementation LxdreamMainWindow
|
nkeynes@681 | 124 | - (id)initWithContentRect:(NSRect)videoRect
|
nkeynes@681 | 125 | {
|
nkeynes@681 | 126 | NSRect contentRect = NSMakeRect(videoRect.origin.x,videoRect.origin.y,
|
nkeynes@681 | 127 | videoRect.size.width,videoRect.size.height+STATUSBAR_HEIGHT);
|
nkeynes@681 | 128 | if( [super initWithContentRect: contentRect
|
nkeynes@736 | 129 | styleMask: ( NSTitledWindowMask | NSClosableWindowMask |
|
nkeynes@736 | 130 | NSMiniaturizableWindowMask | NSResizableWindowMask |
|
nkeynes@736 | 131 | NSUnifiedTitleAndToolbarWindowMask )
|
nkeynes@736 | 132 | backing: NSBackingStoreBuffered defer: NO ] == nil ) {
|
nkeynes@681 | 133 | return nil;
|
nkeynes@681 | 134 | } else {
|
nkeynes@681 | 135 | isGrabbed = NO;
|
nkeynes@780 | 136 | video = (LxdreamVideoView *)video_osx_create_drawable();
|
nkeynes@681 | 137 | [video setFrameOrigin: NSMakePoint(0.0,STATUSBAR_HEIGHT)];
|
nkeynes@780 | 138 | [video setDelegate: self];
|
nkeynes@736 | 139 |
|
nkeynes@681 | 140 | status =
|
nkeynes@705 | 141 | [[NSTextField alloc] initWithFrame: NSMakeRect(0.0,0.0,videoRect.size.width,STATUS_TEXT_HEIGHT)];
|
nkeynes@681 | 142 | [status setStringValue: @"Idle"];
|
nkeynes@681 | 143 | [status setEditable: NO];
|
nkeynes@681 | 144 | [status setDrawsBackground: NO];
|
nkeynes@681 | 145 | [status setBordered: NO];
|
nkeynes@681 | 146 | [[self contentView] addSubview: video];
|
nkeynes@681 | 147 | [[self contentView] addSubview: status];
|
nkeynes@681 | 148 | [self makeFirstResponder: video];
|
nkeynes@681 | 149 |
|
nkeynes@757 | 150 | if( [self respondsToSelector:@selector(setAutorecalculatesContentBorderThickness:forEdge:)] )
|
nkeynes@757 | 151 | [self setAutorecalculatesContentBorderThickness: NO forEdge: NSMinYEdge ];
|
nkeynes@757 | 152 | if( [self respondsToSelector:@selector(setContentBorderThickness:forEdge:)] )
|
nkeynes@757 | 153 | [self setContentBorderThickness: STATUSBAR_HEIGHT forEdge: NSMinYEdge];
|
nkeynes@681 | 154 |
|
nkeynes@681 | 155 | // Share the app delegate for the purposes of keeping it in one place
|
nkeynes@681 | 156 | [self setDelegate: [NSApp delegate]];
|
nkeynes@681 | 157 | [self setContentMinSize: contentRect.size];
|
nkeynes@681 | 158 | [self setAcceptsMouseMovedEvents: YES];
|
nkeynes@837 | 159 | [self updateTitle];
|
nkeynes@681 | 160 |
|
nkeynes@681 | 161 | NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier: @"LxdreamToolbar"];
|
nkeynes@681 | 162 | [toolbar setDelegate: [[LxdreamToolbarDelegate alloc] init]];
|
nkeynes@681 | 163 | [toolbar setDisplayMode: NSToolbarDisplayModeIconOnly];
|
nkeynes@681 | 164 | [toolbar setSizeMode: NSToolbarSizeModeSmall];
|
nkeynes@681 | 165 | [toolbar setSelectedItemIdentifier: @"Pause"];
|
nkeynes@681 | 166 | [self setToolbar: toolbar];
|
nkeynes@681 | 167 | return self;
|
nkeynes@681 | 168 | }
|
nkeynes@681 | 169 | }
|
nkeynes@681 | 170 |
|
nkeynes@837 | 171 | - (void)updateTitle
|
nkeynes@837 | 172 | {
|
nkeynes@837 | 173 | NSString *title;
|
nkeynes@837 | 174 | const char *disc_title = gdrom_get_current_disc_title();
|
nkeynes@837 | 175 | if( disc_title == NULL ) {
|
nkeynes@837 | 176 | title = [NSString stringWithCString: lxdream_package_name];
|
nkeynes@837 | 177 | } else {
|
nkeynes@837 | 178 | title = [NSString stringWithFormat: @"%s - %s", lxdream_package_name, disc_title];
|
nkeynes@837 | 179 | }
|
nkeynes@837 | 180 | [self setTitle: title];
|
nkeynes@837 | 181 | }
|
nkeynes@837 | 182 |
|
nkeynes@681 | 183 | - (void)setStatusText: (const gchar *)text
|
nkeynes@681 | 184 | {
|
nkeynes@681 | 185 | if( isGrabbed ) {
|
nkeynes@681 | 186 | gchar buf[128];
|
nkeynes@681 | 187 | snprintf( buf, sizeof(buf), "%s %s", text, _("(Press <ctrl><alt> to release grab)") );
|
nkeynes@681 | 188 | NSString *s = [NSString stringWithUTF8String: buf];
|
nkeynes@681 | 189 | [status setStringValue: s];
|
nkeynes@681 | 190 | } else {
|
nkeynes@681 | 191 | NSString *s = [NSString stringWithUTF8String: text];
|
nkeynes@681 | 192 | [status setStringValue: s];
|
nkeynes@681 | 193 | }
|
nkeynes@681 | 194 | }
|
nkeynes@681 | 195 | - (void)setRunning:(BOOL)isRunning
|
nkeynes@681 | 196 | {
|
nkeynes@681 | 197 | if( isRunning ) {
|
nkeynes@681 | 198 | [[self toolbar] setSelectedItemIdentifier: @"Run"];
|
nkeynes@681 | 199 | [self setStatusText: _("Running")];
|
nkeynes@681 | 200 | } else {
|
nkeynes@681 | 201 | [[self toolbar] setSelectedItemIdentifier: @"Pause"];
|
nkeynes@681 | 202 | [self setStatusText: _("Stopped")];
|
nkeynes@681 | 203 | }
|
nkeynes@681 | 204 | }
|
nkeynes@681 | 205 | - (BOOL)isGrabbed
|
nkeynes@681 | 206 | {
|
nkeynes@681 | 207 | return isGrabbed;
|
nkeynes@681 | 208 | }
|
nkeynes@681 | 209 | - (void)setIsGrabbed:(BOOL)grab
|
nkeynes@681 | 210 | {
|
nkeynes@681 | 211 | if( grab != isGrabbed ) {
|
nkeynes@681 | 212 | isGrabbed = grab;
|
nkeynes@681 | 213 | [self setRunning: dreamcast_is_running() ? YES : NO];
|
nkeynes@780 | 214 |
|
nkeynes@780 | 215 | if( isGrabbed ) {
|
nkeynes@780 | 216 | [NSCursor hide];
|
nkeynes@780 | 217 | CGAssociateMouseAndMouseCursorPosition(NO);
|
nkeynes@780 | 218 | } else {
|
nkeynes@780 | 219 | [NSCursor unhide];
|
nkeynes@780 | 220 | CGAssociateMouseAndMouseCursorPosition(YES);
|
nkeynes@780 | 221 | }
|
nkeynes@780 | 222 | [video setIsGrabbed: isGrabbed];
|
nkeynes@681 | 223 | }
|
nkeynes@681 | 224 | }
|
nkeynes@780 | 225 | - (void)viewRequestedGrab: (id)sender
|
nkeynes@780 | 226 | {
|
nkeynes@780 | 227 | [self setIsGrabbed: YES];
|
nkeynes@780 | 228 | }
|
nkeynes@780 | 229 | - (void)viewRequestedUngrab: (id)sender
|
nkeynes@780 | 230 | {
|
nkeynes@780 | 231 | [self setIsGrabbed: NO];
|
nkeynes@780 | 232 | }
|
nkeynes@681 | 233 | @end
|
nkeynes@681 | 234 |
|
nkeynes@681 | 235 | NSWindow *cocoa_gui_create_main_window()
|
nkeynes@681 | 236 | {
|
nkeynes@736 | 237 | NSRect contentRect = {{0,0},{640,480}};
|
nkeynes@736 | 238 | NSWindow *main_win = [[LxdreamMainWindow alloc] initWithContentRect: contentRect];
|
nkeynes@736 | 239 | return main_win;
|
nkeynes@681 | 240 | }
|