ProfilePolicyConnectorFactory: Refactoring from Profile to BrowserContext.
[chromium-blink-merge.git] / ash / frame / default_header_painter.cc
blob72d720eb460a5f7d4e8ad831b2d4545112beac1d
1 // Copyright 2014 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.
5 #include "ash/frame/default_header_painter.h"
7 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
8 #include "ash/frame/header_painter_util.h"
9 #include "base/debug/leak_annotations.h"
10 #include "base/logging.h" // DCHECK
11 #include "grit/ash_resources.h"
12 #include "third_party/skia/include/core/SkPaint.h"
13 #include "third_party/skia/include/core/SkPath.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/animation/slide_animation.h"
16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/color_utils.h"
18 #include "ui/gfx/font_list.h"
19 #include "ui/gfx/geometry/rect.h"
20 #include "ui/gfx/image/image.h"
21 #include "ui/gfx/skia_util.h"
22 #include "ui/views/view.h"
23 #include "ui/views/widget/native_widget_aura.h"
24 #include "ui/views/widget/widget.h"
25 #include "ui/views/widget/widget_delegate.h"
27 using views::Widget;
29 namespace {
31 // Color for the window title text.
32 const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40);
33 // Color of the active window header/content separator line.
34 const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(150, 150, 152);
35 // Color of the inactive window header/content separator line.
36 const SkColor kHeaderContentSeparatorInactiveColor =
37 SkColorSetRGB(180, 180, 182);
38 // The default color of the frame.
39 const SkColor kDefaultFrameColor = SkColorSetRGB(242, 242, 242);
40 // Duration of crossfade animation for activating and deactivating frame.
41 const int kActivationCrossfadeDurationMs = 200;
42 // Luminance below which to use white caption buttons.
43 const int kMaxLuminanceForLightButtons = 125;
45 // Tiles an image into an area, rounding the top corners.
46 void TileRoundRect(gfx::Canvas* canvas,
47 const SkPaint& paint,
48 const gfx::Rect& bounds,
49 int corner_radius) {
50 SkRect rect = gfx::RectToSkRect(bounds);
51 const SkScalar corner_radius_scalar = SkIntToScalar(corner_radius);
52 SkScalar radii[8] = {
53 corner_radius_scalar, corner_radius_scalar, // top-left
54 corner_radius_scalar, corner_radius_scalar, // top-right
55 0, 0, // bottom-right
56 0, 0}; // bottom-left
57 SkPath path;
58 path.addRoundRect(rect, radii, SkPath::kCW_Direction);
59 canvas->DrawPath(path, paint);
62 // Returns the FontList to use for the title.
63 const gfx::FontList& GetTitleFontList() {
64 static const gfx::FontList* title_font_list =
65 new gfx::FontList(views::NativeWidgetAura::GetWindowTitleFontList());
66 ANNOTATE_LEAKING_OBJECT_PTR(title_font_list);
67 return *title_font_list;
70 } // namespace
72 namespace ash {
74 ///////////////////////////////////////////////////////////////////////////////
75 // DefaultHeaderPainter, public:
77 DefaultHeaderPainter::DefaultHeaderPainter()
78 : frame_(NULL),
79 view_(NULL),
80 left_header_view_(NULL),
81 left_view_x_inset_(HeaderPainterUtil::GetDefaultLeftViewXInset()),
82 active_frame_color_(kDefaultFrameColor),
83 inactive_frame_color_(kDefaultFrameColor),
84 caption_button_container_(NULL),
85 height_(0),
86 mode_(MODE_INACTIVE),
87 initial_paint_(true),
88 activation_animation_(new gfx::SlideAnimation(this)) {
91 DefaultHeaderPainter::~DefaultHeaderPainter() {
94 void DefaultHeaderPainter::Init(
95 views::Widget* frame,
96 views::View* header_view,
97 FrameCaptionButtonContainerView* caption_button_container) {
98 DCHECK(frame);
99 DCHECK(header_view);
100 DCHECK(caption_button_container);
101 frame_ = frame;
102 view_ = header_view;
103 caption_button_container_ = caption_button_container;
104 UpdateAllButtonImages();
107 int DefaultHeaderPainter::GetMinimumHeaderWidth() const {
108 // Ensure we have enough space for the window icon and buttons. We allow
109 // the title string to collapse to zero width.
110 return GetTitleBounds().x() +
111 caption_button_container_->GetMinimumSize().width();
114 void DefaultHeaderPainter::PaintHeader(gfx::Canvas* canvas, Mode mode) {
115 Mode old_mode = mode_;
116 mode_ = mode;
118 if (mode_ != old_mode) {
119 UpdateAllButtonImages();
120 if (!initial_paint_ && HeaderPainterUtil::CanAnimateActivation(frame_)) {
121 activation_animation_->SetSlideDuration(kActivationCrossfadeDurationMs);
122 if (mode_ == MODE_ACTIVE)
123 activation_animation_->Show();
124 else
125 activation_animation_->Hide();
126 } else {
127 if (mode_ == MODE_ACTIVE)
128 activation_animation_->Reset(1);
129 else
130 activation_animation_->Reset(0);
132 initial_paint_ = false;
135 int corner_radius = (frame_->IsMaximized() || frame_->IsFullscreen()) ?
136 0 : HeaderPainterUtil::GetTopCornerRadiusWhenRestored();
138 SkPaint paint;
139 int active_alpha = activation_animation_->CurrentValueBetween(0, 255);
140 paint.setColor(color_utils::AlphaBlend(active_frame_color_,
141 inactive_frame_color_, active_alpha));
143 TileRoundRect(canvas, paint, GetLocalBounds(), corner_radius);
145 if (!frame_->IsMaximized() && !frame_->IsFullscreen() &&
146 mode_ == MODE_INACTIVE && !UsesCustomFrameColors()) {
147 PaintHighlightForInactiveRestoredWindow(canvas);
149 if (frame_->widget_delegate() &&
150 frame_->widget_delegate()->ShouldShowWindowTitle()) {
151 PaintTitleBar(canvas);
153 if (!UsesCustomFrameColors())
154 PaintHeaderContentSeparator(canvas);
157 void DefaultHeaderPainter::LayoutHeader() {
158 UpdateSizeButtonImages(ShouldUseLightImages());
159 caption_button_container_->Layout();
161 gfx::Size caption_button_container_size =
162 caption_button_container_->GetPreferredSize();
163 caption_button_container_->SetBounds(
164 view_->width() - caption_button_container_size.width(),
166 caption_button_container_size.width(),
167 caption_button_container_size.height());
169 LayoutLeftHeaderView();
171 // The header/content separator line overlays the caption buttons.
172 SetHeaderHeightForPainting(caption_button_container_->height());
175 int DefaultHeaderPainter::GetHeaderHeightForPainting() const {
176 return height_;
179 void DefaultHeaderPainter::SetHeaderHeightForPainting(int height) {
180 height_ = height;
183 void DefaultHeaderPainter::SchedulePaintForTitle() {
184 view_->SchedulePaintInRect(GetTitleBounds());
187 void DefaultHeaderPainter::UpdateLeftViewXInset(int left_view_x_inset) {
188 if (left_view_x_inset_ != left_view_x_inset) {
189 left_view_x_inset_ = left_view_x_inset;
190 LayoutLeftHeaderView();
194 void DefaultHeaderPainter::SetFrameColors(SkColor active_frame_color,
195 SkColor inactive_frame_color) {
196 active_frame_color_ = active_frame_color;
197 inactive_frame_color_ = inactive_frame_color;
198 UpdateAllButtonImages();
201 void DefaultHeaderPainter::UpdateLeftHeaderView(views::View* left_header_view) {
202 left_header_view_ = left_header_view;
205 ///////////////////////////////////////////////////////////////////////////////
206 // gfx::AnimationDelegate overrides:
208 void DefaultHeaderPainter::AnimationProgressed(
209 const gfx::Animation* animation) {
210 view_->SchedulePaintInRect(GetLocalBounds());
213 ///////////////////////////////////////////////////////////////////////////////
214 // DefaultHeaderPainter, private:
216 void DefaultHeaderPainter::PaintHighlightForInactiveRestoredWindow(
217 gfx::Canvas* canvas) {
218 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
219 gfx::ImageSkia top_edge = *rb.GetImageSkiaNamed(
220 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_TOP);
221 gfx::ImageSkia left_edge = *rb.GetImageSkiaNamed(
222 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT);
223 gfx::ImageSkia right_edge = *rb.GetImageSkiaNamed(
224 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT);
225 gfx::ImageSkia bottom_edge = *rb.GetImageSkiaNamed(
226 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM);
228 int left_edge_width = left_edge.width();
229 int right_edge_width = right_edge.width();
230 canvas->DrawImageInt(left_edge, 0, 0);
231 canvas->DrawImageInt(right_edge, view_->width() - right_edge_width, 0);
232 canvas->TileImageInt(
233 top_edge,
234 left_edge_width,
236 view_->width() - left_edge_width - right_edge_width,
237 top_edge.height());
239 DCHECK_EQ(left_edge.height(), right_edge.height());
240 int bottom = left_edge.height();
241 int bottom_height = bottom_edge.height();
242 canvas->TileImageInt(
243 bottom_edge,
244 left_edge_width,
245 bottom - bottom_height,
246 view_->width() - left_edge_width - right_edge_width,
247 bottom_height);
250 void DefaultHeaderPainter::PaintTitleBar(gfx::Canvas* canvas) {
251 // The window icon is painted by its own views::View.
252 gfx::Rect title_bounds = GetTitleBounds();
253 title_bounds.set_x(view_->GetMirroredXForRect(title_bounds));
254 canvas->DrawStringRectWithFlags(frame_->widget_delegate()->GetWindowTitle(),
255 GetTitleFontList(),
256 kTitleTextColor,
257 title_bounds,
258 gfx::Canvas::NO_SUBPIXEL_RENDERING);
261 void DefaultHeaderPainter::PaintHeaderContentSeparator(gfx::Canvas* canvas) {
262 SkColor color = (mode_ == MODE_ACTIVE) ?
263 kHeaderContentSeparatorColor :
264 kHeaderContentSeparatorInactiveColor;
266 SkPaint paint;
267 paint.setColor(color);
268 // Draw the line as 1px thick regardless of scale factor.
269 paint.setStrokeWidth(0);
271 float thickness = 1 / canvas->image_scale();
272 SkScalar y = SkIntToScalar(height_) - SkFloatToScalar(thickness);
273 canvas->sk_canvas()->drawLine(0, y, SkIntToScalar(view_->width()), y, paint);
276 void DefaultHeaderPainter::LayoutLeftHeaderView() {
277 if (left_header_view_) {
278 // Vertically center the left header view with respect to the caption button
279 // container.
280 // Floor when computing the center of |caption_button_container_|.
281 gfx::Size size = left_header_view_->GetPreferredSize();
282 int icon_offset_y = caption_button_container_->height() / 2 -
283 size.height() / 2;
284 left_header_view_->SetBounds(
285 left_view_x_inset_, icon_offset_y, size.width(), size.height());
289 bool DefaultHeaderPainter::ShouldUseLightImages() {
290 int luminance = color_utils::GetLuminanceForColor(
291 mode_ == MODE_INACTIVE ? inactive_frame_color_ : active_frame_color_);
292 return luminance < kMaxLuminanceForLightButtons;
295 void DefaultHeaderPainter::UpdateAllButtonImages() {
296 bool use_light_images = ShouldUseLightImages();
297 caption_button_container_->SetButtonImages(
298 CAPTION_BUTTON_ICON_MINIMIZE,
299 use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE_WHITE
300 : IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE,
301 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
302 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
304 UpdateSizeButtonImages(use_light_images);
306 caption_button_container_->SetButtonImages(
307 CAPTION_BUTTON_ICON_CLOSE,
308 use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_WHITE
309 : IDR_AURA_WINDOW_CONTROL_ICON_CLOSE,
310 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
311 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
313 caption_button_container_->SetButtonImages(
314 CAPTION_BUTTON_ICON_LEFT_SNAPPED,
315 use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED_WHITE
316 : IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED,
317 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
318 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
320 caption_button_container_->SetButtonImages(
321 CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
322 use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED_WHITE
323 : IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED,
324 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
325 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
328 void DefaultHeaderPainter::UpdateSizeButtonImages(bool use_light_images) {
329 int icon_id = 0;
330 if (frame_->IsMaximized() || frame_->IsFullscreen()) {
331 icon_id = use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_RESTORE_WHITE
332 : IDR_AURA_WINDOW_CONTROL_ICON_RESTORE;
333 } else {
334 icon_id = use_light_images ? IDR_AURA_WINDOW_CONTROL_ICON_MAXIMIZE_WHITE
335 : IDR_AURA_WINDOW_CONTROL_ICON_MAXIMIZE;
337 caption_button_container_->SetButtonImages(
338 CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
339 icon_id,
340 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
341 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
344 gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
345 return gfx::Rect(view_->width(), height_);
348 gfx::Rect DefaultHeaderPainter::GetTitleBounds() const {
349 return HeaderPainterUtil::GetTitleBounds(
350 left_header_view_, caption_button_container_, GetTitleFontList());
353 bool DefaultHeaderPainter::UsesCustomFrameColors() const {
354 return active_frame_color_ != kDefaultFrameColor ||
355 inactive_frame_color_ != kDefaultFrameColor;
358 } // namespace ash