2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 #import "AppDelegate.h"
28 #import "CannedContent.h"
29 #import "EditingOperations.h"
30 #import "WK1WebDocumentController.h"
31 #import "WK2WebDocumentController.h"
32 #import <WebKit/WKBrowsingContextController.h>
34 static NSString * const UseWebKit2ByDefaultPreferenceKey = @"UseWebKit2ByDefault";
36 @implementation WebEditingAppDelegate {
37 Class _openingDocumentController;
44 _webDocuments = [[NSMutableSet alloc] init];
49 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
51 [NSURLProtocol registerClass:[CannedContent class]];
52 [WKBrowsingContextController registerSchemeForCustomProtocol:@"canned"];
54 [self newEditor:self];
55 [self _updateNewWindowKeyEquivalents];
58 - (IBAction)newEditor:(id)sender
60 Class controllerClass;
63 controllerClass = self._defaultWebDocumentControllerClass;
64 else if (sender == _newWebKit2EditorItem)
65 controllerClass = [WK2WebDocumentController class];
66 else if (sender == _newWebKit1EditorItem)
67 controllerClass = [WK1WebDocumentController class];
69 WebDocumentController *controller = [[controllerClass alloc] init];
70 [[controller window] makeKeyAndOrderFront:sender];
71 [_webDocuments addObject:controller];
72 [controller loadHTMLString:[WebDocumentController defaultEditingSource]];
75 - (IBAction)showOperations:(id)sender
77 static BOOL initialized = NO;
80 NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeMini]];
81 NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
82 NSArray *operations = editingOperations();
85 for (NSString *operationName in operations)
86 maxWidth = MAX(maxWidth, [operationName sizeWithAttributes:attributes].width);
90 unsigned long columnHeight = (operations.count + 2) / 3;
92 NSView *superview = [_operationsPanel contentView];
94 [_operationsPanel setContentSize:NSMakeSize(3 * maxWidth, columnHeight * 16 + 1)];
96 float firstY = NSMaxY([superview frame]) - 1;
99 for (NSString *operationName in operations) {
105 NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(x, y, maxWidth, 16)];
106 [button setBezelStyle:NSRoundedBezelStyle];
107 [button.cell setControlSize:NSControlSizeMini];
108 [button setFont:font];
109 [button setTitle:operationName];
110 [button setAction:NSSelectorFromString(operationName)];
111 [superview addSubview:button];
114 [_operationsPanel center];
115 [_operationsPanel setFloatingPanel:YES];
116 [_operationsPanel setBecomesKeyOnlyIfNeeded:YES];
120 [_operationsPanel orderFront:nil];
123 - (Class)_defaultWebDocumentControllerClass
125 return self.useWebKit2ByDefault ? [WK2WebDocumentController class] : [WK1WebDocumentController class];
128 - (BOOL)useWebKit2ByDefault
130 return [[NSUserDefaults standardUserDefaults] boolForKey:UseWebKit2ByDefaultPreferenceKey];
133 - (IBAction)toggleUseWebKit2ByDefault:(id)sender
135 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
136 [defaults setBool:![defaults boolForKey:UseWebKit2ByDefaultPreferenceKey] forKey:UseWebKit2ByDefaultPreferenceKey];
137 [self _updateNewWindowKeyEquivalents];
140 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
142 SEL action = [menuItem action];
144 if (action == @selector(toggleUseWebKit2ByDefault:))
145 [menuItem setState:[self useWebKit2ByDefault] ? NSOnState : NSOffState];
150 - (void)_openDocumentWithWebKit1:(id)sender
152 _openingDocumentController = [WK1WebDocumentController class];
155 - (void)_openDocumentWithWebKit2:(id)sender
157 _openingDocumentController = [WK2WebDocumentController class];
160 - (IBAction)openDocument:(id)sender
162 _openingDocumentController = self._defaultWebDocumentControllerClass;
164 NSButtonCell *radioButtonPrototype = [[NSButtonCell alloc] init];
165 radioButtonPrototype.buttonType = NSRadioButton;
167 NSMatrix *openPanelAccessoryView = [[NSMatrix alloc] initWithFrame:NSZeroRect mode:NSRadioModeMatrix prototype:radioButtonPrototype numberOfRows:2 numberOfColumns:1];
168 openPanelAccessoryView.autorecalculatesCellSize = YES;
169 openPanelAccessoryView.autosizesCells = YES;
170 NSArray *cells = openPanelAccessoryView.cells;
171 [[cells objectAtIndex:0] setTitle:@"Open with WebKit1"];
172 [[cells objectAtIndex:0] setAction:@selector(_openDocumentWithWebKit1:)];
173 [[cells objectAtIndex:0] setState:!self.useWebKit2ByDefault];
174 [[cells objectAtIndex:1] setTitle:@"Open with WebKit2"];
175 [[cells objectAtIndex:1] setAction:@selector(_openDocumentWithWebKit2:)];
176 [[cells objectAtIndex:1] setState:self.useWebKit2ByDefault];
177 [openPanelAccessoryView sizeToFit];
179 NSOpenPanel *panel = [NSOpenPanel openPanel];
180 [panel setAccessoryView:openPanelAccessoryView];
182 [panel beginWithCompletionHandler:^(NSInteger result) {
183 if (result != NSFileHandlingPanelOKButton)
186 NSURL *URL = panel.URLs.lastObject;
187 [self application:[NSApplication sharedApplication] openFile:URL.path];
188 _openingDocumentController = nil;
192 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
194 Class controllerClass = _openingDocumentController ? _openingDocumentController : self._defaultWebDocumentControllerClass;
195 WebDocumentController *controller = [[controllerClass alloc] init];
196 [controller.window makeKeyAndOrderFront:nil];
197 [_webDocuments addObject:controller];
198 [controller loadHTMLString:[NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:nil]];
202 - (void)_updateNewWindowKeyEquivalents
204 if (self.useWebKit2ByDefault) {
205 [_newWebKit1EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption];
206 [_newWebKit2EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
208 [_newWebKit1EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
209 [_newWebKit2EditorItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption];
213 - (void)performTextFinderAction:(id)sender
215 id keyWindowDelegate = [NSApplication sharedApplication].keyWindow.delegate;
216 if (![keyWindowDelegate isKindOfClass:[WebDocumentController class]])
218 [(WebDocumentController *)keyWindowDelegate performTextFinderAction:sender];