| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/shell/shell.h" |
| |
| #include "base/logging.h" |
| #import "base/mac/cocoa_protocols.h" |
| #include "base/string_piece.h" |
| #include "base/sys_string_conversions.h" |
| #include "content/shell/resource.h" |
| #include "googleurl/src/gurl.h" |
| |
| // Receives notification that the window is closing so that it can start the |
| // tear-down process. Is responsible for deleting itself when done. |
| @interface ContentShellWindowDelegate : NSObject<NSWindowDelegate> { |
| @private |
| content::Shell* shell_; |
| } |
| - (id)initWithShell:(content::Shell*)shell; |
| @end |
| |
| @implementation ContentShellWindowDelegate |
| |
| - (id)initWithShell:(content::Shell*)shell { |
| if ((self = [super init])) { |
| shell_ = shell; |
| } |
| return self; |
| } |
| |
| // Called when the window is about to close. Perform the self-destruction |
| // sequence by getting rid of the shell and removing it and the window from |
| // the various global lists. Instead of doing it here, however, we fire off |
| // a delayed call to |-cleanup:| to allow everything to get off the stack |
| // before we go deleting objects. By returning YES, we allow the window to be |
| // removed from the screen. |
| - (BOOL)windowShouldClose:(id)window { |
| [window autorelease]; |
| |
| // Clean ourselves up and do the work after clearing the stack of anything |
| // that might have the shell on it. |
| [self performSelectorOnMainThread:@selector(cleanup:) |
| withObject:window |
| waitUntilDone:NO]; |
| |
| return YES; |
| } |
| |
| // Does the work of removing the window from our various bookkeeping lists |
| // and gets rid of the shell. |
| - (void)cleanup:(id)window { |
| delete shell_; |
| |
| [self release]; |
| } |
| |
| - (void)performAction:(id)sender { |
| shell_->ActionPerformed([sender tag]); |
| } |
| |
| - (void)takeURLStringValueFrom:(id)sender { |
| shell_->URLEntered(base::SysNSStringToUTF8([sender stringValue])); |
| } |
| |
| @end |
| |
| namespace { |
| |
| NSString* kWindowTitle = @"Content Shell"; |
| |
| const int kButtonWidth = 72; |
| const int kURLBarHeight = 24; |
| |
| void MakeShellButton(NSRect* rect, |
| NSString* title, |
| NSView* parent, |
| int control, |
| NSView* target) { |
| NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; |
| [button setTitle:title]; |
| [button setBezelStyle:NSSmallSquareBezelStyle]; |
| [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; |
| [button setTarget:target]; |
| [button setAction:@selector(performAction:)]; |
| [button setTag:control]; |
| [parent addSubview:button]; |
| rect->origin.x += kButtonWidth; |
| } |
| |
| } // namespace |
| |
| namespace content { |
| |
| void Shell::PlatformInitialize() { |
| } |
| |
| base::StringPiece Shell::PlatformResourceProvider(int key) { |
| return base::StringPiece(); |
| } |
| |
| void Shell::PlatformCleanUp() { |
| } |
| |
| void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) { |
| int id; |
| switch (control) { |
| case BACK_BUTTON: |
| id = IDC_NAV_BACK; |
| break; |
| case FORWARD_BUTTON: |
| id = IDC_NAV_FORWARD; |
| break; |
| case STOP_BUTTON: |
| id = IDC_NAV_STOP; |
| break; |
| default: |
| NOTREACHED() << "Unknown UI control"; |
| return; |
| } |
| [[[window_ contentView] viewWithTag:id] setEnabled:is_enabled]; |
| } |
| |
| void Shell::PlatformSetAddressBarURL(const GURL& url) { |
| NSString* url_string = base::SysUTF8ToNSString(url.spec()); |
| [url_edit_view_ setStringValue:url_string]; |
| } |
| |
| void Shell::PlatformSetIsLoading(bool loading) { |
| } |
| |
| void Shell::PlatformCreateWindow(int width, int height) { |
| NSRect initial_window_bounds = NSMakeRect(0, 0, width, height); |
| window_ = [[NSWindow alloc] initWithContentRect:initial_window_bounds |
| styleMask:(NSTitledWindowMask | |
| NSClosableWindowMask | |
| NSMiniaturizableWindowMask | |
| NSResizableWindowMask ) |
| backing:NSBackingStoreBuffered |
| defer:NO]; |
| [window_ setTitle:kWindowTitle]; |
| |
| // Rely on the window delegate to clean us up rather than immediately |
| // releasing when the window gets closed. We use the delegate to do |
| // everything from the autorelease pool so the shell isn't on the stack |
| // during cleanup (ie, a window close from javascript). |
| [window_ setReleasedWhenClosed:NO]; |
| |
| // Create a window delegate to watch for when it's asked to go away. It will |
| // clean itself up so we don't need to hold a reference. |
| ContentShellWindowDelegate* delegate = |
| [[ContentShellWindowDelegate alloc] initWithShell:this]; |
| [window_ setDelegate:delegate]; |
| |
| NSRect button_frame = |
| NSMakeRect(0, NSMaxY(initial_window_bounds) - kURLBarHeight, |
| kButtonWidth, kURLBarHeight); |
| |
| NSView* content = [window_ contentView]; |
| |
| MakeShellButton(&button_frame, @"Back", content, IDC_NAV_BACK, |
| (NSView*)delegate); |
| MakeShellButton(&button_frame, @"Forward", content, IDC_NAV_FORWARD, |
| (NSView*)delegate); |
| MakeShellButton(&button_frame, @"Reload", content, IDC_NAV_RELOAD, |
| (NSView*)delegate); |
| MakeShellButton(&button_frame, @"Stop", content, IDC_NAV_STOP, |
| (NSView*)delegate); |
| |
| button_frame.size.width = |
| NSWidth(initial_window_bounds) - NSMinX(button_frame); |
| url_edit_view_ = |
| [[[NSTextField alloc] initWithFrame:button_frame] autorelease]; |
| [content addSubview:url_edit_view_]; |
| [url_edit_view_ setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; |
| [url_edit_view_ setTarget:delegate]; |
| [url_edit_view_ setAction:@selector(takeURLStringValueFrom:)]; |
| [[url_edit_view_ cell] setWraps:NO]; |
| [[url_edit_view_ cell] setScrollable:YES]; |
| |
| // show the window |
| [window_ makeKeyAndOrderFront:nil]; |
| } |
| |
| void Shell::PlatformSetContents() { |
| // TODO(avi): I don't know what goes here. |
| } |
| |
| void Shell::PlatformSizeTo(int width, int height) { |
| NSRect frame = [window_ frame]; |
| frame.size = NSMakeSize(width, height); |
| [window_ setFrame:frame display:YES]; |
| } |
| |
| void Shell::PlatformResizeSubViews() { |
| // Not needed; subviews are bound. |
| } |
| |
| void Shell::ActionPerformed(int control) { |
| switch (control) { |
| case IDC_NAV_BACK: |
| GoBackOrForward(-1); |
| break; |
| case IDC_NAV_FORWARD: |
| GoBackOrForward(1); |
| break; |
| case IDC_NAV_RELOAD: |
| Reload(); |
| break; |
| case IDC_NAV_STOP: |
| Stop(); |
| break; |
| } |
| } |
| |
| void Shell::URLEntered(std::string url_string) { |
| if (!url_string.empty()) { |
| GURL url(url_string); |
| if (!url.has_scheme()) |
| url = GURL("http://" + url_string); |
| LoadURL(url); |
| } |
| } |
| |
| } // namespace content |