Changeset 265 for trunk/client/modules/Elezioni/grafici/jpgraph_gantt.php
- Timestamp:
- Apr 13, 2019, 8:05:15 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/client/modules/Elezioni/grafici/jpgraph_gantt.php
r2 r265 1 1 <?php 2 2 /*======================================================================= 3 // File:JPGRAPH_GANTT.PHP4 // Description:JpGraph Gantt plot extension5 // Created:2001-11-126 // Ver: $Id: jpgraph_gantt.php 1091 2009-01-18 22:57:40Z ljp $7 //8 // Copyright (c) Aditus Consulting. All rights reserved.9 //========================================================================10 */11 12 require_once('jpgraph_plotband.php'); 13 require_once('jpgraph_iconplot.php'); 3 // File: JPGRAPH_GANTT.PHP 4 // Description: JpGraph Gantt plot extension 5 // Created: 2001-11-12 6 // Ver: $Id: jpgraph_gantt.php 1809 2009-09-09 13:07:33Z ljp $ 7 // 8 // Copyright (c) Asial Corporation. All rights reserved. 9 //======================================================================== 10 */ 11 12 require_once('jpgraph_plotband.php'); 13 require_once('jpgraph_iconplot.php'); 14 14 require_once('jpgraph_plotmark.inc.php'); 15 15 16 16 // Maximum size for Automatic Gantt chart 17 define('MAX_GANTTIMG_SIZE_W', 4000);17 define('MAX_GANTTIMG_SIZE_W',8000); 18 18 define('MAX_GANTTIMG_SIZE_H',5000); 19 19 … … 27 27 28 28 // Bar patterns 29 define("GANTT_RDIAG",BAND_RDIAG); 29 define("GANTT_RDIAG",BAND_RDIAG); // Right diagonal lines 30 30 define("GANTT_LDIAG",BAND_LDIAG); // Left diagonal lines 31 31 define("GANTT_SOLID",BAND_SOLID); // Solid one color … … 40 40 41 41 // Locales. ONLY KEPT FOR BACKWARDS COMPATIBILITY 42 // You should use the proper locale strings directly 43 // from now on. 42 // You should use the proper locale strings directly 43 // from now on. 44 44 define("LOCALE_EN","en_UK"); 45 45 define("LOCALE_SV","sv_SE"); … … 50 50 51 51 // Style for minute header 52 define("MINUTESTYLE_MM",0); 53 define("MINUTESTYLE_CUSTOM",2); 52 define("MINUTESTYLE_MM",0); // 15 53 define("MINUTESTYLE_CUSTOM",2); // Custom format 54 54 55 55 56 56 // Style for hour header 57 define("HOURSTYLE_HM24",0); 58 define("HOURSTYLE_HMAMPM",1); 59 define("HOURSTYLE_H24",2); 60 define("HOURSTYLE_HAMPM",3); 61 define("HOURSTYLE_CUSTOM",4); 57 define("HOURSTYLE_HM24",0); // 13:10 58 define("HOURSTYLE_HMAMPM",1); // 1:10pm 59 define("HOURSTYLE_H24",2); // 13 60 define("HOURSTYLE_HAMPM",3); // 1pm 61 define("HOURSTYLE_CUSTOM",4); // User defined 62 62 63 63 // Style for day header 64 define("DAYSTYLE_ONELETTER",0); 65 define("DAYSTYLE_LONG",1); 66 define("DAYSTYLE_LONGDAYDATE1",2); 67 define("DAYSTYLE_LONGDAYDATE2",3); 68 define("DAYSTYLE_SHORT",4); 69 define("DAYSTYLE_SHORTDAYDATE1",5); 70 define("DAYSTYLE_SHORTDAYDATE2",6); 71 define("DAYSTYLE_SHORTDAYDATE3",7); 72 define("DAYSTYLE_SHORTDATE1",8); 73 define("DAYSTYLE_SHORTDATE2",9); 74 define("DAYSTYLE_SHORTDATE3",10); 75 define("DAYSTYLE_SHORTDATE4",11); 76 define("DAYSTYLE_CUSTOM",12); 64 define("DAYSTYLE_ONELETTER",0); // "M" 65 define("DAYSTYLE_LONG",1); // "Monday" 66 define("DAYSTYLE_LONGDAYDATE1",2); // "Monday 23 Jun" 67 define("DAYSTYLE_LONGDAYDATE2",3); // "Monday 23 Jun 2003" 68 define("DAYSTYLE_SHORT",4); // "Mon" 69 define("DAYSTYLE_SHORTDAYDATE1",5); // "Mon 23/6" 70 define("DAYSTYLE_SHORTDAYDATE2",6); // "Mon 23 Jun" 71 define("DAYSTYLE_SHORTDAYDATE3",7); // "Mon 23" 72 define("DAYSTYLE_SHORTDATE1",8); // "23/6" 73 define("DAYSTYLE_SHORTDATE2",9); // "23 Jun" 74 define("DAYSTYLE_SHORTDATE3",10); // "Mon 23" 75 define("DAYSTYLE_SHORTDATE4",11); // "23" 76 define("DAYSTYLE_CUSTOM",12); // "M" 77 77 78 78 // Styles for week header … … 128 128 if (!function_exists('array_fill')) { 129 129 function array_fill($iStart, $iLen, $vValue) { 130 131 132 133 134 130 $aResult = array(); 131 for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) { 132 $aResult[$iCount] = $vValue; 133 } 134 return $aResult; 135 135 } 136 136 } … … 138 138 //=================================================== 139 139 // CLASS GanttActivityInfo 140 // Description: 140 // Description: 141 141 //=================================================== 142 142 class GanttActivityInfo { … … 153 153 private $iHeaderAlign='center'; 154 154 155 function GanttActivityInfo() {156 155 function __construct() { 156 $this->vgrid = new LineProperty(); 157 157 } 158 158 159 159 function Hide($aF=true) { 160 160 $this->iShow=!$aF; 161 161 } 162 162 163 163 function Show($aF=true) { 164 164 $this->iShow=$aF; 165 165 } 166 166 167 167 // Specify font 168 168 function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { 169 170 $this->iFStyle= $aFStyle;171 $this->iFSize= $aFSize;169 $this->iFFamily = $aFFamily; 170 $this->iFStyle = $aFStyle; 171 $this->iFSize = $aFSize; 172 172 } 173 173 174 174 function SetStyle($aStyle) { 175 175 $this->iStyle = $aStyle; 176 176 } 177 177 178 178 function SetColumnMargin($aLeft,$aRight) { 179 180 179 $this->iLeftColMargin = $aLeft; 180 $this->iRightColMargin = $aRight; 181 181 } 182 182 183 183 function SetFontColor($aFontColor) { 184 184 $this->iFontColor = $aFontColor; 185 185 } 186 186 187 187 function SetColor($aColor) { 188 188 $this->iColor = $aColor; 189 189 } 190 190 191 191 function SetBackgroundColor($aColor) { 192 192 $this->iBackgroundColor = $aColor; 193 193 } 194 194 195 195 function SetColTitles($aTitles,$aWidth=null) { 196 197 196 $this->iTitles = $aTitles; 197 $this->iWidth = $aWidth; 198 198 } 199 199 200 200 function SetMinColWidth($aWidths) { 201 202 203 204 205 206 207 208 209 210 211 201 $n = min(count($this->iTitles),count($aWidths)); 202 for($i=0; $i < $n; ++$i ) { 203 if( !empty($aWidths[$i]) ) { 204 if( empty($this->iWidth[$i]) ) { 205 $this->iWidth[$i] = $aWidths[$i]; 206 } 207 else { 208 $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]); 209 } 210 } 211 } 212 212 } 213 213 214 214 function GetWidth($aImg) { 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 215 $txt = new TextProperty(); 216 $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 217 $n = count($this->iTitles) ; 218 $rm=$this->iRightColMargin; 219 $w = 0; 220 for($h=0, $i=0; $i < $n; ++$i ) { 221 $w += $this->iLeftColMargin; 222 $txt->Set($this->iTitles[$i]); 223 if( !empty($this->iWidth[$i]) ) { 224 $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]); 225 } 226 else { 227 $w1 = $txt->GetWidth($aImg)+$rm; 228 } 229 $this->iWidth[$i] = $w1; 230 $w += $w1; 231 $h = max($h,$txt->GetHeight($aImg)); 232 } 233 $this->iHeight = $h+$this->iTopHeaderMargin; 234 234 $txt=''; 235 236 } 237 235 return $w; 236 } 237 238 238 function GetColStart($aImg,&$aStart,$aAddLeftMargin=false) { 239 240 241 242 243 244 245 } 246 239 $n = count($this->iTitles) ; 240 $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0; 241 $aStart=array($aImg->left_margin+$adj); 242 for( $i=1; $i < $n; ++$i ) { 243 $aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1]; 244 } 245 } 246 247 247 // Adjust headers left, right or centered 248 248 function SetHeaderAlign($aAlign) { 249 249 $this->iHeaderAlign=$aAlign; 250 250 } 251 251 252 252 function Stroke($aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) { 253 253 254 if( !$this->iShow ) return; 255 256 $txt = new TextProperty(); 257 $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 258 $txt->SetColor($this->iFontColor); 259 $txt->SetAlign($this->iHeaderAlign,'top'); 260 $n=count($this->iTitles); 261 262 if( $n == 0 ) 263 return; 264 265 $x = $aXLeft; 266 $h = $this->iHeight; 267 $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ; 268 269 if( $h < 0 ) { 270 JpGraphError::RaiseL(6001); 271 //('Internal error. Height for ActivityTitles is < 0'); 272 } 273 274 $aImg->SetLineWeight(1); 275 // Set background color 276 $aImg->SetColor($this->iBackgroundColor); 277 $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1); 278 279 if( $this->iStyle == 1 ) { 280 // Make a 3D effect 281 $aImg->SetColor('white'); 282 $aImg->Line($aXLeft,$yTop+1, 283 $aXRight,$yTop+1); 284 } 285 286 for($i=0; $i < $n; ++$i ) { 287 if( $this->iStyle == 1 ) { 288 // Make a 3D effect 289 $aImg->SetColor('white'); 290 $aImg->Line($x+1,$yTop,$x+1,$aYBottom); 291 } 292 $x += $this->iLeftColMargin; 293 $txt->Set($this->iTitles[$i]); 294 295 // Adjust the text anchor position according to the choosen alignment 296 $xp = $x; 297 if( $this->iHeaderAlign == 'center' ) { 298 $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2; 299 } 300 elseif( $this->iHeaderAlign == 'right' ) { 301 $xp = $x +$this->iWidth[$i]-$this->iRightColMargin; 302 } 303 304 $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin); 305 $x += $this->iWidth[$i]; 306 if( $i < $n-1 ) { 307 $aImg->SetColor($this->iColor); 308 $aImg->Line($x,$yTop,$x,$aYBottom); 309 } 310 } 311 312 $aImg->SetColor($this->iColor); 313 $aImg->Line($aXLeft,$yTop, $aXRight,$yTop); 314 315 // Stroke vertical column dividers 316 $cols=array(); 317 $this->GetColStart($aImg,$cols); 318 $n=count($cols); 319 for( $i=1; $i < $n; ++$i ) { 320 $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i], 321 $aImg->height - $aImg->bottom_margin); 322 } 254 if( !$this->iShow ) return; 255 256 $txt = new TextProperty(); 257 $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 258 $txt->SetColor($this->iFontColor); 259 $txt->SetAlign($this->iHeaderAlign,'top'); 260 $n=count($this->iTitles); 261 262 if( $n == 0 ) 263 return; 264 265 $x = $aXLeft; 266 $h = $this->iHeight; 267 $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ; 268 269 if( $h < 0 ) { 270 JpGraphError::RaiseL(6001); 271 //('Internal error. Height for ActivityTitles is < 0'); 272 } 273 274 $aImg->SetLineWeight(1); 275 // Set background color 276 $aImg->SetColor($this->iBackgroundColor); 277 $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1); 278 279 if( $this->iStyle == 1 ) { 280 // Make a 3D effect 281 $aImg->SetColor('white'); 282 $aImg->Line($aXLeft,$yTop+1,$aXRight,$yTop+1); 283 } 284 285 for($i=0; $i < $n; ++$i ) { 286 if( $this->iStyle == 1 ) { 287 // Make a 3D effect 288 $aImg->SetColor('white'); 289 $aImg->Line($x+1,$yTop,$x+1,$aYBottom); 290 } 291 $x += $this->iLeftColMargin; 292 $txt->Set($this->iTitles[$i]); 293 294 // Adjust the text anchor position according to the choosen alignment 295 $xp = $x; 296 if( $this->iHeaderAlign == 'center' ) { 297 $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2; 298 } 299 elseif( $this->iHeaderAlign == 'right' ) { 300 $xp = $x +$this->iWidth[$i]-$this->iRightColMargin; 301 } 302 303 $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin); 304 $x += $this->iWidth[$i]; 305 if( $i < $n-1 ) { 306 $aImg->SetColor($this->iColor); 307 $aImg->Line($x,$yTop,$x,$aYBottom); 308 } 309 } 310 311 $aImg->SetColor($this->iColor); 312 $aImg->Line($aXLeft,$yTop, $aXRight,$yTop); 313 314 // Stroke vertical column dividers 315 $cols=array(); 316 $this->GetColStart($aImg,$cols); 317 $n=count($cols); 318 for( $i=1; $i < $n; ++$i ) { 319 $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i], 320 $aImg->height - $aImg->bottom_margin); 321 } 323 322 } 324 323 } … … 330 329 //=================================================== 331 330 class GanttGraph extends Graph { 332 public $scale; 331 public $scale; // Public accessible 333 332 public $hgrid=null; 334 private $iObj=array(); 335 private $iLabelHMarginFactor=0.2; 336 private $iLabelVMarginFactor=0.4; 337 private $iLayout=GANTT_FROMTOP; 333 private $iObj=array(); // Gantt objects 334 private $iLabelHMarginFactor=0.2; // 10% margin on each side of the labels 335 private $iLabelVMarginFactor=0.4; // 40% margin on top and bottom of label 336 private $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN 338 337 private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11; 339 338 private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red'; 340 339 private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen'; 341 340 private $iSimpleProgressStyle=GANTT_SOLID; 342 //--------------- 343 // CONSTRUCTOR 341 private $iZoomFactor = 1.0; 342 //--------------- 343 // CONSTRUCTOR 344 344 // Create a new gantt graph 345 function GanttGraph($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) {346 347 348 349 350 351 352 353 //("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension.");354 355 Graph::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline); 356 357 358 359 360 361 362 363 364 365 } 366 367 //---------------368 // PUBLIC METHODS369 370 // 345 function __construct($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) { 346 347 // Backward compatibility 348 if( $aWidth == -1 ) $aWidth=0; 349 if( $aHeight == -1 ) $aHeight=0; 350 351 if( $aWidth< 0 || $aHeight < 0 ) { 352 JpgraphError::RaiseL(6002); 353 //("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension."); 354 } 355 parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline); 356 $this->scale = new GanttScale($this->img); 357 358 // Default margins 359 $this->img->SetMargin(15,17,25,15); 360 361 $this->hgrid = new HorizontalGridLine(); 362 363 $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY); 364 $this->SetBox(); 365 } 366 367 //--------------- 368 // PUBLIC METHODS 369 370 // 371 371 372 372 function SetSimpleFont($aFont,$aSize) { 373 374 373 $this->iSimpleFont = $aFont; 374 $this->iSimpleFontSize = $aSize; 375 375 } 376 376 377 377 function SetSimpleStyle($aBand,$aColor,$aBkgColor) { 378 379 380 378 $this->iSimpleStyle = $aBand; 379 $this->iSimpleColor = $aColor; 380 $this->iSimpleBkgColor = $aBkgColor; 381 381 } 382 382 383 383 // A utility function to help create basic Gantt charts 384 384 function CreateSimple($data,$constrains=array(),$progress=array()) { 385 $num = count($data); 386 for( $i=0; $i < $num; ++$i) { 387 switch( $data[$i][1] ) { 388 case ACTYPE_GROUP: 389 // Create a slightly smaller height bar since the 390 // "wings" at the end will make it look taller 391 $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8); 392 $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize); 393 $a->rightMark->Show(); 394 $a->rightMark->SetType(MARK_RIGHTTRIANGLE); 395 $a->rightMark->SetWidth(8); 396 $a->rightMark->SetColor('black'); 397 $a->rightMark->SetFillColor('black'); 398 399 $a->leftMark->Show(); 400 $a->leftMark->SetType(MARK_LEFTTRIANGLE); 401 $a->leftMark->SetWidth(8); 402 $a->leftMark->SetColor('black'); 403 $a->leftMark->SetFillColor('black'); 404 405 $a->SetPattern(BAND_SOLID,'black'); 406 $csimpos = 6; 407 break; 408 409 case ACTYPE_NORMAL: 410 $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10); 411 $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 412 $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor); 413 $a->SetFillColor($this->iSimpleBkgColor); 414 // Check if this activity should have a constrain line 415 $n = count($constrains); 416 for( $j=0; $j < $n; ++$j ) { 417 if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) { 418 JpGraphError::RaiseL(6003,$j); 419 //("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)"); 420 } 421 if( $constrains[$j][0]==$data[$i][0] ) { 422 $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID); 423 } 424 } 425 426 // Check if this activity have a progress bar 427 $n = count($progress); 428 for( $j=0; $j < $n; ++$j ) { 429 430 if( empty($progress[$j]) || (count($progress[$j]) != 2) ) { 431 JpGraphError::RaiseL(6004,$j); 432 //("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)"); 433 } 434 if( $progress[$j][0]==$data[$i][0] ) { 435 $a->progress->Set($progress[$j][1]); 436 $a->progress->SetPattern($this->iSimpleProgressStyle, 437 $this->iSimpleProgressColor); 438 $a->progress->SetFillColor($this->iSimpleProgressBkgColor); 439 //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); 440 break; 441 } 442 } 443 $csimpos = 6; 444 break; 445 446 case ACTYPE_MILESTONE: 447 $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]); 448 $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 449 $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 450 $csimpos = 5; 451 break; 452 default: 453 die('Unknown activity type'); 454 break; 455 } 456 457 // Setup caption 458 $a->caption->Set($data[$i][$csimpos-1]); 459 460 // Check if this activity should have a CSIM target ? 461 if( !empty($data[$i][$csimpos]) ) { 462 $a->SetCSIMTarget($data[$i][$csimpos]); 463 $a->SetCSIMAlt($data[$i][$csimpos+1]); 464 } 465 if( !empty($data[$i][$csimpos+2]) ) { 466 $a->title->SetCSIMTarget($data[$i][$csimpos+2]); 467 $a->title->SetCSIMAlt($data[$i][$csimpos+3]); 468 } 469 470 $this->Add($a); 471 } 472 } 473 474 385 $num = count($data); 386 for( $i=0; $i < $num; ++$i) { 387 switch( $data[$i][1] ) { 388 case ACTYPE_GROUP: 389 // Create a slightly smaller height bar since the 390 // "wings" at the end will make it look taller 391 $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8); 392 $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize); 393 $a->rightMark->Show(); 394 $a->rightMark->SetType(MARK_RIGHTTRIANGLE); 395 $a->rightMark->SetWidth(8); 396 $a->rightMark->SetColor('black'); 397 $a->rightMark->SetFillColor('black'); 398 399 $a->leftMark->Show(); 400 $a->leftMark->SetType(MARK_LEFTTRIANGLE); 401 $a->leftMark->SetWidth(8); 402 $a->leftMark->SetColor('black'); 403 $a->leftMark->SetFillColor('black'); 404 405 $a->SetPattern(BAND_SOLID,'black'); 406 $csimpos = 6; 407 break; 408 409 case ACTYPE_NORMAL: 410 $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10); 411 $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 412 $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor); 413 $a->SetFillColor($this->iSimpleBkgColor); 414 // Check if this activity should have a constrain line 415 $n = count($constrains); 416 for( $j=0; $j < $n; ++$j ) { 417 if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) { 418 JpGraphError::RaiseL(6003,$j); 419 //("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)"); 420 } 421 if( $constrains[$j][0]==$data[$i][0] ) { 422 $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID); 423 } 424 } 425 426 // Check if this activity have a progress bar 427 $n = count($progress); 428 for( $j=0; $j < $n; ++$j ) { 429 430 if( empty($progress[$j]) || (count($progress[$j]) != 2) ) { 431 JpGraphError::RaiseL(6004,$j); 432 //("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)"); 433 } 434 if( $progress[$j][0]==$data[$i][0] ) { 435 $a->progress->Set($progress[$j][1]); 436 $a->progress->SetPattern($this->iSimpleProgressStyle, 437 $this->iSimpleProgressColor); 438 $a->progress->SetFillColor($this->iSimpleProgressBkgColor); 439 //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]); 440 break; 441 } 442 } 443 $csimpos = 6; 444 break; 445 446 case ACTYPE_MILESTONE: 447 $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]); 448 $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 449 $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize); 450 $csimpos = 5; 451 break; 452 default: 453 die('Unknown activity type'); 454 break; 455 } 456 457 // Setup caption 458 $a->caption->Set($data[$i][$csimpos-1]); 459 460 // Check if this activity should have a CSIM targetï¿œ? 461 if( !empty($data[$i][$csimpos]) ) { 462 $a->SetCSIMTarget($data[$i][$csimpos]); 463 $a->SetCSIMAlt($data[$i][$csimpos+1]); 464 } 465 if( !empty($data[$i][$csimpos+2]) ) { 466 $a->title->SetCSIMTarget($data[$i][$csimpos+2]); 467 $a->title->SetCSIMAlt($data[$i][$csimpos+3]); 468 } 469 470 $this->Add($a); 471 } 472 } 473 474 // Set user specified scale zoom factor when auto sizing is used 475 function SetZoomFactor($aZoom) { 476 $this->iZoomFactor = $aZoom; 477 } 478 479 475 480 // Set what headers should be shown 476 481 function ShowHeaders($aFlg) { 477 478 } 479 480 // Specify the fraction of the font height that should be added 482 $this->scale->ShowHeaders($aFlg); 483 } 484 485 // Specify the fraction of the font height that should be added 481 486 // as vertical margin 482 487 function SetLabelVMarginFactor($aVal) { 483 488 $this->iLabelVMarginFactor = $aVal; 484 489 } 485 490 486 491 // Synonym to the method above 487 492 function SetVMarginFactor($aVal) { 488 489 } 490 491 493 $this->iLabelVMarginFactor = $aVal; 494 } 495 496 492 497 // Add a new Gantt object 493 498 function Add($aObject) { 494 if( is_array($aObject) && count($aObject) > 0 ) { 495 $cl = $aObject[0]; 496 if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) { 497 $this->AddIcon($aObject); 498 } 499 else { 500 $n = count($aObject); 501 for($i=0; $i < $n; ++$i) 502 $this->iObj[] = $aObject[$i]; 503 } 499 if( is_array($aObject) && count($aObject) > 0 ) { 500 $cl = $aObject[0]; 501 if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) { 502 $this->AddIcon($aObject); 503 } 504 elseif( class_exists('Text',false) && ($cl instanceof Text) ) { 505 $this->AddText($aObject); 506 } 507 else { 508 $n = count($aObject); 509 for($i=0; $i < $n; ++$i) 510 $this->iObj[] = $aObject[$i]; 511 } 512 } 513 else { 514 if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) { 515 $this->AddIcon($aObject); 516 } 517 elseif( class_exists('Text',false) && ($aObject instanceof Text) ) { 518 $this->AddText($aObject); 519 } 520 else { 521 $this->iObj[] = $aObject; 522 } 523 } 524 } 525 526 function StrokeTexts() { 527 // Stroke any user added text objects 528 if( $this->texts != null ) { 529 $n = count($this->texts); 530 for($i=0; $i < $n; ++$i) { 531 if( $this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null ) { 532 $x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX); 533 $y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY); 534 $y -= $this->scale->GetVertSpacing()/2; 535 } 536 else { 537 $x = $y = null; 538 } 539 $this->texts[$i]->Stroke($this->img,$x,$y); 540 } 541 } 504 542 } 505 else {506 if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) {507 $this->AddIcon($aObject);508 }509 else {510 $this->iObj[] = $aObject;511 }512 }513 }514 543 515 544 // Override inherit method from Graph and give a warning message 516 545 function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) { 517 518 //("SetScale() is not meaningfull with Gantt charts.");546 JpGraphError::RaiseL(6005); 547 //("SetScale() is not meaningfull with Gantt charts."); 519 548 } 520 549 … … 522 551 // automtically determined from the input data) 523 552 function SetDateRange($aStart,$aEnd) { 524 525 526 527 528 529 530 531 } 532 553 // Adjust the start and end so that the indicate the 554 // begining and end of respective start and end days 555 if( strpos($aStart,':') === false ) 556 $aStart = date('Y-m-d 00:00',strtotime($aStart)); 557 if( strpos($aEnd,':') === false ) 558 $aEnd = date('Y-m-d 23:59',strtotime($aEnd)); 559 $this->scale->SetRange($aStart,$aEnd); 560 } 561 533 562 // Get the maximum width of the activity titles columns for the bars 534 563 // The name is lightly misleading since we from now on can have … … 536 565 // it only supported a single label, hence the name. 537 566 function GetMaxLabelWidth() { 538 539 540 541 542 543 544 545 546 547 548 else 549 550 551 552 553 554 } 555 567 $m=10; 568 if( $this->iObj != null ) { 569 $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin; 570 $n = count($this->iObj); 571 for($i=0; $i < $n; ++$i) { 572 if( !empty($this->iObj[$i]->title) ) { 573 if( $this->iObj[$i]->title->HasTabs() ) { 574 list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true); 575 $m=max($m,$tot); 576 } 577 else 578 $m=max($m,$this->iObj[$i]->title->GetWidth($this->img)); 579 } 580 } 581 } 582 return $m; 583 } 584 556 585 // Get the maximum height of the titles for the bars 557 586 function GetMaxLabelHeight() { 558 $m=10; 559 if( $this->iObj != null ) { 560 $n = count($this->iObj); 561 for($i=0; $i < $n; ++$i) { 562 if( !empty($this->iObj[$i]->title) ) { 563 $m=max($m,$this->iObj[$i]->title->GetHeight($this->img)); 564 } 565 } 566 } 567 return $m; 587 $m=10; 588 if( $this->iObj != null ) { 589 $n = count($this->iObj); 590 // We can not include the title of GnttVLine since that title is stroked at the bottom 591 // of the Gantt bar and not in the activity title columns 592 for($i=0; $i < $n; ++$i) { 593 if( !empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof GanttVLine) ) { 594 $m=max($m,$this->iObj[$i]->title->GetHeight($this->img)); 595 } 596 } 597 } 598 return $m; 568 599 } 569 600 570 601 function GetMaxBarAbsHeight() { 571 572 573 574 575 576 577 578 579 return $m; 580 } 581 602 $m=0; 603 if( $this->iObj != null ) { 604 $m = $this->iObj[0]->GetAbsHeight($this->img); 605 $n = count($this->iObj); 606 for($i=1; $i < $n; ++$i) { 607 $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img)); 608 } 609 } 610 return $m; 611 } 612 582 613 // Get the maximum used line number (vertical position) for bars 583 614 function GetBarMaxLineNumber() { 584 585 586 587 588 589 590 591 592 593 } 594 615 $m=1; 616 if( $this->iObj != null ) { 617 $m = $this->iObj[0]->GetLineNbr(); 618 $n = count($this->iObj); 619 for($i=1; $i < $n; ++$i) { 620 $m=max($m,$this->iObj[$i]->GetLineNbr()); 621 } 622 } 623 return $m; 624 } 625 595 626 // Get the minumum and maximum used dates for all bars 596 627 function GetBarMinMax() { 597 598 599 600 601 602 603 //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]');604 605 606 607 608 609 610 611 if( $rmax != false ) 612 613 614 if( $rmin != false ) 615 616 617 618 619 620 $max = strtotime($maxDate); 621 628 $start = 0 ; 629 $n = count($this->iObj); 630 while( $start < $n && $this->iObj[$start]->GetMaxDate() === false ) 631 ++$start; 632 if( $start >= $n ) { 633 JpgraphError::RaiseL(6006); 634 //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]'); 635 } 636 637 $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate()); 638 $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate()); 639 640 for($i=$start+1; $i < $n; ++$i) { 641 $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()); 642 if( $rmax != false ) 643 $max=Max($max,$rmax); 644 $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()); 645 if( $rmin != false ) 646 $min=Min($min,$rmin); 647 } 648 $minDate = date("Y-m-d",$min); 649 $min = strtotime($minDate); 650 $maxDate = date("Y-m-d 23:59",$max); 651 $max = strtotime($maxDate); 652 return array($min,$max); 622 653 } 623 654 … … 628 659 function AutoSize() { 629 660 630 if( $this->img->img == null ) { 631 // The predefined left, right, top, bottom margins. 632 // Note that the top margin might incease depending on 633 // the title. 634 $lm = $this->img->left_margin; 635 $rm = $this->img->right_margin; 636 $rm += 2 ; 637 $tm = $this->img->top_margin; 638 $bm = $this->img->bottom_margin; 639 $bm += 1; 640 if( BRAND_TIMING ) $bm += 10; 641 642 // First find out the height 643 $n=$this->GetBarMaxLineNumber()+1; 644 $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); 645 $height=$n*((1+$this->iLabelVMarginFactor)*$m); 646 647 // Add the height of the scale titles 648 $h=$this->scale->GetHeaderHeight(); 649 $height += $h; 650 651 // Calculate the top margin needed for title and subtitle 652 if( $this->title->t != "" ) { 653 $tm += $this->title->GetFontHeight($this->img); 654 } 655 if( $this->subtitle->t != "" ) { 656 $tm += $this->subtitle->GetFontHeight($this->img); 657 } 658 659 // ...and then take the bottom and top plot margins into account 660 $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; 661 // Now find the minimum width for the chart required 662 663 // If day scale or smaller is shown then we use the day font width 664 // as the base size unit. 665 // If only weeks or above is displayed we use a modified unit to 666 // get a smaller image. 667 if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) { 668 // Add 2 pixel margin on each side 669 $fw=$this->scale->day->GetFontWidth($this->img)+4; 670 } 671 elseif( $this->scale->IsDisplayWeek() ) { 672 $fw = 8; 673 } 674 elseif( $this->scale->IsDisplayMonth() ) { 675 $fw = 4; 676 } 677 else { 678 $fw = 2; 679 } 680 681 $nd=$this->scale->GetNumberOfDays(); 682 683 if( $this->scale->IsDisplayDay() ) { 684 // If the days are displayed we also need to figure out 685 // how much space each day's title will require. 686 switch( $this->scale->day->iStyle ) { 687 case DAYSTYLE_LONG : 688 $txt = "Monday"; 689 break; 690 case DAYSTYLE_LONGDAYDATE1 : 691 $txt = "Monday 23 Jun"; 692 break; 693 case DAYSTYLE_LONGDAYDATE2 : 694 $txt = "Monday 23 Jun 2003"; 695 break; 696 case DAYSTYLE_SHORT : 697 $txt = "Mon"; 698 break; 699 case DAYSTYLE_SHORTDAYDATE1 : 661 if( $this->img->img == null ) { 662 // The predefined left, right, top, bottom margins. 663 // Note that the top margin might incease depending on 664 // the title. 665 $hadj = $vadj = 0; 666 if( $this->doshadow ) { 667 $hadj = $this->shadow_width; 668 $vadj = $this->shadow_width+5; 669 } 670 671 $lm = $this->img->left_margin; 672 $rm = $this->img->right_margin +$hadj; 673 $rm += 2 ; 674 $tm = $this->img->top_margin; 675 $bm = $this->img->bottom_margin + $vadj; 676 $bm += 2; 677 678 // If there are any added GanttVLine we must make sure that the 679 // bottom margin is wide enough to hold a title. 680 $n = count($this->iObj); 681 for($i=0; $i < $n; ++$i) { 682 if( $this->iObj[$i] instanceof GanttVLine ) { 683 $bm = max($bm,$this->iObj[$i]->title->GetHeight($this->img)+10); 684 } 685 } 686 687 // First find out the height 688 $n=$this->GetBarMaxLineNumber()+1; 689 $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); 690 $height=$n*((1+$this->iLabelVMarginFactor)*$m); 691 692 // Add the height of the scale titles 693 $h=$this->scale->GetHeaderHeight(); 694 $height += $h; 695 696 // Calculate the top margin needed for title and subtitle 697 if( $this->title->t != "" ) { 698 $tm += $this->title->GetFontHeight($this->img); 699 } 700 if( $this->subtitle->t != "" ) { 701 $tm += $this->subtitle->GetFontHeight($this->img); 702 } 703 704 // ...and then take the bottom and top plot margins into account 705 $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin; 706 // Now find the minimum width for the chart required 707 708 // If day scale or smaller is shown then we use the day font width 709 // as the base size unit. 710 // If only weeks or above is displayed we use a modified unit to 711 // get a smaller image. 712 if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) { 713 // Add 2 pixel margin on each side 714 $fw=$this->scale->day->GetFontWidth($this->img)+4; 715 } 716 elseif( $this->scale->IsDisplayWeek() ) { 717 $fw = 8; 718 } 719 elseif( $this->scale->IsDisplayMonth() ) { 720 $fw = 4; 721 } 722 else { 723 $fw = 2; 724 } 725 726 $nd=$this->scale->GetNumberOfDays(); 727 728 if( $this->scale->IsDisplayDay() ) { 729 // If the days are displayed we also need to figure out 730 // how much space each day's title will require. 731 switch( $this->scale->day->iStyle ) { 732 case DAYSTYLE_LONG : 733 $txt = "Monday"; 734 break; 735 case DAYSTYLE_LONGDAYDATE1 : 736 $txt = "Monday 23 Jun"; 737 break; 738 case DAYSTYLE_LONGDAYDATE2 : 739 $txt = "Monday 23 Jun 2003"; 740 break; 741 case DAYSTYLE_SHORT : 742 $txt = "Mon"; 743 break; 744 case DAYSTYLE_SHORTDAYDATE1 : 700 745 $txt = "Mon 23/6"; 701 702 703 704 705 706 707 708 746 break; 747 case DAYSTYLE_SHORTDAYDATE2 : 748 $txt = "Mon 23 Jun"; 749 break; 750 case DAYSTYLE_SHORTDAYDATE3 : 751 $txt = "Mon 23"; 752 break; 753 case DAYSTYLE_SHORTDATE1 : 709 754 $txt = "23/6"; 710 break; 711 case DAYSTYLE_SHORTDATE2 : 712 $txt = "23 Jun"; 713 break; 714 case DAYSTYLE_SHORTDATE3 : 715 $txt = "Mon 23"; 716 break; 717 case DAYSTYLE_SHORTDATE4 : 718 $txt = "88"; 719 break; 720 case DAYSTYLE_CUSTOM : 721 $txt = date($this->scale->day->iLabelFormStr, 722 strtotime('2003-12-20 18:00')); 723 break; 724 case DAYSTYLE_ONELETTER : 725 default: 726 $txt = "M"; 727 break; 728 } 729 $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6; 730 } 731 732 // If we have hours enabled we must make sure that each day has enough 733 // space to fit the number of hours to be displayed. 734 if( $this->scale->IsDisplayHour() ) { 735 // Depending on what format the user has choose we need different amount 736 // of space. We therefore create a typical string for the choosen format 737 // and determine the length of that string. 738 switch( $this->scale->hour->iStyle ) { 739 case HOURSTYLE_HMAMPM: 740 $txt = '12:00pm'; 741 break; 742 case HOURSTYLE_H24: 743 // 13 744 $txt = '24'; 745 break; 746 case HOURSTYLE_HAMPM: 747 $txt = '12pm'; 748 break; 749 case HOURSTYLE_CUSTOM: 750 $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00')); 751 break; 752 case HOURSTYLE_HM24: 753 default: 754 $txt = '24:00'; 755 break; 756 } 757 758 $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6; 759 $mw = $hfw; 760 if( $this->scale->IsDisplayMinute() ) { 761 // Depending on what format the user has choose we need different amount 762 // of space. We therefore create a typical string for the choosen format 763 // and determine the length of that string. 764 switch( $this->scale->minute->iStyle ) { 765 case HOURSTYLE_CUSTOM: 766 $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); 767 break; 768 case MINUTESTYLE_MM: 769 default: 770 $txt2 = '15'; 771 break; 772 } 773 774 $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6; 775 $n2 = ceil(60 / $this->scale->minute->GetIntervall() ); 776 $mw = $n2 * $mfw; 777 } 778 $hfw = $hfw < $mw ? $mw : $hfw ; 779 $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) ); 780 $hw = $n * $hfw; 781 $fw = $fw < $hw ? $hw : $fw ; 782 } 783 784 // We need to repeat this code block here as well. 785 // THIS iS NOT A MISTAKE ! 786 // We really need it since we need to adjust for minutes both in the case 787 // where hour scale is shown and when it is not shown. 788 789 if( $this->scale->IsDisplayMinute() ) { 790 // Depending on what format the user has choose we need different amount 791 // of space. We therefore create a typical string for the choosen format 792 // and determine the length of that string. 793 switch( $this->scale->minute->iStyle ) { 794 case HOURSTYLE_CUSTOM: 795 $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); 796 break; 797 case MINUTESTYLE_MM: 798 default: 799 $txt = '15'; 800 break; 801 } 802 803 $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6; 804 $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) ); 805 $mw = $n * $mfw; 806 $fw = $fw < $mw ? $mw : $fw ; 807 } 808 809 // If we display week we must make sure that 7*$fw is enough 810 // to fit up to 10 characters of the week font (if the week is enabled) 811 if( $this->scale->IsDisplayWeek() ) { 812 // Depending on what format the user has choose we need different amount 813 // of space 814 $fsw = strlen($this->scale->week->iLabelFormStr); 815 if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 816 $fsw += 8; 817 } 818 elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) { 819 $fsw += 7; 820 } 821 else { 822 $fsw += 4; 823 } 824 825 $ww = $fsw*$this->scale->week->GetFontWidth($this->img); 826 if( 7*$fw < $ww ) { 827 $fw = ceil($ww/7); 828 } 829 } 830 831 if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && 832 !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 833 $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) { 834 // If we don't display the individual days we can shrink the 835 // scale a little bit. This is a little bit pragmatic at the 836 // moment and should be re-written to take into account 837 // a) What scales exactly are shown and 838 // b) what format do they use so we know how wide we need to 839 // make each scale text space at minimum. 840 $fw /= 2; 841 if( !$this->scale->IsDisplayWeek() ) { 842 $fw /= 1.8; 843 } 844 } 845 846 $cw = $this->GetMaxActInfoColWidth() ; 847 $this->scale->actinfo->SetMinColWidth($cw); 848 if( $this->img->width <= 0 ) { 849 // Now determine the width for the activity titles column 850 851 // Firdst find out the maximum width of each object column 852 $titlewidth = max(max($this->GetMaxLabelWidth(), 853 $this->scale->tableTitle->GetWidth($this->img)), 854 $this->scale->actinfo->GetWidth($this->img)); 855 856 // Add the width of the vertivcal divider line 857 $titlewidth += $this->scale->divider->iWeight*2; 858 859 860 // Now get the total width taking 861 // titlewidth, left and rigt margin, dayfont size 862 // into account 863 $width = $titlewidth + $nd*$fw + $lm+$rm; 864 } 865 else { 866 $width = $this->img->width; 867 } 868 869 $width = round($width); 870 $height = round($height); 871 // Make a sanity check on image size 872 if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) { 873 JpgraphError::RaiseL(6007,$width,$height); 874 //("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."); 875 } 876 $this->img->CreateImgCanvas($width,$height); 877 $this->img->SetMargin($lm,$rm,$tm,$bm); 878 } 755 break; 756 case DAYSTYLE_SHORTDATE2 : 757 $txt = "23 Jun"; 758 break; 759 case DAYSTYLE_SHORTDATE3 : 760 $txt = "Mon 23"; 761 break; 762 case DAYSTYLE_SHORTDATE4 : 763 $txt = "88"; 764 break; 765 case DAYSTYLE_CUSTOM : 766 $txt = date($this->scale->day->iLabelFormStr,strtotime('2003-12-20 18:00')); 767 break; 768 case DAYSTYLE_ONELETTER : 769 default: 770 $txt = "M"; 771 break; 772 } 773 $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6; 774 } 775 776 // If we have hours enabled we must make sure that each day has enough 777 // space to fit the number of hours to be displayed. 778 if( $this->scale->IsDisplayHour() ) { 779 // Depending on what format the user has choose we need different amount 780 // of space. We therefore create a typical string for the choosen format 781 // and determine the length of that string. 782 switch( $this->scale->hour->iStyle ) { 783 case HOURSTYLE_HMAMPM: 784 $txt = '12:00pm'; 785 break; 786 case HOURSTYLE_H24: 787 // 13 788 $txt = '24'; 789 break; 790 case HOURSTYLE_HAMPM: 791 $txt = '12pm'; 792 break; 793 case HOURSTYLE_CUSTOM: 794 $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00')); 795 break; 796 case HOURSTYLE_HM24: 797 default: 798 $txt = '24:00'; 799 break; 800 } 801 802 $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6; 803 $mw = $hfw; 804 if( $this->scale->IsDisplayMinute() ) { 805 // Depending on what format the user has choose we need different amount 806 // of space. We therefore create a typical string for the choosen format 807 // and determine the length of that string. 808 switch( $this->scale->minute->iStyle ) { 809 case HOURSTYLE_CUSTOM: 810 $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); 811 break; 812 case MINUTESTYLE_MM: 813 default: 814 $txt2 = '15'; 815 break; 816 } 817 818 $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6; 819 $n2 = ceil(60 / $this->scale->minute->GetIntervall() ); 820 $mw = $n2 * $mfw; 821 } 822 $hfw = $hfw < $mw ? $mw : $hfw ; 823 $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) ); 824 $hw = $n * $hfw; 825 $fw = $fw < $hw ? $hw : $fw ; 826 } 827 828 // We need to repeat this code block here as well. 829 // THIS iS NOT A MISTAKE ! 830 // We really need it since we need to adjust for minutes both in the case 831 // where hour scale is shown and when it is not shown. 832 833 if( $this->scale->IsDisplayMinute() ) { 834 // Depending on what format the user has choose we need different amount 835 // of space. We therefore create a typical string for the choosen format 836 // and determine the length of that string. 837 switch( $this->scale->minute->iStyle ) { 838 case HOURSTYLE_CUSTOM: 839 $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55')); 840 break; 841 case MINUTESTYLE_MM: 842 default: 843 $txt = '15'; 844 break; 845 } 846 847 $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6; 848 $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) ); 849 $mw = $n * $mfw; 850 $fw = $fw < $mw ? $mw : $fw ; 851 } 852 853 // If we display week we must make sure that 7*$fw is enough 854 // to fit up to 10 characters of the week font (if the week is enabled) 855 if( $this->scale->IsDisplayWeek() ) { 856 // Depending on what format the user has choose we need different amount 857 // of space 858 $fsw = strlen($this->scale->week->iLabelFormStr); 859 if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 860 $fsw += 8; 861 } 862 elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) { 863 $fsw += 7; 864 } 865 else { 866 $fsw += 4; 867 } 868 869 $ww = $fsw*$this->scale->week->GetFontWidth($this->img); 870 if( 7*$fw < $ww ) { 871 $fw = ceil($ww/7); 872 } 873 } 874 875 if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() && 876 !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 877 $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) { 878 // If we don't display the individual days we can shrink the 879 // scale a little bit. This is a little bit pragmatic at the 880 // moment and should be re-written to take into account 881 // a) What scales exactly are shown and 882 // b) what format do they use so we know how wide we need to 883 // make each scale text space at minimum. 884 $fw /= 2; 885 if( !$this->scale->IsDisplayWeek() ) { 886 $fw /= 1.8; 887 } 888 } 889 890 $cw = $this->GetMaxActInfoColWidth() ; 891 $this->scale->actinfo->SetMinColWidth($cw); 892 if( $this->img->width <= 0 ) { 893 // Now determine the width for the activity titles column 894 895 // Firdst find out the maximum width of each object column 896 $titlewidth = max(max($this->GetMaxLabelWidth(), 897 $this->scale->tableTitle->GetWidth($this->img)), 898 $this->scale->actinfo->GetWidth($this->img)); 899 900 // Add the width of the vertivcal divider line 901 $titlewidth += $this->scale->divider->iWeight*2; 902 903 // Adjust the width by the user specified zoom factor 904 $fw *= $this->iZoomFactor; 905 906 // Now get the total width taking 907 // titlewidth, left and rigt margin, dayfont size 908 // into account 909 $width = $titlewidth + $nd*$fw + $lm+$rm; 910 } 911 else { 912 $width = $this->img->width; 913 } 914 915 $width = round($width); 916 $height = round($height); 917 // Make a sanity check on image size 918 if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) { 919 JpgraphError::RaiseL(6007,$width,$height); 920 //("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."); 921 } 922 $this->img->CreateImgCanvas($width,$height); 923 $this->img->SetMargin($lm,$rm,$tm,$bm); 924 } 879 925 } 880 926 … … 884 930 // must walk through all the objects, sigh... 885 931 function GetMaxActInfoColWidth() { 886 887 888 889 890 891 892 893 894 895 if( empty($w[$j]) ) 896 897 else 898 899 900 901 932 $n = count($this->iObj); 933 if( $n == 0 ) return; 934 $w = array(); 935 $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin; 936 937 for( $i=0; $i < $n; ++$i ) { 938 $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m); 939 $nn = count($tmp); 940 for( $j=0; $j < $nn; ++$j ) { 941 if( empty($w[$j]) ) 942 $w[$j] = $tmp[$j]; 943 else 944 $w[$j] = max($w[$j],$tmp[$j]); 945 } 946 } 947 return $w; 902 948 } 903 949 904 950 // Stroke the gantt chart 905 function Stroke($aStrokeFileName="") { 906 907 // If the filename is the predefined value = '_csim_special_' 908 // we assume that the call to stroke only needs to do enough 909 // to correctly generate the CSIM maps. 910 // We use this variable to skip things we don't strictly need 911 // to do to generate the image map to improve performance 912 // a best we can. Therefor you will see a lot of tests !$_csim in the 913 // code below. 914 $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); 915 916 // Should we autoscale dates? 917 918 if( !$this->scale->IsRangeSet() ) { 919 list($min,$max) = $this->GetBarMinMax(); 920 $this->scale->SetRange($min,$max); 921 } 922 923 $this->scale->AdjustStartEndDay(); 924 925 // Check if we should autoscale the image 926 $this->AutoSize(); 927 928 // Should we start from the top or just spread the bars out even over the 929 // available height 930 $this->scale->SetVertLayout($this->iLayout); 931 if( $this->iLayout == GANTT_FROMTOP ) { 932 $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); 933 $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor)); 934 } 935 // If it hasn't been set find out the maximum line number 936 if( $this->scale->iVertLines == -1 ) 937 $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; 938 939 $maxwidth=max($this->scale->actinfo->GetWidth($this->img), 940 max($this->GetMaxLabelWidth(), 941 $this->scale->tableTitle->GetWidth($this->img))); 942 943 $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor)); 944 945 if( !$_csim ) { 946 $this->StrokePlotArea(); 947 if( $this->iIconDepth == DEPTH_BACK ) { 948 $this->StrokeIcons(); 949 } 950 } 951 952 $this->scale->Stroke(); 953 954 if( !$_csim ) { 955 // Due to a minor off by 1 bug we need to temporarily adjust the margin 956 $this->img->right_margin--; 957 $this->StrokePlotBox(); 958 $this->img->right_margin++; 959 } 960 961 // Stroke Grid line 962 $this->hgrid->Stroke($this->img,$this->scale); 963 964 $n = count($this->iObj); 965 for($i=0; $i < $n; ++$i) { 966 //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2)); 967 $this->iObj[$i]->Stroke($this->img,$this->scale); 968 } 969 970 $this->StrokeTitles(); 971 972 if( !$_csim ) { 973 $this->StrokeConstrains(); 974 $this->footer->Stroke($this->img); 975 976 977 if( $this->iIconDepth == DEPTH_FRONT) { 978 $this->StrokeIcons(); 979 } 980 981 // Should we do any final image transformation 982 if( $this->iImgTrans ) { 983 if( !class_exists('ImgTrans',false) ) { 984 require_once('jpgraph_imgtrans.php'); 985 } 986 987 $tform = new ImgTrans($this->img->img); 988 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, 989 $this->iImgTransDirection,$this->iImgTransHighQ, 990 $this->iImgTransMinSize,$this->iImgTransFillColor, 991 $this->iImgTransBorder); 992 } 993 994 995 // If the filename is given as the special "__handle" 996 // then the image handler is returned and the image is NOT 997 // streamed back 998 if( $aStrokeFileName == _IMG_HANDLER ) { 999 return $this->img->img; 1000 } 1001 else { 1002 // Finally stream the generated picture 1003 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, 1004 $aStrokeFileName); 1005 } 1006 } 951 function Stroke($aStrokeFileName="") { 952 953 // If the filename is the predefined value = '_csim_special_' 954 // we assume that the call to stroke only needs to do enough 955 // to correctly generate the CSIM maps. 956 // We use this variable to skip things we don't strictly need 957 // to do to generate the image map to improve performance 958 // a best we can. Therefor you will see a lot of tests !$_csim in the 959 // code below. 960 $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE); 961 962 // Should we autoscale dates? 963 964 if( !$this->scale->IsRangeSet() ) { 965 list($min,$max) = $this->GetBarMinMax(); 966 $this->scale->SetRange($min,$max); 967 } 968 969 $this->scale->AdjustStartEndDay(); 970 971 // Check if we should autoscale the image 972 $this->AutoSize(); 973 974 // Should we start from the top or just spread the bars out even over the 975 // available height 976 $this->scale->SetVertLayout($this->iLayout); 977 if( $this->iLayout == GANTT_FROMTOP ) { 978 $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight()); 979 $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor)); 980 } 981 // If it hasn't been set find out the maximum line number 982 if( $this->scale->iVertLines == -1 ) 983 $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; 984 985 $maxwidth=max($this->scale->actinfo->GetWidth($this->img), 986 max($this->GetMaxLabelWidth(), 987 $this->scale->tableTitle->GetWidth($this->img))); 988 989 $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor)); 990 991 if( !$_csim ) { 992 $this->StrokePlotArea(); 993 if( $this->iIconDepth == DEPTH_BACK ) { 994 $this->StrokeIcons(); 995 } 996 } 997 998 $this->scale->Stroke(); 999 1000 if( !$_csim ) { 1001 // Due to a minor off by 1 bug we need to temporarily adjust the margin 1002 $this->img->right_margin--; 1003 $this->StrokePlotBox(); 1004 $this->img->right_margin++; 1005 } 1006 1007 // Stroke Grid line 1008 $this->hgrid->Stroke($this->img,$this->scale); 1009 1010 $n = count($this->iObj); 1011 for($i=0; $i < $n; ++$i) { 1012 //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2)); 1013 $this->iObj[$i]->Stroke($this->img,$this->scale); 1014 } 1015 1016 $this->StrokeTitles(); 1017 1018 if( !$_csim ) { 1019 $this->StrokeConstrains(); 1020 $this->footer->Stroke($this->img); 1021 1022 1023 if( $this->iIconDepth == DEPTH_FRONT) { 1024 $this->StrokeIcons(); 1025 } 1026 1027 // Stroke all added user texts 1028 $this->StrokeTexts(); 1029 1030 // Should we do any final image transformation 1031 if( $this->iImgTrans ) { 1032 if( !class_exists('ImgTrans',false) ) { 1033 require_once('jpgraph_imgtrans.php'); 1034 } 1035 1036 $tform = new ImgTrans($this->img->img); 1037 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist, 1038 $this->iImgTransDirection,$this->iImgTransHighQ, 1039 $this->iImgTransMinSize,$this->iImgTransFillColor, 1040 $this->iImgTransBorder); 1041 } 1042 1043 1044 // If the filename is given as the special "__handle" 1045 // then the image handler is returned and the image is NOT 1046 // streamed back 1047 if( $aStrokeFileName == _IMG_HANDLER ) { 1048 return $this->img->img; 1049 } 1050 else { 1051 // Finally stream the generated picture 1052 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline, 1053 $aStrokeFileName); 1054 } 1055 } 1007 1056 } 1008 1057 1009 1058 function StrokeConstrains() { 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 //('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.');1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 //('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos);1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1059 $n = count($this->iObj); 1060 1061 // Stroke all constrains 1062 for($i=0; $i < $n; ++$i) { 1063 1064 // Some gantt objects may not have constraints associated with them 1065 // for example we can add IconPlots which doesn't have this property. 1066 if( empty($this->iObj[$i]->constraints) ) continue; 1067 1068 $numConstrains = count($this->iObj[$i]->constraints); 1069 1070 for( $k = 0; $k < $numConstrains; $k++ ) { 1071 $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow; 1072 if( $vpos >= 0 ) { 1073 $c1 = $this->iObj[$i]->iConstrainPos; 1074 1075 // Find out which object is on the target row 1076 $targetobj = -1; 1077 for( $j=0; $j < $n && $targetobj == -1; ++$j ) { 1078 if( $this->iObj[$j]->iVPos == $vpos ) { 1079 $targetobj = $j; 1080 } 1081 } 1082 if( $targetobj == -1 ) { 1083 JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos); 1084 //('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.'); 1085 } 1086 $c2 = $this->iObj[$targetobj]->iConstrainPos; 1087 if( count($c1) == 4 && count($c2 ) == 4) { 1088 switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) { 1089 case CONSTRAIN_ENDSTART: 1090 if( $c1[1] < $c2[1] ) { 1091 $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]); 1092 } 1093 else { 1094 $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]); 1095 } 1096 $link->SetPath(3); 1097 break; 1098 case CONSTRAIN_STARTEND: 1099 if( $c1[1] < $c2[1] ) { 1100 $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]); 1101 } 1102 else { 1103 $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]); 1104 } 1105 $link->SetPath(0); 1106 break; 1107 case CONSTRAIN_ENDEND: 1108 if( $c1[1] < $c2[1] ) { 1109 $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]); 1110 } 1111 else { 1112 $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]); 1113 } 1114 $link->SetPath(1); 1115 break; 1116 case CONSTRAIN_STARTSTART: 1117 if( $c1[1] < $c2[1] ) { 1118 $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]); 1119 } 1120 else { 1121 $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]); 1122 } 1123 $link->SetPath(3); 1124 break; 1125 default: 1126 JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos); 1127 //('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos); 1128 break; 1129 } 1130 1131 $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor); 1132 $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize, 1133 $this->iObj[$i]->constraints[$k]->iConstrainArrowType); 1134 1135 $link->Stroke($this->img); 1136 } 1137 } 1138 } 1139 } 1091 1140 } 1092 1141 1093 1142 function GetCSIMAreas() { 1094 1095 1096 1097 1098 1099 1100 1101 1102 for( $i=$n-1; $i >= 0; --$i ) 1103 1104 1143 if( !$this->iHasStroked ) 1144 $this->Stroke(_CSIM_SPECIALFILE); 1145 1146 $csim = $this->title->GetCSIMAreas(); 1147 $csim .= $this->subtitle->GetCSIMAreas(); 1148 $csim .= $this->subsubtitle->GetCSIMAreas(); 1149 1150 $n = count($this->iObj); 1151 for( $i=$n-1; $i >= 0; --$i ) 1152 $csim .= $this->iObj[$i]->GetCSIMArea(); 1153 return $csim; 1105 1154 } 1106 1155 } … … 1128 1177 1129 1178 function GetLen() { 1130 return $this->iLen ; 1179 return $this->iLen ; 1131 1180 } 1132 1181 1133 1182 function GetImg($aIdx) { 1134 1135 1136 //('Illegal icon index for Gantt builtin icon ['.$aIdx.']');1137 1138 return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1])); 1139 } 1140 1141 function PredefIcons() {1142 1143 1144 1145 1146 $this->iBuiltinIcon[0][1]= 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ; 1161 1162 1163 1164 1165 1166 $this->iBuiltinIcon[1][1]= 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ; 1180 1181 1182 1183 1184 1185 $this->iBuiltinIcon[2][1]= 1186 1187 1188 1189 1190 1191 1192 1193 1194 'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ; 1195 1196 1197 1198 1199 1200 $this->iBuiltinIcon[3][1]= 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ; 1216 1217 1218 1219 1220 1221 $this->iBuiltinIcon[4][1]= 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ; 1232 1233 1234 1235 1236 1237 $this->iBuiltinIcon[5][1]= 1238 1239 1240 1241 1242 1243 1244 1245 'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ; 1246 1247 1248 1249 1250 1251 $this->iBuiltinIcon[6][1]= 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ; 1271 1272 1273 1274 1275 1276 $this->iBuiltinIcon[7][1]= 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ; 1290 1291 1292 1293 1294 1295 $this->iBuiltinIcon[8][1]= 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ; 1308 1309 1310 1311 1312 1313 $this->iBuiltinIcon[9][1]= 1314 1315 1316 1317 1318 1319 1320 1321 'iOsCHgAAAABJRU5ErkJggg==' ; 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1183 if( $aIdx < 0 || $aIdx >= $this->iLen ) { 1184 JpGraphError::RaiseL(6010,$aIdx); 1185 //('Illegal icon index for Gantt builtin icon ['.$aIdx.']'); 1186 } 1187 return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1])); 1188 } 1189 1190 function __construct() { 1191 //========================================================== 1192 // warning.png 1193 //========================================================== 1194 $this->iBuiltinIcon[0][0]= 1043 ; 1195 $this->iBuiltinIcon[0][1]= 1196 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'. 1197 'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'. 1198 '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'. 1199 '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'. 1200 'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'. 1201 'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'. 1202 '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'. 1203 'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'. 1204 'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'. 1205 'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'. 1206 'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'. 1207 'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'. 1208 'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'. 1209 'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ; 1210 1211 //========================================================== 1212 // edit.png 1213 //========================================================== 1214 $this->iBuiltinIcon[1][0]= 959 ; 1215 $this->iBuiltinIcon[1][1]= 1216 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'. 1217 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'. 1218 'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'. 1219 'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'. 1220 'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'. 1221 'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'. 1222 'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'. 1223 'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'. 1224 'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'. 1225 'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'. 1226 'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'. 1227 'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'. 1228 'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ; 1229 1230 //========================================================== 1231 // endconstrain.png 1232 //========================================================== 1233 $this->iBuiltinIcon[2][0]= 666 ; 1234 $this->iBuiltinIcon[2][1]= 1235 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 1236 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'. 1237 'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'. 1238 'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'. 1239 'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'. 1240 '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'. 1241 '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'. 1242 'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'. 1243 'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ; 1244 1245 //========================================================== 1246 // mail.png 1247 //========================================================== 1248 $this->iBuiltinIcon[3][0]= 1122 ; 1249 $this->iBuiltinIcon[3][1]= 1250 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 1251 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'. 1252 'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'. 1253 'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'. 1254 'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'. 1255 '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'. 1256 '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'. 1257 'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'. 1258 'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'. 1259 '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'. 1260 'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'. 1261 'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'. 1262 'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'. 1263 'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'. 1264 'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ; 1265 1266 //========================================================== 1267 // startconstrain.png 1268 //========================================================== 1269 $this->iBuiltinIcon[4][0]= 725 ; 1270 $this->iBuiltinIcon[4][1]= 1271 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 1272 'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'. 1273 'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'. 1274 'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'. 1275 'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'. 1276 '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'. 1277 'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'. 1278 'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'. 1279 '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'. 1280 'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ; 1281 1282 //========================================================== 1283 // calc.png 1284 //========================================================== 1285 $this->iBuiltinIcon[5][0]= 589 ; 1286 $this->iBuiltinIcon[5][1]= 1287 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'. 1288 'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'. 1289 'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'. 1290 '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'. 1291 'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'. 1292 'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'. 1293 'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'. 1294 'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ; 1295 1296 //========================================================== 1297 // mag.png 1298 //========================================================== 1299 $this->iBuiltinIcon[6][0]= 1415 ; 1300 $this->iBuiltinIcon[6][1]= 1301 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'. 1302 'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'. 1303 '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'. 1304 'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'. 1305 'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'. 1306 'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'. 1307 '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'. 1308 'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'. 1309 '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'. 1310 'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'. 1311 'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'. 1312 'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'. 1313 'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'. 1314 'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'. 1315 'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'. 1316 'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'. 1317 'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'. 1318 'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'. 1319 'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ; 1320 1321 //========================================================== 1322 // lock.png 1323 //========================================================== 1324 $this->iBuiltinIcon[7][0]= 963 ; 1325 $this->iBuiltinIcon[7][1]= 1326 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 1327 'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'. 1328 'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'. 1329 'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'. 1330 'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'. 1331 'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'. 1332 'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'. 1333 'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'. 1334 'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'. 1335 'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'. 1336 'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'. 1337 '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'. 1338 'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ; 1339 1340 //========================================================== 1341 // stop.png 1342 //========================================================== 1343 $this->iBuiltinIcon[8][0]= 889 ; 1344 $this->iBuiltinIcon[8][1]= 1345 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 1346 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'. 1347 'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'. 1348 'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'. 1349 'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'. 1350 'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'. 1351 'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'. 1352 'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'. 1353 'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'. 1354 'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'. 1355 'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'. 1356 'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ; 1357 1358 //========================================================== 1359 // error.png 1360 //========================================================== 1361 $this->iBuiltinIcon[9][0]= 541 ; 1362 $this->iBuiltinIcon[9][1]= 1363 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'. 1364 'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'. 1365 'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'. 1366 '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'. 1367 'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'. 1368 'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'. 1369 'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'. 1370 'iOsCHgAAAABJRU5ErkJggg==' ; 1371 1372 //========================================================== 1373 // openfolder.png 1374 //========================================================== 1375 $this->iBuiltinIcon[10][0]= 2040 ; 1376 $this->iBuiltinIcon[10][1]= 1377 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'. 1378 'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'. 1379 'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'. 1380 'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'. 1381 'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'. 1382 'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'. 1383 '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'. 1384 'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'. 1385 '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'. 1386 'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'. 1387 'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'. 1388 'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'. 1389 'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'. 1390 'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'. 1391 'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'. 1392 'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'. 1393 'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'. 1394 'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'. 1395 'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'. 1396 'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'. 1397 'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'. 1398 'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'. 1399 'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'. 1400 'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'. 1401 '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'. 1402 '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'. 1403 'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'. 1404 'dBntAAAAAElFTkSuQmCC' ; 1405 1406 //========================================================== 1407 // folder.png 1408 //========================================================== 1360 1409 $this->iBuiltinIcon[11][0]= 1824 ; 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1410 $this->iBuiltinIcon[11][1]= 1411 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 1412 'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'. 1413 '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'. 1414 'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'. 1415 '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'. 1416 'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'. 1417 'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'. 1418 '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'. 1419 'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'. 1420 'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'. 1421 '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'. 1422 '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'. 1423 'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'. 1424 'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'. 1425 'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'. 1426 'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'. 1427 'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'. 1428 'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'. 1429 'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'. 1430 'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'. 1431 'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'. 1432 'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'. 1433 'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'. 1434 'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'. 1435 'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ; 1436 1437 //========================================================== 1438 // file_important.png 1439 //========================================================== 1440 $this->iBuiltinIcon[12][0]= 1785 ; 1441 $this->iBuiltinIcon[12][1]= 1442 'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'. 1443 'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'. 1444 'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'. 1445 'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'. 1446 '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'. 1447 's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'. 1448 'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'. 1449 'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'. 1450 'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'. 1451 '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'. 1452 '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'. 1453 'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'. 1454 'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'. 1455 'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'. 1456 'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'. 1457 't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'. 1458 '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'. 1459 'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'. 1460 'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'. 1461 'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'. 1462 '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'. 1463 'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'. 1464 'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'. 1465 '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ; 1466 1467 $this->iLen = count($this->iBuiltinIcon); 1419 1468 } 1420 1469 } … … 1427 1476 //=================================================== 1428 1477 // CLASS IconImage 1429 // Description: Holds properties for an icon image 1478 // Description: Holds properties for an icon image 1430 1479 //=================================================== 1431 1480 class IconImage { … … 1435 1484 private $iScale=1.0; 1436 1485 1437 function IconImage($aIcon,$aScale=1) {1438 GLOBAL $_gPredefIcons ; 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 //('Argument to IconImage must be string or integer');1449 1450 1451 1452 1486 function __construct($aIcon,$aScale=1) { 1487 GLOBAL $_gPredefIcons ; 1488 if( is_string($aIcon) ) { 1489 $this->iGDImage = Graph::LoadBkgImage('',$aIcon); 1490 } 1491 elseif( is_integer($aIcon) ) { 1492 // Builtin image 1493 $this->iGDImage = $_gPredefIcons->GetImg($aIcon); 1494 } 1495 else { 1496 JpGraphError::RaiseL(6011); 1497 //('Argument to IconImage must be string or integer'); 1498 } 1499 $this->iScale = $aScale; 1500 $this->iWidth = Image::GetWidth($this->iGDImage); 1501 $this->iHeight = Image::GetHeight($this->iGDImage); 1453 1502 } 1454 1503 1455 1504 function GetWidth() { 1456 1505 return round($this->iScale*$this->iWidth); 1457 1506 } 1458 1507 1459 1508 function GetHeight() { 1460 1509 return round($this->iScale*$this->iHeight); 1461 1510 } 1462 1511 1463 1512 function SetAlign($aX='left',$aY='center') { 1464 1465 $this->ixalign = $aX; 1466 $this->iyalign = $aY; 1467 1513 $this->ixalign = $aX; 1514 $this->iyalign = $aY; 1468 1515 } 1469 1516 1470 1517 function Stroke($aImg,$x,$y) { 1471 1518 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1519 if( $this->ixalign == 'right' ) { 1520 $x -= $this->iWidth; 1521 } 1522 elseif( $this->ixalign == 'center' ) { 1523 $x -= round($this->iWidth/2*$this->iScale); 1524 } 1525 1526 if( $this->iyalign == 'bottom' ) { 1527 $y -= $this->iHeight; 1528 } 1529 elseif( $this->iyalign == 'center' ) { 1530 $y -= round($this->iHeight/2*$this->iScale); 1531 } 1532 1533 $aImg->Copy($this->iGDImage, 1534 $x,$y,0,0, 1535 round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale), 1536 $this->iWidth,$this->iHeight); 1490 1537 } 1491 1538 } … … 1500 1547 public $csimtarget='',$csimwintarget='',$csimalt=''; 1501 1548 private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10; 1549 private $iFontArray=array(); 1502 1550 private $iColor="black"; 1503 1551 private $iText=""; 1504 1552 private $iHAlign="left",$iVAlign="bottom"; 1505 1506 //---------------1507 // CONSTRUCTOR 1508 function TextProperty($aTxt='') {1509 1510 } 1511 1512 //---------------1513 // PUBLIC METHODS 1553 1554 //--------------- 1555 // CONSTRUCTOR 1556 function __construct($aTxt='') { 1557 $this->iText = $aTxt; 1558 } 1559 1560 //--------------- 1561 // PUBLIC METHODS 1514 1562 function Set($aTxt) { 1515 1563 $this->iText = $aTxt; 1516 1564 } 1517 1565 1518 1566 function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') { 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1567 if( is_string($aTarget) ) 1568 $aTarget = array($aTarget); 1569 $this->csimtarget=$aTarget; 1570 1571 if( is_string($aWinTarget) ) 1572 $aWinTarget = array($aWinTarget); 1573 $this->csimwintarget=$aWinTarget; 1574 1575 if( is_string($aAltText) ) 1576 $aAltText = array($aAltText); 1529 1577 $this->csimalt=$aAltText; 1530 1531 } 1532 1578 1579 } 1580 1533 1581 function SetCSIMAlt($aAltText) { 1534 1535 1582 if( is_string($aAltText) ) 1583 $aAltText = array($aAltText); 1536 1584 $this->csimalt=$aAltText; 1537 1585 } … … 1539 1587 // Set text color 1540 1588 function SetColor($aColor) { 1541 1542 } 1543 1589 $this->iColor = $aColor; 1590 } 1591 1544 1592 function HasTabs() { 1545 1546 1547 1548 1549 1550 1551 } 1552 1593 if( is_string($this->iText) ) { 1594 return substr_count($this->iText,"\t") > 0; 1595 } 1596 elseif( is_array($this->iText) ) { 1597 return false; 1598 } 1599 } 1600 1553 1601 // Get number of tabs in string 1554 1602 function GetNbrTabs() { 1555 1556 1557 1558 1559 1560 1561 } 1562 1603 if( is_string($this->iText) ) { 1604 return substr_count($this->iText,"\t") ; 1605 } 1606 else{ 1607 return 0; 1608 } 1609 } 1610 1563 1611 // Set alignment 1564 1612 function Align($aHAlign,$aVAlign="bottom") { 1565 1566 1567 } 1568 1613 $this->iHAlign=$aHAlign; 1614 $this->iVAlign=$aVAlign; 1615 } 1616 1569 1617 // Synonym 1570 1618 function SetAlign($aHAlign,$aVAlign="bottom") { 1571 1572 1573 } 1574 1619 $this->iHAlign=$aHAlign; 1620 $this->iVAlign=$aVAlign; 1621 } 1622 1575 1623 // Specify font 1576 1624 function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { 1577 $this->iFFamily = $aFFamily; 1578 $this->iFStyle = $aFStyle; 1579 $this->iFSize = $aFSize; 1580 } 1625 $this->iFFamily = $aFFamily; 1626 $this->iFStyle = $aFStyle; 1627 $this->iFSize = $aFSize; 1628 } 1629 1630 function SetColumnFonts($aFontArray) { 1631 if( !is_array($aFontArray) || count($aFontArray[0]) != 3 ) { 1632 JpGraphError::RaiseL(6033); 1633 // 'Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)' 1634 } 1635 $this->iFontArray = $aFontArray; 1636 } 1637 1581 1638 1582 1639 function IsColumns() { 1583 return is_array($this->iText) ; 1584 } 1585 1640 return is_array($this->iText) ; 1641 } 1642 1586 1643 // Get width of text. If text contains several columns separated by 1587 // tabs then return both the total width as well as an array with a 1644 // tabs then return both the total width as well as an array with a 1588 1645 // width for each column. 1589 1646 function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) { 1590 $extra_margin=4; 1591 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1592 if( is_string($this->iText) ) { 1593 if( strlen($this->iText) == 0 ) return 0; 1594 $tmp = split("\t",$this->iText); 1595 if( count($tmp) <= 1 || !$aUseTabs ) { 1596 $w = $aImg->GetTextWidth($this->iText); 1597 return $w + 2*$extra_margin; 1598 } 1599 else { 1600 $tot=0; 1601 $n = count($tmp); 1602 for($i=0; $i < $n; ++$i) { 1603 $res[$i] = $aImg->GetTextWidth($tmp[$i]); 1604 $tot += $res[$i]*$aTabExtraMargin; 1605 } 1606 return array(round($tot),$res); 1607 } 1608 } 1609 elseif( is_object($this->iText) ) { 1610 // A single icon 1611 return $this->iText->GetWidth()+2*$extra_margin; 1612 } 1613 elseif( is_array($this->iText) ) { 1614 // Must be an array of texts. In this case we return the sum of the 1615 // length + a fixed margin of 4 pixels on each text string 1616 $n = count($this->iText); 1617 for( $i=0, $w=0; $i < $n; ++$i ) { 1618 $tmp = $this->iText[$i]; 1619 if( is_string($tmp) ) { 1620 $w += $aImg->GetTextWidth($tmp)+$extra_margin; 1621 } 1622 else { 1623 if( is_object($tmp) === false ) { 1624 JpGraphError::RaiseL(6012); 1625 } 1626 $w += $tmp->GetWidth()+$extra_margin; 1627 } 1628 } 1629 return $w; 1630 } 1631 else { 1632 JpGraphError::RaiseL(6012); 1633 } 1647 $extra_margin=4; 1648 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1649 if( is_string($this->iText) ) { 1650 if( strlen($this->iText) == 0 ) return 0; 1651 $tmp = preg_split('/\t/',$this->iText); 1652 if( count($tmp) <= 1 || !$aUseTabs ) { 1653 $w = $aImg->GetTextWidth($this->iText); 1654 return $w + 2*$extra_margin; 1655 } 1656 else { 1657 $tot=0; 1658 $n = count($tmp); 1659 for($i=0; $i < $n; ++$i) { 1660 $res[$i] = $aImg->GetTextWidth($tmp[$i]); 1661 $tot += $res[$i]*$aTabExtraMargin; 1662 } 1663 return array(round($tot),$res); 1664 } 1665 } 1666 elseif( is_object($this->iText) ) { 1667 // A single icon 1668 return $this->iText->GetWidth()+2*$extra_margin; 1669 } 1670 elseif( is_array($this->iText) ) { 1671 // Must be an array of texts. In this case we return the sum of the 1672 // length + a fixed margin of 4 pixels on each text string 1673 $n = count($this->iText); 1674 $nf = count($this->iFontArray); 1675 for( $i=0, $w=0; $i < $n; ++$i ) { 1676 if( $i < $nf ) { 1677 $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); 1678 } 1679 else { 1680 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1681 } 1682 $tmp = $this->iText[$i]; 1683 if( is_string($tmp) ) { 1684 $w += $aImg->GetTextWidth($tmp)+$extra_margin; 1685 } 1686 else { 1687 if( is_object($tmp) === false ) { 1688 JpGraphError::RaiseL(6012); 1689 } 1690 $w += $tmp->GetWidth()+$extra_margin; 1691 } 1692 } 1693 return $w; 1694 } 1695 else { 1696 JpGraphError::RaiseL(6012); 1697 } 1634 1698 } 1635 1699 … … 1638 1702 // column as an array of one 1639 1703 function GetColWidth($aImg,$aMargin=0) { 1640 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1641 if( is_array($this->iText) ) { 1642 $n = count($this->iText); 1643 for( $i=0, $w=array(); $i < $n; ++$i ) { 1644 $tmp = $this->iText[$i]; 1645 if( is_string($tmp) ) { 1646 $w[$i] = $aImg->GetTextWidth($this->iText[$i])+$aMargin; 1647 } 1648 else { 1649 if( is_object($tmp) === false ) { 1650 JpGraphError::RaiseL(6012); 1651 } 1652 $w[$i] = $tmp->GetWidth()+$aMargin; 1653 } 1654 } 1655 return $w; 1656 } 1657 else { 1658 return array($this->GetWidth($aImg)); 1659 } 1660 } 1661 1704 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1705 if( is_array($this->iText) ) { 1706 $n = count($this->iText); 1707 $nf = count($this->iFontArray); 1708 for( $i=0, $w=array(); $i < $n; ++$i ) { 1709 $tmp = $this->iText[$i]; 1710 if( is_string($tmp) ) { 1711 if( $i < $nf ) { 1712 $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); 1713 } 1714 else { 1715 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1716 } 1717 $w[$i] = $aImg->GetTextWidth($tmp)+$aMargin; 1718 } 1719 else { 1720 if( is_object($tmp) === false ) { 1721 JpGraphError::RaiseL(6012); 1722 } 1723 $w[$i] = $tmp->GetWidth()+$aMargin; 1724 } 1725 } 1726 return $w; 1727 } 1728 else { 1729 return array($this->GetWidth($aImg)); 1730 } 1731 } 1732 1662 1733 // Get total height of text 1663 1734 function GetHeight($aImg) { 1664 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1665 return $aImg->GetFontHeight(); 1666 } 1667 1668 // Unhide/hide the text 1735 $nf = count($this->iFontArray); 1736 $maxheight = -1; 1737 1738 if( $nf > 0 ) { 1739 // We have to find out the largest font and take that one as the 1740 // height of the row 1741 for($i=0; $i < $nf; ++$i ) { 1742 $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]); 1743 $height = $aImg->GetFontHeight(); 1744 $maxheight = max($height,$maxheight); 1745 } 1746 } 1747 1748 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1749 $height = $aImg->GetFontHeight(); 1750 $maxheight = max($height,$maxheight); 1751 return $maxheight; 1752 } 1753 1754 // Unhide/hide the text 1669 1755 function Show($aShow=true) { 1670 1671 } 1672 1756 $this->iShow=$aShow; 1757 } 1758 1673 1759 // Stroke text at (x,y) coordinates. If the text contains tabs then the 1674 1760 // x parameter should be an array of positions to be used for each successive 1675 1761 // tab mark. If no array is supplied then the tabs will be ignored. 1676 1762 function Stroke($aImg,$aX,$aY) { 1677 if( $this->iShow ) { 1678 $aImg->SetColor($this->iColor); 1679 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1680 $aImg->SetTextAlign($this->iHAlign,$this->iVAlign); 1681 if( $this->GetNbrTabs() <= 1 ) { 1682 if( is_string($this->iText) ) { 1683 // Get rid of any "\t" characters and stroke string 1684 if( is_array($aX) ) $aX=$aX[0]; 1685 if( is_array($aY) ) $aY=$aY[0]; 1686 $aImg->StrokeText($aX,$aY,str_replace("\t"," ",$this->iText)); 1687 } 1688 elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) { 1689 $ax = is_array($aX) ; 1690 $ay = is_array($aY) ; 1691 if( $ax && $ay ) { 1692 // Nothing; both are already arrays 1693 } 1694 elseif( $ax ) { 1695 $aY = array_fill(0,$n,$aY); 1696 } 1697 elseif( $ay ) { 1698 $aX = array_fill(0,$n,$aX); 1699 } 1700 else { 1701 $aX = array_fill(0,$n,$aX); 1702 $aY = array_fill(0,$n,$aY); 1703 } 1704 $n = min($n, count($aX) ) ; 1705 $n = min($n, count($aY) ) ; 1706 for($i=0; $i < $n; ++$i ) { 1707 $tmp = $this->iText[$i]; 1708 if( is_object($tmp) ) { 1709 $tmp->Stroke($aImg,$aX[$i],$aY[$i]); 1710 } 1711 else 1712 $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp)); 1713 } 1714 } 1715 } 1716 else { 1717 $tmp = split("\t",$this->iText); 1718 $n = min(count($tmp),count($aX)); 1719 for($i=0; $i < $n; ++$i) { 1720 $aImg->StrokeText($aX[$i],$aY,$tmp[$i]); 1721 } 1722 } 1723 } 1763 if( $this->iShow ) { 1764 $aImg->SetColor($this->iColor); 1765 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1766 $aImg->SetTextAlign($this->iHAlign,$this->iVAlign); 1767 if( $this->GetNbrTabs() < 1 ) { 1768 if( is_string($this->iText) ) { 1769 if( is_array($aX) ) $aX=$aX[0]; 1770 if( is_array($aY) ) $aY=$aY[0]; 1771 $aImg->StrokeText($aX,$aY,$this->iText); 1772 } 1773 elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) { 1774 $ax = is_array($aX) ; 1775 $ay = is_array($aY) ; 1776 if( $ax && $ay ) { 1777 // Nothing; both are already arrays 1778 } 1779 elseif( $ax ) { 1780 $aY = array_fill(0,$n,$aY); 1781 } 1782 elseif( $ay ) { 1783 $aX = array_fill(0,$n,$aX); 1784 } 1785 else { 1786 $aX = array_fill(0,$n,$aX); 1787 $aY = array_fill(0,$n,$aY); 1788 } 1789 $n = min($n, count($aX) ) ; 1790 $n = min($n, count($aY) ) ; 1791 for($i=0; $i < $n; ++$i ) { 1792 $tmp = $this->iText[$i]; 1793 if( is_object($tmp) ) { 1794 $tmp->Stroke($aImg,$aX[$i],$aY[$i]); 1795 } 1796 else { 1797 if( $i < count($this->iFontArray) ) { 1798 $font = $this->iFontArray[$i]; 1799 $aImg->SetFont($font[0],$font[1],$font[2]); 1800 } 1801 else { 1802 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1803 } 1804 $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp)); 1805 } 1806 } 1807 } 1808 } 1809 else { 1810 $tmp = preg_split('/\t/',$this->iText); 1811 $n = min(count($tmp),count($aX)); 1812 for($i=0; $i < $n; ++$i) { 1813 if( $i < count($this->iFontArray) ) { 1814 $font = $this->iFontArray[$i]; 1815 $aImg->SetFont($font[0],$font[1],$font[2]); 1816 } 1817 else { 1818 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1819 } 1820 $aImg->StrokeText($aX[$i],$aY,$tmp[$i]); 1821 } 1822 } 1823 } 1724 1824 } 1725 1825 } … … 1727 1827 //=================================================== 1728 1828 // CLASS HeaderProperty 1729 // Description: Data encapsulating class to hold property 1829 // Description: Data encapsulating class to hold property 1730 1830 // for each type of the scale headers 1731 1831 //=================================================== … … 1742 1842 public $iIntervall = 1; 1743 1843 1744 //---------------1745 // CONSTRUCTOR 1746 function HeaderProperty() {1747 1748 } 1749 1750 //---------------1751 // PUBLIC METHODS 1844 //--------------- 1845 // CONSTRUCTOR 1846 function __construct() { 1847 $this->grid = new LineProperty(); 1848 } 1849 1850 //--------------- 1851 // PUBLIC METHODS 1752 1852 function Show($aShow=true) { 1753 1853 $this->iShowLabels = $aShow; 1754 1854 } 1755 1855 1756 1856 function SetIntervall($aInt) { 1757 $this->iIntervall = $aInt; 1857 $this->iIntervall = $aInt; 1858 } 1859 1860 function SetInterval($aInt) { 1861 $this->iIntervall = $aInt; 1758 1862 } 1759 1863 1760 1864 function GetIntervall() { 1761 1762 } 1763 1865 return $this->iIntervall ; 1866 } 1867 1764 1868 function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) { 1765 1766 $this->iFStyle= $aFStyle;1767 $this->iFSize= $aFSize;1869 $this->iFFamily = $aFFamily; 1870 $this->iFStyle = $aFStyle; 1871 $this->iFSize = $aFSize; 1768 1872 } 1769 1873 1770 1874 function SetFontColor($aColor) { 1771 1772 } 1773 1875 $this->iTextColor = $aColor; 1876 } 1877 1774 1878 function GetFontHeight($aImg) { 1775 1776 1879 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1880 return $aImg->GetFontHeight(); 1777 1881 } 1778 1882 1779 1883 function GetFontWidth($aImg) { 1780 1781 1884 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1885 return $aImg->GetFontWidth(); 1782 1886 } 1783 1887 1784 1888 function GetStrWidth($aImg,$aStr) { 1785 1786 1787 } 1788 1889 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize); 1890 return $aImg->GetTextWidth($aStr); 1891 } 1892 1789 1893 function SetStyle($aStyle) { 1790 1791 } 1792 1894 $this->iStyle = $aStyle; 1895 } 1896 1793 1897 function SetBackgroundColor($aColor) { 1794 1898 $this->iBackgroundColor=$aColor; 1795 1899 } 1796 1900 1797 1901 function SetFrameWeight($aWeight) { 1798 1902 $this->iFrameWeight=$aWeight; 1799 1903 } 1800 1904 1801 1905 function SetFrameColor($aColor) { 1802 1803 } 1804 1906 $this->iFrameColor=$aColor; 1907 } 1908 1805 1909 // Only used by day scale 1806 1910 function SetWeekendColor($aColor) { 1807 1808 } 1809 1911 $this->iWeekendBackgroundColor=$aColor; 1912 } 1913 1810 1914 // Only used by day scale 1811 1915 function SetSundayFontColor($aColor) { 1812 1813 } 1814 1916 $this->iSundayTextColor=$aColor; 1917 } 1918 1815 1919 function SetTitleVertMargin($aMargin) { 1816 1817 } 1818 1920 $this->iTitleVertMargin=$aMargin; 1921 } 1922 1819 1923 function SetLabelFormatString($aStr) { 1820 1924 $this->iLabelFormStr=$aStr; 1821 1925 } 1822 1926 1823 1927 function SetFormatString($aStr) { 1824 1928 $this->SetLabelFormatString($aStr); 1825 1929 } 1826 1930 … … 1844 1948 public $actinfo; 1845 1949 public $iTopPlotMargin=10,$iBottomPlotMargin=15; 1846 public $iVertLines=-1; 1950 public $iVertLines=-1; 1847 1951 public $iVertHeaderSize=-1; 1848 1952 // The width of the labels (defaults to the widest of all labels) 1849 private $iLabelWidth; 1953 private $iLabelWidth; 1850 1954 // Out image to stroke the scale to 1851 private $iImg; 1955 private $iImg; 1852 1956 private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black"; 1853 1957 private $iTableHeaderFrameWeight=1; … … 1856 1960 private $iVertLayout=GANTT_EVEN; 1857 1961 private $iUsePlotWeekendBackground=true; 1858 private $iWeekStart = 1; 1859 1860 //---------------1861 // CONSTRUCTOR 1862 function GanttScale($aImg) {1863 $this->iImg = $aImg; 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 $this->year->SetFont(FF_FONT1,FS_BOLD); 1892 1893 1894 $this->dividerh=new LineProperty(); 1895 1896 1897 1898 1899 1900 1901 1902 1903 } 1904 1905 //---------------1906 // PUBLIC METHODS 1962 private $iWeekStart = 1; // Default to have weekends start on Monday 1963 1964 //--------------- 1965 // CONSTRUCTOR 1966 function __construct($aImg) { 1967 $this->iImg = $aImg; 1968 $this->iDateLocale = new DateLocale(); 1969 1970 $this->minute = new HeaderProperty(); 1971 $this->minute->SetIntervall(15); 1972 $this->minute->SetLabelFormatString('i'); 1973 $this->minute->SetFont(FF_FONT0); 1974 $this->minute->grid->SetColor("gray"); 1975 1976 $this->hour = new HeaderProperty(); 1977 $this->hour->SetFont(FF_FONT0); 1978 $this->hour->SetIntervall(6); 1979 $this->hour->SetStyle(HOURSTYLE_HM24); 1980 $this->hour->SetLabelFormatString('H:i'); 1981 $this->hour->grid->SetColor("gray"); 1982 1983 $this->day = new HeaderProperty(); 1984 $this->day->grid->SetColor("gray"); 1985 $this->day->SetLabelFormatString('l'); 1986 1987 $this->week = new HeaderProperty(); 1988 $this->week->SetLabelFormatString("w%d"); 1989 $this->week->SetFont(FF_FONT1); 1990 1991 $this->month = new HeaderProperty(); 1992 $this->month->SetFont(FF_FONT1,FS_BOLD); 1993 1994 $this->year = new HeaderProperty(); 1995 $this->year->SetFont(FF_FONT1,FS_BOLD); 1996 1997 $this->divider=new LineProperty(); 1998 $this->dividerh=new LineProperty(); 1999 $this->dividerh->SetWeight(2); 2000 $this->divider->SetWeight(6); 2001 $this->divider->SetColor('gray'); 2002 $this->divider->SetStyle('fancy'); 2003 2004 $this->tableTitle=new TextProperty(); 2005 $this->tableTitle->Show(false); 2006 $this->actinfo = new GanttActivityInfo(); 2007 } 2008 2009 //--------------- 2010 // PUBLIC METHODS 1907 2011 // Specify what headers should be visible 1908 2012 function ShowHeaders($aFlg) { 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 } 1925 2013 $this->day->Show($aFlg & GANTT_HDAY); 2014 $this->week->Show($aFlg & GANTT_HWEEK); 2015 $this->month->Show($aFlg & GANTT_HMONTH); 2016 $this->year->Show($aFlg & GANTT_HYEAR); 2017 $this->hour->Show($aFlg & GANTT_HHOUR); 2018 $this->minute->Show($aFlg & GANTT_HMIN); 2019 2020 // Make some default settings of gridlines whihc makes sense 2021 if( $aFlg & GANTT_HWEEK ) { 2022 $this->month->grid->Show(false); 2023 $this->year->grid->Show(false); 2024 } 2025 if( $aFlg & GANTT_HHOUR ) { 2026 $this->day->grid->SetColor("black"); 2027 } 2028 } 2029 1926 2030 // Should the weekend background stretch all the way down in the plotarea 1927 2031 function UseWeekendBackground($aShow) { 1928 1929 } 1930 2032 $this->iUsePlotWeekendBackground = $aShow; 2033 } 2034 1931 2035 // Have a range been specified? 1932 2036 function IsRangeSet() { 1933 1934 } 1935 2037 return $this->iStartDate!=-1 && $this->iEndDate!=-1; 2038 } 2039 1936 2040 // Should the layout be from top or even? 1937 2041 function SetVertLayout($aLayout) { 1938 1939 } 1940 2042 $this->iVertLayout = $aLayout; 2043 } 2044 1941 2045 // Which locale should be used? 1942 2046 function SetDateLocale($aLocale) { 1943 1944 } 1945 2047 $this->iDateLocale->Set($aLocale); 2048 } 2049 1946 2050 // Number of days we are showing 1947 2051 function GetNumberOfDays() { 1948 1949 } 1950 2052 return round(($this->iEndDate-$this->iStartDate)/SECPERDAY); 2053 } 2054 1951 2055 // The width of the actual plot area 1952 2056 function GetPlotWidth() { 1953 1954 2057 $img=$this->iImg; 2058 return $img->width - $img->left_margin - $img->right_margin; 1955 2059 } 1956 2060 … … 1959 2063 // widest title) 1960 2064 function SetLabelWidth($aLabelWidth) { 1961 1962 } 1963 1964 1965 2065 $this->iLabelWidth=$aLabelWidth; 2066 } 2067 2068 // Which day should the week start? 2069 // 0==Sun, 1==Monday, 2==Tuesday etc 1966 2070 function SetWeekStart($aStartDay) { 1967 1968 1969 1970 2071 $this->iWeekStart = $aStartDay % 7; 2072 2073 //Recalculate the startday since this will change the week start 2074 $this->SetRange($this->iStartDate,$this->iEndDate); 1971 2075 } 1972 2076 1973 2077 // Do we show min scale? 1974 2078 function IsDisplayMinute() { 1975 2079 return $this->minute->iShowLabels; 1976 2080 } 1977 2081 1978 2082 // Do we show day scale? 1979 2083 function IsDisplayHour() { 1980 1981 } 1982 1983 2084 return $this->hour->iShowLabels; 2085 } 2086 2087 1984 2088 // Do we show day scale? 1985 2089 function IsDisplayDay() { 1986 1987 } 1988 2090 return $this->day->iShowLabels; 2091 } 2092 1989 2093 // Do we show week scale? 1990 2094 function IsDisplayWeek() { 1991 1992 } 1993 2095 return $this->week->iShowLabels; 2096 } 2097 1994 2098 // Do we show month scale? 1995 2099 function IsDisplayMonth() { 1996 1997 } 1998 2100 return $this->month->iShowLabels; 2101 } 2102 1999 2103 // Do we show year scale? 2000 2104 function IsDisplayYear() { 2001 2105 return $this->year->iShowLabels; 2002 2106 } 2003 2107 2004 2108 // Specify spacing (in percent of bar height) between activity bars 2005 2109 function SetVertSpacing($aSpacing) { 2006 2110 $this->iVertSpacing = $aSpacing; 2007 2111 } 2008 2112 … … 2010 2114 // Always round to the nearest week boundary 2011 2115 function SetRange($aMin,$aMax) { 2012 2013 $this->iEndDate = $this->NormalizeDate($aMax); 2116 $this->iStartDate = $this->NormalizeDate($aMin); 2117 $this->iEndDate = $this->NormalizeDate($aMax); 2014 2118 } 2015 2119 … … 2019 2123 function AdjustStartEndDay() { 2020 2124 2021 2022 2023 2024 2025 2026 2027 2028 $de=strftime("%w",$this->iEndDate); 2029 2030 2031 // if the startdate is "behind" the day the week start at. 2032 // This way we ensure that the given start date is always included 2033 // in the range. If we don't do this the nearest correct weekday in the week 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 if( $preferredEndDay != $de ) { 2045 2046 2047 2048 $this->iEndDate = $adjdate; 2049 } 2050 } 2051 2052 // Specify background for the table title area (upper left corner of the table) 2125 if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) { 2126 // Don't adjust 2127 return; 2128 } 2129 2130 // Get day in week for start and ending date (Sun==0) 2131 $ds=strftime("%w",$this->iStartDate); 2132 $de=strftime("%w",$this->iEndDate); 2133 2134 // We want to start on iWeekStart day. But first we subtract a week 2135 // if the startdate is "behind" the day the week start at. 2136 // This way we ensure that the given start date is always included 2137 // in the range. If we don't do this the nearest correct weekday in the week 2138 // to start at might be later than the start date. 2139 if( $ds < $this->iWeekStart ) 2140 $d = strtotime('-7 day',$this->iStartDate); 2141 else 2142 $d = $this->iStartDate; 2143 $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ ); 2144 $this->iStartDate = $adjdate; 2145 2146 // We want to end on the last day of the week 2147 $preferredEndDay = ($this->iWeekStart+6)%7; 2148 if( $preferredEndDay != $de ) { 2149 // Solve equivalence eq: $de + x ~ $preferredDay (mod 7) 2150 $adj = (7+($preferredEndDay - $de)) % 7; 2151 $adjdate = strtotime("+$adj day",$this->iEndDate); 2152 $this->iEndDate = $adjdate; 2153 } 2154 } 2155 2156 // Specify background for the table title area (upper left corner of the table) 2053 2157 function SetTableTitleBackground($aColor) { 2054 2055 } 2056 2057 ///////////////////////////////////////2058 // PRIVATE Methods2059 2158 $this->iTableHeaderBackgroundColor = $aColor; 2159 } 2160 2161 /////////////////////////////////////// 2162 // PRIVATE Methods 2163 2060 2164 // Determine the height of all the scale headers combined 2061 2165 function GetHeaderHeight() { 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 } 2090 2166 $img=$this->iImg; 2167 $height=1; 2168 if( $this->minute->iShowLabels ) { 2169 $height += $this->minute->GetFontHeight($img); 2170 $height += $this->minute->iTitleVertMargin; 2171 } 2172 if( $this->hour->iShowLabels ) { 2173 $height += $this->hour->GetFontHeight($img); 2174 $height += $this->hour->iTitleVertMargin; 2175 } 2176 if( $this->day->iShowLabels ) { 2177 $height += $this->day->GetFontHeight($img); 2178 $height += $this->day->iTitleVertMargin; 2179 } 2180 if( $this->week->iShowLabels ) { 2181 $height += $this->week->GetFontHeight($img); 2182 $height += $this->week->iTitleVertMargin; 2183 } 2184 if( $this->month->iShowLabels ) { 2185 $height += $this->month->GetFontHeight($img); 2186 $height += $this->month->iTitleVertMargin; 2187 } 2188 if( $this->year->iShowLabels ) { 2189 $height += $this->year->GetFontHeight($img); 2190 $height += $this->year->iTitleVertMargin; 2191 } 2192 return $height; 2193 } 2194 2091 2195 // Get width (in pixels) for a single day 2092 2196 function GetDayWidth() { 2093 return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays(); 2197 return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays(); 2094 2198 } 2095 2199 2096 2200 // Get width (in pixels) for a single hour 2097 2201 function GetHourWidth() { 2098 2202 return $this->GetDayWidth() / 24 ; 2099 2203 } 2100 2204 2101 2205 function GetMinuteWidth() { 2102 2206 return $this->GetHourWidth() / 60 ; 2103 2207 } 2104 2208 2105 2209 // Nuber of days in a year 2106 2210 function GetNumDaysInYear($aYear) { 2107 2108 2109 2110 2111 } 2112 2113 // Get week number 2211 if( $this->IsLeap($aYear) ) 2212 return 366; 2213 else 2214 return 365; 2215 } 2216 2217 // Get week number 2114 2218 function GetWeekNbr($aDate,$aSunStart=true) { 2115 2116 2117 2118 2119 2120 2121 2122 2123 // version of Week Nbr calculation. 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 } 2149 2219 // We can't use the internal strftime() since it gets the weeknumber 2220 // wrong since it doesn't follow ISO on all systems since this is 2221 // system linrary dependent. 2222 // Even worse is that this works differently if we are on a Windows 2223 // or UNIX box (it even differs between UNIX boxes how strftime() 2224 // is natively implemented) 2225 // 2226 // Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant 2227 // version of Week Nbr calculation. 2228 2229 $day = $this->NormalizeDate($aDate); 2230 if( $aSunStart ) 2231 $day += 60*60*24; 2232 2233 /*------------------------------------------------------------------------- 2234 According to ISO-8601 : 2235 "Week 01 of a year is per definition the first week that has the Thursday in this year, 2236 which is equivalent to the week that contains the fourth day of January. 2237 In other words, the first week of a new year is the week that has the majority of its 2238 days in the new year." 2239 2240 Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!! 2241 2242 day of year = date("z", $day) + 1 2243 offset to thursday = 3 - (date("w", $day) + 6) % 7 2244 first thursday of year = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7 2245 week number = (thursday's day of year - first thursday's day of year) / 7 + 1 2246 ---------------------------------------------------------------------------*/ 2247 2248 $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7); // take week's thursday 2249 $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7; 2250 2251 return $week; 2252 } 2253 2150 2254 // Is year a leap year? 2151 2255 function IsLeap($aYear) { 2152 2153 2154 2155 2156 2157 2256 // Is the year a leap year? 2257 //$year = 0+date("Y",$aDate); 2258 if( $aYear % 4 == 0) 2259 if( !($aYear % 100 == 0) || ($aYear % 400 == 0) ) 2260 return true; 2261 return false; 2158 2262 } 2159 2263 2160 2264 // Get current year 2161 2265 function GetYear($aDate) { 2162 2163 } 2164 2266 return 0+Date("Y",$aDate); 2267 } 2268 2165 2269 // Return number of days in a year 2166 2270 function GetNumDaysInMonth($aMonth,$aYear) { 2167 2168 2169 2170 2171 2172 2173 } 2174 2271 $days=array(31,28,31,30,31,30,31,31,30,31,30,31); 2272 $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31); 2273 if( $this->IsLeap($aYear)) 2274 return $daysl[$aMonth]; 2275 else 2276 return $days[$aMonth]; 2277 } 2278 2175 2279 // Get day in month 2176 2280 function GetMonthDayNbr($aDate) { 2177 2281 return 0+strftime("%d",$aDate); 2178 2282 } 2179 2283 2180 2284 // Get day in year 2181 2285 function GetYearDayNbr($aDate) { 2182 2183 } 2184 2286 return 0+strftime("%j",$aDate); 2287 } 2288 2185 2289 // Get month number 2186 2290 function GetMonthNbr($aDate) { 2187 2188 } 2189 2190 // Translate a date to screen coordinates 2291 return 0+strftime("%m",$aDate); 2292 } 2293 2294 // Translate a date to screen coordinates (horizontal scale) 2191 2295 function TranslateDate($aDate) { 2192 // 2193 // In order to handle the problem with Daylight savings time 2194 // the scale written with equal number of seconds per day beginning 2195 // with the start date. This means that we "cement" the state of 2196 // DST as it is in the start date. If later the scale includes the 2197 // switchover date (depends on the locale) we need to adjust back 2198 // if the date we try to translate has a different DST status since 2199 // we would otherwise be off by one hour. 2200 $aDate = $this->NormalizeDate($aDate); 2201 $tmp = localtime($aDate); 2202 $cloc = $tmp[8]; 2203 $tmp = localtime($this->iStartDate); 2204 $sloc = $tmp[8]; 2205 $offset = 0; 2206 if( $sloc != $cloc) { 2207 if( $sloc ) 2208 $offset = 3600; 2209 else 2210 $offset = -3600; 2211 } 2212 $img=$this->iImg; 2213 return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;; 2214 } 2215 2216 // Get screen coordinatesz for the vertical position for a bar 2217 function TranslateVertPos($aPos) { 2218 $img=$this->iImg; 2219 $ph=$this->iAvailableHeight; 2220 if( $aPos > $this->iVertLines ) 2221 JpGraphError::RaiseL(6015,$aPos); 2222 // 'Illegal vertical position %d' 2223 if( $this->iVertLayout == GANTT_EVEN ) { 2224 // Position the top bar at 1 vert spacing from the scale 2225 return round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing); 2226 } 2227 else { 2228 // position the top bar at 1/2 a vert spacing from the scale 2229 return round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing); 2230 } 2231 } 2232 2296 // 2297 // In order to handle the problem with Daylight savings time 2298 // the scale written with equal number of seconds per day beginning 2299 // with the start date. This means that we "cement" the state of 2300 // DST as it is in the start date. If later the scale includes the 2301 // switchover date (depends on the locale) we need to adjust back 2302 // if the date we try to translate has a different DST status since 2303 // we would otherwise be off by one hour. 2304 $aDate = $this->NormalizeDate($aDate); 2305 $tmp = localtime($aDate); 2306 $cloc = $tmp[8]; 2307 $tmp = localtime($this->iStartDate); 2308 $sloc = $tmp[8]; 2309 $offset = 0; 2310 if( $sloc != $cloc) { 2311 if( $sloc ) 2312 $offset = 3600; 2313 else 2314 $offset = -3600; 2315 } 2316 $img=$this->iImg; 2317 return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;; 2318 } 2319 2320 // Get screen coordinatesz for the vertical position for a bar 2321 function TranslateVertPos($aPos,$atTop=false) { 2322 $img=$this->iImg; 2323 if( $aPos > $this->iVertLines ) 2324 JpGraphError::RaiseL(6015,$aPos); 2325 // 'Illegal vertical position %d' 2326 if( $this->iVertLayout == GANTT_EVEN ) { 2327 // Position the top bar at 1 vert spacing from the scale 2328 $pos = round($img->top_margin + $this->iVertHeaderSize + ($aPos+1)*$this->iVertSpacing); 2329 } 2330 else { 2331 // position the top bar at 1/2 a vert spacing from the scale 2332 $pos = round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing); 2333 } 2334 2335 if( $atTop ) 2336 $pos -= $this->iVertSpacing; 2337 2338 return $pos; 2339 } 2340 2233 2341 // What is the vertical spacing? 2234 2342 function GetVertSpacing() { 2235 2236 } 2237 2343 return $this->iVertSpacing; 2344 } 2345 2238 2346 // Convert a date to timestamp 2239 2347 function NormalizeDate($aDate) { 2240 if( $aDate === false ) return false; 2241 2242 2243 2244 2245 //("Date string ($aDate) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30");2246 2247 2248 2249 2250 2251 2252 2253 //Unknown date format in GanttScale ($aDate).");2254 } 2255 2256 2348 if( $aDate === false ) return false; 2349 if( is_string($aDate) ) { 2350 $t = strtotime($aDate); 2351 if( $t === FALSE || $t === -1 ) { 2352 JpGraphError::RaiseL(6016,$aDate); 2353 //("Date string ($aDate) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30"); 2354 } 2355 return $t; 2356 } 2357 elseif( is_int($aDate) || is_float($aDate) ) 2358 return $aDate; 2359 else 2360 JpGraphError::RaiseL(6017,$aDate); 2361 //Unknown date format in GanttScale ($aDate)."); 2362 } 2363 2364 2257 2365 // Convert a time string to minutes 2258 2366 2259 2367 function TimeToMinutes($aTimeString) { 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 } 2274 2275 // Stroke the day scale (including gridlines) 2368 // Split in hours and minutes 2369 $pos=strpos($aTimeString,':'); 2370 $minint=60; 2371 if( $pos === false ) { 2372 $hourint = $aTimeString; 2373 $minint = 0; 2374 } 2375 else { 2376 $hourint = floor(substr($aTimeString,0,$pos)); 2377 $minint = floor(substr($aTimeString,$pos+1)); 2378 } 2379 $minint += 60 * $hourint; 2380 return $minint; 2381 } 2382 2383 // Stroke the day scale (including gridlines) 2276 2384 function StrokeMinutes($aYCoord,$getHeight=false) { 2277 $img=$this->iImg; 2278 2279 $yt=$aYCoord+$img->top_margin; 2280 2281 2282 $yb = $yt + $img->GetFontHeight() + 2283 2284 2285 2286 2287 2288 2289 2290 2291 $x = $xt; 2292 2293 2294 2295 2296 if( 60 % $minint !== 0 ) { 2385 $img=$this->iImg; 2386 $xt=$img->left_margin+$this->iLabelWidth; 2387 $yt=$aYCoord+$img->top_margin; 2388 if( $this->minute->iShowLabels ) { 2389 $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize); 2390 $yb = $yt + $img->GetFontHeight() + 2391 $this->minute->iTitleVertMargin + $this->minute->iFrameWeight; 2392 if( $getHeight ) { 2393 return $yb - $img->top_margin; 2394 } 2395 $xb = $img->width-$img->right_margin+1; 2396 $img->SetColor($this->minute->iBackgroundColor); 2397 $img->FilledRectangle($xt,$yt,$xb,$yb); 2398 2399 $x = $xt; 2400 $img->SetTextAlign("center"); 2401 $day = date('w',$this->iStartDate); 2402 $minint = $this->minute->GetIntervall() ; 2403 2404 if( 60 % $minint !== 0 ) { 2297 2405 JpGraphError::RaiseL(6018,$minint); 2298 //'Intervall for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an intervall of '.$minint.' minutes.'); 2299 } 2300 2301 2302 $n = 60 / $minint; 2303 $datestamp = $this->iStartDate; 2304 $width = $this->GetHourWidth() / $n ; 2305 if( $width < 8 ) { 2306 // TO small width to draw minute scale 2307 JpGraphError::RaiseL(6019,$width); 2308 //('The available width ('.$width.') for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.'); 2309 } 2310 2311 $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) ); 2312 $nd = $this->GetNumberOfDays(); 2313 // Convert to intervall to seconds 2314 $minint *= 60; 2315 for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) { 2316 for( $k=0; $k < $nh; ++$k ) { 2317 for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) { 2318 if( $day==6 || $day==0 ) { 2319 2320 $img->PushColor($this->day->iWeekendBackgroundColor); 2321 if( $this->iUsePlotWeekendBackground ) 2322 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); 2323 else 2324 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); 2325 $img->PopColor(); 2326 2327 } 2328 2329 if( $day==0 ) 2330 $img->SetColor($this->day->iSundayTextColor); 2331 else 2332 $img->SetColor($this->day->iTextColor); 2333 2334 switch( $this->minute->iStyle ) { 2335 case MINUTESTYLE_CUSTOM: 2336 $txt = date($this->minute->iLabelFormStr,$datestamp); 2337 break; 2338 case MINUTESTYLE_MM: 2339 default: 2340 // 15 2341 $txt = date('i',$datestamp); 2342 break; 2343 } 2344 $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt); 2345 2346 // FIXME: The rounding problem needs to be solved properly ... 2347 // 2348 // Fix a rounding problem the wrong way .. 2349 // If we also have hour scale then don't draw the firsta or last 2350 // gridline since that will be overwritten by the hour scale gridline if such exists. 2351 // However, due to the propagation of rounding of the 'x+=width' term in the loop 2352 // this might sometimes be one pixel of so we fix this by not drawing it. 2353 // The proper way to fix it would be to re-calculate the scale for each step and 2354 // not using the additive term. 2355 if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) { 2356 $img->SetColor($this->minute->grid->iColor); 2357 $img->SetLineWeight($this->minute->grid->iWeight); 2358 $img->Line($x,$yt,$x,$yb); 2359 $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2360 } 2361 } 2362 } 2363 } 2364 $img->SetColor($this->minute->iFrameColor); 2365 $img->SetLineWeight($this->minute->iFrameWeight); 2366 $img->Rectangle($xt,$yt,$xb,$yb); 2367 return $yb - $img->top_margin; 2368 } 2369 return $aYCoord; 2370 } 2371 2372 // Stroke the day scale (including gridlines) 2406 //'Intervall for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an intervall of '.$minint.' minutes.'); 2407 } 2408 2409 2410 $n = 60 / $minint; 2411 $datestamp = $this->iStartDate; 2412 $width = $this->GetHourWidth() / $n ; 2413 if( $width < 8 ) { 2414 // TO small width to draw minute scale 2415 JpGraphError::RaiseL(6019,$width); 2416 //('The available width ('.$width.') for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.'); 2417 } 2418 2419 $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) ); 2420 $nd = $this->GetNumberOfDays(); 2421 // Convert to intervall to seconds 2422 $minint *= 60; 2423 for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) { 2424 for( $k=0; $k < $nh; ++$k ) { 2425 for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) { 2426 if( $day==6 || $day==0 ) { 2427 2428 $img->PushColor($this->day->iWeekendBackgroundColor); 2429 if( $this->iUsePlotWeekendBackground ) 2430 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); 2431 else 2432 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); 2433 $img->PopColor(); 2434 2435 } 2436 2437 if( $day==0 ) 2438 $img->SetColor($this->day->iSundayTextColor); 2439 else 2440 $img->SetColor($this->day->iTextColor); 2441 2442 switch( $this->minute->iStyle ) { 2443 case MINUTESTYLE_CUSTOM: 2444 $txt = date($this->minute->iLabelFormStr,$datestamp); 2445 break; 2446 case MINUTESTYLE_MM: 2447 default: 2448 // 15 2449 $txt = date('i',$datestamp); 2450 break; 2451 } 2452 $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt); 2453 2454 // Fix a rounding problem the wrong way .. 2455 // If we also have hour scale then don't draw the firsta or last 2456 // gridline since that will be overwritten by the hour scale gridline if such exists. 2457 // However, due to the propagation of rounding of the 'x+=width' term in the loop 2458 // this might sometimes be one pixel of so we fix this by not drawing it. 2459 // The proper way to fix it would be to re-calculate the scale for each step and 2460 // not using the additive term. 2461 if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) { 2462 $img->SetColor($this->minute->grid->iColor); 2463 $img->SetLineWeight($this->minute->grid->iWeight); 2464 $img->Line($x,$yt,$x,$yb); 2465 $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2466 } 2467 } 2468 } 2469 } 2470 $img->SetColor($this->minute->iFrameColor); 2471 $img->SetLineWeight($this->minute->iFrameWeight); 2472 $img->Rectangle($xt,$yt,$xb,$yb); 2473 return $yb - $img->top_margin; 2474 } 2475 return $aYCoord; 2476 } 2477 2478 // Stroke the day scale (including gridlines) 2373 2479 function StrokeHours($aYCoord,$getHeight=false) { 2374 $img=$this->iImg; 2375 2376 $yt=$aYCoord+$img->top_margin; 2377 2378 2379 $yb = $yt + $img->GetFontHeight() + 2380 2381 2382 2383 2384 2385 2386 2387 2388 $x = $xt; 2389 2390 2391 2392 if( 1440 % $minint !== 0 ) { 2480 $img=$this->iImg; 2481 $xt=$img->left_margin+$this->iLabelWidth; 2482 $yt=$aYCoord+$img->top_margin; 2483 if( $this->hour->iShowLabels ) { 2484 $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize); 2485 $yb = $yt + $img->GetFontHeight() + 2486 $this->hour->iTitleVertMargin + $this->hour->iFrameWeight; 2487 if( $getHeight ) { 2488 return $yb - $img->top_margin; 2489 } 2490 $xb = $img->width-$img->right_margin+1; 2491 $img->SetColor($this->hour->iBackgroundColor); 2492 $img->FilledRectangle($xt,$yt,$xb,$yb); 2493 2494 $x = $xt; 2495 $img->SetTextAlign("center"); 2496 $tmp = $this->hour->GetIntervall() ; 2497 $minint = $this->TimeToMinutes($tmp); 2498 if( 1440 % $minint !== 0 ) { 2393 2499 JpGraphError::RaiseL(6020,$tmp); 2394 //('Intervall for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an intervall of '.$tmp);2395 } 2396 2397 2398 2399 2400 2401 2402 2403 for($i=0; $i < $n ;++$i, $x+=$width) { 2404 2405 2406 2407 2408 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); 2409 2410 2411 2412 2413 2414 2415 if( $day==0 ) 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 } 2450 2451 2452 2453 2454 2455 2456 2457 } 2458 2459 2460 // Stroke the day scale (including gridlines) 2500 //('Intervall for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an intervall of '.$tmp); 2501 } 2502 2503 $n = ceil(24*60 / $minint ); 2504 $datestamp = $this->iStartDate; 2505 $day = date('w',$this->iStartDate); 2506 $doback = !$this->minute->iShowLabels; 2507 $width = $this->GetDayWidth() / $n ; 2508 for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) { 2509 for($i=0; $i < $n ;++$i, $x+=$width) { 2510 if( $day==6 || $day==0 ) { 2511 2512 $img->PushColor($this->day->iWeekendBackgroundColor); 2513 if( $this->iUsePlotWeekendBackground && $doback ) 2514 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin); 2515 else 2516 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight); 2517 $img->PopColor(); 2518 2519 } 2520 2521 if( $day==0 ) 2522 $img->SetColor($this->day->iSundayTextColor); 2523 else 2524 $img->SetColor($this->day->iTextColor); 2525 2526 switch( $this->hour->iStyle ) { 2527 case HOURSTYLE_HMAMPM: 2528 // 1:35pm 2529 $txt = date('g:ia',$datestamp); 2530 break; 2531 case HOURSTYLE_H24: 2532 // 13 2533 $txt = date('H',$datestamp); 2534 break; 2535 case HOURSTYLE_HAMPM: 2536 $txt = date('ga',$datestamp); 2537 break; 2538 case HOURSTYLE_CUSTOM: 2539 $txt = date($this->hour->iLabelFormStr,$datestamp); 2540 break; 2541 case HOURSTYLE_HM24: 2542 default: 2543 $txt = date('H:i',$datestamp); 2544 break; 2545 } 2546 $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt); 2547 $img->SetColor($this->hour->grid->iColor); 2548 $img->SetLineWeight($this->hour->grid->iWeight); 2549 $img->Line($x,$yt,$x,$yb); 2550 $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2551 //$datestamp += $minint*60 2552 $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0, 2553 date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); 2554 2555 } 2556 } 2557 $img->SetColor($this->hour->iFrameColor); 2558 $img->SetLineWeight($this->hour->iFrameWeight); 2559 $img->Rectangle($xt,$yt,$xb,$yb); 2560 return $yb - $img->top_margin; 2561 } 2562 return $aYCoord; 2563 } 2564 2565 2566 // Stroke the day scale (including gridlines) 2461 2567 function StrokeDays($aYCoord,$getHeight=false) { 2462 $img=$this->iImg; 2463 2464 2465 $yt=$aYCoord+$img->top_margin; 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 $x = $xt; 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 $x+$daywidth,$img->height-$img->bottom_margin); 2491 2492 2493 2494 2495 2496 2497 if( $mn[0]=='0' ) 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 break; 2533 2534 2535 2536 break; 2537 2538 2539 2540 break; 2541 2542 2543 2544 break; 2545 2546 2547 2548 break; 2549 2550 2551 2552 2553 2554 2555 2556 2557 if( $day==0 ) 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 } 2571 2572 2573 2574 2575 2576 2577 } 2578 2568 $img=$this->iImg; 2569 $daywidth=$this->GetDayWidth(); 2570 $xt=$img->left_margin+$this->iLabelWidth; 2571 $yt=$aYCoord+$img->top_margin; 2572 if( $this->day->iShowLabels ) { 2573 $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize); 2574 $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight; 2575 if( $getHeight ) { 2576 return $yb - $img->top_margin; 2577 } 2578 $xb=$img->width-$img->right_margin+1; 2579 $img->SetColor($this->day->iBackgroundColor); 2580 $img->FilledRectangle($xt,$yt,$xb,$yb); 2581 2582 $x = $xt; 2583 $img->SetTextAlign("center"); 2584 $day = date('w',$this->iStartDate); 2585 $datestamp = $this->iStartDate; 2586 2587 $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels); 2588 2589 setlocale(LC_TIME,$this->iDateLocale->iLocale); 2590 2591 for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) { 2592 if( $day==6 || $day==0 ) { 2593 $img->SetColor($this->day->iWeekendBackgroundColor); 2594 if( $this->iUsePlotWeekendBackground && $doback) 2595 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, 2596 $x+$daywidth,$img->height-$img->bottom_margin); 2597 else 2598 $img->FilledRectangle($x,$yt+$this->day->iFrameWeight, 2599 $x+$daywidth,$yb-$this->day->iFrameWeight); 2600 } 2601 2602 $mn = strftime('%m',$datestamp); 2603 if( $mn[0]=='0' ) 2604 $mn = $mn[1]; 2605 2606 switch( $this->day->iStyle ) { 2607 case DAYSTYLE_LONG: 2608 // "Monday" 2609 $txt = strftime('%A',$datestamp); 2610 break; 2611 case DAYSTYLE_SHORT: 2612 // "Mon" 2613 $txt = strftime('%a',$datestamp); 2614 break; 2615 case DAYSTYLE_SHORTDAYDATE1: 2616 // "Mon 23/6" 2617 $txt = strftime('%a %d/'.$mn,$datestamp); 2618 break; 2619 case DAYSTYLE_SHORTDAYDATE2: 2620 // "Mon 23 Jun" 2621 $txt = strftime('%a %d %b',$datestamp); 2622 break; 2623 case DAYSTYLE_SHORTDAYDATE3: 2624 // "Mon 23 Jun 2003" 2625 $txt = strftime('%a %d %b %Y',$datestamp); 2626 break; 2627 case DAYSTYLE_LONGDAYDATE1: 2628 // "Monday 23 Jun" 2629 $txt = strftime('%A %d %b',$datestamp); 2630 break; 2631 case DAYSTYLE_LONGDAYDATE2: 2632 // "Monday 23 Jun 2003" 2633 $txt = strftime('%A %d %b %Y',$datestamp); 2634 break; 2635 case DAYSTYLE_SHORTDATE1: 2636 // "23/6" 2637 $txt = strftime('%d/'.$mn,$datestamp); 2638 break; 2639 case DAYSTYLE_SHORTDATE2: 2640 // "23 Jun" 2641 $txt = strftime('%d %b',$datestamp); 2642 break; 2643 case DAYSTYLE_SHORTDATE3: 2644 // "Mon 23" 2645 $txt = strftime('%a %d',$datestamp); 2646 break; 2647 case DAYSTYLE_SHORTDATE4: 2648 // "23" 2649 $txt = strftime('%d',$datestamp); 2650 break; 2651 case DAYSTYLE_CUSTOM: 2652 // Custom format 2653 $txt = strftime($this->day->iLabelFormStr,$datestamp); 2654 break; 2655 case DAYSTYLE_ONELETTER: 2656 default: 2657 // "M" 2658 $txt = strftime('%A',$datestamp); 2659 $txt = strtoupper($txt[0]); 2660 break; 2661 } 2662 2663 if( $day==0 ) 2664 $img->SetColor($this->day->iSundayTextColor); 2665 else 2666 $img->SetColor($this->day->iTextColor); 2667 $img->StrokeText(round($x+$daywidth/2+1), 2668 round($yb-$this->day->iTitleVertMargin),$txt); 2669 $img->SetColor($this->day->grid->iColor); 2670 $img->SetLineWeight($this->day->grid->iWeight); 2671 $img->Line($x,$yt,$x,$yb); 2672 $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2673 $datestamp = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp)); 2674 //$datestamp += SECPERDAY; 2675 2676 } 2677 $img->SetColor($this->day->iFrameColor); 2678 $img->SetLineWeight($this->day->iFrameWeight); 2679 $img->Rectangle($xt,$yt,$xb,$yb); 2680 return $yb - $img->top_margin; 2681 } 2682 return $aYCoord; 2683 } 2684 2579 2685 // Stroke week header and grid 2580 2686 function StrokeWeeks($aYCoord,$getHeight=false) { 2581 if( $this->week->iShowLabels ) { 2582 $img=$this->iImg; 2583 $yt=$aYCoord+$img->top_margin; 2584 $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize); 2585 $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; 2586 2587 if( $getHeight ) { 2588 return $yb - $img->top_margin; 2589 } 2590 2591 $xt=$img->left_margin+$this->iLabelWidth; 2592 $weekwidth=$this->GetDayWidth()*7; 2593 $wdays=$this->iDateLocale->GetDayAbb(); 2594 $xb=$img->width-$img->right_margin+1; 2595 $week = $this->iStartDate; 2596 $weeknbr=$this->GetWeekNbr($week); 2597 $img->SetColor($this->week->iBackgroundColor); 2598 $img->FilledRectangle($xt,$yt,$xb,$yb); 2599 $img->SetColor($this->week->grid->iColor); 2600 $x = $xt; 2601 if( $this->week->iStyle==WEEKSTYLE_WNBR ) { 2602 $img->SetTextAlign("center"); 2603 $txtOffset = $weekwidth/2+1; 2604 } 2605 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || 2606 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || 2607 $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 2608 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2609 $img->SetTextAlign("left"); 2610 $txtOffset = 3; 2611 } 2612 else 2613 JpGraphError::RaiseL(6021); 2614 //("Unknown formatting style for week."); 2615 2616 for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) { 2617 $img->PushColor($this->week->iTextColor); 2618 2619 if( $this->week->iStyle==WEEKSTYLE_WNBR ) 2620 $txt = sprintf($this->week->iLabelFormStr,$weeknbr); 2621 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || 2622 $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) 2623 $txt = date("j/n",$week); 2624 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || 2625 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2626 $monthnbr = date("n",$week)-1; 2627 $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); 2628 $txt = Date("j",$week)." ".$shortmonth; 2629 } 2630 2631 if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 2632 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2633 $w = sprintf($this->week->iLabelFormStr,$weeknbr); 2634 $txt .= ' '.$w; 2635 } 2636 2637 $img->StrokeText(round($x+$txtOffset), 2638 round($yb-$this->week->iTitleVertMargin),$txt); 2639 2640 $week = strtotime('+7 day',$week); 2641 $weeknbr = $this->GetWeekNbr($week); 2642 $img->PopColor(); 2643 $img->SetLineWeight($this->week->grid->iWeight); 2644 $img->Line($x,$yt,$x,$yb); 2645 $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2646 } 2647 $img->SetColor($this->week->iFrameColor); 2648 $img->SetLineWeight($this->week->iFrameWeight); 2649 $img->Rectangle($xt,$yt,$xb,$yb); 2650 return $yb-$img->top_margin; 2651 } 2652 return $aYCoord; 2653 } 2654 2687 if( $this->week->iShowLabels ) { 2688 $img=$this->iImg; 2689 $yt=$aYCoord+$img->top_margin; 2690 $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize); 2691 $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; 2692 2693 if( $getHeight ) { 2694 return $yb - $img->top_margin; 2695 } 2696 2697 $xt=$img->left_margin+$this->iLabelWidth; 2698 $weekwidth=$this->GetDayWidth()*7; 2699 $wdays=$this->iDateLocale->GetDayAbb(); 2700 $xb=$img->width-$img->right_margin+1; 2701 $week = $this->iStartDate; 2702 $weeknbr=$this->GetWeekNbr($week); 2703 $img->SetColor($this->week->iBackgroundColor); 2704 $img->FilledRectangle($xt,$yt,$xb,$yb); 2705 $img->SetColor($this->week->grid->iColor); 2706 $x = $xt; 2707 if( $this->week->iStyle==WEEKSTYLE_WNBR ) { 2708 $img->SetTextAlign("center"); 2709 $txtOffset = $weekwidth/2+1; 2710 } 2711 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || 2712 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || 2713 $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 2714 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2715 $img->SetTextAlign("left"); 2716 $txtOffset = 3; 2717 } 2718 else { 2719 JpGraphError::RaiseL(6021); 2720 //("Unknown formatting style for week."); 2721 } 2722 2723 for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) { 2724 $img->PushColor($this->week->iTextColor); 2725 2726 if( $this->week->iStyle==WEEKSTYLE_WNBR ) 2727 $txt = sprintf($this->week->iLabelFormStr,$weeknbr); 2728 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || 2729 $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) 2730 $txt = date("j/n",$week); 2731 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 || 2732 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2733 $monthnbr = date("n",$week)-1; 2734 $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); 2735 $txt = Date("j",$week)." ".$shortmonth; 2736 } 2737 2738 if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR || 2739 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) { 2740 $w = sprintf($this->week->iLabelFormStr,$weeknbr); 2741 $txt .= ' '.$w; 2742 } 2743 2744 $img->StrokeText(round($x+$txtOffset), 2745 round($yb-$this->week->iTitleVertMargin),$txt); 2746 2747 $week = strtotime('+7 day',$week); 2748 $weeknbr = $this->GetWeekNbr($week); 2749 $img->PopColor(); 2750 $img->SetLineWeight($this->week->grid->iWeight); 2751 $img->Line($x,$yt,$x,$yb); 2752 $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2753 } 2754 $img->SetColor($this->week->iFrameColor); 2755 $img->SetLineWeight($this->week->iFrameWeight); 2756 $img->Rectangle($xt,$yt,$xb,$yb); 2757 return $yb-$img->top_margin; 2758 } 2759 return $aYCoord; 2760 } 2761 2655 2762 // Format the mont scale header string 2656 2763 function GetMonthLabel($aMonthNbr,$year) { 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 } 2684 2764 $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr); 2765 $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr); 2766 switch($this->month->iStyle) { 2767 case MONTHSTYLE_SHORTNAME: 2768 $m=$sn; 2769 break; 2770 case MONTHSTYLE_LONGNAME: 2771 $m=$ln; 2772 break; 2773 case MONTHSTYLE_SHORTNAMEYEAR2: 2774 $m=$sn." '".substr("".$year,2); 2775 break; 2776 case MONTHSTYLE_SHORTNAMEYEAR4: 2777 $m=$sn." ".$year; 2778 break; 2779 case MONTHSTYLE_LONGNAMEYEAR2: 2780 $m=$ln." '".substr("".$year,2); 2781 break; 2782 case MONTHSTYLE_LONGNAMEYEAR4: 2783 $m=$ln." ".$year; 2784 break; 2785 case MONTHSTYLE_FIRSTLETTER: 2786 $m=$sn[0]; 2787 break; 2788 } 2789 return $m; 2790 } 2791 2685 2792 // Stroke month scale and gridlines 2686 2793 function StrokeMonths($aYCoord,$getHeight=false) { 2687 2688 $img=$this->iImg; 2689 2690 $yt=$aYCoord+$img->top_margin; 2691 2692 2693 return $yb - $img->top_margin; 2694 2695 $monthnbr = $this->GetMonthNbr($this->iStartDate)-1; 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) 2707 2708 2709 } 2710 2711 2712 2713 2714 2715 2716 $img->SetColor($this->month->iTextColor); 2717 2718 2719 2720 2721 2722 2723 $img->SetColor($this->month->grid->iColor); 2724 2725 2726 2727 2728 2729 2730 2731 2732 $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year); 2733 2734 2735 2736 2737 2738 $img->SetColor($this->month->iTextColor); 2739 2740 2741 2742 2743 } 2744 2745 2746 $img->Rectangle($xt,$yt,$xb,$yb); 2747 2748 2749 2794 if( $this->month->iShowLabels ) { 2795 $img=$this->iImg; 2796 $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize); 2797 $yt=$aYCoord+$img->top_margin; 2798 $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight; 2799 if( $getHeight ) { 2800 return $yb - $img->top_margin; 2801 } 2802 $monthnbr = $this->GetMonthNbr($this->iStartDate)-1; 2803 $xt=$img->left_margin+$this->iLabelWidth; 2804 $xb=$img->width-$img->right_margin+1; 2805 2806 $img->SetColor($this->month->iBackgroundColor); 2807 $img->FilledRectangle($xt,$yt,$xb,$yb); 2808 2809 $img->SetLineWeight($this->month->grid->iWeight); 2810 $img->SetColor($this->month->iTextColor); 2811 $year = 0+strftime("%Y",$this->iStartDate); 2812 $img->SetTextAlign("center"); 2813 if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) 2814 && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) { 2815 $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1); 2816 } 2817 else { 2818 $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1); 2819 } 2820 // Is it enough space to stroke the first month? 2821 $monthName = $this->GetMonthLabel($monthnbr,$year); 2822 if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) { 2823 $img->SetColor($this->month->iTextColor); 2824 $img->StrokeText(round($xt+$monthwidth/2+1), 2825 round($yb-$this->month->iTitleVertMargin), 2826 $monthName); 2827 } 2828 $x = $xt + $monthwidth; 2829 while( $x < $xb ) { 2830 $img->SetColor($this->month->grid->iColor); 2831 $img->Line($x,$yt,$x,$yb); 2832 $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2833 $monthnbr++; 2834 if( $monthnbr==12 ) { 2835 $monthnbr=0; 2836 $year++; 2837 } 2838 $monthName = $this->GetMonthLabel($monthnbr,$year); 2839 $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year); 2840 if( $x + $monthwidth < $xb ) 2841 $w = $monthwidth; 2842 else 2843 $w = $xb-$x; 2844 if( $w >= 1.2*$img->GetTextWidth($monthName) ) { 2845 $img->SetColor($this->month->iTextColor); 2846 $img->StrokeText(round($x+$w/2+1), 2847 round($yb-$this->month->iTitleVertMargin),$monthName); 2848 } 2849 $x += $monthwidth; 2850 } 2851 $img->SetColor($this->month->iFrameColor); 2852 $img->SetLineWeight($this->month->iFrameWeight); 2853 $img->Rectangle($xt,$yt,$xb,$yb); 2854 return $yb-$img->top_margin; 2855 } 2856 return $aYCoord; 2750 2857 } 2751 2858 2752 2859 // Stroke year scale and gridlines 2753 2860 function StrokeYears($aYCoord,$getHeight=false) { 2754 2755 $img=$this->iImg; 2756 $yt=$aYCoord+$img->top_margin; 2757 2758 2759 2760 2761 return $yb - $img->top_margin; 2762 2763 2764 2765 2766 $year = $this->GetYear($this->iStartDate); 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 // The space for a year must be at least 20% bigger than the actual text 2777 2778 2779 $img->SetColor($this->year->iTextColor); 2780 2781 2782 2783 2784 2785 2786 $img->SetColor($this->year->grid->iColor); 2787 2788 2789 2790 $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year); 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 $img->Rectangle($xt,$yt,$xb,$yb); 2806 2807 2808 2809 } 2810 2861 if( $this->year->iShowLabels ) { 2862 $img=$this->iImg; 2863 $yt=$aYCoord+$img->top_margin; 2864 $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize); 2865 $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight; 2866 2867 if( $getHeight ) { 2868 return $yb - $img->top_margin; 2869 } 2870 2871 $xb=$img->width-$img->right_margin+1; 2872 $xt=$img->left_margin+$this->iLabelWidth; 2873 $year = $this->GetYear($this->iStartDate); 2874 $img->SetColor($this->year->iBackgroundColor); 2875 $img->FilledRectangle($xt,$yt,$xb,$yb); 2876 $img->SetLineWeight($this->year->grid->iWeight); 2877 $img->SetTextAlign("center"); 2878 if( $year == $this->GetYear($this->iEndDate) ) 2879 $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1); 2880 else 2881 $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1); 2882 2883 // The space for a year must be at least 20% bigger than the actual text 2884 // so we allow 10% margin on each side 2885 if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) { 2886 $img->SetColor($this->year->iTextColor); 2887 $img->StrokeText(round($xt+$yearwidth/2+1), 2888 round($yb-$this->year->iTitleVertMargin), 2889 $year); 2890 } 2891 $x = $xt + $yearwidth; 2892 while( $x < $xb ) { 2893 $img->SetColor($this->year->grid->iColor); 2894 $img->Line($x,$yt,$x,$yb); 2895 $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin); 2896 $year += 1; 2897 $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year); 2898 if( $x + $yearwidth < $xb ) 2899 $w = $yearwidth; 2900 else 2901 $w = $xb-$x; 2902 if( $w >= 1.2*$img->GetTextWidth("".$year) ) { 2903 $img->SetColor($this->year->iTextColor); 2904 $img->StrokeText(round($x+$w/2+1), 2905 round($yb-$this->year->iTitleVertMargin), 2906 $year); 2907 } 2908 $x += $yearwidth; 2909 } 2910 $img->SetColor($this->year->iFrameColor); 2911 $img->SetLineWeight($this->year->iFrameWeight); 2912 $img->Rectangle($xt,$yt,$xb,$yb); 2913 return $yb-$img->top_margin; 2914 } 2915 return $aYCoord; 2916 } 2917 2811 2918 // Stroke table title (upper left corner) 2812 2919 function StrokeTableHeaders($aYBottom) { 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2); 2824 2825 2826 2827 2828 2829 2830 2831 2832 // Draw the horizontal dividing line 2833 $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb); 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 $tmp = $this->divider->iWeight; 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2920 $img=$this->iImg; 2921 $xt=$img->left_margin; 2922 $yt=$img->top_margin; 2923 $xb=$xt+$this->iLabelWidth; 2924 $yb=$aYBottom+$img->top_margin; 2925 2926 if( $this->tableTitle->iShow ) { 2927 $img->SetColor($this->iTableHeaderBackgroundColor); 2928 $img->FilledRectangle($xt,$yt,$xb,$yb); 2929 $this->tableTitle->Align("center","top"); 2930 $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2); 2931 $img->SetColor($this->iTableHeaderFrameColor); 2932 $img->SetLineWeight($this->iTableHeaderFrameWeight); 2933 $img->Rectangle($xt,$yt,$xb,$yb); 2934 } 2935 2936 $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow); 2937 2938 2939 // Draw the horizontal dividing line 2940 $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb); 2941 2942 // Draw the vertical dividing line 2943 // We do the width "manually" since we want the line only to grow 2944 // to the left 2945 $fancy = $this->divider->iStyle == 'fancy' ; 2946 if( $fancy ) { 2947 $this->divider->iStyle = 'solid'; 2948 } 2949 2950 $tmp = $this->divider->iWeight; 2951 $this->divider->iWeight=1; 2952 $y = $img->height-$img->bottom_margin; 2953 for($i=0; $i < $tmp; ++$i ) { 2954 $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y); 2955 } 2956 2957 // Should we draw "fancy" divider 2958 if( $fancy ) { 2959 $img->SetLineWeight(1); 2960 $img->SetColor($this->iTableHeaderFrameColor); 2961 $img->Line($xb,$yt,$xb,$y); 2962 $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y); 2963 $img->SetColor('white'); 2964 $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y); 2965 } 2859 2966 } 2860 2967 2861 2968 // Main entry point to stroke scale 2862 2969 function Stroke() { 2863 if( !$this->IsRangeSet() ) 2864 JpGraphError::RaiseL(6022); 2865 //("Gantt scale has not been specified."); 2866 $img=$this->iImg; 2867 2868 // If minutes are displayed then hour interval must be 1 2869 if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) { 2870 JpGraphError::RaiseL(6023); 2871 //('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); 2872 } 2873 2874 // Stroke all headers. As argument we supply the offset from the 2875 // top which depends on any previous headers 2876 2877 // First find out the height of each header 2878 $offy=$this->StrokeYears(0,true); 2879 $offm=$this->StrokeMonths($offy,true); 2880 $offw=$this->StrokeWeeks($offm,true); 2881 $offd=$this->StrokeDays($offw,true); 2882 $offh=$this->StrokeHours($offd,true); 2883 $offmin=$this->StrokeMinutes($offh,true); 2884 2885 2886 // ... then we can stroke them in the "backwards order to ensure that 2887 // the larger scale gridlines is stroked over the smaller scale gridline 2888 $this->StrokeMinutes($offh); 2889 $this->StrokeHours($offd); 2890 $this->StrokeDays($offw); 2891 $this->StrokeWeeks($offm); 2892 $this->StrokeMonths($offy); 2893 $this->StrokeYears(0); 2894 2895 // Now when we now the oaverall size of the scale headers 2896 // we can stroke the overall table headers 2897 $this->StrokeTableHeaders($offmin); 2898 2899 // Now we can calculate the correct scaling factor for each vertical position 2900 $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; 2901 $this->iVertHeaderSize = $offmin; 2902 if( $this->iVertSpacing == -1 ) 2903 $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; 2904 } 2970 if( !$this->IsRangeSet() ) { 2971 JpGraphError::RaiseL(6022); 2972 //("Gantt scale has not been specified."); 2973 } 2974 $img=$this->iImg; 2975 2976 // If minutes are displayed then hour interval must be 1 2977 if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) { 2978 JpGraphError::RaiseL(6023); 2979 //('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); 2980 } 2981 2982 // Stroke all headers. As argument we supply the offset from the 2983 // top which depends on any previous headers 2984 2985 // First find out the height of each header 2986 $offy=$this->StrokeYears(0,true); 2987 $offm=$this->StrokeMonths($offy,true); 2988 $offw=$this->StrokeWeeks($offm,true); 2989 $offd=$this->StrokeDays($offw,true); 2990 $offh=$this->StrokeHours($offd,true); 2991 $offmin=$this->StrokeMinutes($offh,true); 2992 2993 2994 // ... then we can stroke them in the "backwards order to ensure that 2995 // the larger scale gridlines is stroked over the smaller scale gridline 2996 $this->StrokeMinutes($offh); 2997 $this->StrokeHours($offd); 2998 $this->StrokeDays($offw); 2999 $this->StrokeWeeks($offm); 3000 $this->StrokeMonths($offy); 3001 $this->StrokeYears(0); 3002 3003 // Now when we now the oaverall size of the scale headers 3004 // we can stroke the overall table headers 3005 $this->StrokeTableHeaders($offmin); 3006 3007 // Now we can calculate the correct scaling factor for each vertical position 3008 $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; 3009 3010 $this->iVertHeaderSize = $offmin; 3011 if( $this->iVertSpacing == -1 ) 3012 $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; 3013 } 2905 3014 } 2906 3015 … … 2917 3026 public $iConstrainArrowType; 2918 3027 2919 //---------------2920 // CONSTRUCTOR2921 function GanttConstraint($aRow,$aType,$aColor,$aArrowSize,$aArrowType){2922 2923 2924 2925 2926 3028 //--------------- 3029 // CONSTRUCTOR 3030 function __construct($aRow,$aType,$aColor,$aArrowSize,$aArrowType){ 3031 $this->iConstrainType = $aType; 3032 $this->iConstrainRow = $aRow; 3033 $this->iConstrainColor=$aColor; 3034 $this->iConstrainArrowSize=$aArrowSize; 3035 $this->iConstrainArrowType=$aArrowType; 2927 3036 } 2928 3037 } … … 2936 3045 public $title,$caption; 2937 3046 public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt=''; 2938 public $constraints = array(); 3047 public $constraints = array(); 2939 3048 public $iCaptionMargin=5; 2940 3049 public $iConstrainPos=array(); 2941 protected $iStart=""; 2942 public $iVPos=0; 2943 protected $iLabelLeftMargin=2; 2944 2945 function GanttPlotObject() {2946 2947 $this->title->Align("left","center");2948 3050 protected $iStart=""; // Start date 3051 public $iVPos=0; // Vertical position 3052 protected $iLabelLeftMargin=2; // Title margin 3053 3054 function __construct() { 3055 $this->title = new TextProperty(); 3056 $this->title->Align('left','center'); 3057 $this->caption = new TextProperty(); 2949 3058 } 2950 3059 2951 3060 function GetCSIMArea() { 2952 3061 return $this->csimarea; 2953 3062 } 2954 3063 2955 3064 function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') { 2956 2957 2958 2959 //('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv");2960 2961 2962 2963 2964 //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");2965 3065 if( !is_string($aTarget) ) { 3066 $tv = substr(var_export($aTarget,true),0,40); 3067 JpGraphError::RaiseL(6024,$tv); 3068 //('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv"); 3069 } 3070 if( !is_string($aAlt) ) { 3071 $tv = substr(var_export($aAlt,true),0,40); 3072 JpGraphError::RaiseL(6025,$tv); 3073 //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); 3074 } 2966 3075 2967 3076 $this->csimtarget=$aTarget; … … 2969 3078 $this->csimalt=$aAlt; 2970 3079 } 2971 3080 2972 3081 function SetCSIMAlt($aAlt) { 2973 2974 2975 2976 //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");2977 3082 if( !is_string($aAlt) ) { 3083 $tv = substr(var_export($aAlt,true),0,40); 3084 JpGraphError::RaiseL(6025,$tv); 3085 //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv"); 3086 } 2978 3087 $this->csimalt=$aAlt; 2979 3088 } 2980 3089 2981 3090 function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) { 2982 3091 $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType); 2983 3092 } 2984 3093 2985 3094 function SetConstrainPos($xt,$yt,$xb,$yb) { 2986 $this->iConstrainPos = array($xt,$yt,$xb,$yb); 2987 } 2988 2989 /* 2990 function GetConstrain() { 2991 return array($this->iConstrainRow,$this->iConstrainType); 2992 } 2993 */ 2994 3095 $this->iConstrainPos = array($xt,$yt,$xb,$yb); 3096 } 3097 2995 3098 function GetMinDate() { 2996 3099 return $this->iStart; 2997 3100 } 2998 3101 2999 3102 function GetMaxDate() { 3000 3001 } 3002 3103 return $this->iStart; 3104 } 3105 3003 3106 function SetCaptionMargin($aMarg) { 3004 3107 $this->iCaptionMargin=$aMarg; 3005 3108 } 3006 3109 3007 3110 function GetAbsHeight($aImg) { 3008 return 0; 3009 } 3010 3111 return 0; 3112 } 3113 3011 3114 function GetLineNbr() { 3012 3115 return $this->iVPos; 3013 3116 } 3014 3117 3015 3118 function SetLabelLeftMargin($aOff) { 3016 3017 } 3119 $this->iLabelLeftMargin=$aOff; 3120 } 3018 3121 3019 3122 function StrokeActInfo($aImg,$aScale,$aYPos) { 3020 3021 3022 $this->title->Stroke($aImg,$cols,$aYPos); 3123 $cols=array(); 3124 $aScale->actinfo->GetColStart($aImg,$cols,true); 3125 $this->title->Stroke($aImg,$cols,$aYPos); 3023 3126 } 3024 3127 } … … 3026 3129 //=================================================== 3027 3130 // CLASS Progress 3028 // Holds parameters for the progress indicator 3131 // Holds parameters for the progress indicator 3029 3132 // displyed within a bar 3030 3133 //=================================================== … … 3033 3136 public $iPattern=GANTT_SOLID; 3034 3137 public $iColor="black", $iFillColor='black'; 3035 public $iDensity=98, $iHeight=0.65; 3036 3138 public $iDensity=98, $iHeight=0.65; 3139 3037 3140 function Set($aProg) { 3038 if( $aProg < 0.0 || $aProg > 1.0 ) 3039 JpGraphError::RaiseL(6027); 3040 //("Progress value must in range [0, 1]"); 3041 $this->iProgress = $aProg; 3042 } 3043 3044 function SetPattern($aPattern,$aColor="blue",$aDensity=98) { 3045 $this->iPattern = $aPattern; 3046 $this->iColor = $aColor; 3047 $this->iDensity = $aDensity; 3141 if( $aProg < 0.0 || $aProg > 1.0 ) { 3142 JpGraphError::RaiseL(6027); 3143 //("Progress value must in range [0, 1]"); 3144 } 3145 $this->iProgress = $aProg; 3146 } 3147 3148 function SetPattern($aPattern,$aColor="blue",$aDensity=98) { 3149 $this->iPattern = $aPattern; 3150 $this->iColor = $aColor; 3151 $this->iDensity = $aDensity; 3048 3152 } 3049 3153 3050 3154 function SetFillColor($aColor) { 3051 3052 } 3053 3155 $this->iFillColor = $aColor; 3156 } 3157 3054 3158 function SetHeight($aHeight) { 3055 3159 $this->iHeight = $aHeight; 3056 3160 } 3057 3161 } … … 3071 3175 private $iStart=0; // 0=from left margin, 1=just along header 3072 3176 3073 function HorizontalGridLine() {3074 3075 3076 3077 } 3078 3177 function __construct() { 3178 $this->line = new LineProperty(); 3179 $this->line->SetColor('gray@0.4'); 3180 $this->line->SetStyle('dashed'); 3181 } 3182 3079 3183 function Show($aShow=true) { 3080 3184 $this->iShow = $aShow; 3081 3185 } 3082 3186 3083 3187 function SetRowFillColor($aColor1,$aColor2='') { 3084 3085 3188 $this->iRowColor1 = $aColor1; 3189 $this->iRowColor2 = $aColor2; 3086 3190 } 3087 3191 3088 3192 function SetStart($aStart) { 3089 3193 $this->iStart = $aStart; 3090 3194 } 3091 3195 3092 3196 function Stroke($aImg,$aScale) { 3093 3094 3095 3096 3097 3098 3099 3100 3101 $xb = round($aScale->TranslateDate($limen)); 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 $yb = round($aScale->TranslateVertPos(1)); 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3197 3198 if( ! $this->iShow ) return; 3199 3200 // Get horizontal width of line 3201 /* 3202 $limst = $aScale->iStartDate; 3203 $limen = $aScale->iEndDate; 3204 $xt = round($aScale->TranslateDate($aScale->iStartDate)); 3205 $xb = round($aScale->TranslateDate($limen)); 3206 */ 3207 3208 if( $this->iStart === 0 ) { 3209 $xt = $aImg->left_margin-1; 3210 } 3211 else { 3212 $xt = round($aScale->TranslateDate($aScale->iStartDate))+1; 3213 } 3214 3215 $xb = $aImg->width-$aImg->right_margin; 3216 3217 $yt = round($aScale->TranslateVertPos(0)); 3218 $yb = round($aScale->TranslateVertPos(1)); 3219 $height = $yb - $yt; 3220 3221 // Loop around for all lines in the chart 3222 for($i=0; $i < $aScale->iVertLines; ++$i ) { 3223 $yb = $yt - $height; 3224 $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); 3225 if( $this->iRowColor1 !== '' ) { 3226 if( $i % 2 == 0 ) { 3227 $aImg->PushColor($this->iRowColor1); 3228 $aImg->FilledRectangle($xt,$yt,$xb,$yb); 3229 $aImg->PopColor(); 3230 } 3231 elseif( $this->iRowColor2 !== '' ) { 3232 $aImg->PushColor($this->iRowColor2); 3233 $aImg->FilledRectangle($xt,$yt,$xb,$yb); 3234 $aImg->PopColor(); 3235 } 3236 } 3237 $yt = round($aScale->TranslateVertPos($i+1)); 3238 } 3239 $yb = $yt - $height; 3240 $this->line->Stroke($aImg,$xt,$yb,$xb,$yb); 3137 3241 } 3138 3242 } … … 3151 3255 private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black"; 3152 3256 private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95; 3153 //--------------- 3154 // CONSTRUCTOR 3155 function GanttBar($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) { 3156 parent::GanttPlotObject(); 3157 $this->iStart = $aStart; 3158 // Is the end date given as a date or as number of days added to start date? 3159 if( is_string($aEnd) ) { 3160 // If end date has been specified without a time we will asssume 3161 // end date is at the end of that date 3162 if( strpos($aEnd,':') === false ) 3163 $this->iEnd = strtotime($aEnd)+SECPERDAY-1; 3164 else 3165 $this->iEnd = $aEnd; 3166 } 3167 elseif(is_int($aEnd) || is_float($aEnd) ) 3168 $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY); 3169 $this->iVPos = $aPos; 3170 $this->iHeightFactor = $aHeightFactor; 3171 $this->title->Set($aLabel); 3172 $this->caption = new TextProperty($aCaption); 3173 $this->caption->Align("left","center"); 3174 $this->leftMark =new PlotMark(); 3175 $this->leftMark->Hide(); 3176 $this->rightMark=new PlotMark(); 3177 $this->rightMark->Hide(); 3178 $this->progress = new Progress(); 3179 } 3180 3181 //--------------- 3182 // PUBLIC METHODS 3257 private $iBreakStyle=false, $iBreakLineStyle='dotted',$iBreakLineWeight=1; 3258 //--------------- 3259 // CONSTRUCTOR 3260 function __construct($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) { 3261 parent::__construct(); 3262 $this->iStart = $aStart; 3263 // Is the end date given as a date or as number of days added to start date? 3264 if( is_string($aEnd) ) { 3265 // If end date has been specified without a time we will asssume 3266 // end date is at the end of that date 3267 if( strpos($aEnd,':') === false ) { 3268 $this->iEnd = strtotime($aEnd)+SECPERDAY-1; 3269 } 3270 else { 3271 $this->iEnd = $aEnd; 3272 } 3273 } 3274 elseif(is_int($aEnd) || is_float($aEnd) ) { 3275 $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY); 3276 } 3277 $this->iVPos = $aPos; 3278 $this->iHeightFactor = $aHeightFactor; 3279 $this->title->Set($aLabel); 3280 $this->caption = new TextProperty($aCaption); 3281 $this->caption->Align("left","center"); 3282 $this->leftMark =new PlotMark(); 3283 $this->leftMark->Hide(); 3284 $this->rightMark=new PlotMark(); 3285 $this->rightMark->Hide(); 3286 $this->progress = new Progress(); 3287 } 3288 3289 //--------------- 3290 // PUBLIC METHODS 3183 3291 function SetShadow($aShadow=true,$aColor="gray") { 3184 $this->iShadow=$aShadow; 3185 $this->iShadowColor=$aColor; 3186 } 3187 3292 $this->iShadow=$aShadow; 3293 $this->iShadowColor=$aColor; 3294 } 3295 3296 function SetBreakStyle($aFlg=true,$aLineStyle='dotted',$aLineWeight=1) { 3297 $this->iBreakStyle = $aFlg; 3298 $this->iBreakLineStyle = $aLineStyle; 3299 $this->iBreakLineWeight = $aLineWeight; 3300 } 3301 3188 3302 function GetMaxDate() { 3189 3190 } 3191 3303 return $this->iEnd; 3304 } 3305 3192 3306 function SetHeight($aHeight) { 3193 3307 $this->iHeightFactor = $aHeight; 3194 3308 } 3195 3309 3196 3310 function SetColor($aColor) { 3197 3311 $this->iFrameColor = $aColor; 3198 3312 } 3199 3313 3200 3314 function SetFillColor($aColor) { 3201 3315 $this->iFillColor = $aColor; 3202 3316 } 3203 3317 3204 3318 function GetAbsHeight($aImg) { 3205 3206 3207 3208 3209 if( $this->leftMark->show ) 3210 3211 if( $this->rightMark->show ) 3212 3213 3214 3215 3216 3217 } 3218 3219 function SetPattern($aPattern,$aColor="blue",$aDensity=95) { 3220 3221 3222 3319 if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) { 3320 $m=-1; 3321 if( is_int($this->iHeightFactor) ) 3322 $m = $this->iHeightFactor; 3323 if( $this->leftMark->show ) 3324 $m = max($m,$this->leftMark->width*2); 3325 if( $this->rightMark->show ) 3326 $m = max($m,$this->rightMark->width*2); 3327 return $m; 3328 } 3329 else 3330 return -1; 3331 } 3332 3333 function SetPattern($aPattern,$aColor="blue",$aDensity=95) { 3334 $this->iPattern = $aPattern; 3335 $this->iPatternColor = $aColor; 3336 $this->iPatternDensity = $aDensity; 3223 3337 } 3224 3338 3225 3339 function Stroke($aImg,$aScale) { 3226 $factory = new RectPatternFactory(); 3227 $prect = $factory->Create($this->iPattern,$this->iPatternColor); 3228 $prect->SetDensity($this->iPatternDensity); 3229 3230 // If height factor is specified as a float between 0,1 then we take it as meaning 3231 // percetage of the scale width between horizontal line. 3232 // If it is an integer > 1 we take it to mean the absolute height in pixels 3233 if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1) 3234 $vs = $aScale->GetVertSpacing()*$this->iHeightFactor; 3235 elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 ) 3236 $vs = $this->iHeightFactor; 3237 else 3238 JpGraphError::RaiseL(6028,$this->iHeightFactor); 3239 //("Specified height (".$this->iHeightFactor.") for gantt bar is out of range."); 3240 3241 // Clip date to min max dates to show 3242 $st = $aScale->NormalizeDate($this->iStart); 3243 $en = $aScale->NormalizeDate($this->iEnd); 3244 3245 3246 $limst = max($st,$aScale->iStartDate); 3247 $limen = min($en,$aScale->iEndDate); 3248 3249 $xt = round($aScale->TranslateDate($limst)); 3250 $xb = round($aScale->TranslateDate($limen)); 3251 $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2)); 3252 $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2)); 3253 $middle = round($yt+($yb-$yt)/2); 3254 $this->StrokeActInfo($aImg,$aScale,$middle); 3255 3256 // CSIM for title 3257 if( ! empty($this->title->csimtarget) ) { 3258 $colwidth = $this->title->GetColWidth($aImg); 3259 $colstarts=array(); 3260 $aScale->actinfo->GetColStart($aImg,$colstarts,true); 3261 $n = min(count($colwidth),count($this->title->csimtarget)); 3262 for( $i=0; $i < $n; ++$i ) { 3263 $title_xt = $colstarts[$i]; 3264 $title_xb = $title_xt + $colwidth[$i]; 3265 $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; 3266 3267 if( ! empty($this->title->csimtarget[$i]) ) { 3268 $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\""; 3269 3270 if( ! empty($this->title->csimwintarget[$i]) ) { 3271 $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" "; 3272 } 3273 3274 if( ! empty($this->title->csimalt[$i]) ) { 3275 $tmp = $this->title->csimalt[$i]; 3276 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; 3277 } 3278 $this->csimarea .= " />\n"; 3279 } 3280 } 3281 } 3282 3283 // Check if the bar is totally outside the current scale range 3284 if( $en < $aScale->iStartDate || $st > $aScale->iEndDate ) 3285 return; 3286 3287 3288 // Remember the positions for the bar 3289 $this->SetConstrainPos($xt,$yt,$xb,$yb); 3290 3291 $prect->ShowFrame(false); 3292 $prect->SetBackground($this->iFillColor); 3293 if( $this->iShadow ) { 3294 $aImg->SetColor($this->iFrameColor); 3295 $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor); 3296 $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2)); 3297 $prect->Stroke($aImg); 3298 } 3299 else { 3300 $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1)); 3301 $prect->Stroke($aImg); 3302 $aImg->SetColor($this->iFrameColor); 3303 $aImg->Rectangle($xt,$yt,$xb,$yb); 3304 } 3305 3306 // CSIM for bar 3307 if( ! empty($this->csimtarget) ) { 3308 3309 $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb"; 3310 $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\""; 3311 3312 if( !empty($this->csimwintarget) ) { 3313 $this->csimarea .= " target=\"".$this->csimwintarget."\" "; 3314 } 3315 3316 if( $this->csimalt != '' ) { 3317 $tmp = $this->csimalt; 3318 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; 3319 } 3320 $this->csimarea .= " />\n"; 3321 } 3322 3323 // Draw progress bar inside activity bar 3324 if( $this->progress->iProgress > 0 ) { 3325 3326 $xtp = $aScale->TranslateDate($st); 3327 $xbp = $aScale->TranslateDate($en); 3328 $len = ($xbp-$xtp)*$this->progress->iProgress; 3329 3330 $endpos = $xtp+$len; 3331 if( $endpos > $xt ) { 3332 3333 // Take away the length of the progress that is not visible (before the start date) 3334 $len -= ($xt-$xtp); 3335 3336 // Is the the progress bar visible after the start date? 3337 if( $xtp < $xt ) 3338 $xtp = $xt; 3339 3340 // Make sure that the progess bar doesn't extend over the end date 3341 if( $xtp+$len-1 > $xb ) 3342 $len = $xb - $xtp ; 3343 3344 $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor); 3345 $prog->SetDensity($this->progress->iDensity); 3346 $prog->SetBackground($this->progress->iFillColor); 3347 $barheight = ($yb-$yt+1); 3348 if( $this->iShadow ) 3349 $barheight -= $this->iShadowWidth; 3350 $progressheight = floor($barheight*$this->progress->iHeight); 3351 $marg = ceil(($barheight-$progressheight)/2); 3352 $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg); 3353 $prog->SetPos($pos); 3354 $prog->Stroke($aImg); 3355 } 3356 } 3357 3358 // We don't plot the end mark if the bar has been capped 3359 if( $limst == $st ) { 3360 $y = $middle; 3361 // We treat the RIGHT and LEFT triangle mark a little bi 3362 // special so that these marks are placed right under the 3363 // bar. 3364 if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) { 3365 $y = $yb ; 3366 } 3367 $this->leftMark->Stroke($aImg,$xt,$y); 3368 } 3369 if( $limen == $en ) { 3370 $y = $middle; 3371 // We treat the RIGHT and LEFT triangle mark a little bi 3372 // special so that these marks are placed right under the 3373 // bar. 3374 if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) { 3375 $y = $yb ; 3376 } 3377 $this->rightMark->Stroke($aImg,$xb,$y); 3378 3379 $margin = $this->iCaptionMargin; 3380 if( $this->rightMark->show ) 3381 $margin += $this->rightMark->GetWidth(); 3382 $this->caption->Stroke($aImg,$xb+$margin,$middle); 3383 } 3340 $factory = new RectPatternFactory(); 3341 $prect = $factory->Create($this->iPattern,$this->iPatternColor); 3342 $prect->SetDensity($this->iPatternDensity); 3343 3344 // If height factor is specified as a float between 0,1 then we take it as meaning 3345 // percetage of the scale width between horizontal line. 3346 // If it is an integer > 1 we take it to mean the absolute height in pixels 3347 if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1) 3348 $vs = $aScale->GetVertSpacing()*$this->iHeightFactor; 3349 elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 ) 3350 $vs = $this->iHeightFactor; 3351 else { 3352 JpGraphError::RaiseL(6028,$this->iHeightFactor); 3353 // ("Specified height (".$this->iHeightFactor.") for gantt bar is out of range."); 3354 } 3355 3356 // Clip date to min max dates to show 3357 $st = $aScale->NormalizeDate($this->iStart); 3358 $en = $aScale->NormalizeDate($this->iEnd); 3359 3360 $limst = max($st,$aScale->iStartDate); 3361 $limen = min($en,$aScale->iEndDate); 3362 3363 $xt = round($aScale->TranslateDate($limst)); 3364 $xb = round($aScale->TranslateDate($limen)); 3365 $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2)); 3366 $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2)); 3367 $middle = round($yt+($yb-$yt)/2); 3368 $this->StrokeActInfo($aImg,$aScale,$middle); 3369 3370 // CSIM for title 3371 if( ! empty($this->title->csimtarget) ) { 3372 $colwidth = $this->title->GetColWidth($aImg); 3373 $colstarts=array(); 3374 $aScale->actinfo->GetColStart($aImg,$colstarts,true); 3375 $n = min(count($colwidth),count($this->title->csimtarget)); 3376 for( $i=0; $i < $n; ++$i ) { 3377 $title_xt = $colstarts[$i]; 3378 $title_xb = $title_xt + $colwidth[$i]; 3379 $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; 3380 3381 if( ! empty($this->title->csimtarget[$i]) ) { 3382 $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\""; 3383 3384 if( ! empty($this->title->csimwintarget[$i]) ) { 3385 $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" "; 3386 } 3387 3388 if( ! empty($this->title->csimalt[$i]) ) { 3389 $tmp = $this->title->csimalt[$i]; 3390 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; 3391 } 3392 $this->csimarea .= " />\n"; 3393 } 3394 } 3395 } 3396 3397 // Check if the bar is totally outside the current scale range 3398 if( $en < $aScale->iStartDate || $st > $aScale->iEndDate ) 3399 return; 3400 3401 3402 // Remember the positions for the bar 3403 $this->SetConstrainPos($xt,$yt,$xb,$yb); 3404 3405 3406 3407 $prect->ShowFrame(false); 3408 $prect->SetBackground($this->iFillColor); 3409 if( $this->iBreakStyle ) { 3410 $aImg->SetColor($this->iFrameColor); 3411 $olds = $aImg->SetLineStyle($this->iBreakLineStyle); 3412 $oldw = $aImg->SetLineWeight($this->iBreakLineWeight); 3413 $aImg->StyleLine($xt,$yt,$xb,$yt); 3414 $aImg->StyleLine($xt,$yb,$xb,$yb); 3415 $aImg->SetLineStyle($olds); 3416 $aImg->SetLineWeight($oldw); 3417 } 3418 else { 3419 if( $this->iShadow ) { 3420 $aImg->SetColor($this->iFrameColor); 3421 $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor); 3422 $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2)); 3423 $prect->Stroke($aImg); 3424 } 3425 else { 3426 $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1)); 3427 $prect->Stroke($aImg); 3428 $aImg->SetColor($this->iFrameColor); 3429 $aImg->Rectangle($xt,$yt,$xb,$yb); 3430 } 3431 } 3432 // CSIM for bar 3433 if( ! empty($this->csimtarget) ) { 3434 3435 $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb"; 3436 $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\""; 3437 3438 if( !empty($this->csimwintarget) ) { 3439 $this->csimarea .= " target=\"".$this->csimwintarget."\" "; 3440 } 3441 3442 if( $this->csimalt != '' ) { 3443 $tmp = $this->csimalt; 3444 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; 3445 } 3446 $this->csimarea .= " />\n"; 3447 } 3448 3449 // Draw progress bar inside activity bar 3450 if( $this->progress->iProgress > 0 ) { 3451 3452 $xtp = $aScale->TranslateDate($st); 3453 $xbp = $aScale->TranslateDate($en); 3454 $len = ($xbp-$xtp)*$this->progress->iProgress; 3455 3456 $endpos = $xtp+$len; 3457 if( $endpos > $xt ) { 3458 3459 // Take away the length of the progress that is not visible (before the start date) 3460 $len -= ($xt-$xtp); 3461 3462 // Is the the progress bar visible after the start date? 3463 if( $xtp < $xt ) 3464 $xtp = $xt; 3465 3466 // Make sure that the progess bar doesn't extend over the end date 3467 if( $xtp+$len-1 > $xb ) 3468 $len = $xb - $xtp ; 3469 3470 $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor); 3471 $prog->SetDensity($this->progress->iDensity); 3472 $prog->SetBackground($this->progress->iFillColor); 3473 $barheight = ($yb-$yt+1); 3474 if( $this->iShadow ) 3475 $barheight -= $this->iShadowWidth; 3476 $progressheight = floor($barheight*$this->progress->iHeight); 3477 $marg = ceil(($barheight-$progressheight)/2); 3478 $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg); 3479 $prog->SetPos($pos); 3480 $prog->Stroke($aImg); 3481 } 3482 } 3483 3484 // We don't plot the end mark if the bar has been capped 3485 if( $limst == $st ) { 3486 $y = $middle; 3487 // We treat the RIGHT and LEFT triangle mark a little bi 3488 // special so that these marks are placed right under the 3489 // bar. 3490 if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) { 3491 $y = $yb ; 3492 } 3493 $this->leftMark->Stroke($aImg,$xt,$y); 3494 } 3495 if( $limen == $en ) { 3496 $y = $middle; 3497 // We treat the RIGHT and LEFT triangle mark a little bi 3498 // special so that these marks are placed right under the 3499 // bar. 3500 if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) { 3501 $y = $yb ; 3502 } 3503 $this->rightMark->Stroke($aImg,$xb,$y); 3504 3505 $margin = $this->iCaptionMargin; 3506 if( $this->rightMark->show ) 3507 $margin += $this->rightMark->GetWidth(); 3508 $this->caption->Stroke($aImg,$xb+$margin,$middle); 3509 } 3384 3510 } 3385 3511 } … … 3391 3517 class MileStone extends GanttPlotObject { 3392 3518 public $mark; 3393 3394 //---------------3395 // CONSTRUCTOR 3396 function MileStone($aVPos,$aLabel,$aDate,$aCaption="") {3397 GanttPlotObject::GanttPlotObject();3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 } 3411 3412 //---------------3413 // PUBLIC METHODS 3414 3519 3520 //--------------- 3521 // CONSTRUCTOR 3522 function __construct($aVPos,$aLabel,$aDate,$aCaption="") { 3523 GanttPlotObject::__construct(); 3524 $this->caption->Set($aCaption); 3525 $this->caption->Align("left","center"); 3526 $this->caption->SetFont(FF_FONT1,FS_BOLD); 3527 $this->title->Set($aLabel); 3528 $this->title->SetColor("darkred"); 3529 $this->mark = new PlotMark(); 3530 $this->mark->SetWidth(10); 3531 $this->mark->SetType(MARK_DIAMOND); 3532 $this->mark->SetColor("darkred"); 3533 $this->mark->SetFillColor("darkred"); 3534 $this->iVPos = $aVPos; 3535 $this->iStart = $aDate; 3536 } 3537 3538 //--------------- 3539 // PUBLIC METHODS 3540 3415 3541 function GetAbsHeight($aImg) { 3416 3417 } 3418 3542 return max($this->title->GetHeight($aImg),$this->mark->GetWidth()); 3543 } 3544 3419 3545 function Stroke($aImg,$aScale) { 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 $this->mark->Stroke($aImg,$x,$y); 3474 3475 3476 3546 // Put the mark in the middle at the middle of the day 3547 $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2; 3548 $x = $aScale->TranslateDate($d); 3549 $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2); 3550 3551 $this->StrokeActInfo($aImg,$aScale,$y); 3552 3553 // CSIM for title 3554 if( ! empty($this->title->csimtarget) ) { 3555 3556 $yt = round($y - $this->title->GetHeight($aImg)/2); 3557 $yb = round($y + $this->title->GetHeight($aImg)/2); 3558 3559 $colwidth = $this->title->GetColWidth($aImg); 3560 $colstarts=array(); 3561 $aScale->actinfo->GetColStart($aImg,$colstarts,true); 3562 $n = min(count($colwidth),count($this->title->csimtarget)); 3563 for( $i=0; $i < $n; ++$i ) { 3564 $title_xt = $colstarts[$i]; 3565 $title_xb = $title_xt + $colwidth[$i]; 3566 $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb"; 3567 3568 if( !empty($this->title->csimtarget[$i]) ) { 3569 3570 $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\""; 3571 3572 if( !empty($this->title->csimwintarget[$i]) ) { 3573 $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\""; 3574 } 3575 3576 if( ! empty($this->title->csimalt[$i]) ) { 3577 $tmp = $this->title->csimalt[$i]; 3578 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" "; 3579 } 3580 $this->csimarea .= " />\n"; 3581 } 3582 } 3583 } 3584 3585 if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) 3586 return; 3587 3588 // Remember the coordinates for any constrains linking to 3589 // this milestone 3590 $w = $this->mark->GetWidth()/2; 3591 $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w)); 3592 3593 // Setup CSIM 3594 if( $this->csimtarget != '' ) { 3595 $this->mark->SetCSIMTarget( $this->csimtarget ); 3596 $this->mark->SetCSIMAlt( $this->csimalt ); 3597 } 3598 3599 $this->mark->Stroke($aImg,$x,$y); 3600 $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y); 3601 3602 $this->csimarea .= $this->mark->GetCSIMAreas(); 3477 3603 } 3478 3604 } … … 3485 3611 3486 3612 class TextPropertyBelow extends TextProperty { 3487 function TextPropertyBelow($aTxt='') {3488 parent::TextProperty($aTxt);3613 function __construct($aTxt='') { 3614 parent::__construct($aTxt); 3489 3615 } 3490 3616 3491 3617 function GetColWidth($aImg,$aMargin=0) { 3492 3493 3494 3618 // Since we are not stroking the title in the columns 3619 // but rather under the graph we want this to return 0. 3620 return array(0); 3495 3621 } 3496 3622 } … … 3498 3624 class GanttVLine extends GanttPlotObject { 3499 3625 3500 private $iLine,$title_margin=3, $iDayOffset=1; 3501 3502 //--------------- 3503 // CONSTRUCTOR 3504 function GanttVLine($aDate,$aTitle="",$aColor="black",$aWeight=3,$aStyle="dashed") { 3505 GanttPlotObject::GanttPlotObject(); 3506 $this->iLine = new LineProperty(); 3507 $this->iLine->SetColor($aColor); 3508 $this->iLine->SetWeight($aWeight); 3509 $this->iLine->SetStyle($aStyle); 3510 $this->iStart = $aDate; 3511 $this->title = new TextPropertyBelow(); 3512 $this->title->Set($aTitle); 3513 } 3514 3515 //--------------- 3516 // PUBLIC METHODS 3626 private $iLine,$title_margin=3, $iDayOffset=0.5; 3627 private $iStartRow = -1, $iEndRow = -1; 3628 3629 //--------------- 3630 // CONSTRUCTOR 3631 function __construct($aDate,$aTitle="",$aColor="darkred",$aWeight=2,$aStyle="solid") { 3632 GanttPlotObject::__construct(); 3633 $this->iLine = new LineProperty(); 3634 $this->iLine->SetColor($aColor); 3635 $this->iLine->SetWeight($aWeight); 3636 $this->iLine->SetStyle($aStyle); 3637 $this->iStart = $aDate; 3638 $this->title = new TextPropertyBelow(); 3639 $this->title->Set($aTitle); 3640 } 3641 3642 //--------------- 3643 // PUBLIC METHODS 3644 3645 // Set start and end rows for the VLine. By default the entire heigh of the 3646 // Gantt chart is used 3647 function SetRowSpan($aStart, $aEnd=-1) { 3648 $this->iStartRow = $aStart; 3649 $this->iEndRow = $aEnd; 3650 } 3517 3651 3518 3652 function SetDayOffset($aOff=0.5) { 3519 if( $aOff < 0.0 || $aOff > 1.0 ) 3520 JpGraphError::RaiseL(6029); 3521 //("Offset for vertical line must be in range [0,1]"); 3522 $this->iDayOffset = $aOff; 3523 } 3524 3653 if( $aOff < 0.0 || $aOff > 1.0 ) { 3654 JpGraphError::RaiseL(6029); 3655 //("Offset for vertical line must be in range [0,1]"); 3656 } 3657 $this->iDayOffset = $aOff; 3658 } 3659 3525 3660 function SetTitleMargin($aMarg) { 3526 $this->title_margin = $aMarg; 3527 } 3528 3661 $this->title_margin = $aMarg; 3662 } 3663 3664 function SetWeight($aWeight) { 3665 $this->iLine->SetWeight($aWeight); 3666 } 3667 3529 3668 function Stroke($aImg,$aScale) { 3530 $d = $aScale->NormalizeDate($this->iStart); 3531 if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) 3532 return; 3533 if($this->iDayOffset != 0.0) 3534 $d += 24*60*60*$this->iDayOffset; 3535 $x = $aScale->TranslateDate($d); 3536 $y1 = $aScale->iVertHeaderSize+$aImg->top_margin; 3537 $y2 = $aImg->height - $aImg->bottom_margin; 3538 $this->iLine->Stroke($aImg,$x,$y1,$x,$y2); 3539 $this->title->Align("center","top"); 3540 $this->title->Stroke($aImg,$x,$y2+$this->title_margin); 3541 } 3669 $d = $aScale->NormalizeDate($this->iStart); 3670 if( $d < $aScale->iStartDate || $d > $aScale->iEndDate ) 3671 return; 3672 if($this->iDayOffset != 0.0) 3673 $d += 24*60*60*$this->iDayOffset; 3674 $x = $aScale->TranslateDate($d);//d=1006858800, 3675 3676 if( $this->iStartRow > -1 ) { 3677 $y1 = $aScale->TranslateVertPos($this->iStartRow,true) ; 3678 } 3679 else { 3680 $y1 = $aScale->iVertHeaderSize+$aImg->top_margin; 3681 } 3682 3683 if( $this->iEndRow > -1 ) { 3684 $y2 = $aScale->TranslateVertPos($this->iEndRow); 3685 } 3686 else { 3687 $y2 = $aImg->height - $aImg->bottom_margin; 3688 } 3689 3690 $this->iLine->Stroke($aImg,$x,$y1,$x,$y2); 3691 $this->title->Align("center","top"); 3692 $this->title->Stroke($aImg,$x,$y2+$this->title_margin); 3693 } 3542 3694 } 3543 3695 3544 3696 //=================================================== 3545 3697 // CLASS LinkArrow 3546 // Handles the drawing of a an arrow 3698 // Handles the drawing of a an arrow 3547 3699 //=================================================== 3548 3700 class LinkArrow { 3549 3701 private $ix,$iy; 3550 3702 private $isizespec = array( 3551 3703 array(2,3),array(3,5),array(3,8),array(6,15),array(8,22)); 3552 3704 private $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2; 3553 3705 private $iColor='black'; 3554 3706 3555 function LinkArrow($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) {3556 3557 3558 3559 3560 3561 } 3562 3707 function __construct($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) { 3708 $this->iDirection = $aDirection; 3709 $this->iType = $aType; 3710 $this->iSize = $aSize; 3711 $this->ix = $x; 3712 $this->iy = $y; 3713 } 3714 3563 3715 function SetColor($aColor) { 3564 3716 $this->iColor = $aColor; 3565 3717 } 3566 3718 3567 3719 function SetSize($aSize) { 3568 3720 $this->iSize = $aSize; 3569 3721 } 3570 3722 3571 3723 function SetType($aType) { 3572 3724 $this->iType = $aType; 3573 3725 } 3574 3726 3575 3727 function Stroke($aImg) { 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 //('Unknown arrow direction for link.');3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 //('Unknown arrow type for link.');3609 3610 break; 3611 3728 list($dx,$dy) = $this->isizespec[$this->iSize]; 3729 $x = $this->ix; 3730 $y = $this->iy; 3731 switch ( $this->iDirection ) { 3732 case ARROW_DOWN: 3733 $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y); 3734 break; 3735 case ARROW_UP: 3736 $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y); 3737 break; 3738 case ARROW_LEFT: 3739 $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y); 3740 break; 3741 case ARROW_RIGHT: 3742 $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y); 3743 break; 3744 default: 3745 JpGraphError::RaiseL(6030); 3746 //('Unknown arrow direction for link.'); 3747 die(); 3748 break; 3749 } 3750 $aImg->SetColor($this->iColor); 3751 switch( $this->iType ) { 3752 case ARROWT_SOLID: 3753 $aImg->FilledPolygon($c); 3754 break; 3755 case ARROWT_OPEN: 3756 $aImg->Polygon($c); 3757 break; 3758 default: 3759 JpGraphError::RaiseL(6031); 3760 //('Unknown arrow type for link.'); 3761 die(); 3762 break; 3763 } 3612 3764 } 3613 3765 } … … 3624 3776 private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID; 3625 3777 3626 function GanttLink($x1=0,$y1=0,$x2=0,$y2=0) {3627 3628 3629 3630 3778 function __construct($x1=0,$y1=0,$x2=0,$y2=0) { 3779 $this->ix1 = $x1; 3780 $this->ix2 = $x2; 3781 $this->iy1 = $y1; 3782 $this->iy2 = $y2; 3631 3783 } 3632 3784 3633 3785 function SetPos($x1,$y1,$x2,$y2) { 3634 3635 3636 3637 3786 $this->ix1 = $x1; 3787 $this->ix2 = $x2; 3788 $this->iy1 = $y1; 3789 $this->iy2 = $y2; 3638 3790 } 3639 3791 3640 3792 function SetPath($aPath) { 3641 3793 $this->iPathType = $aPath; 3642 3794 } 3643 3795 3644 3796 function SetColor($aColor) { 3645 3797 $this->iColor = $aColor; 3646 3798 } 3647 3799 3648 3800 function SetArrow($aSize,$aType=ARROWT_SOLID) { 3649 3650 3651 } 3652 3801 $this->iArrowSize = $aSize; 3802 $this->iArrowType = $aType; 3803 } 3804 3653 3805 function SetWeight($aWeight) { 3654 3806 $this->iWeight = $aWeight; 3655 3807 } 3656 3808 3657 3809 function Stroke($aImg) { 3658 3659 3660 3661 3662 3663 // space between axctivities then no suh detour is made and the 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 //('Internal error: Unknown path type (='.$this->iPathType .') specified for link.');3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 // If we draw a link back in time (end to start) and the bars 3708 // are very close we also change the path so it comes in from 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 //('Internal error: Unknown path type specified for link.');3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 //('Internal error: Unknown path type specified for link.');3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 //('Internal error: Unknown path type specified for link.');3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3810 // The way the path for the arrow is constructed is partly based 3811 // on some heuristics. This is not an exact science but draws the 3812 // path in a way that, for me, makes esthetic sence. For example 3813 // if the start and end activities are very close we make a small 3814 // detour to endter the target horixontally. If there are more 3815 // space between axctivities then no suh detour is made and the 3816 // target is "hit" directly vertical. I have tried to keep this 3817 // simple. no doubt this could become almost infinitive complex 3818 // and have some real AI. Feel free to modify this. 3819 // This will no-doubt be tweaked as times go by. One design aim 3820 // is to avoid having the user choose what types of arrow 3821 // he wants. 3822 3823 // The arrow is drawn between (x1,y1) to (x2,y2) 3824 $x1 = $this->ix1 ; 3825 $x2 = $this->ix2 ; 3826 $y1 = $this->iy1 ; 3827 $y2 = $this->iy2 ; 3828 3829 // Depending on if the target is below or above we have to 3830 // handle thi different. 3831 if( $y2 > $y1 ) { 3832 $arrowtype = ARROW_DOWN; 3833 $midy = round(($y2-$y1)/2+$y1); 3834 if( $x2 > $x1 ) { 3835 switch ( $this->iPathType ) { 3836 case 0: 3837 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3838 break; 3839 case 1: 3840 case 2: 3841 case 3: 3842 $c = array($x1,$y1,$x2,$y1,$x2,$y2); 3843 break; 3844 default: 3845 JpGraphError::RaiseL(6032,$this->iPathType); 3846 //('Internal error: Unknown path type (='.$this->iPathType .') specified for link.'); 3847 exit(1); 3848 break; 3849 } 3850 } 3851 else { 3852 switch ( $this->iPathType ) { 3853 case 0: 3854 case 1: 3855 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3856 break; 3857 case 2: 3858 // Always extend out horizontally a bit from the first point 3859 // If we draw a link back in time (end to start) and the bars 3860 // are very close we also change the path so it comes in from 3861 // the left on the activity 3862 $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, 3863 $x1+$this->iPathExtend,$midy, 3864 $x2,$midy,$x2,$y2); 3865 break; 3866 case 3: 3867 if( $y2-$midy < 6 ) { 3868 $c = array($x1,$y1,$x1,$midy, 3869 $x2-$this->iPathExtend,$midy, 3870 $x2-$this->iPathExtend,$y2, 3871 $x2,$y2); 3872 $arrowtype = ARROW_RIGHT; 3873 } 3874 else { 3875 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3876 } 3877 break; 3878 default: 3879 JpGraphError::RaiseL(6032,$this->iPathType); 3880 //('Internal error: Unknown path type specified for link.'); 3881 exit(1); 3882 break; 3883 } 3884 } 3885 $arrow = new LinkArrow($x2,$y2,$arrowtype); 3886 } 3887 else { 3888 // Y2 < Y1 3889 $arrowtype = ARROW_UP; 3890 $midy = round(($y1-$y2)/2+$y2); 3891 if( $x2 > $x1 ) { 3892 switch ( $this->iPathType ) { 3893 case 0: 3894 case 1: 3895 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3896 break; 3897 case 3: 3898 if( $midy-$y2 < 8 ) { 3899 $arrowtype = ARROW_RIGHT; 3900 $c = array($x1,$y1,$x1,$y2,$x2,$y2); 3901 } 3902 else { 3903 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3904 } 3905 break; 3906 default: 3907 JpGraphError::RaiseL(6032,$this->iPathType); 3908 //('Internal error: Unknown path type specified for link.'); 3909 break; 3910 } 3911 } 3912 else { 3913 switch ( $this->iPathType ) { 3914 case 0: 3915 case 1: 3916 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3917 break; 3918 case 2: 3919 // Always extend out horizontally a bit from the first point 3920 $c = array($x1,$y1,$x1+$this->iPathExtend,$y1, 3921 $x1+$this->iPathExtend,$midy, 3922 $x2,$midy,$x2,$y2); 3923 break; 3924 case 3: 3925 if( $midy-$y2 < 16 ) { 3926 $arrowtype = ARROW_RIGHT; 3927 $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy, 3928 $x2-$this->iPathExtend,$y2, 3929 $x2,$y2); 3930 } 3931 else { 3932 $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2); 3933 } 3934 break; 3935 default: 3936 JpGraphError::RaiseL(6032,$this->iPathType); 3937 //('Internal error: Unknown path type specified for link.'); 3938 break; 3939 } 3940 } 3941 $arrow = new LinkArrow($x2,$y2,$arrowtype); 3942 } 3943 $aImg->SetColor($this->iColor); 3944 $aImg->SetLineWeight($this->iWeight); 3945 $aImg->Polygon($c); 3946 $aImg->SetLineWeight(1); 3947 $arrow->SetColor($this->iColor); 3948 $arrow->SetSize($this->iArrowSize); 3949 $arrow->SetType($this->iArrowType); 3950 $arrow->Stroke($aImg); 3799 3951 } 3800 3952 }
Note:
See TracChangeset
for help on using the changeset viewer.