| Index: ui/app_list/cocoa/apps_grid_view_item.mm
|
| diff --git a/ui/app_list/cocoa/apps_grid_view_item.mm b/ui/app_list/cocoa/apps_grid_view_item.mm
|
| deleted file mode 100644
|
| index 1cc2784b79d88641f351bd7126bfa1db2856e063..0000000000000000000000000000000000000000
|
| --- a/ui/app_list/cocoa/apps_grid_view_item.mm
|
| +++ /dev/null
|
| @@ -1,455 +0,0 @@
|
| -// Copyright 2013 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 "ui/app_list/cocoa/apps_grid_view_item.h"
|
| -
|
| -#include "base/mac/foundation_util.h"
|
| -#include "base/mac/mac_util.h"
|
| -#include "base/mac/scoped_nsobject.h"
|
| -#include "base/strings/sys_string_conversions.h"
|
| -#include "skia/ext/skia_utils_mac.h"
|
| -#include "ui/app_list/app_list_constants.h"
|
| -#include "ui/app_list/app_list_item.h"
|
| -#include "ui/app_list/app_list_item_observer.h"
|
| -#import "ui/app_list/cocoa/apps_grid_controller.h"
|
| -#import "ui/base/cocoa/menu_controller.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/gfx/font_list.h"
|
| -#include "ui/gfx/image/image_skia_operations.h"
|
| -#include "ui/gfx/image/image_skia_util_mac.h"
|
| -#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
|
| -
|
| -namespace {
|
| -
|
| -// Padding from the top of the tile to the top of the app icon.
|
| -const CGFloat kTileTopPadding = 10;
|
| -
|
| -const CGFloat kIconSize = 48;
|
| -
|
| -const CGFloat kProgressBarHorizontalPadding = 8;
|
| -const CGFloat kProgressBarVerticalPadding = 13;
|
| -
|
| -// On Mac, fonts of the same enum from ResourceBundle are larger. The smallest
|
| -// enum is already used, so it needs to be reduced further to match Windows.
|
| -const int kMacFontSizeDelta = -1;
|
| -
|
| -} // namespace
|
| -
|
| -@class AppsGridItemBackgroundView;
|
| -
|
| -@interface AppsGridViewItem ()
|
| -
|
| -// Typed accessor for the root view.
|
| -- (AppsGridItemBackgroundView*)itemBackgroundView;
|
| -
|
| -// Bridged methods from app_list::AppListItemObserver:
|
| -// Update the title, correctly setting the color if the button is highlighted.
|
| -- (void)updateButtonTitle;
|
| -
|
| -// Update the button image after ensuring its dimensions are |kIconSize|.
|
| -- (void)updateButtonImage;
|
| -
|
| -// Add or remove a progress bar from the view.
|
| -- (void)setItemIsInstalling:(BOOL)isInstalling;
|
| -
|
| -// Update the progress bar to represent |percent|, or make it indeterminate if
|
| -// |percent| is -1, when unpacking begins.
|
| -- (void)setPercentDownloaded:(int)percent;
|
| -
|
| -@end
|
| -
|
| -namespace app_list {
|
| -
|
| -class ItemModelObserverBridge : public app_list::AppListItemObserver {
|
| - public:
|
| - ItemModelObserverBridge(AppsGridViewItem* parent, AppListItem* model);
|
| - ~ItemModelObserverBridge() override;
|
| -
|
| - AppListItem* model() { return model_; }
|
| - NSMenu* GetContextMenu();
|
| -
|
| - void ItemIconChanged() override;
|
| - void ItemNameChanged() override;
|
| - void ItemIsInstallingChanged() override;
|
| - void ItemPercentDownloadedChanged() override;
|
| -
|
| - private:
|
| - AppsGridViewItem* parent_; // Weak. Owns us.
|
| - AppListItem* model_; // Weak. Owned by AppListModel.
|
| - base::scoped_nsobject<MenuController> context_menu_controller_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ItemModelObserverBridge);
|
| -};
|
| -
|
| -ItemModelObserverBridge::ItemModelObserverBridge(AppsGridViewItem* parent,
|
| - AppListItem* model)
|
| - : parent_(parent),
|
| - model_(model) {
|
| - model_->AddObserver(this);
|
| -}
|
| -
|
| -ItemModelObserverBridge::~ItemModelObserverBridge() {
|
| - model_->RemoveObserver(this);
|
| -}
|
| -
|
| -NSMenu* ItemModelObserverBridge::GetContextMenu() {
|
| - if (!context_menu_controller_) {
|
| - ui::MenuModel* menu_model = model_->GetContextMenuModel();
|
| - if (!menu_model)
|
| - return nil;
|
| -
|
| - context_menu_controller_.reset(
|
| - [[MenuController alloc] initWithModel:menu_model
|
| - useWithPopUpButtonCell:NO]);
|
| - }
|
| - return [context_menu_controller_ menu];
|
| -}
|
| -
|
| -void ItemModelObserverBridge::ItemIconChanged() {
|
| - [parent_ updateButtonImage];
|
| -}
|
| -
|
| -void ItemModelObserverBridge::ItemNameChanged() {
|
| - [parent_ updateButtonTitle];
|
| -}
|
| -
|
| -void ItemModelObserverBridge::ItemIsInstallingChanged() {
|
| - [parent_ setItemIsInstalling:model_->is_installing()];
|
| -}
|
| -
|
| -void ItemModelObserverBridge::ItemPercentDownloadedChanged() {
|
| - [parent_ setPercentDownloaded:model_->percent_downloaded()];
|
| -}
|
| -
|
| -} // namespace app_list
|
| -
|
| -// Container for an NSButton to allow proper alignment of the icon in the apps
|
| -// grid, and to draw with a highlight when selected.
|
| -@interface AppsGridItemBackgroundView : NSView {
|
| - @private
|
| - BOOL selected_;
|
| -}
|
| -
|
| -- (NSButton*)button;
|
| -
|
| -- (void)setSelected:(BOOL)flag;
|
| -
|
| -@end
|
| -
|
| -@interface AppsGridItemButtonCell : NSButtonCell {
|
| - @private
|
| - BOOL hasShadow_;
|
| -}
|
| -
|
| -@property(assign, nonatomic) BOOL hasShadow;
|
| -
|
| -@end
|
| -
|
| -@interface AppsGridItemButton : NSButton;
|
| -@end
|
| -
|
| -@implementation AppsGridItemBackgroundView
|
| -
|
| -- (NSButton*)button {
|
| - // These views are part of a prototype NSCollectionViewItem, copied with an
|
| - // NSCoder. Rather than encoding additional members, the following relies on
|
| - // the button always being the first item added to AppsGridItemBackgroundView.
|
| - return base::mac::ObjCCastStrict<NSButton>([[self subviews] objectAtIndex:0]);
|
| -}
|
| -
|
| -- (void)setSelected:(BOOL)flag {
|
| - DCHECK(selected_ != flag);
|
| - selected_ = flag;
|
| - [self setNeedsDisplay:YES];
|
| -}
|
| -
|
| -// Ignore all hit tests. The grid controller needs to be the owner of any drags.
|
| -- (NSView*)hitTest:(NSPoint)aPoint {
|
| - return nil;
|
| -}
|
| -
|
| -- (void)drawRect:(NSRect)dirtyRect {
|
| - if (!selected_)
|
| - return;
|
| -
|
| - [gfx::SkColorToSRGBNSColor(app_list::kSelectedColor) set];
|
| - NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
|
| -}
|
| -
|
| -- (void)mouseDown:(NSEvent*)theEvent {
|
| - [[[self button] cell] setHighlighted:YES];
|
| -}
|
| -
|
| -- (void)mouseDragged:(NSEvent*)theEvent {
|
| - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow]
|
| - fromView:nil];
|
| - BOOL isInView = [self mouse:pointInView inRect:[self bounds]];
|
| - [[[self button] cell] setHighlighted:isInView];
|
| -}
|
| -
|
| -- (void)mouseUp:(NSEvent*)theEvent {
|
| - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow]
|
| - fromView:nil];
|
| - if (![self mouse:pointInView inRect:[self bounds]])
|
| - return;
|
| -
|
| - [[self button] performClick:self];
|
| -}
|
| -
|
| -@end
|
| -
|
| -@implementation AppsGridViewItem
|
| -
|
| -- (id)initWithSize:(NSSize)tileSize {
|
| - if ((self = [super init])) {
|
| - base::scoped_nsobject<AppsGridItemButton> prototypeButton(
|
| - [[AppsGridItemButton alloc] initWithFrame:NSMakeRect(
|
| - 0, 0, tileSize.width, tileSize.height - kTileTopPadding)]);
|
| -
|
| - // This NSButton style always positions the icon at the very top of the
|
| - // button frame. AppsGridViewItem uses an enclosing view so that it is
|
| - // visually correct.
|
| - [prototypeButton setImagePosition:NSImageAbove];
|
| - [prototypeButton setButtonType:NSMomentaryChangeButton];
|
| - [prototypeButton setBordered:NO];
|
| -
|
| - base::scoped_nsobject<AppsGridItemBackgroundView> prototypeButtonBackground(
|
| - [[AppsGridItemBackgroundView alloc]
|
| - initWithFrame:NSMakeRect(0, 0, tileSize.width, tileSize.height)]);
|
| - [prototypeButtonBackground addSubview:prototypeButton];
|
| - [self setView:prototypeButtonBackground];
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (NSProgressIndicator*)progressIndicator {
|
| - return progressIndicator_;
|
| -}
|
| -
|
| -- (void)updateButtonTitle {
|
| - if (progressIndicator_)
|
| - return;
|
| -
|
| - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
|
| - [[NSMutableParagraphStyle alloc] init]);
|
| - [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
|
| - [paragraphStyle setAlignment:NSCenterTextAlignment];
|
| - NSDictionary* titleAttributes = @{
|
| - NSParagraphStyleAttributeName : paragraphStyle,
|
| - NSFontAttributeName : ui::ResourceBundle::GetSharedInstance()
|
| - .GetFontList(app_list::kItemTextFontStyle)
|
| - .DeriveWithSizeDelta(kMacFontSizeDelta)
|
| - .GetPrimaryFont()
|
| - .GetNativeFont(),
|
| - NSForegroundColorAttributeName : [self isSelected] ?
|
| - gfx::SkColorToSRGBNSColor(app_list::kGridTitleHoverColor) :
|
| - gfx::SkColorToSRGBNSColor(app_list::kGridTitleColor)
|
| - };
|
| - NSString* buttonTitle =
|
| - base::SysUTF8ToNSString([self model]->GetDisplayName());
|
| - base::scoped_nsobject<NSAttributedString> attributedTitle(
|
| - [[NSAttributedString alloc] initWithString:buttonTitle
|
| - attributes:titleAttributes]);
|
| - [[self button] setAttributedTitle:attributedTitle];
|
| -
|
| - // If the display name would be truncated in the NSButton, or if the display
|
| - // name differs from the full name, add a tooltip showing the full name.
|
| - NSRect titleRect =
|
| - [[[self button] cell] titleRectForBounds:[[self button] bounds]];
|
| - if ([self model]->name() == [self model]->GetDisplayName() &&
|
| - [attributedTitle size].width < NSWidth(titleRect)) {
|
| - [[self view] removeAllToolTips];
|
| - } else {
|
| - [[self view] setToolTip:base::SysUTF8ToNSString([self model]->name())];
|
| - }
|
| -}
|
| -
|
| -- (void)updateButtonImage {
|
| - const gfx::Size iconSize = gfx::Size(kIconSize, kIconSize);
|
| - gfx::ImageSkia icon = [self model]->icon();
|
| - if (icon.size() != iconSize) {
|
| - icon = gfx::ImageSkiaOperations::CreateResizedImage(
|
| - icon, skia::ImageOperations::RESIZE_BEST, iconSize);
|
| - }
|
| - NSImage* buttonImage = gfx::NSImageFromImageSkiaWithColorSpace(
|
| - icon, base::mac::GetSRGBColorSpace());
|
| - [[self button] setImage:buttonImage];
|
| - [[[self button] cell] setHasShadow:[self model]->has_shadow()];
|
| -}
|
| -
|
| -- (void)setModel:(app_list::AppListItem*)itemModel {
|
| - [trackingArea_.get() clearOwner];
|
| - if (!itemModel) {
|
| - observerBridge_.reset();
|
| - return;
|
| - }
|
| -
|
| - observerBridge_.reset(new app_list::ItemModelObserverBridge(self, itemModel));
|
| - [self updateButtonTitle];
|
| - [self updateButtonImage];
|
| -
|
| - if (trackingArea_.get())
|
| - [[self view] removeTrackingArea:trackingArea_.get()];
|
| -
|
| - trackingArea_.reset(
|
| - [[CrTrackingArea alloc] initWithRect:NSZeroRect
|
| - options:NSTrackingInVisibleRect |
|
| - NSTrackingMouseEnteredAndExited |
|
| - NSTrackingActiveInKeyWindow
|
| - owner:self
|
| - userInfo:nil]);
|
| - [[self view] addTrackingArea:trackingArea_.get()];
|
| -}
|
| -
|
| -- (app_list::AppListItem*)model {
|
| - return observerBridge_->model();
|
| -}
|
| -
|
| -- (NSButton*)button {
|
| - return [[self itemBackgroundView] button];
|
| -}
|
| -
|
| -- (NSMenu*)contextMenu {
|
| - // Don't show the menu if button is already held down, e.g. with a left-click.
|
| - if ([[[self button] cell] isHighlighted])
|
| - return nil;
|
| -
|
| - [self setSelected:YES];
|
| - return observerBridge_->GetContextMenu();
|
| -}
|
| -
|
| -- (NSBitmapImageRep*)dragRepresentationForRestore:(BOOL)isRestore {
|
| - NSButton* button = [self button];
|
| - NSView* itemView = [self view];
|
| -
|
| - // The snapshot is never drawn as if it was selected. Also remove the cell
|
| - // highlight on the button image, added when it was clicked.
|
| - [button setHidden:NO];
|
| - [[button cell] setHighlighted:NO];
|
| - [self setSelected:NO];
|
| - [progressIndicator_ setHidden:YES];
|
| - if (isRestore)
|
| - [self updateButtonTitle];
|
| - else
|
| - [button setTitle:@""];
|
| -
|
| - NSBitmapImageRep* imageRep =
|
| - [itemView bitmapImageRepForCachingDisplayInRect:[itemView visibleRect]];
|
| - [itemView cacheDisplayInRect:[itemView visibleRect]
|
| - toBitmapImageRep:imageRep];
|
| -
|
| - if (isRestore) {
|
| - [progressIndicator_ setHidden:NO];
|
| - [self setSelected:YES];
|
| - }
|
| - // Button is always hidden until the drag animation completes.
|
| - [button setHidden:YES];
|
| - return imageRep;
|
| -}
|
| -
|
| -- (void)setItemIsInstalling:(BOOL)isInstalling {
|
| - if (!isInstalling == !progressIndicator_)
|
| - return;
|
| -
|
| - if (!isInstalling) {
|
| - [progressIndicator_ removeFromSuperview];
|
| - progressIndicator_.reset();
|
| - [self updateButtonTitle];
|
| - [self setSelected:YES];
|
| - return;
|
| - }
|
| -
|
| - NSRect rect = NSMakeRect(
|
| - kProgressBarHorizontalPadding,
|
| - kProgressBarVerticalPadding,
|
| - NSWidth([[self view] bounds]) - 2 * kProgressBarHorizontalPadding,
|
| - NSProgressIndicatorPreferredAquaThickness);
|
| - [[self button] setTitle:@""];
|
| - progressIndicator_.reset([[NSProgressIndicator alloc] initWithFrame:rect]);
|
| - [progressIndicator_ setIndeterminate:NO];
|
| - [progressIndicator_ setControlSize:NSSmallControlSize];
|
| - [[self view] addSubview:progressIndicator_];
|
| -}
|
| -
|
| -- (void)setPercentDownloaded:(int)percent {
|
| - // In a corner case, items can be installing when they are first added. For
|
| - // those, the icon will start desaturated. Wait for a progress update before
|
| - // showing the progress bar.
|
| - [self setItemIsInstalling:YES];
|
| - if (percent != -1) {
|
| - [progressIndicator_ setDoubleValue:percent];
|
| - return;
|
| - }
|
| -
|
| - // Otherwise, fully downloaded and waiting for install to complete.
|
| - [progressIndicator_ setIndeterminate:YES];
|
| - [progressIndicator_ startAnimation:self];
|
| -}
|
| -
|
| -- (AppsGridItemBackgroundView*)itemBackgroundView {
|
| - return base::mac::ObjCCastStrict<AppsGridItemBackgroundView>([self view]);
|
| -}
|
| -
|
| -- (void)mouseEntered:(NSEvent*)theEvent {
|
| - [self setSelected:YES];
|
| -}
|
| -
|
| -- (void)mouseExited:(NSEvent*)theEvent {
|
| - [self setSelected:NO];
|
| -}
|
| -
|
| -- (void)setSelected:(BOOL)flag {
|
| - if ([self isSelected] == flag)
|
| - return;
|
| -
|
| - [[self itemBackgroundView] setSelected:flag];
|
| - [super setSelected:flag];
|
| - [self updateButtonTitle];
|
| -}
|
| -
|
| -@end
|
| -
|
| -@implementation AppsGridItemButton
|
| -
|
| -+ (Class)cellClass {
|
| - return [AppsGridItemButtonCell class];
|
| -}
|
| -
|
| -@end
|
| -
|
| -@implementation AppsGridItemButtonCell
|
| -
|
| -@synthesize hasShadow = hasShadow_;
|
| -
|
| -- (void)drawImage:(NSImage*)image
|
| - withFrame:(NSRect)frame
|
| - inView:(NSView*)controlView {
|
| - if (!hasShadow_) {
|
| - [super drawImage:image
|
| - withFrame:frame
|
| - inView:controlView];
|
| - return;
|
| - }
|
| -
|
| - base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
|
| - gfx::ScopedNSGraphicsContextSaveGState context;
|
| - [shadow setShadowOffset:NSMakeSize(0, -2)];
|
| - [shadow setShadowBlurRadius:2.0];
|
| - [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0
|
| - alpha:0.14]];
|
| - [shadow set];
|
| -
|
| - [super drawImage:image
|
| - withFrame:frame
|
| - inView:controlView];
|
| -}
|
| -
|
| -// Workaround for http://crbug.com/324365: AppKit in Mavericks tries to call
|
| -// - [NSButtonCell item] when inspecting accessibility. Without this, an
|
| -// unrecognized selector exception is thrown inside AppKit, crashing Chrome.
|
| -- (id)item {
|
| - return nil;
|
| -}
|
| -
|
| -@end
|
|
|