|
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 |
|
6 |
|
7 // A little delay that prevents the grid from being too sensitive when dragging |
|
8 // sites around. |
|
9 const DELAY_REARRANGE_MS = 100; |
|
10 |
|
11 /** |
|
12 * This singleton implements site dropping functionality. |
|
13 */ |
|
14 let gDrop = { |
|
15 /** |
|
16 * The last drop target. |
|
17 */ |
|
18 _lastDropTarget: null, |
|
19 |
|
20 /** |
|
21 * Handles the 'dragenter' event. |
|
22 * @param aCell The drop target cell. |
|
23 */ |
|
24 enter: function Drop_enter(aCell) { |
|
25 this._delayedRearrange(aCell); |
|
26 }, |
|
27 |
|
28 /** |
|
29 * Handles the 'dragexit' event. |
|
30 * @param aCell The drop target cell. |
|
31 * @param aEvent The 'dragexit' event. |
|
32 */ |
|
33 exit: function Drop_exit(aCell, aEvent) { |
|
34 if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) { |
|
35 this._delayedRearrange(); |
|
36 } else { |
|
37 // The drag operation has been cancelled. |
|
38 this._cancelDelayedArrange(); |
|
39 this._rearrange(); |
|
40 } |
|
41 }, |
|
42 |
|
43 /** |
|
44 * Handles the 'drop' event. |
|
45 * @param aCell The drop target cell. |
|
46 * @param aEvent The 'dragexit' event. |
|
47 */ |
|
48 drop: function Drop_drop(aCell, aEvent) { |
|
49 // The cell that is the drop target could contain a pinned site. We need |
|
50 // to find out where that site has gone and re-pin it there. |
|
51 if (aCell.containsPinnedSite()) |
|
52 this._repinSitesAfterDrop(aCell); |
|
53 |
|
54 // Pin the dragged or insert the new site. |
|
55 this._pinDraggedSite(aCell, aEvent); |
|
56 |
|
57 this._cancelDelayedArrange(); |
|
58 |
|
59 // Update the grid and move all sites to their new places. |
|
60 gUpdater.updateGrid(); |
|
61 }, |
|
62 |
|
63 /** |
|
64 * Re-pins all pinned sites in their (new) positions. |
|
65 * @param aCell The drop target cell. |
|
66 */ |
|
67 _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) { |
|
68 let sites = gDropPreview.rearrange(aCell); |
|
69 |
|
70 // Filter out pinned sites. |
|
71 let pinnedSites = sites.filter(function (aSite) { |
|
72 return aSite && aSite.isPinned(); |
|
73 }); |
|
74 |
|
75 // Re-pin all shifted pinned cells. |
|
76 pinnedSites.forEach(function (aSite) aSite.pin(sites.indexOf(aSite)), this); |
|
77 }, |
|
78 |
|
79 /** |
|
80 * Pins the dragged site in its new place. |
|
81 * @param aCell The drop target cell. |
|
82 * @param aEvent The 'dragexit' event. |
|
83 */ |
|
84 _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) { |
|
85 let index = aCell.index; |
|
86 let draggedSite = gDrag.draggedSite; |
|
87 |
|
88 if (draggedSite) { |
|
89 // Pin the dragged site at its new place. |
|
90 if (aCell != draggedSite.cell) |
|
91 draggedSite.pin(index); |
|
92 } else { |
|
93 let link = gDragDataHelper.getLinkFromDragEvent(aEvent); |
|
94 if (link) { |
|
95 // A new link was dragged onto the grid. Create it by pinning its URL. |
|
96 gPinnedLinks.pin(link, index); |
|
97 |
|
98 // Make sure the newly added link is not blocked. |
|
99 gBlockedLinks.unblock(link); |
|
100 } |
|
101 } |
|
102 }, |
|
103 |
|
104 /** |
|
105 * Time a rearrange with a little delay. |
|
106 * @param aCell The drop target cell. |
|
107 */ |
|
108 _delayedRearrange: function Drop_delayedRearrange(aCell) { |
|
109 // The last drop target didn't change so there's no need to re-arrange. |
|
110 if (this._lastDropTarget == aCell) |
|
111 return; |
|
112 |
|
113 let self = this; |
|
114 |
|
115 function callback() { |
|
116 self._rearrangeTimeout = null; |
|
117 self._rearrange(aCell); |
|
118 } |
|
119 |
|
120 this._cancelDelayedArrange(); |
|
121 this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS); |
|
122 |
|
123 // Store the last drop target. |
|
124 this._lastDropTarget = aCell; |
|
125 }, |
|
126 |
|
127 /** |
|
128 * Cancels a timed rearrange, if any. |
|
129 */ |
|
130 _cancelDelayedArrange: function Drop_cancelDelayedArrange() { |
|
131 if (this._rearrangeTimeout) { |
|
132 clearTimeout(this._rearrangeTimeout); |
|
133 this._rearrangeTimeout = null; |
|
134 } |
|
135 }, |
|
136 |
|
137 /** |
|
138 * Rearrange all sites in the grid depending on the current drop target. |
|
139 * @param aCell The drop target cell. |
|
140 */ |
|
141 _rearrange: function Drop_rearrange(aCell) { |
|
142 let sites = gGrid.sites; |
|
143 |
|
144 // We need to rearrange the grid only if there's a current drop target. |
|
145 if (aCell) |
|
146 sites = gDropPreview.rearrange(aCell); |
|
147 |
|
148 gTransformation.rearrangeSites(sites, {unfreeze: !aCell}); |
|
149 } |
|
150 }; |