/* * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #import "AppDelegate.h" #import "CannedContent.h" #import "EditingOperations.h" #import "WK1WebDocumentController.h" #import "WK2WebDocumentController.h" #import static NSString * const UseWebKit2ByDefaultPreferenceKey = @"UseWebKit2ByDefault"; @implementation WebEditingAppDelegate { Class _openingDocumentController; } - (id)init { self = [super init]; if (self) _webDocuments = [[NSMutableSet alloc] init]; return self; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [NSURLProtocol registerClass:[CannedContent class]]; [WKBrowsingContextController registerSchemeForCustomProtocol:@"canned"]; [self newEditor:self]; [self _updateNewWindowKeyEquivalents]; } - (IBAction)newEditor:(id)sender { Class controllerClass; if (sender == self) controllerClass = self._defaultWebDocumentControllerClass; else if (sender == _newWebKit2EditorItem) controllerClass = [WK2WebDocumentController class]; else if (sender == _newWebKit1EditorItem) controllerClass = [WK1WebDocumentController class]; WebDocumentController *controller = [[controllerClass alloc] init]; [[controller window] makeKeyAndOrderFront:sender]; [_webDocuments addObject:controller]; [controller loadHTMLString:[WebDocumentController defaultEditingSource]]; } - (IBAction)showOperations:(id)sender { static BOOL initialized = NO; if (!initialized) { NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeMini]]; NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; NSArray *operations = editingOperations(); float maxWidth = 0; for (NSString *operationName in operations) maxWidth = MAX(maxWidth, [operationName sizeWithAttributes:attributes].width); maxWidth += 24; unsigned long columnHeight = (operations.count + 2) / 3; NSView *superview = [_operationsPanel contentView]; [_operationsPanel setContentSize:NSMakeSize(3 * maxWidth, columnHeight * 16 + 1)]; float firstY = NSMaxY([superview frame]) - 1; float y = firstY; float x = 0; for (NSString *operationName in operations) { y -= 16; if (y < 0) { y = firstY - 16; x += maxWidth; } NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, maxWidth, 16)]; [button setBezelStyle:NSRoundedBezelStyle]; [button.cell setControlSize:NSControlSizeMini]; [button setFont:font]; [button setTitle:operationName]; [button setAction:NSSelectorFromString(operationName)]; [superview addSubview:button]; } [_operationsPanel center]; [_operationsPanel setFloatingPanel:YES]; [_operationsPanel setBecomesKeyOnlyIfNeeded:YES]; initialized = YES; } [_operationsPanel orderFront:nil]; } - (Class)_defaultWebDocumentControllerClass { return self.useWebKit2ByDefault ? [WK2WebDocumentController class] : [WK1WebDocumentController class]; } - (BOOL)useWebKit2ByDefault { return [[NSUserDefaults standardUserDefaults] boolForKey:UseWebKit2ByDefaultPreferenceKey]; } - (IBAction)toggleUseWebKit2ByDefault:(id)sender { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setBool:![defaults boolForKey:UseWebKit2ByDefaultPreferenceKey] forKey:UseWebKit2ByDefaultPreferenceKey]; [self _updateNewWindowKeyEquivalents]; } - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { SEL action = [menuItem action]; if (action == @selector(toggleUseWebKit2ByDefault:)) [menuItem setState:[self useWebKit2ByDefault] ? NSOnState : NSOffState]; return YES; } - (void)_openDocumentWithWebKit1:(id)sender { _openingDocumentController = [WK1WebDocumentController class]; } - (void)_openDocumentWithWebKit2:(id)sender { _openingDocumentController = [WK2WebDocumentController class]; } - (IBAction)openDocument:(id)sender { _openingDocumentController = self._defaultWebDocumentControllerClass; NSButtonCell *radioButtonPrototype = [[NSButtonCell alloc] init]; radioButtonPrototype.buttonType = NSRadioButton; NSMatrix *openPanelAccessoryView = [[NSMatrix alloc] initWithFrame:NSZeroRect mode:NSRadioModeMatrix prototype:radioButtonPrototype numberOfRows:2 numberOfColumns:1]; openPanelAccessoryView.autorecalculatesCellSize = YES; openPanelAccessoryView.autosizesCells = YES; NSArray *cells = openPanelAccessoryView.cells; [[cells objectAtIndex:0] setTitle:@"Open with WebKit1"]; [[cells objectAtIndex:0] setAction:@selector(_openDocumentWithWebKit1:)]; [[cells objectAtIndex:0] setState:!self.useWebKit2ByDefault]; [[cells objectAtIndex:1] setTitle:@"Open with WebKit2"]; [[cells objectAtIndex:1] setAction:@selector(_openDocumentWithWebKit2:)]; [[cells objectAtIndex:1] setState:self.useWebKit2ByDefault]; [openPanelAccessoryView sizeToFit]; NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setAccessoryView:openPanelAccessoryView]; [panel beginWithCompletionHandler:^(NSInteger result) { if (result != NSFileHandlingPanelOKButton) return; NSURL *URL = panel.URLs.lastObject; [self application:[NSApplication sharedApplication] openFile:URL.path]; _openingDocumentController = nil; }]; } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { Class controllerClass = _openingDocumentController ? _openingDocumentController : self._defaultWebDocumentControllerClass; WebDocumentController *controller = [[controllerClass alloc] init]; [controller.window makeKeyAndOrderFront:nil]; [_webDocuments addObject:controller]; [controller loadHTMLString:[NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:nil]]; return YES; } - (void)_updateNewWindowKeyEquivalents { if (self.useWebKit2ByDefault) { [_newWebKit1EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption]; [_newWebKit2EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand]; } else { [_newWebKit1EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand]; [_newWebKit2EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption]; } } - (void)performTextFinderAction:(id)sender { id keyWindowDelegate = [NSApplication sharedApplication].keyWindow.delegate; if (![keyWindowDelegate isKindOfClass:[WebDocumentController class]]) return; [(WebDocumentController *)keyWindowDelegate performTextFinderAction:sender]; } @end