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

Side by Side Diff: ui/app_list/page_switcher.cc

Issue 11784034: Skeleton for app_list on OSX, and refactoring for enable_app_list=1 on OS=="mac". (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase for 175876 and 175961 Created 7 years, 11 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
« no previous file with comments | « ui/app_list/page_switcher.h ('k') | ui/app_list/pulsing_block_view.h » ('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 (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/app_list/page_switcher.h"
6
7 #include <algorithm>
8
9 #include "third_party/skia/include/core/SkPath.h"
10 #include "ui/app_list/pagination_model.h"
11 #include "ui/base/animation/throb_animation.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/skia_util.h"
14 #include "ui/views/controls/button/custom_button.h"
15 #include "ui/views/layout/box_layout.h"
16
17 namespace {
18
19 const int kPreferredHeight = 57;
20
21 const int kMaxButtonSpacing = 18;
22 const int kMinButtonSpacing = 4;
23 const int kMaxButtonWidth = 68;
24 const int kMinButtonWidth = 28;
25 const int kButtonHeight = 6;
26 const int kButtonCornerRadius = 2;
27 const int kButtonStripPadding = 20;
28
29 const SkColor kHoverColor = SkColorSetRGB(0xB4, 0xB4, 0xB4);
30
31 const SkColor kNormalColor = SkColorSetRGB(0xE2, 0xE2, 0xE2);
32
33 const SkColor kSelectedColor = SkColorSetRGB(0x46, 0x8F, 0xFC);
34
35 class PageSwitcherButton : public views::CustomButton {
36 public:
37 explicit PageSwitcherButton(views::ButtonListener* listener)
38 : views::CustomButton(listener),
39 button_width_(kMaxButtonWidth),
40 selected_range_(0) {
41 }
42 virtual ~PageSwitcherButton() {}
43
44 void SetSelectedRange(double selected_range) {
45 if (selected_range_ == selected_range)
46 return;
47
48 selected_range_ = selected_range;
49 SchedulePaint();
50 }
51
52 void set_button_width(int button_width) { button_width_ = button_width; }
53
54 // Overridden from views::View:
55 virtual gfx::Size GetPreferredSize() OVERRIDE {
56 return gfx::Size(button_width_, kButtonHeight);
57 }
58
59 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
60 if (state() == STATE_HOVERED) {
61 PaintButton(canvas, kHoverColor);
62 } else {
63 PaintButton(canvas, kNormalColor);
64 }
65 }
66
67 private:
68 // Paints a button that has two rounded corner at bottom.
69 void PaintButton(gfx::Canvas* canvas, SkColor base_color) {
70 gfx::Rect rect(GetContentsBounds());
71 rect.ClampToCenteredSize(gfx::Size(button_width_, kButtonHeight));
72
73 SkPath path;
74 path.addRoundRect(gfx::RectToSkRect(rect),
75 SkIntToScalar(kButtonCornerRadius),
76 SkIntToScalar(kButtonCornerRadius));
77
78 SkPaint paint;
79 paint.setAntiAlias(true);
80 paint.setStyle(SkPaint::kFill_Style);
81 paint.setColor(base_color);
82 canvas->DrawPath(path, paint);
83
84 int selected_start_x = 0;
85 int selected_width = 0;
86 if (selected_range_ > 0) {
87 selected_width = selected_range_ * rect.width();
88 } else if (selected_range_ < 0) {
89 selected_width = -selected_range_ * rect.width();
90 selected_start_x = rect.right() - selected_width;
91 }
92
93 if (selected_width) {
94 gfx::Rect selected_rect(rect);
95 selected_rect.set_x(selected_start_x);
96 selected_rect.set_width(selected_width);
97
98 SkPath selected_path;
99 selected_path.addRoundRect(gfx::RectToSkRect(selected_rect),
100 SkIntToScalar(kButtonCornerRadius),
101 SkIntToScalar(kButtonCornerRadius));
102 paint.setColor(kSelectedColor);
103 canvas->DrawPath(selected_path, paint);
104 }
105 }
106
107 int button_width_;
108
109 // [-1, 1] range that represents the portion of the button that should be
110 // painted with kSelectedColor. Positive range starts from left side and
111 // negative range starts from the right side.
112 double selected_range_;
113
114 DISALLOW_COPY_AND_ASSIGN(PageSwitcherButton);
115 };
116
117 // Gets PageSwitcherButton at |index| in |buttons|.
118 PageSwitcherButton* GetButtonByIndex(views::View* buttons, int index) {
119 return static_cast<PageSwitcherButton*>(buttons->child_at(index));
120 }
121
122 } // namespace
123
124 namespace app_list {
125
126 PageSwitcher::PageSwitcher(PaginationModel* model)
127 : model_(model),
128 buttons_(new views::View) {
129 AddChildView(buttons_);
130
131 TotalPagesChanged();
132 SelectedPageChanged(-1, model->selected_page());
133 model_->AddObserver(this);
134 }
135
136 PageSwitcher::~PageSwitcher() {
137 model_->RemoveObserver(this);
138 }
139
140 int PageSwitcher::GetPageForPoint(const gfx::Point& point) const {
141 if (!buttons_->bounds().Contains(point))
142 return -1;
143
144 gfx::Point buttons_point(point);
145 views::View::ConvertPointToTarget(this, buttons_, &buttons_point);
146
147 for (int i = 0; i < buttons_->child_count(); ++i) {
148 const views::View* button = buttons_->child_at(i);
149 if (button->bounds().Contains(buttons_point))
150 return i;
151 }
152
153 return -1;
154 }
155
156 void PageSwitcher::UpdateUIForDragPoint(const gfx::Point& point) {
157 int page = GetPageForPoint(point);
158
159 const int button_count = buttons_->child_count();
160 if (page >= 0 && page < button_count) {
161 PageSwitcherButton* button =
162 static_cast<PageSwitcherButton*>(buttons_->child_at(page));
163 button->SetState(views::CustomButton::STATE_HOVERED);
164 return;
165 }
166
167 for (int i = 0; i < button_count; ++i) {
168 PageSwitcherButton* button =
169 static_cast<PageSwitcherButton*>(buttons_->child_at(i));
170 button->SetState(views::CustomButton::STATE_NORMAL);
171 }
172 }
173
174 gfx::Size PageSwitcher::GetPreferredSize() {
175 // Always return a size with correct height so that container resize is not
176 // needed when more pages are added.
177 return gfx::Size(buttons_->GetPreferredSize().width(),
178 kPreferredHeight);
179 }
180
181 void PageSwitcher::Layout() {
182 gfx::Rect rect(GetContentsBounds());
183
184 CalculateButtonWidthAndSpacing(rect.width());
185
186 // Makes |buttons_| horizontally center and vertically fill.
187 gfx::Size buttons_size(buttons_->GetPreferredSize());
188 gfx::Rect buttons_bounds(rect.CenterPoint().x() - buttons_size.width() / 2,
189 rect.y(),
190 buttons_size.width(),
191 rect.height());
192 buttons_->SetBoundsRect(gfx::IntersectRects(rect, buttons_bounds));
193 }
194
195 void PageSwitcher::CalculateButtonWidthAndSpacing(int contents_width) {
196 const int button_count = buttons_->child_count();
197 if (!button_count)
198 return;
199
200 contents_width -= 2 * kButtonStripPadding;
201
202 int button_width = kMinButtonWidth;
203 int button_spacing = kMinButtonSpacing;
204 if (button_count > 1) {
205 button_spacing = (contents_width - button_width * button_count) /
206 (button_count - 1);
207 button_spacing = std::min(kMaxButtonSpacing,
208 std::max(kMinButtonSpacing, button_spacing));
209 }
210
211 button_width = (contents_width - (button_count - 1) * button_spacing) /
212 button_count;
213 button_width = std::min(kMaxButtonWidth,
214 std::max(kMinButtonWidth, button_width));
215
216 buttons_->SetLayoutManager(new views::BoxLayout(
217 views::BoxLayout::kHorizontal, kButtonStripPadding, 0, button_spacing));
218 for (int i = 0; i < button_count; ++i) {
219 PageSwitcherButton* button =
220 static_cast<PageSwitcherButton*>(buttons_->child_at(i));
221 button->set_button_width(button_width);
222 }
223 }
224
225 void PageSwitcher::ButtonPressed(views::Button* sender,
226 const ui::Event& event) {
227 for (int i = 0; i < buttons_->child_count(); ++i) {
228 if (sender == static_cast<views::Button*>(buttons_->child_at(i))) {
229 model_->SelectPage(i, true /* animate */);
230 break;
231 }
232 }
233 }
234
235 void PageSwitcher::TotalPagesChanged() {
236 buttons_->RemoveAllChildViews(true);
237 for (int i = 0; i < model_->total_pages(); ++i) {
238 PageSwitcherButton* button = new PageSwitcherButton(this);
239 button->SetSelectedRange(i == model_->selected_page() ? 1 : 0);
240 buttons_->AddChildView(button);
241 }
242 buttons_->SetVisible(model_->total_pages() > 1);
243 Layout();
244 }
245
246 void PageSwitcher::SelectedPageChanged(int old_selected, int new_selected) {
247 if (old_selected >= 0 && old_selected < buttons_->child_count())
248 GetButtonByIndex(buttons_, old_selected)->SetSelectedRange(0);
249 if (new_selected >= 0 && new_selected < buttons_->child_count())
250 GetButtonByIndex(buttons_, new_selected)->SetSelectedRange(1);
251 }
252
253 void PageSwitcher::TransitionChanged() {
254 const int current_page = model_->selected_page();
255 const int target_page = model_->transition().target_page;
256
257 double progress = model_->transition().progress;
258 double remaining = progress - 1;
259
260 if (current_page > target_page) {
261 remaining = -remaining;
262 progress = -progress;
263 }
264
265 GetButtonByIndex(buttons_, current_page)->SetSelectedRange(remaining);
266 if (model_->is_valid_page(target_page))
267 GetButtonByIndex(buttons_, target_page)->SetSelectedRange(progress);
268 }
269
270 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/page_switcher.h ('k') | ui/app_list/pulsing_block_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698