| 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 |