1
|
|
|
<?php |
|
|
|
|
2
|
|
|
namespace Amenadiel\JpGraph\Graph; |
3
|
|
|
|
4
|
|
|
use Amenadiel\JpGraph\Util; |
5
|
|
|
|
6
|
|
|
/*======================================================================= |
7
|
|
|
// File: JPGRAPH_GANTT.PHP |
8
|
|
|
// Description: JpGraph Gantt plot extension |
9
|
|
|
// Created: 2001-11-12 |
10
|
|
|
// Ver: $Id: jpgraph_gantt.php 1809 2009-09-09 13:07:33Z ljp $ |
11
|
|
|
// |
12
|
|
|
// Copyright (c) Asial Corporation. All rights reserved. |
13
|
|
|
//======================================================================== |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
require_once 'jpgraph_plotband.php'; |
17
|
|
|
require_once 'jpgraph_iconplot.php'; |
18
|
|
|
require_once 'jpgraph_plotmark.inc.php'; |
19
|
|
|
|
20
|
|
|
// Maximum size for Automatic Gantt chart |
21
|
|
|
define('MAX_GANTTIMG_SIZE_W', 8000); |
22
|
|
|
define('MAX_GANTTIMG_SIZE_H', 5000); |
23
|
|
|
|
24
|
|
|
// Scale Header types |
25
|
|
|
define("GANTT_HDAY", 1); |
26
|
|
|
define("GANTT_HWEEK", 2); |
27
|
|
|
define("GANTT_HMONTH", 4); |
28
|
|
|
define("GANTT_HYEAR", 8); |
29
|
|
|
define("GANTT_HHOUR", 16); |
30
|
|
|
define("GANTT_HMIN", 32); |
31
|
|
|
|
32
|
|
|
// Bar patterns |
33
|
|
|
define("GANTT_RDIAG", BAND_RDIAG); // Right diagonal lines |
34
|
|
|
define("GANTT_LDIAG", BAND_LDIAG); // Left diagonal lines |
35
|
|
|
define("GANTT_SOLID", BAND_SOLID); // Solid one color |
36
|
|
|
define("GANTT_VLINE", BAND_VLINE); // Vertical lines |
37
|
|
|
define("GANTT_HLINE", BAND_HLINE); // Horizontal lines |
38
|
|
|
define("GANTT_3DPLANE", BAND_3DPLANE); // "3D" Plane |
39
|
|
|
define("GANTT_HVCROSS", BAND_HVCROSS); // Vertical/Hor crosses |
40
|
|
|
define("GANTT_DIAGCROSS", BAND_DIAGCROSS); // Diagonal crosses |
41
|
|
|
|
42
|
|
|
// Conversion constant |
43
|
|
|
define("SECPERDAY", 3600 * 24); |
44
|
|
|
|
45
|
|
|
// Locales. ONLY KEPT FOR BACKWARDS COMPATIBILITY |
46
|
|
|
// You should use the proper locale strings directly |
47
|
|
|
// from now on. |
48
|
|
|
define("LOCALE_EN", "en_UK"); |
49
|
|
|
define("LOCALE_SV", "sv_SE"); |
50
|
|
|
|
51
|
|
|
// Layout of bars |
52
|
|
|
define("GANTT_EVEN", 1); |
53
|
|
|
define("GANTT_FROMTOP", 2); |
54
|
|
|
|
55
|
|
|
// Style for minute header |
56
|
|
|
define("MINUTESTYLE_MM", 0); // 15 |
57
|
|
|
define("MINUTESTYLE_CUSTOM", 2); // Custom format |
58
|
|
|
|
59
|
|
|
// Style for hour header |
60
|
|
|
define("HOURSTYLE_HM24", 0); // 13:10 |
61
|
|
|
define("HOURSTYLE_HMAMPM", 1); // 1:10pm |
62
|
|
|
define("HOURSTYLE_H24", 2); // 13 |
63
|
|
|
define("HOURSTYLE_HAMPM", 3); // 1pm |
64
|
|
|
define("HOURSTYLE_CUSTOM", 4); // User defined |
65
|
|
|
|
66
|
|
|
// Style for day header |
67
|
|
|
define("DAYSTYLE_ONELETTER", 0); // "M" |
68
|
|
|
define("DAYSTYLE_LONG", 1); // "Monday" |
69
|
|
|
define("DAYSTYLE_LONGDAYDATE1", 2); // "Monday 23 Jun" |
70
|
|
|
define("DAYSTYLE_LONGDAYDATE2", 3); // "Monday 23 Jun 2003" |
71
|
|
|
define("DAYSTYLE_SHORT", 4); // "Mon" |
72
|
|
|
define("DAYSTYLE_SHORTDAYDATE1", 5); // "Mon 23/6" |
73
|
|
|
define("DAYSTYLE_SHORTDAYDATE2", 6); // "Mon 23 Jun" |
74
|
|
|
define("DAYSTYLE_SHORTDAYDATE3", 7); // "Mon 23" |
75
|
|
|
define("DAYSTYLE_SHORTDATE1", 8); // "23/6" |
76
|
|
|
define("DAYSTYLE_SHORTDATE2", 9); // "23 Jun" |
77
|
|
|
define("DAYSTYLE_SHORTDATE3", 10); // "Mon 23" |
78
|
|
|
define("DAYSTYLE_SHORTDATE4", 11); // "23" |
79
|
|
|
define("DAYSTYLE_CUSTOM", 12); // "M" |
80
|
|
|
|
81
|
|
|
// Styles for week header |
82
|
|
|
define("WEEKSTYLE_WNBR", 0); |
83
|
|
|
define("WEEKSTYLE_FIRSTDAY", 1); |
84
|
|
|
define("WEEKSTYLE_FIRSTDAY2", 2); |
85
|
|
|
define("WEEKSTYLE_FIRSTDAYWNBR", 3); |
86
|
|
|
define("WEEKSTYLE_FIRSTDAY2WNBR", 4); |
87
|
|
|
|
88
|
|
|
// Styles for month header |
89
|
|
|
define("MONTHSTYLE_SHORTNAME", 0); |
90
|
|
|
define("MONTHSTYLE_LONGNAME", 1); |
91
|
|
|
define("MONTHSTYLE_LONGNAMEYEAR2", 2); |
92
|
|
|
define("MONTHSTYLE_SHORTNAMEYEAR2", 3); |
93
|
|
|
define("MONTHSTYLE_LONGNAMEYEAR4", 4); |
94
|
|
|
define("MONTHSTYLE_SHORTNAMEYEAR4", 5); |
95
|
|
|
define("MONTHSTYLE_FIRSTLETTER", 6); |
96
|
|
|
|
97
|
|
|
// Types of constrain links |
98
|
|
|
define('CONSTRAIN_STARTSTART', 0); |
99
|
|
|
define('CONSTRAIN_STARTEND', 1); |
100
|
|
|
define('CONSTRAIN_ENDSTART', 2); |
101
|
|
|
define('CONSTRAIN_ENDEND', 3); |
102
|
|
|
|
103
|
|
|
// Arrow direction for constrain links |
104
|
|
|
define('ARROW_DOWN', 0); |
105
|
|
|
define('ARROW_UP', 1); |
106
|
|
|
define('ARROW_LEFT', 2); |
107
|
|
|
define('ARROW_RIGHT', 3); |
108
|
|
|
|
109
|
|
|
// Arrow type for constrain type |
110
|
|
|
define('ARROWT_SOLID', 0); |
111
|
|
|
define('ARROWT_OPEN', 1); |
112
|
|
|
|
113
|
|
|
// Arrow size for constrain lines |
114
|
|
|
define('ARROW_S1', 0); |
115
|
|
|
define('ARROW_S2', 1); |
116
|
|
|
define('ARROW_S3', 2); |
117
|
|
|
define('ARROW_S4', 3); |
118
|
|
|
define('ARROW_S5', 4); |
119
|
|
|
|
120
|
|
|
// Activity types for use with utility method CreateSimple() |
121
|
|
|
define('ACTYPE_NORMAL', 0); |
122
|
|
|
define('ACTYPE_GROUP', 1); |
123
|
|
|
define('ACTYPE_MILESTONE', 2); |
124
|
|
|
|
125
|
|
|
define('ACTINFO_3D', 1); |
126
|
|
|
define('ACTINFO_2D', 0); |
127
|
|
|
|
128
|
|
|
// Check if array_fill() exists |
129
|
|
|
if (!function_exists('array_fill')) { |
130
|
|
|
function array_fill($iStart, $iLen, $vValue) |
131
|
|
|
{ |
132
|
|
|
$aResult = array(); |
133
|
|
|
for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) { |
134
|
|
|
$aResult[$iCount] = $vValue; |
135
|
|
|
} |
136
|
|
|
return $aResult; |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
//=================================================== |
141
|
|
|
// CLASS GanttActivityInfo |
142
|
|
|
// Description: |
143
|
|
|
//=================================================== |
144
|
|
|
class GanttActivityInfo |
145
|
|
|
{ |
146
|
|
|
public $iShow = true; |
147
|
|
|
public $iLeftColMargin = 4; |
148
|
|
|
public $iRightColMargin = 1; |
149
|
|
|
public $iTopColMargin = 1; |
150
|
|
|
public $iBottomColMargin = 3; |
151
|
|
|
public $vgrid = null; |
152
|
|
|
private $iColor = 'black'; |
153
|
|
|
private $iBackgroundColor = 'lightgray'; |
154
|
|
|
private $iFFamily = FF_FONT1; |
155
|
|
|
private $iFStyle = FS_NORMAL; |
156
|
|
|
private $iFSize = 10; |
157
|
|
|
private $iFontColor = 'black'; |
158
|
|
|
private $iTitles = array(); |
159
|
|
|
private $iWidth = array(); |
160
|
|
|
private $iHeight = -1; |
161
|
|
|
private $iTopHeaderMargin = 4; |
162
|
|
|
private $iStyle = 1; |
163
|
|
|
private $iHeaderAlign = 'center'; |
164
|
|
|
|
165
|
|
|
public function __construct() |
166
|
|
|
{ |
167
|
|
|
$this->vgrid = new LineProperty(); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
public function Hide($aF = true) |
171
|
|
|
{ |
172
|
|
|
$this->iShow = !$aF; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
public function Show($aF = true) |
176
|
|
|
{ |
177
|
|
|
$this->iShow = $aF; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
// Specify font |
181
|
|
|
public function SetFont($aFFamily, $aFStyle = FS_NORMAL, $aFSize = 10) |
182
|
|
|
{ |
183
|
|
|
$this->iFFamily = $aFFamily; |
184
|
|
|
$this->iFStyle = $aFStyle; |
185
|
|
|
$this->iFSize = $aFSize; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
public function SetStyle($aStyle) |
189
|
|
|
{ |
190
|
|
|
$this->iStyle = $aStyle; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
public function SetColumnMargin($aLeft, $aRight) |
194
|
|
|
{ |
195
|
|
|
$this->iLeftColMargin = $aLeft; |
196
|
|
|
$this->iRightColMargin = $aRight; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
public function SetFontColor($aFontColor) |
200
|
|
|
{ |
201
|
|
|
$this->iFontColor = $aFontColor; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
public function SetColor($aColor) |
205
|
|
|
{ |
206
|
|
|
$this->iColor = $aColor; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
public function SetBackgroundColor($aColor) |
210
|
|
|
{ |
211
|
|
|
$this->iBackgroundColor = $aColor; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
public function SetColTitles($aTitles, $aWidth = null) |
215
|
|
|
{ |
216
|
|
|
$this->iTitles = $aTitles; |
217
|
|
|
$this->iWidth = $aWidth; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
public function SetMinColWidth($aWidths) |
221
|
|
|
{ |
222
|
|
|
$n = min(count($this->iTitles), count($aWidths)); |
223
|
|
|
for ($i = 0; $i < $n; ++$i) { |
224
|
|
|
if (!empty($aWidths[$i])) { |
225
|
|
|
if (empty($this->iWidth[$i])) { |
226
|
|
|
$this->iWidth[$i] = $aWidths[$i]; |
227
|
|
|
} else { |
228
|
|
|
$this->iWidth[$i] = max($this->iWidth[$i], $aWidths[$i]); |
229
|
|
|
} |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function GetWidth($aImg) |
235
|
|
|
{ |
236
|
|
|
$txt = new TextProperty(); |
237
|
|
|
$txt->SetFont($this->iFFamily, $this->iFStyle, $this->iFSize); |
238
|
|
|
$n = count($this->iTitles); |
239
|
|
|
$rm = $this->iRightColMargin; |
240
|
|
|
$w = 0; |
241
|
|
|
for ($h = 0, $i = 0; $i < $n; ++$i) { |
242
|
|
|
$w += $this->iLeftColMargin; |
243
|
|
|
$txt->Set($this->iTitles[$i]); |
244
|
|
|
if (!empty($this->iWidth[$i])) { |
245
|
|
|
$w1 = max($txt->GetWidth($aImg) + $rm, $this->iWidth[$i]); |
246
|
|
|
} else { |
247
|
|
|
$w1 = $txt->GetWidth($aImg) + $rm; |
248
|
|
|
} |
249
|
|
|
$this->iWidth[$i] = $w1; |
250
|
|
|
$w += $w1; |
251
|
|
|
$h = max($h, $txt->GetHeight($aImg)); |
252
|
|
|
} |
253
|
|
|
$this->iHeight = $h + $this->iTopHeaderMargin; |
254
|
|
|
$txt = ''; |
|
|
|
|
255
|
|
|
return $w; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
public function GetColStart($aImg, &$aStart, $aAddLeftMargin = false) |
259
|
|
|
{ |
260
|
|
|
$n = count($this->iTitles); |
261
|
|
|
$adj = $aAddLeftMargin ? $this->iLeftColMargin : 0; |
262
|
|
|
$aStart = array($aImg->left_margin + $adj); |
263
|
|
|
for ($i = 1; $i < $n; ++$i) { |
264
|
|
|
$aStart[$i] = $aStart[$i - 1] + $this->iLeftColMargin + $this->iWidth[$i - 1]; |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
// Adjust headers left, right or centered |
269
|
|
|
public function SetHeaderAlign($aAlign) |
270
|
|
|
{ |
271
|
|
|
$this->iHeaderAlign = $aAlign; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
public function Stroke($aImg, $aXLeft, $aYTop, $aXRight, $aYBottom, $aUseTextHeight = false) |
275
|
|
|
{ |
276
|
|
|
if (!$this->iShow) { |
277
|
|
|
return; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
$txt = new TextProperty(); |
281
|
|
|
$txt->SetFont($this->iFFamily, $this->iFStyle, $this->iFSize); |
282
|
|
|
$txt->SetColor($this->iFontColor); |
283
|
|
|
$txt->SetAlign($this->iHeaderAlign, 'top'); |
284
|
|
|
$n = count($this->iTitles); |
285
|
|
|
|
286
|
|
|
if ($n == 0) { |
287
|
|
|
return; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
$x = $aXLeft; |
291
|
|
|
$h = $this->iHeight; |
292
|
|
|
$yTop = $aUseTextHeight ? $aYBottom - $h - $this->iTopColMargin - $this->iBottomColMargin : $aYTop; |
293
|
|
|
|
294
|
|
|
if ($h < 0) { |
295
|
|
|
Util\JpGraphError::RaiseL(6001); |
296
|
|
|
//('Internal error. Height for ActivityTitles is < 0'); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
$aImg->SetLineWeight(1); |
300
|
|
|
// Set background color |
301
|
|
|
$aImg->SetColor($this->iBackgroundColor); |
302
|
|
|
$aImg->FilledRectangle($aXLeft, $yTop, $aXRight, $aYBottom - 1); |
303
|
|
|
|
304
|
|
|
if ($this->iStyle == 1) { |
305
|
|
|
// Make a 3D effect |
306
|
|
|
$aImg->SetColor('white'); |
307
|
|
|
$aImg->Line($aXLeft, $yTop + 1, $aXRight, $yTop + 1); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
for ($i = 0; $i < $n; ++$i) { |
311
|
|
|
if ($this->iStyle == 1) { |
312
|
|
|
// Make a 3D effect |
313
|
|
|
$aImg->SetColor('white'); |
314
|
|
|
$aImg->Line($x + 1, $yTop, $x + 1, $aYBottom); |
315
|
|
|
} |
316
|
|
|
$x += $this->iLeftColMargin; |
317
|
|
|
$txt->Set($this->iTitles[$i]); |
318
|
|
|
|
319
|
|
|
// Adjust the text anchor position according to the choosen alignment |
320
|
|
|
$xp = $x; |
321
|
|
|
if ($this->iHeaderAlign == 'center') { |
322
|
|
|
$xp = (($x - $this->iLeftColMargin) + ($x + $this->iWidth[$i])) / 2; |
323
|
|
|
} elseif ($this->iHeaderAlign == 'right') { |
324
|
|
|
$xp = $x + $this->iWidth[$i] - $this->iRightColMargin; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
$txt->Stroke($aImg, $xp, $yTop + $this->iTopHeaderMargin); |
328
|
|
|
$x += $this->iWidth[$i]; |
329
|
|
|
if ($i < $n - 1) { |
330
|
|
|
$aImg->SetColor($this->iColor); |
331
|
|
|
$aImg->Line($x, $yTop, $x, $aYBottom); |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
$aImg->SetColor($this->iColor); |
336
|
|
|
$aImg->Line($aXLeft, $yTop, $aXRight, $yTop); |
337
|
|
|
|
338
|
|
|
// Stroke vertical column dividers |
339
|
|
|
$cols = array(); |
340
|
|
|
$this->GetColStart($aImg, $cols); |
341
|
|
|
$n = count($cols); |
342
|
|
|
for ($i = 1; $i < $n; ++$i) { |
343
|
|
|
$this->vgrid->Stroke($aImg, $cols[$i], $aYBottom, $cols[$i], |
344
|
|
|
$aImg->height - $aImg->bottom_margin); |
345
|
|
|
} |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
//=================================================== |
350
|
|
|
// Global cache for builtin images |
351
|
|
|
//=================================================== |
352
|
|
|
$_gPredefIcons = new PredefIcons(); |
353
|
|
|
|
354
|
|
|
// <EOF> |
355
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.