1: <?php
2:
3: class HtmlGrid {
4:
5: private $cells = array();
6:
7: public function __construct($attributes = array()) {
8: $this->attributes = $attributes;
9: }
10:
11: 12: 13: 14: 15: 16:
17: public function cell($x, $y) {
18: if (empty($this->cells[$x][$y])) {
19: $this->cells[$x][$y] = new HtmlGrid_Cell($x, $y);
20: }
21:
22: return $this->cells[$x][$y];
23: }
24:
25: public function hasCell($x, $y) {
26: return !empty($this->cells[$x][$y]);
27: }
28:
29: public function cells() {
30: $array = array();
31: foreach ($this->cells as $x => $ys) {
32: foreach ($ys as $y => $cell) {
33: $array[] = $cell;
34: }
35: }
36: return $array;
37: }
38:
39: public function attributes() {
40: return $this->attributes;
41: }
42:
43: public function out() {
44: $tableOut = new _HtmlGrid_TableOut($this);
45: return $tableOut->out();
46: }
47:
48: public function outDebug() {
49: $tableOut = new _HtmlGrid_TableOut($this);
50: return $tableOut->outDebug();
51: }
52:
53: }
54:
55: class HtmlGrid_Cell {
56:
57: private $content = '';
58: private $width = 1;
59: private $height = 1;
60: private $left;
61: private $top;
62: private $attributes = array();
63:
64: public function __construct($left, $top) {
65: $this->left = $left;
66: $this->top = $top;
67: }
68:
69: public function setContent($content) {
70: $this->content = $content;
71: return $this;
72: }
73:
74: public function getContent() {
75: return $this->content;
76: }
77:
78: public function setWidth($width) {
79: $this->width = $width;
80: return $this;
81: }
82:
83: public function getWidth() {
84: return $this->width;
85: }
86:
87: public function setHeight($height) {
88: $this->height = $height;
89: return $this;
90: }
91:
92: public function getHeight() {
93: return $this->height;
94: }
95:
96: public function getLeft() {
97: return $this->left;
98: }
99:
100: public function getTop() {
101: return $this->top;
102: }
103:
104: public function getRight() {
105: return $this->left + $this->width - 1;
106: }
107:
108: public function getBottom() {
109: return $this->top + $this->height - 1;
110: }
111:
112: public function getAttributes() {
113: return $this->attributes;
114: }
115:
116: public function setAttribute($name, $value) {
117: $this->attributes[$name] = $value;
118: return $this;
119: }
120:
121: public function getAttribute($name) {
122: return empty($this->attributes[$name]) ?
123: null :
124: $this->attributes[$name];
125: }
126:
127: public function addClass($class) {
128: if (empty($this->attributes['class']) || trim($this->attributes['class']) == '') {
129: $this->attributes['class'] = $class;
130: } else {
131: $this->attributes['class'] .= ' ' . $class;
132: }
133: return $this;
134: }
135:
136: public function hasClass($class) {
137: if (empty($this->attributes['class'])) {
138: return false;
139: } else {
140: return array_search($class, explode(' ', $this->attributes['class'])) !== false;
141: }
142: }
143:
144: }
145:
146: class _HtmlGrid_TableOut {
147:
148: 149: 150: 151:
152: private $grid;
153:
154: public function __construct(HtmlGrid $grid) {
155: $this->grid = $grid;
156: }
157:
158: public function out() {
159: $b = '<table';
160: foreach ($this->grid->attributes() as $key => $value) {
161: $b .= " $key=\"$value\"";
162: }
163: $b .= '>';
164: foreach ($this->_buildTableRows() as $row) {
165: $b .= $this->_outTableRow($row);
166: }
167: $b .= "</table>\n";
168: return $b;
169: }
170:
171: public function outDebug() {
172: $rowsCount = $this->_tableRowsCount();
173: $columnsCount = $this->_tableColumnsCount();
174:
175: $tdStyle = 'style="border: thin solid black; font-size: smaller"';
176:
177: $b = '<table style="border: thin solid black; border-collapse: collapse">';
178: $b .= '<tr>';
179: $b .= "<th $tdStyle>Rows: $rowsCount/Col: $columnsCount</th>";
180: for ($x = 0; $x < $columnsCount; $x++) {
181: $b .= "<th $tdStyle>";
182: $b .= $x;
183: $b .= '</th>';
184: }
185: $b .= "</tr>\n";
186: for ($y = 0; $y < $rowsCount; $y++) {
187: $b .= '<tr>';
188: $b .= "<th $tdStyle>";
189: $b .= $y;
190: $b .= '</th>';
191: for ($x = 0; $x < $columnsCount; $x++) {
192: $b .= "<td $tdStyle>";
193: if ($this->grid->hasCell($x, $y)) {
194: $cell = $this->grid->cell($x, $y);
195: $b .= "<table>";
196: $b .= "<tr><th $tdStyle>Left:</th><td $tdStyle>{$cell->getLeft()}</td></tr>";
197: $b .= "<tr><th $tdStyle>Top:</th><td $tdStyle>{$cell->getTop()}</td></tr>";
198: $b .= "<tr><th $tdStyle>Class:</th><td $tdStyle>{$cell->getAttribute('class')}</td></tr>";
199: $b .= "</table>";
200: } else {
201: $b .= '-';
202: }
203: $b .= '</td>';
204: }
205: $b .= "</tr>\n";
206: }
207: $b .= "</table>\n";
208:
209: return $b;
210: }
211:
212: private function _outTableRow($row) {
213: $b = '<tr>';
214: foreach ($row as $cell) {
215: $b .= $this->_outTableRowCell($cell);
216: }
217: $b .= "</tr>\n";
218: return $b;
219: }
220:
221: private function _outTableRowCell($cell) {
222: $b = '<td';
223: foreach ($cell['attributes'] as $key => $value) {
224: $b .= " $key='$value'";
225: }
226: $b .= '>';
227: $b .= $cell['content'];
228: $b .= "</td>\n";
229:
230: return $b;
231: }
232:
233: private function _buildTableRows() {
234: $columnCount = $this->_tableColumnsCount();
235: $rowCount = $this->_tableRowsCount();
236: $map = $this->_buildTableCellsMap();
237:
238: $emptyCell = array(
239: 'attributes' => array(),
240: 'content' => ''
241: );
242:
243: $rows = array();
244:
245: for ($y = 0; $y < $rowCount; $y++) {
246: $row = array();
247: for ($x = 0; $x < $columnCount; $x++) {
248: if (empty($map[$x][$y])) {
249: $row[] = $emptyCell;
250: } else if ($map[$x][$y] instanceof HtmlGrid_Cell) {
251: $attributes = array(
252: 'rowSpan' => $map[$x][$y]->getHeight(),
253: 'colSpan' => $map[$x][$y]->getWidth(),
254: );
255:
256: foreach ($map[$x][$y]->getAttributes() as $name => $value) {
257: $attributes[$name] = $value;
258: }
259:
260: $row[] = array(
261: 'attributes' => $attributes,
262: 'content' => $map[$x][$y]->getContent()
263: );
264: }
265: }
266:
267: $rows[] = $row;
268: }
269:
270:
271:
272: return $rows;
273: }
274:
275: private function _buildTableCellsMap() {
276: $map = array();
277: foreach ($this->grid->cells() as $cell)
278: for ($x = $cell->getLeft(); $x <= $cell->getRight(); $x++) {
279: for ($y = $cell->getTop(); $y <= $cell->getBottom(); $y++) {
280: $map[$x][$y] = $x == $cell->getLeft() && $y == $cell->getTop() ?
281: $cell :
282: true;
283: }
284: }
285:
286:
287: return $map;
288: }
289:
290: private function _tableColumnsCount() {
291: $max = -1;
292: foreach ($this->grid->cells() as $cell) {
293: if ($cell->getRight() > $max) {
294: $max = $cell->getRight();
295: }
296: }
297: return $max + 1;
298: }
299:
300: private function _tableRowsCount() {
301: $max = -1;
302: foreach ($this->grid->cells() as $cell) {
303: if ($cell->getBottom() > $max) {
304: $max = $cell->getBottom();
305: }
306: }
307: return $max + 1;
308: }
309:
310: }