browser/base/content/newtab/dropPreview.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial