// Copyright (c) 2012 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 "ui/views/controls/button/label_button_border.h"

#include "base/logging.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/effects/SkLerpXfermode.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/sys_color_change_listener.h"
#include "ui/native_theme/native_theme.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/native_theme_delegate.h"

namespace views {

namespace {

// Insets for the unified button images. This assumes that the images
// are of a 9 grid, of 5x5 size each.
const int kButtonInsets = 5;

// The text-button hot and pushed image IDs; normal is unadorned by default.
const int kTextHoveredImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER);
const int kTextPressedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED);

// A helper function to paint the appropriate broder images.
void PaintHelper(LabelButtonBorder* border,
                 gfx::Canvas* canvas,
                 ui::NativeTheme::State state,
                 const gfx::Rect& rect,
                 const ui::NativeTheme::ExtraParams& extra) {
  Painter* painter =
      border->GetPainter(extra.button.is_focused,
                         Button::GetButtonStateFrom(state));
  // Paint any corresponding unfocused painter if there is no focused painter.
  if (!painter && extra.button.is_focused)
    painter = border->GetPainter(false, Button::GetButtonStateFrom(state));
  if (painter)
    Painter::PaintPainterAt(canvas, painter, rect);
}

}  // namespace

LabelButtonBorder::LabelButtonBorder(Button::ButtonStyle style)
    : style_(style) {
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  const gfx::Insets insets(kButtonInsets,
                           kButtonInsets,
                           kButtonInsets,
                           kButtonInsets);

  if (style == Button::STYLE_BUTTON) {
    set_insets(gfx::Insets(8, 13, 8, 13));
    SetPainter(false, Button::STATE_NORMAL,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_NORMAL), insets));
    SetPainter(false, Button::STATE_HOVERED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_HOVER), insets));
    SetPainter(false, Button::STATE_PRESSED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_PRESSED), insets));
    SetPainter(false, Button::STATE_DISABLED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_DISABLED), insets));
    SetPainter(true, Button::STATE_NORMAL,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_FOCUSED_NORMAL), insets));
    SetPainter(true, Button::STATE_HOVERED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_FOCUSED_HOVER), insets));
    SetPainter(true, Button::STATE_PRESSED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_FOCUSED_PRESSED), insets));
    SetPainter(true, Button::STATE_DISABLED,
               Painter::CreateImagePainter(
                   *rb.GetImageSkiaNamed(IDR_BUTTON_DISABLED), insets));
  } else if (style == Button::STYLE_TEXTBUTTON) {
    set_insets(gfx::Insets(5, 6, 5, 6));
    SetPainter(false, Button::STATE_HOVERED,
               Painter::CreateImageGridPainter(kTextHoveredImages));
    SetPainter(false, Button::STATE_PRESSED,
               Painter::CreateImageGridPainter(kTextPressedImages));
  }
}

LabelButtonBorder::~LabelButtonBorder() {}

void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) {
  const NativeThemeDelegate* native_theme_delegate =
      static_cast<const LabelButton*>(&view);
  gfx::Rect rect(native_theme_delegate->GetThemePaintRect());
  ui::NativeTheme::ExtraParams extra;
  const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation();
  ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra);

  if (animation && animation->is_animating()) {
    // Linearly interpolate background and foreground painters during animation.
    const SkRect sk_rect = gfx::RectToSkRect(rect);
    canvas->sk_canvas()->saveLayer(&sk_rect, NULL);
    state = native_theme_delegate->GetBackgroundThemeState(&extra);
    PaintHelper(this, canvas, state, rect, extra);

    SkPaint paint;
    skia::RefPtr<SkXfermode> sk_lerp_xfer =
        skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue()));
    paint.setXfermode(sk_lerp_xfer.get());
    canvas->sk_canvas()->saveLayer(&sk_rect, &paint);
    state = native_theme_delegate->GetForegroundThemeState(&extra);
    PaintHelper(this, canvas, state, rect, extra);
    canvas->sk_canvas()->restore();

    canvas->sk_canvas()->restore();
  } else {
    PaintHelper(this, canvas, state, rect, extra);
  }
}

gfx::Insets LabelButtonBorder::GetInsets() const {
  return insets_;
}

gfx::Size LabelButtonBorder::GetMinimumSize() const {
  gfx::Size minimum_size;
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < Button::STATE_COUNT; ++j) {
      if (painters_[i][j])
        minimum_size.SetToMax(painters_[i][j]->GetMinimumSize());
    }
  }
  return minimum_size;
}

Painter* LabelButtonBorder::GetPainter(bool focused,
                                       Button::ButtonState state) {
  return painters_[focused ? 1 : 0][state].get();
}

void LabelButtonBorder::SetPainter(bool focused,
                                   Button::ButtonState state,
                                   Painter* painter) {
  painters_[focused ? 1 : 0][state].reset(painter);
}

}  // namespace views
