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/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_->window_delegate()->ShouldShowWindowTitle()) { 52 title_ = new views::Label(frame_->window_delegate()->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_->window_delegate()->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 140void BubbleFrameView::UpdateWindowIcon() { 141} 142 143gfx::Insets BubbleFrameView::GetInsets() const { 144 gfx::Insets border_insets; 145 border()->GetInsets(&border_insets); 146 147 gfx::Insets insets(kTitleTopPadding, 148 kHorizontalPadding, 149 0, 150 kHorizontalPadding); 151 insets += border_insets; 152 return insets; 153} 154 155gfx::Size BubbleFrameView::GetPreferredSize() { 156 gfx::Size pref = frame_->client_view()->GetPreferredSize(); 157 gfx::Rect bounds(0, 0, pref.width(), pref.height()); 158 return frame_->non_client_view()->GetWindowBoundsForClientBounds( 159 bounds).size(); 160} 161 162void BubbleFrameView::Layout() { 163 gfx::Insets insets = GetInsets(); 164 165 gfx::Size title_size; 166 if (title_) 167 title_size = title_->GetPreferredSize(); 168 gfx::Size close_button_size; 169 if (close_button_) 170 close_button_size = close_button_->GetPreferredSize(); 171 gfx::Size throbber_size; 172 if (throbber_) 173 throbber_size = throbber_->GetPreferredSize(); 174 175 if (title_) { 176 title_->SetBounds( 177 insets.left(), insets.top(), 178 std::max(0, width() - insets.width() - close_button_size.width()), 179 title_size.height()); 180 } 181 182 if (close_button_) { 183 close_button_->SetBounds( 184 width() - insets.right() - close_button_size.width(), insets.top(), 185 close_button_size.width(), close_button_size.height()); 186 } 187 188 if (throbber_) { 189 throbber_->SetBounds( 190 insets.left(), insets.top(), 191 std::min(throbber_size.width(), width()), 192 throbber_size.height()); 193 } 194 195 int top_height = insets.top(); 196 if (title_size.height() > 0 || 197 close_button_size.height() > 0 || 198 throbber_size.height() > 0) { 199 top_height += kTitleContentPadding + std::max( 200 std::max(title_size.height(), close_button_size.height()), 201 throbber_size.height()); 202 } 203 client_view_bounds_.SetRect(insets.left(), top_height, 204 std::max(0, width() - insets.width()), 205 std::max(0, height() - top_height - insets.bottom())); 206} 207 208void BubbleFrameView::OnPaint(gfx::Canvas* canvas) { 209 // The border of this view creates an anti-aliased round-rect region for the 210 // contents, which we need to fill with the background color. 211 SkPaint paint; 212 paint.setAntiAlias(true); 213 paint.setStyle(SkPaint::kFill_Style); 214 paint.setColor(BubbleWindow::kBackgroundColor); 215 gfx::Path path; 216 gfx::Rect bounds(GetContentsBounds()); 217 SkRect rect; 218 rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()), 219 SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom())); 220 SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 221 path.addRoundRect(rect, radius, radius); 222 canvas->AsCanvasSkia()->drawPath(path, paint); 223 224 OnPaintBorder(canvas); 225} 226 227void BubbleFrameView::ButtonPressed(views::Button* sender, 228 const views::Event& event) { 229 if (close_button_ != NULL && sender == close_button_) 230 frame_->CloseWindow(); 231} 232 233} // namespace chromeos 234