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 }; |
| 133 |
| 134 /** |
| 135 * Map from orientation to CSS class name. |
| 136 * @type {object.< |
| 137 * print_preview.ticket_items.CustomMargins.Orientation, |
| 138 * MarginControl.Classes_>} |
| 139 * @private |
| 140 */ |
| 141 MarginControl.OrientationToClass_ = {}; |
| 142 MarginControl.OrientationToClass_[ |
| 143 print_preview.ticket_items.CustomMargins.Orientation.TOP] = |
| 144 MarginControl.Classes_.TOP; |
| 145 MarginControl.OrientationToClass_[ |
| 146 print_preview.ticket_items.CustomMargins.Orientation.RIGHT] = |
| 147 MarginControl.Classes_.RIGHT; |
| 148 MarginControl.OrientationToClass_[ |
| 149 print_preview.ticket_items.CustomMargins.Orientation.BOTTOM] = |
| 150 MarginControl.Classes_.BOTTOM; |
| 151 MarginControl.OrientationToClass_[ |
| 152 print_preview.ticket_items.CustomMargins.Orientation.LEFT] = |
| 153 MarginControl.Classes_.LEFT; |
| 154 |
| 155 MarginControl.prototype = { |
| 156 __proto__: print_preview.Component.prototype, |
| 157 |
| 158 /** @return {boolean} Whether this margin control is in focus. */ |
| 159 getIsFocused: function() { |
| 160 return this.isFocused_; |
| 161 }, |
| 162 |
| 163 /** |
| 164 * @return {print_preview.ticket_items.CustomMargins.Orientation} |
| 165 * Orientation of the margin control. |
| 166 */ |
| 167 getOrientation: function() { |
| 168 return this.orientation_; |
| 169 }, |
| 170 |
| 171 /** |
| 172 * @param {number} scaleTransform New scale transform of the margin control. |
| 173 */ |
| 174 setScaleTransform: function(scaleTransform) { |
| 175 this.scaleTransform_ = scaleTransform; |
| 176 // Reset position |
| 177 this.setPositionInPts(this.positionInPts_); |
| 178 }, |
| 179 |
| 180 /** |
| 181 * @param {!print_preview.Coordinate2d} translateTransform New translate |
| 182 * transform of the margin control. |
| 183 */ |
| 184 setTranslateTransform: function(translateTransform) { |
| 185 this.translateTransform_ = translateTransform; |
| 186 // Reset position |
| 187 this.setPositionInPts(this.positionInPts_); |
| 188 }, |
| 189 |
| 190 /** |
| 191 * @param {!print_preview.Size} pageSize New size of the document's pages. |
| 192 */ |
| 193 setPageSize: function(pageSize) { |
| 194 this.pageSize_ = pageSize; |
| 195 this.setPositionInPts(this.positionInPts_); |
| 196 }, |
| 197 |
| 198 /** @param {boolean} isVisible Whether the margin control is visible. */ |
| 199 setIsVisible: function(isVisible) { |
| 200 if (isVisible) { |
| 201 this.getElement().classList.remove(MarginControl.Classes_.INVISIBLE); |
| 202 } else { |
| 203 this.getElement().classList.add(MarginControl.Classes_.INVISIBLE); |
| 204 } |
| 205 }, |
| 206 |
| 207 /** @return {boolean} Whether the margin control is in an error state. */ |
| 208 getIsInError: function() { |
| 209 return this.isInError_; |
| 210 }, |
| 211 |
| 212 /** |
| 213 * @param {boolean} isInError Whether the margin control is in an error |
| 214 * state. |
| 215 */ |
| 216 setIsInError: function(isInError) { |
| 217 this.isInError_ = isInError; |
| 218 if (isInError) { |
| 219 this.textbox_.classList.add(MarginControl.Classes_.INVALID); |
| 220 } else { |
| 221 this.textbox_.classList.remove(MarginControl.Classes_.INVALID); |
| 222 } |
| 223 }, |
| 224 |
| 225 /** @param {boolean} isEnabled Whether to enable the margin control. */ |
| 226 setIsEnabled: function(isEnabled) { |
| 227 this.textbox_.disabled = !isEnabled; |
| 228 if (isEnabled) { |
| 229 this.getElement().classList.remove(MarginControl.Classes_.DISABLED); |
| 230 } else { |
| 231 this.getElement().classList.add(MarginControl.Classes_.DISABLED); |
| 232 } |
| 233 }, |
| 234 |
| 235 /** |
| 236 * @param {number} posInPts New position of the margin control in points. |
| 237 */ |
| 238 setPositionInPts: function(posInPts) { |
| 239 this.positionInPts_ = posInPts; |
| 240 var orientationEnum = |
| 241 print_preview.ticket_items.CustomMargins.Orientation; |
| 242 var x = this.translateTransform_.x; |
| 243 var y = this.translateTransform_.y; |
| 244 var width = null, height = null; |
| 245 if (this.orientation_ == orientationEnum.TOP) { |
| 246 y = this.scaleTransform_ * posInPts + this.translateTransform_.y - 9; |
| 247 width = this.scaleTransform_ * this.pageSize_.width; |
| 248 } else if (this.orientation_ == orientationEnum.RIGHT) { |
| 249 x = this.scaleTransform_ * (this.pageSize_.width - posInPts) + |
| 250 this.translateTransform_.x - 9; |
| 251 height = this.scaleTransform_ * this.pageSize_.height; |
| 252 } else if (this.orientation_ == orientationEnum.BOTTOM) { |
| 253 y = this.scaleTransform_ * (this.pageSize_.height - posInPts) + |
| 254 this.translateTransform_.y - 9; |
| 255 width = this.scaleTransform_ * this.pageSize_.width; |
| 256 } else { |
| 257 x = this.scaleTransform_ * posInPts + this.translateTransform_.x - 9; |
| 258 height = this.scaleTransform_ * this.pageSize_.height; |
| 259 } |
| 260 this.getElement().style.left = Math.round(x) + 'px'; |
| 261 this.getElement().style.top = Math.round(y) + 'px'; |
| 262 if (width != null) { |
| 263 this.getElement().style.width = Math.round(width) + 'px'; |
| 264 } |
| 265 if (height != null) { |
| 266 this.getElement().style.height = Math.round(height) + 'px'; |
| 267 } |
| 268 }, |
| 269 |
| 270 /** @return {string} The value in the margin control's textbox. */ |
| 271 getTextboxValue: function() { |
| 272 return this.textbox_.value; |
| 273 }, |
| 274 |
| 275 /** @param {string} value New value of the margin control's textbox. */ |
| 276 setTextboxValue: function(value) { |
| 277 if (this.textbox_.value != value) { |
| 278 this.textbox_.value = value; |
| 279 } |
| 280 }, |
| 281 |
| 282 /** |
| 283 * Converts a value in pixels to points. |
| 284 * @param {number} Pixel value to convert. |
| 285 * @return {number} Given value expressed in points. |
| 286 */ |
| 287 convertPixelsToPts: function(pixels) { |
| 288 var pts; |
| 289 var orientationEnum = |
| 290 print_preview.ticket_items.CustomMargins.Orientation; |
| 291 if (this.orientation_ == orientationEnum.TOP) { |
| 292 pts = pixels - this.translateTransform_.y; |
| 293 pts /= this.scaleTransform_; |
| 294 } else if (this.orientation_ == orientationEnum.RIGHT) { |
| 295 pts = pixels - this.translateTransform_.x; |
| 296 pts /= this.scaleTransform_; |
| 297 pts = this.pageSize_.width - pts; |
| 298 } else if (this.orientation_ == orientationEnum.BOTTOM) { |
| 299 pts = pixels - this.translateTransform_.y; |
| 300 pts /= this.scaleTransform_; |
| 301 pts = this.pageSize_.height - pts; |
| 302 } else { |
| 303 pts = pixels - this.translateTransform_.x; |
| 304 pts /= this.scaleTransform_; |
| 305 } |
| 306 return pts; |
| 307 }, |
| 308 |
| 309 /** |
| 310 * Translates the position of the margin control relative to the mouse |
| 311 * position in pixels. |
| 312 * @param {!print_preview.Coordinate2d} mousePosition New position of |
| 313 * the mouse. |
| 314 * @return {!print_preview.Coordinate2d} New position of the margin control. |
| 315 */ |
| 316 translateMouseToPositionInPixels: function(mousePosition) { |
| 317 return new print_preview.Coordinate2d( |
| 318 mousePosition.x - this.mouseStartPositionInPixels_.x + |
| 319 this.marginStartPositionInPixels_.x, |
| 320 mousePosition.y - this.mouseStartPositionInPixels_.y + |
| 321 this.marginStartPositionInPixels_.y); |
| 322 }, |
| 323 |
| 324 /** @override */ |
| 325 createDom: function() { |
| 326 this.setElementInternal(this.cloneTemplateInternal( |
| 327 'margin-control-template')); |
| 328 this.getElement().classList.add(MarginControl.OrientationToClass_[ |
| 329 this.orientation_]); |
| 330 this.textbox_ = this.getElement().getElementsByClassName( |
| 331 MarginControl.Classes_.TEXTBOX)[0]; |
| 332 this.marginLineEl_ = this.getElement().getElementsByClassName( |
| 333 MarginControl.Classes_.LINE)[0]; |
| 334 }, |
| 335 |
| 336 /** @override */ |
| 337 enterDocument: function() { |
| 338 print_preview.Component.prototype.enterDocument.call(this); |
| 339 this.tracker.add( |
| 340 this.getElement(), 'mousedown', this.onMouseDown_.bind(this)); |
| 341 this.tracker.add(this.textbox_, 'keyup', this.onTextboxKeyUp_.bind(this)); |
| 342 this.tracker.add( |
| 343 this.textbox_, 'focus', this.setIsFocused_.bind(this, true)); |
| 344 this.tracker.add(this.textbox_, 'blur', this.onTexboxBlur_.bind(this)); |
| 345 }, |
| 346 |
| 347 /** @override */ |
| 348 exitDocument: function() { |
| 349 print_preview.Component.prototype.exitDocument.call(this); |
| 350 this.textbox_ = null; |
| 351 this.marginLineEl_ = null; |
| 352 }, |
| 353 |
| 354 /** |
| 355 * @param {boolean} isFocused Whether the margin control is in focus. |
| 356 * @private |
| 357 */ |
| 358 setIsFocused_: function(isFocused) { |
| 359 this.isFocused_ = isFocused; |
| 360 }, |
| 361 |
| 362 /** |
| 363 * Called whenever a mousedown event occurs on the component. |
| 364 * @param {MouseEvent} event The event that occured. |
| 365 * @private |
| 366 */ |
| 367 onMouseDown_: function(event) { |
| 368 if (!this.textbox_.disabled && |
| 369 event.button == 0 && |
| 370 (event.target == this.getElement() || |
| 371 event.target == this.marginLineEl_)) { |
| 372 this.mouseStartPositionInPixels_ = |
| 373 new print_preview.Coordinate2d(event.x, event.y); |
| 374 this.marginStartPositionInPixels_ = new print_preview.Coordinate2d( |
| 375 this.getElement().offsetLeft, this.getElement().offsetTop); |
| 376 this.setIsInError(false); |
| 377 cr.dispatchSimpleEvent(this, MarginControl.EventType.DRAG_START); |
| 378 } |
| 379 }, |
| 380 |
| 381 /** |
| 382 * Called when a key up event occurs on the textbox. Dispatches a |
| 383 * TEXT_CHANGE event if the "Enter" key was pressed. |
| 384 * @param {Event} event Contains the key that was released. |
| 385 * @private |
| 386 */ |
| 387 onTextboxKeyUp_: function(event) { |
| 388 if (event.keyIdentifier == 'Enter') { |
| 389 cr.dispatchSimpleEvent(this, MarginControl.EventType.TEXT_CHANGE); |
| 390 } |
| 391 }, |
| 392 |
| 393 /** |
| 394 * Called when the textbox loses focus. Dispatches a TEXT_CHANGE event. |
| 395 */ |
| 396 onTexboxBlur_: function() { |
| 397 this.setIsFocused_(false); |
| 398 cr.dispatchSimpleEvent(this, MarginControl.EventType.TEXT_CHANGE); |
| 399 } |
| 400 }; |
| 401 |
| 402 // Export |
| 403 return { |
| 404 MarginControl: MarginControl |
| 405 }; |
| 406 }); |
OLD | NEW |