| OLD | NEW |
| 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 * settings-slider wraps a paper-slider. It maps the slider's values from a | 7 * settings-slider wraps a paper-slider. It maps the slider's values from a |
| 8 * linear UI range to a range of real values. When |value| does not map exactly | 8 * linear UI range to a range of real values. When |value| does not map exactly |
| 9 * to a tick mark, it interpolates to the nearest tick. | 9 * to a tick mark, it interpolates to the nearest tick. |
| 10 * | 10 * |
| 11 * Unlike paper-slider, there is no distinction between value and | 11 * Unlike paper-slider, there is no distinction between value and |
| 12 * immediateValue; when either changes, the |value| property is updated. | 12 * immediateValue; when either changes, the |value| property is updated. |
| 13 */ | 13 */ |
| 14 Polymer({ | 14 Polymer({ |
| 15 is: 'settings-slider', | 15 is: 'settings-slider', |
| 16 | 16 |
| 17 behaviors: [CrPolicyPrefBehavior], | 17 behaviors: [CrPolicyPrefBehavior], |
| 18 | 18 |
| 19 properties: { | 19 properties: { |
| 20 /** @type {?settings.DirectionDelegate} */ |
| 21 directionDelegate: { |
| 22 observer: 'directionDelegateChanged_', |
| 23 type: Object, |
| 24 value: new settings.DirectionDelegateImpl(), |
| 25 }, |
| 26 |
| 20 /** @type {!chrome.settingsPrivate.PrefObject} */ | 27 /** @type {!chrome.settingsPrivate.PrefObject} */ |
| 21 pref: Object, | 28 pref: Object, |
| 22 | 29 |
| 23 /** @type {!Array<number>} Values corresponding to each tick. */ | 30 /** @type {!Array<number>} Values corresponding to each tick. */ |
| 24 tickValues: {type: Array, value: []}, | 31 tickValues: {type: Array, value: []}, |
| 25 | 32 |
| 26 min: Number, | 33 min: Number, |
| 27 | 34 |
| 28 max: Number, | 35 max: Number, |
| 29 | 36 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 45 ], | 52 ], |
| 46 | 53 |
| 47 /** | 54 /** |
| 48 * Sets the |pref.value| property to the value corresponding to the knob | 55 * Sets the |pref.value| property to the value corresponding to the knob |
| 49 * position after a user action. | 56 * position after a user action. |
| 50 * @private | 57 * @private |
| 51 */ | 58 */ |
| 52 onSliderChanged_: function() { | 59 onSliderChanged_: function() { |
| 53 var newValue; | 60 var newValue; |
| 54 if (this.tickValues && this.tickValues.length > 0) | 61 if (this.tickValues && this.tickValues.length > 0) |
| 55 newValue = this.tickValues[this.$.slider.immediateValue]; | 62 newValue = |
| 63 this.tickValues[this.convertValue_(this.$.slider.immediateValue)]; |
| 56 else | 64 else |
| 57 newValue = this.$.slider.immediateValue; | 65 newValue = this.convertValue_(this.$.slider.immediateValue); |
| 58 | 66 |
| 59 this.set('pref.value', newValue); | 67 this.set('pref.value', newValue); |
| 60 }, | 68 }, |
| 61 | 69 |
| 62 /** @private */ | 70 /** @private */ |
| 63 computeDisableSlider_: function() { | 71 computeDisableSlider_: function() { |
| 64 return this.disabled || this.isPrefEnforced(); | 72 return this.disabled || this.isPrefEnforced(); |
| 65 }, | 73 }, |
| 66 | 74 |
| 67 /** | 75 /** |
| 76 * Convert to/from the slider value and the preference value. |
| 77 * TODO(dschuyler): This is a workaround for paper-slider which doesn't |
| 78 * currently handle RTL. It'd be better to convert at a lower level. |
| 79 * @private |
| 80 */ |
| 81 convertValue_: function(sliderValue) { |
| 82 return (this.directionDelegate.isRtl() && this.tickValues) ? |
| 83 this.tickValues.length - 1 - sliderValue : |
| 84 sliderValue; |
| 85 }, |
| 86 |
| 87 /** |
| 68 * Updates the knob position when |pref.value| changes. If the knob is still | 88 * Updates the knob position when |pref.value| changes. If the knob is still |
| 69 * being dragged, this instead forces |pref.value| back to the current | 89 * being dragged, this instead forces |pref.value| back to the current |
| 70 * position. | 90 * position. |
| 71 * @private | 91 * @private |
| 72 */ | 92 */ |
| 73 valueChanged_: function() { | 93 valueChanged_: function() { |
| 74 // If |tickValues| is empty, simply set current value to the slider. | 94 // If |tickValues| is empty, simply set current value to the slider. |
| 75 if (this.tickValues.length == 0) { | 95 if (this.tickValues.length == 0) { |
| 76 this.$.slider.value = this.pref.value; | 96 this.$.slider.value = this.convertValue_(this.pref.value); |
| 77 return; | 97 return; |
| 78 } | 98 } |
| 79 | 99 |
| 80 // First update the slider settings if |tickValues| was set. | 100 // First update the slider settings if |tickValues| was set. |
| 81 var numTicks = Math.max(1, this.tickValues.length); | 101 var numTicks = Math.max(1, this.tickValues.length); |
| 82 this.$.slider.max = numTicks - 1; | 102 this.$.slider.max = numTicks - 1; |
| 83 // Limit the number of ticks to 10 to keep the slider from looking too busy. | 103 // Limit the number of ticks to 10 to keep the slider from looking too busy. |
| 84 /** @const */ var MAX_TICKS = 10; | 104 /** @const */ var MAX_TICKS = 10; |
| 85 this.$.slider.snaps = numTicks < MAX_TICKS; | 105 this.$.slider.snaps = numTicks < MAX_TICKS; |
| 86 this.$.slider.maxMarkers = numTicks < MAX_TICKS ? numTicks : 0; | 106 this.$.slider.maxMarkers = numTicks < MAX_TICKS ? numTicks : 0; |
| 87 | 107 |
| 88 if (this.$.slider.dragging && this.tickValues.length > 0 && | 108 if (this.$.slider.dragging && this.tickValues.length > 0 && |
| 89 this.pref.value != this.tickValues[this.$.slider.immediateValue]) { | 109 this.pref.value != this.tickValues[this.$.slider.immediateValue]) { |
| 90 // The value changed outside settings-slider but we're still holding the | 110 // The value changed outside settings-slider but we're still holding the |
| 91 // knob, so set the value back to where the knob was. | 111 // knob, so set the value back to where the knob was. |
| 92 // Async so we don't confuse Polymer's data binding. | 112 // Async so we don't confuse Polymer's data binding. |
| 93 this.async(function() { | 113 this.async(function() { |
| 94 var newValue = this.tickValues[this.$.slider.immediateValue]; | 114 var newValue = |
| 115 this.tickValues[this.convertValue_(this.$.slider.immediateValue)]; |
| 95 this.set('pref.value', newValue); | 116 this.set('pref.value', newValue); |
| 96 }); | 117 }); |
| 97 return; | 118 return; |
| 98 } | 119 } |
| 99 | 120 |
| 100 // Convert from the public |value| to the slider index (where the knob | 121 // Convert from the public |value| to the slider index (where the knob |
| 101 // should be positioned on the slider). | 122 // should be positioned on the slider). |
| 102 var sliderIndex = this.tickValues.length > 0 ? | 123 var sliderIndex = this.tickValues.length > 0 ? |
| 103 this.tickValues.indexOf(/** @type {number} */ (this.pref.value)) : | 124 this.tickValues.indexOf(/** @type {number} */ (this.pref.value)) : |
| 104 0; | 125 0; |
| 105 if (sliderIndex == -1) { | 126 if (sliderIndex == -1) { |
| 106 // No exact match. | 127 // No exact match. |
| 107 sliderIndex = this.findNearestIndex_( | 128 sliderIndex = this.findNearestIndex_( |
| 108 this.tickValues, | 129 this.tickValues, |
| 109 /** @type {number} */ (this.pref.value)); | 130 /** @type {number} */ (this.pref.value)); |
| 110 } | 131 } |
| 111 this.$.slider.value = sliderIndex; | 132 this.$.slider.value = this.convertValue_(sliderIndex); |
| 112 }, | 133 }, |
| 113 | 134 |
| 114 /** | 135 /** |
| 115 * Returns the index of the item in |arr| closest to |value|. | 136 * Returns the index of the item in |arr| closest to |value|. |
| 116 * @param {!Array<number>} arr | 137 * @param {!Array<number>} arr |
| 117 * @param {number} value | 138 * @param {number} value |
| 118 * @return {number} | 139 * @return {number} |
| 119 * @private | 140 * @private |
| 120 */ | 141 */ |
| 121 findNearestIndex_: function(arr, value) { | 142 findNearestIndex_: function(arr, value) { |
| 122 var closestIndex; | 143 var closestIndex; |
| 123 var minDifference = Number.MAX_VALUE; | 144 var minDifference = Number.MAX_VALUE; |
| 124 for (var i = 0; i < arr.length; i++) { | 145 for (var i = 0; i < arr.length; i++) { |
| 125 var difference = Math.abs(arr[i] - value); | 146 var difference = Math.abs(arr[i] - value); |
| 126 if (difference < minDifference) { | 147 if (difference < minDifference) { |
| 127 closestIndex = i; | 148 closestIndex = i; |
| 128 minDifference = difference; | 149 minDifference = difference; |
| 129 } | 150 } |
| 130 } | 151 } |
| 131 | 152 |
| 132 assert(typeof closestIndex != 'undefined'); | 153 assert(typeof closestIndex != 'undefined'); |
| 133 return closestIndex; | 154 return closestIndex; |
| 134 }, | 155 }, |
| 135 }); | 156 }); |
| OLD | NEW |