Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3279)

Unified Diff: chrome/browser/ui/cocoa/web_intent_sheet_controller.mm

Issue 11414153: Remove legacy constrained window dialogs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/web_intent_sheet_controller.mm
diff --git a/chrome/browser/ui/cocoa/web_intent_sheet_controller.mm b/chrome/browser/ui/cocoa/web_intent_sheet_controller.mm
deleted file mode 100644
index 7a47e53b931c94f67b791d82ad98ea276d79bcef..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/cocoa/web_intent_sheet_controller.mm
+++ /dev/null
@@ -1,1192 +0,0 @@
-// 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.
-
-#import "chrome/browser/ui/cocoa/web_intent_sheet_controller.h"
-
-#include "base/memory/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/ui/browser_list.h"
-#import "chrome/browser/ui/cocoa/event_utils.h"
-#import "chrome/browser/ui/cocoa/hover_close_button.h"
-#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
-#import "chrome/browser/ui/cocoa/info_bubble_view.h"
-#import "chrome/browser/ui/cocoa/info_bubble_window.h"
-#include "chrome/browser/ui/cocoa/web_intent_picker_cocoa.h"
-#include "chrome/browser/ui/constrained_window.h"
-#include "chrome/browser/ui/constrained_window_constants.h"
-#include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
-#include "chrome/browser/ui/intents/web_intent_picker_model.h"
-#import "chrome/browser/ui/cocoa/tabs/throbber_view.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
-#include "grit/generated_resources.h"
-#include "grit/google_chrome_strings.h"
-#include "grit/locale_settings.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/l10n_util_mac.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/text/text_elider.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/image/image.h"
-
-using content::OpenURLParams;
-using content::Referrer;
-
-@interface HyperlinkButtonCell (Private)
-- (void)customizeButtonCell;
-@end
-
-@interface CustomLinkButtonCell : HyperlinkButtonCell
-@end
-
-namespace {
-
-// The width of a service button, in view coordinates.
-const CGFloat kServiceButtonWidth = 300;
-
-// Spacing in between sections.
-const CGFloat kVerticalSpacing = 18;
-
-// Square size of the close button.
-const CGFloat kCloseButtonSize = 16;
-
-// Width of the text fields.
-const CGFloat kTextWidth = WebIntentPicker::kWindowMinWidth -
- (WebIntentPicker::kContentAreaBorder * 2.0 + kCloseButtonSize);
-
-// Maximum number of intents (suggested and installed) displayed.
-const int kMaxIntentRows = 4;
-
-// Sets properties on the given |field| to act as title or description labels.
-void ConfigureTextFieldAsLabel(NSTextField* field) {
- [field setEditable:NO];
- [field setSelectable:YES];
- [field setDrawsBackground:NO];
- [field setBezeled:NO];
-}
-
-NSButton* CreateHyperlinkButton(NSString* title, const NSRect& frame) {
- NSButton* button = [[NSButton alloc] initWithFrame:frame];
- scoped_nsobject<CustomLinkButtonCell> cell(
- [[CustomLinkButtonCell alloc] initTextCell:title]);
- [cell setControlSize:NSSmallControlSize];
- [button setCell:cell.get()];
- [button setButtonType:NSMomentaryPushInButton];
- [button setBezelStyle:NSRegularSquareBezelStyle];
-
- return button;
-}
-
-} // namespace
-
-
-// Provide custom link format for intent picker. Removes underline attribute,
-// since UX direction is "look like WebUI".
-@implementation CustomLinkButtonCell
-- (void)customizeButtonCell {
- [super customizeButtonCell];
- [self setTextColor:[NSColor colorWithDeviceRed:0x11/255.0
- green:0x55/255.0
- blue:0xcc/255.0
- alpha:0xff/255.0]];
-}
-
-- (NSDictionary*)linkAttributes {
- scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
- [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
- [paragraphStyle setAlignment:[self alignment]];
-
- return @{
- NSForegroundColorAttributeName: [self textColor],
- NSFontAttributeName: [self font],
- NSCursorAttributeName: [NSCursor pointingHandCursor],
- NSParagraphStyleAttributeName: paragraphStyle.get()
- };
-}
-@end
-
-// This simple NSView subclass is used as the single subview of the page info
-// bubble's window's contentView. Drawing is flipped so that layout of the
-// sections is easier. Apple recommends flipping the coordinate origin when
-// doing a lot of text layout because it's more natural.
-@interface WebIntentsContentView : NSView
-@end
-@implementation WebIntentsContentView
-- (BOOL)isFlipped {
- return YES;
-}
-
-- (void)drawRect:(NSRect)rect {
- [[NSColor colorWithCalibratedWhite:1.0 alpha:1.0] set];
- NSRectFill(rect);
-}
-@end
-
-// NSImageView subclassed to allow fading the alpha value of the image to
-// indicate an inactive/disabled extension.
-@interface DimmableImageView : NSImageView {
- @private
- CGFloat alpha;
-}
-
-- (void)setEnabled:(BOOL)enabled;
-
-// NSView override
-- (void)drawRect:(NSRect)rect;
-@end
-
-@implementation DimmableImageView
-- (void)drawRect:(NSRect)rect {
- NSImage* image = [self image];
-
- NSRect sourceRect, destinationRect;
- sourceRect.origin = NSZeroPoint;
- sourceRect.size = [image size];
-
- destinationRect.origin = NSZeroPoint;
- destinationRect.size = [self frame].size;
-
- // If the source image is smaller than the destination, center it.
- if (destinationRect.size.width > sourceRect.size.width) {
- destinationRect.origin.x =
- (destinationRect.size.width - sourceRect.size.width) / 2.0;
- destinationRect.size.width = sourceRect.size.width;
- }
- if (destinationRect.size.height > sourceRect.size.height) {
- destinationRect.origin.y =
- (destinationRect.size.height - sourceRect.size.height) / 2.0;
- destinationRect.size.height = sourceRect.size.height;
- }
-
- [image drawInRect:destinationRect
- fromRect:sourceRect
- operation:NSCompositeSourceOver
- fraction:alpha];
-}
-
-- (void)setEnabled:(BOOL)enabled {
- if (enabled)
- alpha = 1.0;
- else
- alpha = 0.5;
- [self setNeedsDisplay:YES];
-}
-@end
-
-@interface WaitingView : NSView {
- @private
- scoped_nsobject<NSTextField> text_;
- scoped_nsobject<ThrobberView> throbber_;
-}
-@end
-
-@implementation WaitingView
-- (id)init {
- NSRect frame = NSMakeRect(WebIntentPicker::kContentAreaBorder, 0,
- kTextWidth, 140);
-
- if (self = [super initWithFrame:frame]) {
- const CGFloat kTopMargin = 35.0;
- const CGFloat kBottomMargin = 25.0;
- const CGFloat kVerticalSpacing = 18.0;
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-
- frame.origin = NSMakePoint(WebIntentPicker::kContentAreaBorder,
- kBottomMargin);
- frame.size.width = kTextWidth;
- text_.reset([[NSTextField alloc] initWithFrame:frame]);
- ConfigureTextFieldAsLabel(text_);
- [text_ setAlignment:NSCenterTextAlignment];
- [text_ setFont:[NSFont boldSystemFontOfSize:[NSFont systemFontSize]]];
- [text_ setStringValue:
- l10n_util::GetNSStringWithFixup(IDS_INTENT_PICKER_WAIT_FOR_CWS)];
- frame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:
- text_];
- [text_ setFrame:frame];
-
- frame.origin.y += NSHeight(frame) + kVerticalSpacing;
-
- // The sprite image consists of all the animation frames put together in one
- // horizontal/wide image. Each animation frame is square in shape within the
- // sprite.
- NSImage* iconImage =
- rb.GetNativeImageNamed(IDR_SPEECH_INPUT_SPINNER).ToNSImage();
- frame.size = [iconImage size];
- frame.size.width = NSHeight(frame);
- frame.origin.x = (WebIntentPicker::kWindowMinWidth - NSWidth(frame))/2.0;
- throbber_.reset([ThrobberView filmstripThrobberViewWithFrame:frame
- image:iconImage]);
-
- frame.size = NSMakeSize(WebIntentPicker::kWindowMinWidth,
- NSMaxY(frame) + kTopMargin);
- frame.origin = NSMakePoint(0, 0);
- [self setSubviews:@[throbber_, text_]];
- [self setFrame:frame];
- }
- return self;
-}
-@end
-
-// An NSView subclass to display ratings stars.
-@interface RatingsView : NSView
- // Mark RatingsView as disabled/enabled.
-- (void)setEnabled:(BOOL)enabled;
-@end
-
-@implementation RatingsView
-- (void)setEnabled:(BOOL)enabled {
- for (DimmableImageView* imageView in [self subviews])
- [imageView setEnabled:enabled];
-}
-@end
-
-// NSView for the header of the box.
-@interface HeaderView : NSView {
- @private
- // Used to forward button clicks. Weak reference.
- scoped_nsobject<NSTextField> titleField_;
- scoped_nsobject<NSTextField> subtitleField_;
- scoped_nsobject<NSBox> spacer_;
-}
-
-- (id)init;
-@end
-
-@implementation HeaderView
-- (id)init {
- NSRect contentFrame = NSMakeRect(0, 0, WebIntentPicker::kWindowMinWidth, 1);
- if (self = [super initWithFrame:contentFrame]) {
- NSRect frame = NSMakeRect(WebIntentPicker::kContentAreaBorder, 0,
- kTextWidth, 1);
-
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- titleField_.reset([[NSTextField alloc] initWithFrame:frame]);
- ConfigureTextFieldAsLabel(titleField_);
- gfx::Font titleFont = rb.GetFont(
- ConstrainedWindowConstants::kTitleFontStyle);
- titleFont = titleFont.DeriveFont(0, gfx::Font::BOLD);
- [titleField_ setFont:titleFont.GetNativeFont()];
-
- frame = NSMakeRect(WebIntentPicker::kContentAreaBorder, 0,
- kTextWidth, 1);
- subtitleField_.reset([[NSTextField alloc] initWithFrame:frame]);
- ConfigureTextFieldAsLabel(subtitleField_);
- gfx::Font textFont = rb.GetFont(ConstrainedWindowConstants::kTextFontStyle);
- [subtitleField_ setFont:textFont.GetNativeFont()];
-
- frame = NSMakeRect(0, 0, WebIntentPicker::kWindowMinWidth, 1.0);
- spacer_.reset([[NSBox alloc] initWithFrame:frame]);
- [spacer_ setBoxType:NSBoxSeparator];
- [spacer_ setBorderColor:[NSColor blackColor]];
- [spacer_ setAlphaValue:0.2];
-
- NSArray* subviews = @[titleField_, subtitleField_, spacer_];
- [self setSubviews:subviews];
- }
- return self;
-}
-
-- (void)setTitle:(NSString*)title {
- NSRect frame = [titleField_ frame];
- [titleField_ setStringValue:title];
- frame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:
- titleField_];
- [titleField_ setFrame:frame];
-}
-
-- (void)setSubtitle:(NSString*)subtitle {
- if (subtitle && [subtitle length]) {
- NSRect frame = [subtitleField_ frame];
-
- [subtitleField_ setHidden:FALSE];
- [subtitleField_ setStringValue:subtitle];
- frame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:
- subtitleField_];
- [subtitleField_ setFrame:frame];
- } else {
- [subtitleField_ setHidden:TRUE];
- }
-}
-
-- (void)performLayout {
- CGFloat offset = kVerticalSpacing;
-
- NSRect frame = [spacer_ frame];
- frame.origin.y = offset;
- [spacer_ setFrame:frame];
- offset += NSHeight(frame);
-
- offset += kVerticalSpacing;
-
- if (![subtitleField_ isHidden]) {
- frame = [subtitleField_ frame];
- frame.origin.y = offset;
- [subtitleField_ setFrame:frame];
- offset += NSHeight(frame);
- }
-
- frame = [titleField_ frame];
- frame.origin.y = offset;
- [titleField_ setFrame:frame];
- offset += NSHeight(frame);
-
- // No kContentAreaBorder here, since that is currently handled elsewhere.
- frame = [self frame];
- frame.size.height = offset;
- [self setFrame:frame];
-}
-@end
-
-// NSView for a single row in the intents view.
-@interface IntentRowView : NSView {
- @private
- scoped_nsobject<NSProgressIndicator> throbber_;
- scoped_nsobject<NSButton> cwsButton_;
- scoped_nsobject<RatingsView> ratingsWidget_;
- scoped_nsobject<NSButton> installButton_;
- scoped_nsobject<DimmableImageView> iconView_;
- scoped_nsobject<NSTextField> label_;
-}
-
-- (id)initWithExtension:
- (const WebIntentPickerModel::SuggestedExtension*)extension
- withIndex:(size_t)index
- forController:(WebIntentPickerSheetController*)controller;
-- (void)startThrobber;
-- (void)setEnabled:(BOOL)enabled;
-- (void)stopThrobber;
-- (NSInteger)tag;
-@end
-
-@implementation IntentRowView
-const CGFloat kMaxHeight = 34.0;
-const CGFloat kTitleX = 20.0;
-const CGFloat kMinAddButtonHeight = 28.0;
-const CGFloat kAddButtonX = 245;
-const CGFloat kAddButtonWidth = 128.0;
-
-+ (RatingsView*)createStarWidgetWithRating:(CGFloat)rating {
- const int kStarSpacing = 1; // Spacing between stars in pixels.
- const CGFloat kStarSize = 16.0; // Size of the star in pixels.
-
- NSMutableArray* subviews = [NSMutableArray array];
-
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- NSRect imageFrame = NSMakeRect(0, 0, kStarSize, kStarSize);
-
- for (int i = 0; i < 5; ++i) {
- NSImage* nsImage = rb.GetNativeImageNamed(
- WebIntentPicker::GetNthStarImageIdFromCWSRating(rating, i)).ToNSImage();
-
- scoped_nsobject<DimmableImageView> imageView(
- [[DimmableImageView alloc] initWithFrame:imageFrame]);
- [imageView setImage:nsImage];
- [imageView setImageFrameStyle:NSImageFrameNone];
- [imageView setFrame:imageFrame];
- [imageView setEnabled:YES];
- [subviews addObject:imageView];
- imageFrame.origin.x += kStarSize + kStarSpacing;
- }
-
- NSRect frame = NSMakeRect(0, 0, (kStarSize + kStarSpacing) * 5, kStarSize);
- RatingsView* widget = [[RatingsView alloc] initWithFrame:frame];
- [widget setSubviews:subviews];
- return widget;
-}
-
-
-- (void)setIcon:(NSImage*)icon {
- NSRect imageFrame = NSZeroRect;
-
- iconView_.reset(
- [[DimmableImageView alloc] initWithFrame:imageFrame]);
- [iconView_ setImage:icon];
- [iconView_ setImageFrameStyle:NSImageFrameNone];
- [iconView_ setEnabled:YES];
-
- imageFrame.size = [icon size];
- imageFrame.size.height = std::min(NSHeight(imageFrame), kMaxHeight);
- imageFrame.origin.y += (kMaxHeight - NSHeight(imageFrame)) / 2.0;
- [iconView_ setFrame:imageFrame];
-}
-
-- (void)setActionButton:(NSString*)title
- withSelector:(SEL)selector
- forController:(WebIntentPickerSheetController*)controller {
-
- NSRect frame = NSMakeRect(kAddButtonX, 0, kAddButtonWidth, 0);
- installButton_.reset([[NSButton alloc] initWithFrame:frame]);
- [installButton_ setAlignment:NSCenterTextAlignment];
- [installButton_ setButtonType:NSMomentaryPushInButton];
- [installButton_ setBezelStyle:NSRegularSquareBezelStyle];
- [installButton_ setTitle:title];
- frame.size.height = std::min(kMinAddButtonHeight, kMaxHeight);
- frame.origin.y += (kMaxHeight - NSHeight(frame)) / 2.0;
- [installButton_ setFrame:frame];
-
- [installButton_ setTarget:controller];
- [installButton_ setAction:selector];
-}
-
-- (id)init {
- // Build the main view.
- NSRect contentFrame = NSMakeRect(
- 0, 0, WebIntentPicker::kWindowMinWidth, kMaxHeight);
- if (self = [super initWithFrame:contentFrame]) {
- NSMutableArray* subviews = [NSMutableArray array];
- if (iconView_) [subviews addObject:iconView_];
- if (label_) [subviews addObject:label_];
- if (cwsButton_) [subviews addObject:cwsButton_];
- if (ratingsWidget_) [subviews addObject:ratingsWidget_];
- if (installButton_) [subviews addObject:installButton_];
- if (throbber_) [subviews addObject:throbber_];
- [self setSubviews:subviews];
- }
- return self;
-}
-
-- (id)initWithExtension:
- (const WebIntentPickerModel::SuggestedExtension*)extension
- withIndex:(size_t)index
- forController:(WebIntentPickerSheetController*)controller {
- // Add the extension icon.
- [self setIcon:extension->icon.ToNSImage()];
-
- // Add the extension title.
- NSRect frame = NSMakeRect(kTitleX, 0, 0, 0);
- const string16 elidedTitle = ui::ElideText(
- extension->title, gfx::Font(), WebIntentPicker::kTitleLinkMaxWidth,
- ui::ELIDE_AT_END);
- NSString* string = base::SysUTF16ToNSString(elidedTitle);
- cwsButton_.reset(CreateHyperlinkButton(string, frame));
- [cwsButton_ setAlignment:NSCenterTextAlignment];
- [cwsButton_ setTarget:controller];
- [cwsButton_ setAction:@selector(openExtensionLink:)];
- [cwsButton_ setTag:index];
- [cwsButton_ sizeToFit];
-
- frame = [cwsButton_ frame];
- frame.size.height = std::min([[cwsButton_ cell] cellSize].height,
- kMaxHeight);
- frame.origin.y = (kMaxHeight - NSHeight(frame)) / 2.0;
- [cwsButton_ setFrame:frame];
-
- // Add the star rating
- CGFloat offsetX = frame.origin.x + NSWidth(frame) +
- WebIntentPicker::kContentAreaBorder;
- ratingsWidget_.reset(
- [IntentRowView
- createStarWidgetWithRating:extension->average_rating]);
- frame = [ratingsWidget_ frame];
- frame.origin.y += (kMaxHeight - NSHeight(frame)) / 2.0;
- frame.origin.x = offsetX;
- [ratingsWidget_ setFrame:frame];
-
- // Add an "add to chromium" button.
- string = l10n_util::GetNSStringWithFixup(
- IDS_INTENT_PICKER_INSTALL_EXTENSION);
- [self setActionButton:string
- withSelector:@selector(installExtension:)
- forController:controller];
- [installButton_ setTag:index];
-
- // Keep a throbber handy.
- frame = [installButton_ frame];
- frame.origin.x += (NSWidth(frame) - 16) / 2;
- frame.origin.y += (NSHeight(frame) - 16) /2;
- frame.size = NSMakeSize(16, 16);
- throbber_.reset([[NSProgressIndicator alloc] initWithFrame:frame]);
- [throbber_ setHidden:YES];
- [throbber_ setStyle:NSProgressIndicatorSpinningStyle];
-
- return [self init];
-}
-
-- (id)initWithService:
- (const WebIntentPickerModel::InstalledService*)service
- withIndex:(size_t)index
- forController:(WebIntentPickerSheetController*)controller {
-
- // Add the extension icon.
- [self setIcon:service->favicon.ToNSImage()];
-
- // Add the extension title.
- NSRect frame = NSMakeRect(
- kTitleX, 0, WebIntentPicker::kTitleLinkMaxWidth, 10);
-
- const string16 elidedTitle = ui::ElideText(
- service->title, gfx::Font(),
- WebIntentPicker::kTitleLinkMaxWidth, ui::ELIDE_AT_END);
- NSString* string = base::SysUTF16ToNSString(elidedTitle);
-
- label_.reset([[NSTextField alloc] initWithFrame:frame]);
- ConfigureTextFieldAsLabel(label_);
- [label_ setStringValue:string];
- frame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:
- label_];
- frame.origin.y = (kMaxHeight - NSHeight(frame)) / 2.0;
- [label_ setFrame:frame];
-
- string = l10n_util::GetNSStringWithFixup(
- IDS_INTENT_PICKER_SELECT_INTENT);
- [self setActionButton:string
- withSelector:@selector(invokeService:)
- forController:controller];
- [installButton_ setTag:index];
- return [self init];
-}
-
-- (NSInteger)tag {
- return [installButton_ tag];
-}
-
-- (void)startThrobber {
- [installButton_ setHidden:YES];
- [throbber_ setHidden:NO];
- [throbber_ startAnimation:self];
- [iconView_ setEnabled:YES];
- [ratingsWidget_ setEnabled:NO];
-}
-
-- (void)setEnabled:(BOOL) enabled {
- [installButton_ setEnabled:enabled];
- [cwsButton_ setEnabled:enabled];
- [iconView_ setEnabled:enabled];
- [ratingsWidget_ setEnabled:enabled];
-}
-
-- (void)stopThrobber {
- if (throbber_.get()) {
- [throbber_ setHidden:YES];
- [throbber_ stopAnimation:self];
- }
- [installButton_ setHidden:NO];
-}
-
-- (void)adjustButtonSize:(CGFloat)newWidth {
- CGFloat increase = std::max(kAddButtonWidth, newWidth) - kAddButtonWidth;
- NSRect frame = [self frame];
- frame.size.width += increase;
- [self setFrame:frame];
-
- frame = [installButton_ frame];
- frame.size.width += increase;
- [installButton_ setFrame:frame];
-}
-
-@end
-
-@interface IntentView : NSView {
- @private
- // Used to forward button clicks. Weak reference.
- WebIntentPickerSheetController* controller_;
-}
-
-- (id)initWithModel:(WebIntentPickerModel*)model
- forController:(WebIntentPickerSheetController*)controller;
-- (void)startThrobberForRow:(NSInteger)index;
-- (void)stopThrobber;
-@end
-
-@implementation IntentView
-- (id)initWithModel:(WebIntentPickerModel*)model
- forController:(WebIntentPickerSheetController*)controller {
- if (self = [super initWithFrame:NSZeroRect]) {
- const CGFloat kYMargin = 16.0;
- int availableSpots = kMaxIntentRows;
-
- CGFloat offset = kYMargin;
- NSMutableArray* subviews = [NSMutableArray array];
- NSMutableArray* rows = [NSMutableArray array];
-
- for (size_t i = 0; i < model->GetInstalledServiceCount() && availableSpots;
- ++i, --availableSpots) {
- const WebIntentPickerModel::InstalledService& svc =
- model->GetInstalledServiceAt(i);
- scoped_nsobject<NSView> suggestView(
- [[IntentRowView alloc] initWithService:&svc
- withIndex:i
- forController:controller]);
-
- [rows addObject:suggestView];
- }
-
- // Special case for the empty view.
- size_t count = model->GetSuggestedExtensionCount();
- if (count == 0 && availableSpots == kMaxIntentRows)
- return nil;
-
- for (size_t i = count; i > 0 && availableSpots; --i, --availableSpots) {
- const WebIntentPickerModel::SuggestedExtension& ext =
- model->GetSuggestedExtensionAt(i - 1);
- scoped_nsobject<NSView> suggestView(
- [[IntentRowView alloc] initWithExtension:&ext
- withIndex:i-1
- forController:controller]);
- [rows addObject:suggestView];
- }
-
- // Determine optimal width for buttons given localized texts.
- scoped_nsobject<NSButton> sizeHelper(
- [[NSButton alloc] initWithFrame:NSZeroRect]);
- [sizeHelper setAlignment:NSCenterTextAlignment];
- [sizeHelper setButtonType:NSMomentaryPushInButton];
- [sizeHelper setBezelStyle:NSRegularSquareBezelStyle];
-
- [sizeHelper setTitle:
- l10n_util::GetNSStringWithFixup(IDS_INTENT_PICKER_INSTALL_EXTENSION)];
- [sizeHelper sizeToFit];
- CGFloat buttonWidth = NSWidth([sizeHelper frame]);
-
- [sizeHelper setTitle:
- l10n_util::GetNSStringWithFixup(IDS_INTENT_PICKER_SELECT_INTENT)];
- [sizeHelper sizeToFit];
- buttonWidth = std::max(buttonWidth, NSWidth([sizeHelper frame]));
-
- for (IntentRowView* row in [rows reverseObjectEnumerator]) {
- [row adjustButtonSize:buttonWidth];
- offset += [self addStackedView:row
- toSubviews:subviews
- atOffset:offset];
- }
-
- [self setSubviews:subviews];
- NSRect contentFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, 0,
- WebIntentPicker::kWindowMinWidth, offset);
- [self setFrame:contentFrame];
- controller_ = controller;
- }
- return self;
-}
-
-- (void)startThrobberForRow:(NSInteger)index {
- for (IntentRowView* row in [self subviews]) {
- if ([row isMemberOfClass:[IntentRowView class]]) {
- [row setEnabled:NO];
- if ([row tag] == index) {
- [row startThrobber];
- }
- }
- }
-}
-
-- (void)stopThrobber {
- for (IntentRowView* row in [self subviews]) {
- if ([row isMemberOfClass:[IntentRowView class]]) {
- [row stopThrobber];
- [row setEnabled:YES];
- }
- }
-}
-
-- (IBAction)installExtension:(id)sender {
- [controller_ installExtension:sender];
-}
-
-- (CGFloat)addStackedView:(NSView*)view
- toSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- if (view == nil)
- return 0.0;
-
- NSPoint frameOrigin = [view frame].origin;
- frameOrigin.y = offset;
- [view setFrameOrigin:frameOrigin];
- [subviews addObject:view];
-
- return NSHeight([view frame]);
-}
-@end
-
-@implementation WebIntentPickerSheetController
-
-- (id)initWithPicker:(WebIntentPickerCocoa*)picker {
- // Use an arbitrary height because it will reflect the size of the content.
- NSRect contentRect = NSMakeRect(
- 0, 0, WebIntentPicker::kWindowMinWidth, kVerticalSpacing);
-
- // |window| is retained by the ConstrainedWindowMacDelegateCustomSheet when
- // the sheet is initialized.
- scoped_nsobject<NSWindow> window(
- [[NSWindow alloc] initWithContentRect:contentRect
- styleMask:NSTitledWindowMask
- backing:NSBackingStoreBuffered
- defer:YES]);
- if ((self = [super initWithWindow:window.get()])) {
- picker_ = picker;
- if (picker)
- model_ = picker->model();
-
- inlineDispositionTitleField_.reset([[NSTextField alloc] init]);
- ConfigureTextFieldAsLabel(inlineDispositionTitleField_);
- [inlineDispositionTitleField_ setFont:
- [NSFont boldSystemFontOfSize:[NSFont systemFontSize]]];
- flipView_.reset([[WebIntentsContentView alloc] init]);
- [flipView_ setAutoresizingMask:NSViewMinYMargin];
- [[[self window] contentView] setSubviews:@[flipView_]];
-
- [self performLayoutWithModel:model_];
- }
- return self;
-}
-
-// Handle default OSX dialog cancel mechanisms. (Cmd-.)
-- (void)cancelOperation:(id)sender {
- if (picker_)
- picker_->OnCancelled();
- [self closeSheet];
-}
-
-- (void)chooseAnotherService:(id)sender {
- if (picker_)
- picker_->OnChooseAnotherService();
-}
-
-- (void)sheetDidEnd:(NSWindow*)sheet
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo {
- if (picker_)
- picker_->OnSheetDidEnd(sheet);
-}
-
-- (void)setInlineDispositionWebContents:(content::WebContents*)webContents {
- webContents_ = webContents;
-}
-
-- (void)setInlineDispositionFrameSize:(NSSize)inlineContentSize {
- DCHECK(webContents_);
-
- NSView* webContentView = webContents_->GetNativeView();
-
- // Make sure inline content size is never shrunk.
- inlineContentSize = NSMakeSize(
- std::max(NSWidth([webContentView frame]), inlineContentSize.width),
- std::max(NSHeight([webContentView frame]), inlineContentSize.height));
-
- // Compute container size to fit all elements, including padding.
- NSSize containerSize = inlineContentSize;
- containerSize.height +=
- [webContentView frame].origin.y + WebIntentPicker::kContentAreaBorder;
- containerSize.width += 2 * WebIntentPicker::kContentAreaBorder;
-
- // Ensure minimum container width.
- containerSize.width =
- std::max(CGFloat(WebIntentPicker::kWindowMinWidth), containerSize.width);
-
- // Resize web contents.
- [webContentView setFrameSize:inlineContentSize];
- [self setContainerSize:containerSize];
-}
-
-- (void)setContainerSize:(NSSize)containerSize {
- // Resize container views
- NSRect frame = NSMakeRect(0, 0, 0, 0);
- frame.size = containerSize;
- [[[self window] contentView] setFrame:frame];
- [flipView_ setFrame:frame];
-
- // Resize and reposition dialog window.
- frame.size = [[[self window] contentView] convertSize:containerSize
- toView:nil];
- frame = [[self window] frameRectForContentRect:frame];
-
- // Readjust window position to keep top in place and center horizontally.
- NSRect windowFrame = [[self window] frame];
- windowFrame.origin.x -= (NSWidth(frame) - NSWidth(windowFrame)) / 2.0;
- windowFrame.origin.y -= (NSHeight(frame) - NSHeight(windowFrame));
- windowFrame.size = frame.size;
- [[self window] setFrame:windowFrame display:YES animate:NO];
-}
-
-// Pop up a new tab with the Chrome Web Store.
-- (IBAction)showChromeWebStore:(id)sender {
- DCHECK(picker_);
- picker_->OnSuggestionsLinkClicked(
- event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
-}
-
-// A picker button has been pressed - invoke corresponding service.
-- (IBAction)invokeService:(id)sender {
- DCHECK(picker_);
- picker_->OnServiceChosen([sender tag]);
-}
-
-- (IBAction)openExtensionLink:(id)sender {
- DCHECK(model_);
- DCHECK(picker_);
- const WebIntentPickerModel::SuggestedExtension& extension =
- model_->GetSuggestedExtensionAt([sender tag]);
-
- picker_->OnExtensionLinkClicked(extension.id,
- event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]));
-}
-
-- (IBAction)installExtension:(id)sender {
- DCHECK(model_);
- DCHECK(picker_);
- const WebIntentPickerModel::SuggestedExtension& extension =
- model_->GetSuggestedExtensionAt([sender tag]);
- if (picker_) {
- [intentView_ startThrobberForRow:[sender tag]];
- [closeButton_ setEnabled:NO];
- picker_->OnExtensionInstallRequested(extension.id);
- }
-}
-
-- (CGFloat)addStackedView:(NSView*)view
- toSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- if (view == nil)
- return 0.0;
-
- NSPoint frameOrigin = [view frame].origin;
- frameOrigin.y = offset;
- [view setFrameOrigin:frameOrigin];
- [subviews addObject:view];
-
- return NSHeight([view frame]);
-}
-
-// Adds a link to the Chrome Web Store, to obtain further intent handlers.
-// Returns the y position delta for the next offset.
-- (CGFloat)addCwsButtonToSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- NSImage* iconImage = rb.GetNativeImageNamed(IDR_WEBSTORE_ICON_16).ToNSImage();
- NSRect imageFrame;
- imageFrame.origin = NSMakePoint(WebIntentPicker::kContentAreaBorder, offset);
- imageFrame.size = [iconImage size];
- scoped_nsobject<NSImageView> iconView(
- [[NSImageView alloc] initWithFrame:imageFrame]);
- [iconView setImage:iconImage];
- [iconView setImageFrameStyle:NSImageFrameNone];
-
- const CGFloat kCWSIconPadding = 4.0; // Same spacing as for service options.
- NSRect frame = NSMakeRect(WebIntentPicker::kContentAreaBorder +
- NSWidth(imageFrame) + kCWSIconPadding,
- offset, 100, 10);
- NSString* string = l10n_util::GetNSStringWithFixup(
- IDS_FIND_MORE_INTENT_HANDLER_MESSAGE);
- scoped_nsobject<NSButton> button(CreateHyperlinkButton(string, frame));
- [button setTarget:self];
- [button setAction:@selector(showChromeWebStore:)];
- [subviews addObjectsFromArray:@[iconView, button]];
-
- // Call size-to-fit to fixup for the localized string.
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:button];
-
- return NSHeight([button frame]);
-}
-
-- (void)addCloseButtonToSubviews:(NSMutableArray*)subviews {
- const CGFloat kButtonPadding = 4.0; // whitespace inside button frame.
- if (!closeButton_.get()) {
- NSRect buttonFrame = NSMakeRect(
- WebIntentPicker::kContentAreaBorder + kTextWidth + kButtonPadding,
- WebIntentPicker::kContentAreaBorder - kButtonPadding,
- kCloseButtonSize, kCloseButtonSize);
- closeButton_.reset(
- [[HoverCloseButton alloc] initWithFrame:buttonFrame]);
- // Anchor close button to upper right.
- // (NSViewMaxYMargin since parent view is flipped.)
- [closeButton_ setAutoresizingMask:NSViewMaxYMargin|NSViewMinXMargin];
- [closeButton_ setTarget:self];
- [closeButton_ setAction:@selector(cancelOperation:)];
- [[closeButton_ cell] setKeyEquivalent:@"\e"];
- }
- [subviews addObject:closeButton_];
-}
-
-// Adds a header (icon and explanatory text) to picker bubble.
-// Returns the y position delta for the next offset.
-- (CGFloat)addHeaderToSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- // Create a new text field if we don't have one yet.
- // TODO(groby): This should not be necessary since the controller sends this
- // string.
- if (!actionTextField_.get()) {
- NSString* nsString =
- l10n_util::GetNSStringWithFixup(IDS_CHOOSE_INTENT_HANDLER_MESSAGE);
- [self setActionString:nsString];
- }
-
- scoped_nsobject<HeaderView> header([[HeaderView alloc] init]);
-
- [header setTitle:[actionTextField_ stringValue]];
- string16 labelText;
- if (model_ && model_->GetInstalledServiceCount() == 0)
- labelText = model_->GetSuggestionsLinkText();
- [header setSubtitle:base::SysUTF16ToNSString(labelText)];
- [header performLayout];
-
- NSRect frame = [header frame];
- frame.origin.y = offset;
- [header setFrame:frame];
- [subviews addObject:header];
-
- return NSHeight(frame);
-}
-
-- (CGFloat)addInlineHtmlToSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- if (!webContents_)
- return 0;
-
- // Determine a good size for the inline disposition window.
-
- gfx::Size size = picker_->GetMinInlineDispositionSize();
- NSView* webContentView = webContents_->GetNativeView();
- NSRect contentFrame = NSMakeRect(
- WebIntentPicker::kContentAreaBorder,
- offset,
- std::max(NSWidth([webContentView frame]),CGFloat(size.width())),
- std::max(NSHeight([webContentView frame]),CGFloat(size.height())));
-
- [webContentView setFrame:contentFrame];
- [subviews addObject:webContentView];
-
- return NSHeight(contentFrame);
-}
-
-- (CGFloat)addAnotherServiceLinkToSubviews:(NSMutableArray*)subviews
- atOffset:(CGFloat)offset {
- DCHECK(model_);
- DCHECK(model_->IsInlineDisposition());
- GURL url = model_->inline_disposition_url();
-
- const WebIntentPickerModel::InstalledService* service =
- model_->GetInstalledServiceWithURL(url);
- DCHECK(service);
-
- CGFloat originalOffset = offset;
-
- // Icon for current service.
- scoped_nsobject<NSImageView> icon;
- NSRect imageFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, offset,
- 0, 0);
- icon.reset([[NSImageView alloc] initWithFrame:imageFrame]);
- [icon setImage:service->favicon.ToNSImage()];
- [icon setImageFrameStyle:NSImageFrameNone];
- [icon setEnabled:YES];
-
- imageFrame.size = [service->favicon.ToNSImage() size];
- [icon setFrame:imageFrame];
-
- [subviews addObject:icon];
-
- // Resize control to fit text
- NSRect textFrame =
- NSMakeRect(NSMaxX(imageFrame) + 4,
- offset,
- WebIntentPicker::kTitleLinkMaxWidth, 1);
- [inlineDispositionTitleField_ setFrame:textFrame];
- [subviews addObject:inlineDispositionTitleField_];
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:inlineDispositionTitleField_];
- textFrame = [inlineDispositionTitleField_ frame];
-
- // Add link for "choose another service" if other suggestions are available
- // or if more than one (the current) service is installed.
- if (model_->show_use_another_service() &&
- (model_->GetInstalledServiceCount() > 1 ||
- model_->GetSuggestedExtensionCount())) {
- NSRect frame = NSMakeRect(
- NSMaxX(textFrame) + WebIntentPicker::kContentAreaBorder, offset,
- 1, 1);
- NSString* string = l10n_util::GetNSStringWithFixup(
- IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE);
- scoped_nsobject<NSButton> button(CreateHyperlinkButton(string, frame));
- [[button cell] setControlSize:NSRegularControlSize];
- [[button cell] setFont:
- [NSFont controlContentFontOfSize:[NSFont systemFontSize]]];
- [button setTarget:self];
- [button setAction:@selector(chooseAnotherService:)];
- [subviews addObject:button];
-
- // Call size-to-fit to fixup for the localized string.
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:button];
-
- // Right-align the "use another service" button.
- frame = [button frame];
- frame.origin.x = WebIntentPicker::kWindowMinWidth - NSWidth(frame) -
- 2 * WebIntentPicker::kContentAreaBorder - kCloseButtonSize;
- [button setFrame:frame];
- [button setAutoresizingMask:NSViewMinXMargin];
-
- // And finally, make sure the link and the title are horizontally centered.
- frame = [button frame];
- CGFloat height = std::max(NSHeight(textFrame), NSHeight(frame));
- frame.origin.y += (height - NSHeight(frame)) / 2.0;
- frame.size.height = height;
- textFrame.origin.y += (height - NSHeight(textFrame)) / 2.0;
- textFrame.size.height = height;
- [button setFrame:frame];
- [inlineDispositionTitleField_ setFrame:textFrame];
- }
-
- offset += NSHeight(textFrame) + kVerticalSpacing;
-
- scoped_nsobject<NSBox> spacer;
-
- NSRect frame = NSMakeRect(0, offset, WebIntentPicker::kWindowMinWidth, 1.0);
- spacer.reset([[NSBox alloc] initWithFrame:frame]);
- [spacer setBoxType:NSBoxSeparator];
- [spacer setAlphaValue:0.2];
- [spacer setAutoresizingMask:NSViewWidthSizable];
- [subviews addObject: spacer];
-
- return offset + kVerticalSpacing - originalOffset;
-}
-
-- (NSView*)createEmptyView {
- NSRect titleFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder,
- WebIntentPicker::kContentAreaBorder,
- kTextWidth, 1);
- scoped_nsobject<NSTextField> title(
- [[NSTextField alloc] initWithFrame:titleFrame]);
- ConfigureTextFieldAsLabel(title);
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- gfx::Font titleFont = rb.GetFont(ConstrainedWindowConstants::kTitleFontStyle);
- titleFont = titleFont.DeriveFont(0, gfx::Font::BOLD);
- [title setFont:titleFont.GetNativeFont()];
- [title setStringValue:
- l10n_util::GetNSStringWithFixup(IDS_INTENT_PICKER_NO_SERVICES_TITLE)];
- titleFrame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
-
- NSRect bodyFrame = titleFrame;
- bodyFrame.origin.y +=
- NSHeight(titleFrame) + WebIntentPicker::kContentAreaBorder;
-
- scoped_nsobject<NSTextField> body(
- [[NSTextField alloc] initWithFrame:bodyFrame]);
- ConfigureTextFieldAsLabel(body);
- [body setStringValue:
- l10n_util::GetNSStringWithFixup(IDS_INTENT_PICKER_NO_SERVICES)];
- bodyFrame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:body];
- NSRect viewFrame = NSMakeRect(
- 0,
- WebIntentPicker::kContentAreaBorder,
- std::max(NSWidth(bodyFrame), NSWidth(titleFrame)) +
- 2 * WebIntentPicker::kContentAreaBorder,
- NSHeight(titleFrame) + NSHeight(bodyFrame) + kVerticalSpacing);
-
- titleFrame.origin.y = NSHeight(viewFrame) - NSHeight(titleFrame);
- bodyFrame.origin.y = 0;
-
- [title setFrame:titleFrame];
- [body setFrame:bodyFrame];
-
- NSView* view = [[NSView alloc] initWithFrame:viewFrame];
- [view setSubviews:@[title, body]];
-
- return view;
-}
-
-- (void)performLayoutWithModel:(WebIntentPickerModel*)model {
- model_ = model;
-
- // |offset| is the Y position that should be drawn at next.
- CGFloat offset = WebIntentPicker::kContentAreaBorder;
-
- // Keep the new subviews in an array that gets replaced at the end.
- NSMutableArray* subviews = [NSMutableArray array];
-
- // Indicator that we have neither suggested nor installed services,
- // and we're not in the wait stage any more either.
- BOOL isEmpty = model_ &&
- !model_->IsWaitingForSuggestions() &&
- !model_->GetInstalledServiceCount() &&
- !model_->GetSuggestedExtensionCount();
-
- if (model_ && model_->IsWaitingForSuggestions()) {
- if (!waitingView_.get())
- waitingView_.reset([[WaitingView alloc] init]);
- [subviews addObject:waitingView_];
- offset += NSHeight([waitingView_ frame]);
- } else if (isEmpty) {
- scoped_nsobject<NSView> emptyView([self createEmptyView]);
- [subviews addObject:emptyView];
- offset += NSHeight([emptyView frame]);
- } else if (webContents_) {
- offset += [self addAnotherServiceLinkToSubviews:subviews
- atOffset:offset];
- offset += [self addInlineHtmlToSubviews:subviews atOffset:offset];
- } else {
- offset += [self addHeaderToSubviews:subviews atOffset:offset];
-
- if (model) {
- intentView_.reset(
- [[IntentView alloc] initWithModel:model forController:self]);
- offset += [self addStackedView:intentView_
- toSubviews:subviews
- atOffset:offset];
- }
- offset += [self addCwsButtonToSubviews:subviews atOffset:offset];
- }
-
- // Add the bottom padding.
- offset += WebIntentPicker::kContentAreaBorder;
-
- // Resize to fit.
- [self setContainerSize:NSMakeSize(WebIntentPicker::kWindowMinWidth, offset)];
-
- [self addCloseButtonToSubviews:subviews];
-
- // Replace the window's content.
- [flipView_ setSubviews:subviews];
-}
-
-- (void)setActionString:(NSString*)actionString {
- NSRect textFrame;
- if (!actionTextField_.get()) {
- textFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, 0,
- kTextWidth, 1);
-
- actionTextField_.reset([[NSTextField alloc] initWithFrame:textFrame]);
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- ConfigureTextFieldAsLabel(actionTextField_);
- gfx::Font titleFont = rb.GetFont(
- ConstrainedWindowConstants::kTitleFontStyle);
- titleFont = titleFont.DeriveFont(0, gfx::Font::BOLD);
- [actionTextField_ setFont:titleFont.GetNativeFont()];
- } else {
- textFrame = [actionTextField_ frame];
- }
-
- [actionTextField_ setStringValue:actionString];
- textFrame.size.height +=
- [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:
- actionTextField_];
- [actionTextField_ setFrame:textFrame];
-}
-
-- (void)setInlineDispositionTitle:(NSString*)title {
- NSFont* nsfont = [inlineDispositionTitleField_ font];
- gfx::Font font(
- base::SysNSStringToUTF8([nsfont fontName]), [nsfont pointSize]);
- NSString* elidedTitle = base::SysUTF16ToNSString(ui::ElideText(
- base::SysNSStringToUTF16(title),
- font, WebIntentPicker::kTitleLinkMaxWidth, ui::ELIDE_AT_END));
- [inlineDispositionTitleField_ setStringValue:elidedTitle];
-}
-
-- (void)stopThrobber {
- [closeButton_ setEnabled:YES];
- [intentView_ stopThrobber];
-}
-
-- (void)closeSheet {
- [NSApp endSheet:[self window]];
-}
-
-@end // WebIntentPickerSheetController

Powered by Google App Engine
This is Rietveld 408576698