OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 cr.define('print_preview', function() { | 5 cr.define('print_preview', function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 /** | 8 /** |
9 * Creates a Margins object that holds four margin values. The units in which | |
10 * the values are expressed can be any numeric value. | |
11 * @constructor | |
12 * @param {number} left The left margin. | |
13 * @param {number} top The top margin. | |
14 * @param {number} right The right margin. | |
15 * @param {number} bottom The bottom margin. | |
16 */ | |
17 function Margins(left, top, right, bottom) { | |
18 this[MarginSettings.LEFT_GROUP] = left; | |
19 this[MarginSettings.TOP_GROUP] = top; | |
20 this[MarginSettings.RIGHT_GROUP] = right; | |
21 this[MarginSettings.BOTTOM_GROUP] = bottom; | |
22 } | |
23 | |
24 /** | |
25 * Rounds |value| keeping |precision| decimal numbers. Example: 32.76643 | |
26 * becomes 32.77. | |
27 * @param {number} value The number to round. | |
28 * @param {number} precision The desired precision. | |
29 * @return {number} The rounded number. | |
30 */ | |
31 Margins.roundToPrecision = function(value, precision) { | |
32 return Math.round(value * Math.pow(10, precision)) / | |
33 Math.pow(10, precision); | |
34 } | |
35 | |
36 Margins.prototype = { | |
37 /** | |
38 * Checks if |rhs| is equal to |this|. | |
39 * @param {Margins} rhs The Margins object to compare against. | |
40 * @return {boolean} true if they are equal. | |
41 */ | |
42 isEqual: function(rhs) { | |
43 return this[MarginSettings.TOP_GROUP] === rhs[MarginSettings.TOP_GROUP] && | |
44 this[MarginSettings.LEFT_GROUP] === rhs[MarginSettings.LEFT_GROUP] && | |
45 this[MarginSettings.RIGHT_GROUP] === | |
46 rhs[MarginSettings.RIGHT_GROUP] && | |
47 this[MarginSettings.BOTTOM_GROUP] === | |
48 rhs[MarginSettings.BOTTOM_GROUP]; | |
49 }, | |
50 | |
51 /** | |
52 * Copies the four margin values from |rhs|. | |
53 * @param {Margins} rhs The Margins object values to be used. | |
54 */ | |
55 copy: function(rhs) { | |
56 this[MarginSettings.TOP_GROUP] = rhs[MarginSettings.TOP_GROUP]; | |
57 this[MarginSettings.LEFT_GROUP] = rhs[MarginSettings.LEFT_GROUP]; | |
58 this[MarginSettings.RIGHT_GROUP] = rhs[MarginSettings.RIGHT_GROUP]; | |
59 this[MarginSettings.BOTTOM_GROUP] = rhs[MarginSettings.BOTTOM_GROUP]; | |
60 }, | |
61 | |
62 /** | |
63 * Converts |this| to inches and returns the result in a new Margins object. | |
64 * |this| is not affected. It assumes that |this| is currently expressed in | |
65 * points. | |
66 * @param {number} The number of decimal points to keep. | |
67 * @return {Margins} The equivalent of |this| in inches. | |
68 */ | |
69 toInches: function(precision) { | |
70 return new Margins( | |
71 Margins.roundToPrecision(convertPointsToInches( | |
72 this[MarginSettings.LEFT_GROUP]), precision), | |
73 Margins.roundToPrecision(convertPointsToInches( | |
74 this[MarginSettings.TOP_GROUP]), precision), | |
75 Margins.roundToPrecision(convertPointsToInches( | |
76 this[MarginSettings.RIGHT_GROUP]), precision), | |
77 Margins.roundToPrecision(convertPointsToInches( | |
78 this[MarginSettings.BOTTOM_GROUP]), precision) | |
79 ); | |
80 } | |
81 }; | |
82 | |
83 /** | |
84 * @constructor | |
85 * Class describing the layout of the page. | |
86 */ | |
87 function PageLayout(width, height, left, top, right, bottom) { | |
88 this.contentWidth_ = width; | |
89 this.contentHeight_ = height; | |
90 this.margins_ = new Margins(left, top, right, bottom); | |
91 } | |
92 | |
93 PageLayout.prototype = { | |
94 /** | |
95 * @type {number} The width of the page. | |
96 */ | |
97 get pageWidth() { | |
98 return this.margins_.left + this.margins_.right + this.contentWidth_; | |
99 }, | |
100 | |
101 /** | |
102 * @type {number} The height of the page. | |
103 */ | |
104 get pageHeight() { | |
105 return this.margins_.top + this.margins_.bottom + this.contentHeight_; | |
106 } | |
107 }; | |
108 | |
109 /** | |
9 * Creates a MarginSettings object. This object encapsulates all settings and | 110 * Creates a MarginSettings object. This object encapsulates all settings and |
10 * logic related to the margins mode. | 111 * logic related to the margins mode. |
11 * @constructor | 112 * @constructor |
12 */ | 113 */ |
13 function MarginSettings() { | 114 function MarginSettings() { |
14 this.marginsOption_ = $('margins-option'); | 115 this.marginsOption_ = $('margins-option'); |
15 this.marginList_ = $('margin-list'); | 116 this.marginList_ = $('margin-list'); |
16 // Holds the custom left margin value (if set). | 117 this.marginsUI_ = null; |
17 this.customMarginLeft_ = -1; | 118 |
18 // Holds the custom right margin value (if set). | 119 // Holds the custom margin values in points (if set). |
19 this.customMarginRight_ = -1; | 120 this.customMargins_ = new Margins(-1, -1, -1, -1); |
20 // Holds the custom top margin value (if set). | 121 // Holds the previous custom margin values in points. |
21 this.customMarginTop_ = -1; | 122 this.previousCustomMargins_ = new Margins(-1, -1, -1, -1); |
22 // Holds the custom bottom margin value (if set). | 123 // Holds the width of the page in points. |
23 this.customMarginBottom_ = -1; | 124 this.pageWidth_ = -1; |
24 // Margin list values. | 125 // Holds the height of the page in points. |
25 this.customMarginsValue_ = 2; | 126 this.pageHeight_ = -1; |
26 this.defaultMarginsValue_ = 0; | 127 // The last selected margin option. |
27 this.noMarginsValue_ = 1; | 128 this.lastSelectedOption_ = MarginSettings.MARGINS_VALUE_DEFAULT; |
28 // Default Margins option index. | 129 |
29 this.defaultMarginsIndex_ = 0; | 130 // Holds the currently updated default page layout values. |
131 this.currentDefaultPageLayout = null; | |
132 // Holds the default page layout values when the custom margins was last | |
133 // selected. | |
134 this.previousDefaultPageLayout_ = null; | |
135 | |
136 // True if the margins UI should be shown regardless of mouse position. | |
137 this.forceDisplayingMarginLines_ = true; | |
30 } | 138 } |
31 | 139 |
140 // Number of points per inch. | |
141 MarginSettings.POINTS_PER_INCH = 72; | |
142 // Margin list values. | |
143 MarginSettings.MARGINS_VALUE_DEFAULT = 0; | |
144 MarginSettings.MARGINS_VALUE_NO_MARGINS = 1; | |
145 MarginSettings.MARGINS_VALUE_CUSTOM = 2; | |
146 // Default Margins option index. | |
147 MarginSettings.DEFAULT_MARGINS_OPTION_INDEX = 0; | |
148 // Group name corresponding to the top margin. | |
149 MarginSettings.TOP_GROUP = 'top'; | |
150 // Group name corresponding to the left margin. | |
151 MarginSettings.LEFT_GROUP = 'left'; | |
152 // Group name corresponding to the right margin. | |
153 MarginSettings.RIGHT_GROUP = 'right'; | |
154 // Group name corresponding to the bottom margin. | |
155 MarginSettings.BOTTOM_GROUP = 'bottom'; | |
156 | |
32 cr.addSingletonGetter(MarginSettings); | 157 cr.addSingletonGetter(MarginSettings); |
33 | 158 |
34 MarginSettings.prototype = { | 159 MarginSettings.prototype = { |
35 /** | 160 /** |
36 * The selection list corresponding to the margins option. | |
37 * @return {HTMLInputElement} | |
38 */ | |
39 get marginList() { | |
40 return this.marginList_; | |
41 }, | |
42 | |
43 /** | |
44 * Returns a dictionary of the four custom margin values. | 161 * Returns a dictionary of the four custom margin values. |
45 * @return {object} | 162 * @return {object} |
46 */ | 163 */ |
47 get customMargins() { | 164 get customMargins() { |
48 return {'marginLeft': this.customMarginLeft_, | 165 var margins = {}; |
49 'marginTop': this.customMarginTop_, | 166 margins.marginLeft = this.customMargins_.left; |
50 'marginRight': this.customMarginRight_, | 167 margins.marginTop = this.customMargins_.top; |
51 'marginBottom': this.customMarginBottom_}; | 168 margins.marginRight = this.customMargins_.right; |
169 margins.marginBottom = this.customMargins_.bottom; | |
170 return margins; | |
52 }, | 171 }, |
53 | 172 |
54 /** | 173 /** |
55 * Gets the value of the selected margin option. | 174 * @return {number} The value of the selected margin option. |
56 * @private | 175 * @private |
57 * @return {number} | |
58 */ | 176 */ |
59 get selectedMarginsValue_() { | 177 get selectedMarginsValue_() { |
60 return this.marginList_.options[this.marginList_.selectedIndex].value; | 178 return this.marginList_.options[this.marginList_.selectedIndex].value; |
61 }, | 179 }, |
62 | 180 |
63 /** | 181 /** |
64 * Checks whether user has selected the Default Margins option or not. | 182 * @return {boolean} True if default margins are selected. |
65 * | |
66 * @return {boolean} true if default margins are selected. | |
67 */ | 183 */ |
68 isDefaultMarginsSelected: function() { | 184 isDefaultMarginsSelected: function() { |
69 return this.selectedMarginsValue_ == this.defaultMarginsValue_; | 185 return this.selectedMarginsValue_ == MarginSettings.MARGINS_VALUE_DEFAULT; |
70 }, | 186 }, |
71 | 187 |
72 /** | 188 /** |
73 * Adds listeners to all margin related controls. The listeners take care | 189 * @return {boolean} True if no margins are selected. |
74 * of altering their behavior depending on |hasPendingPreviewRequest|. | 190 */ |
191 isNoMarginsSelected: function() { | |
192 return this.selectedMarginsValue_ == | |
193 MarginSettings.MARGINS_VALUE_NO_MARGINS; | |
194 }, | |
195 | |
196 /** | |
197 * @return {boolean} True if custom margins are selected. | |
198 */ | |
199 isCustomMarginsSelected: function() { | |
200 return this.selectedMarginsValue_ == MarginSettings.MARGINS_VALUE_CUSTOM; | |
201 }, | |
202 | |
203 /** | |
204 * If the custom margin values have changed then request a new preview based | |
205 * on the newly set margins. | |
206 * @private | |
207 */ | |
208 requestPreviewIfNeeded_: function() { | |
209 if (!this.areMarginSettingsValid()) | |
210 return; | |
211 if (this.customMargins_.toInches(2).isEqual( | |
212 this.previousCustomMargins_.toInches(2))) { | |
213 return; | |
214 } | |
215 this.previousCustomMargins_.copy(this.customMargins_); | |
216 setDefaultValuesAndRegeneratePreview(false); | |
217 }, | |
218 | |
219 /** | |
220 * Listener executed when the mouse is over the sidebar. If the custom | |
221 * margin lines are displayed, then, it fades them out. | |
222 * @private | |
223 */ | |
224 onSidebarMouseOver_: function(e) { | |
225 if (!this.forceDisplayingMarginLines_) | |
226 this.marginsUI.hide(); | |
227 }, | |
228 | |
229 /** | |
230 * Listener executed when the mouse is over the main view. If the custom | |
231 * margin lines are hidden, then, it fades them in. | |
232 * @private | |
233 */ | |
234 onMainviewMouseOver_: function() { | |
235 this.forceDisplayingMarginLines_ = false; | |
236 this.marginsUI.show(); | |
237 }, | |
238 | |
239 /** | |
240 * Adds listeners to all margin related controls. | |
75 */ | 241 */ |
76 addEventListeners: function() { | 242 addEventListeners: function() { |
77 this.marginList_.onchange = this.onMarginsChanged_.bind(this); | 243 this.marginList_.onchange = this.onMarginsChanged_.bind(this); |
78 document.addEventListener('PDFLoaded', this.onPDFLoaded_.bind(this)); | 244 document.addEventListener('PDFLoaded', this.onPDFLoaded_.bind(this)); |
79 }, | 245 }, |
80 | 246 |
81 /** | 247 /** |
82 * Listener executing when user selects a different margin option, ie, | 248 * @return {boolean} True if the margin settings are valid. |
83 * |this.marginList_| is changed. | 249 */ |
250 areMarginSettingsValid: function() { | |
251 if (this.marginsUI_ == null) | |
252 return true; | |
253 | |
254 var pairs = this.marginsUI.pairsAsList; | |
255 for (var i = 0; i < pairs.length; i++) { | |
Evan Stade
2011/10/07 03:29:58
return pairs.every(function(pair) {
return pair.
dpapad
2011/10/07 16:49:20
Done.
| |
256 if (!pairs[i].box_.isValid) | |
257 return false; | |
258 } | |
259 return true; | |
260 }, | |
261 | |
262 /** | |
263 * Calculates the maximum allowable value of the selected margin text for | |
264 * every margin. | |
265 * @return {array} The maximum allowable value in order top, left, right, | |
266 * bottom. | |
267 * @private | |
268 */ | |
269 getMarginValueLimits_: function() { | |
270 var marginValueLimits = []; | |
271 marginValueLimits[0] = this.pageHeight_ - this.customMargins_.bottom; | |
272 marginValueLimits[1] = this.pageWidth_ - this.customMargins_.right; | |
273 marginValueLimits[2] = this.pageWidth_ - this.customMargins_.left; | |
274 marginValueLimits[3] = this.pageHeight_ - this.customMargins_.top; | |
275 return marginValueLimits; | |
276 }, | |
277 | |
278 /** | |
279 * When the user stops typing in the margin text box a new print preview is | |
280 * requested, only if | |
281 * 1) The input is compeletely valid (it can be parsed in its entirety). | |
Evan Stade
2011/10/07 03:29:58
indent the list
dpapad
2011/10/07 16:49:20
Done.
| |
282 * 2) The newly selected margins differ from the previous selected margins. | |
283 * @param {cr.Event} event The change event holding information about what | |
284 * changed. | |
285 * @private | |
286 */ | |
287 onMarginTextValueMayHaveChanged_: function(event) { | |
288 var marginBox = event.target; | |
289 var marginBoxValue = convertInchesToPoints(marginBox.margin); | |
290 this.customMargins_[marginBox.marginGroup] = marginBoxValue; | |
291 this.requestPreviewIfNeeded_(); | |
292 }, | |
293 | |
294 /** | |
295 * @type {print_preview.MarginsUI} The object holding the UI for specifying | |
296 * custom margins. | |
297 */ | |
298 get marginsUI() { | |
299 if (!this.marginsUI_) { | |
300 this.marginsUI_ = new print_preview.MarginsUI($('mainview')); | |
301 this.marginsUI_.addObserver( | |
302 this.onMarginTextValueMayHaveChanged_.bind(this)); | |
303 } | |
304 return this.marginsUI_; | |
305 }, | |
306 | |
307 /** | |
308 * Adds listeners when the custom margins option is selected. | |
309 * @private | |
310 */ | |
311 addCustomMarginEventListeners_: function() { | |
312 $('mainview').onmouseover = this.onMainviewMouseOver_.bind(this); | |
313 $('sidebar').onmouseover = this.onSidebarMouseOver_.bind(this); | |
314 }, | |
315 | |
316 /** | |
317 * Removes the event listeners associated with the custom margins option. | |
318 * @private | |
319 */ | |
320 removeCustomMarginEventListeners_: function() { | |
321 $('mainview').onmouseover = null; | |
322 $('sidebar').onmouseover = null; | |
323 this.marginsUI.hide(); | |
324 }, | |
325 | |
326 /** | |
327 * Updates |this.marginsUI| depending on the specified margins and the | |
328 * position of the page within the plugin. | |
329 * @private | |
330 */ | |
331 drawCustomMarginsUI_: function() { | |
332 // TODO(dpapad): find out why passing |!this.areMarginsSettingsValid()| | |
333 // directly produces the opposite value even though | |
334 // |this.getMarginsRectangleInPercent_()| and | |
335 // |this.getMarginValueLimits_()| have no side effects. | |
336 var keepDisplayedValue = !this.areMarginSettingsValid(); | |
337 this.marginsUI.update(this.getMarginsRectangleInPercent_(), | |
338 this.customMargins_, | |
339 this.getMarginValueLimits_(), | |
340 keepDisplayedValue); | |
341 this.marginsUI.draw(); | |
342 }, | |
343 | |
344 /** | |
345 * Called when there is change in the preview position or size. | |
346 */ | |
347 onPreviewPositionChanged: function() { | |
348 if (this.isCustomMarginsSelected() && previewArea.pdfLoaded && | |
349 pageSettings.totalPageCount != undefined) { | |
350 this.drawCustomMarginsUI_(); | |
351 } | |
352 }, | |
353 | |
354 /** | |
355 * Executes when user selects a different margin option, ie, | |
356 * |this.marginList_.selectedIndex| is changed. | |
84 * @private | 357 * @private |
85 */ | 358 */ |
86 onMarginsChanged_: function() { | 359 onMarginsChanged_: function() { |
87 if (this.selectedMarginsValue_ == this.defaultMarginsValue_) { | 360 if (this.isDefaultMarginsSelected()) |
88 setDefaultValuesAndRegeneratePreview(false); | 361 this.onDefaultMarginsSelected_(); |
89 } else if (this.selectedMarginsValue_ == this.noMarginsValue_) { | 362 else if (this.isNoMarginsSelected()) |
90 this.customMarginLeft_ = 0; | 363 this.onNoMarginsSelected_(); |
91 this.customMarginTop_ = 0; | 364 else if (this.isCustomMarginsSelected()) |
92 this.customMarginRight_ = 0; | 365 this.onCustomMarginsSelected_(); |
93 this.customMarginBottom_ = 0; | 366 |
94 setDefaultValuesAndRegeneratePreview(false); | 367 this.lastSelectedOption_ = this.selectedMarginsValue_; |
95 } | 368 }, |
96 // TODO(aayushkumar): Add handler for custom margins | 369 |
370 /** | |
371 * Executes when the default margins option is selected. | |
372 * @private | |
373 */ | |
374 onDefaultMarginsSelected_: function() { | |
375 this.removeCustomMarginEventListeners_(); | |
376 this.forceDisplayingMarginLines_ = true; | |
377 setDefaultValuesAndRegeneratePreview(false); | |
378 }, | |
379 | |
380 /** | |
381 * Executes when the no margins option is selected. | |
382 * @private | |
383 */ | |
384 onNoMarginsSelected_: function() { | |
385 this.removeCustomMarginEventListeners_(); | |
386 this.forceDisplayingMarginLines_ = true; | |
387 this.customMargins_ = new Margins(0, 0, 0, 0); | |
388 setDefaultValuesAndRegeneratePreview(false); | |
389 }, | |
390 | |
391 /** | |
392 * Executes when the custom margins option is selected. | |
393 * @private | |
394 */ | |
395 onCustomMarginsSelected_: function() { | |
396 this.addCustomMarginEventListeners_(); | |
397 | |
398 if (this.lastSelectedOption_ == MarginSettings.MARGINS_VALUE_DEFAULT) | |
399 this.customMargins_ = this.currentDefaultPageLayout.margins_; | |
400 this.previousCustomMargins_.copy(this.customMargins_); | |
401 | |
402 if (this.previousDefaultPageLayout_ != this.currentDefaultPageLayout) { | |
403 this.pageWidth_ = this.currentDefaultPageLayout.pageWidth; | |
404 this.pageHeight_ = this.currentDefaultPageLayout.pageHeight; | |
405 } | |
406 | |
407 this.previousDefaultPageLayout_ = this.currentDefaultPageLayout; | |
408 this.drawCustomMarginsUI_(); | |
409 this.marginsUI.show(); | |
410 }, | |
411 | |
412 /** | |
413 * Calculates the coordinates of the four margin lines. These are the | |
414 * coordinates where the margin lines should be displayed. The coordinates | |
415 * are expressed in terms of percentages with respect to the total width | |
416 * and height of the plugin. | |
417 * @private | |
Evan Stade
2011/10/07 03:29:58
.
dpapad
2011/10/07 16:49:20
?
| |
418 * @return {print_preview.Rect} A rectnangle that describes the position of | |
419 * the four margin lines. | |
420 */ | |
421 getMarginsRectangleInPercent_: function() { | |
422 var pageLocation = previewArea.getPageLocationNormalized(); | |
423 var marginsInPercent = this.getMarginsInPercent_(); | |
424 var leftX = pageLocation.x + marginsInPercent.left; | |
425 var topY = pageLocation.y + marginsInPercent.top; | |
426 var contentWidth = pageLocation.width - (marginsInPercent.left + | |
427 marginsInPercent.right); | |
428 var contentHeight = pageLocation.height - (marginsInPercent.top + | |
429 marginsInPercent.bottom); | |
430 return new print_preview.Rect( | |
431 leftX, topY, contentWidth, contentHeight); | |
432 }, | |
433 | |
434 /** | |
435 * @private | |
Evan Stade
2011/10/07 03:29:58
.
dpapad
2011/10/07 16:49:20
?
| |
436 * @return {print_preview.Margins} The currently selected margin values | |
437 * normalized to the total width and height of the plugin. | |
438 */ | |
439 getMarginsInPercent_: function() { | |
440 var pageInformation = previewArea.getPageLocationNormalized(); | |
441 var totalWidthInPoints = this.pageWidth_ / pageInformation.width; | |
442 var totalHeightInPoints = this.pageHeight_ / pageInformation.height; | |
443 var marginsInPercent = new Margins( | |
444 this.customMargins_.left / totalWidthInPoints, | |
445 this.customMargins_.top / totalHeightInPoints, | |
446 this.customMargins_.right / totalWidthInPoints, | |
447 this.customMargins_.bottom / totalHeightInPoints); | |
448 return marginsInPercent; | |
97 }, | 449 }, |
98 | 450 |
99 /** | 451 /** |
100 * If custom margins is the currently selected option then change to the | 452 * If custom margins is the currently selected option then change to the |
101 * default margins option. | 453 * default margins option. |
454 * @private | |
102 */ | 455 */ |
103 resetMarginsIfNeeded: function() { | 456 resetMarginsIfNeeded: function() { |
104 if (this.selectedMarginsValue_ == this.customMarginsValue_) | 457 if (this.isCustomMarginsSelected()) { |
105 this.marginList_.options[this.defaultMarginsIndex_].selected = true; | 458 this.marginList_.options[ |
106 }, | 459 MarginSettings.DEFAULT_MARGINS_OPTION_INDEX].selected = true; |
107 | 460 this.removeCustomMarginEventListeners_(); |
108 /** | 461 this.lastSelectedOption_ = MarginSettings.MARGINS_VALUE_DEFAULT; |
109 * Listener executing when a PDFLoaded event occurs. | 462 } |
463 }, | |
464 | |
465 /** | |
466 * Executes when a PDFLoaded event occurs. | |
110 * @private | 467 * @private |
111 */ | 468 */ |
112 onPDFLoaded_: function() { | 469 onPDFLoaded_: function() { |
113 if (!previewModifiable) | 470 if (!previewModifiable) |
114 fadeOutElement(this.marginsOption_); | 471 fadeOutElement(this.marginsOption_); |
115 } | 472 } |
116 }; | 473 }; |
117 | 474 |
118 return { | 475 return { |
119 MarginSettings: MarginSettings, | 476 MarginSettings: MarginSettings, |
477 PageLayout: PageLayout, | |
120 }; | 478 }; |
121 }); | 479 }); |
OLD | NEW |