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

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: 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
(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 observers: ['displaysChanged_(displays, layouts)'],
46
47 /** @private {!Object<chrome.system.display.DisplayUnitInfo>} */
48 displayMap_: {},
49
50 /** @private {!Object<chrome.system.display.DisplayLayout>} */
51 layoutMap_: {},
52
53 /** @private {!Object<chrome.system.display.Bounds>} */
54 boundsMap_: {},
55
56 /** @private {!{left: number, top: number}} */
57 visualOffset_: {left: 0, top: 0},
58
59 /** @override */
60 attached: function() {
61 // TODO(stevenjb): Remove retry once fixed:
62 // https://github.com/Polymer/polymer/issues/3629
63 var self = this;
64 var retry = 100; // ms
65 function tryCalcVisualScale() {
66 if (!self.calculateVisualScale_())
67 setTimeout(tryCalcVisualScale, retry);
68 }
69 tryCalcVisualScale();
70 },
71
72 /** @private */
73 displaysChanged_: function(displays, layouts) {
74 this.displayMap_ = {};
75 for (let display of this.displays)
76 this.displayMap_[display.id] = display;
77
78 this.layoutMap_ = {};
79 for (let layout of this.layouts)
80 this.layoutMap_[layout.id] = layout;
81
82 this.boundsMap_ = {};
83 for (let display of this.displays)
84 this.calcDisplayBounds_(display);
85
86 this.calculateVisualScale_();
87 },
88
89 /**
90 * Calculates the visual offset and scale for the display area
91 * (i.e. the ratio of the display area div size to the area required to
92 * contain the DisplayUnitInfo bounding boxes).
93 * @return {boolean} Whether the calculation was successful.
94 * @private
95 */
96 calculateVisualScale_() {
97 var displayAreaDiv = this.$.displayArea;
98 if (!displayAreaDiv || !displayAreaDiv.offsetWidth || !this.displays)
99 return false;
100
101 var maxWidth = 0;
102 var maxHeight = 0;
103 var displayInfoBoundingBox =
104 {left: Number.MAX_VALUE, right: 0, top: Number.MAX_VALUE, bottom: 0};
michaelpg 2016/06/23 04:29:35 Normally the origin (0, 0) is the top-left, and th
stevenjb 2016/06/23 19:11:01 The intention is that these will be immediately ov
michaelpg 2016/06/24 20:25:10 If you use Array.prototype.reduce you wouldn't hav
stevenjb 2016/06/24 20:59:51 Interesting. I can see how that would be useful, b
105
106 for (let display of this.displays) {
107 var bounds = this.boundsMap_[display.id];
108 displayInfoBoundingBox.left =
109 Math.min(displayInfoBoundingBox.left, bounds.left);
110 displayInfoBoundingBox.right =
111 Math.max(displayInfoBoundingBox.right, bounds.left + bounds.width);
112 displayInfoBoundingBox.top =
113 Math.min(displayInfoBoundingBox.top, bounds.top);
114 displayInfoBoundingBox.bottom =
115 Math.max(displayInfoBoundingBox.bottom, bounds.top + bounds.height);
116 maxWidth = Math.max(maxWidth, bounds.width);
117 maxHeight = Math.max(maxHeight, bounds.height);
118 }
119
120 // Create a margin around the bounding box equal to the size of the
121 // largest display.
michaelpg 2016/06/23 04:29:34 display(s) -- e.g., a landscape display and a port
stevenjb 2016/06/23 19:11:01 Done.
122 var displayInfoBoundsWidth =
123 displayInfoBoundingBox.right - displayInfoBoundingBox.left +
124 maxWidth * 2;
125 var displayInfoBoundsHeight =
126 displayInfoBoundingBox.bottom - displayInfoBoundingBox.top +
127 maxHeight * 2;
128
129 // Calculate the scale.
130 var horizontalScale = displayAreaDiv.offsetWidth / displayInfoBoundsWidth;
131 var verticalScale = displayAreaDiv.offsetHeight / displayInfoBoundsHeight;
132 var scale = Math.min(horizontalScale, verticalScale);
133
134 // Calculate the offset.
135 this.visualOffset_.left = (-displayInfoBoundingBox.left + maxWidth) * scale;
136 this.visualOffset_.top = (-displayInfoBoundingBox.top + maxHeight) * scale;
137
138 // Update the scale which will trigger calls to getDivStyle_.
139 this.visualScale = Math.max(MIN_VISUAL_SCALE, scale);
140
141 return true;
142 },
143
144 /**
145 * @param {!chrome.system.display.DisplayUnitInfo} display
146 * @param {number} visualScale
147 * @return {string} The style string for the div.
148 * @private
149 */
150 getDivStyle_: function(display, visualScale) {
151 /** @const {number} */ var BORDER = 2;
michaelpg 2016/06/23 04:29:35 why 2, when the border with on .display is 1?
stevenjb 2016/06/23 19:11:01 It has a box shadow of width 2. Added a comment.
152 var bounds = this.boundsMap_[display.id];
153 var height = Math.round(bounds.height * this.visualScale) - BORDER * 2;
michaelpg 2016/06/23 04:29:35 I think using box-sizing: border-box on these divs
stevenjb 2016/06/23 19:11:01 Alas, your newfangled CSS property doesn't appear
154 var width = Math.round(bounds.width * this.visualScale) - BORDER * 2;
155 var left =
156 this.visualOffset_.left + Math.round(bounds.left * this.visualScale);
michaelpg 2016/06/23 04:29:34 why round the 2nd term but not the offset?
stevenjb 2016/06/23 19:11:01 Good catch. Fixed.
157 var top =
158 this.visualOffset_.top + Math.round(bounds.top * this.visualScale);
159 var style = 'height:' + height + 'px;' + 'width:' + width + 'px;' +
michaelpg 2016/06/23 04:29:35 i think this is a great use case for es6 template
stevenjb 2016/06/23 19:11:01 Cute. Closure is fine with it. Done.
160 'left:' + left + 'px;' + 'top:' + top + 'px;';
161 return style;
162 },
163
164 /**
165 * @param {!chrome.system.display.DisplayUnitInfo} display
166 * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
167 * @return {boolean}
168 * @private
169 */
170 isSelected_: function(display, selectedDisplay) {
171 return display.id == selectedDisplay.id;
172 },
173
174 /**
175 * @param {!{model: !{index: number}, target: !PaperButtonElement}} e
michaelpg 2016/06/23 04:29:35 meh, remove unused target property info
stevenjb 2016/06/23 19:11:01 Done.
176 * @private
177 */
178 onSelectDisplayTap_: function(e) {
179 this.fire('select-display', e.model.index);
180 },
181
182 /**
183 * Recursively calculate the bounds of a display relative to its parents.
184 * Caches the display bounds so that parent bounds are only calculated once.
185 * TODO(stevenjb): Move this function and the maps it requires to a separate
186 * behavior which will include snapping and collisions.
187 * @param {!chrome.system.display.DisplayUnitInfo} display
188 * @return {!chrome.system.display.Bounds}
189 * @private
190 */
191 calcDisplayBounds_: function(display) {
192 var left, top;
193 if (display.isPrimary) {
194 left = -display.bounds.width / 2;
195 top = -display.bounds.height / 2;
196 } else {
197 var layout = this.layoutMap_[display.id];
198 var parentDisplay = this.displayMap_[layout.parentId];
199 var parentBounds;
200 if (parentDisplay.id in this.boundsMap_)
201 parentBounds = this.boundsMap_[parentDisplay.id];
202 else
203 parentBounds = this.calcDisplayBounds_(parentDisplay);
204 left = parentBounds.left;
205 top = parentBounds.top;
206 switch (layout.position) {
207 case chrome.system.display.LayoutPosition.TOP:
208 top -= display.bounds.height;
209 break;
210 case chrome.system.display.LayoutPosition.RIGHT:
211 left += parentBounds.width;
212 break;
213 case chrome.system.display.LayoutPosition.BOTTOM:
214 top += parentBounds.height;
215 break;
216 case chrome.system.display.LayoutPosition.LEFT:
217 left -= display.bounds.height;
218 break;
219 }
220 }
221 var result = {
222 left: left,
223 top: top,
224 width: display.bounds.width,
225 height: display.bounds.height
226 };
227 this.boundsMap_[display.id] = result;
228 return result;
229 }
230 });
231
232 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698