123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #ifdef 0
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- #endif
- /**
- * This singleton provides the ability to re-arrange the current grid to
- * indicate the transformation that results from dropping a cell at a certain
- * position.
- */
- var gDropPreview = {
- /**
- * Rearranges the sites currently contained in the grid when a site would be
- * dropped onto the given cell.
- * @param aCell The drop target cell.
- * @return The re-arranged array of sites.
- */
- rearrange: function(aCell) {
- let sites = gGrid.sites;
- // Insert the dragged site into the current grid.
- this._insertDraggedSite(sites, aCell);
- // After the new site has been inserted we need to correct the positions
- // of all pinned tabs that have been moved around.
- this._repositionPinnedSites(sites, aCell);
- return sites;
- },
- /**
- * Inserts the currently dragged site into the given array of sites.
- * @param aSites The array of sites to insert into.
- * @param aCell The drop target cell.
- */
- _insertDraggedSite: function(aSites, aCell) {
- let dropIndex = aCell.index;
- let draggedSite = gDrag.draggedSite;
- // We're currently dragging a site.
- if (draggedSite) {
- let dragCell = draggedSite.cell;
- let dragIndex = dragCell.index;
- // Move the dragged site into its new position.
- if (dragIndex != dropIndex) {
- aSites.splice(dragIndex, 1);
- aSites.splice(dropIndex, 0, draggedSite);
- }
- // We're handling an external drag item.
- } else {
- aSites.splice(dropIndex, 0, null);
- }
- },
- /**
- * Correct the position of all pinned sites that might have been moved to
- * different positions after the dragged site has been inserted.
- * @param aSites The array of sites containing the dragged site.
- * @param aCell The drop target cell.
- */
- _repositionPinnedSites:
- function(aSites, aCell) {
- // Collect all pinned sites.
- let pinnedSites = this._filterPinnedSites(aSites, aCell);
- // Correct pinned site positions.
- pinnedSites.forEach(function(aSite) {
- aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
- aSites[aSite.cell.index] = aSite;
- }, this);
- // There might be a pinned cell that got pushed out of the grid, try to
- // sneak it in by removing a lower-priority cell.
- if (this._hasOverflowedPinnedSite(aSites, aCell))
- this._repositionOverflowedPinnedSite(aSites, aCell);
- },
- /**
- * Filter pinned sites out of the grid that are still on their old positions
- * and have not moved.
- * @param aSites The array of sites to filter.
- * @param aCell The drop target cell.
- * @return The filtered array of sites.
- */
- _filterPinnedSites: function(aSites, aCell) {
- let draggedSite = gDrag.draggedSite;
- // When dropping on a cell that contains a pinned site make sure that all
- // pinned cells surrounding the drop target are moved as well.
- let range = this._getPinnedRange(aCell);
- return aSites.filter(function(aSite, aIndex) {
- // The site must be valid, pinned and not the dragged site.
- if (!aSite || aSite == draggedSite || !aSite.isPinned())
- return false;
- let index = aSite.cell.index;
- // If it's not in the 'pinned range' it's a valid pinned site.
- return (index > range.end || index < range.start);
- });
- },
- /**
- * Determines the range of pinned sites surrounding the drop target cell.
- * @param aCell The drop target cell.
- * @return The range of pinned cells.
- */
- _getPinnedRange: function(aCell) {
- let dropIndex = aCell.index;
- let range = {start: dropIndex, end: dropIndex};
- // We need a pinned range only when dropping on a pinned site.
- if (aCell.containsPinnedSite()) {
- let links = gPinnedLinks.links;
- // Find all previous siblings of the drop target that are pinned as well.
- while (range.start && links[range.start - 1])
- range.start--;
- let maxEnd = links.length - 1;
- // Find all next siblings of the drop target that are pinned as well.
- while (range.end < maxEnd && links[range.end + 1])
- range.end++;
- }
- return range;
- },
- /**
- * Checks if the given array of sites contains a pinned site that has
- * been pushed out of the grid.
- * @param aSites The array of sites to check.
- * @param aCell The drop target cell.
- * @return Whether there is an overflowed pinned cell.
- */
- _hasOverflowedPinnedSite:
- function(aSites, aCell) {
- // If the drop target isn't pinned there's no way a pinned site has been
- // pushed out of the grid so we can just exit here.
- if (!aCell.containsPinnedSite())
- return false;
- let cells = gGrid.cells;
- // No cells have been pushed out of the grid, nothing to do here.
- if (aSites.length <= cells.length)
- return false;
- let overflowedSite = aSites[cells.length];
- // Nothing to do if the site that got pushed out of the grid is not pinned.
- return (overflowedSite && overflowedSite.isPinned());
- },
- /**
- * We have a overflowed pinned site that we need to re-position so that it's
- * visible again. We try to find a lower-priority cell (empty or containing
- * an unpinned site) that we can move it to.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- */
- _repositionOverflowedPinnedSite:
- function(aSites, aCell) {
- // Try to find a lower-priority cell (empty or containing an unpinned site).
- let index = this._indexOfLowerPrioritySite(aSites, aCell);
- if (index > -1) {
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
- // Move all pinned cells to their new positions to let the overflowed
- // site fit into the grid.
- for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
- if (i != dropIndex) {
- aSites[lastPosition] = aSites[i];
- lastPosition = i;
- }
- }
- // Finally, remove the overflowed site from its previous position.
- aSites.splice(cells.length, 1);
- }
- },
- /**
- * Finds the index of the last cell that is empty or contains an unpinned
- * site. These are considered to be of a lower priority.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- * @return The cell's index.
- */
- _indexOfLowerPrioritySite:
- function(aSites, aCell) {
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
- // Search (beginning with the last site in the grid) for a site that is
- // empty or unpinned (an thus lower-priority) and can be pushed out of the
- // grid instead of the pinned site.
- for (let i = cells.length - 1; i >= 0; i--) {
- // The cell that is our drop target is not a good choice.
- if (i == dropIndex)
- continue;
- let site = aSites[i];
- // We can use the cell only if it's empty or the site is un-pinned.
- if (!site || !site.isPinned())
- return i;
- }
- return -1;
- }
- };
|