OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/app_list/views/apps_grid_view.h" | 5 #include "ui/app_list/views/apps_grid_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 const int kTopPadding = 1; | 64 const int kTopPadding = 1; |
65 const int kBottomPadding = 24; | 65 const int kBottomPadding = 24; |
66 | 66 |
67 // Padding space in pixels between pages. | 67 // Padding space in pixels between pages. |
68 const int kPagePadding = 40; | 68 const int kPagePadding = 40; |
69 | 69 |
70 // Preferred tile size when showing in fixed layout. | 70 // Preferred tile size when showing in fixed layout. |
71 const int kPreferredTileWidth = 88; | 71 const int kPreferredTileWidth = 88; |
72 const int kPreferredTileHeight = 98; | 72 const int kPreferredTileHeight = 98; |
73 | 73 |
| 74 const int kExperimentalPreferredTileWidth = 90; |
| 75 const int kExperimentalPrefferedTileHeight = 90; |
| 76 |
| 77 // Padding on each side of a tile. |
| 78 const int kExperimentalTileLeftRightPadding = 15; |
| 79 const int kExperimentalTileTopBottomPadding = 11; |
| 80 |
74 // Width in pixels of the area on the sides that triggers a page flip. | 81 // Width in pixels of the area on the sides that triggers a page flip. |
75 const int kPageFlipZoneSize = 40; | 82 const int kPageFlipZoneSize = 40; |
76 | 83 |
77 // Delay in milliseconds to do the page flip. | 84 // Delay in milliseconds to do the page flip. |
78 const int kPageFlipDelayInMs = 1000; | 85 const int kPageFlipDelayInMs = 1000; |
79 | 86 |
80 // How many pages on either side of the selected one we prerender. | 87 // How many pages on either side of the selected one we prerender. |
81 const int kPrerenderPages = 1; | 88 const int kPrerenderPages = 1; |
82 | 89 |
83 // The drag and drop proxy should get scaled by this factor. | 90 // The drag and drop proxy should get scaled by this factor. |
84 const float kDragAndDropProxyScale = 1.5f; | 91 const float kDragAndDropProxyScale = 1.5f; |
85 | 92 |
86 // Delays in milliseconds to show folder dropping preview circle. | 93 // Delays in milliseconds to show folder dropping preview circle. |
87 const int kFolderDroppingDelay = 150; | 94 const int kFolderDroppingDelay = 150; |
88 | 95 |
89 // Delays in milliseconds to show re-order preview. | 96 // Delays in milliseconds to show re-order preview. |
90 const int kReorderDelay = 120; | 97 const int kReorderDelay = 120; |
91 | 98 |
92 // Delays in milliseconds to show folder item reparent UI. | 99 // Delays in milliseconds to show folder item reparent UI. |
93 const int kFolderItemReparentDelay = 50; | 100 const int kFolderItemReparentDelay = 50; |
94 | 101 |
95 // Radius of the circle, in which if entered, show folder dropping preview | 102 // Radius of the circle, in which if entered, show folder dropping preview |
96 // UI. | 103 // UI. |
97 const int kFolderDroppingCircleRadius = 39; | 104 const int kFolderDroppingCircleRadius = 39; |
98 | 105 |
| 106 // Returns the size of a tile view excluding its padding. |
| 107 gfx::Size GetTileViewSize() { |
| 108 return switches::IsExperimentalAppListEnabled() |
| 109 ? gfx::Size(kExperimentalPreferredTileWidth, |
| 110 kExperimentalPrefferedTileHeight) |
| 111 : gfx::Size(kPreferredTileWidth, kPreferredTileHeight); |
| 112 } |
| 113 |
| 114 // Returns the size of a tile view inccluding its padding. |
| 115 gfx::Size GetTotalTileSize() { |
| 116 gfx::Size size = GetTileViewSize(); |
| 117 if (switches::IsExperimentalAppListEnabled()) |
| 118 size.Enlarge(2 * kExperimentalTileLeftRightPadding, |
| 119 2 * kExperimentalTileTopBottomPadding); |
| 120 return size; |
| 121 } |
| 122 |
99 // RowMoveAnimationDelegate is used when moving an item into a different row. | 123 // RowMoveAnimationDelegate is used when moving an item into a different row. |
100 // Before running the animation, the item's layer is re-created and kept in | 124 // Before running the animation, the item's layer is re-created and kept in |
101 // the original position, then the item is moved to just before its target | 125 // the original position, then the item is moved to just before its target |
102 // position and opacity set to 0. When the animation runs, this delegate moves | 126 // position and opacity set to 0. When the animation runs, this delegate moves |
103 // the layer and fades it out while fading in the item at the same time. | 127 // the layer and fades it out while fading in the item at the same time. |
104 class RowMoveAnimationDelegate : public gfx::AnimationDelegate { | 128 class RowMoveAnimationDelegate : public gfx::AnimationDelegate { |
105 public: | 129 public: |
106 RowMoveAnimationDelegate(views::View* view, | 130 RowMoveAnimationDelegate(views::View* view, |
107 ui::Layer* layer, | 131 ui::Layer* layer, |
108 const gfx::Rect& layer_target) | 132 const gfx::Rect& layer_target) |
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 if (pulsing_blocks_model_.view_size() == desired) | 1057 if (pulsing_blocks_model_.view_size() == desired) |
1034 return; | 1058 return; |
1035 | 1059 |
1036 while (pulsing_blocks_model_.view_size() > desired) { | 1060 while (pulsing_blocks_model_.view_size() > desired) { |
1037 views::View* view = pulsing_blocks_model_.view_at(0); | 1061 views::View* view = pulsing_blocks_model_.view_at(0); |
1038 pulsing_blocks_model_.Remove(0); | 1062 pulsing_blocks_model_.Remove(0); |
1039 delete view; | 1063 delete view; |
1040 } | 1064 } |
1041 | 1065 |
1042 while (pulsing_blocks_model_.view_size() < desired) { | 1066 while (pulsing_blocks_model_.view_size() < desired) { |
1043 views::View* view = new PulsingBlockView( | 1067 views::View* view = new PulsingBlockView(GetTotalTileSize(), true); |
1044 gfx::Size(kPreferredTileWidth, kPreferredTileHeight), true); | |
1045 pulsing_blocks_model_.Add(view, 0); | 1068 pulsing_blocks_model_.Add(view, 0); |
1046 AddChildView(view); | 1069 AddChildView(view); |
1047 } | 1070 } |
1048 } | 1071 } |
1049 | 1072 |
1050 views::View* AppsGridView::CreateViewForItemAtIndex(size_t index) { | 1073 views::View* AppsGridView::CreateViewForItemAtIndex(size_t index) { |
1051 // The drag_view_ might be pending for deletion, therefore view_model_ | 1074 // The drag_view_ might be pending for deletion, therefore view_model_ |
1052 // may have one more item than item_list_. | 1075 // may have one more item than item_list_. |
1053 DCHECK_LE(index, item_list_->item_count()); | 1076 DCHECK_LE(index, item_list_->item_count()); |
1054 AppListItemView* view = new AppListItemView(this, | 1077 AppListItemView* view = new AppListItemView(this, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 const gfx::Rect& target = view_model_.ideal_bounds(i); | 1269 const gfx::Rect& target = view_model_.ideal_bounds(i); |
1247 if (bounds_animator_.GetTargetBounds(view) == target) | 1270 if (bounds_animator_.GetTargetBounds(view) == target) |
1248 continue; | 1271 continue; |
1249 | 1272 |
1250 const gfx::Rect& current = view->bounds(); | 1273 const gfx::Rect& current = view->bounds(); |
1251 const bool current_visible = visible_bounds.Intersects(current); | 1274 const bool current_visible = visible_bounds.Intersects(current); |
1252 const bool target_visible = visible_bounds.Intersects(target); | 1275 const bool target_visible = visible_bounds.Intersects(target); |
1253 const bool visible = current_visible || target_visible; | 1276 const bool visible = current_visible || target_visible; |
1254 | 1277 |
1255 const int y_diff = target.y() - current.y(); | 1278 const int y_diff = target.y() - current.y(); |
1256 if (visible && y_diff && y_diff % kPreferredTileHeight == 0) { | 1279 if (visible && y_diff && y_diff % GetTotalTileSize().height() == 0) { |
1257 AnimationBetweenRows(view, | 1280 AnimationBetweenRows(view, |
1258 current_visible, | 1281 current_visible, |
1259 current, | 1282 current, |
1260 target_visible, | 1283 target_visible, |
1261 target); | 1284 target); |
1262 } else if (visible || bounds_animator_.IsAnimating(view)) { | 1285 } else if (visible || bounds_animator_.IsAnimating(view)) { |
1263 bounds_animator_.AnimateViewTo(view, target); | 1286 bounds_animator_.AnimateViewTo(view, target); |
1264 bounds_animator_.SetAnimationDelegate( | 1287 bounds_animator_.SetAnimationDelegate( |
1265 view, | 1288 view, |
1266 scoped_ptr<gfx::AnimationDelegate>( | 1289 scoped_ptr<gfx::AnimationDelegate>( |
(...skipping 21 matching lines...) Expand all Loading... |
1288 | 1311 |
1289 scoped_ptr<ui::Layer> layer; | 1312 scoped_ptr<ui::Layer> layer; |
1290 if (animate_current) { | 1313 if (animate_current) { |
1291 layer = view->RecreateLayer(); | 1314 layer = view->RecreateLayer(); |
1292 layer->SuppressPaint(); | 1315 layer->SuppressPaint(); |
1293 | 1316 |
1294 view->SetFillsBoundsOpaquely(false); | 1317 view->SetFillsBoundsOpaquely(false); |
1295 view->layer()->SetOpacity(0.f); | 1318 view->layer()->SetOpacity(0.f); |
1296 } | 1319 } |
1297 | 1320 |
| 1321 gfx::Size total_tile_size = GetTotalTileSize(); |
1298 gfx::Rect current_out(current); | 1322 gfx::Rect current_out(current); |
1299 current_out.Offset(dir * kPreferredTileWidth, 0); | 1323 current_out.Offset(dir * total_tile_size.width(), 0); |
1300 | 1324 |
1301 gfx::Rect target_in(target); | 1325 gfx::Rect target_in(target); |
1302 if (animate_target) | 1326 if (animate_target) |
1303 target_in.Offset(-dir * kPreferredTileWidth, 0); | 1327 target_in.Offset(-dir * total_tile_size.width(), 0); |
1304 view->SetBoundsRect(target_in); | 1328 view->SetBoundsRect(target_in); |
1305 bounds_animator_.AnimateViewTo(view, target); | 1329 bounds_animator_.AnimateViewTo(view, target); |
1306 | 1330 |
1307 bounds_animator_.SetAnimationDelegate( | 1331 bounds_animator_.SetAnimationDelegate( |
1308 view, | 1332 view, |
1309 scoped_ptr<gfx::AnimationDelegate>( | 1333 scoped_ptr<gfx::AnimationDelegate>( |
1310 new RowMoveAnimationDelegate(view, layer.release(), current_out))); | 1334 new RowMoveAnimationDelegate(view, layer.release(), current_out))); |
1311 } | 1335 } |
1312 | 1336 |
1313 void AppsGridView::ExtractDragLocation(const ui::LocatedEvent& event, | 1337 void AppsGridView::ExtractDragLocation(const ui::LocatedEvent& event, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 gfx::Point reorder_placeholder_center = | 1412 gfx::Point reorder_placeholder_center = |
1389 GetExpectedTileBounds(reorder_placeholder_.slot).CenterPoint(); | 1413 GetExpectedTileBounds(reorder_placeholder_.slot).CenterPoint(); |
1390 | 1414 |
1391 int x_offset_direction = 0; | 1415 int x_offset_direction = 0; |
1392 if (grid_index == reorder_placeholder_) { | 1416 if (grid_index == reorder_placeholder_) { |
1393 x_offset_direction = reorder_placeholder_center.x() < point.x() ? -1 : 1; | 1417 x_offset_direction = reorder_placeholder_center.x() < point.x() ? -1 : 1; |
1394 } else { | 1418 } else { |
1395 x_offset_direction = reorder_placeholder_ < grid_index ? -1 : 1; | 1419 x_offset_direction = reorder_placeholder_ < grid_index ? -1 : 1; |
1396 } | 1420 } |
1397 | 1421 |
| 1422 gfx::Size total_tile_size = GetTotalTileSize(); |
1398 int row = grid_index.slot / cols_; | 1423 int row = grid_index.slot / cols_; |
1399 | 1424 |
1400 // Offset the target column based on the direction of the target. This will | 1425 // Offset the target column based on the direction of the target. This will |
1401 // result in earlier targets getting their reorder zone shifted backwards | 1426 // result in earlier targets getting their reorder zone shifted backwards |
1402 // and later targets getting their reorder zones shifted forwards. | 1427 // and later targets getting their reorder zones shifted forwards. |
1403 // | 1428 // |
1404 // This makes eordering feel like the user is slotting items into the spaces | 1429 // This makes eordering feel like the user is slotting items into the spaces |
1405 // between apps. | 1430 // between apps. |
1406 int x_offset = x_offset_direction * | 1431 int x_offset = x_offset_direction * |
1407 (kPreferredTileWidth - kFolderDroppingCircleRadius) / 2; | 1432 (total_tile_size.width() - kFolderDroppingCircleRadius) / 2; |
1408 int col = (point.x() - bounds.x() + x_offset) / kPreferredTileWidth; | 1433 int col = (point.x() - bounds.x() + x_offset) / total_tile_size.width(); |
1409 col = ClampToRange(col, 0, cols_ - 1); | 1434 col = ClampToRange(col, 0, cols_ - 1); |
1410 *drop_target = | 1435 *drop_target = |
1411 std::min(Index(pagination_model_.selected_page(), row * cols_ + col), | 1436 std::min(Index(pagination_model_.selected_page(), row * cols_ + col), |
1412 GetLastViewIndex()); | 1437 GetLastViewIndex()); |
1413 } | 1438 } |
1414 | 1439 |
1415 void AppsGridView::OnReorderTimer() { | 1440 void AppsGridView::OnReorderTimer() { |
1416 if (drop_attempt_ == DROP_FOR_REORDER) { | 1441 if (drop_attempt_ == DROP_FOR_REORDER) { |
1417 reorder_placeholder_ = reorder_drop_target_; | 1442 reorder_placeholder_ = reorder_drop_target_; |
1418 AnimateToIdealBounds(); | 1443 AnimateToIdealBounds(); |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2060 // Items can be dropped into non-folders (which have no children) or folders | 2085 // Items can be dropped into non-folders (which have no children) or folders |
2061 // that have fewer than the max allowed items. | 2086 // that have fewer than the max allowed items. |
2062 // OEM folder does not allow to drag/drop other items in it. | 2087 // OEM folder does not allow to drag/drop other items in it. |
2063 return target_item->ChildItemCount() < kMaxFolderItems && | 2088 return target_item->ChildItemCount() < kMaxFolderItems && |
2064 !IsOEMFolderItem(target_item); | 2089 !IsOEMFolderItem(target_item); |
2065 } | 2090 } |
2066 | 2091 |
2067 AppsGridView::Index AppsGridView::GetNearestTileIndexForPoint( | 2092 AppsGridView::Index AppsGridView::GetNearestTileIndexForPoint( |
2068 const gfx::Point& point) const { | 2093 const gfx::Point& point) const { |
2069 gfx::Rect bounds = GetContentsBounds(); | 2094 gfx::Rect bounds = GetContentsBounds(); |
2070 int col = | 2095 gfx::Size total_tile_size = GetTotalTileSize(); |
2071 ClampToRange((point.x() - bounds.x()) / kPreferredTileWidth, 0, cols_); | 2096 int col = ClampToRange( |
| 2097 (point.x() - bounds.x()) / total_tile_size.width(), 0, cols_); |
2072 int row = ClampToRange( | 2098 int row = ClampToRange( |
2073 (point.y() - bounds.y()) / kPreferredTileHeight, 0, rows_per_page_); | 2099 (point.y() - bounds.y()) / total_tile_size.height(), 0, rows_per_page_); |
2074 return Index(pagination_model_.selected_page(), row * cols_ + col); | 2100 return Index(pagination_model_.selected_page(), row * cols_ + col); |
2075 } | 2101 } |
2076 | 2102 |
2077 gfx::Size AppsGridView::GetTileGridSize() const { | 2103 gfx::Size AppsGridView::GetTileGridSize() const { |
2078 gfx::Rect bounds = GetExpectedTileBounds(0, 0); | 2104 gfx::Rect bounds = GetExpectedTileBounds(0, 0); |
2079 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); | 2105 bounds.Union(GetExpectedTileBounds(rows_per_page_ - 1, cols_ - 1)); |
| 2106 if (switches::IsExperimentalAppListEnabled()) |
| 2107 bounds.Inset(-kExperimentalTileLeftRightPadding, |
| 2108 -kExperimentalTileTopBottomPadding); |
2080 return bounds.size(); | 2109 return bounds.size(); |
2081 } | 2110 } |
2082 | 2111 |
2083 gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const { | 2112 gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const { |
2084 return GetExpectedTileBounds(slot / cols_, slot % cols_); | 2113 return GetExpectedTileBounds(slot / cols_, slot % cols_); |
2085 } | 2114 } |
2086 | 2115 |
2087 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { | 2116 gfx::Rect AppsGridView::GetExpectedTileBounds(int row, int col) const { |
2088 gfx::Rect bounds(GetContentsBounds()); | 2117 gfx::Rect bounds(GetContentsBounds()); |
2089 gfx::Size tile_size(kPreferredTileWidth, kPreferredTileHeight); | 2118 gfx::Size total_tile_size = GetTotalTileSize(); |
2090 return gfx::Rect(gfx::Point(bounds.x() + col * tile_size.width(), | 2119 gfx::Rect tile_bounds(gfx::Point(bounds.x() + col * total_tile_size.width(), |
2091 bounds.y() + row * tile_size.height()), | 2120 bounds.y() + row * total_tile_size.height()), |
2092 tile_size); | 2121 total_tile_size); |
| 2122 tile_bounds.ClampToCenteredSize(GetTileViewSize()); |
| 2123 return tile_bounds; |
2093 } | 2124 } |
2094 | 2125 |
2095 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { | 2126 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { |
2096 if (slot < 0) | 2127 if (slot < 0) |
2097 return NULL; | 2128 return NULL; |
2098 | 2129 |
2099 // Calculate the original bound of the tile at |index|. | 2130 // Calculate the original bound of the tile at |index|. |
2100 int row = slot / cols_; | 2131 int row = slot / cols_; |
2101 int col = slot % cols_; | 2132 int col = slot % cols_; |
2102 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); | 2133 gfx::Rect tile_rect = GetExpectedTileBounds(row, col); |
2103 | 2134 |
2104 for (int i = 0; i < view_model_.view_size(); ++i) { | 2135 for (int i = 0; i < view_model_.view_size(); ++i) { |
2105 views::View* view = view_model_.view_at(i); | 2136 views::View* view = view_model_.view_at(i); |
2106 if (view->bounds() == tile_rect && view != drag_view_) | 2137 if (view->bounds() == tile_rect && view != drag_view_) |
2107 return view; | 2138 return view; |
2108 } | 2139 } |
2109 return NULL; | 2140 return NULL; |
2110 } | 2141 } |
2111 | 2142 |
2112 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, | 2143 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, |
2113 bool is_target_folder) { | 2144 bool is_target_folder) { |
2114 AppListItemView* target_view = | 2145 AppListItemView* target_view = |
2115 static_cast<AppListItemView*>( | 2146 static_cast<AppListItemView*>( |
2116 GetViewAtSlotOnCurrentPage(target_index.slot)); | 2147 GetViewAtSlotOnCurrentPage(target_index.slot)); |
2117 if (target_view) | 2148 if (target_view) |
2118 target_view->SetAsAttemptedFolderTarget(is_target_folder); | 2149 target_view->SetAsAttemptedFolderTarget(is_target_folder); |
2119 } | 2150 } |
2120 | 2151 |
2121 } // namespace app_list | 2152 } // namespace app_list |
OLD | NEW |