| // 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 |