Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: chrome/browser/resources/settings/device_page/display_layout.js

Issue 2097793004: MD Settings: Display: Implement dragging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@issue_547080_display_settings7
Patch Set: Feedback Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * 'display-layout' presents a visual representation of the layout of one or 7 * 'display-layout' presents a visual representation of the layout of one or
8 * more displays and allows them to be arranged. 8 * more displays and allows them to be arranged.
9 */ 9 */
10 10
11 (function() { 11 (function() {
12 12
13 /** @const {number} */ var MIN_VISUAL_SCALE = .01; 13 /** @const {number} */ var MIN_VISUAL_SCALE = .01;
14 14
15 Polymer({ 15 Polymer({
16 is: 'display-layout', 16 is: 'display-layout',
17 17
18 behaviors: [ 18 behaviors: [
19 Polymer.IronResizableBehavior, 19 Polymer.IronResizableBehavior,
20 DragBehavior,
20 ], 21 ],
21 22
22 properties: { 23 properties: {
23 /** 24 /**
24 * Array of displays. 25 * Array of displays.
25 * @type {!Array<!chrome.system.display.DisplayUnitInfo>} 26 * @type {!Array<!chrome.system.display.DisplayUnitInfo>}
26 */ 27 */
27 displays: Array, 28 displays: Array,
28 29
29 /** 30 /**
30 * Array of display layouts. 31 * Array of display layouts.
31 * @type {!Array<!chrome.system.display.DisplayLayout>} 32 * @type {!Array<!chrome.system.display.DisplayLayout>}
32 */ 33 */
33 layouts: Array, 34 layouts: Array,
34 35
36 /**
37 * Whether or not mirroring is enabled.
38 * @type {boolean}
39 */
40 mirroring: false,
41
35 /** @type {!chrome.system.display.DisplayUnitInfo|undefined} */ 42 /** @type {!chrome.system.display.DisplayUnitInfo|undefined} */
36 selectedDisplay: Object, 43 selectedDisplay: Object,
37 44
38 /** 45 /**
39 * The ratio of the display area div (in px) to DisplayUnitInfo.bounds. 46 * The ratio of the display area div (in px) to DisplayUnitInfo.bounds.
40 * @type {number} 47 * @type {number}
41 */ 48 */
42 visualScale: 1, 49 visualScale: 1,
43 }, 50 },
44 51
45 /** @private {!Object<chrome.system.display.DisplayUnitInfo>} */ 52 /** @private {!Object<chrome.system.display.Bounds>} */
46 displayMap_: {}, 53 displayBoundsMap_: {},
47 54
48 /** @private {!Object<chrome.system.display.DisplayLayout>} */ 55 /** @private {!Object<chrome.system.display.DisplayLayout>} */
49 layoutMap_: {}, 56 layoutMap_: {},
50 57
51 /** @private {!Object<chrome.system.display.Bounds>} */ 58 /**
52 boundsMap_: {}, 59 * The calculated bounds used for generating the div bounds.
60 * @private {!Object<chrome.system.display.Bounds>}
61 */
62 calculatedBoundsMap_: {},
53 63
54 /** @private {!{left: number, top: number}} */ 64 /** @private {!{left: number, top: number}} */
55 visualOffset_: {left: 0, top: 0}, 65 visualOffset_: {left: 0, top: 0},
56 66
57 /** @override */ 67 /** @override */
58 attached: function() { 68 attached: function() {
59 // TODO(stevenjb): Remove retry once fixed: 69 // TODO(stevenjb): Remove retry once fixed:
60 // https://github.com/Polymer/polymer/issues/3629 70 // https://github.com/Polymer/polymer/issues/3629
61 var self = this; 71 var self = this;
62 var retry = 100; // ms 72 var retry = 100; // ms
63 function tryCalcVisualScale() { 73 function tryCalcVisualScale() {
64 if (!self.calculateVisualScale_()) 74 if (!self.calculateVisualScale_())
65 setTimeout(tryCalcVisualScale, retry); 75 setTimeout(tryCalcVisualScale, retry);
66 } 76 }
67 tryCalcVisualScale(); 77 tryCalcVisualScale();
68 }, 78 },
69 79
80 /** @override */
81 detached: function() {
82 this.initializeDrag(false);
83 },
84
70 /** 85 /**
71 * Called explicitly when |this.displays| and their associated |this.layouts| 86 * Called explicitly when |this.displays| and their associated |this.layouts|
72 * have been fetched from chrome. 87 * have been fetched from chrome.
73 * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays 88 * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
74 * @param {!Array<!chrome.system.display.DisplayLayout>} layouts 89 * @param {!Array<!chrome.system.display.DisplayLayout>} layouts
75 */ 90 */
76 updateDisplays: function(displays, layouts) { 91 updateDisplays: function(displays, layouts) {
77 this.displays = displays; 92 this.displays = displays;
78 this.layouts = layouts; 93 this.layouts = layouts;
79 94
80 this.displayMap_ = {}; 95 this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId;
96
97 this.displayBoundsMap_ = {};
81 for (let display of this.displays) 98 for (let display of this.displays)
82 this.displayMap_[display.id] = display; 99 this.displayBoundsMap_[display.id] = display.bounds;
83 100
84 this.layoutMap_ = {}; 101 this.layoutMap_ = {};
85 for (let layout of this.layouts) 102 for (let layout of this.layouts)
86 this.layoutMap_[layout.id] = layout; 103 this.layoutMap_[layout.id] = layout;
87 104
88 this.boundsMap_ = {}; 105 this.calculatedBoundsMap_ = {};
89 for (let display of this.displays) 106 for (let display of this.displays)
90 this.calcDisplayBounds_(display); 107 this.calculateBounds_(display.id, display.bounds);
91 108
92 this.calculateVisualScale_(); 109 this.calculateVisualScale_();
110
111 this.initializeDrag(
112 !this.mirroring, this.$.displayArea, this.onDrag_.bind(this));
93 }, 113 },
94 114
95 /** 115 /**
96 * Calculates the visual offset and scale for the display area 116 * Calculates the visual offset and scale for the display area
97 * (i.e. the ratio of the display area div size to the area required to 117 * (i.e. the ratio of the display area div size to the area required to
98 * contain the DisplayUnitInfo bounding boxes). 118 * contain the DisplayUnitInfo bounding boxes).
99 * @return {boolean} Whether the calculation was successful. 119 * @return {boolean} Whether the calculation was successful.
100 * @private 120 * @private
101 */ 121 */
102 calculateVisualScale_() { 122 calculateVisualScale_() {
103 var displayAreaDiv = this.$.displayArea; 123 var displayAreaDiv = this.$.displayArea;
104 if (!displayAreaDiv || !displayAreaDiv.offsetWidth || !this.displays || 124 if (!displayAreaDiv || !displayAreaDiv.offsetWidth || !this.displays ||
105 !this.displays.length) { 125 !this.displays.length) {
106 return false; 126 return false;
107 } 127 }
108 128
109 var display = this.displays[0]; 129 var display = this.displays[0];
110 var bounds = this.boundsMap_[display.id]; 130 var bounds = this.calculatedBoundsMap_[display.id];
111 var displayInfoBoundingBox = { 131 var displayInfoBoundingBox = {
112 left: bounds.left, 132 left: bounds.left,
113 right: bounds.left + bounds.width, 133 right: bounds.left + bounds.width,
114 top: bounds.top, 134 top: bounds.top,
115 bottom: bounds.top + bounds.height, 135 bottom: bounds.top + bounds.height,
116 }; 136 };
117 var maxWidth = bounds.width; 137 var maxWidth = bounds.width;
118 var maxHeight = bounds.height; 138 var maxHeight = bounds.height;
119 for (let i = 1; i < this.displays.length; ++i) { 139 for (let i = 1; i < this.displays.length; ++i) {
120 display = this.displays[i]; 140 display = this.displays[i];
121 bounds = this.boundsMap_[display.id]; 141 bounds = this.calculatedBoundsMap_[display.id];
122 displayInfoBoundingBox.left = 142 displayInfoBoundingBox.left =
123 Math.min(displayInfoBoundingBox.left, bounds.left); 143 Math.min(displayInfoBoundingBox.left, bounds.left);
124 displayInfoBoundingBox.right = 144 displayInfoBoundingBox.right =
125 Math.max(displayInfoBoundingBox.right, bounds.left + bounds.width); 145 Math.max(displayInfoBoundingBox.right, bounds.left + bounds.width);
126 displayInfoBoundingBox.top = 146 displayInfoBoundingBox.top =
127 Math.min(displayInfoBoundingBox.top, bounds.top); 147 Math.min(displayInfoBoundingBox.top, bounds.top);
128 displayInfoBoundingBox.bottom = 148 displayInfoBoundingBox.bottom =
129 Math.max(displayInfoBoundingBox.bottom, bounds.top + bounds.height); 149 Math.max(displayInfoBoundingBox.bottom, bounds.top + bounds.height);
130 maxWidth = Math.max(maxWidth, bounds.width); 150 maxWidth = Math.max(maxWidth, bounds.width);
131 maxHeight = Math.max(maxHeight, bounds.height); 151 maxHeight = Math.max(maxHeight, bounds.height);
(...skipping 15 matching lines...) Expand all
147 this.visualOffset_.left = (-displayInfoBoundingBox.left + maxWidth) * scale; 167 this.visualOffset_.left = (-displayInfoBoundingBox.left + maxWidth) * scale;
148 this.visualOffset_.top = (-displayInfoBoundingBox.top + maxHeight) * scale; 168 this.visualOffset_.top = (-displayInfoBoundingBox.top + maxHeight) * scale;
149 169
150 // Update the scale which will trigger calls to getDivStyle_. 170 // Update the scale which will trigger calls to getDivStyle_.
151 this.visualScale = Math.max(MIN_VISUAL_SCALE, scale); 171 this.visualScale = Math.max(MIN_VISUAL_SCALE, scale);
152 172
153 return true; 173 return true;
154 }, 174 },
155 175
156 /** 176 /**
157 * @param {!chrome.system.display.DisplayUnitInfo} display 177 * @param {string} id
178 * @param {!chrome.system.display.Bounds} displayBounds
158 * @param {number} visualScale 179 * @param {number} visualScale
159 * @return {string} The style string for the div. 180 * @return {string} The style string for the div.
160 * @private 181 * @private
161 */ 182 */
162 getDivStyle_: function(display, visualScale) { 183 getDivStyle_: function(id, displayBounds, visualScale) {
163 // This matches the size of the box-shadow or border in CSS. 184 // This matches the size of the box-shadow or border in CSS.
164 /** @const {number} */ var BORDER = 2; 185 /** @const {number} */ var BORDER = 2;
165 var bounds = this.boundsMap_[display.id]; 186 var bounds = this.calculatedBoundsMap_[id];
166 var height = Math.round(bounds.height * this.visualScale) - BORDER * 2; 187 var height = Math.round(bounds.height * this.visualScale) - BORDER * 2;
167 var width = Math.round(bounds.width * this.visualScale) - BORDER * 2; 188 var width = Math.round(bounds.width * this.visualScale) - BORDER * 2;
168 var left = 189 var left =
169 Math.round(this.visualOffset_.left + (bounds.left * this.visualScale)); 190 Math.round(this.visualOffset_.left + (bounds.left * this.visualScale));
170 var top = 191 var top =
171 Math.round(this.visualOffset_.top + (bounds.top * this.visualScale)); 192 Math.round(this.visualOffset_.top + (bounds.top * this.visualScale));
172 return `height: ${height}px; width: ${width}px;` + 193 return `height: ${height}px; width: ${width}px;` +
173 ` left: ${left}px; top: ${top}px`; 194 ` left: ${left}px; top: ${top}px`;
174 }, 195 },
175 196
(...skipping 13 matching lines...) Expand all
189 */ 210 */
190 onSelectDisplayTap_: function(e) { 211 onSelectDisplayTap_: function(e) {
191 this.fire('select-display', e.model.index); 212 this.fire('select-display', e.model.index);
192 }, 213 },
193 214
194 /** 215 /**
195 * Recursively calculate the bounds of a display relative to its parents. 216 * Recursively calculate the bounds of a display relative to its parents.
196 * Caches the display bounds so that parent bounds are only calculated once. 217 * Caches the display bounds so that parent bounds are only calculated once.
197 * TODO(stevenjb): Move this function and the maps it requires to a separate 218 * TODO(stevenjb): Move this function and the maps it requires to a separate
198 * behavior which will include snapping and collisions. 219 * behavior which will include snapping and collisions.
199 * @param {!chrome.system.display.DisplayUnitInfo} display 220 * @param {string} id
221 * @param {!chrome.system.display.Bounds} bounds
200 * @private 222 * @private
201 */ 223 */
202 calcDisplayBounds_: function(display) { 224 calculateBounds_: function(id, bounds) {
203 if (display.id in this.boundsMap_) 225 if (id in this.calculatedBoundsMap_)
204 return; // Already calculated (i.e. a parent of a previous display) 226 return; // Already calculated (i.e. a parent of a previous display)
205 var left, top; 227 var left, top;
206 if (display.isPrimary) { 228 var layout = this.layoutMap_[id];
207 left = -display.bounds.width / 2; 229 if (!layout || !layout.parentId) {
208 top = -display.bounds.height / 2; 230 left = -bounds.width / 2;
231 top = -bounds.height / 2;
209 } else { 232 } else {
210 var layout = this.layoutMap_[display.id]; 233 var parentDisplayBounds = this.displayBoundsMap_[layout.parentId];
211 assert(layout.parentId);
212 var parentDisplay = this.displayMap_[layout.parentId];
213 var parentBounds; 234 var parentBounds;
214 if (!(parentDisplay.id in this.boundsMap_)) 235 if (!(layout.parentId in this.calculatedBoundsMap_))
215 this.calcDisplayBounds_(parentDisplay); 236 this.calculateBounds_(layout.parentId, parentDisplayBounds);
216 parentBounds = this.boundsMap_[parentDisplay.id]; 237 parentBounds = this.calculatedBoundsMap_[layout.parentId];
217 left = parentBounds.left; 238 left = parentBounds.left;
218 top = parentBounds.top; 239 top = parentBounds.top;
219 switch (layout.position) { 240 switch (layout.position) {
220 case chrome.system.display.LayoutPosition.TOP: 241 case chrome.system.display.LayoutPosition.TOP:
221 top -= display.bounds.height; 242 top -= bounds.height;
222 break; 243 break;
223 case chrome.system.display.LayoutPosition.RIGHT: 244 case chrome.system.display.LayoutPosition.RIGHT:
224 left += parentBounds.width; 245 left += parentBounds.width;
225 break; 246 break;
226 case chrome.system.display.LayoutPosition.BOTTOM: 247 case chrome.system.display.LayoutPosition.BOTTOM:
227 top += parentBounds.height; 248 top += parentBounds.height;
228 break; 249 break;
229 case chrome.system.display.LayoutPosition.LEFT: 250 case chrome.system.display.LayoutPosition.LEFT:
230 left -= display.bounds.height; 251 left -= bounds.height;
231 break; 252 break;
232 } 253 }
233 } 254 }
234 var result = { 255 var result = {
235 left: left, 256 left: left,
236 top: top, 257 top: top,
237 width: display.bounds.width, 258 width: bounds.width,
238 height: display.bounds.height 259 height: bounds.height
239 }; 260 };
240 this.boundsMap_[display.id] = result; 261 this.calculatedBoundsMap_[id] = result;
241 } 262 },
263
264 /**
265 * @param {string} id
266 * @param {?DragPosition} amount
267 */
268 onDrag_(id, amount) {
269 id = id.substr(1); // Skip prefix
270
271 var newBounds;
272 if (!amount) {
273 // TODO(stevenjb): Resolve layout and send update.
274 newBounds = this.calculatedBoundsMap_[id];
275 } else {
276 // Make sure the dragged display is also selected.
277 if (id != this.selectedDisplay.id)
278 this.fire('select-display', id);
279
280 var calculatedBounds = this.calculatedBoundsMap_[id];
281 newBounds =
282 /** @type {chrome.system.display.Bounds} */ (
283 Object.assign({}, calculatedBounds));
284 newBounds.left += Math.round(amount.x / this.visualScale);
285 newBounds.top += Math.round(amount.y / this.visualScale);
286 // TODO(stevenjb): Update layout.
287 }
288 var left =
289 this.visualOffset_.left + Math.round(newBounds.left * this.visualScale);
290 var top =
291 this.visualOffset_.top + Math.round(newBounds.top * this.visualScale);
292 var div = this.$$('#_' + id);
293 div.style.left = '' + left + 'px';
294 div.style.top = '' + top + 'px';
295 },
296
242 }); 297 });
243 298
244 })(); 299 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698