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/gtk/infobars/infobar_arrow_model.h"
6
7 #include "chrome/browser/ui/gtk/infobars/infobar_gtk.h"
8 #include "third_party/skia/include/effects/SkGradientShader.h"
9 #include "ui/gfx/canvas_skia_paint.h"
10 #include "ui/gfx/color_utils.h"
11 #include "ui/gfx/rect.h"
12 #include "ui/gfx/skia_utils_gtk.h"
13
14 const size_t InfoBarArrowModel::kDefaultArrowSize = 12;
15
InfoBarArrowModel(Observer * observer)16 InfoBarArrowModel::InfoBarArrowModel(Observer* observer)
17 : observer_(observer),
18 animation_(this) {
19 animation_.SetTweenType(ui::Tween::LINEAR);
20 animation_.Reset(1.0);
21 target_colors_.top = target_colors_.bottom = SkColorSetARGB(0, 0, 0, 0);
22 previous_colors_ = target_colors_;
23 }
24
~InfoBarArrowModel()25 InfoBarArrowModel::~InfoBarArrowModel() {
26 }
27
CurrentInfoBarColors()28 InfoBarArrowModel::InfoBarColors InfoBarArrowModel::CurrentInfoBarColors() {
29 double alpha = animation_.GetCurrentValue();
30 InfoBarColors colors = {
31 color_utils::AlphaBlend(target_colors_.top,
32 previous_colors_.top,
33 alpha * 0xff),
34 color_utils::AlphaBlend(target_colors_.bottom,
35 previous_colors_.bottom,
36 alpha * 0xff)};
37 return colors;
38 }
39
NeedToDrawInfoBarArrow()40 bool InfoBarArrowModel::NeedToDrawInfoBarArrow() {
41 return SkColorGetA(CurrentInfoBarColors().top) != 0;
42 }
43
ShowArrowFor(InfoBar * bar,bool animate)44 void InfoBarArrowModel::ShowArrowFor(InfoBar* bar, bool animate) {
45 scoped_ptr<std::pair<SkColor, SkColor> > colors;
46
47 previous_colors_ = CurrentInfoBarColors();
48
49 if (bar) {
50 double r, g, b;
51 bar->GetTopColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
52 target_colors_.top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
53 bar->GetBottomColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
54 target_colors_.bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
55 } else {
56 target_colors_.bottom = target_colors_.top = SkColorSetARGB(0, 0, 0, 0);
57 }
58
59 if (animate) {
60 // Fade from the current color to the target color.
61 animation_.Reset();
62 animation_.Show();
63 } else {
64 // Skip straight to showing the target color.
65 animation_.Reset(1.0);
66 }
67
68 observer_->PaintStateChanged();
69 }
70
Paint(GtkWidget * widget,GdkEventExpose * expose,const gfx::Rect & bounds,const GdkColor & border_color)71 void InfoBarArrowModel::Paint(GtkWidget* widget,
72 GdkEventExpose* expose,
73 const gfx::Rect& bounds,
74 const GdkColor& border_color) {
75 if (!NeedToDrawInfoBarArrow())
76 return;
77
78 SkPath path;
79 path.moveTo(bounds.x() + 0.5, bounds.bottom() + 0.5);
80 path.rLineTo(bounds.width() / 2.0, -bounds.height());
81 path.lineTo(bounds.right() + 0.5, bounds.bottom() + 0.5);
82 path.close();
83
84 SkPaint paint;
85 paint.setStrokeWidth(1);
86 paint.setStyle(SkPaint::kFill_Style);
87 paint.setAntiAlias(true);
88
89 SkPoint grad_points[2];
90 grad_points[0].set(SkIntToScalar(0), SkIntToScalar(bounds.bottom()));
91 grad_points[1].set(SkIntToScalar(0),
92 SkIntToScalar(bounds.bottom() + InfoBar::kInfoBarHeight));
93
94 InfoBarColors colors = CurrentInfoBarColors();
95 SkColor grad_colors[2];
96 grad_colors[0] = colors.top;
97 grad_colors[1] = colors.bottom;
98
99 SkShader* gradient_shader = SkGradientShader::CreateLinear(
100 grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode);
101 paint.setShader(gradient_shader);
102 gradient_shader->unref();
103
104 gfx::CanvasSkiaPaint canvas(expose, false);
105 canvas.drawPath(path, paint);
106
107 paint.setShader(NULL);
108 paint.setColor(SkColorSetA(gfx::GdkColorToSkColor(border_color),
109 SkColorGetA(colors.top)));
110 paint.setStyle(SkPaint::kStroke_Style);
111 canvas.drawPath(path, paint);
112 }
113
AnimationEnded(const ui::Animation * animation)114 void InfoBarArrowModel::AnimationEnded(const ui::Animation* animation) {
115 observer_->PaintStateChanged();
116 }
117
AnimationProgressed(const ui::Animation * animation)118 void InfoBarArrowModel::AnimationProgressed(const ui::Animation* animation) {
119 observer_->PaintStateChanged();
120 }
121
AnimationCanceled(const ui::Animation * animation)122 void InfoBarArrowModel::AnimationCanceled(const ui::Animation* animation) {
123 observer_->PaintStateChanged();
124 }
125