普通文本  |  234行  |  7.07 KB

// 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/chromeos/frame/bubble_frame_view.h"

#include "chrome/browser/chromeos/frame/bubble_window.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/ui/views/bubble/bubble_border.h"
#include "grit/theme_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/font.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/path.h"
#include "ui/gfx/rect.h"
#include "views/controls/button/image_button.h"
#include "views/controls/label.h"
#include "views/controls/throbber.h"
#include "views/window/hit_test.h"
#include "views/window/window.h"
#include "views/window/window_delegate.h"
#include "third_party/skia/include/core/SkPaint.h"

namespace {

static const int kTitleTopPadding = 10;
static const int kTitleContentPadding = 10;
static const int kHorizontalPadding = 10;

// Title font size correction.
#if defined(CROS_FONTS_USING_BCI)
static const int kTitleFontSizeDelta = 0;
#else
static const int kTitleFontSizeDelta = 1;
#endif

}  // namespace

namespace chromeos {

BubbleFrameView::BubbleFrameView(views::Window* frame,
                                 BubbleWindow::Style style)
    : frame_(frame),
      style_(style),
      title_(NULL),
      close_button_(NULL),
      throbber_(NULL) {
  set_border(new BubbleBorder(BubbleBorder::NONE));

  if (frame_->window_delegate()->ShouldShowWindowTitle()) {
    title_ = new views::Label(frame_->window_delegate()->GetWindowTitle());
    title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    title_->SetFont(title_->font().DeriveFont(kFontSizeCorrectionDelta,
                                              gfx::Font::BOLD));
    AddChildView(title_);
  }

  if (style_ & BubbleWindow::STYLE_XBAR) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    close_button_ = new views::ImageButton(this);
    close_button_->SetImage(views::CustomButton::BS_NORMAL,
        rb.GetBitmapNamed(IDR_CLOSE_BAR));
    close_button_->SetImage(views::CustomButton::BS_HOT,
        rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
    close_button_->SetImage(views::CustomButton::BS_PUSHED,
        rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
    AddChildView(close_button_);
  }

  if (style_ & BubbleWindow::STYLE_THROBBER) {
    throbber_ = CreateDefaultSmoothedThrobber();
    AddChildView(throbber_);
  }
}

BubbleFrameView::~BubbleFrameView() {
}

void BubbleFrameView::StartThrobber() {
  DCHECK(throbber_ != NULL);
  if (title_)
    title_->SetText(std::wstring());
  throbber_->Start();
}

void BubbleFrameView::StopThrobber() {
  DCHECK(throbber_ != NULL);
  throbber_->Stop();
  if (title_)
    title_->SetText(frame_->window_delegate()->GetWindowTitle());
}

gfx::Rect BubbleFrameView::GetBoundsForClientView() const {
  return client_view_bounds_;
}

gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds(
    const gfx::Rect& client_bounds) const {
  gfx::Insets insets = GetInsets();

  gfx::Size title_size;
  if (title_)
    title_size = title_->GetPreferredSize();
  gfx::Size close_button_size;
  if (close_button_)
    close_button_size = close_button_->GetPreferredSize();
  gfx::Size throbber_size;
  if (throbber_)
    throbber_size = throbber_->GetPreferredSize();

  int top_height = insets.top();
  if (title_size.height() > 0 ||
      close_button_size.height() > 0 ||
      throbber_size.height() > 0) {
    top_height += kTitleContentPadding + std::max(
        std::max(title_size.height(), close_button_size.height()),
        throbber_size.height());
  }
  return gfx::Rect(std::max(0, client_bounds.x() - insets.left()),
                   std::max(0, client_bounds.y() - top_height),
                   client_bounds.width() + insets.width(),
                   client_bounds.height() + top_height + insets.bottom());
}

int BubbleFrameView::NonClientHitTest(const gfx::Point& point) {
  return HTNOWHERE;
}

void BubbleFrameView::GetWindowMask(const gfx::Size& size,
                                    gfx::Path* window_mask) {
}

void BubbleFrameView::EnableClose(bool enable) {
}

void BubbleFrameView::ResetWindowControls() {
}

void BubbleFrameView::UpdateWindowIcon() {
}

gfx::Insets BubbleFrameView::GetInsets() const {
  gfx::Insets border_insets;
  border()->GetInsets(&border_insets);

  gfx::Insets insets(kTitleTopPadding,
                     kHorizontalPadding,
                     0,
                     kHorizontalPadding);
  insets += border_insets;
  return insets;
}

gfx::Size BubbleFrameView::GetPreferredSize() {
  gfx::Size pref = frame_->client_view()->GetPreferredSize();
  gfx::Rect bounds(0, 0, pref.width(), pref.height());
  return frame_->non_client_view()->GetWindowBoundsForClientBounds(
      bounds).size();
}

void BubbleFrameView::Layout() {
  gfx::Insets insets = GetInsets();

  gfx::Size title_size;
  if (title_)
    title_size = title_->GetPreferredSize();
  gfx::Size close_button_size;
  if (close_button_)
    close_button_size = close_button_->GetPreferredSize();
  gfx::Size throbber_size;
  if (throbber_)
    throbber_size = throbber_->GetPreferredSize();

  if (title_) {
    title_->SetBounds(
        insets.left(), insets.top(),
        std::max(0, width() - insets.width() - close_button_size.width()),
        title_size.height());
  }

  if (close_button_) {
    close_button_->SetBounds(
        width() - insets.right() - close_button_size.width(), insets.top(),
        close_button_size.width(), close_button_size.height());
  }

  if (throbber_) {
    throbber_->SetBounds(
        insets.left(), insets.top(),
        std::min(throbber_size.width(), width()),
        throbber_size.height());
  }

  int top_height = insets.top();
  if (title_size.height() > 0 ||
      close_button_size.height() > 0 ||
      throbber_size.height() > 0) {
    top_height += kTitleContentPadding + std::max(
        std::max(title_size.height(), close_button_size.height()),
        throbber_size.height());
  }
  client_view_bounds_.SetRect(insets.left(), top_height,
      std::max(0, width() - insets.width()),
      std::max(0, height() - top_height - insets.bottom()));
}

void BubbleFrameView::OnPaint(gfx::Canvas* canvas) {
  // The border of this view creates an anti-aliased round-rect region for the
  // contents, which we need to fill with the background color.
  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(BubbleWindow::kBackgroundColor);
  gfx::Path path;
  gfx::Rect bounds(GetContentsBounds());
  SkRect rect;
  rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
           SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom()));
  SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius());
  path.addRoundRect(rect, radius, radius);
  canvas->AsCanvasSkia()->drawPath(path, paint);

  OnPaintBorder(canvas);
}

void BubbleFrameView::ButtonPressed(views::Button* sender,
                                    const views::Event& event) {
  if (close_button_ != NULL && sender == close_button_)
    frame_->CloseWindow();
}

}  // namespace chromeos