Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: ash/frame/default_header_painter.cc

Issue 189463013: [Refactor] Move code for painting the window header for browser windows out of ash (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/frame/default_header_painter.h ('k') | ash/frame/default_header_painter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "ash/frame/default_header_painter.h"
6
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/SkColor.h"
13 #include "third_party/skia/include/core/SkPaint.h"
14 #include "third_party/skia/include/core/SkPath.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/gfx/animation/slide_animation.h"
17 #include "ui/gfx/canvas.h"
18 #include "ui/gfx/font_list.h"
19 #include "ui/gfx/image/image.h"
20 #include "ui/gfx/rect.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"
26
27 using views::Widget;
28
29 namespace {
30
31 // Color for the window title text.
32 const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40);
33 // Size of header/content separator line.
34 const int kHeaderContentSeparatorSize = 1;
35 // Color of the active window header/content separator line.
36 const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(180, 180, 182);
37 // Color of the inactive window header/content separator line.
38 const SkColor kHeaderContentSeparatorInactiveColor =
39 SkColorSetRGB(150, 150, 152);
40 // Duration of crossfade animation for activating and deactivating frame.
41 const int kActivationCrossfadeDurationMs = 200;
42
43 // Tiles an image into an area, rounding the top corners.
44 void TileRoundRect(gfx::Canvas* canvas,
45 const gfx::ImageSkia& image,
46 const SkPaint& paint,
47 const gfx::Rect& bounds,
48 int corner_radius) {
49 SkRect rect = gfx::RectToSkRect(bounds);
50 const SkScalar corner_radius_scalar = SkIntToScalar(corner_radius);
51 SkScalar radii[8] = {
52 corner_radius_scalar, corner_radius_scalar, // top-left
53 corner_radius_scalar, corner_radius_scalar, // top-right
54 0, 0, // bottom-right
55 0, 0}; // bottom-left
56 SkPath path;
57 path.addRoundRect(rect, radii, SkPath::kCW_Direction);
58 canvas->DrawImageInPath(image, 0, 0, path, paint);
59 }
60
61 // Returns the FontList to use for the title.
62 const gfx::FontList& GetTitleFontList() {
63 static const gfx::FontList* title_font_list =
64 new gfx::FontList(views::NativeWidgetAura::GetWindowTitleFontList());
65 ANNOTATE_LEAKING_OBJECT_PTR(title_font_list);
66 return *title_font_list;
67 }
68
69 } // namespace
70
71 namespace ash {
72
73 ///////////////////////////////////////////////////////////////////////////////
74 // DefaultHeaderPainter, public:
75
76 DefaultHeaderPainter::DefaultHeaderPainter()
77 : frame_(NULL),
78 view_(NULL),
79 window_icon_(NULL),
80 caption_button_container_(NULL),
81 height_(0),
82 mode_(MODE_INACTIVE),
83 initial_paint_(true),
84 activation_animation_(new gfx::SlideAnimation(this)) {
85 }
86
87 DefaultHeaderPainter::~DefaultHeaderPainter() {
88 }
89
90 void DefaultHeaderPainter::Init(
91 views::Widget* frame,
92 views::View* header_view,
93 views::View* window_icon,
94 FrameCaptionButtonContainerView* caption_button_container) {
95 DCHECK(frame);
96 DCHECK(header_view);
97 // window_icon may be NULL.
98 DCHECK(caption_button_container);
99 frame_ = frame;
100 view_ = header_view;
101 window_icon_ = window_icon;
102 caption_button_container_ = caption_button_container;
103
104 caption_button_container_->SetButtonImages(
105 CAPTION_BUTTON_ICON_MINIMIZE,
106 IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE,
107 IDR_AURA_WINDOW_CONTROL_ICON_MINIMIZE_I,
108 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
109 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
110 caption_button_container_->SetButtonImages(
111 CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
112 IDR_AURA_WINDOW_CONTROL_ICON_SIZE,
113 IDR_AURA_WINDOW_CONTROL_ICON_SIZE_I,
114 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
115 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
116 caption_button_container_->SetButtonImages(
117 CAPTION_BUTTON_ICON_CLOSE,
118 IDR_AURA_WINDOW_CONTROL_ICON_CLOSE,
119 IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I,
120 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
121 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
122
123 // There is no dedicated icon for the snap-left and snap-right buttons
124 // when |frame_| is inactive because they should never be visible while
125 // |frame_| is inactive.
126 caption_button_container_->SetButtonImages(
127 CAPTION_BUTTON_ICON_LEFT_SNAPPED,
128 IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED,
129 IDR_AURA_WINDOW_CONTROL_ICON_LEFT_SNAPPED,
130 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
131 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
132 caption_button_container_->SetButtonImages(
133 CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
134 IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED,
135 IDR_AURA_WINDOW_CONTROL_ICON_RIGHT_SNAPPED,
136 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
137 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
138 }
139
140 int DefaultHeaderPainter::GetMinimumHeaderWidth() const {
141 // Ensure we have enough space for the window icon and buttons. We allow
142 // the title string to collapse to zero width.
143 return GetTitleBounds().x() +
144 caption_button_container_->GetMinimumSize().width();
145 }
146
147 void DefaultHeaderPainter::PaintHeader(gfx::Canvas* canvas, Mode mode) {
148 Mode old_mode = mode_;
149 mode_ = mode;
150
151 if (mode_ != old_mode) {
152 if (!initial_paint_ && HeaderPainterUtil::CanAnimateActivation(frame_)) {
153 activation_animation_->SetSlideDuration(kActivationCrossfadeDurationMs);
154 if (mode_ == MODE_ACTIVE)
155 activation_animation_->Show();
156 else
157 activation_animation_->Hide();
158 } else {
159 if (mode_ == MODE_ACTIVE)
160 activation_animation_->Reset(1);
161 else
162 activation_animation_->Reset(0);
163 }
164 initial_paint_ = false;
165 }
166
167 int corner_radius = (frame_->IsMaximized() || frame_->IsFullscreen()) ?
168 0 : HeaderPainterUtil::GetTopCornerRadiusWhenRestored();
169
170 int active_alpha = activation_animation_->CurrentValueBetween(0, 255);
171 int inactive_alpha = 255 - active_alpha;
172
173 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
174 SkPaint paint;
175 if (inactive_alpha > 0) {
176 if (active_alpha > 0)
177 paint.setXfermodeMode(SkXfermode::kPlus_Mode);
178
179 paint.setAlpha(inactive_alpha);
180 gfx::ImageSkia inactive_frame =
181 *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_BASE_INACTIVE);
182 TileRoundRect(canvas, inactive_frame, paint, GetLocalBounds(),
183 corner_radius);
184 }
185
186 if (active_alpha > 0) {
187 paint.setAlpha(active_alpha);
188 gfx::ImageSkia active_frame =
189 *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_BASE_ACTIVE);
190 TileRoundRect(canvas, active_frame, paint, GetLocalBounds(),
191 corner_radius);
192 }
193
194 if (!frame_->IsMaximized() &&
195 !frame_->IsFullscreen() &&
196 mode_ == MODE_INACTIVE) {
197 PaintHighlightForInactiveRestoredWindow(canvas);
198 }
199 if (frame_->widget_delegate() &&
200 frame_->widget_delegate()->ShouldShowWindowTitle()) {
201 PaintTitleBar(canvas);
202 }
203 PaintHeaderContentSeparator(canvas);
204 }
205
206 void DefaultHeaderPainter::LayoutHeader() {
207 caption_button_container_->Layout();
208
209 gfx::Size caption_button_container_size =
210 caption_button_container_->GetPreferredSize();
211 caption_button_container_->SetBounds(
212 view_->width() - caption_button_container_size.width(),
213 0,
214 caption_button_container_size.width(),
215 caption_button_container_size.height());
216
217 if (window_icon_) {
218 // Vertically center the window icon with respect to the caption button
219 // container.
220 int icon_size = HeaderPainterUtil::GetIconSize();
221 int icon_offset_y = (caption_button_container_->height() - icon_size) / 2;
222 window_icon_->SetBounds(HeaderPainterUtil::GetIconXOffset(), icon_offset_y,
223 icon_size, icon_size);
224 }
225
226 SetHeaderHeightForPainting(caption_button_container_->height() +
227 kHeaderContentSeparatorSize);
228 }
229
230 int DefaultHeaderPainter::GetHeaderHeightForPainting() const {
231 return height_;
232 }
233
234 void DefaultHeaderPainter::SetHeaderHeightForPainting(int height) {
235 height_ = height;
236 }
237
238 void DefaultHeaderPainter::SchedulePaintForTitle() {
239 view_->SchedulePaintInRect(GetTitleBounds());
240 }
241
242 ///////////////////////////////////////////////////////////////////////////////
243 // gfx::AnimationDelegate overrides:
244
245 void DefaultHeaderPainter::AnimationProgressed(
246 const gfx::Animation* animation) {
247 view_->SchedulePaintInRect(GetLocalBounds());
248 }
249
250 ///////////////////////////////////////////////////////////////////////////////
251 // DefaultHeaderPainter, private:
252
253 void DefaultHeaderPainter::PaintHighlightForInactiveRestoredWindow(
254 gfx::Canvas* canvas) {
255 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
256 gfx::ImageSkia top_edge = *rb.GetImageSkiaNamed(
257 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_TOP);
258 gfx::ImageSkia left_edge = *rb.GetImageSkiaNamed(
259 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT);
260 gfx::ImageSkia right_edge = *rb.GetImageSkiaNamed(
261 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT);
262 gfx::ImageSkia bottom_edge = *rb.GetImageSkiaNamed(
263 IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM);
264
265 int left_edge_width = left_edge.width();
266 int right_edge_width = right_edge.width();
267 canvas->DrawImageInt(left_edge, 0, 0);
268 canvas->DrawImageInt(right_edge, view_->width() - right_edge_width, 0);
269 canvas->TileImageInt(
270 top_edge,
271 left_edge_width,
272 0,
273 view_->width() - left_edge_width - right_edge_width,
274 top_edge.height());
275
276 DCHECK_EQ(left_edge.height(), right_edge.height());
277 int bottom = left_edge.height();
278 int bottom_height = bottom_edge.height();
279 canvas->TileImageInt(
280 bottom_edge,
281 left_edge_width,
282 bottom - bottom_height,
283 view_->width() - left_edge_width - right_edge_width,
284 bottom_height);
285 }
286
287 void DefaultHeaderPainter::PaintTitleBar(gfx::Canvas* canvas) {
288 // The window icon is painted by its own views::View.
289 gfx::Rect title_bounds = GetTitleBounds();
290 title_bounds.set_x(view_->GetMirroredXForRect(title_bounds));
291 canvas->DrawStringRectWithFlags(frame_->widget_delegate()->GetWindowTitle(),
292 GetTitleFontList(),
293 kTitleTextColor,
294 title_bounds,
295 gfx::Canvas::NO_SUBPIXEL_RENDERING);
296 }
297
298 void DefaultHeaderPainter::PaintHeaderContentSeparator(gfx::Canvas* canvas) {
299 SkColor color = (mode_ == MODE_ACTIVE) ?
300 kHeaderContentSeparatorColor :
301 kHeaderContentSeparatorInactiveColor;
302
303 canvas->FillRect(gfx::Rect(0,
304 height_ - kHeaderContentSeparatorSize,
305 view_->width(),
306 kHeaderContentSeparatorSize),
307 color);
308 }
309
310 gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
311 return gfx::Rect(view_->width(), height_);
312 }
313
314 gfx::Rect DefaultHeaderPainter::GetTitleBounds() const {
315 return HeaderPainterUtil::GetTitleBounds(
316 window_icon_, caption_button_container_, GetTitleFontList());
317 }
318
319 } // namespace ash
OLDNEW
« no previous file with comments | « ash/frame/default_header_painter.h ('k') | ash/frame/default_header_painter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698