-
akalin@chromium.org authored
of HtmlDialogView. Added TODO to fix inaccurate font height metric for OS X font class (and maybe width). Added the BrowserCommandExecutor protocol so that not just a BrowserWindowController can be the window controller for a ChromeEventProcessingWindow. Added unittests. Also tested manually with the bookmark sync setup wizard dialog. BUG=23073 TEST=added unittests, trybot, and manual testing Review URL: http://codereview.chromium.org/344008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30619 0039d316-1c4b-4281-b951-d872f2087c98
akalin@chromium.org authoredof HtmlDialogView. Added TODO to fix inaccurate font height metric for OS X font class (and maybe width). Added the BrowserCommandExecutor protocol so that not just a BrowserWindowController can be the window controller for a ChromeEventProcessingWindow. Added unittests. Also tested manually with the bookmark sync setup wizard dialog. BUG=23073 TEST=added unittests, trybot, and manual testing Review URL: http://codereview.chromium.org/344008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30619 0039d316-1c4b-4281-b951-d872f2087c98
html_dialog_window_controller.mm 8.87 KiB
// Copyright (c) 2009 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.
#import "chrome/browser/cocoa/html_dialog_window_controller.h"
#include "base/gfx/size.h"
#include "base/logging.h"
#include "base/scoped_nsobject.h"
#include "base/sys_string_conversions.h"
#include "chrome/browser/browser.h"
#import "chrome/browser/cocoa/browser_command_executor.h"
#import "chrome/browser/cocoa/chrome_event_processing_window.h"
#include "chrome/browser/dom_ui/html_dialog_ui.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "googleurl/src/gurl.h"
HtmlDialogWindowDelegateBridge::HtmlDialogWindowDelegateBridge(
HtmlDialogUIDelegate* delegate, NSWindowController* controller,
NSWindow* window, Browser* browser)
: delegate_(delegate), controller_(controller), window_(window),
browser_(browser) {
DCHECK(delegate_);
DCHECK(controller_);
DCHECK(window_);
DCHECK(browser_);
}
HtmlDialogWindowDelegateBridge::~HtmlDialogWindowDelegateBridge() {}
void HtmlDialogWindowDelegateBridge::WindowControllerClosed() {
DelegateOnDialogClosed("");
}
bool HtmlDialogWindowDelegateBridge::DelegateOnDialogClosed(
const std::string& json_retval) {
if (delegate_) {
HtmlDialogUIDelegate* real_delegate = delegate_;
delegate_ = NULL;
real_delegate->OnDialogClosed(json_retval);
return true;
}
return false;
}
// HtmlDialogUIDelegate definitions.
// All of these functions check for NULL first since delegate_ is set
// to NULL when the window is closed.
bool HtmlDialogWindowDelegateBridge::IsDialogModal() const {
// TODO(akalin): Support modal dialog boxes.
if (delegate_ && delegate_->IsDialogModal()) {
LOG(WARNING) << "Modal HTML dialogs are not supported yet";
}
return false;
}
std::wstring HtmlDialogWindowDelegateBridge::GetDialogTitle() const {
return delegate_ ? delegate_->GetDialogTitle() : L"";
}
GURL HtmlDialogWindowDelegateBridge::GetDialogContentURL() const {
return delegate_ ? delegate_->GetDialogContentURL() : GURL();
}
void HtmlDialogWindowDelegateBridge::GetDOMMessageHandlers(
std::vector<DOMMessageHandler*>* handlers) const {
if (delegate_) {
delegate_->GetDOMMessageHandlers(handlers);
} else {
// TODO(akalin): Add this clause in the windows version. Also
// make sure that everything expects handlers to be non-NULL and
// document it.
handlers->clear();
}
}
void HtmlDialogWindowDelegateBridge::GetDialogSize(gfx::Size* size) const {
if (delegate_) {
delegate_->GetDialogSize(size);
} else {
*size = gfx::Size();
}
}
std::string HtmlDialogWindowDelegateBridge::GetDialogArgs() const {
return delegate_ ? delegate_->GetDialogArgs() : "";
}
void HtmlDialogWindowDelegateBridge::OnDialogClosed(
const std::string& json_retval) {
// [controller_ close] should be called at most once, too.
if (DelegateOnDialogClosed(json_retval)) {
[controller_ close];
}
}
// TabContentsDelegate definitions. Most of this logic is copied from
// chrome/browser/views/html_dialog_view.cc . All functions with empty
// bodies are notifications we don't care about.
void HtmlDialogWindowDelegateBridge::OpenURLFromTab(
TabContents* source, const GURL& url, const GURL& referrer,
WindowOpenDisposition disposition, PageTransition::Type transition) {
// Force all links to open in a new window.
static_cast<TabContentsDelegate*>(browser_)->
OpenURLFromTab(source, url, referrer, NEW_WINDOW, transition);
}
void HtmlDialogWindowDelegateBridge::NavigationStateChanged(
const TabContents* source, unsigned changed_flags) {
}
void HtmlDialogWindowDelegateBridge::AddNewContents(
TabContents* source, TabContents* new_contents,
WindowOpenDisposition disposition, const gfx::Rect& initial_pos,
bool user_gesture) {
// Force this to open in a new window, too.
static_cast<TabContentsDelegate*>(browser_)->
AddNewContents(source, new_contents, NEW_WINDOW,
initial_pos, user_gesture);
}
void HtmlDialogWindowDelegateBridge::ActivateContents(TabContents* contents) {}
void HtmlDialogWindowDelegateBridge::LoadingStateChanged(TabContents* source) {}
void HtmlDialogWindowDelegateBridge::CloseContents(TabContents* source) {}
void HtmlDialogWindowDelegateBridge::MoveContents(TabContents* source,
const gfx::Rect& pos) {
// TODO(akalin): Actually set the window bounds.
}
bool HtmlDialogWindowDelegateBridge::IsPopup(TabContents* source) {
// This needs to return true so that we are allowed to be resized by
// our contents.
return true;
}
void HtmlDialogWindowDelegateBridge::ToolbarSizeChanged(
TabContents* source, bool is_animating) {
// TODO(akalin): Figure out what to do here.
}
void HtmlDialogWindowDelegateBridge::URLStarredChanged(
TabContents* source, bool starred) {
// We don't have a visible star to click in the window.
NOTREACHED();
}
void HtmlDialogWindowDelegateBridge::UpdateTargetURL(
TabContents* source, const GURL& url) {}
// ChromeEventProcessingWindow expect its controller to implement this
// protocol.
@interface HtmlDialogWindowController (InternalAPI) <BrowserCommandExecutor>
- (void)executeCommand:(int)command;
@end
@implementation HtmlDialogWindowController (InternalAPI)
- (void)executeCommand:(int)command {
if (browser_->command_updater()->IsCommandEnabled(command)) {
browser_->ExecuteCommand(command);
}
}
@end
@implementation HtmlDialogWindowController
+ (void)showHtmlDialog:(HtmlDialogUIDelegate*)delegate
parentWindow:(gfx::NativeWindow)parent_window
browser:(Browser*)browser {
HtmlDialogWindowController* html_dialog_window_controller =
[[HtmlDialogWindowController alloc] initWithDelegate:delegate
parentWindow:parent_window
browser:browser];
[html_dialog_window_controller loadDialogContents];
[html_dialog_window_controller showWindow:nil];
}
- (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate
parentWindow:(gfx::NativeWindow)parent_window
browser:(Browser*)browser {
DCHECK(delegate);
DCHECK(parent_window);
DCHECK(browser);
// Put the dialog box in the center of the window.
//
// TODO(akalin): Surely there must be a cleaner way to do this.
//
// TODO(akalin): Perhaps use [window center] instead, which centers
// the dialog to the screen, although it doesn't match the Windows
// behavior.
NSRect parent_window_frame = [parent_window frame];
NSPoint parent_window_origin = parent_window_frame.origin;
NSSize parent_window_size = parent_window_frame.size;
gfx::Size dialog_size;
delegate->GetDialogSize(&dialog_size);
NSRect dialog_rect =
NSMakeRect(parent_window_origin.x +
(parent_window_size.width - dialog_size.width()) / 2,
parent_window_origin.y +
(parent_window_size.height - dialog_size.height()) / 2,
dialog_size.width(),
dialog_size.height());
// TODO(akalin): Make the window resizable (but with the minimum size being
// dialog_size and always on top (but not modal) to match the Windows
// behavior.
NSUInteger style = NSTitledWindowMask | NSClosableWindowMask;
scoped_nsobject<ChromeEventProcessingWindow> window(
[[ChromeEventProcessingWindow alloc]
initWithContentRect:dialog_rect
styleMask:style
backing:NSBackingStoreBuffered
defer:YES]);
if (!window.get()) {
return nil;
}
self = [super initWithWindow:window];
if (!self) {
return nil;
}
[window setWindowController:self];
[window setDelegate:self];
[window setTitle:base::SysWideToNSString(delegate->GetDialogTitle())];
browser_ = browser;
delegate_.reset(
new HtmlDialogWindowDelegateBridge(delegate, self, window, browser));
return self;
}
- (void)loadDialogContents {
// TODO(akalin): Figure out if this can be an incognito profile.
Profile* profile = browser_->profile();
tab_contents_.reset(new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL));
[[self window] setContentView:tab_contents_->GetNativeView()];
tab_contents_->set_delegate(delegate_.get());
// This must be done before loading the page; see the comments in
// HtmlDialogUI.
HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
delegate_.get());
tab_contents_->controller().LoadURL(delegate_->GetDialogContentURL(),
GURL(), PageTransition::START_PAGE);
// TODO(akalin): add accelerator for ESC to close the dialog box.
//
// TODO(akalin): Figure out why implementing (void)cancel:(id)sender
// to do the above doesn't work.
}
- (void)windowWillClose:(NSNotification*)notification {
delegate_->WindowControllerClosed();
[self autorelease];
}
@end