// Copyright (c) 2011 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/ui/gtk/infobars/infobar_arrow_model.h" #include "chrome/browser/ui/gtk/infobars/infobar_gtk.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "ui/gfx/canvas_skia_paint.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/rect.h" #include "ui/gfx/skia_utils_gtk.h" const size_t InfoBarArrowModel::kDefaultArrowSize = 12; InfoBarArrowModel::InfoBarArrowModel(Observer* observer) : observer_(observer), animation_(this) { animation_.SetTweenType(ui::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::Rect& bounds, const GdkColor& border_color) { if (!NeedToDrawInfoBarArrow()) return; SkPath path; path.moveTo(bounds.x() + 0.5, bounds.bottom() + 0.5); path.rLineTo(bounds.width() / 2.0, -bounds.height()); path.lineTo(bounds.right() + 0.5, bounds.bottom() + 0.5); path.close(); SkPaint paint; paint.setStrokeWidth(1); paint.setStyle(SkPaint::kFill_Style); paint.setAntiAlias(true); SkPoint grad_points[2]; grad_points[0].set(SkIntToScalar(0), SkIntToScalar(bounds.bottom())); grad_points[1].set(SkIntToScalar(0), SkIntToScalar(bounds.bottom() + 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 ui::Animation* animation) { observer_->PaintStateChanged(); } void InfoBarArrowModel::AnimationProgressed(const ui::Animation* animation) { observer_->PaintStateChanged(); } void InfoBarArrowModel::AnimationCanceled(const ui::Animation* animation) { observer_->PaintStateChanged(); }