diff options
author | saintlou@chromium.org <saintlou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-17 18:04:47 +0000 |
---|---|---|
committer | saintlou@chromium.org <saintlou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-17 18:04:47 +0000 |
commit | 80d4aeaebaf149c5ba113f9133fd0e067d7e321d (patch) | |
tree | 9525850ce740fca5584385674043482a93374ce8 /chrome/browser/ui/touch | |
parent | 2b5f8edb264918e897ee7d1e0847d0ffbfeb6b70 (diff) | |
download | chromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.zip chromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.tar.gz chromium_src-80d4aeaebaf149c5ba113f9133fd0e067d7e321d.tar.bz2 |
Improve large tab strip by leveraging touch icons when present.
BUG=none
TEST=TemplateURLParserTest.TestDictionary, TestMSDN, TestWikipedia (as per sadrul)
Note: testing with mobile user-agent will also yield better results: --user-agent=iPhone or similar mobile
Review URL: http://codereview.chromium.org/7065052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89512 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/touch')
-rw-r--r-- | chrome/browser/ui/touch/tabs/tab_strip_factory.cc | 8 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab.cc | 55 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab.h | 14 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab_strip.cc | 5 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab_strip.h | 3 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc | 171 | ||||
-rw-r--r-- | chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h | 46 |
7 files changed, 257 insertions, 45 deletions
diff --git a/chrome/browser/ui/touch/tabs/tab_strip_factory.cc b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc index 343a27f..8d6046c 100644 --- a/chrome/browser/ui/touch/tabs/tab_strip_factory.cc +++ b/chrome/browser/ui/touch/tabs/tab_strip_factory.cc @@ -7,15 +7,15 @@ #include "chrome/browser/ui/views/tabs/tab_strip_factory.h" #include "chrome/browser/ui/touch/tabs/touch_tab_strip.h" -#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" +#include "chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h" -// The implmentation of CreateTabStrip for touchui creates a TouchTabStrip +// The implementation of CreateTabStrip for touchui creates a TouchTabStrip AbstractTabStripView* CreateTabStrip(Browser* browser, views::View* parent, TabStripModel* model, bool use_vertical_tabs) { - BrowserTabStripController* tabstrip_controller = - new BrowserTabStripController(browser, model); + TouchTabStripController* tabstrip_controller = + new TouchTabStripController(browser, model); // Ownership of this controller is given to a specific tabstrip when we // construct it below. diff --git a/chrome/browser/ui/touch/tabs/touch_tab.cc b/chrome/browser/ui/touch/tabs/touch_tab.cc index dca408a..837ef50 100644 --- a/chrome/browser/ui/touch/tabs/touch_tab.cc +++ b/chrome/browser/ui/touch/tabs/touch_tab.cc @@ -19,10 +19,6 @@ static const int kLeftPadding = 16; static const int kRightPadding = 15; static const int kDropShadowHeight = 2; -// The size of the favicon touch area. This generally would be the same as -// kFaviconSize in ui/gfx/favicon_size.h -static const int kTouchTabIconSize = 32; - TouchTab::TouchTabImage TouchTab::tab_alpha = {0}; TouchTab::TouchTabImage TouchTab::tab_active = {0}; TouchTab::TouchTabImage TouchTab::tab_inactive = {0}; @@ -180,7 +176,6 @@ void TouchTab::PaintActiveTabBackground(gfx::Canvas* canvas) { } void TouchTab::PaintIcon(gfx::Canvas* canvas) { - // TODO(wyck): use thumbnailer to get better page images int x = favicon_bounds_.x(); int y = favicon_bounds_.y(); @@ -190,23 +185,19 @@ void TouchTab::PaintIcon(gfx::Canvas* canvas) { x += x_base; if (base::i18n::IsRTL()) { - x = width() - x - - (data().favicon.isNull() ? kFaviconSize : data().favicon.width()); + x = width() - x - (data().favicon.isNull() + ? kTouchTargetIconSize : data().favicon.width()); } - int favicon_x = x; - if (!data().favicon.isNull() && data().favicon.width() != kFaviconSize) - favicon_x += (data().favicon.width() - kFaviconSize) / 2; - if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { ui::ThemeProvider* tp = GetThemeProvider(); SkBitmap frames(*tp->GetBitmapNamed( - (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ? - IDR_THROBBER_WAITING : IDR_THROBBER)); + (data().network_state == TabRendererData::NETWORK_STATE_WAITING) + ? IDR_THROBBER_WAITING : IDR_THROBBER)); int image_size = frames.height(); int image_offset = loading_animation_frame() * image_size; - canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x, y, - kTouchTabIconSize, kTouchTabIconSize, false); + canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x, + y, kTouchTargetIconSize, kTouchTargetIconSize, false); } else { canvas->Save(); canvas->ClipRectInt(0, 0, width(), height()); @@ -215,33 +206,16 @@ void TouchTab::PaintIcon(gfx::Canvas* canvas) { SkBitmap crashed_favicon(*rb.GetBitmapNamed(IDR_SAD_FAVICON)); canvas->DrawBitmapInt(crashed_favicon, 0, 0, crashed_favicon.width(), crashed_favicon.height(), x, y + favicon_hiding_offset(), - kTouchTabIconSize, kTouchTabIconSize, true); + kTouchTargetIconSize, kTouchTargetIconSize, true); } else { if (!data().favicon.isNull()) { - - if ((data().favicon.width() == kTouchTabIconSize) && - (data().favicon.height() == kTouchTabIconSize)) { - canvas->DrawBitmapInt(data().favicon, 0, 0, - data().favicon.width(), data().favicon.height(), - x, y + favicon_hiding_offset(), - kTouchTabIconSize, kTouchTabIconSize, true); - } else { - // Draw a background around target touch area in case the favicon - // is smaller than touch area (e.g www.google.com is 16x16 now) - canvas->DrawRectInt( - GetThemeProvider()->GetColor( - ThemeService::COLOR_BUTTON_BACKGROUND), - x, y, kTouchTabIconSize, kTouchTabIconSize); - - // We center the image - // TODO(saintlou): later request larger image from HistoryService - canvas->DrawBitmapInt(data().favicon, 0, 0, data().favicon.width(), - data().favicon.height(), - x + ((kTouchTabIconSize - data().favicon.width()) / 2), - y + ((kTouchTabIconSize - data().favicon.height()) / 2) + - favicon_hiding_offset(), - data().favicon.width(), data().favicon.height(), true); - } + // We center the image since it might not be square + canvas->DrawBitmapInt(data().favicon, + 0, 0, data().favicon.width(), data().favicon.height(), + x + ((kTouchTargetIconSize - data().favicon.width()) / 2), + y + ((kTouchTargetIconSize - data().favicon.height()) / 2) + + favicon_hiding_offset(), + data().favicon.width(), data().favicon.height(), true); } } canvas->Restore(); @@ -260,7 +234,6 @@ void TouchTab::InitTabResources() { LoadTabImages(); } - // static void TouchTab::LoadTabImages() { // We're not letting people override tab images just yet. diff --git a/chrome/browser/ui/touch/tabs/touch_tab.h b/chrome/browser/ui/touch/tabs/touch_tab.h index b4ff409..ec458aa 100644 --- a/chrome/browser/ui/touch/tabs/touch_tab.h +++ b/chrome/browser/ui/touch/tabs/touch_tab.h @@ -25,6 +25,9 @@ class TouchTab : public BaseTab { // The menu button's class name. static const char kViewClassName[]; + // The size of the favicon touch area. + static const int kTouchTargetIconSize = 32; + explicit TouchTab(TabController* controller); virtual ~TouchTab(); @@ -34,6 +37,14 @@ class TouchTab : public BaseTab { background_offset_ = offset; } + // get and set touch icon + void set_touch_icon(const SkBitmap& bitmap) { + touch_icon_ = bitmap; + } + const SkBitmap& touch_icon() const { + return touch_icon_; + } + // Returns the minimum possible size of a single unselected Tab. static gfx::Size GetMinimumUnselectedSize(); @@ -74,6 +85,9 @@ class TouchTab : public BaseTab { // The offset used to paint the inactive background image. gfx::Point background_offset_; + // The touch icon found + SkBitmap touch_icon_; + // 'l' is for left // 'c' is for center // 'r' is for right diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.cc b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc index f051bac..46bfd71 100644 --- a/chrome/browser/ui/touch/tabs/touch_tab_strip.cc +++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.cc @@ -271,6 +271,11 @@ TouchTab* TouchTabStrip::GetTabAtTabDataIndex(int tab_data_index) const { return static_cast<TouchTab*>(base_tab_at_tab_index(tab_data_index)); } +// Retrieves the Tab at the specified *model* index. +TouchTab* TouchTabStrip::GetTouchTabAtModelIndex(int model_index) const { + return static_cast<TouchTab*>(GetBaseTabAtModelIndex(model_index)); +} + //////////////////////////////////////////////////////////////////////////////// // TouchTabStrip, private: diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip.h b/chrome/browser/ui/touch/tabs/touch_tab_strip.h index 0ab5396..f6dadb3 100644 --- a/chrome/browser/ui/touch/tabs/touch_tab_strip.h +++ b/chrome/browser/ui/touch/tabs/touch_tab_strip.h @@ -66,6 +66,9 @@ class TouchTabStrip : public BaseTabStrip { // is in terms of tab_data, *not* the model. TouchTab* GetTabAtTabDataIndex(int tab_data_index) const; + // Retrieves the Tab at the specified *model* index. + TouchTab* GetTouchTabAtModelIndex(int model_index) const; + private: void Init(); diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc new file mode 100644 index 0000000..185f542 --- /dev/null +++ b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.cc @@ -0,0 +1,171 @@ +// Copyright (c) 2011 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 "chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h" + +#include "chrome/browser/extensions/extension_tab_helper.h" +#include "chrome/browser/favicon/favicon_tab_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/touch/tabs/touch_tab.h" +#include "chrome/browser/ui/touch/tabs/touch_tab_strip.h" +#include "chrome/browser/ui/views/tabs/tab_renderer_data.h" +#include "skia/ext/image_operations.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" + +namespace { + +void CalcTouchIconTargetSize(int* width, int* height) { + if (*width > TouchTab::kTouchTargetIconSize || + *height > TouchTab::kTouchTargetIconSize) { + // Too big, resize it maintaining the aspect ratio. + float aspect_ratio = static_cast<float>(*width) / + static_cast<float>(*height); + *height = TouchTab::kTouchTargetIconSize; + *width = static_cast<int>(aspect_ratio * *height); + if (*width > TouchTab::kTouchTargetIconSize) { + *width = TouchTab::kTouchTargetIconSize; + *height = static_cast<int>(*width / aspect_ratio); + } + } +} + +GURL GetURLWithoutFragment(const GURL& gurl) { + url_canon::Replacements<char> replacements; + replacements.ClearUsername(); + replacements.ClearPassword(); + replacements.ClearQuery(); + replacements.ClearRef(); + return gurl.ReplaceComponents(replacements); +} + +} // namespace + +TouchTabStripController::TouchTabStripController(Browser* browser, + TabStripModel* model) + : BrowserTabStripController(browser, model) { +} + +TouchTabStripController::~TouchTabStripController() { +} + +void TouchTabStripController::TabDetachedAt(TabContentsWrapper* contents, + int model_index) { + if (consumer_.HasPendingRequests()) { + TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index); + consumer_.CancelAllRequestsForClientData(touch_tab); + } +} + +void TouchTabStripController::TabChangedAt(TabContentsWrapper* contents, + int model_index, + TabChangeType change_type) { + // Clear the large icon if we are loading a different URL in the same tab. + if (change_type == LOADING_ONLY) { + TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index); + if (!touch_tab->touch_icon().isNull()) { + GURL existing_tab_url = GetURLWithoutFragment(touch_tab->data().url); + GURL page_url = GetURLWithoutFragment(contents->tab_contents()->GetURL()); + // Reset touch icon if the url are different. + if (existing_tab_url != page_url) { + touch_tab->set_touch_icon(SkBitmap()); + consumer_.CancelAllRequestsForClientData(touch_tab); + } + } + } + + // Always call parent's method. + BrowserTabStripController::TabChangedAt(contents, model_index, change_type); +} + +void TouchTabStripController::SetTabRendererDataFromModel( + TabContents* contents, + int model_index, + TabRendererData* data, + TabStatus tab_status) { + // Call parent first. + BrowserTabStripController::SetTabRendererDataFromModel(contents, model_index, + data, tab_status); + if (tab_status == NEW_TAB) + return; + + // Use the touch icon if any. + TouchTab* touch_tab = tabstrip()->GetTouchTabAtModelIndex(model_index); + if (!touch_tab->touch_icon().isNull()) { + data->favicon = touch_tab->touch_icon(); + return; + } + + // In the case where we do not have a touch icon we scale up the small + // favicons (16x16) which originally are coming from NavigationEntry. + if (data->favicon.width() == kFaviconSize && + data->favicon.height() == kFaviconSize) { + data->favicon = skia::ImageOperations::Resize(data->favicon, + skia::ImageOperations::RESIZE_BEST, TouchTab::kTouchTargetIconSize, + TouchTab::kTouchTargetIconSize); + } + + // Check if we have an outstanding request for this tab. + if (consumer_.HasPendingRequests()) + consumer_.CancelAllRequestsForClientData(touch_tab); + + // Request touch icon. + GURL page_url = GetURLWithoutFragment(contents->GetURL()); + FaviconService* favicon_service = profile()->GetFaviconService( + Profile::EXPLICIT_ACCESS); + if (favicon_service) { + CancelableRequestProvider::Handle h = + favicon_service->GetFaviconForURL( + page_url, + history::TOUCH_ICON | history::TOUCH_PRECOMPOSED_ICON, + &consumer_, + NewCallback(this, &TouchTabStripController::OnTouchIconAvailable)); + consumer_.SetClientData(favicon_service, h, touch_tab); + } +} + +const TouchTabStrip* TouchTabStripController::tabstrip() const { + return static_cast<const TouchTabStrip*>( + BrowserTabStripController::tabstrip()); +} + +void TouchTabStripController::OnTouchIconAvailable( + FaviconService::Handle h, + history::FaviconData favicon) { + // Abandon the request when there is no valid favicon. + if (!favicon.is_valid()) + return; + + // Retrieve the model_index from the TouchTab pointer received. + TouchTab* touch_tab = consumer_.GetClientDataForCurrentRequest(); + int model_index = tabstrip()->GetModelIndexOfBaseTab(touch_tab); + if (!IsValidIndex(model_index)) + return; + + // Try to decode the favicon, return on failure. + SkBitmap bitmap; + gfx::PNGCodec::Decode(favicon.image_data->front(), + favicon.image_data->size(), + &bitmap); + if (bitmap.isNull()) + return; + + // Rescale output, if needed, and assign to the TouchTab instance. + int width = bitmap.width(); + int height = bitmap.height(); + if (width == TouchTab::kTouchTargetIconSize && + height == TouchTab::kTouchTargetIconSize) { + touch_tab->set_touch_icon(bitmap); + } else { + CalcTouchIconTargetSize(&width, &height); + touch_tab->set_touch_icon(skia::ImageOperations::Resize(bitmap, + skia::ImageOperations::RESIZE_BEST, width, height)); + } + + // Refresh UI since favicon changed. + browser()->GetTabContentsAt(model_index)->NotifyNavigationStateChanged( + TabContents::INVALIDATE_TAB); +} diff --git a/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h new file mode 100644 index 0000000..484b079 --- /dev/null +++ b/chrome/browser/ui/touch/tabs/touch_tab_strip_controller.h @@ -0,0 +1,46 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_ +#define CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_ +#pragma once + +#include "chrome/browser/favicon/favicon_service.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" + +class TouchTab; +class TouchTabStrip; + +class TouchTabStripController : public BrowserTabStripController { + public: + TouchTabStripController(Browser* browser, TabStripModel* model); + virtual ~TouchTabStripController(); + + virtual void TabDetachedAt(TabContentsWrapper* contents, + int model_index) OVERRIDE; + + virtual void TabChangedAt(TabContentsWrapper* contents, + int model_index, + TabChangeType change_type) OVERRIDE; + + protected: + virtual void SetTabRendererDataFromModel(TabContents* contents, + int model_index, + TabRendererData* data, + TabStatus tab_status) OVERRIDE; + + const TouchTabStrip* tabstrip() const; + + private: + void OnTouchIconAvailable(FaviconService::Handle h, + history::FaviconData favicon); + + // Our consumer for touch icon requests. + CancelableRequestConsumerTSimple<TouchTab*> consumer_; + + DISALLOW_COPY_AND_ASSIGN(TouchTabStripController); +}; + +#endif // CHROME_BROWSER_UI_TOUCH_TABS_TOUCH_TAB_STRIP_CONTROLLER_H_ |