summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authortapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 11:50:06 +0000
committertapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 11:50:06 +0000
commitaa004442c2838a5bf7eb6f5f7b0433f8157c5735 (patch)
tree074f9aa23f3957fe9b22b2112bc15c5f1a22a9b9 /ui
parentfae7b5685539ff8f0f22a16a4b5ac5bbbf61c892 (diff)
downloadchromium_src-aa004442c2838a5bf7eb6f5f7b0433f8157c5735.zip
chromium_src-aa004442c2838a5bf7eb6f5f7b0433f8157c5735.tar.gz
chromium_src-aa004442c2838a5bf7eb6f5f7b0433f8157c5735.tar.bz2
UI updates for items in the OSX app list: mouseover, font, padding.
This change adds a CrTrackingArea to items in the apps grid for a mouseover effect. There are also minor UI tweaks: use a correct padding for the icon in the apps grid, and use the same font as used by the CrOS and Windows app launchers. BUG=138633 TEST=Added: app_list_unittests --gtest_filter=AppsGridControllerTest.MouseoverSelects Review URL: https://chromiumcodereview.appspot.com/12764024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188346 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/app_list/app_list_constants.cc5
-rw-r--r--ui/app_list/app_list_constants.h4
-rw-r--r--ui/app_list/cocoa/apps_grid_controller.h2
-rw-r--r--ui/app_list/cocoa/apps_grid_controller.mm35
-rw-r--r--ui/app_list/cocoa/apps_grid_controller_unittest.mm41
-rw-r--r--ui/app_list/cocoa/apps_grid_view_item.h6
-rw-r--r--ui/app_list/cocoa/apps_grid_view_item.mm134
-rw-r--r--ui/app_list/views/app_list_item_view.cc4
8 files changed, 190 insertions, 41 deletions
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc
index 4c31d2f..115f600 100644
--- a/ui/app_list/app_list_constants.cc
+++ b/ui/app_list/app_list_constants.cc
@@ -7,6 +7,7 @@
namespace app_list {
const SkColor kContentsBackgroundColor = SkColorSetRGB(0xF5, 0xF5, 0xF5);
+const SkColor kHoverAndPushedColor = SkColorSetARGB(0x19, 0, 0, 0);
// Duration in milliseconds for page transition.
const int kPageTransitionDurationInMs = 180;
@@ -18,4 +19,8 @@ const int kOverscrollPageTransitionDurationMs = 50;
const int kPreferredCols = 4;
const int kPreferredRows = 4;
+// Font style for app item labels.
+const ui::ResourceBundle::FontStyle kItemTextFontStyle =
+ ui::ResourceBundle::SmallBoldFont;
+
} // namespace app_list
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h
index cc68664..7579d99 100644
--- a/ui/app_list/app_list_constants.h
+++ b/ui/app_list/app_list_constants.h
@@ -7,10 +7,12 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/app_list/app_list_export.h"
+#include "ui/base/resource/resource_bundle.h"
namespace app_list {
APP_LIST_EXPORT extern const SkColor kContentsBackgroundColor;
+APP_LIST_EXPORT extern const SkColor kHoverAndPushedColor;
APP_LIST_EXPORT extern const int kPageTransitionDurationInMs;
APP_LIST_EXPORT extern const int kOverscrollPageTransitionDurationMs;
@@ -18,6 +20,8 @@ APP_LIST_EXPORT extern const int kOverscrollPageTransitionDurationMs;
APP_LIST_EXPORT extern const int kPreferredCols;
APP_LIST_EXPORT extern const int kPreferredRows;
+APP_LIST_EXPORT extern const ui::ResourceBundle::FontStyle kItemTextFontStyle;
+
} // namespace app_list
#endif // UI_APP_LIST_APP_LIST_CONSTANTS_H_
diff --git a/ui/app_list/cocoa/apps_grid_controller.h b/ui/app_list/cocoa/apps_grid_controller.h
index 3a5f052..8f01fe4 100644
--- a/ui/app_list/cocoa/apps_grid_controller.h
+++ b/ui/app_list/cocoa/apps_grid_controller.h
@@ -38,7 +38,7 @@ class AppsGridDelegateBridge;
- (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex;
-- (NSButton*)viewAtItemIndex:(size_t)itemIndex;
+- (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex;
- (app_list::AppListModel*)model;
diff --git a/ui/app_list/cocoa/apps_grid_controller.mm b/ui/app_list/cocoa/apps_grid_controller.mm
index 55628ba..7eb3f5e 100644
--- a/ui/app_list/cocoa/apps_grid_controller.mm
+++ b/ui/app_list/cocoa/apps_grid_controller.mm
@@ -40,9 +40,6 @@ const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight;
// Index of the page with the most content currently visible.
- (size_t)nearestPageIndex;
-// Make an item prototype containing an app button for an NSCollectionView page.
-- (NSCollectionViewItem*)makeItemPrototype;
-
// Make an empty NSCollectionView positioned horizontally for |pageIndex|.
- (NSCollectionView*)makePageForIndex:(size_t)pageIndex;
@@ -55,8 +52,6 @@ const CGFloat kViewHeight = kFixedRows * kPreferredTileHeight;
- (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex
indexInPage:(size_t)indexInPage;
-- (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex;
-
// Update the model in full, and rebuild subviews.
- (void)modelUpdated;
@@ -128,11 +123,6 @@ class AppsGridDelegateBridge : public ui::ListModelObserver {
return [pages_ objectAtIndex:pageIndex];
}
-- (NSButton*)viewAtItemIndex:(size_t)itemIndex {
- return base::mac::ObjCCastStrict<NSButton>(
- [[self itemAtIndex:itemIndex] view]);
-}
-
- (app_list::AppListModel*)model {
return model_.get();
}
@@ -209,21 +199,6 @@ class AppsGridDelegateBridge : public ui::ListModelObserver {
}
}
-- (NSCollectionViewItem*)makeItemPrototype {
- scoped_nsobject<NSButton> prototypeButton(
- [[NSButton alloc] initWithFrame:NSZeroRect]);
- [prototypeButton setImagePosition:NSImageAbove];
- [prototypeButton setButtonType:NSMomentaryPushInButton];
- [prototypeButton setTarget:self];
- [prototypeButton setAction:@selector(onItemClicked:)];
- [prototypeButton setBordered:NO];
-
- scoped_nsobject<AppsGridViewItem> itemPrototype(
- [[AppsGridViewItem alloc] init]);
- [itemPrototype setView:prototypeButton];
- return itemPrototype.autorelease();
-}
-
- (NSCollectionView*)makePageForIndex:(size_t)pageIndex {
NSRect pageFrame = NSMakeRect(
kLeftRightPadding + kViewWidth * pageIndex, 0,
@@ -236,7 +211,13 @@ class AppsGridDelegateBridge : public ui::ListModelObserver {
[itemCollectionView setMaxItemSize:itemSize];
[itemCollectionView setSelectable:YES];
[itemCollectionView setFocusRingType:NSFocusRingTypeNone];
- [itemCollectionView setItemPrototype:[self makeItemPrototype]];
+
+ scoped_nsobject<AppsGridViewItem> itemPrototype(
+ [[AppsGridViewItem alloc] initWithSize:itemSize]);
+ [[itemPrototype button] setTarget:self];
+ [[itemPrototype button] setAction:@selector(onItemClicked:)];
+
+ [itemCollectionView setItemPrototype:itemPrototype];
return itemCollectionView.autorelease();
}
@@ -259,7 +240,7 @@ class AppsGridDelegateBridge : public ui::ListModelObserver {
- (void)onItemClicked:(id)sender {
for (size_t i = 0; i < [items_ count]; ++i) {
AppsGridViewItem* item = [self itemAtIndex:i];
- if ([[item view] isEqual:sender])
+ if ([[item button] isEqual:sender])
delegate_->ActivateAppListItem([item model], 0);
}
}
diff --git a/ui/app_list/cocoa/apps_grid_controller_unittest.mm b/ui/app_list/cocoa/apps_grid_controller_unittest.mm
index 76d1345..744152e 100644
--- a/ui/app_list/cocoa/apps_grid_controller_unittest.mm
+++ b/ui/app_list/cocoa/apps_grid_controller_unittest.mm
@@ -8,6 +8,7 @@
#import "testing/gtest_mac.h"
#include "ui/app_list/app_list_item_model.h"
#import "ui/app_list/cocoa/apps_grid_controller.h"
+#import "ui/app_list/cocoa/apps_grid_view_item.h"
#include "ui/app_list/test/app_list_test_model.h"
#include "ui/app_list/test/app_list_test_view_delegate.h"
#import "ui/base/test/cocoa_test_event_utils.h"
@@ -58,6 +59,16 @@ class AppsGridControllerTest : public ui::CocoaTest {
[test_window() keyDown:cocoa_test_event_utils::KeyEventWithCharacter(c)];
}
+ void SimulateMouseEnterItemAt(size_t index) {
+ [[apps_grid_controller_ itemAtIndex:index] mouseEntered:
+ cocoa_test_event_utils::EnterExitEventWithType(NSMouseEntered)];
+ }
+
+ void SimulateMouseExitItemAt(size_t index) {
+ [[apps_grid_controller_ itemAtIndex:index] mouseExited:
+ cocoa_test_event_utils::EnterExitEventWithType(NSMouseExited)];
+ }
+
// Do a bulk replacement of the items in the grid.
void ReplaceTestModel(int item_count) {
scoped_ptr<app_list::test::AppListTestModel> new_model(
@@ -78,7 +89,7 @@ class AppsGridControllerTest : public ui::CocoaTest {
}
NSButton* GetItemViewAt(size_t index) {
- return [apps_grid_controller_ viewAtItemIndex:index];
+ return [[apps_grid_controller_ itemAtIndex:index] button];
}
NSCollectionView* GetPageAt(size_t index) {
@@ -90,9 +101,9 @@ class AppsGridControllerTest : public ui::CocoaTest {
NSView* GetSelectedView() {
NSIndexSet* selection = [GetPageAt(0) selectionIndexes];
if ([selection count]) {
- NSCollectionViewItem* item =
- [GetPageAt(0) itemAtIndex:[selection firstIndex]];
- return [item view];
+ AppsGridViewItem* item = base::mac::ObjCCastStrict<AppsGridViewItem>(
+ [GetPageAt(0) itemAtIndex:[selection firstIndex]]);
+ return [item button];
}
return nil;
@@ -281,3 +292,25 @@ TEST_F(AppsGridControllerTest, ModelUpdates) {
EXPECT_EQ(kTestImageSize, icon_size.width);
EXPECT_EQ(kTestImageSize, icon_size.height);
}
+
+// Test mouseover selection.
+TEST_F(AppsGridControllerTest, MouseoverSelects) {
+ model()->PopulateApps(2);
+ EXPECT_EQ(nil, GetSelectedView());
+
+ // Test entering and exiting the first item.
+ SimulateMouseEnterItemAt(0);
+ EXPECT_EQ(GetItemViewAt(0), GetSelectedView());
+ SimulateMouseExitItemAt(0);
+ EXPECT_EQ(nil, GetSelectedView());
+
+ // AppKit doesn't guarantee the order, so test moving between items.
+ SimulateMouseEnterItemAt(0);
+ EXPECT_EQ(GetItemViewAt(0), GetSelectedView());
+ SimulateMouseEnterItemAt(1);
+ EXPECT_EQ(GetItemViewAt(1), GetSelectedView());
+ SimulateMouseExitItemAt(0);
+ EXPECT_EQ(GetItemViewAt(1), GetSelectedView());
+ SimulateMouseExitItemAt(1);
+ EXPECT_EQ(nil, GetSelectedView());
+}
diff --git a/ui/app_list/cocoa/apps_grid_view_item.h b/ui/app_list/cocoa/apps_grid_view_item.h
index f16d96e..976ca51 100644
--- a/ui/app_list/cocoa/apps_grid_view_item.h
+++ b/ui/app_list/cocoa/apps_grid_view_item.h
@@ -8,6 +8,7 @@
#import <Cocoa/Cocoa.h>
#include "base/memory/scoped_ptr.h"
+#import "ui/base/cocoa/tracking_area.h"
namespace app_list {
class AppListItemModel;
@@ -19,8 +20,13 @@ class ItemModelObserverBridge;
@interface AppsGridViewItem : NSCollectionViewItem {
@private
scoped_ptr<app_list::ItemModelObserverBridge> observerBridge_;
+
+ // Used to highlight the background on hover.
+ ui::ScopedCrTrackingArea trackingArea_;
}
+- (id)initWithSize:(NSSize)tileSize;
+
- (void)setModel:(app_list::AppListItemModel*)itemModel;
- (app_list::AppListItemModel*)model;
diff --git a/ui/app_list/cocoa/apps_grid_view_item.mm b/ui/app_list/cocoa/apps_grid_view_item.mm
index d7c251a..6f7e465 100644
--- a/ui/app_list/cocoa/apps_grid_view_item.mm
+++ b/ui/app_list/cocoa/apps_grid_view_item.mm
@@ -5,12 +5,22 @@
#import "ui/app_list/cocoa/apps_grid_view_item.h"
#include "base/mac/foundation_util.h"
+#include "base/memory/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_model.h"
#include "ui/app_list/app_list_item_model_observer.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia_util_mac.h"
+#include "ui/gfx/font.h"
+
+namespace {
+
+// Padding from the top of the tile to the top of the app icon.
+const CGFloat kTileTopPadding = 10;
+
+} // namespace
namespace app_list {
@@ -67,8 +77,97 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() {
} // 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
+
+@implementation AppsGridItemBackgroundView
+
+- (NSButton*)button {
+ return base::mac::ObjCCastStrict<NSButton>([[self subviews] objectAtIndex:0]);
+}
+
+- (void)setSelected:(BOOL)flag {
+ if (selected_ == flag)
+ return;
+
+ selected_ = flag;
+ [self setNeedsDisplay:YES];
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+ if (!selected_)
+ return;
+
+ [gfx::SkColorToCalibratedNSColor(app_list::kHoverAndPushedColor) 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
+
+@interface AppsGridViewItem ()
+
+- (AppsGridItemBackgroundView*)itemBackgroundView;
+
+@end
+
@implementation AppsGridViewItem
+- (id)initWithSize:(NSSize)tileSize {
+ if ((self = [super init])) {
+ scoped_nsobject<NSButton> prototypeButton(
+ [[NSButton 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];
+
+ [[prototypeButton cell]
+ setFont:ui::ResourceBundle::GetSharedInstance().GetFont(
+ app_list::kItemTextFontStyle).GetNativeFont()];
+
+ scoped_nsobject<AppsGridItemBackgroundView> prototypeButtonBackground(
+ [[AppsGridItemBackgroundView alloc] initWithFrame:NSMakeRect(
+ 0, 0, tileSize.width, tileSize.height)]);
+ [prototypeButtonBackground addSubview:prototypeButton];
+ [self setView:prototypeButtonBackground];
+ }
+ return self;
+}
+
- (void)setModel:(app_list::AppListItemModel*)itemModel {
if (!itemModel) {
observerBridge_.reset();
@@ -79,6 +178,18 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() {
[button setTitle:base::SysUTF8ToNSString(itemModel->title())];
[button setImage:gfx::NSImageFromImageSkia(itemModel->icon())];
observerBridge_.reset(new app_list::ItemModelObserverBridge(self, itemModel));
+
+ 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::AppListItemModel*)model {
@@ -86,16 +197,25 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() {
}
- (NSButton*)button {
- return base::mac::ObjCCastStrict<NSButton>([self view]);
+ DCHECK_EQ(1u, [[[self view] subviews] count]);
+ return base::mac::ObjCCastStrict<NSButton>(
+ [[[self view] subviews] objectAtIndex:0]);
+}
+
+- (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 (flag) {
- [[[self button] cell] setBackgroundColor:[NSColor lightGrayColor]];
- } else {
- [[[self button] cell] setBackgroundColor:gfx::SkColorToCalibratedNSColor(
- app_list::kContentsBackgroundColor)];
- }
+ [[self itemBackgroundView] setSelected:flag];
[super setSelected:flag];
}
diff --git a/ui/app_list/views/app_list_item_view.cc b/ui/app_list/views/app_list_item_view.cc
index 640aa57..2061211 100644
--- a/ui/app_list/views/app_list_item_view.cc
+++ b/ui/app_list/views/app_list_item_view.cc
@@ -8,6 +8,7 @@
#include "base/utf_string_conversions.h"
#include "grit/ui_resources.h"
+#include "ui/app_list/app_list_constants.h"
#include "ui/app_list/app_list_item_model.h"
#include "ui/app_list/views/apps_grid_view.h"
#include "ui/app_list/views/cached_label.h"
@@ -40,7 +41,6 @@ const int kProgressBarHeight = 4;
const SkColor kTitleColor = SkColorSetRGB(0x5A, 0x5A, 0x5A);
const SkColor kTitleHoverColor = SkColorSetRGB(0x3C, 0x3C, 0x3C);
-const SkColor kHoverAndPushedColor = SkColorSetARGB(0x19, 0, 0, 0);
const SkColor kSelectedColor = SkColorSetARGB(0x0D, 0, 0, 0);
const SkColor kHighlightedColor = kHoverAndPushedColor;
const SkColor kDownloadProgressBackgroundColor =
@@ -75,7 +75,7 @@ AppListItemView::AppListItemView(AppsGridView* apps_grid_view,
title_->SetBackgroundColor(0);
title_->SetAutoColorReadabilityEnabled(false);
title_->SetEnabledColor(kTitleColor);
- title_->SetFont(rb.GetFont(ui::ResourceBundle::SmallBoldFont));
+ title_->SetFont(rb.GetFont(kItemTextFontStyle));
title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
title_->SetVisible(!model_->is_installing());
title_->Invalidate();