| Total Complexity | 158 |
| Total Lines | 909 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Complex classes like GanttGraph often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use GanttGraph, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 18 | class GanttGraph extends Graph |
||
| 19 | { |
||
| 20 | public $scale; // Public accessible |
||
| 21 | public $hgrid; |
||
| 22 | private $iObj = []; // Gantt objects |
||
| 23 | private $iLabelHMarginFactor = 0.2; // 10% margin on each side of the labels |
||
|
|
|||
| 24 | private $iLabelVMarginFactor = 0.4; // 40% margin on top and bottom of label |
||
| 25 | private $iLayout = GANTT_FROMTOP; // Could also be GANTT_EVEN |
||
| 26 | private $iSimpleFont = FF_FONT1; |
||
| 27 | private $iSimpleFontSize = 11; |
||
| 28 | private $iSimpleStyle = GANTT_RDIAG; |
||
| 29 | private $iSimpleColor = 'yellow'; |
||
| 30 | private $iSimpleBkgColor = 'red'; |
||
| 31 | private $iSimpleProgressBkgColor = 'gray'; |
||
| 32 | private $iSimpleProgressColor = 'darkgreen'; |
||
| 33 | private $iSimpleProgressStyle = GANTT_SOLID; |
||
| 34 | private $iZoomFactor = 1.0; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * CONSTRUCTOR |
||
| 38 | * // Create a new gantt graph. |
||
| 39 | * |
||
| 40 | * @param mixed $aWidth |
||
| 41 | * @param mixed $aHeight |
||
| 42 | * @param mixed $aCachedName |
||
| 43 | * @param mixed $aTimeOut |
||
| 44 | * @param mixed $aInline |
||
| 45 | */ |
||
| 46 | public function __construct($aWidth = 0, $aHeight = 0, $aCachedName = '', $aTimeOut = 0, $aInline = true) |
||
| 71 | } |
||
| 72 | |||
| 73 | /** |
||
| 74 | * PUBLIC METHODS. |
||
| 75 | * |
||
| 76 | * @param mixed $aFont |
||
| 77 | * @param mixed $aSize |
||
| 78 | */ |
||
| 79 | public function SetSimpleFont($aFont, $aSize) |
||
| 80 | { |
||
| 81 | $this->iSimpleFont = $aFont; |
||
| 82 | $this->iSimpleFontSize = $aSize; |
||
| 83 | } |
||
| 84 | |||
| 85 | public function SetSimpleStyle($aBand, $aColor, $aBkgColor) |
||
| 86 | { |
||
| 87 | $this->iSimpleStyle = $aBand; |
||
| 88 | $this->iSimpleColor = $aColor; |
||
| 89 | $this->iSimpleBkgColor = $aBkgColor; |
||
| 90 | } |
||
| 91 | |||
| 92 | // A utility function to help create basic Gantt charts |
||
| 93 | public function CreateSimple($data, $constrains = [], $progress = []) |
||
| 94 | { |
||
| 95 | $num = safe_count($data); |
||
| 96 | for ($i = 0; $i < $num; ++$i) { |
||
| 97 | switch ($data[$i][1]) { |
||
| 98 | case ACTYPE_GROUP: |
||
| 99 | // Create a slightly smaller height bar since the |
||
| 100 | // "wings" at the end will make it look taller |
||
| 101 | $a = new Plot\GanttBar($data[$i][0], $data[$i][2], $data[$i][3], $data[$i][4], '', 8); |
||
| 102 | $a->title->SetFont($this->iSimpleFont, FS_BOLD, $this->iSimpleFontSize); |
||
| 103 | $a->rightMark->Show(); |
||
| 104 | $a->rightMark->SetType(MARK_RIGHTTRIANGLE); |
||
| 105 | $a->rightMark->SetWidth(8); |
||
| 106 | $a->rightMark->SetColor('black'); |
||
| 107 | $a->rightMark->SetFillColor('black'); |
||
| 108 | |||
| 109 | $a->leftMark->Show(); |
||
| 110 | $a->leftMark->SetType(MARK_LEFTTRIANGLE); |
||
| 111 | $a->leftMark->SetWidth(8); |
||
| 112 | $a->leftMark->SetColor('black'); |
||
| 113 | $a->leftMark->SetFillColor('black'); |
||
| 114 | |||
| 115 | $a->SetPattern(BAND_SOLID, 'black'); |
||
| 116 | $csimpos = 6; |
||
| 117 | |||
| 118 | break; |
||
| 119 | case ACTYPE_NORMAL: |
||
| 120 | $a = new Plot\GanttBar($data[$i][0], $data[$i][2], $data[$i][3], $data[$i][4], '', 10); |
||
| 121 | $a->title->SetFont($this->iSimpleFont, FS_NORMAL, $this->iSimpleFontSize); |
||
| 122 | $a->SetPattern($this->iSimpleStyle, $this->iSimpleColor); |
||
| 123 | $a->SetFillColor($this->iSimpleBkgColor); |
||
| 124 | // Check if this activity should have a constrain line |
||
| 125 | $n = safe_count($constrains); |
||
| 126 | for ($j = 0; $j < $n; ++$j) { |
||
| 127 | if (empty($constrains[$j]) || (safe_count($constrains[$j]) != 3)) { |
||
| 128 | Util\JpGraphError::RaiseL(6003, $j); |
||
| 129 | //("Invalid format for Constrain parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Constrain-To,Constrain-Type)"); |
||
| 130 | } |
||
| 131 | if ($constrains[$j][0] == $data[$i][0]) { |
||
| 132 | $a->SetConstrain($constrains[$j][1], $constrains[$j][2], 'black', ARROW_S2, ARROWT_SOLID); |
||
| 133 | } |
||
| 134 | } |
||
| 135 | |||
| 136 | // Check if this activity have a progress bar |
||
| 137 | $n = safe_count($progress); |
||
| 138 | for ($j = 0; $j < $n; ++$j) { |
||
| 139 | if (empty($progress[$j]) || (safe_count($progress[$j]) != 2)) { |
||
| 140 | Util\JpGraphError::RaiseL(6004, $j); |
||
| 141 | //("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)"); |
||
| 142 | } |
||
| 143 | if ($progress[$j][0] == $data[$i][0]) { |
||
| 144 | $a->progress->Set($progress[$j][1]); |
||
| 145 | $a->progress->SetPattern( |
||
| 146 | $this->iSimpleProgressStyle, |
||
| 147 | $this->iSimpleProgressColor |
||
| 148 | ); |
||
| 149 | $a->progress->SetFillColor($this->iSimpleProgressBkgColor); |
||
| 150 | //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); |
||
| 151 | break; |
||
| 152 | } |
||
| 153 | } |
||
| 154 | $csimpos = 6; |
||
| 155 | |||
| 156 | break; |
||
| 157 | case ACTYPE_MILESTONE: |
||
| 158 | $a = new Plot\MileStone($data[$i][0], $data[$i][2], $data[$i][3]); |
||
| 159 | $a->title->SetFont($this->iSimpleFont, FS_NORMAL, $this->iSimpleFontSize); |
||
| 160 | $a->caption->SetFont($this->iSimpleFont, FS_NORMAL, $this->iSimpleFontSize); |
||
| 161 | $csimpos = 5; |
||
| 162 | |||
| 163 | break; |
||
| 164 | default: |
||
| 165 | die('Unknown activity type'); |
||
| 166 | |||
| 167 | break; |
||
| 168 | } |
||
| 169 | |||
| 170 | // Setup caption |
||
| 171 | $a->caption->Set($data[$i][$csimpos - 1]); |
||
| 172 | |||
| 173 | // Check if this activity should have a CSIM target�? |
||
| 174 | if (!empty($data[$i][$csimpos])) { |
||
| 175 | $a->SetCSIMTarget($data[$i][$csimpos]); |
||
| 176 | $a->SetCSIMAlt($data[$i][$csimpos + 1]); |
||
| 177 | } |
||
| 178 | if (!empty($data[$i][$csimpos + 2])) { |
||
| 179 | $a->title->SetCSIMTarget($data[$i][$csimpos + 2]); |
||
| 180 | $a->title->SetCSIMAlt($data[$i][$csimpos + 3]); |
||
| 181 | } |
||
| 182 | |||
| 183 | $this->Add($a); |
||
| 184 | } |
||
| 185 | } |
||
| 186 | |||
| 187 | // Set user specified scale zoom factor when auto sizing is used |
||
| 188 | public function SetZoomFactor($aZoom) |
||
| 189 | { |
||
| 190 | $this->iZoomFactor = $aZoom; |
||
| 191 | } |
||
| 192 | |||
| 193 | // Set what headers should be shown |
||
| 194 | public function ShowHeaders($aFlg) |
||
| 195 | { |
||
| 196 | $this->scale->ShowHeaders($aFlg); |
||
| 197 | } |
||
| 198 | |||
| 199 | // Specify the fraction of the font height that should be added |
||
| 200 | // as vertical margin |
||
| 201 | public function SetLabelVMarginFactor($aVal) |
||
| 202 | { |
||
| 203 | $this->iLabelVMarginFactor = $aVal; |
||
| 204 | } |
||
| 205 | |||
| 206 | // Synonym to the method above |
||
| 207 | public function SetVMarginFactor($aVal) |
||
| 208 | { |
||
| 209 | $this->iLabelVMarginFactor = $aVal; |
||
| 210 | } |
||
| 211 | |||
| 212 | // Add a new Gantt object |
||
| 213 | public function Add($aObject) |
||
| 214 | { |
||
| 215 | if (is_array($aObject) && safe_count($aObject) > 0) { |
||
| 216 | $cl = $aObject[0]; |
||
| 217 | if (($cl instanceof Plot\IconPlot)) { |
||
| 218 | $this->AddIcon($aObject); |
||
| 219 | } elseif (($cl instanceof Text\Text)) { |
||
| 220 | $this->AddText($aObject); |
||
| 221 | } else { |
||
| 222 | $n = safe_count($aObject); |
||
| 223 | for ($i = 0; $i < $n; ++$i) { |
||
| 224 | $this->iObj[] = $aObject[$i]; |
||
| 225 | } |
||
| 226 | } |
||
| 227 | } else { |
||
| 228 | if (($aObject instanceof Plot\IconPlot)) { |
||
| 229 | $this->AddIcon($aObject); |
||
| 230 | } elseif (($aObject instanceof Text\Text)) { |
||
| 231 | $this->AddText($aObject); |
||
| 232 | } else { |
||
| 233 | $this->iObj[] = $aObject; |
||
| 234 | } |
||
| 235 | } |
||
| 236 | } |
||
| 237 | |||
| 238 | public function StrokeTexts() |
||
| 239 | { |
||
| 240 | // Stroke any user added text objects |
||
| 241 | if ($this->texts != null) { |
||
| 242 | $n = safe_count($this->texts); |
||
| 243 | for ($i = 0; $i < $n; ++$i) { |
||
| 244 | if ($this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null) { |
||
| 245 | $x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX); |
||
| 246 | $y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY); |
||
| 247 | $y -= $this->scale->GetVertSpacing() / 2; |
||
| 248 | } else { |
||
| 249 | $x = $y = null; |
||
| 250 | } |
||
| 251 | $this->texts[$i]->Stroke($this->img, $x, $y); |
||
| 252 | } |
||
| 253 | } |
||
| 254 | } |
||
| 255 | |||
| 256 | // Override inherit method from Graph and give a warning message |
||
| 257 | public function SetScale($aAxisType, $aYMin = 1, $aYMax = 1, $aXMin = 1, $aXMax = 1) |
||
| 258 | { |
||
| 259 | Util\JpGraphError::RaiseL(6005); |
||
| 260 | //("SetScale() is not meaningfull with Gantt charts."); |
||
| 261 | } |
||
| 262 | |||
| 263 | // Specify the date range for Gantt graphs (if this is not set it will be |
||
| 264 | // automtically determined from the input data) |
||
| 265 | public function SetDateRange($aStart, $aEnd) |
||
| 266 | { |
||
| 267 | // Adjust the start and end so that the indicate the |
||
| 268 | // begining and end of respective start and end days |
||
| 269 | if (strpos($aStart, ':') === false) { |
||
| 270 | $aStart = date('Y-m-d 00:00', strtotime($aStart)); |
||
| 271 | } |
||
| 272 | |||
| 273 | if (strpos($aEnd, ':') === false) { |
||
| 274 | $aEnd = date('Y-m-d 23:59', strtotime($aEnd)); |
||
| 275 | } |
||
| 276 | |||
| 277 | $this->scale->SetRange($aStart, $aEnd); |
||
| 278 | } |
||
| 279 | |||
| 280 | // Get the maximum width of the activity titles columns for the bars |
||
| 281 | // The name is lightly misleading since we from now on can have |
||
| 282 | // multiple columns in the label section. When this was first written |
||
| 283 | // it only supported a single label, hence the name. |
||
| 284 | public function GetMaxLabelWidth() |
||
| 285 | { |
||
| 286 | $m = 10; |
||
| 287 | if ($this->iObj != null) { |
||
| 288 | $marg = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin; |
||
| 289 | $n = safe_count($this->iObj); |
||
| 290 | for ($i = 0; $i < $n; ++$i) { |
||
| 291 | if (!empty($this->iObj[$i]->title)) { |
||
| 292 | if ($this->iObj[$i]->title->HasTabs()) { |
||
| 293 | list($tot, $w) = $this->iObj[$i]->title->GetWidth($this->img, true); |
||
| 294 | $m = max($m, $tot); |
||
| 295 | } else { |
||
| 296 | $m = max($m, $this->iObj[$i]->title->GetWidth($this->img)); |
||
| 297 | } |
||
| 298 | } |
||
| 299 | } |
||
| 300 | } |
||
| 301 | |||
| 302 | return $m; |
||
| 303 | } |
||
| 304 | |||
| 305 | // Get the maximum height of the titles for the bars |
||
| 306 | public function GetMaxLabelHeight() |
||
| 307 | { |
||
| 308 | $m = 10; |
||
| 309 | if ($this->iObj != null) { |
||
| 310 | $n = safe_count($this->iObj); |
||
| 311 | // We can not include the title of GnttVLine since that title is stroked at the bottom |
||
| 312 | // of the Gantt bar and not in the activity title columns |
||
| 313 | for ($i = 0; $i < $n; ++$i) { |
||
| 314 | if (!empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof Plot\GanttVLine)) { |
||
| 315 | $m = max($m, $this->iObj[$i]->title->GetHeight($this->img)); |
||
| 316 | } |
||
| 317 | } |
||
| 318 | } |
||
| 319 | |||
| 320 | return $m; |
||
| 321 | } |
||
| 322 | |||
| 323 | public function GetMaxBarAbsHeight() |
||
| 324 | { |
||
| 325 | $m = 0; |
||
| 326 | if ($this->iObj != null) { |
||
| 327 | $m = $this->iObj[0]->GetAbsHeight($this->img); |
||
| 328 | $n = safe_count($this->iObj); |
||
| 329 | for ($i = 1; $i < $n; ++$i) { |
||
| 330 | $m = max($m, $this->iObj[$i]->GetAbsHeight($this->img)); |
||
| 331 | } |
||
| 332 | } |
||
| 333 | |||
| 334 | return $m; |
||
| 335 | } |
||
| 336 | |||
| 337 | // Get the maximum used line number (vertical position) for bars |
||
| 338 | public function GetBarMaxLineNumber() |
||
| 339 | { |
||
| 340 | $m = 1; |
||
| 341 | if ($this->iObj != null) { |
||
| 342 | $m = $this->iObj[0]->GetLineNbr(); |
||
| 343 | $n = safe_count($this->iObj); |
||
| 344 | for ($i = 1; $i < $n; ++$i) { |
||
| 345 | $m = max($m, $this->iObj[$i]->GetLineNbr()); |
||
| 346 | } |
||
| 347 | } |
||
| 348 | |||
| 349 | return $m; |
||
| 350 | } |
||
| 351 | |||
| 352 | // Get the minumum and maximum used dates for all bars |
||
| 353 | public function GetBarMinMax() |
||
| 354 | { |
||
| 355 | $start = 0; |
||
| 356 | $n = safe_count($this->iObj); |
||
| 357 | while ($start < $n && $this->iObj[$start]->GetMaxDate() === false) { |
||
| 358 | ++$start; |
||
| 359 | } |
||
| 360 | |||
| 361 | if ($start >= $n) { |
||
| 362 | Util\JpGraphError::RaiseL(6006); |
||
| 363 | //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]'); |
||
| 364 | } |
||
| 365 | |||
| 366 | $max = $this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate()); |
||
| 367 | $min = $this->scale->NormalizeDate($this->iObj[$start]->GetMinDate()); |
||
| 368 | |||
| 369 | for ($i = $start + 1; $i < $n; ++$i) { |
||
| 370 | $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()); |
||
| 371 | if ($rmax != false) { |
||
| 372 | $max = max($max, $rmax); |
||
| 373 | } |
||
| 374 | |||
| 375 | $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()); |
||
| 376 | if ($rmin != false) { |
||
| 377 | $min = min($min, $rmin); |
||
| 378 | } |
||
| 379 | } |
||
| 380 | $minDate = date('Y-m-d', $min); |
||
| 381 | $min = strtotime($minDate); |
||
| 382 | $maxDate = date('Y-m-d 23:59', $max); |
||
| 383 | $max = strtotime($maxDate); |
||
| 384 | |||
| 385 | return [$min, $max]; |
||
| 386 | } |
||
| 387 | |||
| 388 | // Create a new auto sized canvas if the user hasn't specified a size |
||
| 389 | // The size is determined by what scale the user has choosen and hence |
||
| 390 | // the minimum width needed to display the headers. Some margins are |
||
| 391 | // also added to make it better looking. |
||
| 392 | public function AutoSize() |
||
| 393 | { |
||
| 394 | if ($this->img->img == null) { |
||
| 395 | // The predefined left, right, top, bottom margins. |
||
| 396 | // Note that the top margin might incease depending on |
||
| 397 | // the title. |
||
| 398 | $hadj = $vadj = 0; |
||
| 399 | if ($this->doshadow) { |
||
| 400 | $hadj = $this->shadow_width; |
||
| 401 | $vadj = $this->shadow_width + 5; |
||
| 402 | } |
||
| 403 | |||
| 404 | $lm = $this->img->left_margin; |
||
| 405 | $rm = $this->img->right_margin + $hadj; |
||
| 406 | $rm += 2; |
||
| 407 | $tm = $this->img->top_margin; |
||
| 408 | $bm = $this->img->bottom_margin + $vadj; |
||
| 409 | $bm += 2; |
||
| 410 | |||
| 411 | // If there are any added Plot\GanttVLine we must make sure that the |
||
| 412 | // bottom margin is wide enough to hold a title. |
||
| 413 | $n = safe_count($this->iObj); |
||
| 414 | for ($i = 0; $i < $n; ++$i) { |
||
| 415 | if ($this->iObj[$i] instanceof Plot\GanttVLine) { |
||
| 416 | $bm = max($bm, $this->iObj[$i]->title->GetHeight($this->img) + 10); |
||
| 417 | } |
||
| 418 | } |
||
| 419 | |||
| 420 | // First find out the height |
||
| 421 | $n = $this->GetBarMaxLineNumber() + 1; |
||
| 422 | $m = max($this->GetMaxLabelHeight(), $this->GetMaxBarAbsHeight()); |
||
| 423 | $height = $n * ((1 + $this->iLabelVMarginFactor) * $m); |
||
| 424 | |||
| 425 | // Add the height of the scale titles |
||
| 426 | $h = $this->scale->GetHeaderHeight(); |
||
| 427 | $height += $h; |
||
| 428 | |||
| 429 | // Calculate the top margin needed for title and subtitle |
||
| 430 | if ($this->title->t != '') { |
||
| 431 | $tm += $this->title->GetFontHeight($this->img); |
||
| 432 | } |
||
| 433 | if ($this->subtitle->t != '') { |
||
| 434 | $tm += $this->subtitle->GetFontHeight($this->img); |
||
| 435 | } |
||
| 436 | |||
| 437 | // ...and then take the bottom and top plot margins into account |
||
| 438 | $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; |
||
| 439 | // Now find the minimum width for the chart required |
||
| 440 | |||
| 441 | // If day scale or smaller is shown then we use the day font width |
||
| 442 | // as the base size unit. |
||
| 443 | // If only weeks or above is displayed we use a modified unit to |
||
| 444 | // get a smaller image. |
||
| 445 | if ($this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute()) { |
||
| 446 | // Add 2 pixel margin on each side |
||
| 447 | $fw = $this->scale->day->GetFontWidth($this->img) + 4; |
||
| 448 | } elseif ($this->scale->IsDisplayWeek()) { |
||
| 449 | $fw = 8; |
||
| 450 | } elseif ($this->scale->IsDisplayMonth()) { |
||
| 451 | $fw = 4; |
||
| 452 | } else { |
||
| 453 | $fw = 2; |
||
| 454 | } |
||
| 455 | |||
| 456 | $nd = $this->scale->GetNumberOfDays(); |
||
| 457 | |||
| 458 | if ($this->scale->IsDisplayDay()) { |
||
| 459 | // If the days are displayed we also need to figure out |
||
| 460 | // how much space each day's title will require. |
||
| 461 | switch ($this->scale->day->iStyle) { |
||
| 462 | case DAYSTYLE_LONG: |
||
| 463 | $txt = 'Monday'; |
||
| 464 | |||
| 465 | break; |
||
| 466 | case DAYSTYLE_LONGDAYDATE1: |
||
| 467 | $txt = 'Monday 23 Jun'; |
||
| 468 | |||
| 469 | break; |
||
| 470 | case DAYSTYLE_LONGDAYDATE2: |
||
| 471 | $txt = 'Monday 23 Jun 2003'; |
||
| 472 | |||
| 473 | break; |
||
| 474 | case DAYSTYLE_SHORT: |
||
| 475 | $txt = 'Mon'; |
||
| 476 | |||
| 477 | break; |
||
| 478 | case DAYSTYLE_SHORTDAYDATE1: |
||
| 479 | $txt = 'Mon 23/6'; |
||
| 480 | |||
| 481 | break; |
||
| 482 | case DAYSTYLE_SHORTDAYDATE2: |
||
| 483 | $txt = 'Mon 23 Jun'; |
||
| 484 | |||
| 485 | break; |
||
| 486 | case DAYSTYLE_SHORTDAYDATE3: |
||
| 487 | $txt = 'Mon 23'; |
||
| 488 | |||
| 489 | break; |
||
| 490 | case DAYSTYLE_SHORTDATE1: |
||
| 491 | $txt = '23/6'; |
||
| 492 | |||
| 493 | break; |
||
| 494 | case DAYSTYLE_SHORTDATE2: |
||
| 495 | $txt = '23 Jun'; |
||
| 496 | |||
| 497 | break; |
||
| 498 | case DAYSTYLE_SHORTDATE3: |
||
| 499 | $txt = 'Mon 23'; |
||
| 500 | |||
| 501 | break; |
||
| 502 | case DAYSTYLE_SHORTDATE4: |
||
| 503 | $txt = '88'; |
||
| 504 | |||
| 505 | break; |
||
| 506 | case DAYSTYLE_CUSTOM: |
||
| 507 | $txt = date($this->scale->day->iLabelFormStr, strtotime('2003-12-20 18:00')); |
||
| 508 | |||
| 509 | break; |
||
| 510 | case DAYSTYLE_ONELETTER: |
||
| 511 | default: |
||
| 512 | $txt = 'M'; |
||
| 513 | |||
| 514 | break; |
||
| 515 | } |
||
| 516 | $fw = $this->scale->day->GetStrWidth($this->img, $txt) + 6; |
||
| 517 | } |
||
| 518 | |||
| 519 | // If we have hours enabled we must make sure that each day has enough |
||
| 520 | // space to fit the number of hours to be displayed. |
||
| 521 | if ($this->scale->IsDisplayHour()) { |
||
| 522 | // Depending on what format the user has choose we need different amount |
||
| 523 | // of space. We therefore create a typical string for the choosen format |
||
| 524 | // and determine the length of that string. |
||
| 525 | switch ($this->scale->hour->iStyle) { |
||
| 526 | case HOURSTYLE_HMAMPM: |
||
| 527 | $txt = '12:00pm'; |
||
| 528 | |||
| 529 | break; |
||
| 530 | case HOURSTYLE_H24: |
||
| 531 | // 13 |
||
| 532 | $txt = '24'; |
||
| 533 | |||
| 534 | break; |
||
| 535 | case HOURSTYLE_HAMPM: |
||
| 536 | $txt = '12pm'; |
||
| 537 | |||
| 538 | break; |
||
| 539 | case HOURSTYLE_CUSTOM: |
||
| 540 | $txt = date($this->scale->hour->iLabelFormStr, strtotime('2003-12-20 18:00')); |
||
| 541 | |||
| 542 | break; |
||
| 543 | case HOURSTYLE_HM24: |
||
| 544 | default: |
||
| 545 | $txt = '24:00'; |
||
| 546 | |||
| 547 | break; |
||
| 548 | } |
||
| 549 | |||
| 550 | $hfw = $this->scale->hour->GetStrWidth($this->img, $txt) + 6; |
||
| 551 | $mw = $hfw; |
||
| 552 | if ($this->scale->IsDisplayMinute()) { |
||
| 553 | // Depending on what format the user has choose we need different amount |
||
| 554 | // of space. We therefore create a typical string for the choosen format |
||
| 555 | // and determine the length of that string. |
||
| 556 | switch ($this->scale->minute->iStyle) { |
||
| 557 | case HOURSTYLE_CUSTOM: |
||
| 558 | $txt2 = date($this->scale->minute->iLabelFormStr, strtotime('2005-05-15 18:55')); |
||
| 559 | |||
| 560 | break; |
||
| 561 | case MINUTESTYLE_MM: |
||
| 562 | default: |
||
| 563 | $txt2 = '15'; |
||
| 564 | |||
| 565 | break; |
||
| 566 | } |
||
| 567 | |||
| 568 | $mfw = $this->scale->minute->GetStrWidth($this->img, $txt2) + 6; |
||
| 569 | $n2 = ceil(60 / $this->scale->minute->GetIntervall()); |
||
| 570 | $mw = $n2 * $mfw; |
||
| 571 | } |
||
| 572 | $hfw = $hfw < $mw ? $mw : $hfw; |
||
| 573 | $n = ceil(24 * 60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall())); |
||
| 574 | $hw = $n * $hfw; |
||
| 575 | $fw = $fw < $hw ? $hw : $fw; |
||
| 576 | } |
||
| 577 | |||
| 578 | // We need to repeat this code block here as well. |
||
| 579 | // THIS iS NOT A MISTAKE ! |
||
| 580 | // We really need it since we need to adjust for minutes both in the case |
||
| 581 | // where hour scale is shown and when it is not shown. |
||
| 582 | |||
| 583 | if ($this->scale->IsDisplayMinute()) { |
||
| 584 | // Depending on what format the user has choose we need different amount |
||
| 585 | // of space. We therefore create a typical string for the choosen format |
||
| 586 | // and determine the length of that string. |
||
| 587 | switch ($this->scale->minute->iStyle) { |
||
| 588 | case HOURSTYLE_CUSTOM: |
||
| 589 | $txt = date($this->scale->minute->iLabelFormStr, strtotime('2005-05-15 18:55')); |
||
| 590 | |||
| 591 | break; |
||
| 592 | case MINUTESTYLE_MM: |
||
| 593 | default: |
||
| 594 | $txt = '15'; |
||
| 595 | |||
| 596 | break; |
||
| 597 | } |
||
| 598 | |||
| 599 | $mfw = $this->scale->minute->GetStrWidth($this->img, $txt) + 6; |
||
| 600 | $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall())); |
||
| 601 | $mw = $n * $mfw; |
||
| 602 | $fw = $fw < $mw ? $mw : $fw; |
||
| 603 | } |
||
| 604 | |||
| 605 | // If we display week we must make sure that 7*$fw is enough |
||
| 606 | // to fit up to 10 characters of the week font (if the week is enabled) |
||
| 607 | if ($this->scale->IsDisplayWeek()) { |
||
| 608 | // Depending on what format the user has choose we need different amount |
||
| 609 | // of space |
||
| 610 | $fsw = strlen($this->scale->week->iLabelFormStr); |
||
| 611 | if ($this->scale->week->iStyle == WEEKSTYLE_FIRSTDAY2WNBR) { |
||
| 612 | $fsw += 8; |
||
| 613 | } elseif ($this->scale->week->iStyle == WEEKSTYLE_FIRSTDAYWNBR) { |
||
| 614 | $fsw += 7; |
||
| 615 | } else { |
||
| 616 | $fsw += 4; |
||
| 617 | } |
||
| 618 | |||
| 619 | $ww = $fsw * $this->scale->week->GetFontWidth($this->img); |
||
| 620 | if (7 * $fw < $ww) { |
||
| 621 | $fw = ceil($ww / 7); |
||
| 622 | } |
||
| 623 | } |
||
| 624 | |||
| 625 | if (!$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && |
||
| 626 | !(($this->scale->week->iStyle == WEEKSTYLE_FIRSTDAYWNBR || |
||
| 627 | $this->scale->week->iStyle == WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek())) { |
||
| 628 | // If we don't display the individual days we can shrink the |
||
| 629 | // scale a little bit. This is a little bit pragmatic at the |
||
| 630 | // moment and should be re-written to take into account |
||
| 631 | // a) What scales exactly are shown and |
||
| 632 | // b) what format do they use so we know how wide we need to |
||
| 633 | // make each scale text space at minimum. |
||
| 634 | $fw /= 2; |
||
| 635 | if (!$this->scale->IsDisplayWeek()) { |
||
| 636 | $fw /= 1.8; |
||
| 637 | } |
||
| 638 | } |
||
| 639 | |||
| 640 | $cw = $this->GetMaxActInfoColWidth(); |
||
| 641 | $this->scale->actinfo->SetMinColWidth($cw); |
||
| 642 | if ($this->img->width <= 0) { |
||
| 643 | // Now determine the width for the activity titles column |
||
| 644 | |||
| 645 | // Firdst find out the maximum width of each object column |
||
| 646 | $titlewidth = max( |
||
| 647 | max( |
||
| 648 | $this->GetMaxLabelWidth(), |
||
| 649 | $this->scale->tableTitle->GetWidth($this->img) |
||
| 650 | ), |
||
| 651 | $this->scale->actinfo->GetWidth($this->img) |
||
| 652 | ); |
||
| 653 | |||
| 654 | // Add the width of the vertivcal divider line |
||
| 655 | $titlewidth += $this->scale->divider->iWeight * 2; |
||
| 656 | |||
| 657 | // Adjust the width by the user specified zoom factor |
||
| 658 | $fw *= $this->iZoomFactor; |
||
| 659 | |||
| 660 | // Now get the total width taking |
||
| 661 | // titlewidth, left and rigt margin, dayfont size |
||
| 662 | // into account |
||
| 663 | $width = $titlewidth + $nd * $fw + $lm + $rm; |
||
| 664 | } else { |
||
| 665 | $width = $this->img->width; |
||
| 666 | } |
||
| 667 | |||
| 668 | $width = round($width); |
||
| 669 | $height = round($height); |
||
| 670 | // Make a sanity check on image size |
||
| 671 | if ($width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H) { |
||
| 672 | Util\JpGraphError::RaiseL(6007, $width, $height); |
||
| 673 | //("Sanity check for automatic Gantt chart size failed. Either the width (=$width) or height (=$height) is larger than MAX_GANTTIMG_SIZE. This could potentially be caused by a wrong date in one of the activities."); |
||
| 674 | } |
||
| 675 | $this->img->CreateImgCanvas($width, $height); |
||
| 676 | $this->img->SetMargin($lm, $rm, $tm, $bm); |
||
| 677 | } |
||
| 678 | } |
||
| 679 | |||
| 680 | // Return an array width the maximum width for each activity |
||
| 681 | // column. This is used when we autosize the columns where we need |
||
| 682 | // to find out the maximum width of each column. In order to do that we |
||
| 683 | // must walk through all the objects, sigh... |
||
| 684 | public function GetMaxActInfoColWidth() |
||
| 707 | } |
||
| 708 | |||
| 709 | // Stroke the gantt chart |
||
| 710 | public function Stroke($aStrokeFileName = '') |
||
| 711 | { |
||
| 712 | // If the filename is the predefined value = '_csim_special_' |
||
| 713 | // we assume that the call to stroke only needs to do enough |
||
| 714 | // to correctly generate the CSIM maps. |
||
| 715 | // We use this variable to skip things we don't strictly need |
||
| 716 | // to do to generate the image map to improve performance |
||
| 717 | // a best we can. Therefor you will see a lot of tests !$_csim in the |
||
| 718 | // code below. |
||
| 719 | $_csim = ($aStrokeFileName === _CSIM_SPECIALFILE); |
||
| 720 | |||
| 819 | ); |
||
| 820 | } |
||
| 821 | } |
||
| 822 | |||
| 823 | public function StrokeConstrains() |
||
| 905 | } |
||
| 906 | } |
||
| 907 | } |
||
| 908 | } |
||
| 909 | } |
||
| 910 | |||
| 911 | public function GetCSIMAreas() |
||
| 927 | } |
||
| 928 | } |
||
| 929 |