1 /**
  2  * Constructs a new rule with default properties. Rules are not typically
  3  * constructed directly, but by adding to a panel or an existing mark via
  4  * {@link pv.Mark#add}.
  5  *
  6  * @class Represents a horizontal or vertical rule. Rules are frequently used
  7  * for axes and grid lines. For example, specifying only the bottom property
  8  * draws horizontal rules, while specifying only the left draws vertical
  9  * rules. Rules can also be used as thin bars. The visual style is controlled in
 10  * the same manner as lines.
 11  *
 12  * <p>Rules are positioned exclusively the standard box model properties. The
 13  * following combinations of properties are supported:
 14  *
 15  * <table>
 16  * <thead><th style="width:12em;">Properties</th><th>Orientation</th></thead>
 17  * <tbody>
 18  * <tr><td>left</td><td>vertical</td></tr>
 19  * <tr><td>right</td><td>vertical</td></tr>
 20  * <tr><td>left, bottom, top</td><td>vertical</td></tr>
 21  * <tr><td>right, bottom, top</td><td>vertical</td></tr>
 22  * <tr><td>top</td><td>horizontal</td></tr>
 23  * <tr><td>bottom</td><td>horizontal</td></tr>
 24  * <tr><td>top, left, right</td><td>horizontal</td></tr>
 25  * <tr><td>bottom, left, right</td><td>horizontal</td></tr>
 26  * <tr><td>left, top, height</td><td>vertical</td></tr>
 27  * <tr><td>left, bottom, height</td><td>vertical</td></tr>
 28  * <tr><td>right, top, height</td><td>vertical</td></tr>
 29  * <tr><td>right, bottom, height</td><td>vertical</td></tr>
 30  * <tr><td>left, top, width</td><td>horizontal</td></tr>
 31  * <tr><td>left, bottom, width</td><td>horizontal</td></tr>
 32  * <tr><td>right, top, width</td><td>horizontal</td></tr>
 33  * <tr><td>right, bottom, width</td><td>horizontal</td></tr>
 34  * </tbody>
 35  * </table>
 36  *
 37  * <p>Small rules can be used as tick marks; alternatively, a {@link Dot} with
 38  * the "tick" shape can be used.
 39  *
 40  * <p>See also the <a href="../../api/Rule.html">Rule guide</a>.
 41  *
 42  * @see pv.Line
 43  * @extends pv.Mark
 44  */
 45 pv.Rule = function() {
 46   pv.Mark.call(this);
 47 };
 48 
 49 pv.Rule.prototype = pv.extend(pv.Mark)
 50     .property("width")
 51     .property("height")
 52     .property("lineWidth")
 53     .property("strokeStyle");
 54 
 55 pv.Rule.prototype.type = "rule";
 56 
 57 /**
 58  * The width of the rule, in pixels. If the left position is specified, the rule
 59  * extends rightward from the left edge; if the right position is specified, the
 60  * rule extends leftward from the right edge.
 61  *
 62  * @type number
 63  * @name pv.Rule.prototype.width
 64  */
 65 
 66 /**
 67  * The height of the rule, in pixels. If the bottom position is specified, the
 68  * rule extends upward from the bottom edge; if the top position is specified,
 69  * the rule extends downward from the top edge.
 70  *
 71  * @type number
 72  * @name pv.Rule.prototype.height
 73  */
 74 
 75 /**
 76  * The width of stroked lines, in pixels; used in conjunction with
 77  * <tt>strokeStyle</tt> to stroke the rule. The default value is 1 pixel.
 78  *
 79  * @type number
 80  * @name pv.Rule.prototype.lineWidth
 81  */
 82 
 83 /**
 84  * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
 85  * stroke the rule. The default value of this property is black.
 86  *
 87  * @type string
 88  * @name pv.Rule.prototype.strokeStyle
 89  * @see pv.color
 90  */
 91 
 92 /**
 93  * Default properties for rules. By default, a single-pixel black line is
 94  * stroked.
 95  *
 96  * @type pv.Rule
 97  */
 98 pv.Rule.prototype.defaults = new pv.Rule()
 99     .extend(pv.Mark.prototype.defaults)
100     .lineWidth(1)
101     .strokeStyle("black");
102 
103 /**
104  * Constructs a new rule anchor with default properties. Rules support five
105  * different anchors:<ul>
106  *
107  * <li>top
108  * <li>left
109  * <li>center
110  * <li>bottom
111  * <li>right
112  *
113  * </ul>In addition to positioning properties (left, right, top bottom), the
114  * anchors support text rendering properties (text-align, text-baseline). Text is
115  * rendered to appear outside the rule. Note that this behavior is different
116  * from other mark anchors, which default to rendering text <i>inside</i> the
117  * mark.
118  *
119  * <p>For consistency with the other mark types, the anchor positions are
120  * defined in terms of their opposite edge. For example, the top anchor defines
121  * the bottom property, such that a bar added to the top anchor grows upward.
122  *
123  * @param {string} name the anchor name; either a string or a property function.
124  * @returns {pv.Anchor}
125  */
126 pv.Rule.prototype.anchor = function(name) {
127   return pv.Bar.prototype.anchor.call(this, name)
128     .textAlign(function(d) {
129         switch (this.name()) {
130           case "left": return "right";
131           case "bottom":
132           case "top":
133           case "center": return "center";
134           case "right": return "left";
135         }
136       })
137     .textBaseline(function(d) {
138         switch (this.name()) {
139           case "right":
140           case "left":
141           case "center": return "middle";
142           case "top": return "bottom";
143           case "bottom": return "top";
144         }
145       });
146 };
147 
148 /**
149  * @private Overrides the default behavior of {@link pv.Mark.buildImplied} to
150  * determine the orientation (vertical or horizontal) of the rule.
151  *
152  * @param s a node in the scene graph; the instance of the rule to build.
153  */
154 pv.Rule.prototype.buildImplied = function(s) {
155   var l = s.left, r = s.right, t = s.top, b = s.bottom;
156 
157   /* Determine horizontal or vertical orientation. */
158   if ((s.width != null)
159       || ((l == null) && (r == null))
160       || ((r != null) && (l != null))) {
161     s.height = 0;
162   } else {
163     s.width = 0;
164   }
165 
166   pv.Mark.prototype.buildImplied.call(this, s);
167 };
168