summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/infobar_arrow_model.cc
blob: e66bb02b4dcc83b6c21b7fb13b6d30f49d9de7a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) 2010 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/gtk/infobar_arrow_model.h"

#include "chrome/browser/gtk/infobar_gtk.h"
#include "gfx/canvas_skia_paint.h"
#include "gfx/color_utils.h"
#include "gfx/point.h"
#include "gfx/skia_utils_gtk.h"
#include "third_party/skia/include/effects/SkGradientShader.h"

InfoBarArrowModel::InfoBarArrowModel(Observer* observer)
    : observer_(observer),
      animation_(this) {
  animation_.SetTweenType(Tween::LINEAR);
  animation_.Reset(1.0);
  target_colors_.top = target_colors_.bottom = SkColorSetARGB(0, 0, 0, 0);
  previous_colors_ = target_colors_;
}

InfoBarArrowModel::~InfoBarArrowModel() {
}

InfoBarArrowModel::InfoBarColors InfoBarArrowModel::CurrentInfoBarColors() {
  double alpha = animation_.GetCurrentValue();
  InfoBarColors colors = {
      color_utils::AlphaBlend(target_colors_.top,
                              previous_colors_.top,
                              alpha * 0xff),
      color_utils::AlphaBlend(target_colors_.bottom,
                              previous_colors_.bottom,
                              alpha * 0xff)};
  return colors;
}

bool InfoBarArrowModel::NeedToDrawInfoBarArrow() {
  return SkColorGetA(CurrentInfoBarColors().top) != 0;
}

void InfoBarArrowModel::ShowArrowFor(InfoBar* bar, bool animate) {
  scoped_ptr<std::pair<SkColor, SkColor> > colors;

  previous_colors_ = CurrentInfoBarColors();

  if (bar) {
    double r, g, b;
    bar->GetTopColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
    target_colors_.top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
    bar->GetBottomColor(bar->delegate()->GetInfoBarType(), &r, &g, &b);
    target_colors_.bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff);
  } else {
    target_colors_.bottom = target_colors_.top = SkColorSetARGB(0, 0, 0, 0);
  }

  if (animate) {
    // Fade from the current color to the target color.
    animation_.Reset();
    animation_.Show();
  } else {
    // Skip straight to showing the target color.
    animation_.Reset(1.0);
  }

  observer_->PaintStateChanged();
}

void InfoBarArrowModel::Paint(GtkWidget* widget,
                              GdkEventExpose* expose,
                              const gfx::Point& origin,
                              const GdkColor& border_color) {
  if (!NeedToDrawInfoBarArrow())
    return;

  // The size of the arrow (its height; also half its width).
  const int kArrowSize = 10;

  SkPath path;
  path.moveTo(SkPoint::Make(origin.x() - kArrowSize, origin.y()));
  path.rLineTo(kArrowSize, -kArrowSize);
  path.rLineTo(kArrowSize, kArrowSize);
  path.close();

  SkPaint paint;
  paint.setStrokeWidth(1);
  paint.setStyle(SkPaint::kFill_Style);

  SkPoint grad_points[2];
  grad_points[0].set(SkIntToScalar(0), SkIntToScalar(origin.y()));
  grad_points[1].set(SkIntToScalar(0),
                     SkIntToScalar(origin.y() + InfoBar::kInfoBarHeight));

  InfoBarColors colors = CurrentInfoBarColors();
  SkColor grad_colors[2];
  grad_colors[0] = colors.top;
  grad_colors[1] = colors.bottom;

  SkShader* gradient_shader = SkGradientShader::CreateLinear(
      grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode);
  paint.setShader(gradient_shader);
  gradient_shader->unref();

  gfx::CanvasSkiaPaint canvas(expose, false);
  canvas.drawPath(path, paint);

  paint.setShader(NULL);
  paint.setColor(SkColorSetA(gfx::GdkColorToSkColor(border_color),
                             SkColorGetA(colors.top)));
  paint.setStyle(SkPaint::kStroke_Style);
  canvas.drawPath(path, paint);
}

void InfoBarArrowModel::AnimationEnded(const Animation* animation) {
  observer_->PaintStateChanged();
}

void InfoBarArrowModel::AnimationProgressed(const Animation* animation) {
  observer_->PaintStateChanged();
}

void InfoBarArrowModel::AnimationCanceled(const Animation* animation) {
  observer_->PaintStateChanged();
}