1 | <?php |
||
2 | |||
3 | /** |
||
4 | * JPGraph v4.0.3 |
||
5 | */ |
||
6 | |||
7 | namespace Amenadiel\JpGraph\Text; |
||
8 | |||
9 | use Amenadiel\JpGraph\Util; |
||
10 | |||
11 | /** |
||
12 | * @class GTextTable |
||
13 | * // Description: |
||
14 | * // Graphic text table |
||
15 | */ |
||
16 | class GTextTable |
||
17 | { |
||
18 | public $iCells = []; |
||
19 | public $iSize = [0, 0]; // Need to be public since they are used by the cell |
||
20 | private $iWidth = 0; |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
21 | private $iHeight = 0; |
||
0 ignored issues
–
show
|
|||
22 | private $iColWidth; |
||
23 | private $iRowHeight; |
||
24 | private $iImg; |
||
0 ignored issues
–
show
|
|||
25 | private $iXPos = 0; |
||
26 | private $iYPos = 0; |
||
27 | private $iScaleXPos; |
||
28 | private $iScaleYPos; |
||
29 | private $iBGColor = ''; |
||
30 | private $iBorderColor = 'black'; |
||
31 | private $iBorderWeight = 1; |
||
32 | private $iInit = false; |
||
33 | private $iYAnchor = 'top'; |
||
34 | private $iXAnchor = 'left'; |
||
35 | |||
36 | /** |
||
37 | * First and second phase constructors |
||
38 | *-----------------------------------------------------------------. |
||
39 | */ |
||
40 | public function __construct() |
||
41 | { |
||
42 | // Empty |
||
43 | } |
||
44 | |||
45 | public function Init($aRows = 0, $aCols = 0, $aFillText = '') |
||
46 | { |
||
47 | $this->iSize[0] = $aRows; |
||
48 | $this->iSize[1] = $aCols; |
||
49 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
50 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
51 | $this->iCells[$i][$j] = new GTextTableCell($aFillText, $i, $j); |
||
52 | $this->iCells[$i][$j]->Init($this); |
||
53 | } |
||
54 | } |
||
55 | $this->iInit = true; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * Outer border of table |
||
60 | *-----------------------------------------------------------------. |
||
61 | * |
||
62 | * @param mixed $aWeight |
||
63 | * @param mixed $aColor |
||
64 | */ |
||
65 | public function SetBorder($aWeight = 1, $aColor = 'black') |
||
66 | { |
||
67 | $this->iBorderColor = $aColor; |
||
68 | $this->iBorderWeight = $aWeight; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Position in graph of table |
||
73 | *-----------------------------------------------------------------. |
||
74 | * |
||
75 | * @param mixed $aX |
||
76 | * @param mixed $aY |
||
77 | */ |
||
78 | public function SetPos($aX, $aY) |
||
79 | { |
||
80 | $this->iXPos = $aX; |
||
81 | $this->iYPos = $aY; |
||
82 | } |
||
83 | |||
84 | public function SetScalePos($aX, $aY) |
||
85 | { |
||
86 | $this->iScaleXPos = $aX; |
||
87 | $this->iScaleYPos = $aY; |
||
88 | } |
||
89 | |||
90 | public function SetAnchorPos($aXAnchor, $aYAnchor = 'top') |
||
91 | { |
||
92 | $this->iXAnchor = $aXAnchor; |
||
93 | $this->iYAnchor = $aYAnchor; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Setup country flag in a cell |
||
98 | *-----------------------------------------------------------------. |
||
99 | * |
||
100 | * @param mixed $aRow |
||
101 | * @param mixed $aCol |
||
102 | * @param mixed $aFlag |
||
103 | * @param mixed $aScale |
||
104 | * @param mixed $aMix |
||
105 | * @param mixed $aStdSize |
||
106 | */ |
||
107 | public function SetCellCountryFlag($aRow, $aCol, $aFlag, $aScale = 1.0, $aMix = 100, $aStdSize = 3) |
||
108 | { |
||
109 | $this->_chkR($aRow); |
||
110 | $this->_chkC($aCol); |
||
111 | $this->iCells[$aRow][$aCol]->SetCountryFlag($aFlag, $aScale, $aMix, $aStdSize); |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Setup image in a cell |
||
116 | *-----------------------------------------------------------------. |
||
117 | * |
||
118 | * @param mixed $aRow |
||
119 | * @param mixed $aCol |
||
120 | * @param mixed $aFile |
||
121 | * @param mixed $aScale |
||
122 | * @param mixed $aMix |
||
123 | */ |
||
124 | public function SetCellImage($aRow, $aCol, $aFile, $aScale = 1.0, $aMix = 100) |
||
125 | { |
||
126 | $this->_chkR($aRow); |
||
127 | $this->_chkC($aCol); |
||
128 | $this->iCells[$aRow][$aCol]->SetImage($aFile, $aScale, $aMix); |
||
129 | } |
||
130 | |||
131 | public function SetRowImage($aRow, $aFile, $aScale = 1.0, $aMix = 100) |
||
132 | { |
||
133 | $this->_chkR($aRow); |
||
134 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
135 | $this->iCells[$aRow][$j]->SetImage($aFile, $aScale, $aMix); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | public function SetColImage($aCol, $aFile, $aScale = 1.0, $aMix = 100) |
||
140 | { |
||
141 | $this->_chkC($aCol); |
||
142 | for ($j = 0; $j < $this->iSize[0]; ++$j) { |
||
143 | $this->iCells[$j][$aCol]->SetImage($aFile, $aScale, $aMix); |
||
144 | } |
||
145 | } |
||
146 | |||
147 | public function SetImage($aFileR1, $aScaleC1 = null, $aMixR2 = null, $aC2 = null, $aFile = null, $aScale = 1.0, $aMix = 100) |
||
148 | { |
||
149 | if ($aScaleC1 !== null && $aMixR2 !== null && $aC2 !== null && $aFile !== null) { |
||
150 | $this->_chkR($aArgR1); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
151 | $this->_chkC($aC1); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
152 | $this->_chkR($aR2); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
153 | $this->_chkC($aC2); |
||
154 | } else { |
||
155 | if ($aScaleC1 !== null) { |
||
156 | $aScale = $aScaleC1; |
||
157 | } |
||
158 | |||
159 | if ($aMixR2 !== null) { |
||
160 | $aMix = $aMixR2; |
||
161 | } |
||
162 | |||
163 | $aFile = $aFileR1; |
||
164 | $aMixR2 = $this->iSize[0] - 1; |
||
0 ignored issues
–
show
|
|||
165 | $aFileR1 = 0; |
||
0 ignored issues
–
show
|
|||
166 | $aC2 = $this->iSize[1] - 1; |
||
167 | $aScaleC1 = 0; |
||
0 ignored issues
–
show
|
|||
168 | } |
||
169 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
170 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
171 | $this->iCells[$i][$j]->SetImage($aFile, $aScale, $aMix); |
||
172 | } |
||
173 | } |
||
174 | } |
||
175 | |||
176 | public function SetCellImageConstrain($aRow, $aCol, $aType, $aVal) |
||
177 | { |
||
178 | $this->_chkR($aRow); |
||
179 | $this->_chkC($aCol); |
||
180 | $this->iCells[$aRow][$aCol]->SetImageConstrain($aType, $aVal); |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Generate a HTML version of the table |
||
185 | *-----------------------------------------------------------------. |
||
186 | */ |
||
187 | public function toString() |
||
188 | { |
||
189 | $t = '<table border=1 cellspacing=0 cellpadding=0>'; |
||
190 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
191 | $t .= '<tr>'; |
||
192 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
193 | $t .= '<td>'; |
||
194 | if ($this->iCells[$i][$j]->iMerged) { |
||
195 | $t .= 'M '; |
||
196 | } |
||
197 | |||
198 | $t .= 'val=' . $this->iCells[$i][$j]->iVal->t; |
||
199 | $t .= ' (cs=' . $this->iCells[$i][$j]->iColSpan . |
||
200 | ', rs=' . $this->iCells[$i][$j]->iRowSpan . ')'; |
||
201 | $t .= '</td>'; |
||
202 | } |
||
203 | $t .= '</tr>'; |
||
204 | } |
||
205 | $t .= '</table>'; |
||
206 | |||
207 | return $t; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Specify data for table |
||
212 | *-----------------------------------------------------------------. |
||
213 | * |
||
214 | * @param mixed $aArg1 |
||
215 | * @param null|mixed $aArg2 |
||
216 | * @param null|mixed $aArg3 |
||
217 | */ |
||
218 | public function Set($aArg1, $aArg2 = null, $aArg3 = null) |
||
219 | { |
||
220 | if ($aArg2 === null && $aArg3 === null) { |
||
221 | if (is_array($aArg1)) { |
||
222 | if (is_array($aArg1[0])) { |
||
223 | $m = safe_count($aArg1); |
||
224 | // Find the longest row |
||
225 | $n = 0; |
||
226 | for ($i = 0; $i < $m; ++$i) { |
||
227 | $n = max(safe_count($aArg1[$i]), $n); |
||
228 | } |
||
229 | |||
230 | for ($i = 0; $i < $m; ++$i) { |
||
231 | for ($j = 0; $j < $n; ++$j) { |
||
232 | if (isset($aArg1[$i][$j])) { |
||
233 | $this->_setcell($i, $j, (string) $aArg1[$i][$j]); |
||
234 | } else { |
||
235 | $this->_setcell($i, $j); |
||
236 | } |
||
237 | } |
||
238 | } |
||
239 | $this->iSize[0] = $m; |
||
240 | $this->iSize[1] = $n; |
||
241 | $this->iInit = true; |
||
242 | } else { |
||
243 | Util\JpGraphError::RaiseL(27001); |
||
244 | //('Illegal argument to GTextTable::Set(). Array must be 2 dimensional'); |
||
245 | } |
||
246 | } else { |
||
247 | Util\JpGraphError::RaiseL(27002); |
||
248 | //('Illegal argument to GTextTable::Set()'); |
||
249 | } |
||
250 | } else { |
||
251 | // Must be in the form (row,col,val) |
||
252 | $this->_chkR($aArg1); |
||
253 | $this->_chkC($aArg2); |
||
254 | $this->_setcell($aArg1, $aArg2, (string) $aArg3); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Cell margin setting |
||
260 | *---------------------------------------------------------------------. |
||
261 | * |
||
262 | * @param mixed $aArgR1 |
||
263 | * @param null|mixed $aC1 |
||
264 | * @param null|mixed $aR2 |
||
265 | * @param null|mixed $aC2 |
||
266 | * @param null|mixed $aPad |
||
267 | */ |
||
268 | public function SetPadding($aArgR1, $aC1 = null, $aR2 = null, $aC2 = null, $aPad = null) |
||
269 | { |
||
270 | if ($aC1 !== null && $aR2 !== null && $aC2 !== null && $aPad !== null) { |
||
271 | $this->_chkR($aArgR1); |
||
272 | $this->_chkC($aC1); |
||
273 | $this->_chkR($aR2); |
||
274 | $this->_chkC($aC2); |
||
275 | } else { |
||
276 | $aPad = $aArgR1; |
||
277 | $aR2 = $this->iSize[0] - 1; |
||
278 | $aArgR1 = 0; |
||
279 | $aC2 = $this->iSize[1] - 1; |
||
280 | $aC1 = 0; |
||
281 | } |
||
282 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
283 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
284 | $this->iCells[$i][$j]->SetMargin($aPad, $aPad, $aPad, $aPad); |
||
285 | } |
||
286 | } |
||
287 | } |
||
288 | |||
289 | public function SetRowPadding($aRow, $aPad) |
||
290 | { |
||
291 | $this->_chkR($aRow); |
||
292 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
293 | $this->iCells[$aRow][$j]->SetMargin($aPad, $aPad, $aPad, $aPad); |
||
294 | } |
||
295 | } |
||
296 | |||
297 | public function SetColPadding($aCol, $aPad) |
||
298 | { |
||
299 | $this->_chkC($aCol); |
||
300 | for ($j = 0; $j < $this->iSize[0]; ++$j) { |
||
301 | $this->iCells[$j][$aCol]->SetMargin($aPad, $aPad, $aPad, $aPad); |
||
302 | } |
||
303 | } |
||
304 | |||
305 | public function SetCellPadding($aRow, $aCol, $aPad) |
||
306 | { |
||
307 | $this->_chkR($aRow); |
||
308 | $this->_chkC($aCol); |
||
309 | $this->iCells[$aRow][$aCol]->SetMargin($aPad, $aPad, $aPad, $aPad); |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Cell text orientation setting |
||
314 | *---------------------------------------------------------------------. |
||
315 | * |
||
316 | * @param mixed $aArgR1 |
||
317 | * @param null|mixed $aC1 |
||
318 | * @param null|mixed $aR2 |
||
319 | * @param null|mixed $aC2 |
||
320 | * @param null|mixed $aO |
||
321 | */ |
||
322 | public function SetTextOrientation($aArgR1, $aC1 = null, $aR2 = null, $aC2 = null, $aO = null) |
||
323 | { |
||
324 | if ($aC1 !== null && $aR2 !== null && $aC2 !== null && $aPad !== null) { |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
325 | $this->_chkR($aArgR1); |
||
326 | $this->_chkC($aC1); |
||
327 | $this->_chkR($aR2); |
||
328 | $this->_chkC($aC2); |
||
329 | } else { |
||
330 | $aO = $aArgR1; |
||
331 | $aR2 = $this->iSize[0] - 1; |
||
332 | $aArgR1 = 0; |
||
333 | $aC2 = $this->iSize[1] - 1; |
||
334 | $aC1 = 0; |
||
335 | } |
||
336 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
337 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
338 | $this->iCells[$i][$j]->iVal->SetOrientation($aO); |
||
339 | } |
||
340 | } |
||
341 | } |
||
342 | |||
343 | public function SetRowTextOrientation($aRow, $aO) |
||
344 | { |
||
345 | $this->_chkR($aRow); |
||
346 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
347 | $this->iCells[$aRow][$j]->iVal->SetOrientation($aO); |
||
348 | } |
||
349 | } |
||
350 | |||
351 | public function SetColTextOrientation($aCol, $aO) |
||
352 | { |
||
353 | $this->_chkC($aCol); |
||
354 | for ($j = 0; $j < $this->iSize[0]; ++$j) { |
||
355 | $this->iCells[$j][$aCol]->iVal->SetOrientation($aO); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | public function SetCellTextOrientation($aRow, $aCol, $aO) |
||
360 | { |
||
361 | $this->_chkR($aRow); |
||
362 | $this->_chkC($aCol); |
||
363 | $this->iCells[$aRow][$aCol]->iVal->SetOrientation($aO); |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * Font color setting |
||
368 | *---------------------------------------------------------------------. |
||
369 | * |
||
370 | * @param mixed $aArgR1 |
||
371 | * @param null|mixed $aC1 |
||
372 | * @param null|mixed $aR2 |
||
373 | * @param null|mixed $aC2 |
||
374 | * @param null|mixed $aArg |
||
375 | */ |
||
376 | public function SetColor($aArgR1, $aC1 = null, $aR2 = null, $aC2 = null, $aArg = null) |
||
377 | { |
||
378 | if ($aC1 !== null && $aR2 !== null && $aC2 !== null && $aArg !== null) { |
||
379 | $this->_chkR($aArgR1); |
||
380 | $this->_chkC($aC1); |
||
381 | $this->_chkR($aR2); |
||
382 | $this->_chkC($aC2); |
||
383 | } else { |
||
384 | $aArg = $aArgR1; |
||
385 | $aR2 = $this->iSize[0] - 1; |
||
386 | $aArgR1 = 0; |
||
387 | $aC2 = $this->iSize[1] - 1; |
||
388 | $aC1 = 0; |
||
389 | } |
||
390 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
391 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
392 | $this->iCells[$i][$j]->SetFontColor($aArg); |
||
393 | } |
||
394 | } |
||
395 | } |
||
396 | |||
397 | public function SetRowColor($aRow, $aColor) |
||
398 | { |
||
399 | $this->_chkR($aRow); |
||
400 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
401 | $this->iCells[$aRow][$j]->SetFontColor($aColor); |
||
402 | } |
||
403 | } |
||
404 | |||
405 | public function SetColColor($aCol, $aColor) |
||
406 | { |
||
407 | $this->_chkC($aCol); |
||
408 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
409 | $this->iCells[$i][$aCol]->SetFontColor($aColor); |
||
410 | } |
||
411 | } |
||
412 | |||
413 | public function SetCellColor($aRow, $aCol, $aColor) |
||
414 | { |
||
415 | $this->_chkR($aRow); |
||
416 | $this->_chkC($aCol); |
||
417 | $this->iCells[$aRow][$aCol]->SetFontColor($aColor); |
||
418 | } |
||
419 | |||
420 | /** |
||
421 | * Fill color settings |
||
422 | *---------------------------------------------------------------------. |
||
423 | * |
||
424 | * @param mixed $aArgR1 |
||
425 | * @param null|mixed $aC1 |
||
426 | * @param null|mixed $aR2 |
||
427 | * @param null|mixed $aC2 |
||
428 | * @param null|mixed $aArg |
||
429 | */ |
||
430 | public function SetFillColor($aArgR1, $aC1 = null, $aR2 = null, $aC2 = null, $aArg = null) |
||
431 | { |
||
432 | if ($aC1 !== null && $aR2 !== null && $aC2 !== null && $aArg !== null) { |
||
433 | $this->_chkR($aArgR1); |
||
434 | $this->_chkC($aC1); |
||
435 | $this->_chkR($aR2); |
||
436 | $this->_chkC($aC2); |
||
437 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
438 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
439 | $this->iCells[$i][$j]->SetFillColor($aArg); |
||
440 | } |
||
441 | } |
||
442 | } else { |
||
443 | $this->iBGColor = $aArgR1; |
||
444 | } |
||
445 | } |
||
446 | |||
447 | public function SetRowFillColor($aRow, $aColor) |
||
448 | { |
||
449 | $this->_chkR($aRow); |
||
450 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
451 | $this->iCells[$aRow][$j]->SetFillColor($aColor); |
||
452 | } |
||
453 | } |
||
454 | |||
455 | public function SetColFillColor($aCol, $aColor) |
||
456 | { |
||
457 | $this->_chkC($aCol); |
||
458 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
459 | $this->iCells[$i][$aCol]->SetFillColor($aColor); |
||
460 | } |
||
461 | } |
||
462 | |||
463 | public function SetCellFillColor($aRow, $aCol, $aColor) |
||
464 | { |
||
465 | $this->_chkR($aRow); |
||
466 | $this->_chkC($aCol); |
||
467 | $this->iCells[$aRow][$aCol]->SetFillColor($aColor); |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * Font family setting |
||
472 | *---------------------------------------------------------------------. |
||
473 | */ |
||
474 | public function SetFont() |
||
475 | { |
||
476 | $numargs = func_num_args(); |
||
477 | if ($numargs == 2 || $numargs == 3) { |
||
478 | $aFF = func_get_arg(0); |
||
479 | $aFS = func_get_arg(1); |
||
480 | if ($numargs == 3) { |
||
481 | $aFSize = func_get_arg(2); |
||
482 | } else { |
||
483 | $aFSize = 10; |
||
484 | } |
||
485 | |||
486 | $aR2 = $this->iSize[0] - 1; |
||
487 | $aR1 = 0; |
||
488 | $aC2 = $this->iSize[1] - 1; |
||
489 | $aC1 = 0; |
||
490 | } elseif ($numargs == 6 || $numargs == 7) { |
||
491 | $aR1 = func_get_arg(0); |
||
492 | $aC1 = func_get_arg(1); |
||
493 | $aR2 = func_get_arg(2); |
||
494 | $aC2 = func_get_arg(3); |
||
495 | $aFF = func_get_arg(4); |
||
496 | $aFS = func_get_arg(5); |
||
497 | if ($numargs == 7) { |
||
498 | $aFSize = func_get_arg(6); |
||
499 | } else { |
||
500 | $aFSize = 10; |
||
501 | } |
||
502 | } else { |
||
503 | Util\JpGraphError::RaiseL(27003); |
||
504 | //('Wrong number of arguments to GTextTable::SetColor()'); |
||
505 | } |
||
506 | $this->_chkR($aR1); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
507 | $this->_chkC($aC1); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
508 | $this->_chkR($aR2); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
509 | $this->_chkC($aC2); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
510 | for ($i = $aR1; $i <= $aR2; ++$i) { |
||
511 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
512 | $this->iCells[$i][$j]->SetFont($aFF, $aFS, $aFSize); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||
513 | } |
||
514 | } |
||
515 | } |
||
516 | |||
517 | public function SetRowFont($aRow, $aFF, $aFS, $aFSize = 10) |
||
518 | { |
||
519 | $this->_chkR($aRow); |
||
520 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
521 | $this->iCells[$aRow][$j]->SetFont($aFF, $aFS, $aFSize); |
||
522 | } |
||
523 | } |
||
524 | |||
525 | public function SetColFont($aCol, $aFF, $aFS, $aFSize = 10) |
||
526 | { |
||
527 | $this->_chkC($aCol); |
||
528 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
529 | $this->iCells[$i][$aCol]->SetFont($aFF, $aFS, $aFSize); |
||
530 | } |
||
531 | } |
||
532 | |||
533 | public function SetCellFont($aRow, $aCol, $aFF, $aFS, $aFSize = 10) |
||
534 | { |
||
535 | $this->_chkR($aRow); |
||
536 | $this->_chkC($aCol); |
||
537 | $this->iCells[$aRow][$aCol]->SetFont($aFF, $aFS, $aFSize); |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Cell align settings |
||
542 | *---------------------------------------------------------------------. |
||
543 | * |
||
544 | * @param null|mixed $aR1HAlign |
||
545 | * @param null|mixed $aC1VAlign |
||
546 | * @param null|mixed $aR2 |
||
547 | * @param null|mixed $aC2 |
||
548 | * @param null|mixed $aHArg |
||
549 | * @param mixed $aVArg |
||
550 | */ |
||
551 | public function SetAlign($aR1HAlign = null, $aC1VAlign = null, $aR2 = null, $aC2 = null, $aHArg = null, $aVArg = 'center') |
||
552 | { |
||
553 | if ($aC1VAlign !== null && $aR2 !== null && $aC2 !== null && $aHArg !== null) { |
||
554 | $this->_chkR($aR1HAlign); |
||
555 | $this->_chkC($aC1VAlign); |
||
556 | $this->_chkR($aR2); |
||
557 | $this->_chkC($aC2); |
||
558 | } else { |
||
559 | if ($aR1HAlign === null) { |
||
560 | Util\JpGraphError::RaiseL(27010); |
||
561 | } |
||
562 | if ($aC1VAlign === null) { |
||
563 | $aC1VAlign = 'center'; |
||
564 | } |
||
565 | $aHArg = $aR1HAlign; |
||
566 | $aVArg = $aC1VAlign === null ? 'center' : $aC1VAlign; |
||
567 | $aR2 = $this->iSize[0] - 1; |
||
568 | $aR1HAlign = 0; |
||
569 | $aC2 = $this->iSize[1] - 1; |
||
570 | $aC1VAlign = 0; |
||
571 | } |
||
572 | for ($i = $aR1HAlign; $i <= $aR2; ++$i) { |
||
573 | for ($j = $aC1VAlign; $j <= $aC2; ++$j) { |
||
574 | $this->iCells[$i][$j]->SetAlign($aHArg, $aVArg); |
||
575 | } |
||
576 | } |
||
577 | } |
||
578 | |||
579 | public function SetCellAlign($aRow, $aCol, $aHorAlign, $aVertAlign = 'bottom') |
||
580 | { |
||
581 | $this->_chkR($aRow); |
||
582 | $this->_chkC($aCol); |
||
583 | $this->iCells[$aRow][$aCol]->SetAlign($aHorAlign, $aVertAlign); |
||
584 | } |
||
585 | |||
586 | public function SetRowAlign($aRow, $aHorAlign, $aVertAlign = 'bottom') |
||
587 | { |
||
588 | $this->_chkR($aRow); |
||
589 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
590 | $this->iCells[$aRow][$j]->SetAlign($aHorAlign, $aVertAlign); |
||
591 | } |
||
592 | } |
||
593 | |||
594 | public function SetColAlign($aCol, $aHorAlign, $aVertAlign = 'bottom') |
||
595 | { |
||
596 | $this->_chkC($aCol); |
||
597 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
598 | $this->iCells[$i][$aCol]->SetAlign($aHorAlign, $aVertAlign); |
||
599 | } |
||
600 | } |
||
601 | |||
602 | /** |
||
603 | * Cell number format |
||
604 | *---------------------------------------------------------------------. |
||
605 | * |
||
606 | * @param mixed $aArgR1 |
||
607 | * @param null|mixed $aC1 |
||
608 | * @param null|mixed $aR2 |
||
609 | * @param null|mixed $aC2 |
||
610 | * @param null|mixed $aArg |
||
611 | */ |
||
612 | public function SetNumberFormat($aArgR1, $aC1 = null, $aR2 = null, $aC2 = null, $aArg = null) |
||
613 | { |
||
614 | if ($aC1 !== null && $aR2 !== null && $aC2 !== null && $aArg !== null) { |
||
615 | $this->_chkR($aArgR1); |
||
616 | $this->_chkC($aC1); |
||
617 | $this->_chkR($aR2); |
||
618 | $this->_chkC($aC2); |
||
619 | } else { |
||
620 | $aArg = $aArgR1; |
||
621 | $aR2 = $this->iSize[0] - 1; |
||
622 | $aArgR1 = 0; |
||
623 | $aC2 = $this->iSize[1] - 1; |
||
624 | $aC1 = 0; |
||
625 | } |
||
626 | if (!is_string($aArg)) { |
||
627 | Util\JpGraphError::RaiseL(27013); // argument must be a string |
||
628 | } |
||
629 | for ($i = $aArgR1; $i <= $aR2; ++$i) { |
||
630 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
631 | $this->iCells[$i][$j]->SetNumberFormat($aArg); |
||
632 | } |
||
633 | } |
||
634 | } |
||
635 | |||
636 | public function SetRowNumberFormat($aRow, $aF) |
||
637 | { |
||
638 | $this->_chkR($aRow); |
||
639 | if (!is_string($aF)) { |
||
640 | Util\JpGraphError::RaiseL(27013); // argument must be a string |
||
641 | } |
||
642 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
643 | $this->iCells[$aRow][$j]->SetNumberFormat($aF); |
||
644 | } |
||
645 | } |
||
646 | |||
647 | public function SetColNumberFormat($aCol, $aF) |
||
648 | { |
||
649 | $this->_chkC($aCol); |
||
650 | if (!is_string($aF)) { |
||
651 | Util\JpGraphError::RaiseL(27013); // argument must be a string |
||
652 | } |
||
653 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
654 | $this->iCells[$i][$aCol]->SetNumberFormat($aF); |
||
655 | } |
||
656 | } |
||
657 | |||
658 | public function SetCellNumberFormat($aRow, $aCol, $aF) |
||
659 | { |
||
660 | $this->_chkR($aRow); |
||
661 | $this->_chkC($aCol); |
||
662 | if (!is_string($aF)) { |
||
663 | Util\JpGraphError::RaiseL(27013); // argument must be a string |
||
664 | } |
||
665 | $this->iCells[$aRow][$aCol]->SetNumberFormat($aF); |
||
666 | } |
||
667 | |||
668 | /** |
||
669 | * Set row and column min size |
||
670 | *---------------------------------------------------------------------. |
||
671 | * |
||
672 | * @param mixed $aColWidth |
||
673 | * @param null|mixed $aWidth |
||
674 | */ |
||
675 | public function SetMinColWidth($aColWidth, $aWidth = null) |
||
676 | { |
||
677 | // If there is only one argument this means that all |
||
678 | // columns get set to the same width |
||
679 | if ($aWidth === null) { |
||
680 | for ($i = 0; $i < $this->iSize[1]; ++$i) { |
||
681 | $this->iColWidth[$i] = $aColWidth; |
||
682 | } |
||
683 | } else { |
||
684 | $this->_chkC($aColWidth); |
||
685 | $this->iColWidth[$aColWidth] = $aWidth; |
||
686 | } |
||
687 | } |
||
688 | |||
689 | public function SetMinRowHeight($aRowHeight, $aHeight = null) |
||
690 | { |
||
691 | // If there is only one argument this means that all |
||
692 | // rows get set to the same height |
||
693 | if ($aHeight === null) { |
||
694 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
695 | $this->iRowHeight[$i] = $aRowHeight; |
||
696 | } |
||
697 | } else { |
||
698 | $this->_chkR($aRowHeight); |
||
699 | $this->iRowHeight[$aRowHeight] = $aHeight; |
||
700 | } |
||
701 | } |
||
702 | |||
703 | /** |
||
704 | * Grid line settings |
||
705 | *---------------------------------------------------------------------. |
||
706 | * |
||
707 | * @param mixed $aWeight |
||
708 | * @param mixed $aColor |
||
709 | * @param mixed $aStyle |
||
710 | */ |
||
711 | public function SetGrid($aWeight = 1, $aColor = 'black', $aStyle = TGRID_SINGLE) |
||
712 | { |
||
713 | $rc = $this->iSize[0]; |
||
714 | $cc = $this->iSize[1]; |
||
715 | for ($i = 0; $i < $rc; ++$i) { |
||
716 | for ($j = 0; $j < $cc; ++$j) { |
||
717 | $this->iCells[$i][$j]->SetGridColor($aColor, $aColor); |
||
718 | $this->iCells[$i][$j]->SetGridWeight($aWeight, $aWeight); |
||
719 | $this->iCells[$i][$j]->SetGridStyle($aStyle); |
||
720 | } |
||
721 | } |
||
722 | } |
||
723 | |||
724 | public function SetColGrid($aCol, $aWeight = 1, $aColor = 'black', $aStyle = TGRID_SINGLE) |
||
725 | { |
||
726 | $this->_chkC($aCol); |
||
727 | for ($i = 0; $i < $this->iSize[0]; ++$i) { |
||
728 | $this->iCells[$i][$aCol]->SetGridWeight($aWeight); |
||
729 | $this->iCells[$i][$aCol]->SetGridColor($aColor); |
||
730 | $this->iCells[$i][$aCol]->SetGridStyle($aStyle); |
||
731 | } |
||
732 | } |
||
733 | |||
734 | public function SetRowGrid($aRow, $aWeight = 1, $aColor = 'black', $aStyle = TGRID_SINGLE) |
||
735 | { |
||
736 | $this->_chkR($aRow); |
||
737 | for ($j = 0; $j < $this->iSize[1]; ++$j) { |
||
738 | $this->iCells[$aRow][$j]->SetGridWeight(null, $aWeight); |
||
739 | $this->iCells[$aRow][$j]->SetGridColor(null, $aColor); |
||
740 | $this->iCells[$aRow][$j]->SetGridStyle(null, $aStyle); |
||
741 | } |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * Merge cells |
||
746 | *---------------------------------------------------------------------. |
||
747 | * |
||
748 | * @param mixed $aRow |
||
749 | * @param mixed $aHAlign |
||
750 | * @param mixed $aVAlign |
||
751 | */ |
||
752 | public function MergeRow($aRow, $aHAlign = 'center', $aVAlign = 'center') |
||
753 | { |
||
754 | $this->_chkR($aRow); |
||
755 | $this->MergeCells($aRow, 0, $aRow, $this->iSize[1] - 1, $aHAlign, $aVAlign); |
||
756 | } |
||
757 | |||
758 | public function MergeCol($aCol, $aHAlign = 'center', $aVAlign = 'center') |
||
759 | { |
||
760 | $this->_chkC($aCol); |
||
761 | $this->MergeCells(0, $aCol, $this->iSize[0] - 1, $aCol, $aHAlign, $aVAlign); |
||
762 | } |
||
763 | |||
764 | public function MergeCells($aR1, $aC1, $aR2, $aC2, $aHAlign = 'center', $aVAlign = 'center') |
||
765 | { |
||
766 | if ($aR1 > $aR2 || $aC1 > $aC2) { |
||
767 | Util\JpGraphError::RaiseL(27004); |
||
768 | //('GTextTable::MergeCells(). Specified cell range to be merged is not valid.'); |
||
769 | } |
||
770 | $this->_chkR($aR1); |
||
771 | $this->_chkC($aC1); |
||
772 | $this->_chkR($aR2); |
||
773 | $this->_chkC($aC2); |
||
774 | $rspan = $aR2 - $aR1 + 1; |
||
775 | $cspan = $aC2 - $aC1 + 1; |
||
776 | // Setup the parent cell for this merged group |
||
777 | if ($this->iCells[$aR1][$aC1]->IsMerged()) { |
||
778 | Util\JpGraphError::RaiseL(27005, $aR1, $aC1, $aR2, $aC2); |
||
779 | //("Cannot merge already merged cells in the range ($aR1,$aC1), ($aR2,$aC2)"); |
||
780 | } |
||
781 | $this->iCells[$aR1][$aC1]->SetRowColSpan($rspan, $cspan); |
||
782 | $this->iCells[$aR1][$aC1]->SetAlign($aHAlign, $aVAlign); |
||
783 | for ($i = $aR1; $i <= $aR2; ++$i) { |
||
784 | for ($j = $aC1; $j <= $aC2; ++$j) { |
||
785 | if (!($i == $aR1 && $j == $aC1)) { |
||
786 | if ($this->iCells[$i][$j]->IsMerged()) { |
||
787 | Util\JpGraphError::RaiseL(27005, $aR1, $aC1, $aR2, $aC2); |
||
788 | //("Cannot merge already merged cells in the range ($aR1,$aC1), ($aR2,$aC2)"); |
||
789 | } |
||
790 | $this->iCells[$i][$j]->SetMerged($aR1, $aC1, true); |
||
791 | } |
||
792 | } |
||
793 | } |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * CSIM methods |
||
798 | *---------------------------------------------------------------------. |
||
799 | * |
||
800 | * @param mixed $aTarget |
||
801 | * @param null|mixed $aAlt |
||
802 | * @param mixed $aAutoTarget |
||
803 | */ |
||
804 | public function SetCSIMTarget($aTarget, $aAlt = null, $aAutoTarget = false) |
||
805 | { |
||
806 | $m = $this->iSize[0]; |
||
807 | $n = $this->iSize[1]; |
||
808 | $csim = ''; |
||
0 ignored issues
–
show
|
|||
809 | for ($i = 0; $i < $m; ++$i) { |
||
810 | for ($j = 0; $j < $n; ++$j) { |
||
811 | if ($aAutoTarget) { |
||
812 | $t = $aTarget . "?row=${i}&col=${j}"; |
||
813 | } else { |
||
814 | $t = $aTarget; |
||
815 | } |
||
816 | |||
817 | $this->iCells[$i][$j]->SetCSIMTarget($t, $aAlt); |
||
818 | } |
||
819 | } |
||
820 | } |
||
821 | |||
822 | public function SetCellCSIMTarget($aRow, $aCol, $aTarget, $aAlt = null) |
||
823 | { |
||
824 | $this->_chkR($aRow); |
||
825 | $this->_chkC($aCol); |
||
826 | $this->iCells[$aRow][$aCol]->SetCSIMTarget($aTarget, $aAlt); |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Private methods |
||
831 | *---------------------------------------------------------------------. |
||
832 | */ |
||
833 | public function GetCSIMAreas() |
||
834 | { |
||
835 | $m = $this->iSize[0]; |
||
836 | $n = $this->iSize[1]; |
||
837 | $csim = ''; |
||
838 | for ($i = 0; $i < $m; ++$i) { |
||
839 | for ($j = 0; $j < $n; ++$j) { |
||
840 | $csim .= $this->iCells[$i][$j]->GetCSIMArea(); |
||
841 | } |
||
842 | } |
||
843 | |||
844 | return $csim; |
||
845 | } |
||
846 | |||
847 | public function _chkC($aCol) |
||
848 | { |
||
849 | if (!$this->iInit) { |
||
850 | Util\JpGraphError::Raise(27014); // Table not initialized |
||
851 | } |
||
852 | if ($aCol < 0 || $aCol >= $this->iSize[1]) { |
||
853 | Util\JpGraphError::RaiseL(27006, $aCol); |
||
854 | } |
||
855 | |||
856 | //("GTextTable:\nColumn argument ($aCol) is outside specified table size."); |
||
857 | } |
||
858 | |||
859 | public function _chkR($aRow) |
||
860 | { |
||
861 | if (!$this->iInit) { |
||
862 | Util\JpGraphError::Raise(27014); // Table not initialized |
||
863 | } |
||
864 | if ($aRow < 0 || $aRow >= $this->iSize[0]) { |
||
865 | Util\JpGraphError::RaiseL(27007, $aRow); |
||
866 | } |
||
867 | |||
868 | //("GTextTable:\nRow argument ($aRow) is outside specified table size."); |
||
869 | } |
||
870 | |||
871 | public function _getScalePos() |
||
872 | { |
||
873 | if ($this->iScaleXPos === null || $this->iScaleYPos === null) { |
||
874 | return false; |
||
875 | } |
||
876 | |||
877 | return [$this->iScaleXPos, $this->iScaleYPos]; |
||
878 | } |
||
879 | |||
880 | public function _autoSizeTable($aImg) |
||
881 | { |
||
882 | // Get maximum column width and row height |
||
883 | $m = $this->iSize[0]; |
||
884 | $n = $this->iSize[1]; |
||
885 | $w = 1; |
||
0 ignored issues
–
show
|
|||
886 | $h = 1; |
||
0 ignored issues
–
show
|
|||
887 | |||
888 | // Get maximum row height per row |
||
889 | for ($i = 0; $i < $m; ++$i) { |
||
890 | $h = 0; |
||
891 | for ($j = 0; $j < $n; ++$j) { |
||
892 | $h = max($h, $this->iCells[$i][$j]->GetHeight($aImg)); |
||
893 | } |
||
894 | if (isset($this->iRowHeight[$i])) { |
||
895 | $this->iRowHeight[$i] = max($h, $this->iRowHeight[$i]); |
||
896 | } else { |
||
897 | $this->iRowHeight[$i] = $h; |
||
898 | } |
||
899 | } |
||
900 | |||
901 | // Get maximum col width per columns |
||
902 | for ($j = 0; $j < $n; ++$j) { |
||
903 | $w = 0; |
||
904 | for ($i = 0; $i < $m; ++$i) { |
||
905 | $w = max($w, $this->iCells[$i][$j]->GetWidth($aImg)); |
||
906 | } |
||
907 | if (isset($this->iColWidth[$j])) { |
||
908 | $this->iColWidth[$j] = max($w, $this->iColWidth[$j]); |
||
909 | } else { |
||
910 | $this->iColWidth[$j] = $w; |
||
911 | } |
||
912 | } |
||
913 | } |
||
914 | |||
915 | public function _setcell($aRow, $aCol, $aVal = '') |
||
916 | { |
||
917 | if (isset($this->iCells[$aRow][$aCol])) { |
||
918 | $this->iCells[$aRow][$aCol]->Set($aVal); |
||
919 | } else { |
||
920 | $this->iCells[$aRow][$aCol] = new GTextTableCell((string) $aVal, $aRow, $aCol); |
||
921 | $this->iCells[$aRow][$aCol]->Init($this); |
||
922 | } |
||
923 | } |
||
924 | |||
925 | public function StrokeWithScale($aImg, $aXScale, $aYScale) |
||
926 | { |
||
927 | if (is_numeric($this->iScaleXPos) && is_numeric($this->iScaleYPos)) { |
||
928 | $x = round($aXScale->Translate($this->iScaleXPos)); |
||
929 | $y = round($aYScale->Translate($this->iScaleYPos)); |
||
930 | $this->Stroke($aImg, $x, $y); |
||
931 | } else { |
||
932 | $this->Stroke($aImg); |
||
933 | } |
||
934 | } |
||
935 | |||
936 | public function Stroke($aImg, $aX = null, $aY = null) |
||
937 | { |
||
938 | if ($aX !== null && $aY !== null) { |
||
939 | $this->iXPos = $aX; |
||
940 | $this->iYPos = $aY; |
||
941 | } |
||
942 | |||
943 | $rc = $this->iSize[0]; // row count |
||
944 | $cc = $this->iSize[1]; // column count |
||
945 | |||
946 | if ($rc == 0 || $cc == 0) { |
||
947 | Util\JpGraphError::RaiseL(27009); |
||
948 | } |
||
949 | |||
950 | // Adjust margins of each cell based on the weight of the grid. Each table grid line |
||
951 | // is actually occupying the left side and top part of each cell. |
||
952 | for ($j = 0; $j < $cc; ++$j) { |
||
953 | $this->iCells[0][$j]->iMarginTop += $this->iBorderWeight; |
||
954 | } |
||
955 | for ($i = 0; $i < $rc; ++$i) { |
||
956 | $this->iCells[$i][0]->iMarginLeft += $this->iBorderWeight; |
||
957 | } |
||
958 | for ($i = 0; $i < $rc; ++$i) { |
||
959 | for ($j = 0; $j < $cc; ++$j) { |
||
960 | $this->iCells[$i][$j]->AdjustMarginsForGrid(); |
||
961 | } |
||
962 | } |
||
963 | |||
964 | // adjust row and column size depending on cell content |
||
965 | $this->_autoSizeTable($aImg); |
||
966 | |||
967 | if ($this->iSize[1] != safe_count($this->iColWidth) || $this->iSize[0] != safe_count($this->iRowHeight)) { |
||
968 | Util\JpGraphError::RaiseL(27008); |
||
969 | //('Column and row size arrays must match the dimesnions of the table'); |
||
970 | } |
||
971 | |||
972 | // Find out overall table size |
||
973 | $width = 0; |
||
974 | for ($i = 0; $i < $cc; ++$i) { |
||
975 | $width += $this->iColWidth[$i]; |
||
976 | } |
||
977 | $height = 0; |
||
978 | for ($i = 0; $i < $rc; ++$i) { |
||
979 | $height += $this->iRowHeight[$i]; |
||
980 | } |
||
981 | |||
982 | // Adjust the X,Y position to alway be at the top left corner |
||
983 | // The anchor position, i.e. how the client want to interpret the specified |
||
984 | // x and y coordinate must be taken into account |
||
985 | switch (strtolower($this->iXAnchor)) { |
||
986 | case 'left': |
||
987 | break; |
||
988 | case 'center': |
||
989 | $this->iXPos -= round($width / 2); |
||
990 | |||
991 | break; |
||
992 | case 'right': |
||
993 | $this->iXPos -= $width; |
||
994 | |||
995 | break; |
||
996 | } |
||
997 | switch (strtolower($this->iYAnchor)) { |
||
998 | case 'top': |
||
999 | break; |
||
1000 | case 'center': |
||
1001 | case 'middle': |
||
1002 | $this->iYPos -= round($height / 2); |
||
1003 | |||
1004 | break; |
||
1005 | case 'bottom': |
||
1006 | $this->iYPos -= $height; |
||
1007 | |||
1008 | break; |
||
1009 | } |
||
1010 | |||
1011 | // Set the overall background color of the table if set |
||
1012 | if ($this->iBGColor !== '') { |
||
1013 | $aImg->SetColor($this->iBGColor); |
||
1014 | $aImg->FilledRectangle($this->iXPos, $this->iYPos, $this->iXPos + $width, $this->iYPos + $height); |
||
1015 | } |
||
1016 | |||
1017 | // Stroke all cells |
||
1018 | $rpos = $this->iYPos; |
||
1019 | for ($i = 0; $i < $rc; ++$i) { |
||
1020 | $cpos = $this->iXPos; |
||
1021 | for ($j = 0; $j < $cc; ++$j) { |
||
1022 | // Calculate width and height of this cell if it is spanning |
||
1023 | // more than one column or row |
||
1024 | $cwidth = 0; |
||
1025 | for ($k = 0; $k < $this->iCells[$i][$j]->iColSpan; ++$k) { |
||
1026 | $cwidth += $this->iColWidth[$j + $k]; |
||
1027 | } |
||
1028 | $cheight = 0; |
||
1029 | for ($k = 0; $k < $this->iCells[$i][$j]->iRowSpan; ++$k) { |
||
1030 | $cheight += $this->iRowHeight[$i + $k]; |
||
1031 | } |
||
1032 | |||
1033 | $this->iCells[$i][$j]->Stroke($aImg, $cpos, $rpos, $cwidth, $cheight); |
||
1034 | $cpos += $this->iColWidth[$j]; |
||
1035 | } |
||
1036 | $rpos += $this->iRowHeight[$i]; |
||
1037 | } |
||
1038 | |||
1039 | // Stroke outer border |
||
1040 | $aImg->SetColor($this->iBorderColor); |
||
1041 | if ($this->iBorderWeight == 1) { |
||
1042 | $aImg->Rectangle($this->iXPos, $this->iYPos, $this->iXPos + $width, $this->iYPos + $height); |
||
1043 | } else { |
||
1044 | for ($i = 0; $i < $this->iBorderWeight; ++$i) { |
||
1045 | $aImg->Rectangle( |
||
1046 | $this->iXPos + $i, |
||
1047 | $this->iYPos + $i, |
||
1048 | $this->iXPos + $width - 1 + $this->iBorderWeight - $i, |
||
1049 | $this->iYPos + $height - 1 + $this->iBorderWeight - $i |
||
1050 | ); |
||
1051 | } |
||
1052 | } |
||
1053 | } |
||
1054 | } |
||
1055 |