Add simple line layout toggle to MiniBrowser
[WebKit-https.git] / Tools / MiniBrowser / mac / WK1BrowserWindowController.m
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #import "WK1BrowserWindowController.h"
27
28 #import "AppDelegate.h"
29 #import "SettingsController.h"
30 #import <WebKit/WebKit.h>
31 #import <WebKit/WebNSURLExtras.h>
32 #import <WebKit/WebPreferences.h>
33 #import <WebKit/WebPreferencesPrivate.h>
34 #import <WebKit/WebPreferenceKeysPrivate.h>
35 #import <WebKit/WebViewPrivate.h>
36
37 @interface WK1BrowserWindowController () <WebFrameLoadDelegate, WebPolicyDelegate, WebResourceLoadDelegate, WebUIDelegate>
38 @end
39
40 @implementation WK1BrowserWindowController
41
42 - (void)awakeFromNib
43 {
44     _webView = [[WebView alloc] initWithFrame:[containerView bounds] frameName:nil groupName:@"MiniBrowser"];
45     [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
46
47     _webView.editable = self.isEditable;
48
49     [_webView setFrameLoadDelegate:self];
50     [_webView setUIDelegate:self];
51     [_webView setResourceLoadDelegate:self];
52     [_webView setPolicyDelegate:self];
53
54     [[WebPreferences standardPreferences] setFullScreenEnabled:YES];
55     [[WebPreferences standardPreferences] setDeveloperExtrasEnabled:YES];
56     [[WebPreferences standardPreferences] setImageControlsEnabled:YES];
57     [[WebPreferences standardPreferences] setServiceControlsEnabled:YES];
58     [[WebPreferences standardPreferences] setJavaScriptCanOpenWindowsAutomatically:YES];
59
60     [_webView _listenForLayoutMilestones:WebDidFirstLayout | WebDidFirstVisuallyNonEmptyLayout | WebDidHitRelevantRepaintedObjectsAreaThreshold];
61
62     [self didChangeSettings];
63
64     [containerView addSubview:_webView];
65 }
66
67 - (void)dealloc
68 {
69     [_webView setFrameLoadDelegate:nil];
70     [_webView setUIDelegate:nil];
71     [_webView setResourceLoadDelegate:nil];
72     [_webView release];
73
74     [super dealloc];
75 }
76
77 - (void)loadURLString:(NSString *)urlString
78 {
79     // FIXME: We shouldn't have to set the url text here.
80     [urlText setStringValue:urlString];
81     [self fetch:nil];
82 }
83
84 - (void)loadHTMLString:(NSString *)HTMLString
85 {
86     [_webView.mainFrame loadHTMLString:HTMLString baseURL:nil];
87 }
88
89 - (IBAction)fetch:(id)sender
90 {
91     [urlText setStringValue:[self addProtocolIfNecessary:[urlText stringValue]]];
92     NSURL *url = [NSURL _webkit_URLWithUserTypedString:urlText.stringValue];
93     [[_webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url]];
94 }
95
96 - (IBAction)setPageScale:(id)sender
97 {
98     CGFloat scale = [self pageScaleForMenuItemTag:[sender tag]];
99     [_webView _scaleWebView:scale atOrigin:NSZeroPoint];
100 }
101
102 - (IBAction)setViewScale:(id)sender
103 {
104 }
105
106 - (IBAction)reload:(id)sender
107 {
108     [_webView reload:sender];
109 }
110
111 - (IBAction)forceRepaint:(id)sender
112 {
113     [_webView setNeedsDisplay:YES];
114 }
115
116 - (IBAction)goBack:(id)sender
117 {
118     [_webView goBack:sender];
119 }
120
121 - (IBAction)goForward:(id)sender
122 {
123     [_webView goForward:sender];
124 }
125
126 static BOOL areEssentiallyEqual(double a, double b)
127 {
128     double tolerance = 0.001;
129     return (fabs(a - b) <= tolerance);
130 }
131
132 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
133 {
134     SEL action = [menuItem action];
135
136     if (action == @selector(zoomIn:))
137         return [self canZoomIn];
138     if (action == @selector(zoomOut:))
139         return [self canZoomOut];
140     if (action == @selector(resetZoom:))
141         return [self canResetZoom];
142
143     if (action == @selector(showHideWebView:))
144         [menuItem setTitle:[_webView isHidden] ? @"Show Web View" : @"Hide Web View"];
145     else if (action == @selector(removeReinsertWebView:))
146         [menuItem setTitle:[_webView window] ? @"Remove Web View" : @"Insert Web View"];
147     else if (action == @selector(toggleZoomMode:))
148         [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
149     else if (action == @selector(toggleEditable:))
150         [menuItem setState:self.isEditable ? NSOnState : NSOffState];
151
152     if (action == @selector(setPageScale:))
153         [menuItem setState:areEssentiallyEqual([_webView _viewScaleFactor], [self pageScaleForMenuItemTag:[menuItem tag]])];
154
155     return YES;
156 }
157
158 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
159 {
160     SEL action = [item action];
161
162     if (action == @selector(goBack:))
163         return [_webView canGoBack];
164     
165     if (action == @selector(goForward:))
166         return [_webView canGoForward];
167     
168     return YES;
169 }
170
171 - (void)validateToolbar
172 {
173     [toolbar validateVisibleItems];
174 }
175
176 - (BOOL)windowShouldClose:(id)sender
177 {
178     return YES;
179 }
180
181 - (void)windowWillClose:(NSNotification *)notification
182 {
183     [(BrowserAppDelegate *)[[NSApplication sharedApplication] delegate] browserWindowWillClose:self.window];
184     [self autorelease];
185 }
186
187 - (double)currentZoomFactor
188 {
189     return 1;
190 }
191
192 - (BOOL)canZoomIn
193 {
194     return [_webView canMakeTextLarger];
195 }
196
197 - (void)zoomIn:(id)sender
198 {
199     if (![self canZoomIn])
200         return;
201
202     [_webView makeTextLarger:sender];
203 }
204
205 - (BOOL)canZoomOut
206 {
207     return [_webView canMakeTextSmaller];
208 }
209
210 - (void)zoomOut:(id)sender
211 {
212     if (![self canZoomIn])
213         return;
214
215     [_webView makeTextSmaller:sender];
216 }
217
218 - (BOOL)canResetZoom
219 {
220     return [_webView canMakeTextStandardSize];
221 }
222
223 - (void)resetZoom:(id)sender
224 {
225     if (![self canResetZoom])
226         return;
227
228     [_webView makeTextStandardSize:sender];
229 }
230
231 - (IBAction)toggleZoomMode:(id)sender
232 {
233     // FIXME: non-text zoom not implemented.
234     _zoomTextOnly = !_zoomTextOnly;
235 }
236
237 - (IBAction)toggleShrinkToFit:(id)sender
238 {
239 }
240
241 - (IBAction)dumpSourceToConsole:(id)sender
242 {
243 }
244
245 - (NSURL *)currentURL
246 {
247     return _webView.mainFrame.dataSource.request.URL;
248 }
249
250 - (NSView *)mainContentView
251 {
252     return _webView;
253 }
254
255 - (void)setEditable:(BOOL)editable
256 {
257     [super setEditable:editable];
258     _webView.editable = editable;
259 }
260
261 - (void)didChangeSettings
262 {
263     SettingsController *settings = [SettingsController shared];
264
265     [[WebPreferences standardPreferences] setSubpixelCSSOMElementMetricsEnabled:settings.subPixelCSSOMMetricsEnabled];
266     [[WebPreferences standardPreferences] setShowDebugBorders:settings.layerBordersVisible];
267     [[WebPreferences standardPreferences] setSimpleLineLayoutEnabled:settings.simpleLineLayoutEnabled];
268     [[WebPreferences standardPreferences] setSimpleLineLayoutDebugBordersEnabled:settings.simpleLineLayoutDebugBordersEnabled];
269     [[WebPreferences standardPreferences] setShowRepaintCounter:settings.layerBordersVisible];
270     [[WebPreferences standardPreferences] setSuppressesIncrementalRendering:settings.incrementalRenderingSuppressed];
271     [[WebPreferences standardPreferences] setAcceleratedDrawingEnabled:settings.acceleratedDrawingEnabled];
272     [[WebPreferences standardPreferences] setResourceLoadStatisticsEnabled:settings.resourceLoadStatisticsEnabled];
273     [[WebPreferences standardPreferences] setVisualViewportEnabled:settings.visualViewportEnabled];
274     [[WebPreferences standardPreferences] setLargeImageAsyncDecodingEnabled:settings.largeImageAsyncDecodingEnabled];
275     [[WebPreferences standardPreferences] setAnimatedImageAsyncDecodingEnabled:settings.animatedImageAsyncDecodingEnabled];
276
277     BOOL useTransparentWindows = settings.useTransparentWindows;
278     if (useTransparentWindows != !self.window.isOpaque) {
279         [self.window setOpaque:!useTransparentWindows];
280         [self.window setBackgroundColor:[NSColor clearColor]];
281         [self.window setHasShadow:!useTransparentWindows];
282
283         [_webView setBackgroundColor:useTransparentWindows ? [NSColor clearColor] : [NSColor whiteColor]];
284
285         [self.window display];
286     }
287
288     BOOL usePaginatedMode = settings.usePaginatedMode;
289     if (usePaginatedMode != (_webView._paginationMode != WebPaginationModeUnpaginated)) {
290         if (usePaginatedMode) {
291             [_webView _setPaginationMode:WebPaginationModeLeftToRight];
292             [_webView _setPageLength:_webView.bounds.size.width / 2];
293             [_webView _setGapBetweenPages:10];
294         } else
295             [_webView _setPaginationMode:WebPaginationModeUnpaginated];
296     }
297 }
298
299 - (IBAction)printWebView:(id)sender
300 {
301     [[[[_webView mainFrame] frameView] printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]] runOperationModalForWindow:self.window delegate:nil didRunSelector:nil contextInfo:nil];
302 }
303
304 - (void)webView:(WebView *)sender didLayout:(WebLayoutMilestones)milestones
305 {
306     if (milestones & WebDidFirstLayout)
307         LOG(@"layout milestone: %@", @"first layout");
308
309     if (milestones & WebDidFirstVisuallyNonEmptyLayout)
310         LOG(@"layout milestone: %@", @"first non-empty layout");
311
312     if (milestones & WebDidHitRelevantRepaintedObjectsAreaThreshold)
313         LOG(@"layout milestone: %@", @"relevant repainted objects area threshold");
314 }
315
316 - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
317 {
318     [listener use];
319 }
320
321 // WebFrameLoadDelegate Methods
322 - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
323 {
324 }
325
326 - (void)updateTitle:(NSString *)title
327 {
328     if (!title) {
329         NSURL *url = _webView.mainFrame.dataSource.request.URL;
330         title = url.lastPathComponent ?: url._web_userVisibleString;
331     }
332
333     [self.window setTitle:[title stringByAppendingFormat:@" [WK1]%@", _webView.editable ? @" [Editable]" : @""]];
334 }
335
336 - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request
337 {
338     WK1BrowserWindowController *newBrowserWindowController = [[WK1BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"];
339     [newBrowserWindowController.window makeKeyAndOrderFront:self];
340
341     return newBrowserWindowController->_webView;
342 }
343
344 - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
345 {
346     if (frame != [sender mainFrame])
347         return;
348
349     NSURL *committedURL = [[[frame dataSource] request] URL];
350     urlText.stringValue = committedURL._web_userVisibleString;
351
352     [self updateTitle:nil];
353 }
354
355 - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
356 {
357     if (frame != [sender mainFrame])
358         return;
359
360     [self updateTitle:title];
361 }
362
363 - (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
364 {
365     return defaultMenuItems;
366 }
367
368 - (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
369 {
370     NSAlert *alert = [[NSAlert alloc] init];
371     [alert addButtonWithTitle:@"OK"];
372
373     alert.messageText = [NSString stringWithFormat:@"JavaScript alert dialog from %@.", frame.dataSource.request.URL.absoluteString];
374     alert.informativeText = message;
375
376     [alert runModal];
377     [alert release];
378 }
379
380 - (BOOL)webView:(WebView *)sender runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
381 {
382     NSAlert *alert = [[NSAlert alloc] init];
383
384     alert.messageText = [NSString stringWithFormat:@"JavaScript before unload dialog from %@.", frame.dataSource.request.URL.absoluteString];
385     alert.informativeText = message;
386
387     [alert addButtonWithTitle:@"Leave Page"];
388     [alert addButtonWithTitle:@"Stay On Page"];
389
390     NSModalResponse response = [alert runModal];
391     
392     [alert release];
393
394     return response == NSAlertFirstButtonReturn;
395 }
396
397 @end