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

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

Issue 2084673003: MD Settings: Add display layout (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@issue_547080_display_settings6
Patch Set: Nit 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
(Empty)
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
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview
7 * 'display-layout' presents a visual representation of the layout of one or
8 * more displays and allows them to be arranged.
9 */
10
11 (function() {
12
13 /** @const {number} */ var MIN_VISUAL_SCALE = .01;
14
15 Polymer({
16 is: 'display-layout',
17
18 behaviors: [
19 Polymer.IronResizableBehavior,
20 ],
21
22 properties: {
23 /**
24 * Array of displays.
25 * @type {!Array<!chrome.system.display.DisplayUnitInfo>}
26 */
27 displays: Array,
28
29 /**
30 * Array of display layouts.
31 * @type {!Array<!chrome.system.display.DisplayLayout>}
32 */
33 layouts: Array,
34
35 /** @type {!chrome.system.display.DisplayUnitInfo|undefined} */
36 selectedDisplay: Object,
37
38 /**
39 * The ratio of the display area div (in px) to DisplayUnitInfo.bounds.
40 * @type {number}
41 */
42 visualScale: 1,
43 },
44
45 /** @private {!Object<chrome.system.display.DisplayUnitInfo>} */
46 displayMap_: {},
47
48 /** @private {!Object<chrome.system.display.DisplayLayout>} */
49 layoutMap_: {},
50
51 /** @private {!Object<chrome.system.display.Bounds>} */
52 boundsMap_: {},
53
54 /** @private {!{left: number, top: number}} */
55 visualOffset_: {left: 0, top: 0},
56
57 /** @override */
58 attached: function() {
59 // TODO(stevenjb): Remove retry once fixed:
60 // https://github.com/Polymer/polymer/issues/3629
61 var self = this;
62 var retry = 100; // ms
63 function tryCalcVisualScale() {
64 if (!self.calculateVisualScale_())
65 setTimeout(tryCalcVisualScale, retry);
66 }
67 tryCalcVisualScale();
68 },
69
70 /**
71 * Called explicitly when |this.displays| and their associated |this.layouts|
72 * have been fetched from chrome.
73 * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
74 * @param {!Array<!chrome.system.display.DisplayLayout>} layouts
75 */
76 updateDisplays: function(displays, layouts) {
77 this.displays = displays;
78 this.layouts = layouts;
79
80 this.displayMap_ = {};
81 for (let display of this.displays)
82 this.displayMap_[display.id] = display;
83
84 this.layoutMap_ = {};
85 for (let layout of this.layouts)
86 this.layoutMap_[layout.id] = layout;
87
88 this.boundsMap_ = {};
89 for (let display of this.displays)
90 this.calcDisplayBounds_(display);
91
92 this.calculateVisualScale_();
93 },
94
95 /**
96 * 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
98 * contain the DisplayUnitInfo bounding boxes).
99 * @return {boolean} Whether the calculation was successful.
100 * @private
101 */
102 calculateVisualScale_() {
103 var displayAreaDiv = this.$.displayArea;
104 if (!displayAreaDiv || !displayAreaDiv.offsetWidth || !this.displays ||
105 !this.displays.length) {
106 return false;
107 }
108
109 var display = this.displays[0];
110 var bounds = this.boundsMap_[display.id];
111 var displayInfoBoundingBox = {
112 left: bounds.left,
113 right: bounds.left + bounds.width,
114 top: bounds.top,
115 bottom: bounds.top + bounds.height,
116 };
117 var maxWidth = bounds.width;
118 var maxHeight = bounds.height;
119 for (let i = 1; i < this.displays.length; ++i) {
120 display = this.displays[i];
121 bounds = this.boundsMap_[display.id];
122 displayInfoBoundingBox.left =
123 Math.min(displayInfoBoundingBox.left, bounds.left);
124 displayInfoBoundingBox.right =
125 Math.max(displayInfoBoundingBox.right, bounds.left + bounds.width);
126 displayInfoBoundingBox.top =
127 Math.min(displayInfoBoundingBox.top, bounds.top);
128 displayInfoBoundingBox.bottom =
129 Math.max(displayInfoBoundingBox.bottom, bounds.top + bounds.height);
130 maxWidth = Math.max(maxWidth, bounds.width);
131 maxHeight = Math.max(maxHeight, bounds.height);
132 }
133
134 // Create a margin around the bounding box equal to the size of the
135 // largest displays.
136 var displayInfoBoundsWidth = displayInfoBoundingBox.right -
137 displayInfoBoundingBox.left + maxWidth * 2;
138 var displayInfoBoundsHeight = displayInfoBoundingBox.bottom -
139 displayInfoBoundingBox.top + maxHeight * 2;
140
141 // Calculate the scale.
142 var horizontalScale = displayAreaDiv.offsetWidth / displayInfoBoundsWidth;
143 var verticalScale = displayAreaDiv.offsetHeight / displayInfoBoundsHeight;
144 var scale = Math.min(horizontalScale, verticalScale);
145
146 // Calculate the offset.
147 this.visualOffset_.left = (-displayInfoBoundingBox.left + maxWidth) * scale;
148 this.visualOffset_.top = (-displayInfoBoundingBox.top + maxHeight) * scale;
149
150 // Update the scale which will trigger calls to getDivStyle_.
151 this.visualScale = Math.max(MIN_VISUAL_SCALE, scale);
152
153 return true;
154 },
155
156 /**
157 * @param {!chrome.system.display.DisplayUnitInfo} display
158 * @param {number} visualScale
159 * @return {string} The style string for the div.
160 * @private
161 */
162 getDivStyle_: function(display, visualScale) {
163 // This matches the size of the box-shadow or border in CSS.
164 /** @const {number} */ var BORDER = 2;
165 var bounds = this.boundsMap_[display.id];
166 var height = Math.round(bounds.height * this.visualScale) - BORDER * 2;
167 var width = Math.round(bounds.width * this.visualScale) - BORDER * 2;
168 var left =
169 Math.round(this.visualOffset_.left + (bounds.left * this.visualScale));
170 var top =
171 Math.round(this.visualOffset_.top + (bounds.top * this.visualScale));
172 return `height: ${height}px; width: ${width}px;` +
173 ` left: ${left}px; top: ${top}px`;
174 },
175
176 /**
177 * @param {!chrome.system.display.DisplayUnitInfo} display
178 * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
179 * @return {boolean}
180 * @private
181 */
182 isSelected_: function(display, selectedDisplay) {
183 return display.id == selectedDisplay.id;
184 },
185
186 /**
187 * @param {!{model: !{index: number}}} e
188 * @private
189 */
190 onSelectDisplayTap_: function(e) {
191 this.fire('select-display', e.model.index);
192 },
193
194 /**
195 * Recursively calculate the bounds of a display relative to its parents.
196 * 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
198 * behavior which will include snapping and collisions.
199 * @param {!chrome.system.display.DisplayUnitInfo} display
200 * @private
201 */
202 calcDisplayBounds_: function(display) {
203 if (display.id in this.boundsMap_)
204 return; // Already calculated (i.e. a parent of a previous display)
205 var left, top;
206 if (display.isPrimary) {
207 left = -display.bounds.width / 2;
208 top = -display.bounds.height / 2;
209 } else {
210 var layout = this.layoutMap_[display.id];
211 assert(layout.parentId);
212 var parentDisplay = this.displayMap_[layout.parentId];
213 var parentBounds;
214 if (!(parentDisplay.id in this.boundsMap_))
215 this.calcDisplayBounds_(parentDisplay);
216 parentBounds = this.boundsMap_[parentDisplay.id];
217 left = parentBounds.left;
218 top = parentBounds.top;
219 switch (layout.position) {
220 case chrome.system.display.LayoutPosition.TOP:
221 top -= display.bounds.height;
222 break;
223 case chrome.system.display.LayoutPosition.RIGHT:
224 left += parentBounds.width;
225 break;
226 case chrome.system.display.LayoutPosition.BOTTOM:
227 top += parentBounds.height;
228 break;
229 case chrome.system.display.LayoutPosition.LEFT:
230 left -= display.bounds.height;
231 break;
232 }
233 }
234 var result = {
235 left: left,
236 top: top,
237 width: display.bounds.width,
238 height: display.bounds.height
239 };
240 this.boundsMap_[display.id] = result;
241 }
242 });
243
244 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698