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