OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 cr.define('print_preview', function() { |
| 6 'use strict'; |
| 7 |
| 8 /** |
| 9 * Draggable control for setting a page margin. |
| 10 * |
| 11 * @param {print_preview.MarginControl.Orientation} orientation Orientation |
| 12 * of the margin control that determines where the margin textbox will be |
| 13 * placed. |
| 14 * @constructor |
| 15 * @extends {print_preview.Component} |
| 16 */ |
| 17 function MarginControl(orientation) { |
| 18 print_preview.Component.call(this); |
| 19 |
| 20 /** |
| 21 * Determines where the margin textbox will be placed. |
| 22 * @type {print_preview.MarginControl.Orientation} |
| 23 * @private |
| 24 */ |
| 25 this.orientation_ = orientation; |
| 26 |
| 27 this.positionInPts_ = 0; |
| 28 this.pageSize_ = new print_preview.Size(0, 0); |
| 29 this.scaleTransform_ = 1; |
| 30 this.translateTransform_ = new print_preview.Coordinate2d(0, 0); |
| 31 |
| 32 /** |
| 33 * Measurement system used in the print preview. |
| 34 * @type {!print_preview.MeasurementSystem} |
| 35 * @private |
| 36 */ |
| 37 this.measurementSystem_ = new print_preview.MeasurementSystem( |
| 38 ',', '.', print_preview.MeasurementSystem.UnitType.IMPERIAL); |
| 39 |
| 40 /** |
| 41 * Position of the margin control when dragging starts. |
| 42 * @type {print_preview.Coordinate2d} |
| 43 * @private |
| 44 */ |
| 45 this.marginStartPositionInPixels_ = null; |
| 46 |
| 47 /** |
| 48 * Position of the mouse when the dragging starts. |
| 49 * @type {print_preview.Coordinate2d} |
| 50 * @private |
| 51 */ |
| 52 this.mouseStartPositionInPixels_ = null; |
| 53 |
| 54 /** |
| 55 * Processing timeout for the textbox. |
| 56 * @type {Object} |
| 57 * @private |
| 58 */ |
| 59 this.textTimeout_ = null; |
| 60 }; |
| 61 |
| 62 /** |
| 63 * Enumeration of margin control orientations. |
| 64 * @enum {string} |
| 65 */ |
| 66 MarginControl.Orientation = { |
| 67 TOP: 'top', |
| 68 RIGHT: 'right', |
| 69 BOTTOM: 'bottom', |
| 70 LEFT: 'left' |
| 71 }; |
| 72 |
| 73 /** |
| 74 * Events dispatched by the margin control. |
| 75 * @enum {string} |
| 76 */ |
| 77 MarginControl.Event = { |
| 78 // Dispatched when the margin control starts dragging. |
| 79 DRAG_START: 'print_preview.MarginControl.DRAG_START', |
| 80 |
| 81 // Dispatched when the text in the margin control's textbox changes. |
| 82 TEXT_CHANGE: 'print_preview.MarginControl.TEXT_CHANGE' |
| 83 }; |
| 84 |
| 85 /** |
| 86 * CSS classes used by this component. |
| 87 * @enum {string} |
| 88 * @private |
| 89 */ |
| 90 MarginControl.Classes_ = { |
| 91 TOP: 'margin-control-top', |
| 92 RIGHT: 'margin-control-right', |
| 93 BOTTOM: 'margin-control-bottom', |
| 94 LEFT: 'margin-control-left', |
| 95 TEXTBOX: 'margin-control-textbox', |
| 96 INVALID: 'invalid', |
| 97 INVISIBLE: 'invisible' |
| 98 }; |
| 99 |
| 100 /** |
| 101 * Map from orientation to CSS class name. |
| 102 * @type {object.<MarginControl.Orientation, MarginControl.Classes_>} |
| 103 * @private |
| 104 */ |
| 105 MarginControl.OrientationToClass_ = {}; |
| 106 MarginControl.OrientationToClass_[MarginControl.Orientation.TOP] = |
| 107 MarginControl.Classes_.TOP; |
| 108 MarginControl.OrientationToClass_[MarginControl.Orientation.RIGHT] = |
| 109 MarginControl.Classes_.RIGHT; |
| 110 MarginControl.OrientationToClass_[MarginControl.Orientation.BOTTOM] = |
| 111 MarginControl.Classes_.BOTTOM; |
| 112 MarginControl.OrientationToClass_[MarginControl.Orientation.LEFT] = |
| 113 MarginControl.Classes_.LEFT; |
| 114 |
| 115 /** |
| 116 * Timeout in milliseconds before processing the value of the textbox. |
| 117 * @type {number} |
| 118 * @const |
| 119 * @private |
| 120 */ |
| 121 MarginControl.TEXTBOX_DELAY_ = 250; |
| 122 |
| 123 /** |
| 124 * Default precision used in the margin control. |
| 125 * @type {number} |
| 126 * @const |
| 127 * @private |
| 128 */ |
| 129 MarginControl.PRECISION_ = 3; |
| 130 |
| 131 MarginControl.prototype = { |
| 132 __proto__: print_preview.Component.prototype, |
| 133 |
| 134 get isInFocus() { |
| 135 return this.textbox_.focused; |
| 136 }, |
| 137 |
| 138 set measurementSystem(measurementSystem) { |
| 139 this.measurementSystem_ = measurementSystem; |
| 140 }, |
| 141 |
| 142 set scaleTransform(scaleTransform) { |
| 143 this.scaleTransform_ = scaleTransform; |
| 144 // Reset position |
| 145 this.positionInPts = this.positionInPts_; |
| 146 }, |
| 147 |
| 148 set translateTransform(translateTransform) { |
| 149 this.translateTransform_ = translateTransform; |
| 150 // Reset position |
| 151 this.positionInPts = this.positionInPts_; |
| 152 }, |
| 153 |
| 154 set pageSize(pageSize) { |
| 155 this.pageSize_ = pageSize; |
| 156 this.positionInPts = this.positionInPts_; |
| 157 }, |
| 158 |
| 159 get orientation() { |
| 160 return this.orientation_; |
| 161 }, |
| 162 |
| 163 /** @param {boolean} isVisible Whether the margin control is visible. */ |
| 164 set isVisible(isVisible) { |
| 165 if (isVisible) { |
| 166 this.getElement().classList.remove(MarginControl.Classes_.INVISIBLE); |
| 167 } else { |
| 168 this.getElement().classList.add(MarginControl.Classes_.INVISIBLE); |
| 169 } |
| 170 }, |
| 171 |
| 172 set isInError(isInError) { |
| 173 if (isInError) { |
| 174 this.textbox_.classList.add(MarginControl.Classes_.INVALID); |
| 175 } else { |
| 176 this.textbox_.classList.remove(MarginControl.Classes_.INVALID); |
| 177 } |
| 178 }, |
| 179 |
| 180 get positionInPts() { |
| 181 return this.positionInPts_; |
| 182 }, |
| 183 |
| 184 set positionInPts(posInPts) { |
| 185 this.positionInPts_ = posInPts; |
| 186 this.textbox_.value = |
| 187 this.measurementSystem_.convertFromPoints(posInPts). |
| 188 toPrecision(MarginControl.PRECISION_) + |
| 189 this.measurementSystem_.unitSymbol; |
| 190 var posInPixels; |
| 191 if (this.orientation_ == MarginControl.Orientation.TOP) { |
| 192 posInPixels = posInPts * this.scaleTransform_; |
| 193 posInPixels += this.translateTransform_.y; |
| 194 this.getElement().style.top = posInPixels + 'px'; |
| 195 } else if (this.orientation_ == MarginControl.Orientation.RIGHT) { |
| 196 posInPixels = this.pageSize_.width - posInPts; |
| 197 posInPixels *= this.scaleTransform_; |
| 198 posInPixels += this.translateTransform_.x; |
| 199 this.getElement().style.left = posInPixels + 'px'; |
| 200 } else if (this.orientation_ == MarginControl.Orientation.BOTTOM) { |
| 201 posInPixels = this.pageSize_.height - posInPts; |
| 202 posInPixels *= this.scaleTransform_; |
| 203 posInPixels += this.translateTransform_.y; |
| 204 this.getElement().style.top = posInPixels + 'px'; |
| 205 } else { |
| 206 posInPixels = posInPts * this.scaleTransform_; |
| 207 posInPixels += this.translateTransform_.x; |
| 208 this.getElement().style.left = posInPixels + 'px'; |
| 209 } |
| 210 }, |
| 211 |
| 212 convertPixelsToPts: function(pixels) { |
| 213 var pts; |
| 214 if (this.orientation_ == MarginControl.Orientation.TOP) { |
| 215 pts = pixels - this.translateTransform_.y; |
| 216 pts /= this.scaleTransform_; |
| 217 } else if (this.orientation_ == MarginControl.Orientation.RIGHT) { |
| 218 pts = pixels - this.translateTransform_.x; |
| 219 pts /= this.scaleTransform_; |
| 220 pts = this.pageSize_.width - pts; |
| 221 } else if (this.orientation_ == MarginControl.Orientation.BOTTOM) { |
| 222 pts = pixels - this.translateTransform_.y; |
| 223 pts /= this.scaleTransform_; |
| 224 pts = this.pageSize_.height - pts; |
| 225 } else { |
| 226 pts = pixels - this.translateTransform_.x; |
| 227 pts /= this.scaleTransform_; |
| 228 } |
| 229 return pts; |
| 230 }, |
| 231 |
| 232 /** |
| 233 * Translates the position of the margin control relative to the mouse |
| 234 * position in pixels. |
| 235 * @param {!print_preview.Coordinate2d} mousePosition New position of |
| 236 * the mouse. |
| 237 * @return {!print_preview.Coordinate2d} New position of the margin control. |
| 238 */ |
| 239 translateMouseToPositionInPixels: function(mousePosition) { |
| 240 return new print_preview.Coordinate2d( |
| 241 mousePosition.x - this.mouseStartPositionInPixels_.x + |
| 242 this.marginStartPositionInPixels_.x, |
| 243 mousePosition.y - this.mouseStartPositionInPixels_.y + |
| 244 this.marginStartPositionInPixels_.y); |
| 245 }, |
| 246 |
| 247 /** @override */ |
| 248 createDom: function() { |
| 249 this.setElementInternal(this.cloneTemplateInternal( |
| 250 'margin-control-template')); |
| 251 this.getElement().classList.add(MarginControl.OrientationToClass_[ |
| 252 this.orientation_]); |
| 253 }, |
| 254 |
| 255 /** @override */ |
| 256 enterDocument: function() { |
| 257 print_preview.Component.prototype.enterDocument.call(this); |
| 258 this.tracker.add( |
| 259 this.getElement(), 'mousedown', this.onMouseDown_.bind(this)); |
| 260 this.tracker.add(this.textbox_, 'keyup', this.onTextboxKeyUp_.bind(this)); |
| 261 }, |
| 262 |
| 263 get textbox_() { |
| 264 return this.getElement().getElementsByClassName( |
| 265 MarginControl.Classes_.TEXTBOX)[0]; |
| 266 }, |
| 267 |
| 268 /** |
| 269 * Called whenever a mousedown event occurs on the component. |
| 270 * @param {MouseEvent} e The event that occured. |
| 271 * @private |
| 272 */ |
| 273 onMouseDown_: function(e) { |
| 274 if (e.button != 0 || e.target != this.getElement()) { |
| 275 return; |
| 276 } |
| 277 this.mouseStartPositionInPixels_ = new print_preview.Coordinate2d( |
| 278 e.x, e.y); |
| 279 this.marginStartPositionInPixels_ = new print_preview.Coordinate2d( |
| 280 this.getElement().offsetLeft, this.getElement().offsetTop); |
| 281 this.isInError = false; |
| 282 cr.dispatchSimpleEvent(this, MarginControl.Event.DRAG_START); |
| 283 }, |
| 284 |
| 285 /** |
| 286 * Called when a key up event occurs on the textbox. Starts a timeout. |
| 287 * @private |
| 288 */ |
| 289 onTextboxKeyUp_: function() { |
| 290 if (this.textTimeout_) { |
| 291 clearTimeout(this.textTimeout_); |
| 292 } |
| 293 this.textTimeout_ = setTimeout( |
| 294 this.onTextboxTimeout_.bind(this), MarginControl.TEXTBOX_DELAY_); |
| 295 }, |
| 296 |
| 297 /** |
| 298 * Called when the textbox timeout fires. Dispatches a TEXT_CHANGE event. |
| 299 * @private |
| 300 */ |
| 301 onTextboxTimeout_: function() { |
| 302 this.textTimeout_ = null; |
| 303 var value = print_preview.extractMarginValue( |
| 304 this.textbox_.value, this.measurementSystem_); |
| 305 if (value < 0) { |
| 306 this.isInError = true; |
| 307 } else { |
| 308 this.isInError = false; |
| 309 var newPositionInPts = this.measurementSystem_.convertToPoints(value); |
| 310 if (newPositionInPts != this.positionInPts_) { |
| 311 this.positionInPts = newPositionInPts; |
| 312 cr.dispatchSimpleEvent(this, MarginControl.Event.TEXT_CHANGE); |
| 313 } |
| 314 } |
| 315 } |
| 316 }; |
| 317 |
| 318 // Export |
| 319 return { |
| 320 MarginControl: MarginControl |
| 321 }; |
| 322 }); |
OLD | NEW |