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

Side by Side Diff: chrome/browser/views/browser_actions_container.cc

Issue 259004: First cut at badge implementation. Right now it just uses static (Closed)
Patch Set: cleanup Created 11 years, 2 months 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 unified diff | Download patch
« no previous file with comments | « chrome/browser/views/browser_actions_container.h ('k') | chrome/browser/views/toolbar_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/views/browser_actions_container.h" 5 #include "chrome/browser/views/browser_actions_container.h"
6 6
7 #include "app/gfx/canvas.h"
8 #include "app/resource_bundle.h"
7 #include "base/stl_util-inl.h" 9 #include "base/stl_util-inl.h"
8 #include "chrome/browser/extensions/extension_browser_event_router.h" 10 #include "chrome/browser/extensions/extension_browser_event_router.h"
9 #include "chrome/browser/extensions/extensions_service.h" 11 #include "chrome/browser/extensions/extensions_service.h"
10 #include "chrome/browser/extensions/extension_tabs_module.h" 12 #include "chrome/browser/extensions/extension_tabs_module.h"
11 #include "chrome/browser/image_loading_tracker.h" 13 #include "chrome/browser/image_loading_tracker.h"
12 #include "chrome/browser/profile.h" 14 #include "chrome/browser/profile.h"
13 #include "chrome/browser/views/toolbar_view.h" 15 #include "chrome/browser/views/toolbar_view.h"
14 #include "chrome/common/extensions/extension_action.h" 16 #include "chrome/common/extensions/extension_action.h"
15 #include "chrome/common/notification_source.h" 17 #include "chrome/common/notification_source.h"
16 #include "chrome/common/notification_type.h" 18 #include "chrome/common/notification_type.h"
19 #include "grit/app_resources.h"
17 #include "third_party/skia/include/core/SkBitmap.h" 20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkTypeface.h"
22 #include "third_party/skia/include/effects/SkGradientShader.h"
18 #include "views/controls/button/text_button.h" 23 #include "views/controls/button/text_button.h"
19 24
20 // The size of the icon for page actions. 25 // The size of the icon for page actions.
21 static const int kIconSize = 30; 26 static const int kIconSize = 29;
22 27
23 // The padding between the browser actions and the omnibox/page menu. 28 // The padding between the browser actions and the omnibox/page menu.
24 static const int kHorizontalPadding = 4; 29 static const int kHorizontalPadding = 4;
25 30
31 // This is the same value from toolbar.cc. We position the browser actions
32 // container flush with the edges of the toolbar as a special case so that we
33 // can draw the badge outside the visual bounds of the contianer.
34 static const int kControlVertOffset = 6;
35
26 //////////////////////////////////////////////////////////////////////////////// 36 ////////////////////////////////////////////////////////////////////////////////
27 // BrowserActionImageView 37 // BrowserActionImageView
28 38
29 // The BrowserActionImageView is a specialization of the TextButton class. 39 // The BrowserActionImageView is a specialization of the TextButton class.
30 // It acts on a ExtensionAction, in this case a BrowserAction and handles 40 // It acts on a ExtensionAction, in this case a BrowserAction and handles
31 // loading the image for the button asynchronously on the file thread to 41 // loading the image for the button asynchronously on the file thread to
32 class BrowserActionImageView : public views::TextButton, 42 class BrowserActionImageView : public views::TextButton,
33 public views::ButtonListener, 43 public views::ButtonListener,
34 public ImageLoadingTracker::Observer, 44 public ImageLoadingTracker::Observer,
35 public NotificationObserver { 45 public NotificationObserver {
(...skipping 11 matching lines...) Expand all
47 57
48 // Overridden from NotificationObserver: 58 // Overridden from NotificationObserver:
49 virtual void Observe(NotificationType type, 59 virtual void Observe(NotificationType type,
50 const NotificationSource& source, 60 const NotificationSource& source,
51 const NotificationDetails& details); 61 const NotificationDetails& details);
52 62
53 private: 63 private:
54 // Called to update the display to match the browser action's state. 64 // Called to update the display to match the browser action's state.
55 void OnStateUpdated(); 65 void OnStateUpdated();
56 66
67 // Override painting to implement the badge.
68 virtual void Paint(gfx::Canvas* canvas);
69
57 // The browser action this view represents. The ExtensionAction is not owned 70 // The browser action this view represents. The ExtensionAction is not owned
58 // by this class. 71 // by this class.
59 ExtensionAction* browser_action_; 72 ExtensionAction* browser_action_;
60 73
61 // The state of our browser action. Not owned by this class. 74 // The state of our browser action. Not owned by this class.
62 ExtensionActionState* browser_action_state_; 75 ExtensionActionState* browser_action_state_;
63 76
64 // The icons representing different states for the browser action. 77 // The icons representing different states for the browser action.
65 std::vector<SkBitmap> browser_action_icons_; 78 std::vector<SkBitmap> browser_action_icons_;
66 79
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 return gfx::Size(0, 0); 226 return gfx::Size(0, 0);
214 int width = kHorizontalPadding * 2 + 227 int width = kHorizontalPadding * 2 +
215 browser_action_views_.size() * kIconSize; 228 browser_action_views_.size() * kIconSize;
216 return gfx::Size(width, kIconSize); 229 return gfx::Size(width, kIconSize);
217 } 230 }
218 231
219 void BrowserActionsContainer::Layout() { 232 void BrowserActionsContainer::Layout() {
220 for (size_t i = 0; i < browser_action_views_.size(); ++i) { 233 for (size_t i = 0; i < browser_action_views_.size(); ++i) {
221 views::TextButton* view = browser_action_views_[i]; 234 views::TextButton* view = browser_action_views_[i];
222 int x = kHorizontalPadding + i * kIconSize; 235 int x = kHorizontalPadding + i * kIconSize;
223 view->SetBounds(x, (height() - kIconSize) / 2, kIconSize, kIconSize); 236 view->SetBounds(x, kControlVertOffset, kIconSize,
237 height() - (2 * kControlVertOffset));
224 } 238 }
225 } 239 }
226 240
227 void BrowserActionsContainer::Observe(NotificationType type, 241 void BrowserActionsContainer::Observe(NotificationType type,
228 const NotificationSource& source, 242 const NotificationSource& source,
229 const NotificationDetails& details) { 243 const NotificationDetails& details) {
230 if (type == NotificationType::EXTENSION_LOADED || 244 if (type == NotificationType::EXTENSION_LOADED ||
231 type == NotificationType::EXTENSION_UNLOADED || 245 type == NotificationType::EXTENSION_UNLOADED ||
232 type == NotificationType::EXTENSION_UNLOADED_DISABLED) { 246 type == NotificationType::EXTENSION_UNLOADED_DISABLED) {
233 RefreshBrowserActionViews(); 247 RefreshBrowserActionViews();
234 } else { 248 } else {
235 NOTREACHED() << L"Received unexpected notification"; 249 NOTREACHED() << L"Received unexpected notification";
236 } 250 }
237 } 251 }
252
253 void BrowserActionsContainer::PaintChildren(gfx::Canvas* canvas) {
254 View::PaintChildren(canvas);
255
256 // TODO(aa): Hook this up to the API to feed the badge color and text
257 // dynamically.
258 std::string text;
259 for (size_t i = 0; i < browser_action_views_.size(); ++i) {
260 if (i > 0) {
261 text += IntToString(i);
262 PaintBadge(canvas, browser_action_views_[i],
263 SkColorSetARGB(255, 218, 0, 24), text);
264 }
265 }
266 }
267
268 void BrowserActionsContainer::PaintBadge(gfx::Canvas* canvas,
269 views::TextButton* view,
270 const SkColor& badge_color,
271 const std::string& text) {
272 const int kTextSize = 8;
273 const int kBottomMargin = 6;
274 const int kPadding = 2;
275 const int kBadgeHeight = 11;
276 const int kMaxTextWidth = 23;
277 const int kCenterAlignThreshold = 20; // at than width, we center align
278
279 canvas->save();
280
281 SkTypeface* typeface = SkTypeface::CreateFromName("Arial", SkTypeface::kBold);
282 SkPaint text_paint;
283 text_paint.setAntiAlias(true);
284 text_paint.setColor(SkColorSetARGB(255, 255, 255, 255));
285 text_paint.setFakeBoldText(true);
286 text_paint.setTextAlign(SkPaint::kLeft_Align);
Erik does not do reviews 2009/10/01 20:21:04 Don't we want to be centered? In the case where t
287 text_paint.setTextSize(SkIntToScalar(kTextSize));
288 text_paint.setTypeface(typeface);
289
290 // Calculate text width. We clamp it to a max size.
291 SkScalar text_width = text_paint.measureText(text.c_str(), text.size());
292 text_width = SkIntToScalar(
293 std::min(kMaxTextWidth, SkScalarFloor(text_width)));
294
295 // Cacluate badge size. It is clamped to a min width just because it looks
296 // silly if it is too skinny.
297 int badge_width = SkScalarFloor(text_width) + kPadding * 2;
298 badge_width = std::max(kBadgeHeight, badge_width);
299
300 // Paint the badge background color in the right location. It is usually
301 // right-aligned, but it can also be center-aligned if it is large.
302 SkRect rect;
303 rect.fBottom = SkIntToScalar(height() - kBottomMargin);
304 rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight);
305 if (badge_width >= kCenterAlignThreshold) {
306 rect.fLeft = SkIntToScalar(view->bounds().x() +
307 (view->bounds().width() - badge_width) / 2);
308 rect.fRight = rect.fLeft + SkIntToScalar(badge_width);
309 } else {
310 rect.fRight = SkIntToScalar(view->bounds().right());
311 rect.fLeft = rect.fRight - badge_width;
312 }
313
314 SkPaint rect_paint;
315 rect_paint.setStyle(SkPaint::kFill_Style);
316 rect_paint.setAntiAlias(true);
317 rect_paint.setColor(badge_color);
318 canvas->drawRoundRect(rect, SkIntToScalar(2), SkIntToScalar(2), rect_paint);
319
320 // Overlay the gradient. It is stretchy, so we do this in three parts.
321 ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance();
322 SkBitmap* gradient_left = resource_bundle.GetBitmapNamed(
323 IDR_BROWSER_ACTION_BADGE_LEFT);
324 SkBitmap* gradient_right = resource_bundle.GetBitmapNamed(
325 IDR_BROWSER_ACTION_BADGE_RIGHT);
326 SkBitmap* gradient_center = resource_bundle.GetBitmapNamed(
327 IDR_BROWSER_ACTION_BADGE_CENTER);
328
329 canvas->drawBitmap(*gradient_left, rect.fLeft, rect.fTop);
330 canvas->TileImageInt(*gradient_center,
331 SkScalarFloor(rect.fLeft) + gradient_left->width(),
332 SkScalarFloor(rect.fTop),
333 SkScalarFloor(rect.width()) - gradient_left->width() -
334 gradient_right->width(),
335 SkScalarFloor(rect.height()));
336 canvas->drawBitmap(*gradient_right,
337 rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop);
338
339 // Finally, draw the text centered within the badge. We set a clip in case the
340 // text was too large.
341 rect.fLeft += kPadding;
342 rect.fRight -= kPadding;
343 canvas->clipRect(rect);
344 canvas->drawText(text.c_str(), text.size(),
345 rect.fLeft + (rect.width() - text_width) / 2,
346 rect.fTop + kTextSize + 1,
347 text_paint);
348 canvas->restore();
349 }
OLDNEW
« no previous file with comments | « chrome/browser/views/browser_actions_container.h ('k') | chrome/browser/views/toolbar_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698