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