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 * @param {print_preview.ticket_items.CustomMargins.Orientation} orientation |
| 11 * Orientation of the margin control that determines where the margin |
| 12 * textbox will be placed. |
| 13 * @constructor |
| 14 * @extends {print_preview.Component} |
| 15 */ |
| 16 function MarginControl(orientation) { |
| 17 print_preview.Component.call(this); |
| 18 |
| 19 /** |
| 20 * Determines where the margin textbox will be placed. |
| 21 * @type {print_preview.ticket_items.CustomMargins.Orientation} |
| 22 * @private |
| 23 */ |
| 24 this.orientation_ = orientation; |
| 25 |
| 26 /** |
| 27 * Position of the margin control in points. |
| 28 * @type {number} |
| 29 * @private |
| 30 */ |
| 31 this.positionInPts_ = 0; |
| 32 |
| 33 /** |
| 34 * Page size of the document to print. |
| 35 * @type {!print_preview.Size} |
| 36 * @private |
| 37 */ |
| 38 this.pageSize_ = new print_preview.Size(0, 0); |
| 39 |
| 40 /** |
| 41 * Amount to scale pixel values by to convert to pixel space. |
| 42 * @type {number} |
| 43 * @private |
| 44 */ |
| 45 this.scaleTransform_ = 1; |
| 46 |
| 47 /** |
| 48 * Amount to translate values in pixel space. |
| 49 * @type {!print_preview.Coordinate2d} |
| 50 * @private |
| 51 */ |
| 52 this.translateTransform_ = new print_preview.Coordinate2d(0, 0); |
| 53 |
| 54 /** |
| 55 * Position of the margin control when dragging starts. |
| 56 * @type {print_preview.Coordinate2d} |
| 57 * @private |
| 58 */ |
| 59 this.marginStartPositionInPixels_ = null; |
| 60 |
| 61 /** |
| 62 * Position of the mouse when the dragging starts. |
| 63 * @type {print_preview.Coordinate2d} |
| 64 * @private |
| 65 */ |
| 66 this.mouseStartPositionInPixels_ = null; |
| 67 |
| 68 /** |
| 69 * Processing timeout for the textbox. |
| 70 * @type {Object} |
| 71 * @private |
| 72 */ |
| 73 this.textTimeout_ = null; |
| 74 |
| 75 /** |
| 76 * Textbox used to display and receive the value of the margin. |
| 77 * @type {HTMLInputElement} |
| 78 * @private |
| 79 */ |
| 80 this.textbox_ = null; |
| 81 |
| 82 /** |
| 83 * Element of the margin control line. |
| 84 * @type {HTMLElement} |
| 85 * @private |
| 86 */ |
| 87 this.marginLineEl_ = null; |
| 88 |
| 89 /** |
| 90 * Whether this margin control's textbox has keyboard focus. |
| 91 * @type {boolean} |
| 92 * @private |
| 93 */ |
| 94 this.isFocused_ = false; |
| 95 |
| 96 /** |
| 97 * Whether the margin control is in an error state. |
| 98 * @type {boolean} |
| 99 * @private |
| 100 */ |
| 101 this.isInError_ = false; |
| 102 }; |
| 103 |
| 104 /** |
| 105 * Event types dispatched by the margin control. |
| 106 * @enum {string} |
| 107 */ |
| 108 MarginControl.EventType = { |
| 109 // Dispatched when the margin control starts dragging. |
| 110 DRAG_START: 'print_preview.MarginControl.DRAG_START', |
| 111 |
| 112 // Dispatched when the text in the margin control's textbox changes. |
| 113 TEXT_CHANGE: 'print_preview.MarginControl.TEXT_CHANGE' |
| 114 }; |
| 115 |
| 116 /** |
| 117 * CSS classes used by this component. |
| 118 * @enum {string} |
| 119 * @private |
| 120 */ |
| 121 MarginControl.Classes_ = { |
| 122 TOP: 'margin-control-top', |
| 123 RIGHT: 'margin-control-right', |
| 124 BOTTOM: 'margin-control-bottom', |
| 125 LEFT: 'margin-control-left', |
| 126 TEXTBOX: 'margin-control-textbox', |
| 127 INVALID: 'invalid', |
| 128 INVISIBLE: 'invisible', |
| 129 DISABLED: 'margin-control-disabled', |
| 130 DRAGGING: 'margin-control-dragging', |
| 131 LINE: 'margin-control-line', |
| 132 ANIMATED: 'margin-control-animated' |
| 133 }; |
| 134 |
| 135 /** |
| 136 * Map from orientation to CSS class name. |
| 137 * @type {object.< |
| 138 * print_preview.ticket_items.CustomMargins.Orientation, |
| 139 * MarginControl.Classes_>} |
| 140 * @private |
| 141 */ |
| 142 MarginControl.OrientationToClass_ = {}; |
| 143 MarginControl.OrientationToClass_[ |
| 144 print_preview.ticket_items.CustomMargins.Orientation.TOP] = |
| 145 MarginControl.Classes_.TOP; |
| 146 MarginControl.OrientationToClass_[ |
| 147 print_preview.ticket_items.CustomMargins.Orientation.RIGHT] = |
| 148 MarginControl.Classes_.RIGHT; |
| 149 MarginControl.OrientationToClass_[ |
| 150 print_preview.ticket_items.CustomMargins.Orientation.BOTTOM] = |
| 151 MarginControl.Classes_.BOTTOM; |
| 152 MarginControl.OrientationToClass_[ |
| 153 print_preview.ticket_items.CustomMargins.Orientation.LEFT] = |
| 154 MarginControl.Classes_.LEFT; |
| 155 |
| 156 /** |
| 157 * Timeout in milliseconds before processing the value of the textbox. |
| 158 * @type {number} |
| 159 * @const |
| 160 * @private |
| 161 */ |
| 162 MarginControl.TEXTBOX_DELAY_ = 500; |
| 163 |
| 164 MarginControl.prototype = { |
| 165 __proto__: print_preview.Component.prototype, |
| 166 |
| 167 /** @return {boolean} Whether this margin control is in focus. */ |
| 168 getIsFocused: function() { |
| 169 return this.isFocused_; |
| 170 }, |
| 171 |
| 172 /** |
| 173 * @return {print_preview.ticket_items.CustomMargins.Orientation} |
| 174 * Orientation of the margin control. |
| 175 */ |
| 176 getOrientation: function() { |
| 177 return this.orientation_; |
| 178 }, |
| 179 |
| 180 /** |
| 181 * @param {number} scaleTransform New scale transform of the margin control. |
| 182 */ |
| 183 setScaleTransform: function(scaleTransform) { |
| 184 this.scaleTransform_ = scaleTransform; |
| 185 // Reset position |
| 186 this.setPositionInPts(this.positionInPts_); |
| 187 }, |
| 188 |
| 189 /** |
| 190 * @param {!print_preview.Coordinate2d} translateTransform New translate |
| 191 * transform of the margin control. |
| 192 */ |
| 193 setTranslateTransform: function(translateTransform) { |
| 194 this.translateTransform_ = translateTransform; |
| 195 // Reset position |
| 196 this.setPositionInPts(this.positionInPts_); |
| 197 }, |
| 198 |
| 199 /** |
| 200 * @param {!print_preview.Size} pageSize New size of the document's pages. |
| 201 */ |
| 202 setPageSize: function(pageSize) { |
| 203 this.pageSize_ = pageSize; |
| 204 this.setPositionInPts(this.positionInPts_); |
| 205 }, |
| 206 |
| 207 /** @param {boolean} isVisible Whether the margin control is visible. */ |
| 208 setIsVisible: function(isVisible) { |
| 209 if (isVisible) { |
| 210 this.getElement().classList.remove(MarginControl.Classes_.INVISIBLE); |
| 211 } else { |
| 212 this.getElement().classList.add(MarginControl.Classes_.INVISIBLE); |
| 213 } |
| 214 }, |
| 215 |
| 216 /** @return {boolean} Whether the margin control is in an error state. */ |
| 217 getIsInError: function() { |
| 218 return this.isInError_; |
| 219 }, |
| 220 |
| 221 /** |
| 222 * @param {boolean} isInError Whether the margin control is in an error |
| 223 * state. |
| 224 */ |
| 225 setIsInError: function(isInError) { |
| 226 this.isInError_ = isInError; |
| 227 if (isInError) { |
| 228 this.textbox_.classList.add(MarginControl.Classes_.INVALID); |
| 229 } else { |
| 230 this.textbox_.classList.remove(MarginControl.Classes_.INVALID); |
| 231 } |
| 232 }, |
| 233 |
| 234 /** @param {boolean} isEnabled Whether to enable the margin control. */ |
| 235 setIsEnabled: function(isEnabled) { |
| 236 this.textbox_.disabled = !isEnabled; |
| 237 if (isEnabled) { |
| 238 this.getElement().classList.remove(MarginControl.Classes_.DISABLED); |
| 239 } else { |
| 240 this.getElement().classList.add(MarginControl.Classes_.DISABLED); |
| 241 } |
| 242 }, |
| 243 |
| 244 /** @param {boolean} Whether the margin control should be animated. */ |
| 245 setIsAnimated: function(isAnimated) { |
| 246 if (isAnimated) { |
| 247 this.getElement().classList.add(MarginControl.Classes_.ANIMATED); |
| 248 } else { |
| 249 this.getElement().classList.remove(MarginControl.Classes_.ANIMATED); |
| 250 } |
| 251 }, |
| 252 |
| 253 /** |
| 254 * @param {number} posInPts New position of the margin control in points. |
| 255 */ |
| 256 setPositionInPts: function(posInPts) { |
| 257 this.positionInPts_ = posInPts; |
| 258 var orientationEnum = |
| 259 print_preview.ticket_items.CustomMargins.Orientation; |
| 260 var posInPixels; |
| 261 if (this.orientation_ == orientationEnum.TOP) { |
| 262 posInPixels = posInPts * this.scaleTransform_; |
| 263 posInPixels += this.translateTransform_.y; |
| 264 this.getElement().style.top = posInPixels + 'px'; |
| 265 } else if (this.orientation_ == orientationEnum.RIGHT) { |
| 266 posInPixels = this.pageSize_.width - posInPts; |
| 267 posInPixels *= this.scaleTransform_; |
| 268 posInPixels += this.translateTransform_.x; |
| 269 this.getElement().style.left = posInPixels + 'px'; |
| 270 } else if (this.orientation_ == orientationEnum.BOTTOM) { |
| 271 posInPixels = this.pageSize_.height - posInPts; |
| 272 posInPixels *= this.scaleTransform_; |
| 273 posInPixels += this.translateTransform_.y; |
| 274 this.getElement().style.top = posInPixels + 'px'; |
| 275 } else { |
| 276 posInPixels = posInPts * this.scaleTransform_; |
| 277 posInPixels += this.translateTransform_.x; |
| 278 this.getElement().style.left = posInPixels + 'px'; |
| 279 } |
| 280 }, |
| 281 |
| 282 /** @return {string} The value in the margin control's textbox. */ |
| 283 getTextboxValue: function() { |
| 284 return this.textbox_.value; |
| 285 }, |
| 286 |
| 287 /** @param {string} value New value of the margin control's textbox. */ |
| 288 setTextboxValue: function(value) { |
| 289 if (this.textbox_.value != value) { |
| 290 this.textbox_.value = value; |
| 291 } |
| 292 }, |
| 293 |
| 294 /** |
| 295 * Converts a value in pixels to points. |
| 296 * @param {number} Pixel value to convert. |
| 297 * @return {number} Given value expressed in points. |
| 298 */ |
| 299 convertPixelsToPts: function(pixels) { |
| 300 var pts; |
| 301 var orientationEnum = |
| 302 print_preview.ticket_items.CustomMargins.Orientation; |
| 303 if (this.orientation_ == orientationEnum.TOP) { |
| 304 pts = pixels - this.translateTransform_.y; |
| 305 pts /= this.scaleTransform_; |
| 306 } else if (this.orientation_ == orientationEnum.RIGHT) { |
| 307 pts = pixels - this.translateTransform_.x; |
| 308 pts /= this.scaleTransform_; |
| 309 pts = this.pageSize_.width - pts; |
| 310 } else if (this.orientation_ == orientationEnum.BOTTOM) { |
| 311 pts = pixels - this.translateTransform_.y; |
| 312 pts /= this.scaleTransform_; |
| 313 pts = this.pageSize_.height - pts; |
| 314 } else { |
| 315 pts = pixels - this.translateTransform_.x; |
| 316 pts /= this.scaleTransform_; |
| 317 } |
| 318 return pts; |
| 319 }, |
| 320 |
| 321 /** |
| 322 * Translates the position of the margin control relative to the mouse |
| 323 * position in pixels. |
| 324 * @param {!print_preview.Coordinate2d} mousePosition New position of |
| 325 * the mouse. |
| 326 * @return {!print_preview.Coordinate2d} New position of the margin control. |
| 327 */ |
| 328 translateMouseToPositionInPixels: function(mousePosition) { |
| 329 return new print_preview.Coordinate2d( |
| 330 mousePosition.x - this.mouseStartPositionInPixels_.x + |
| 331 this.marginStartPositionInPixels_.x, |
| 332 mousePosition.y - this.mouseStartPositionInPixels_.y + |
| 333 this.marginStartPositionInPixels_.y); |
| 334 }, |
| 335 |
| 336 /** @override */ |
| 337 createDom: function() { |
| 338 this.setElementInternal(this.cloneTemplateInternal( |
| 339 'margin-control-template')); |
| 340 this.getElement().classList.add(MarginControl.OrientationToClass_[ |
| 341 this.orientation_]); |
| 342 this.textbox_ = this.getElement().getElementsByClassName( |
| 343 MarginControl.Classes_.TEXTBOX)[0]; |
| 344 this.marginLineEl_ = this.getElement().getElementsByClassName( |
| 345 MarginControl.Classes_.LINE)[0]; |
| 346 }, |
| 347 |
| 348 /** @override */ |
| 349 enterDocument: function() { |
| 350 print_preview.Component.prototype.enterDocument.call(this); |
| 351 this.tracker.add( |
| 352 this.getElement(), 'mousedown', this.onMouseDown_.bind(this)); |
| 353 this.tracker.add( |
| 354 this.getElement(), |
| 355 'webkitTransitionEnd', |
| 356 this.onAnimationEnd_.bind(this)); |
| 357 this.tracker.add(this.textbox_, 'keyup', this.onTextboxKeyUp_.bind(this)); |
| 358 this.tracker.add( |
| 359 this.textbox_, 'focus', this.setIsFocused_.bind(this, true)); |
| 360 this.tracker.add( |
| 361 this.textbox_, 'blur', this.setIsFocused_.bind(this, false)); |
| 362 }, |
| 363 |
| 364 /** @override */ |
| 365 exitDocument: function() { |
| 366 print_preview.Component.prototype.exitDocument.call(this); |
| 367 this.textbox_ = null; |
| 368 this.marginLineEl_ = null; |
| 369 }, |
| 370 |
| 371 /** |
| 372 * @param {boolean} isFocused Whether the margin control is in focus. |
| 373 * @private |
| 374 */ |
| 375 setIsFocused_: function(isFocused) { |
| 376 this.isFocused_ = isFocused; |
| 377 }, |
| 378 |
| 379 /** |
| 380 * Called whenever a mousedown event occurs on the component. |
| 381 * @param {MouseEvent} event The event that occured. |
| 382 * @private |
| 383 */ |
| 384 onMouseDown_: function(event) { |
| 385 if (!this.textbox_.disabled && |
| 386 event.button == 0 && |
| 387 (event.target == this.getElement() || |
| 388 event.target == this.marginLineEl_)) { |
| 389 this.mouseStartPositionInPixels_ = |
| 390 new print_preview.Coordinate2d(event.x, event.y); |
| 391 this.marginStartPositionInPixels_ = new print_preview.Coordinate2d( |
| 392 this.getElement().offsetLeft, this.getElement().offsetTop); |
| 393 this.setIsInError(false); |
| 394 cr.dispatchSimpleEvent(this, MarginControl.EventType.DRAG_START); |
| 395 } |
| 396 }, |
| 397 |
| 398 /** |
| 399 * Called when a key up event occurs on the textbox. Starts a timeout. |
| 400 * @private |
| 401 */ |
| 402 onTextboxKeyUp_: function() { |
| 403 if (this.textTimeout_) { |
| 404 clearTimeout(this.textTimeout_); |
| 405 } |
| 406 this.textTimeout_ = setTimeout( |
| 407 this.onTextboxTimeout_.bind(this), MarginControl.TEXTBOX_DELAY_); |
| 408 }, |
| 409 |
| 410 /** |
| 411 * Called when the textbox timeout fires. Dispatches a TEXT_CHANGE event. |
| 412 * @private |
| 413 */ |
| 414 onTextboxTimeout_: function() { |
| 415 this.textTimeout_ = null; |
| 416 cr.dispatchSimpleEvent(this, MarginControl.EventType.TEXT_CHANGE); |
| 417 }, |
| 418 |
| 419 /** |
| 420 * Called when the sliding animation on the margin control completes. |
| 421 * Removes animation transitions from the margin control element. |
| 422 * @private |
| 423 */ |
| 424 onAnimationEnd_: function() { |
| 425 this.setIsAnimated(false); |
| 426 } |
| 427 }; |
| 428 |
| 429 // Export |
| 430 return { |
| 431 MarginControl: MarginControl |
| 432 }; |
| 433 }); |
OLD | NEW |