• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/touch/tabs/touch_tab.h"
6 
7 #include "base/logging.h"
8 #include "chrome/browser/themes/theme_service.h"
9 #include "grit/app_resources.h"
10 #include "grit/theme_resources.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas_skia.h"
13 #include "ui/gfx/favicon_size.h"
14 #include "ui/gfx/path.h"
15 #include "ui/gfx/skbitmap_operations.h"
16 
17 static const int kLeftPadding = 16;
18 static const int kRightPadding = 15;
19 static const int kDropShadowHeight = 2;
20 
21 // The size of the favicon touch area. This generally would be the same as
22 // kFaviconSize in ui/gfx/favicon_size.h
23 static const int kTouchTabIconSize = 32;
24 
25 TouchTab::TouchTabImage TouchTab::tab_alpha = {0};
26 TouchTab::TouchTabImage TouchTab::tab_active = {0};
27 TouchTab::TouchTabImage TouchTab::tab_inactive = {0};
28 
29 ////////////////////////////////////////////////////////////////////////////////
30 // TouchTab, public:
31 
TouchTab(TabController * controller)32 TouchTab::TouchTab(TabController* controller)
33     : BaseTab(controller) {
34   InitTabResources();
35 }
36 
~TouchTab()37 TouchTab::~TouchTab() {
38 }
39 
40 // static
GetMinimumUnselectedSize()41 gfx::Size TouchTab::GetMinimumUnselectedSize() {
42   InitTabResources();
43 
44   gfx::Size minimum_size;
45   minimum_size.set_width(kLeftPadding + kRightPadding);
46   minimum_size.set_height(32);
47   return minimum_size;
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 // TouchTab, protected:
GetTitleBounds() const52 const gfx::Rect& TouchTab::GetTitleBounds() const {
53   return title_bounds_;
54 }
55 
GetIconBounds() const56 const gfx::Rect& TouchTab::GetIconBounds() const {
57   return favicon_bounds_;
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 // TouchTab, views::View overrides:
62 
63 // We'll get selected via the mouse interactions with the TouchTabStrip.  There
64 // is no need to directly handle the mouse movements in the TouchTab.
65 
OnMousePressed(const views::MouseEvent & event)66 bool TouchTab::OnMousePressed(const views::MouseEvent& event) {
67   return false;
68 }
69 
OnMouseDragged(const views::MouseEvent & event)70 bool TouchTab::OnMouseDragged(const views::MouseEvent& event) {
71   return false;
72 }
73 
OnMouseReleased(const views::MouseEvent & event)74 void TouchTab::OnMouseReleased(const views::MouseEvent& event) {
75 }
76 
OnPaint(gfx::Canvas * canvas)77 void TouchTab::OnPaint(gfx::Canvas* canvas) {
78   // Don't paint if we're narrower than we can render correctly. (This should
79   // only happen during animations).
80   if (width() < GetMinimumUnselectedSize().width() && !data().mini)
81     return;
82 
83   PaintTabBackground(canvas);
84 
85   SkColor title_color = GetThemeProvider()->
86       GetColor(IsSelected() ?
87           ThemeService::COLOR_TAB_TEXT :
88           ThemeService::COLOR_BACKGROUND_TAB_TEXT);
89 
90   PaintTitle(canvas, title_color);
91   PaintIcon(canvas);
92 }
93 
Layout()94 void TouchTab::Layout() {
95   gfx::Rect local_bounds = GetContentsBounds();
96   TouchTabImage* tab_image = &tab_active;
97   TouchTabImage* alpha = &tab_alpha;
98   int image_height = alpha->image_l->height();
99   int x_base = tab_image->image_l->width();
100   int y_base = height() - image_height;
101   int center_width = width() - tab_image->l_width - tab_image->r_width;
102   if (center_width < 0)
103     center_width = 0;
104   title_bounds_ = gfx::Rect(x_base, y_base, center_width, image_height);
105   favicon_bounds_ = local_bounds;
106 }
107 
HasHitTestMask() const108 bool TouchTab::HasHitTestMask() const {
109   return true;
110 }
111 
GetHitTestMask(gfx::Path * path) const112 void TouchTab::GetHitTestMask(gfx::Path* path) const {
113   DCHECK(path);
114 
115   SkScalar h = SkIntToScalar(height());
116   SkScalar w = SkIntToScalar(width());
117 
118   path->moveTo(0, h);
119   path->lineTo(0, 0);
120   path->lineTo(w, 0);
121   path->lineTo(w, h);
122   path->lineTo(0, h);
123   path->close();
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 // TouchTab, private:
128 
PaintTabBackground(gfx::Canvas * canvas)129 void TouchTab::PaintTabBackground(gfx::Canvas* canvas) {
130   if (IsSelected()) {
131     PaintActiveTabBackground(canvas);
132   }
133 }
134 
PaintActiveTabBackground(gfx::Canvas * canvas)135 void TouchTab::PaintActiveTabBackground(gfx::Canvas* canvas) {
136   int offset = GetMirroredX() + background_offset_.x();
137   ThemeProvider* tp = GetThemeProvider();
138   if (!tp)
139     NOTREACHED() << "Unable to get theme provider";
140 
141   SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
142 
143   TouchTabImage* tab_image = &tab_active;
144   TouchTabImage* alpha = &tab_alpha;
145 
146   // Draw left edge.
147   int image_height = alpha->image_l->height();
148   int y_base = height() - image_height;
149   SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
150       *tab_bg, offset, 0, tab_image->l_width, image_height);
151   SkBitmap theme_l =
152       SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
153   canvas->DrawBitmapInt(theme_l, 0, y_base);
154 
155   // Draw right edge.
156   SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
157       offset + width() - tab_image->r_width, 0,
158       tab_image->r_width, image_height);
159   SkBitmap theme_r =
160       SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
161   canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, y_base);
162 
163   // Draw center.  Instead of masking out the top portion we simply skip over it
164   // by incrementing by kDropShadowHeight, since it's a simple rectangle.
165   canvas->TileImageInt(*tab_bg,
166      offset + tab_image->l_width,
167      kDropShadowHeight + tab_image->y_offset,
168      tab_image->l_width,
169      y_base + kDropShadowHeight + tab_image->y_offset,
170      width() - tab_image->l_width - tab_image->r_width,
171      height() - kDropShadowHeight - tab_image->y_offset);
172 
173   // Now draw the highlights/shadows around the tab edge.
174   canvas->DrawBitmapInt(*tab_image->image_l, 0, y_base);
175   canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, y_base,
176       width() - tab_image->l_width - tab_image->r_width, image_height);
177   canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width,
178                         y_base);
179 }
180 
PaintIcon(gfx::Canvas * canvas)181 void TouchTab::PaintIcon(gfx::Canvas* canvas) {
182   // TODO(wyck): use thumbnailer to get better page images
183   int x = favicon_bounds_.x();
184   int y = favicon_bounds_.y();
185 
186   TouchTabImage* tab_image = &tab_active;
187   int x_base = tab_image->image_l->width();
188 
189   x += x_base;
190 
191   if (base::i18n::IsRTL()) {
192     x = width() - x -
193         (data().favicon.isNull() ? kFaviconSize : data().favicon.width());
194   }
195 
196   int favicon_x = x;
197   if (!data().favicon.isNull() && data().favicon.width() != kFaviconSize)
198     favicon_x += (data().favicon.width() - kFaviconSize) / 2;
199 
200   if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
201     ThemeProvider* tp = GetThemeProvider();
202     SkBitmap frames(*tp->GetBitmapNamed(
203         (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ?
204         IDR_THROBBER_WAITING : IDR_THROBBER));
205     int image_size = frames.height();
206     int image_offset = loading_animation_frame() * image_size;
207     canvas->DrawBitmapInt(frames, image_offset, 0, image_size, image_size, x, y,
208                           kTouchTabIconSize, kTouchTabIconSize, false);
209   } else {
210     canvas->Save();
211     canvas->ClipRectInt(0, 0, width(), height());
212     if (should_display_crashed_favicon()) {
213       ResourceBundle& rb = ResourceBundle::GetSharedInstance();
214       SkBitmap crashed_favicon(*rb.GetBitmapNamed(IDR_SAD_FAVICON));
215       canvas->DrawBitmapInt(crashed_favicon, 0, 0, crashed_favicon.width(),
216           crashed_favicon.height(), x, y + favicon_hiding_offset(),
217           kTouchTabIconSize, kTouchTabIconSize, true);
218     } else {
219       if (!data().favicon.isNull()) {
220 
221         if ((data().favicon.width() == kTouchTabIconSize) &&
222             (data().favicon.height() == kTouchTabIconSize)) {
223           canvas->DrawBitmapInt(data().favicon, 0, 0,
224                                 data().favicon.width(), data().favicon.height(),
225                                 x, y + favicon_hiding_offset(),
226                                 kTouchTabIconSize, kTouchTabIconSize, true);
227         } else {
228           // Draw a background around target touch area in case the favicon
229           // is smaller than touch area (e.g www.google.com is 16x16 now)
230           canvas->DrawRectInt(
231               GetThemeProvider()->GetColor(
232                   ThemeService::COLOR_BUTTON_BACKGROUND),
233               x, y, kTouchTabIconSize, kTouchTabIconSize);
234 
235           // We center the image
236           // TODO(saintlou): later request larger image from HistoryService
237           canvas->DrawBitmapInt(data().favicon, 0, 0, data().favicon.width(),
238               data().favicon.height(),
239               x + ((kTouchTabIconSize - data().favicon.width()) / 2),
240               y + ((kTouchTabIconSize - data().favicon.height()) / 2) +
241                                                      favicon_hiding_offset(),
242               data().favicon.width(), data().favicon.height(), true);
243         }
244       }
245     }
246     canvas->Restore();
247   }
248 }
249 
250 // static
InitTabResources()251 void TouchTab::InitTabResources() {
252   static bool initialized = false;
253   if (initialized)
254     return;
255 
256   initialized = true;
257 
258   // Load the tab images once now, and maybe again later if the theme changes.
259   LoadTabImages();
260 }
261 
262 
263 // static
LoadTabImages()264 void TouchTab::LoadTabImages() {
265   // We're not letting people override tab images just yet.
266   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
267 
268   tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
269   tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
270 
271   tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
272   tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
273   tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
274   tab_active.l_width = tab_active.image_l->width();
275   tab_active.r_width = tab_active.image_r->width();
276 
277   tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
278   tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
279   tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
280   tab_inactive.l_width = tab_inactive.image_l->width();
281   tab_inactive.r_width = tab_inactive.image_r->width();
282 }
283