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
5cr.define('print_preview.ticket_items', function() {
6  'use strict';
7
8  /**
9   * Custom page margins ticket item whose value is a
10   * {@code print_preview.Margins}.
11   * @param {!print_preview.AppState} appState App state used to persist custom
12   *     margins.
13   * @param {!print_preview.DocumentInfo} documentInfo Information about the
14   *     document to print.
15   * @constructor
16   * @extends {print_preview.ticket_items.TicketItem}
17   */
18  function CustomMargins(appState, documentInfo) {
19    print_preview.ticket_items.TicketItem.call(
20        this,
21        appState,
22        print_preview.AppState.Field.CUSTOM_MARGINS,
23        null /*destinationStore*/,
24        documentInfo);
25  };
26
27  /**
28   * Enumeration of the orientations of margins.
29   * @enum {string}
30   */
31  CustomMargins.Orientation = {
32    TOP: 'top',
33    RIGHT: 'right',
34    BOTTOM: 'bottom',
35    LEFT: 'left'
36  };
37
38  /**
39   * Mapping of a margin orientation to its opposite.
40   * @type {!Object.<!CustomMargins.Orientation, !CustomMargins.Orientation>}
41   * @private
42   */
43  CustomMargins.OppositeOrientation_ = {};
44  CustomMargins.OppositeOrientation_[CustomMargins.Orientation.TOP] =
45      CustomMargins.Orientation.BOTTOM;
46  CustomMargins.OppositeOrientation_[CustomMargins.Orientation.RIGHT] =
47      CustomMargins.Orientation.LEFT;
48  CustomMargins.OppositeOrientation_[CustomMargins.Orientation.BOTTOM] =
49      CustomMargins.Orientation.TOP;
50  CustomMargins.OppositeOrientation_[CustomMargins.Orientation.LEFT] =
51      CustomMargins.Orientation.RIGHT;
52
53  /**
54   * Minimum distance in points that two margins can be separated by.
55   * @type {number}
56   * @const
57   * @private
58   */
59  CustomMargins.MINIMUM_MARGINS_DISTANCE_ = 72; // 1 inch.
60
61  CustomMargins.prototype = {
62    __proto__: print_preview.ticket_items.TicketItem.prototype,
63
64    /** @override */
65    wouldValueBeValid: function(value) {
66      var margins = /** @type {!print_preview.Margins} */ (value);
67      for (var key in CustomMargins.Orientation) {
68        var o = CustomMargins.Orientation[key];
69        var max = this.getMarginMax_(
70            o, margins.get(CustomMargins.OppositeOrientation_[o]));
71        if (margins.get(o) > max || margins.get(o) < 0) {
72          return false;
73        }
74      }
75      return true;
76    },
77
78    /** @override */
79    isCapabilityAvailable: function() {
80      return this.getDocumentInfoInternal().isModifiable;
81    },
82
83    /** @override */
84    isValueEqual: function(value) {
85      return this.getValue().equals(value);
86    },
87
88    /**
89     * @param {!print_preview.ticket_items.CustomMargins.Orientation}
90     *     orientation Specifies the margin to get the maximum value for.
91     * @return {number} Maximum value in points of the specified margin.
92     */
93    getMarginMax: function(orientation) {
94      var oppositeOrient = CustomMargins.OppositeOrientation_[orientation];
95      var margins = /** @type {!print_preview.Margins} */ (this.getValue());
96      return this.getMarginMax_(orientation, margins.get(oppositeOrient));
97    },
98
99    /** @override */
100    updateValue: function(value) {
101      var margins = /** @type {!print_preview.Margins} */ (value);
102      if (margins != null) {
103        margins = new print_preview.Margins(
104            Math.round(margins.get(CustomMargins.Orientation.TOP)),
105            Math.round(margins.get(CustomMargins.Orientation.RIGHT)),
106            Math.round(margins.get(CustomMargins.Orientation.BOTTOM)),
107            Math.round(margins.get(CustomMargins.Orientation.LEFT)));
108      }
109      print_preview.ticket_items.TicketItem.prototype.updateValue.call(
110          this, margins);
111    },
112
113    /**
114     * Updates the specified margin in points while keeping the value within
115     * a maximum and minimum.
116     * @param {!print_preview.ticket_items.CustomMargins.Orientation}
117     *     orientation Specifies the margin to update.
118     * @param {number} value Updated margin value in points.
119     */
120    updateMargin: function(orientation, value) {
121      var margins = /** @type {!print_preview.Margins} */ (this.getValue());
122      var oppositeOrientation = CustomMargins.OppositeOrientation_[orientation];
123      var max =
124          this.getMarginMax_(orientation, margins.get(oppositeOrientation));
125      value = Math.max(0, Math.min(max, value));
126      this.updateValue(margins.set(orientation, value));
127    },
128
129    /** @override */
130    getDefaultValueInternal: function() {
131      return this.getDocumentInfoInternal().margins ||
132             new print_preview.Margins(72, 72, 72, 72);
133    },
134
135    /** @override */
136    getCapabilityNotAvailableValueInternal: function() {
137      return this.getDocumentInfoInternal().margins ||
138             new print_preview.Margins(72, 72, 72, 72);
139    },
140
141    /**
142     * @param {!print_preview.ticket_items.CustomMargins.Orientation}
143     *     orientation Specifies which margin to get the maximum value of.
144     * @param {number} oppositeMargin Value of the margin in points
145     *     opposite the specified margin.
146     * @return {number} Maximum value in points of the specified margin.
147     * @private
148     */
149    getMarginMax_: function(orientation, oppositeMargin) {
150      var max;
151      if (orientation == CustomMargins.Orientation.TOP ||
152          orientation == CustomMargins.Orientation.BOTTOM) {
153        max = this.getDocumentInfoInternal().pageSize.height - oppositeMargin -
154            CustomMargins.MINIMUM_MARGINS_DISTANCE_;
155      } else {
156        max = this.getDocumentInfoInternal().pageSize.width - oppositeMargin -
157            CustomMargins.MINIMUM_MARGINS_DISTANCE_;
158      }
159      return Math.round(max);
160    }
161  };
162
163  // Export
164  return {
165    CustomMargins: CustomMargins
166  };
167});
168