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 * UI component used for setting custom print margins. |
| 10 * @param {!print_preview.PrintTicketStore} printTicketStore Used to read and |
| 11 * write custom margin values. |
| 12 * @constructor |
| 13 * @extends {print_preview.Component} |
| 14 */ |
| 15 function MarginControlContainer(printTicketStore) { |
| 16 print_preview.Component.call(this); |
| 17 |
| 18 /** |
| 19 * Used to read and write custom margin values. |
| 20 * @type {!print_preview.PrintTicketStore} |
| 21 * @private |
| 22 */ |
| 23 this.printTicketStore_ = printTicketStore; |
| 24 |
| 25 /** |
| 26 * Convenience array that contains all of the margin controls. |
| 27 * @type {!Object< |
| 28 * print_preview.ticket_items.CustomMargins.Orientation, |
| 29 * !print_preview.MarginControl>} |
| 30 * @private |
| 31 */ |
| 32 this.controls_ = {}; |
| 33 for (var key in print_preview.ticket_items.CustomMargins.Orientation) { |
| 34 var orientation = print_preview.ticket_items.CustomMargins.Orientation[ |
| 35 key]; |
| 36 var control = new print_preview.MarginControl(orientation); |
| 37 this.controls_[orientation] = control; |
| 38 this.addChild(control); |
| 39 } |
| 40 |
| 41 /** |
| 42 * Margin control currently being dragged. Null if no control is being |
| 43 * dragged. |
| 44 * @type {print_preview.MarginControl} |
| 45 * @private |
| 46 */ |
| 47 this.draggedControl_ = null; |
| 48 |
| 49 /** |
| 50 * Translation transformation in pixels to translate from the origin of the |
| 51 * custom margins component to the top-left corner of the most visible |
| 52 * preview page. |
| 53 * @type {!print_preview.Coordinate2d} |
| 54 * @private |
| 55 */ |
| 56 this.translateTransform_ = new print_preview.Coordinate2d(0, 0); |
| 57 |
| 58 /** |
| 59 * Scaling transformation to scale from pixels to the units which the |
| 60 * print preview is in. The scaling factor is the same in both dimensions, |
| 61 * so this field is just a single number. |
| 62 * @type {number} |
| 63 * @private |
| 64 */ |
| 65 this.scaleTransform_ = 1; |
| 66 |
| 67 /** |
| 68 * Clipping size for clipping the margin controls. |
| 69 * @type {print_preview.Size} |
| 70 * @private |
| 71 */ |
| 72 this.clippingSize_ = null; |
| 73 }; |
| 74 |
| 75 /** |
| 76 * CSS classes used by the custom margins component. |
| 77 * @enum {string} |
| 78 * @private |
| 79 */ |
| 80 MarginControlContainer.Classes_ = { |
| 81 DRAGGING_HORIZONTAL: 'margin-control-container-dragging-horizontal', |
| 82 DRAGGING_VERTICAL: 'margin-control-container-dragging-vertical' |
| 83 }; |
| 84 |
| 85 /** |
| 86 * @param {print_preview.ticket_items.CustomMargins.Orientation} orientation |
| 87 * Orientation value to test. |
| 88 * @return {boolean} Whether the given orientation is TOP or BOTTOM. |
| 89 * @private |
| 90 */ |
| 91 MarginControlContainer.isTopOrBottom_ = function(orientation) { |
| 92 return orientation == |
| 93 print_preview.ticket_items.CustomMargins.Orientation.TOP || |
| 94 orientation == |
| 95 print_preview.ticket_items.CustomMargins.Orientation.BOTTOM; |
| 96 }; |
| 97 |
| 98 MarginControlContainer.prototype = { |
| 99 __proto__: print_preview.Component.prototype, |
| 100 |
| 101 /** |
| 102 * Updates the translation transformation that translates pixel values in |
| 103 * the space of the HTML DOM. |
| 104 * @param {print_preview.Coordinate2d} translateTransform Updated value of |
| 105 * the translation transformation. |
| 106 */ |
| 107 updateTranslationTransform: function(translateTransform) { |
| 108 if (!translateTransform.equals(this.translateTransform_)) { |
| 109 this.translateTransform_ = translateTransform; |
| 110 for (var orientation in this.controls_) { |
| 111 this.controls_[orientation].setTranslateTransform(translateTransform); |
| 112 } |
| 113 } |
| 114 }, |
| 115 |
| 116 /** |
| 117 * Updates the scaling transform that scales pixels values to point values. |
| 118 * @param {number} scaleTransform Updated value of the scale transform. |
| 119 */ |
| 120 updateScaleTransform: function(scaleTransform) { |
| 121 if (scaleTransform != this.scaleTransform_) { |
| 122 this.scaleTransform_ = scaleTransform; |
| 123 for (var orientation in this.controls_) { |
| 124 this.controls_[orientation].setScaleTransform(scaleTransform); |
| 125 } |
| 126 } |
| 127 }, |
| 128 |
| 129 /** |
| 130 * Clips margin controls to the given clip size in pixels. |
| 131 * @param {print_preview.Size} Size to clip the margin controls to. |
| 132 */ |
| 133 updateClippingMask: function(clipSize) { |
| 134 if (!clipSize) { |
| 135 return; |
| 136 } |
| 137 this.clippingSize_ = clipSize; |
| 138 for (var orientation in this.controls_) { |
| 139 var el = this.controls_[orientation].getElement(); |
| 140 el.style.clip = 'rect(' + |
| 141 (-el.offsetTop) + 'px, ' + |
| 142 (clipSize.width - el.offsetLeft) + 'px, ' + |
| 143 (clipSize.height - el.offsetTop) + 'px, ' + |
| 144 (-el.offsetLeft) + 'px)'; |
| 145 } |
| 146 }, |
| 147 |
| 148 /** @override */ |
| 149 decorateInternal: function() { |
| 150 for (var orientation in this.controls_) { |
| 151 this.controls_[orientation].render(this.getElement()); |
| 152 } |
| 153 }, |
| 154 |
| 155 /** @override */ |
| 156 enterDocument: function() { |
| 157 print_preview.Component.prototype.enterDocument.call(this); |
| 158 |
| 159 // We want to respond to mouse up events even beyond the component's |
| 160 // element. |
| 161 this.tracker.add(window, 'mouseup', this.onMouseUp_.bind(this)); |
| 162 this.tracker.add(window, 'mousemove', this.onMouseMove_.bind(this)); |
| 163 this.tracker.add( |
| 164 this.getElement(), 'mouseover', this.onMouseOver_.bind(this)); |
| 165 this.tracker.add( |
| 166 this.getElement(), 'mouseout', this.onMouseOut_.bind(this)); |
| 167 |
| 168 this.tracker.add( |
| 169 this.printTicketStore_, |
| 170 print_preview.PrintTicketStore.EventType.INITIALIZE, |
| 171 this.onTicketChange_.bind(this)); |
| 172 this.tracker.add( |
| 173 this.printTicketStore_, |
| 174 print_preview.PrintTicketStore.EventType.TICKET_CHANGE, |
| 175 this.onTicketChange_.bind(this)); |
| 176 this.tracker.add( |
| 177 this.printTicketStore_, |
| 178 print_preview.PrintTicketStore.EventType.DOCUMENT_CHANGE, |
| 179 this.onTicketChange_.bind(this)); |
| 180 this.tracker.add( |
| 181 this.printTicketStore_, |
| 182 print_preview.PrintTicketStore.EventType.CAPABILITIES_CHANGE, |
| 183 this.onTicketChange_.bind(this)); |
| 184 |
| 185 for (var orientation in this.controls_) { |
| 186 this.tracker.add( |
| 187 this.controls_[orientation], |
| 188 print_preview.MarginControl.EventType.DRAG_START, |
| 189 this.onControlDragStart_.bind(this, this.controls_[orientation])); |
| 190 this.tracker.add( |
| 191 this.controls_[orientation], |
| 192 print_preview.MarginControl.EventType.TEXT_CHANGE, |
| 193 this.onControlTextChange_.bind(this, this.controls_[orientation])); |
| 194 } |
| 195 }, |
| 196 |
| 197 /** |
| 198 * @param {boolean} isVisible Whether the margin controls are visible. |
| 199 * @private |
| 200 */ |
| 201 setIsMarginControlsVisible_: function(isVisible) { |
| 202 for (var orientation in this.controls_) { |
| 203 this.controls_[orientation].setIsVisible(isVisible); |
| 204 } |
| 205 }, |
| 206 |
| 207 /** |
| 208 * Moves the position of the given control to the desired position in |
| 209 * pixels within some constraint minimum and maximum. |
| 210 * @param {!print_preview.MarginControl} control Control to move. |
| 211 * @param {!print_preview.Coordinate2d} posInPixels Desired position to move |
| 212 * to in pixels. |
| 213 * @private |
| 214 */ |
| 215 moveControlWithConstraints_: function(control, posInPixels) { |
| 216 var newPosInPts; |
| 217 if (MarginControlContainer.isTopOrBottom_(control.getOrientation())) { |
| 218 newPosInPts = control.convertPixelsToPts(posInPixels.y); |
| 219 } else { |
| 220 newPosInPts = control.convertPixelsToPts(posInPixels.x); |
| 221 } |
| 222 newPosInPts = Math.min( |
| 223 this.printTicketStore_.getCustomMarginMaxInPts( |
| 224 control.getOrientation()), |
| 225 newPosInPts); |
| 226 newPosInPts = Math.max(0, newPosInPts); |
| 227 control.setPositionInPts(newPosInPts); |
| 228 control.setTextboxValue( |
| 229 this.printTicketStore_.serializeMarginFromPts(newPosInPts)); |
| 230 }, |
| 231 |
| 232 /** |
| 233 * Called when a margin control starts to drag. |
| 234 * @param {print_preview.MarginControl} control The control which started to |
| 235 * drag. |
| 236 * @private |
| 237 */ |
| 238 onControlDragStart_: function(control) { |
| 239 this.draggedControl_ = control; |
| 240 this.getElement().classList.add( |
| 241 MarginControlContainer.isTopOrBottom_(control.getOrientation()) ? |
| 242 MarginControlContainer.Classes_.DRAGGING_VERTICAL : |
| 243 MarginControlContainer.Classes_.DRAGGING_HORIZONTAL); |
| 244 }, |
| 245 |
| 246 /** |
| 247 * Called when the mouse moves in the custom margins component. Moves the |
| 248 * dragged margin control. |
| 249 * @param {MouseEvent} event Contains the position of the mouse. |
| 250 * @private |
| 251 */ |
| 252 onMouseMove_: function(event) { |
| 253 if (this.draggedControl_) { |
| 254 this.moveControlWithConstraints_( |
| 255 this.draggedControl_, |
| 256 this.draggedControl_.translateMouseToPositionInPixels( |
| 257 new print_preview.Coordinate2d(event.x, event.y))); |
| 258 this.updateClippingMask(this.clippingSize_); |
| 259 } |
| 260 }, |
| 261 |
| 262 /** |
| 263 * Called when the mouse is released in the custom margins component. |
| 264 * Releases the dragged margin control. |
| 265 * @param {MouseEvent} event Contains the position of the mouse. |
| 266 * @private |
| 267 */ |
| 268 onMouseUp_: function(event) { |
| 269 if (this.draggedControl_) { |
| 270 this.getElement().classList.remove( |
| 271 MarginControlContainer.Classes_.DRAGGING_VERTICAL); |
| 272 this.getElement().classList.remove( |
| 273 MarginControlContainer.Classes_.DRAGGING_HORIZONTAL); |
| 274 if (event) { |
| 275 var posInPixels = |
| 276 this.draggedControl_.translateMouseToPositionInPixels( |
| 277 new print_preview.Coordinate2d(event.x, event.y)); |
| 278 this.moveControlWithConstraints_(this.draggedControl_, posInPixels); |
| 279 } |
| 280 this.updateClippingMask(this.clippingSize_); |
| 281 this.printTicketStore_.updateCustomMargin( |
| 282 this.draggedControl_.getOrientation(), |
| 283 this.draggedControl_.getTextboxValue()); |
| 284 this.draggedControl_ = null; |
| 285 } |
| 286 }, |
| 287 |
| 288 /** |
| 289 * Called when the mouse moves onto the component. Shows the margin |
| 290 * controls. |
| 291 * @private |
| 292 */ |
| 293 onMouseOver_: function() { |
| 294 var fromElement = event.fromElement; |
| 295 while (fromElement != null) { |
| 296 if (fromElement == this.getElement()) { |
| 297 return; |
| 298 } |
| 299 fromElement = fromElement.parentElement; |
| 300 } |
| 301 if (this.printTicketStore_.hasMarginsCapability() && |
| 302 this.printTicketStore_.getMarginsType() == |
| 303 print_preview.ticket_items.MarginsType.Value.CUSTOM) { |
| 304 this.setIsMarginControlsVisible_(true); |
| 305 } |
| 306 }, |
| 307 |
| 308 /** |
| 309 * Called when the mouse moves off of the component. Hides the margin |
| 310 * controls. |
| 311 * @private |
| 312 */ |
| 313 onMouseOut_: function(event) { |
| 314 var toElement = event.toElement; |
| 315 while (toElement != null) { |
| 316 if (toElement == this.getElement()) { |
| 317 return; |
| 318 } |
| 319 toElement = toElement.parentElement; |
| 320 } |
| 321 if (this.draggedControl_ != null) { |
| 322 return; |
| 323 } |
| 324 for (var orientation in this.controls_) { |
| 325 if (this.controls_[orientation].getIsFocused() || |
| 326 this.controls_[orientation].getIsInError()) { |
| 327 return; |
| 328 } |
| 329 } |
| 330 this.setIsMarginControlsVisible_(false); |
| 331 }, |
| 332 |
| 333 /** |
| 334 * Called when the print ticket changes. Updates the position of the margin |
| 335 * controls. |
| 336 * @private |
| 337 */ |
| 338 onTicketChange_: function() { |
| 339 var stringMargins = this.printTicketStore_.getCustomMargins(); |
| 340 var isCustomMarginsValid = this.printTicketStore_.isCustomMarginsValid(); |
| 341 for (var orientation in this.controls_) { |
| 342 var control = this.controls_[orientation]; |
| 343 var isInError = |
| 344 !this.printTicketStore_.isCustomMarginParseable(orientation); |
| 345 control.setIsInError(isInError); |
| 346 control.setPageSize(this.printTicketStore_.pageSize); |
| 347 control.setTextboxValue(stringMargins.get(orientation)); |
| 348 control.setIsEnabled(isCustomMarginsValid || isInError); |
| 349 } |
| 350 if (isCustomMarginsValid) { |
| 351 var customMarginsInPts = this.printTicketStore_.getCustomMarginsInPts(); |
| 352 for (var orientation in this.controls_) { |
| 353 var control = this.controls_[orientation]; |
| 354 control.setPositionInPts(customMarginsInPts.get(orientation)); |
| 355 } |
| 356 } |
| 357 this.updateClippingMask(this.clippingSize_); |
| 358 this.setIsMarginControlsVisible_( |
| 359 this.printTicketStore_.getMarginsType() == |
| 360 print_preview.ticket_items.MarginsType.Value.CUSTOM); |
| 361 }, |
| 362 |
| 363 /** |
| 364 * Called when the text in a textbox of a margin control changes. |
| 365 * Updates the print ticket store. |
| 366 * @param {!print_preview.MarginControl} control Updated control. |
| 367 * @private |
| 368 */ |
| 369 onControlTextChange_: function(control) { |
| 370 this.printTicketStore_.updateCustomMargin( |
| 371 control.getOrientation(), control.getTextboxValue()); |
| 372 } |
| 373 }; |
| 374 |
| 375 // Export |
| 376 return { |
| 377 MarginControlContainer: MarginControlContainer |
| 378 }; |
| 379 }); |
OLD | NEW |