1 // Copyright (c) 2012 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 "ui/views/window/frame_background.h"
6
7 #include "grit/ui_resources.h"
8 #include "third_party/skia/include/core/SkCanvas.h"
9 #include "third_party/skia/include/core/SkColor.h"
10 #include "ui/base/theme_provider.h"
11 #include "ui/gfx/canvas.h"
12 #include "ui/views/view.h"
13
14 namespace views {
15
FrameBackground()16 FrameBackground::FrameBackground()
17 : frame_color_(0),
18 theme_image_(NULL),
19 theme_overlay_image_(NULL),
20 top_area_height_(0),
21 left_edge_(NULL),
22 top_edge_(NULL),
23 right_edge_(NULL),
24 bottom_edge_(NULL),
25 top_left_corner_(NULL),
26 top_right_corner_(NULL),
27 bottom_left_corner_(NULL),
28 bottom_right_corner_(NULL),
29 maximized_top_left_(NULL),
30 maximized_top_right_(NULL),
31 maximized_top_offset_(0),
32 theme_background_y_(0) {
33 }
34
~FrameBackground()35 FrameBackground::~FrameBackground() {
36 }
37
SetSideImages(const gfx::ImageSkia * left,const gfx::ImageSkia * top,const gfx::ImageSkia * right,const gfx::ImageSkia * bottom)38 void FrameBackground::SetSideImages(const gfx::ImageSkia* left,
39 const gfx::ImageSkia* top,
40 const gfx::ImageSkia* right,
41 const gfx::ImageSkia* bottom) {
42 left_edge_ = left;
43 top_edge_ = top;
44 right_edge_ = right;
45 bottom_edge_ = bottom;
46 }
47
SetCornerImages(const gfx::ImageSkia * top_left,const gfx::ImageSkia * top_right,const gfx::ImageSkia * bottom_left,const gfx::ImageSkia * bottom_right)48 void FrameBackground::SetCornerImages(const gfx::ImageSkia* top_left,
49 const gfx::ImageSkia* top_right,
50 const gfx::ImageSkia* bottom_left,
51 const gfx::ImageSkia* bottom_right) {
52 top_left_corner_ = top_left;
53 top_right_corner_ = top_right;
54 bottom_left_corner_ = bottom_left;
55 bottom_right_corner_ = bottom_right;
56 }
57
PaintRestored(gfx::Canvas * canvas,View * view) const58 void FrameBackground::PaintRestored(gfx::Canvas* canvas, View* view) const {
59 // Fill with the frame color first so we have a constant background for
60 // areas not covered by the theme image.
61 PaintFrameColor(canvas, view);
62
63 // Draw the theme frame.
64 canvas->TileImageInt(*theme_image_,
65 0, 0, view->width(), theme_image_->height());
66
67 // Draw the theme frame overlay, if available.
68 if (theme_overlay_image_)
69 canvas->DrawImageInt(*theme_overlay_image_, 0, 0);
70
71 // Draw the top corners and edge, scaling the corner images down if they
72 // are too big and relative to the vertical space available.
73 int top_left_height =
74 std::min(top_left_corner_->height(),
75 view->height() - bottom_left_corner_->height());
76 canvas->DrawImageInt(*top_left_corner_,
77 0, 0, top_left_corner_->width(), top_left_height,
78 0, 0, top_left_corner_->width(), top_left_height,
79 false);
80 canvas->TileImageInt(*top_edge_,
81 top_left_corner_->width(),
82 0,
83 view->width() - top_left_corner_->width() - top_right_corner_->width(),
84 top_edge_->height());
85 int top_right_height =
86 std::min(top_right_corner_->height(),
87 view->height() - bottom_right_corner_->height());
88 canvas->DrawImageInt(*top_right_corner_,
89 0, 0,
90 top_right_corner_->width(), top_right_height,
91 view->width() - top_right_corner_->width(), 0,
92 top_right_corner_->width(), top_right_height,
93 false);
94
95 // Right edge.
96 int right_edge_height =
97 view->height() - top_right_height - bottom_right_corner_->height();
98 canvas->TileImageInt(*right_edge_,
99 view->width() - right_edge_->width(),
100 top_right_height,
101 right_edge_->width(),
102 right_edge_height);
103
104 // Bottom corners and edge.
105 canvas->DrawImageInt(*bottom_right_corner_,
106 view->width() - bottom_right_corner_->width(),
107 view->height() - bottom_right_corner_->height());
108 canvas->TileImageInt(
109 *bottom_edge_,
110 bottom_left_corner_->width(),
111 view->height() - bottom_edge_->height(),
112 view->width() - bottom_left_corner_->width()
113 - bottom_right_corner_->width(),
114 bottom_edge_->height());
115 canvas->DrawImageInt(*bottom_left_corner_, 0,
116 view->height() - bottom_left_corner_->height());
117
118 // Left edge.
119 int left_edge_height =
120 view->height() - top_left_height - bottom_left_corner_->height();
121 canvas->TileImageInt(*left_edge_,
122 0, top_left_height,
123 left_edge_->width(), left_edge_height);
124 }
125
PaintMaximized(gfx::Canvas * canvas,View * view) const126 void FrameBackground::PaintMaximized(gfx::Canvas* canvas, View* view) const {
127 // We will be painting from top_offset to top_offset + theme_frame_height. If
128 // this is less than top_area_height_, we need to paint the frame color
129 // to fill in the area beneath the image.
130 // TODO(jamescook): I'm not sure this is correct, as it doesn't seem to fully
131 // account for the top_offset, but this is how it worked before.
132 int theme_frame_bottom = maximized_top_offset_ + theme_image_->height();
133 if (top_area_height_ > theme_frame_bottom) {
134 canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_),
135 frame_color_);
136 }
137
138 int left_offset = 0;
139 int right_offset = 0;
140
141 // Draw top-left and top-right corners to give maximized ChromeOS windows
142 // a rounded appearance.
143 if (maximized_top_left_ || maximized_top_right_) {
144 // If we have either a left or right we should have both.
145 DCHECK(maximized_top_left_ && maximized_top_right_);
146 left_offset = maximized_top_left_->width();
147 right_offset = maximized_top_right_->width();
148 canvas->DrawImageInt(*maximized_top_left_, 0, 0);
149 canvas->DrawImageInt(*maximized_top_right_,
150 view->width() - right_offset, 0);
151 }
152
153 // Draw the theme frame.
154 canvas->TileImageInt(*theme_image_,
155 left_offset,
156 maximized_top_offset_,
157 view->width() - (left_offset + right_offset),
158 theme_image_->height());
159 // Draw the theme frame overlay, if available.
160 if (theme_overlay_image_)
161 canvas->DrawImageInt(*theme_overlay_image_, 0, theme_background_y_);
162 }
163
PaintFrameColor(gfx::Canvas * canvas,View * view) const164 void FrameBackground::PaintFrameColor(gfx::Canvas* canvas, View* view) const {
165 // Fill the top area.
166 canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_),
167 frame_color_);
168
169 // If the window is very short, we're done.
170 int remaining_height = view->height() - top_area_height_;
171 if (remaining_height <= 0)
172 return;
173
174 // Fill down the sides.
175 canvas->FillRect(gfx::Rect(0, top_area_height_, left_edge_->width(),
176 remaining_height), frame_color_);
177 canvas->FillRect(gfx::Rect(view->width() - right_edge_->width(),
178 top_area_height_, right_edge_->width(),
179 remaining_height), frame_color_);
180
181 // If the window is very narrow, we're done.
182 int center_width =
183 view->width() - left_edge_->width() - right_edge_->width();
184 if (center_width <= 0)
185 return;
186
187 // Fill the bottom area.
188 canvas->FillRect(gfx::Rect(left_edge_->width(),
189 view->height() - bottom_edge_->height(),
190 center_width, bottom_edge_->height()),
191 frame_color_);
192 }
193
194 } // namespace views
195