| OLD | NEW |
| (Empty) |
| 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 "ash/app_list/app_list_bubble_border.h" | |
| 6 | |
| 7 #include "third_party/skia/include/core/SkPath.h" | |
| 8 #include "third_party/skia/include/core/SkPaint.h" | |
| 9 #include "third_party/skia/include/effects/SkBlurDrawLooper.h" | |
| 10 #include "third_party/skia/include/effects/SkGradientShader.h" | |
| 11 #include "ui/gfx/canvas.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 const int kCornerRadius = 3; | |
| 16 | |
| 17 const int kArrowHeight = 10; | |
| 18 const int kArrowWidth = 20; | |
| 19 | |
| 20 const SkColor kBorderColor = SkColorSetARGB(0xFF, 0, 0, 0); | |
| 21 const int kBorderSize = 1; | |
| 22 | |
| 23 const SkColor kShadowColor = SkColorSetARGB(0xFF, 0, 0, 0); | |
| 24 const int kShadowRadius = 4; | |
| 25 | |
| 26 const SkColor kModelViewGradientColor1 = SkColorSetARGB(0xFF, 0xFE, 0xFE, 0xFE); | |
| 27 const SkColor kModelViewGradientColor2 = SkColorSetARGB(0xFF, 0xF8, 0xF8, 0xF8); | |
| 28 const int kModelViewGradientSize = 10; | |
| 29 | |
| 30 const SkColor kFooterBorderGradientColor1 = | |
| 31 SkColorSetARGB(0xFF, 0xA0, 0xA0, 0xA0); | |
| 32 const SkColor kFooterBorderGradientColor2 = | |
| 33 SkColorSetARGB(0xFF, 0xD4, 0xD4, 0xD4); | |
| 34 const int kFooterBorderSize = 3; | |
| 35 const SkColor kFooterBackground = SkColorSetARGB(0xFF, 0xDC, 0xDC, 0xDC); | |
| 36 | |
| 37 // TODO(xiyuan): Merge this with the one in skia_util. | |
| 38 SkShader* CreateVerticalGradientShader(int start_point, | |
| 39 int end_point, | |
| 40 SkColor start_color, | |
| 41 SkColor end_color, | |
| 42 SkShader::TileMode mode) { | |
| 43 SkColor grad_colors[2] = { start_color, end_color}; | |
| 44 SkPoint grad_points[2]; | |
| 45 grad_points[0].iset(0, start_point); | |
| 46 grad_points[1].iset(0, end_point); | |
| 47 | |
| 48 return SkGradientShader::CreateLinear(grad_points, | |
| 49 grad_colors, | |
| 50 NULL, | |
| 51 2, | |
| 52 mode); | |
| 53 } | |
| 54 | |
| 55 // Builds a bubble shape for given |bounds|. | |
| 56 void BuildShape(const gfx::Rect& bounds, | |
| 57 SkScalar padding, | |
| 58 SkScalar arrow_offset, | |
| 59 SkPath* path) { | |
| 60 const SkScalar left = SkIntToScalar(bounds.x()) + padding; | |
| 61 const SkScalar top = SkIntToScalar(bounds.y()) + padding; | |
| 62 const SkScalar right = SkIntToScalar(bounds.right()) - padding; | |
| 63 const SkScalar bottom = SkIntToScalar(bounds.bottom()) - padding; | |
| 64 | |
| 65 const SkScalar center_x = SkIntToScalar((bounds.x() + bounds.right()) / 2); | |
| 66 const SkScalar center_y = SkIntToScalar((bounds.y() + bounds.bottom()) / 2); | |
| 67 | |
| 68 const SkScalar half_array_width = SkIntToScalar(kArrowWidth / 2); | |
| 69 const SkScalar arrow_height = SkIntToScalar(kArrowHeight) - padding; | |
| 70 | |
| 71 path->reset(); | |
| 72 path->incReserve(12); | |
| 73 | |
| 74 path->moveTo(center_x, top); | |
| 75 path->arcTo(left, top, left, center_y, SkIntToScalar(kCornerRadius)); | |
| 76 path->arcTo(left, bottom, center_x - half_array_width, bottom, | |
| 77 SkIntToScalar(kCornerRadius)); | |
| 78 path->lineTo(center_x + arrow_offset - half_array_width, bottom); | |
| 79 path->lineTo(center_x + arrow_offset, bottom + arrow_height); | |
| 80 path->lineTo(center_x + arrow_offset + half_array_width, bottom); | |
| 81 path->arcTo(right, bottom, right, center_y, SkIntToScalar(kCornerRadius)); | |
| 82 path->arcTo(right, top, center_x, top, SkIntToScalar(kCornerRadius)); | |
| 83 path->close(); | |
| 84 } | |
| 85 | |
| 86 } // namespace | |
| 87 | |
| 88 namespace ash { | |
| 89 | |
| 90 AppListBubbleBorder::AppListBubbleBorder(views::View* app_list_view) | |
| 91 : views::BubbleBorder(views::BubbleBorder::BOTTOM_RIGHT, | |
| 92 views::BubbleBorder::NO_SHADOW), | |
| 93 app_list_view_(app_list_view), | |
| 94 arrow_offset_(0) { | |
| 95 } | |
| 96 | |
| 97 AppListBubbleBorder::~AppListBubbleBorder() { | |
| 98 } | |
| 99 | |
| 100 void AppListBubbleBorder::PaintModelViewBackground( | |
| 101 gfx::Canvas* canvas, | |
| 102 const gfx::Rect& bounds) const { | |
| 103 const views::View* page_switcher = app_list_view_->child_at(1); | |
| 104 const gfx::Rect page_switcher_bounds = | |
| 105 app_list_view_->ConvertRectToWidget(page_switcher->bounds()); | |
| 106 gfx::Rect rect(bounds.x(), | |
| 107 bounds.y(), | |
| 108 bounds.width(), | |
| 109 page_switcher_bounds.y() - bounds.y()); | |
| 110 | |
| 111 SkPaint paint; | |
| 112 paint.setStyle(SkPaint::kFill_Style); | |
| 113 SkSafeUnref(paint.setShader(CreateVerticalGradientShader( | |
| 114 rect.y(), | |
| 115 rect.y() + kModelViewGradientSize, | |
| 116 kModelViewGradientColor1, | |
| 117 kModelViewGradientColor2, | |
| 118 SkShader::kClamp_TileMode))); | |
| 119 canvas->DrawRect(rect, paint); | |
| 120 } | |
| 121 | |
| 122 void AppListBubbleBorder::PaintPageSwitcherBackground( | |
| 123 gfx::Canvas* canvas, | |
| 124 const gfx::Rect& bounds) const { | |
| 125 const views::View* page_switcher = app_list_view_->child_at(1); | |
| 126 const gfx::Rect page_switcher_bounds = | |
| 127 app_list_view_->ConvertRectToWidget(page_switcher->bounds()); | |
| 128 | |
| 129 gfx::Rect rect(bounds.x(), | |
| 130 page_switcher_bounds.y(), | |
| 131 bounds.width(), | |
| 132 kFooterBorderSize); | |
| 133 SkPaint paint; | |
| 134 paint.setStyle(SkPaint::kFill_Style); | |
| 135 SkSafeUnref(paint.setShader(CreateVerticalGradientShader( | |
| 136 rect.y(), | |
| 137 rect.bottom(), | |
| 138 kFooterBorderGradientColor1, | |
| 139 kFooterBorderGradientColor2, | |
| 140 SkShader::kClamp_TileMode))); | |
| 141 canvas->DrawRect(rect, paint); | |
| 142 | |
| 143 rect.set_y(rect.bottom()); | |
| 144 rect.set_height(bounds.bottom() - rect.y() + kArrowHeight - kBorderSize); | |
| 145 canvas->FillRect(rect, kFooterBackground); | |
| 146 } | |
| 147 | |
| 148 void AppListBubbleBorder::GetInsets(gfx::Insets* insets) const { | |
| 149 insets->Set(kShadowRadius + kBorderSize, | |
| 150 kShadowRadius + kBorderSize, | |
| 151 kShadowRadius + kBorderSize + kArrowHeight, | |
| 152 kShadowRadius + kBorderSize); | |
| 153 } | |
| 154 | |
| 155 gfx::Rect AppListBubbleBorder::GetBounds( | |
| 156 const gfx::Rect& position_relative_to, | |
| 157 const gfx::Size& contents_size) const { | |
| 158 gfx::Size border_size(contents_size); | |
| 159 gfx::Insets insets; | |
| 160 GetInsets(&insets); | |
| 161 border_size.Enlarge(insets.width(), insets.height()); | |
| 162 | |
| 163 int anchor_x = (position_relative_to.x() + position_relative_to.right()) / 2; | |
| 164 int arrow_tip_x = border_size.width() / 2 + arrow_offset_; | |
| 165 | |
| 166 return gfx::Rect( | |
| 167 gfx::Point(anchor_x - arrow_tip_x, | |
| 168 position_relative_to.y() - border_size.height() + | |
| 169 kShadowRadius), | |
| 170 border_size); | |
| 171 } | |
| 172 | |
| 173 void AppListBubbleBorder::Paint(const views::View& view, | |
| 174 gfx::Canvas* canvas) const { | |
| 175 gfx::Insets insets; | |
| 176 GetInsets(&insets); | |
| 177 | |
| 178 gfx::Rect bounds = view.bounds(); | |
| 179 bounds.Inset(insets); | |
| 180 | |
| 181 SkPath path; | |
| 182 | |
| 183 SkPaint paint; | |
| 184 paint.setAntiAlias(true); | |
| 185 paint.setStyle(SkPaint::kStroke_Style); | |
| 186 paint.setColor(kBorderColor); | |
| 187 SkSafeUnref(paint.setLooper( | |
| 188 new SkBlurDrawLooper(kShadowRadius, | |
| 189 0, 0, | |
| 190 kShadowColor, | |
| 191 SkBlurDrawLooper::kHighQuality_BlurFlag))); | |
| 192 // Pads with 0.5 pixel since anti alias is used. | |
| 193 BuildShape(bounds, | |
| 194 SkDoubleToScalar(0.5), | |
| 195 SkIntToScalar(arrow_offset_), | |
| 196 &path); | |
| 197 canvas->DrawPath(path, paint); | |
| 198 | |
| 199 // Pads with kBoprderSize pixels to leave space for border lines. | |
| 200 BuildShape(bounds, | |
| 201 SkIntToScalar(kBorderSize), | |
| 202 SkIntToScalar(arrow_offset_), | |
| 203 &path); | |
| 204 canvas->Save(); | |
| 205 canvas->ClipPath(path); | |
| 206 | |
| 207 PaintModelViewBackground(canvas, bounds); | |
| 208 PaintPageSwitcherBackground(canvas, bounds); | |
| 209 | |
| 210 canvas->Restore(); | |
| 211 } | |
| 212 | |
| 213 } // namespace ash | |
| OLD | NEW |