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 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 25 InfoBarArrowModel::~InfoBarArrowModel() { 26 } 27 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 40 bool InfoBarArrowModel::NeedToDrawInfoBarArrow() { 41 return SkColorGetA(CurrentInfoBarColors().top) != 0; 42 } 43 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 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 114 void InfoBarArrowModel::AnimationEnded(const ui::Animation* animation) { 115 observer_->PaintStateChanged(); 116 } 117 118 void InfoBarArrowModel::AnimationProgressed(const ui::Animation* animation) { 119 observer_->PaintStateChanged(); 120 } 121 122 void InfoBarArrowModel::AnimationCanceled(const ui::Animation* animation) { 123 observer_->PaintStateChanged(); 124 } 125