browser/base/content/newtab/dropPreview.js

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

michael@0 1 #ifdef 0
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5 #endif
michael@0 6
michael@0 7 /**
michael@0 8 * This singleton provides the ability to re-arrange the current grid to
michael@0 9 * indicate the transformation that results from dropping a cell at a certain
michael@0 10 * position.
michael@0 11 */
michael@0 12 let gDropPreview = {
michael@0 13 /**
michael@0 14 * Rearranges the sites currently contained in the grid when a site would be
michael@0 15 * dropped onto the given cell.
michael@0 16 * @param aCell The drop target cell.
michael@0 17 * @return The re-arranged array of sites.
michael@0 18 */
michael@0 19 rearrange: function DropPreview_rearrange(aCell) {
michael@0 20 let sites = gGrid.sites;
michael@0 21
michael@0 22 // Insert the dragged site into the current grid.
michael@0 23 this._insertDraggedSite(sites, aCell);
michael@0 24
michael@0 25 // After the new site has been inserted we need to correct the positions
michael@0 26 // of all pinned tabs that have been moved around.
michael@0 27 this._repositionPinnedSites(sites, aCell);
michael@0 28
michael@0 29 return sites;
michael@0 30 },
michael@0 31
michael@0 32 /**
michael@0 33 * Inserts the currently dragged site into the given array of sites.
michael@0 34 * @param aSites The array of sites to insert into.
michael@0 35 * @param aCell The drop target cell.
michael@0 36 */
michael@0 37 _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
michael@0 38 let dropIndex = aCell.index;
michael@0 39 let draggedSite = gDrag.draggedSite;
michael@0 40
michael@0 41 // We're currently dragging a site.
michael@0 42 if (draggedSite) {
michael@0 43 let dragCell = draggedSite.cell;
michael@0 44 let dragIndex = dragCell.index;
michael@0 45
michael@0 46 // Move the dragged site into its new position.
michael@0 47 if (dragIndex != dropIndex) {
michael@0 48 aSites.splice(dragIndex, 1);
michael@0 49 aSites.splice(dropIndex, 0, draggedSite);
michael@0 50 }
michael@0 51 // We're handling an external drag item.
michael@0 52 } else {
michael@0 53 aSites.splice(dropIndex, 0, null);
michael@0 54 }
michael@0 55 },
michael@0 56
michael@0 57 /**
michael@0 58 * Correct the position of all pinned sites that might have been moved to
michael@0 59 * different positions after the dragged site has been inserted.
michael@0 60 * @param aSites The array of sites containing the dragged site.
michael@0 61 * @param aCell The drop target cell.
michael@0 62 */
michael@0 63 _repositionPinnedSites:
michael@0 64 function DropPreview_repositionPinnedSites(aSites, aCell) {
michael@0 65
michael@0 66 // Collect all pinned sites.
michael@0 67 let pinnedSites = this._filterPinnedSites(aSites, aCell);
michael@0 68
michael@0 69 // Correct pinned site positions.
michael@0 70 pinnedSites.forEach(function (aSite) {
michael@0 71 aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
michael@0 72 aSites[aSite.cell.index] = aSite;
michael@0 73 }, this);
michael@0 74
michael@0 75 // There might be a pinned cell that got pushed out of the grid, try to
michael@0 76 // sneak it in by removing a lower-priority cell.
michael@0 77 if (this._hasOverflowedPinnedSite(aSites, aCell))
michael@0 78 this._repositionOverflowedPinnedSite(aSites, aCell);
michael@0 79 },
michael@0 80
michael@0 81 /**
michael@0 82 * Filter pinned sites out of the grid that are still on their old positions
michael@0 83 * and have not moved.
michael@0 84 * @param aSites The array of sites to filter.
michael@0 85 * @param aCell The drop target cell.
michael@0 86 * @return The filtered array of sites.
michael@0 87 */
michael@0 88 _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
michael@0 89 let draggedSite = gDrag.draggedSite;
michael@0 90
michael@0 91 // When dropping on a cell that contains a pinned site make sure that all
michael@0 92 // pinned cells surrounding the drop target are moved as well.
michael@0 93 let range = this._getPinnedRange(aCell);
michael@0 94
michael@0 95 return aSites.filter(function (aSite, aIndex) {
michael@0 96 // The site must be valid, pinned and not the dragged site.
michael@0 97 if (!aSite || aSite == draggedSite || !aSite.isPinned())
michael@0 98 return false;
michael@0 99
michael@0 100 let index = aSite.cell.index;
michael@0 101
michael@0 102 // If it's not in the 'pinned range' it's a valid pinned site.
michael@0 103 return (index > range.end || index < range.start);
michael@0 104 });
michael@0 105 },
michael@0 106
michael@0 107 /**
michael@0 108 * Determines the range of pinned sites surrounding the drop target cell.
michael@0 109 * @param aCell The drop target cell.
michael@0 110 * @return The range of pinned cells.
michael@0 111 */
michael@0 112 _getPinnedRange: function DropPreview_getPinnedRange(aCell) {
michael@0 113 let dropIndex = aCell.index;
michael@0 114 let range = {start: dropIndex, end: dropIndex};
michael@0 115
michael@0 116 // We need a pinned range only when dropping on a pinned site.
michael@0 117 if (aCell.containsPinnedSite()) {
michael@0 118 let links = gPinnedLinks.links;
michael@0 119
michael@0 120 // Find all previous siblings of the drop target that are pinned as well.
michael@0 121 while (range.start && links[range.start - 1])
michael@0 122 range.start--;
michael@0 123
michael@0 124 let maxEnd = links.length - 1;
michael@0 125
michael@0 126 // Find all next siblings of the drop target that are pinned as well.
michael@0 127 while (range.end < maxEnd && links[range.end + 1])
michael@0 128 range.end++;
michael@0 129 }
michael@0 130
michael@0 131 return range;
michael@0 132 },
michael@0 133
michael@0 134 /**
michael@0 135 * Checks if the given array of sites contains a pinned site that has
michael@0 136 * been pushed out of the grid.
michael@0 137 * @param aSites The array of sites to check.
michael@0 138 * @param aCell The drop target cell.
michael@0 139 * @return Whether there is an overflowed pinned cell.
michael@0 140 */
michael@0 141 _hasOverflowedPinnedSite:
michael@0 142 function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
michael@0 143
michael@0 144 // If the drop target isn't pinned there's no way a pinned site has been
michael@0 145 // pushed out of the grid so we can just exit here.
michael@0 146 if (!aCell.containsPinnedSite())
michael@0 147 return false;
michael@0 148
michael@0 149 let cells = gGrid.cells;
michael@0 150
michael@0 151 // No cells have been pushed out of the grid, nothing to do here.
michael@0 152 if (aSites.length <= cells.length)
michael@0 153 return false;
michael@0 154
michael@0 155 let overflowedSite = aSites[cells.length];
michael@0 156
michael@0 157 // Nothing to do if the site that got pushed out of the grid is not pinned.
michael@0 158 return (overflowedSite && overflowedSite.isPinned());
michael@0 159 },
michael@0 160
michael@0 161 /**
michael@0 162 * We have a overflowed pinned site that we need to re-position so that it's
michael@0 163 * visible again. We try to find a lower-priority cell (empty or containing
michael@0 164 * an unpinned site) that we can move it to.
michael@0 165 * @param aSites The array of sites.
michael@0 166 * @param aCell The drop target cell.
michael@0 167 */
michael@0 168 _repositionOverflowedPinnedSite:
michael@0 169 function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
michael@0 170
michael@0 171 // Try to find a lower-priority cell (empty or containing an unpinned site).
michael@0 172 let index = this._indexOfLowerPrioritySite(aSites, aCell);
michael@0 173
michael@0 174 if (index > -1) {
michael@0 175 let cells = gGrid.cells;
michael@0 176 let dropIndex = aCell.index;
michael@0 177
michael@0 178 // Move all pinned cells to their new positions to let the overflowed
michael@0 179 // site fit into the grid.
michael@0 180 for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
michael@0 181 if (i != dropIndex) {
michael@0 182 aSites[lastPosition] = aSites[i];
michael@0 183 lastPosition = i;
michael@0 184 }
michael@0 185 }
michael@0 186
michael@0 187 // Finally, remove the overflowed site from its previous position.
michael@0 188 aSites.splice(cells.length, 1);
michael@0 189 }
michael@0 190 },
michael@0 191
michael@0 192 /**
michael@0 193 * Finds the index of the last cell that is empty or contains an unpinned
michael@0 194 * site. These are considered to be of a lower priority.
michael@0 195 * @param aSites The array of sites.
michael@0 196 * @param aCell The drop target cell.
michael@0 197 * @return The cell's index.
michael@0 198 */
michael@0 199 _indexOfLowerPrioritySite:
michael@0 200 function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
michael@0 201
michael@0 202 let cells = gGrid.cells;
michael@0 203 let dropIndex = aCell.index;
michael@0 204
michael@0 205 // Search (beginning with the last site in the grid) for a site that is
michael@0 206 // empty or unpinned (an thus lower-priority) and can be pushed out of the
michael@0 207 // grid instead of the pinned site.
michael@0 208 for (let i = cells.length - 1; i >= 0; i--) {
michael@0 209 // The cell that is our drop target is not a good choice.
michael@0 210 if (i == dropIndex)
michael@0 211 continue;
michael@0 212
michael@0 213 let site = aSites[i];
michael@0 214
michael@0 215 // We can use the cell only if it's empty or the site is un-pinned.
michael@0 216 if (!site || !site.isPinned())
michael@0 217 return i;
michael@0 218 }
michael@0 219
michael@0 220 return -1;
michael@0 221 }
michael@0 222 };

mercurial