bubble_frame_view.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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/chromeos/frame/bubble_frame_view.h" 6 7#include "chrome/browser/chromeos/frame/bubble_window.h" 8#include "chrome/browser/chromeos/login/helper.h" 9#include "chrome/browser/ui/views/bubble_border.h" 10#include "grit/theme_resources.h" 11#include "ui/base/resource/resource_bundle.h" 12#include "ui/gfx/canvas_skia.h" 13#include "ui/gfx/font.h" 14#include "ui/gfx/insets.h" 15#include "ui/gfx/path.h" 16#include "ui/gfx/rect.h" 17#include "views/controls/button/image_button.h" 18#include "views/controls/label.h" 19#include "views/controls/throbber.h" 20#include "views/window/hit_test.h" 21#include "views/window/window.h" 22#include "views/window/window_delegate.h" 23#include "third_party/skia/include/core/SkPaint.h" 24 25namespace { 26 27static const int kTitleTopPadding = 10; 28static const int kTitleContentPadding = 10; 29static const int kHorizontalPadding = 10; 30 31// Title font size correction. 32#if defined(CROS_FONTS_USING_BCI) 33static const int kTitleFontSizeDelta = 0; 34#else 35static const int kTitleFontSizeDelta = 1; 36#endif 37 38} // namespace 39 40namespace chromeos { 41 42BubbleFrameView::BubbleFrameView(views::Window* frame, 43 BubbleWindow::Style style) 44 : frame_(frame), 45 style_(style), 46 title_(NULL), 47 close_button_(NULL), 48 throbber_(NULL) { 49 set_border(new BubbleBorder(BubbleBorder::NONE)); 50 51 if (frame_->GetDelegate()->ShouldShowWindowTitle()) { 52 title_ = new views::Label(frame_->GetDelegate()->GetWindowTitle()); 53 title_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 54 title_->SetFont(title_->font().DeriveFont(kFontSizeCorrectionDelta, 55 gfx::Font::BOLD)); 56 AddChildView(title_); 57 } 58 59 if (style_ & BubbleWindow::STYLE_XBAR) { 60 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 61 close_button_ = new views::ImageButton(this); 62 close_button_->SetImage(views::CustomButton::BS_NORMAL, 63 rb.GetBitmapNamed(IDR_CLOSE_BAR)); 64 close_button_->SetImage(views::CustomButton::BS_HOT, 65 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); 66 close_button_->SetImage(views::CustomButton::BS_PUSHED, 67 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); 68 AddChildView(close_button_); 69 } 70 71 if (style_ & BubbleWindow::STYLE_THROBBER) { 72 throbber_ = CreateDefaultSmoothedThrobber(); 73 AddChildView(throbber_); 74 } 75} 76 77BubbleFrameView::~BubbleFrameView() { 78} 79 80void BubbleFrameView::StartThrobber() { 81 DCHECK(throbber_ != NULL); 82 if (title_) 83 title_->SetText(std::wstring()); 84 throbber_->Start(); 85} 86 87void BubbleFrameView::StopThrobber() { 88 DCHECK(throbber_ != NULL); 89 throbber_->Stop(); 90 if (title_) 91 title_->SetText(frame_->GetDelegate()->GetWindowTitle()); 92} 93 94gfx::Rect BubbleFrameView::GetBoundsForClientView() const { 95 return client_view_bounds_; 96} 97 98gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( 99 const gfx::Rect& client_bounds) const { 100 gfx::Insets insets = GetInsets(); 101 102 gfx::Size title_size; 103 if (title_) 104 title_size = title_->GetPreferredSize(); 105 gfx::Size close_button_size; 106 if (close_button_) 107 close_button_size = close_button_->GetPreferredSize(); 108 gfx::Size throbber_size; 109 if (throbber_) 110 throbber_size = throbber_->GetPreferredSize(); 111 112 int top_height = insets.top(); 113 if (title_size.height() > 0 || 114 close_button_size.height() > 0 || 115 throbber_size.height() > 0) { 116 top_height += kTitleContentPadding + std::max( 117 std::max(title_size.height(), close_button_size.height()), 118 throbber_size.height()); 119 } 120 return gfx::Rect(std::max(0, client_bounds.x() - insets.left()), 121 std::max(0, client_bounds.y() - top_height), 122 client_bounds.width() + insets.width(), 123 client_bounds.height() + top_height + insets.bottom()); 124} 125 126int BubbleFrameView::NonClientHitTest(const gfx::Point& point) { 127 return HTNOWHERE; 128} 129 130void BubbleFrameView::GetWindowMask(const gfx::Size& size, 131 gfx::Path* window_mask) { 132} 133 134void BubbleFrameView::EnableClose(bool enable) { 135} 136 137void BubbleFrameView::ResetWindowControls() { 138} 139 140gfx::Insets BubbleFrameView::GetInsets() const { 141 gfx::Insets border_insets; 142 border()->GetInsets(&border_insets); 143 144 gfx::Insets insets(kTitleTopPadding, 145 kHorizontalPadding, 146 0, 147 kHorizontalPadding); 148 insets += border_insets; 149 return insets; 150} 151 152gfx::Size BubbleFrameView::GetPreferredSize() { 153 gfx::Size pref = frame_->GetClientView()->GetPreferredSize(); 154 gfx::Rect bounds(0, 0, pref.width(), pref.height()); 155 return frame_->GetNonClientView()->GetWindowBoundsForClientBounds( 156 bounds).size(); 157} 158 159void BubbleFrameView::Layout() { 160 gfx::Insets insets = GetInsets(); 161 162 gfx::Size title_size; 163 if (title_) 164 title_size = title_->GetPreferredSize(); 165 gfx::Size close_button_size; 166 if (close_button_) 167 close_button_size = close_button_->GetPreferredSize(); 168 gfx::Size throbber_size; 169 if (throbber_) 170 throbber_size = throbber_->GetPreferredSize(); 171 172 if (title_) { 173 title_->SetBounds( 174 insets.left(), insets.top(), 175 std::max(0, width() - insets.width() - close_button_size.width()), 176 title_size.height()); 177 } 178 179 if (close_button_) { 180 close_button_->SetBounds( 181 width() - insets.right() - close_button_size.width(), insets.top(), 182 close_button_size.width(), close_button_size.height()); 183 } 184 185 if (throbber_) { 186 throbber_->SetBounds( 187 insets.left(), insets.top(), 188 std::min(throbber_size.width(), width()), 189 throbber_size.height()); 190 } 191 192 int top_height = insets.top(); 193 if (title_size.height() > 0 || 194 close_button_size.height() > 0 || 195 throbber_size.height() > 0) { 196 top_height += kTitleContentPadding + std::max( 197 std::max(title_size.height(), close_button_size.height()), 198 throbber_size.height()); 199 } 200 client_view_bounds_.SetRect(insets.left(), top_height, 201 std::max(0, width() - insets.width()), 202 std::max(0, height() - top_height - insets.bottom())); 203} 204 205void BubbleFrameView::Paint(gfx::Canvas* canvas) { 206 // The border of this view creates an anti-aliased round-rect region for the 207 // contents, which we need to fill with the background color. 208 SkPaint paint; 209 paint.setAntiAlias(true); 210 paint.setStyle(SkPaint::kFill_Style); 211 paint.setColor(BubbleWindow::kBackgroundColor); 212 gfx::Path path; 213 gfx::Rect bounds(GetContentsBounds()); 214 SkRect rect; 215 rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()), 216 SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom())); 217 SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 218 path.addRoundRect(rect, radius, radius); 219 canvas->AsCanvasSkia()->drawPath(path, paint); 220 221 PaintBorder(canvas); 222} 223 224void BubbleFrameView::ButtonPressed(views::Button* sender, 225 const views::Event& event) { 226 if (close_button_ != NULL && sender == close_button_) 227 frame_->Close(); 228} 229 230} // namespace chromeos 231