1<?php
2// $Header: /cvsroot/html2ps/box.checkbutton.php,v 1.21 2007/05/07 12:15:53 Konstantin Exp $
3
4/**
5 * @package HTML2PS
6 * @subpackage Document
7 *
8 * This file contains the class describing layot and behavior of <input type="checkbox">
9 * elements
10 */
11
12/**
13 * @package HTML2PS
14 * @subpackage Document
15 *
16 * The CheckBox class desribes the layour of HTML checkboxes (they have HTML2PS-specific
17 * '-checkbox' value of 'display' property)
18 *
19 * Checkboxes have fixed size, which can be configured using CHECKBOX_SIZE constant
20 * in config.inc.php file. If "checked" attribute is present (whatever its value is),
21 * a small cross is drawn inside the checkbox.
22 *
23 * @see CHECKBOX_SIZE
24 *
25 * @todo add "disabled" state
26 */
27class CheckBox extends GenericFormattedBox {
28  /**
29   * @var Boolean Flag indicating whether the check mark should be drawn
30   * @access private
31   */
32  var $_checked;
33
34  /**
35   * @var String name of the corresponding form field
36   * @access private
37   */
38  var $_name;
39
40  /**
41   * Notes: leading and trailing spaces are removed; if value is not specified,
42   * checkbox is not rendered as ineractive control
43   *
44   * @var String value to be posted from ineractive form for this checkbox
45   * @access private
46   */
47  var $_value;
48
49  /**
50   * Create a new checkbutton element using DOM tree element to initialize
51   * it.
52   *
53   * @param DOMElement $root the DOM 'input' element
54   *
55   * @return CheckBox new checkbox element
56   *
57   * @see CheckBox::CheckBox()
58   */
59  function &create(&$root, &$pipeline) {
60    $value = $root->get_attribute('value');
61
62    if (trim($value) == "") {
63      error_log("Checkbox with empty 'value' attribute");
64      $value = sprintf("___Value%s",md5(time().rand()));
65    };
66
67    $box =& new CheckBox($root->has_attribute('checked'),
68                         $root->get_attribute('name'),
69                         $value);
70    $box->readCSS($pipeline->get_current_css_state());
71    $box->setup_dimensions();
72    return $box;
73  }
74
75  /**
76   * Create a new checkbox element with the given state
77   *
78   * @param $checked flag inidicating if this box should be checked
79   *
80   * @see CheckBox::create()
81   */
82  function CheckBox($checked, $name, $value) {
83    $this->GenericFormattedBox();
84
85    $this->_checked = $checked;
86    $this->_name    = trim($name);
87    $this->_value   = trim($value);
88  }
89
90  /**
91   * Returns the width of the checkbox; not that max/min width does not
92   * make sense for the checkbuttons, as their width is always constant.
93   *
94   * @param FlowContext Context object describing current flow parameters (unused)
95   *
96   * @return int width of the checkbox
97   *
98   * @see CheckBox::get_max_width
99   */
100  function get_min_width(&$context) {
101    return $this->width;
102  }
103
104  /**
105   * Returns the width of the checkbox; not that max/min width does not
106   * make sense for the checkbuttons, as their width is always constant.
107   *
108   * @param FlowContext Context object describing current flow parameters (unused)
109   *
110   * @return int width of the checkbox
111   *
112   * @see CheckBox::get_min_width
113   */
114  function get_max_width(&$context) {
115    return $this->width;
116  }
117
118  /**
119   * Layout current checkbox element. Note that most CSS properties do not apply to the
120   * checkboxes; i.e. margin/padding values are ignored, checkboxes always aligned to
121   * to bottom of current line, etc.
122   *
123   * @param GenericContainerBox $parent
124   * @param FlowContext $context Context object describing current flow parameters
125   *
126   * @return Boolean flag indicating the error/success state; 'null' value in case of critical error
127   */
128  function reflow(&$parent, &$context) {
129    GenericFormattedBox::reflow($parent, $context);
130
131    /**
132     * Check box size is constant (defined in config.inc.php) and is never affected
133     * neither by CSS nor HTML. Call setup_dimensions once more to restore possible
134     * changes size
135     *
136     * @see CHECKBOX_SIZE
137     */
138    $this->setup_dimensions();
139
140    // set default baseline
141    $this->baseline = $this->default_baseline;
142
143//     // Vertical-align
144//     $this->_apply_vertical_align($parent);
145
146    /**
147     * append to parent line box
148     */
149    $parent->append_line($this);
150
151    /**
152     * Determine coordinates of upper-left margin corner
153     */
154    $this->guess_corner($parent);
155
156    /**
157     * Offset parent current X coordinate
158     */
159    $parent->_current_x += $this->get_full_width();
160
161    /**
162     * Extend parents height to fit the checkbox
163     */
164    $parent->extend_height($this->get_bottom_margin());
165  }
166
167  /**
168   * Render the checkbox using the specified output driver
169   *
170   * @param OutputDriver $driver The output device driver object
171   */
172  function show(&$driver) {
173    /**
174     * Get the coordinates of the check mark
175     */
176    $x = ($this->get_left() + $this->get_right()) / 2;
177    $y = ($this->get_top() + $this->get_bottom()) / 2;
178
179    /**
180     * Calculate checkmark size; it looks nice when it takes
181     * 1/3 of the box size
182     */
183    $size = $this->get_width() / 3;
184
185    /**
186     * Draw the box
187     */
188    $driver->setrgbcolor(0,0,0);
189    $driver->setlinewidth(0.25);
190    $driver->moveto($x - $size, $y + $size);
191    $driver->lineto($x + $size, $y + $size);
192    $driver->lineto($x + $size, $y - $size);
193    $driver->lineto($x - $size, $y - $size);
194    $driver->closepath();
195    $driver->stroke();
196
197    /**
198     * Render the interactive button (if requested and possible)
199     * Also, field should be rendered only if name is not empty
200     */
201    global $g_config;
202    if ($g_config['renderforms'] && $this->_name != "" && $this->_value != "") {
203      $driver->field_checkbox($x - $size,
204                              $y + $size,
205                              2*$size,
206                              2*$size,
207                              $this->_name,
208                              $this->_value,
209                              $this->_checked);
210    } else {
211      /**
212       * Draw check mark if needed
213       */
214      if ($this->_checked) {
215        $check_size = $this->get_width() / 6;
216
217        $driver->moveto($x - $check_size, $y + $check_size);
218        $driver->lineto($x + $check_size, $y - $check_size);
219        $driver->stroke();
220
221        $driver->moveto($x + $check_size, $y + $check_size);
222        $driver->lineto($x - $check_size, $y - $check_size);
223        $driver->stroke();
224      }
225    };
226
227    return true;
228  }
229
230  function setup_dimensions() {
231    $this->default_baseline = units2pt(CHECKBOX_SIZE);
232    $this->height           = units2pt(CHECKBOX_SIZE);
233    $this->width            = units2pt(CHECKBOX_SIZE);
234  }
235}
236?>