[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/projectmanager/inc/jpgraph-1.5.2/src/ -> jpgraph_gantt.php (source)

   1  <?php
   2  /*=======================================================================
   3  // File:    JPGRAPH_GANTT.PHP
   4  // Description:    JpGraph Gantt plot extension
   5  // Created:     2001-11-12
   6  // Author:    Johan Persson (johanp@aditus.nu)
   7  // Ver:        $Id: jpgraph_gantt.php 18250 2005-05-07 14:13:43Z ralfbecker $
   8  //
   9  // License:    This code is released under GPL 2.0
  10  //
  11  //========================================================================
  12  */
  13  
  14  // Scale Header types
  15  DEFINE("GANTT_HDAY",1);
  16  DEFINE("GANTT_HWEEK",2);
  17  DEFINE("GANTT_HMONTH",4);
  18  DEFINE("GANTT_HYEAR",8);
  19  
  20  // Bar patterns
  21  DEFINE("GANTT_RDIAG",BAND_RDIAG);    // Right diagonal lines
  22  DEFINE("GANTT_LDIAG",BAND_LDIAG); // Left diagonal lines
  23  DEFINE("GANTT_SOLID",BAND_SOLID); // Solid one color
  24  DEFINE("GANTT_VLINE",BAND_VLINE); // Vertical lines
  25  DEFINE("GANTT_HLINE",BAND_HLINE);  // Horizontal lines
  26  DEFINE("GANTT_3DPLANE",BAND_3DPLANE);  // "3D" Plane
  27  DEFINE("GANTT_HVCROSS",BAND_HVCROSS);  // Vertical/Hor crosses
  28  DEFINE("GANTT_DIAGCROSS",BAND_DIAGCROSS); // Diagonal crosses
  29  
  30  // Conversion constant
  31  DEFINE("SECPERDAY",3600*24);
  32  
  33  // Locales
  34  DEFINE("LOCALE_EN",0);
  35  DEFINE("LOCALE_SE",1);
  36  DEFINE("LOCALE_DE",2);
  37  
  38  // Layout of bars
  39  DEFINE("GANTT_EVEN",1);
  40  DEFINE("GANTT_FROMTOP",2);
  41  
  42  // Styles for week header
  43  DEFINE("WEEKSTYLE_WNBR",0);
  44  DEFINE("WEEKSTYLE_FIRSTDAY",1);
  45  DEFINE("WEEKSTYLE_FIRSTDAY2",1);
  46  
  47  // Styles for month header
  48  DEFINE("MONTHSTYLE_SHORTNAME",0);
  49  DEFINE("MONTHSTYLE_LONGNAME",1);
  50  DEFINE("MONTHSTYLE_LONGNAMEYEAR2",2);
  51  DEFINE("MONTHSTYLE_SHORTNAMEYEAR2",3);
  52  DEFINE("MONTHSTYLE_LONGNAMEYEAR4",4);
  53  DEFINE("MONTHSTYLE_SHORTNAMEYEAR4",5);
  54  
  55  //===================================================
  56  // CLASS DateLocale
  57  // Description: Hold localized text used in dates
  58  // ToDOo: Rewrite this to use the real local locale
  59  // instead.
  60  //===================================================
  61  class DateLocale {
  62      var $iLocale=0;     // Default to english
  63      var $iDayAbb = array(
  64      array("M","T","W","T","F","S","S"),            // English locale
  65      array("M","T","O","T","F","L","S"),            // Swedish locale
  66      array("M","D","M","D","F","S","S"));            // German locale
  67      var $iShortDay = array(
  68      array("Mon","Tue","Wed","Thu","Fri","Sat","Sun"),
  69      array("Mån","Tis","Ons","Tor","Fre","Lör","Sön"),
  70      array("Mon","Die","Mit","Don","Fre","Sam","Son"));
  71      var $iShortMonth = array(
  72      array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),
  73      array("Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"),
  74      array("Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"));
  75      var $iMonthName = array(
  76      array("January","February","Mars","April","May","June","July","August","September","October","November","December"),
  77      array("Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"),
  78      array("Januar","Februar","März","April","Mai","Juni","July","August","September","Oktober","November","Dezember"));
  79      
  80  //---------------
  81  // CONSTRUCTOR    
  82      function DateLocale() {
  83      // Empty
  84      }
  85  
  86  //---------------
  87  // PUBLIC METHODS    
  88      function Set($aLocale) {
  89      if( $aLocale < LOCALE_EN || $aLocale > LOCALE_DE )
  90          JpGraphError::Raise("<b>JpGraph Error:</b> Unsupported locale ($aLocale)");
  91      $this->iLocale = $aLocale;
  92      }
  93      
  94      function GetDayAbb() {
  95      return $this->iDayAbb[$this->iLocale];
  96      }
  97      
  98      function GetShortDay() {
  99      return $this->iShortDay[$this->iLocale];
 100      }
 101  
 102      function GetShortMonth($aMonth=null) {
 103      return $this->iShortMonth[$this->iLocale];
 104      }
 105      
 106      function GetShortMonthName($aNbr) {
 107      return $this->iShortMonth[$this->iLocale][$aNbr];
 108      }
 109  
 110      function GetLongMonthName($aNbr) {
 111      return $this->iMonthName[$this->iLocale][$aNbr];
 112      }
 113  
 114      function GetMonth() {
 115      return $this->iMonthName[$this->iLocale];
 116      }
 117  }
 118  
 119  //===================================================
 120  // CLASS GanttGraph
 121  // Description: Main class to handle gantt graphs
 122  //===================================================
 123  class GanttGraph extends Graph {
 124      var $scale;                            // Public accessible
 125      var $iObj=array();                // Gantt objects
 126      var $iLabelHMarginFactor=0.2;    // 10% margin on each side of the labels
 127      var $iLabelVMarginFactor=0.4;    // 40% margin on top and bottom of label
 128      var $iLayout=GANTT_FROMTOP;    // Could also be GANTT_EVEN
 129  
 130  //---------------
 131  // CONSTRUCTOR    
 132      // Create a new gantt graph
 133      function GanttGraph($aWidth=-1,$aHeight=-1,$aCachedName="",$aTimeOut=0,$aInline=true) {
 134      Graph::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline);        
 135      $this->scale = new GanttScale($this->img);
 136      $this->img->SetMargin($aWidth/17,$aWidth/17,$aHeight/7,$aHeight/10);
 137          
 138      $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY);
 139      $this->SetBox();
 140      }
 141      
 142  //---------------
 143  // PUBLIC METHODS    
 144      // Set what headers should be shown
 145      function ShowHeaders($aFlg) {
 146      $this->scale->ShowHeaders($aFlg);
 147      }
 148      
 149      // Specify the fraction of the font height that should be added 
 150      // as vertical margin
 151      function SetLabelVMarginFactor($aVal) {
 152      $this->iLabelVMarginFactor = $aVal;
 153      }
 154      
 155      // Add a new Gantt object
 156      function Add(&$aObject) {
 157      if( is_array($aObject) ) {
 158          for($i=0; $i<count($aObject); ++$i)
 159          $this->iObj[] = $aObject[$i];
 160      }
 161      else
 162          $this->iObj[] = $aObject;
 163      }
 164  
 165      // Override inherit method from Graph and give a warning message
 166      function SetScale() {
 167      JpGraphError::Raise("<b>JpGraph Error:</b> SetScale() is not meaningfull with Gantt charts.");
 168      // Empty
 169      }
 170  
 171      // Specify the date range for Gantt graphs (if this is not set it will be
 172      // automtically determined from the input data)
 173      function SetDateRange($aStart,$aEnd) {
 174      $this->scale->SetRange($aStart,$aEnd);
 175      }
 176      
 177      // Get the maximum width of the titles for the bars    
 178      function GetMaxLabelWidth() {
 179      $m=0;
 180      if( $this->iObj != null ) {
 181          $m = $this->iObj[0]->title->GetWidth($this->img);
 182          for($i=1; $i<count($this->iObj); ++$i) {
 183          if( $this->iObj[$i]->title->HasTabs() ) {
 184              list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true);
 185              $m=max($m,$tot);
 186          }
 187          else 
 188              $m=max($m,$this->iObj[$i]->title->GetWidth($this->img));
 189          }
 190      }
 191      return $m;
 192      }
 193      
 194      // Get the maximum height of the titles for the bars
 195      function GetMaxLabelHeight() {
 196      $m=0;
 197      if( $this->iObj != null ) {
 198          $m = $this->iObj[0]->title->GetHeight($this->img);
 199          for($i=1; $i<count($this->iObj); ++$i) {
 200          $m=max($m,$this->iObj[$i]->title->GetHeight($this->img));
 201          }
 202      }
 203      return $m;
 204      }
 205  
 206      function GetMaxBarAbsHeight() {
 207      $m=0;
 208      if( $this->iObj != null ) {
 209          $m = $this->iObj[0]->GetAbsHeight($this->img);
 210          for($i=1; $i<count($this->iObj); ++$i) {
 211          $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img));
 212          }
 213      }
 214      return $m;        
 215      }
 216      
 217      // Get the maximum used line number (vertical position) for bars
 218      function GetBarMaxLineNumber() {
 219      $m=0;
 220      if( $this->iObj != null ) {
 221          $m = $this->iObj[0]->GetLineNbr();
 222          for($i=1; $i<count($this->iObj); ++$i) {
 223          $m=max($m,$this->iObj[$i]->GetLineNbr());
 224          }
 225      }
 226      return $m;
 227      }
 228      
 229      // Get the minumum and maximum used dates for all bars
 230      function GetBarMinMax() {
 231      $max=$this->scale->NormalizeDate($this->iObj[0]->GetMaxDate());
 232      $min=$this->scale->NormalizeDate($this->iObj[0]->GetMinDate());
 233      for($i=1; $i<count($this->iObj); ++$i) {
 234          $max=Max($max,$this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate()));
 235          $min=Min($min,$this->scale->NormalizeDate($this->iObj[$i]->GetMinDate()));
 236      }
 237      $minDate = date("Y-m-d",$min);
 238      $min = strtotime($minDate);
 239      $maxDate = date("Y-m-d",$max);
 240      $max = strtotime($maxDate);    
 241      return array($min,$max);
 242      }
 243  
 244      // Stroke the gantt chart
 245      function Stroke($aStrokeFileName="") {    
 246  
 247      // Should we autoscale dates?
 248      if( !$this->scale->IsRangeSet() ) {
 249          list($min,$max) = $this->GetBarMinMax();
 250          $this->scale->SetRange($min,$max);
 251      }
 252          
 253      if( $this->img->img == null ) {
 254          // The predefined left, right, top, bottom margins.
 255          // Note that the top margin might incease depending on
 256          // the title.
 257          $lm=30;$rm=30;$tm=20;$bm=30;            
 258          if( BRAND_TIMING ) $bm += 10;
 259              
 260          // First find out the height            
 261          $n=$this->GetBarMaxLineNumber()+1;
 262          $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
 263          $height=$n*((1+$this->iLabelVMarginFactor)*$m);            
 264              
 265          // Add the height of the scale titles            
 266          $h=$this->scale->GetHeaderHeight();
 267          $height += $h;
 268  
 269          // Calculate the top margin needed for title and subtitle
 270          if( $this->title->t != "" ) {
 271          $tm += $this->title->GetFontHeight($this->img);
 272          }
 273          if( $this->subtitle->t != "" ) {
 274          $tm += $this->subtitle->GetFontHeight($this->img);
 275          }
 276  
 277          // ...and then take the bottom and top plot margins into account
 278          $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin;
 279              
 280          // Now find the minimum width for the chart required
 281          $fw=$this->scale->day->GetFontWidth($this->img)+4;
 282          $nd=$this->scale->GetNumberOfDays();
 283          if( !$this->scale->IsDisplayDay() ) {
 284                  // If we don't display the individual days we can shrink the
 285                  // scale a little bit. This is a little bit pragmatic at the 
 286                  // moment and should be re-written to take into account
 287                  // a) What scales exactly are shown and 
 288                  // b) what format do they use so we know how wide we need to
 289                  // make each scale text space at minimum.
 290          $fw /= 2;
 291          if( !$this->scale->IsDisplayWeek() ) {
 292              $fw /= 1.8;
 293          }
 294          }
 295              
 296          // Now determine the width for the activity titles column
 297          // This is complicated by the fact that the titles may have
 298          // tabs. In that case we also need to calculate the individual
 299          // tab positions based on the width of the individual columns
 300              
 301          $titlewidth = $this->GetMaxLabelWidth();
 302                          
 303          // Now get the total width taking 
 304          // titlewidth, left and rigt margin, dayfont size 
 305          // into account
 306          $width = $titlewidth + $nd*$fw + $lm+$rm;
 307                          
 308          $this->img->CreateImgCanvas($width,$height);            
 309          $this->img->SetMargin($lm,$rm,$tm,$bm);
 310      }
 311          
 312      // Should we start from the top or just spread the bars out even over the
 313      // available height
 314      $this->scale->SetVertLayout($this->iLayout);            
 315      if( $this->iLayout == GANTT_FROMTOP ) {
 316          $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
 317          $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor));
 318      }
 319      // If it hasn't been set find out the maximum line number
 320      if( $this->scale->iVertLines == -1 ) 
 321          $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1;     
 322          
 323      $maxwidth=max($this->GetMaxLabelWidth(),$this->scale->tableTitle->GetWidth($this->img));
 324      $this->scale->SetLabelWidth($maxwidth*(1+$this->iLabelHMarginFactor));
 325      $this->StrokePlotArea();
 326      $this->scale->Stroke();
 327      $this->StrokePlotBox();
 328          
 329      for($i=0; $i<count($this->iObj); ++$i) {
 330          $this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2));
 331          $this->iObj[$i]->Stroke($this->img,$this->scale);
 332      }
 333          
 334      $this->StrokeTitles();
 335      $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);                
 336      }
 337  }
 338  
 339  //===================================================
 340  // CLASS TextProperty
 341  // Description: Holds properties for a text
 342  //===================================================
 343  class TextProperty {
 344      var $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10;
 345      var $iColor="black";
 346      var $iShow=true;
 347      var $iText="";
 348      var $iHAlign="left",$iVAlign="bottom";
 349      
 350  //---------------
 351  // CONSTRUCTOR    
 352      function TextProperty($aTxt="") {
 353      $this->iText = $aTxt;
 354      }        
 355      
 356  //---------------
 357  // PUBLIC METHODS    
 358      function Set($aTxt) {
 359      $this->iText = $aTxt;
 360      }
 361      
 362      // Set text color
 363      function SetColor($aColor) {
 364      $this->iColor = $aColor;
 365      }
 366      
 367      function HasTabs() {
 368      return substr_count($this->iText,"\t") > 0;
 369      }
 370      
 371      // Get number of tabs in string
 372      function GetNbrTabs() {
 373      substr_count($this->iText,"\t");
 374      }
 375      
 376      // Set alignment
 377      function Align($aHAlign,$aVAlign="bottom") {
 378      $this->iHAlign=$aHAlign;
 379      $this->iVAlign=$aVAlign;
 380      }
 381      
 382      // Specify font
 383      function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
 384      $this->iFFamily = $aFFamily;
 385      $this->iFStyle     = $aFStyle;
 386      $this->iFSize     = $aFSize;
 387      }
 388      
 389      // Get width of text. If text contains several columns separated by
 390      // tabs then return both the total width as well as an array with a 
 391      // width for each column.
 392      function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) {
 393      if( strlen($this->iText)== 0 ) return;
 394      $tmp = split("\t",$this->iText);
 395      $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
 396      if( count($tmp) <= 1 || !$aUseTabs ) {
 397          return $aImg->GetTextWidth($this->iText);
 398      }
 399      else {
 400          $tot=0;
 401          for($i=0; $i<count($tmp); ++$i) {
 402          $res[$i] = $aImg->GetTextWidth($tmp[$i]);
 403          $tot += $res[$i]*$aTabExtraMargin;
 404          }
 405          return array($tot,$res);
 406      }
 407      }
 408      
 409      // Get total height of text
 410      function GetHeight($aImg) {
 411      $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
 412      return $aImg->GetFontHeight();
 413      }
 414      
 415      // Unhide/hide the text    
 416      function Show($aShow) {
 417      $this->iShow=$aShow;
 418      }
 419      
 420      // Stroke text at (x,y) coordinates. If the text contains tabs then the
 421      // x parameter should be an array of positions to be used for each successive
 422      // tab mark. If no array is supplied then the tabs will be ignored.
 423      function Stroke($aImg,$aX,$aY) {
 424      if( $this->iShow ) {
 425          $aImg->SetColor($this->iColor);
 426          $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
 427          $aImg->SetTextAlign($this->iHAlign,$this->iVAlign);            
 428          if( $this->GetNbrTabs() <= 1 || !is_array($aX) ) {
 429                  // Get rid of any "\t" characters and stroke string
 430          $aImg->StrokeText($aX,$aY,str_replace("\t"," ",$this->iText));
 431          }
 432          else {
 433          $tmp = split("\t",$this->iText);
 434          $n = min(count($tmp),count($aX));
 435          for($i=0; $i<$n; ++$i) {
 436              $aImg->StrokeText($aX[$i],$aY,$tmp[$i]);
 437          }    
 438          }
 439      }
 440      }
 441  }
 442  
 443  //===================================================
 444  // CLASS HeaderProperty
 445  // Description: Data encapsulating class to hold property 
 446  // for each type of the scale headers
 447  //===================================================
 448  class HeaderProperty {
 449      var $iTitleVertMargin=3,$iFFamily=FF_FONT0,$iFStyle=FS_NORMAL,$iFSize=8;
 450      var $iFrameColor="black",$iFrameWeight=1;
 451      var $iShowLabels=true,$iShowGrid=true;
 452      var $iBackgroundColor="white";
 453      var $iWeekendBackgroundColor="lightgray",$iSundayTextColor="red"; // these are only used with day scale
 454      var $iTextColor="black";
 455      var $iLabelFormStr="%d";
 456      var $grid,$iStyle=0;
 457  
 458  //---------------
 459  // CONSTRUCTOR    
 460      function HeaderProperty() {
 461      $this->grid = new LineProperty();
 462      }
 463  
 464  //---------------
 465  // PUBLIC METHODS        
 466      function Show($aShow) {
 467      $this->iShowLabels = $aShow;
 468      }
 469      
 470      function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
 471      $this->iFFamily = $aFFamily;
 472      $this->iFStyle     = $aFStyle;
 473      $this->iFSize     = $aFSize;
 474      }
 475  
 476      function SetFontColor($aColor) {
 477      $this->iTextColor = $aColor;
 478      }
 479      
 480      function GetFontHeight($aImg) {
 481      $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
 482      return $aImg->GetFontHeight();
 483      }
 484  
 485      function GetFontWidth($aImg) {
 486      $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
 487      return $aImg->GetFontWidth();
 488      }
 489      
 490      function SetStyle($aStyle) {
 491      $this->iStyle = $aStyle;
 492      }
 493      
 494      function SetBackgroundColor($aColor) {
 495      $this->iBackgroundColor=$aColor;
 496      }
 497  
 498      function SetFrameWeight($aWeight) {
 499      $this->iFrameWeight=$aWeight;
 500      }
 501  
 502      function SetFrameColor($aColor) {
 503      $this->iFrameColor=$aColor;
 504      }
 505      
 506      // Only used by day scale
 507      function SetWeekendColor($aColor) {
 508      $this->iWeekendBackgroundColor=$aColor;
 509      }
 510      
 511      // Only used by day scale
 512      function SetSundayFontColor($aColor) {
 513      $this->iSundayTextColor=$aColor;
 514      }
 515      
 516      function SetTitleVertMargin($aMargin) {
 517      $this->iTitleVertMargin=$aMargin;
 518      }
 519      
 520      function SetLabelFormatString($aStr) {
 521      $this->iLabelFormStr=$aStr;
 522      }
 523  }
 524  
 525  //===================================================
 526  // CLASS GanttScale
 527  // Description: Responsible for calculating and showing
 528  // the scale in a gantt chart. This includes providing methods for
 529  // converting dates to position in the chart as well as stroking the
 530  // date headers (days, week, etc).
 531  //===================================================
 532  class GanttScale {
 533      var $day,$week,$month,$year;
 534      var $divider,$dividerh,$tableTitle;
 535      var $iStartDate=-1,$iEndDate=-1;    
 536      // Number of gantt bar position (n.b not necessariliy the same as the number of bars)
 537      // we could have on bar in position 1, and one bar in position 5 then there are two
 538      // bars but the number of bar positions is 5
 539      var $iVertLines=-1;    
 540      // The width of the labels (defaults to the widest of all labels)
 541      var $iLabelWidth;    
 542      // Out image to stroke the scale to
 543      var $iImg;    
 544      var $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black";
 545      var $iTableHeaderFrameWeight=1;
 546      var $iAvailableHeight=-1,$iVertSpacing=-1,$iVertHeaderSize=-1;
 547      var $iDateLocale;
 548      var $iVertLayout=GANTT_EVEN;
 549      var $iTopPlotMargin=10,$iBottomPlotMargin=15;
 550      var $iUsePlotWeekendBackground=true;
 551      
 552  //---------------
 553  // CONSTRUCTOR    
 554      function GanttScale(&$aImg) {
 555      $this->iImg = &$aImg;        
 556      $this->iDateLocale = new DateLocale();
 557      $this->day = new HeaderProperty();
 558      $this->day->grid->SetColor("gray");
 559  
 560      $this->week = new HeaderProperty();
 561      $this->week->SetLabelFormatString("w%d");
 562      $this->week->SetFont(FF_FONT1);
 563  
 564      $this->month = new HeaderProperty();
 565      $this->month->SetFont(FF_FONT1,FS_BOLD);
 566  
 567      $this->year = new HeaderProperty();
 568      $this->year->SetFont(FF_FONT1,FS_BOLD);        
 569          
 570      $this->divider=new LineProperty();
 571      $this->dividerh=new LineProperty();        
 572      $this->tableTitle=new TextProperty();
 573      }
 574      
 575  //---------------
 576  // PUBLIC METHODS    
 577      // Specify what headers should be visible
 578      function ShowHeaders($aFlg) {
 579      $this->day->Show($aFlg & GANTT_HDAY);
 580      $this->week->Show($aFlg & GANTT_HWEEK);
 581      $this->month->Show($aFlg & GANTT_HMONTH);
 582      $this->year->Show($aFlg & GANTT_HYEAR);
 583  
 584      // Make some default settings of gridlines whihc makes sense
 585      if( $aFlg & GANTT_HWEEK ) {
 586          $this->month->grid->Show(false);
 587          $this->year->grid->Show(false);
 588      }
 589      }
 590      
 591      // Should the weekend background stretch all the way down in the plotarea
 592      function UseWeekendBackground($aShow) {
 593      $this->iUsePlotWeekendBackground = $aShow;
 594      }
 595      
 596      // Have a range been specified?
 597      function IsRangeSet() {
 598      return $this->iStartDate!=-1 && $this->iEndDate!=-1;
 599      }
 600      
 601      // Should the layout be from top or even?
 602      function SetVertLayout($aLayout) {
 603      $this->iVertLayout = $aLayout;
 604      }
 605      
 606      // Which locale should be used?
 607      function SetDateLocale($aLocale) {
 608      $this->iDateLocale->Set($aLocale);
 609      }
 610      
 611      // Number of days we are showing
 612      function GetNumberOfDays() {
 613      return round(($this->iEndDate-$this->iStartDate)/SECPERDAY)+1;
 614      }
 615      
 616      // The widthj of the actual plot area
 617      function GetPlotWidth() {
 618      $img=$this->iImg;
 619      return $img->width - $img->left_margin - $img->right_margin;
 620      }
 621  
 622      // Specify the width of the titles(labels) for the activities
 623      // (This is by default set to the minimum width enought for the
 624      // widest title)
 625      function SetLabelWidth($aLabelWidth) {
 626      $this->iLabelWidth=$aLabelWidth;
 627      }
 628      
 629      // Do we show day scale?
 630      function IsDisplayDay() {
 631      return $this->day->iShowLabels;
 632      }
 633      
 634      // Do we show week scale?
 635      function IsDisplayWeek() {
 636      return $this->week->iShowLabels;
 637      }
 638      
 639      // Do we show month scale?
 640      function IsDisplayMonth() {
 641      return $this->month->iShowLabels;
 642      }
 643      
 644      // Do we show year scale?
 645      function IsDisplayYear() {
 646      return $this->year->iShowLabels;
 647      }
 648  
 649      // Specify spacing (in percent of bar height) between activity bars
 650      function SetVertSpacing($aSpacing) {
 651      $this->iVertSpacing = $aSpacing;
 652      }
 653  
 654      // Specify scale min and max date either as timestamp or as date strings
 655      // Always round to the nearest week boundary
 656      function SetRange($aMin,$aMax) {
 657      $this->iStartDate = $this->NormalizeDate($aMin);
 658      $this->iEndDate = $this->NormalizeDate($aMax);
 659          
 660      // Get day in week Sun=0
 661      $ds=strftime("%w",$this->iStartDate);
 662      $de=strftime("%w",$this->iEndDate);
 663          
 664      if( $ds==0 ) $ds=7;
 665      if( $de==0 ) $de=7;
 666      
 667      // We want to start on Monday
 668      $this->iStartDate -= SECPERDAY*($ds-1);
 669          
 670      // We want to end on a Sunday
 671      $this->iEndDate += SECPERDAY*(7-$de);
 672      }
 673  
 674      // Specify background for the table title area (upper left corner of the table)    
 675      function SetTableTitleBackground($aColor) {
 676      $this->iTableHeaderBackgroundColor = $aColor;
 677      }
 678  
 679  ///////////////////////////////////////
 680  // PRIVATE Methods
 681      
 682      // Determine the height of all the scale headers combined
 683      function GetHeaderHeight() {
 684      $img=$this->iImg;
 685      $height=1;
 686      if( $this->day->iShowLabels ) {
 687          $height += $this->day->GetFontHeight($img);
 688          $height += $this->day->iTitleVertMargin;
 689      }
 690      if( $this->week->iShowLabels ) {
 691          $height += $this->week->GetFontHeight($img);
 692          $height += $this->week->iTitleVertMargin;
 693      }
 694      if( $this->month->iShowLabels ) {
 695          $height += $this->month->GetFontHeight($img);
 696          $height += $this->month->iTitleVertMargin;
 697      }
 698      if( $this->year->iShowLabels ) {
 699          $height += $this->year->GetFontHeight($img);
 700          $height += $this->year->iTitleVertMargin;
 701      }
 702      return $height;
 703      }
 704      
 705      // Get width (in pisels) for a single day
 706      function GetDayWidth() {
 707      return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();    
 708      }
 709  
 710      // Nuber of days in a year
 711      function GetNumDaysInYear($aYear) {
 712      if( $this->IsLeap($aYear) )
 713          return 366;
 714      else
 715          return 365;
 716      }
 717      
 718      // Get day number in year    
 719      function GetDayNbrInYear($aDate) {
 720      return 0+strftime("%j",$aDate);
 721      }
 722      
 723      // Get week number 
 724      function GetWeekNbr($aDate) {
 725      // We can't use the internal strftime() since it gets the weeknumber
 726      // wrong since it doesn't follow ISO.
 727      // Even worse is that this works differently if we are on a Windows
 728      // or UNIX box (it even differs between UNIX boxes how strftime()
 729      // is natively implemented)
 730      //
 731      // Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant
 732      // version of Week Nbr calculation. 
 733          
 734      $day = $this->NormalizeDate($aDate);
 735          
 736      /*-------------------------------------------------------------------------
 737        According to ISO-8601 :
 738        "Week 01 of a year is per definition the first week that has the Thursday in this year,
 739        which is equivalent to the week that contains the fourth day of January.
 740        In other words, the first week of a new year is the week that has the majority of its
 741        days in the new year."
 742            
 743        Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!!
 744            
 745        day of year             = date("z", $day) + 1
 746        offset to thursday      = 3 - (date("w", $day) + 6) % 7
 747        first thursday of year  = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7
 748        week number             = (thursday's day of year - first thursday's day of year) / 7 + 1
 749        ---------------------------------------------------------------------------*/
 750           
 751      $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7);              // take week's thursday
 752      $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7;
 753            
 754      return $week;
 755      }
 756      
 757      // Is year a leap year?
 758      function IsLeap($aYear) {
 759      // Is the year a leap year?
 760      //$year = 0+date("Y",$aDate);
 761      if( $aYear % 4 == 0)
 762          if( !($aYear % 100 == 0) || ($aYear % 400 == 0) )
 763          return true;
 764      return false;
 765      }
 766  
 767      // Get current year
 768      function GetYear($aDate) {
 769      return 0+Date("Y",$aDate);
 770      }
 771      
 772      // Return number of days in a year
 773      function GetNumDaysInMonth($aMonth,$aYear) {
 774      $days=array(31,28,31,30,31,30,31,31,30,31,30,31);
 775      $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31);
 776      if( $this->IsLeap($aYear))
 777          return $daysl[$aMonth];
 778      else
 779          return $days[$aMonth];
 780      }
 781      
 782      // Get day in month
 783      function GetMonthDayNbr($aDate) {
 784      return 0+strftime("%d",$aDate);
 785      }
 786  
 787      // Get day in year
 788      function GetYearDayNbr($aDate) {
 789      return 0+strftime("%j",$aDate);
 790      }
 791      
 792      // Get month number
 793      function GetMonthNbr($aDate) {
 794      return 0+strftime("%m",$aDate);
 795      }
 796      
 797      // Translate a date to screen coordinates    (horizontal scale)
 798      function TranslateDate($aDate) {
 799      $aDate = $this->NormalizeDate($aDate);
 800      $img=$this->iImg;        
 801      //print date('d-m-Y H:i:s',$aDate).'--'.date('d-m-Y H:i:s',$this->iEndDate)."<br>";
 802      if( $aDate < $this->iStartDate || $aDate > $this->iEndDate )
 803          JpGraphError::Raise("<b>JpGraph Error:</b> Date is outside specified scale range.");
 804      return ($aDate-$this->iStartDate)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;;
 805      }
 806  
 807      // Get screen coordinatesz for the vertical position for a bar        
 808      function TranslateVertPos($aPos) {
 809      $img=$this->iImg;
 810      $ph=$this->iAvailableHeight;
 811      if( $aPos > $this->iVertLines ) 
 812          JpGraphError::Raise("<b>JpGraph Error:</b> Illegal vertical position $aPos");
 813      if( $this->iVertLayout == GANTT_EVEN ) {
 814          // Position the top bar at 1 vert spacing from the scale
 815          return round($img->top_margin + $this->iVertHeaderSize +  ($aPos+1)*$this->iVertSpacing);
 816      }
 817      else {
 818          // position the top bar at 1/2 a vert spacing from the scale
 819          return round($img->top_margin + $this->iVertHeaderSize  + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing);        
 820      }
 821      }
 822      
 823      // What is the vertical spacing?
 824      function GetVertSpacing() {
 825      return $this->iVertSpacing;
 826      }
 827                      
 828      // Convert a date to timestamp
 829      function NormalizeDate($aDate) {
 830      if( is_string($aDate) )
 831          return strtotime($aDate);
 832      elseif( is_int($aDate) || is_float($aDate) )
 833          return $aDate;
 834      else
 835          JpGraphError::Raise("<b>JpGraph Error:</b> Unknown date format in GanttScale ($aDate).");
 836      }
 837  
 838      // Stroke the day scale (including gridlines)            
 839      function StrokeDays($aYCoord) {
 840      $wdays=$this->iDateLocale->GetDayAbb();    
 841      $img=$this->iImg;    
 842      $daywidth=$this->GetDayWidth();
 843      $xt=$img->left_margin+$this->iLabelWidth;
 844      $yt=$aYCoord+$img->top_margin;        
 845      if( $this->day->iShowLabels ) {
 846          $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize);
 847          $xb=$img->width-$img->right_margin;
 848          $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight;
 849          $img->SetColor($this->day->iBackgroundColor);
 850          $img->FilledRectangle($xt,$yt,$xb,$yb);
 851  
 852          $img->SetColor($this->day->grid->iColor);
 853          $x = $xt;
 854          $img->SetTextAlign("center");
 855          for($i=0; $i<$this->GetNumberOfDays(); ++$i, $x+=$daywidth) {
 856          $day=$i%7;
 857          if( $day==5 ) {
 858              $img->PushColor($this->day->iWeekendBackgroundColor);
 859              if( $this->iUsePlotWeekendBackground )
 860              $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+2*$daywidth,$img->height-$img->bottom_margin);                        
 861              else
 862              $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+2*$daywidth,$yb-$this->day->iFrameWeight);
 863              $img->PopColor();
 864          }
 865          if( $day==6 ) 
 866              $img->PushColor($this->day->iSundayTextColor);
 867          else
 868              $img->PushColor($this->day->iTextColor);
 869          $img->StrokeText(round($x+$daywidth/2+1),
 870                   round($yb-$this->day->iTitleVertMargin),
 871                   $wdays[$i%7]);
 872          $img->PopColor();                        
 873          $img->Line($x,$yt,$x,$yb);
 874          $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
 875          }            
 876          $img->SetColor($this->day->iFrameColor);
 877          $img->SetLineWeight($this->day->iFrameWeight);
 878          $img->Rectangle($xt,$yt,$xb,$yb);
 879          return $yb - $img->top_margin;
 880      }
 881      return $aYCoord;
 882      }
 883      
 884      // Stroke week header and grid
 885      function StrokeWeeks($aYCoord) {
 886      $wdays=$this->iDateLocale->GetDayAbb();    
 887      $img=$this->iImg;    
 888      $weekwidth=$this->GetDayWidth()*7;
 889      $xt=$img->left_margin+$this->iLabelWidth;
 890      $yt=$aYCoord+$img->top_margin;        
 891      $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize);
 892      $xb=$img->width-$img->right_margin;
 893      $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight;
 894          
 895      $week = $this->iStartDate;
 896      $weeknbr=$this->GetWeekNbr($week);
 897      if( $this->week->iShowLabels ) {
 898          $img->SetColor($this->week->iBackgroundColor);
 899          $img->FilledRectangle($xt,$yt,$xb,$yb);
 900          $img->SetColor($this->week->grid->iColor);
 901          $x = $xt;
 902          if( $this->week->iStyle==WEEKSTYLE_WNBR ) {
 903          $img->SetTextAlign("center");
 904          $txtOffset = $weekwidth/2+1;
 905          }
 906          elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY || $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ) {
 907          $img->SetTextAlign("left");
 908          $txtOffset = 2;
 909          }
 910          else
 911          JpGraphError::Raise("<b>JpGraph Error:</b>Unknown formatting style for week.");
 912                  
 913          for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) {
 914          $img->PushColor($this->week->iTextColor);
 915                  
 916          if( $this->week->iStyle==WEEKSTYLE_WNBR )
 917              $txt = sprintf($this->week->iLabelFormStr,$weeknbr);
 918          elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY )
 919              $txt = date("j/n",$week);
 920          elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ) {
 921              $monthnbr = date("n",$week)-1;
 922              $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr);
 923              $txt = Date("j",$week)." ".$shortmonth;
 924          }
 925                  
 926          $img->StrokeText(round($x+$txtOffset),round($yb-$this->week->iTitleVertMargin),$txt);
 927                  
 928          $week += 7*SECPERDAY;
 929          $weeknbr = $this->GetWeekNbr($week);
 930          $img->PopColor();                        
 931          $img->Line($x,$yt,$x,$yb);
 932          $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
 933          }            
 934          $img->SetColor($this->week->iFrameColor);
 935          $img->SetLineWeight($this->week->iFrameWeight);
 936          $img->Rectangle($xt,$yt,$xb,$yb);
 937          return $yb-$img->top_margin;
 938      }
 939      return $aYCoord;
 940      }    
 941      
 942      // Format the mont scale header string
 943      function GetMonthLabel($aMonthNbr,$year) {
 944      $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr);
 945      $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr);
 946      switch($this->month->iStyle) {
 947          case MONTHSTYLE_SHORTNAME:
 948          $m=$sn;
 949          break;
 950          case MONTHSTYLE_LONGNAME:
 951          $m=$ln;
 952          break;
 953          case MONTHSTYLE_SHORTNAMEYEAR2:
 954          $m=$sn." '".substr("".$year,2);
 955          break;
 956          case MONTHSTYLE_SHORTNAMEYEAR4:
 957          $m=$sn." ".$year;
 958          break;
 959          case MONTHSTYLE_LONGNAMEYEAR2:
 960          $m=$ln." '".substr("".$year,2);
 961          break;
 962          case MONTHSTYLE_LONGNAMEYEAR4:
 963          $m=$ln." ".$year;
 964          break;
 965      }
 966      return $m;
 967      }
 968      
 969      // Stroke month scale and gridlines
 970      function StrokeMonths($aYCoord) {
 971      if( $this->month->iShowLabels ) {
 972          $monthnbr = $this->GetMonthNbr($this->iStartDate)-1; 
 973          $img=$this->iImg;    
 974          
 975          $xt=$img->left_margin+$this->iLabelWidth;
 976          $yt=$aYCoord+$img->top_margin;        
 977          $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize);
 978          $xb=$img->width-$img->right_margin;
 979          $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight;
 980              
 981          $img->SetColor($this->month->iBackgroundColor);
 982          $img->FilledRectangle($xt,$yt,$xb,$yb);
 983  
 984          $img->SetLineWeight($this->month->grid->iWeight);
 985          $img->SetColor($this->month->iTextColor);
 986          $year = 0+strftime("%Y",$this->iStartDate);
 987          $img->SetTextAlign("center");
 988          $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1);
 989          // Is it enough space to stroke the first month?
 990          $monthName = $this->GetMonthLabel($monthnbr,$year);
 991          if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) {
 992          $img->SetColor($this->month->iTextColor);                
 993          $img->StrokeText(round($xt+$monthwidth/2+1),
 994                   round($yb-$this->month->iTitleVertMargin),
 995                   $monthName);
 996          }
 997          $x = $xt + $monthwidth;
 998          while( $x < $xb ) {
 999          $img->SetColor($this->month->grid->iColor);                
1000          $img->Line($x,$yt,$x,$yb);
1001          $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
1002          $monthnbr++;
1003          if( $monthnbr==12 ) {
1004              $monthnbr=0;
1005              $year++;
1006          }
1007          $monthName = $this->GetMonthLabel($monthnbr,$year);
1008          $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year);                
1009          if( $x + $monthwidth < $xb )
1010              $w = $monthwidth;
1011          else
1012              $w = $xb-$x;
1013          if( $w >= 1.2*$img->GetTextWidth($monthName) ) {
1014              $img->SetColor($this->month->iTextColor);                
1015              $img->StrokeText(round($x+$w/2+1),
1016                       round($yb-$this->month->iTitleVertMargin),$monthName);
1017          }
1018          $x += $monthwidth;
1019          }    
1020          $img->SetColor($this->month->iFrameColor);
1021          $img->SetLineWeight($this->month->iFrameWeight);
1022          $img->Rectangle($xt,$yt,$xb,$yb);            
1023          return $yb-$img->top_margin;
1024      }
1025      return $aYCoord;
1026      }
1027  
1028      // Stroke year scale and gridlines
1029      function StrokeYears($aYCoord) {
1030      if( $this->year->iShowLabels ) {
1031          $year = $this->GetYear($this->iStartDate); 
1032          $img=$this->iImg;    
1033          
1034          $xt=$img->left_margin+$this->iLabelWidth;
1035          $yt=$aYCoord+$img->top_margin;        
1036          $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize);
1037          $xb=$img->width-$img->right_margin;
1038          $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight;
1039              
1040          $img->SetColor($this->year->iBackgroundColor);
1041          $img->FilledRectangle($xt,$yt,$xb,$yb);
1042          $img->SetLineWeight($this->year->grid->iWeight);
1043          $img->SetTextAlign("center");
1044          if( $year == $this->GetYear($this->iEndDate) )
1045          $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1);
1046          else
1047          $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1);
1048              
1049          // The space for a year must be at least 20% bigger than the actual text 
1050          // so we allow 10% margin on each side
1051          if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) {
1052          $img->SetColor($this->year->iTextColor);                
1053          $img->StrokeText(round($xt+$yearwidth/2+1),
1054                   round($yb-$this->year->iTitleVertMargin),
1055                   $year);
1056          }
1057          $x = $xt + $yearwidth;
1058          while( $x < $xb ) {
1059          $img->SetColor($this->year->grid->iColor);                
1060          $img->Line($x,$yt,$x,$yb);
1061          $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
1062          $year += 1;
1063          $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year);                
1064          if( $x + $yearwidth < $xb )
1065              $w = $yearwidth;
1066          else
1067              $w = $xb-$x;
1068          if( $w >= 1.2*$img->GetTextWidth("".$year) ) {
1069              $img->SetColor($this->year->iTextColor);
1070              $img->StrokeText(round($x+$w/2+1),
1071                       round($yb-$this->year->iTitleVertMargin),
1072                       $year);
1073          }
1074          $x += $yearwidth;
1075          }
1076          $img->SetColor($this->year->iFrameColor);
1077          $img->SetLineWeight($this->year->iFrameWeight);
1078          $img->Rectangle($xt,$yt,$xb,$yb);            
1079          return $yb-$img->top_margin;
1080      }
1081      return $aYCoord;
1082      }
1083      
1084      // Stroke table title (upper left corner)
1085      function StrokeTableHeaders($aYBottom) {
1086      $img=$this->iImg;
1087      $xt=$img->left_margin;
1088      $yt=$img->top_margin;
1089      $xb=$xt+$this->iLabelWidth;
1090      $yb=$aYBottom+$img->top_margin;
1091          
1092      $img->SetColor($this->iTableHeaderBackgroundColor);
1093      $img->FilledRectangle($xt,$yt,$xb,$yb);
1094      $this->tableTitle->Align("center","center");
1095      $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+($yb-$yt)/2);        
1096      $img->SetColor($this->iTableHeaderFrameColor);
1097      $img->SetLineWeight($this->iTableHeaderFrameWeight);
1098      $img->Rectangle($xt,$yt,$xb,$yb);
1099          
1100      // Draw the vertical dividing line
1101      $this->divider->Stroke($img,$xb,$yt,$xb,$img->height-$img->bottom_margin);
1102          
1103      // Draw the horizontal dividing line        
1104      $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb);        
1105      }
1106  
1107      // Main entry point to stroke scale
1108      function Stroke() {
1109      if( !$this->IsRangeSet() )
1110          JpGraphError::Raise("<b>JpGraph Error:</b> Gantt scale has not been specified.");
1111      $img=$this->iImg;
1112          
1113      // Stroke all headers. Aa argument we supply the offset from the
1114      // top which depends on any previous headers
1115      $offy=$this->StrokeYears(0);
1116      $offm=$this->StrokeMonths($offy);
1117      $offw=$this->StrokeWeeks($offm);
1118      $offd=$this->StrokeDays($offw);
1119  
1120      // We stroke again in case days also have gridlines that may have
1121      // overwritten the weeks gridline (or month/year). It may seem that we should have logic
1122      // in the days routine instead but this is much easier and wont make to much
1123      // of an performance impact.
1124      $this->StrokeWeeks($offm);        
1125      $this->StrokeMonths($offy);        
1126      $this->StrokeYears(0);
1127      $this->StrokeTableHeaders($offd);
1128          
1129      // Now we can calculate the correct scaling factor for each vertical position
1130      $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd;        
1131      $this->iVertHeaderSize = $offd;
1132      if( $this->iVertSpacing == -1 )
1133          $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines;
1134      }    
1135  }
1136  
1137  //===================================================
1138  // CLASS GanttPlotObject
1139  // The common signature for a Gantt object
1140  //===================================================
1141  class GanttPlotObject {
1142      var $iVPos=0;                    // Vertical position
1143      var $iLabelLeftMargin=2;    // Title margin
1144      var $iStart="";                // Start date
1145      var $title,$caption;
1146      var $iCaptionMargin=5;
1147          
1148      function GanttPlotObject() {
1149      $this->title = new TextProperty();
1150      $this->title->Align("left","center");
1151      $this->caption = new TextProperty();
1152      }
1153      
1154      function GetMinDate() {
1155      return $this->iStart;
1156      }
1157  
1158      function GetMaxDate() {
1159      return $this->iStart;
1160      }
1161      
1162      function SetCaptionMargin($aMarg) {
1163      $this->iCaptionMargin=$aMarg;
1164      }
1165  
1166  #    function GetLineNbr() {
1167  #    return 0;
1168  #    }
1169  
1170      function GetAbsHeight($aImg) {
1171      return 0;
1172      }
1173      
1174      function GetLineNbr() {
1175      return $this->iVPos;
1176      }
1177  
1178      function SetLabelLeftMargin($aOff) {
1179      $this->iLabelLeftMargin=$aOff;
1180      }        
1181  }
1182  
1183  //===================================================
1184  // CLASS Progress
1185  // Holds parameters for the progress indicator 
1186  // displyed within a bar
1187  //===================================================
1188  class Progress {
1189      var $iProgress=-1, $iColor="black", $iPattern=GANTT_SOLID;
1190      var $iDensity=98, $iHeight=0.65; 
1191      
1192      function Set($aProg) {
1193      if( $aProg < 0.0 || $aProg > 1.0 )
1194          JpGraphError::Raise("<b>JpGraph Error:</b> Progress value must in range [0, 1]");
1195      $this->iProgress = $aProg;
1196      }
1197  
1198      function SetPattern($aPattern,$aColor="blue",$aDensity=98) {        
1199      $this->iPattern = $aPattern;
1200      $this->iColor = $aColor;
1201      $this->iDensity = $aDensity;
1202      }
1203      
1204      function SetHeight($aHeight) {
1205      $this->iHeight = $aHeight;
1206      }
1207  }
1208  
1209  //===================================================
1210  // CLASS GanttBar
1211  // Responsible for formatting individual gantt bars
1212  //===================================================
1213  class GanttBar extends GanttPlotObject {
1214      var $iEnd;
1215      var $iHeightFactor=0.5;
1216      var $iFillColor="white",$iFrameColor="blue";
1217      var $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black";
1218      var $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95;
1219      var $leftMark,$rightMark;
1220      var $progress;
1221      
1222  //---------------
1223  // CONSTRUCTOR    
1224      function GanttBar($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) {
1225      parent::GanttPlotObject();    
1226      $this->iStart = $aStart;    
1227      // Is the end date given as a date or as number of days added to start date?
1228      if( is_string($aEnd) )
1229          $this->iEnd = strtotime($aEnd)+SECPERDAY;
1230      // check for unix timestamp
1231      elseif($aEnd > 1000000)
1232          $this->iEnd = $aEnd;
1233      elseif(is_int($aEnd) || is_float($aEnd) ) 
1234          $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY);
1235      $this->iVPos = $aPos;
1236      $this->iHeightFactor = $aHeightFactor;
1237      $this->title->Set($aLabel);
1238      $this->caption = new TextProperty($aCaption);
1239      $this->caption->Align("left","center");
1240      $this->leftMark =new PlotMark();
1241      $this->leftMark->Hide();
1242      $this->rightMark=new PlotMark();
1243      $this->rightMark->Hide();
1244      $this->progress = new Progress();
1245      }
1246      
1247  //---------------
1248  // PUBLIC METHODS    
1249      function SetShadow($aShadow=true,$aColor="gray") {
1250      $this->iShadow=$aShadow;
1251      $this->iShadowColor=$aColor;
1252      }
1253          
1254      function GetMaxDate() {
1255      return $this->iEnd;
1256      }
1257      
1258      function SetHeight($aHeight) {
1259      $this->iHeightFactor = $aHeight;
1260      }
1261  
1262      function SetColor($aColor) {
1263      $this->iFrameColor = $aColor;
1264      }
1265  
1266      function SetFillColor($aColor) {
1267      $this->iFillColor = $aColor;
1268      }
1269  
1270      function GetAbsHeight($aImg) {
1271      if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) {
1272          $m=-1;
1273          if( is_int($this->iHeightFactor) )
1274          $m = $this->iHeightFactor;
1275          if( $this->leftMark->show ) 
1276          $m = max($m,$this->leftMark->width*2);
1277          if( $this->rightMark->show ) 
1278          $m = max($m,$this->rightMark->width*2);
1279          return $m;
1280      }
1281      else
1282          return -1;
1283      }
1284      
1285      function SetPattern($aPattern,$aColor="blue",$aDensity=95) {        
1286      $this->iPattern = $aPattern;
1287      $this->iPatternColor = $aColor;
1288      $this->iPatternDensity = $aDensity;
1289      }
1290  
1291      function Stroke($aImg,$aScale) {
1292      $factory = new RectPatternFactory();
1293      $prect = $factory->Create($this->iPattern,$this->iPatternColor);
1294      $prect->SetDensity($this->iPatternDensity);
1295          
1296      // If height factor is specified as a float between 0,1 then we take it as meaning
1297      // percetage of the scale width between horizontal line.
1298      // If it is an integer > 1 we take it to mean the absolute height in pixels
1299      if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1)
1300          $vs = $aScale->GetVertSpacing()*$this->iHeightFactor;
1301      elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor<200)
1302          $vs = $this->iHeightFactor;
1303      else
1304          JpGraphError::Raise("<b>JpGraph Error:</b>Specified height (".$this->iHeightFactor.") for gantt bar is out of range.");
1305  
1306      $xt = $aScale->TranslateDate($aScale->NormalizeDate($this->iStart));
1307      $xb = $aScale->TranslateDate($aScale->NormalizeDate($this->iEnd));
1308      $yt = $aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2);
1309      $yb = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2);
1310  
1311      $prect->ShowFrame(false);
1312      $prect->SetBackground($this->iFillColor);
1313      if( $this->iShadow ) {
1314          $aImg->SetColor($this->iFrameColor);
1315          $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor);                
1316          $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2));                
1317          $prect->Stroke($aImg);
1318      }
1319      else {    
1320          $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1));                
1321          $prect->Stroke($aImg);
1322          $aImg->SetColor($this->iFrameColor);
1323          $aImg->Rectangle($xt,$yt,$xb,$yb);
1324      }
1325      if( $this->progress->iProgress > 0 ) {
1326          $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor);
1327          $prog->SetDensity($this->progress->iDensity);
1328          $barheight = ($yb-$yt+1);
1329          if( $this->iShadow ) 
1330          $barheight -= $this->iShadowWidth;
1331          $progressheight = floor($barheight*$this->progress->iHeight);
1332          $marg = ceil(($barheight-$progressheight)/2);
1333          $pos = new Rectangle($xt,
1334          $yt + $marg,
1335          ($xb-$xt+1)*$this->progress->iProgress,
1336          $barheight-2*$marg);
1337          $prog->SetPos($pos);
1338          $prog->Stroke($aImg);
1339      }
1340          
1341      $middle = round($yt+($yb-$yt)/2);
1342      $this->title->Stroke($aImg,$aImg->left_margin+$this->iLabelLeftMargin,$middle);
1343      $this->leftMark->Stroke($aImg,$xt,$middle);
1344      $this->rightMark->Stroke($aImg,$xb,$middle);
1345      $margin = $this->iCaptionMargin;
1346      if( $this->rightMark->show ) 
1347          $margin += $this->rightMark->GetWidth();
1348  
1349      $this->caption->Stroke($aImg,$xb+$margin,$middle);
1350      }
1351  }
1352  
1353  //===================================================
1354  // CLASS MileStone
1355  // Responsible for formatting individual milestones
1356  //===================================================
1357  class MileStone extends GanttPlotObject {
1358      var $mark;
1359      
1360  //---------------
1361  // CONSTRUCTOR    
1362      function MileStone($aVPos,$aLabel,$aDate,$aCaption="") {
1363      GanttPlotObject::GanttPlotObject();
1364      $this->caption->Set($aCaption);
1365      $this->caption->Align("left","center");
1366      $this->caption->SetFont(FF_FONT1,FS_BOLD);
1367      $this->title->Set($aLabel);
1368      $this->title->SetColor("darkred");
1369      $this->mark = new PlotMark();
1370      $this->mark->SetWidth(10);
1371      $this->mark->SetType(MARK_DIAMOND);
1372      $this->mark->SetColor("darkred");
1373      $this->mark->SetFillColor("darkred");
1374      $this->iVPos = $aVPos;
1375      $this->iStart = $aDate;
1376      }
1377      
1378  //---------------
1379  // PUBLIC METHODS    
1380      
1381      function GetAbsHeight($aImg) {
1382      return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
1383      }
1384          
1385      function Stroke($aImg,$aScale) {
1386      // Put the mark in the middle at the middle of the day
1387      $x = $aScale->TranslateDate($aScale->NormalizeDate($this->iStart)+SECPERDAY/2);
1388      $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2);
1389          
1390      $this->mark->Stroke($aImg,$x,$y);        
1391      $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y);
1392      $x=$aImg->left_margin+$this->iLabelLeftMargin;
1393      $this->title->Stroke($aImg,$x,$y);
1394      }
1395  }
1396  
1397  
1398  //===================================================
1399  // CLASS GanttVLine
1400  // Responsible for formatting individual milestones
1401  //===================================================
1402  
1403  class GanttVLine extends GanttPlotObject {
1404  
1405      var $iLine,$title_margin=3;
1406      var $iDayOffset=0;    // Defult to left edge of day
1407      
1408  //---------------
1409  // CONSTRUCTOR    
1410      function GanttVLine($aDate,$aTitle="",$aColor="black",$aWeight=3,$aStyle="dashed") {
1411      GanttPlotObject::GanttPlotObject();
1412      $this->iLine = new LineProperty();
1413      $this->iLine->SetColor($aColor);
1414      $this->iLine->SetWeight($aWeight);
1415      $this->iLine->SetStyle($aStyle);
1416      $this->iStart = $aDate;
1417      $this->title->Set($aTitle);
1418      }
1419  
1420  //---------------
1421  // PUBLIC METHODS    
1422  
1423      function SetDayOffset($aOff=0.5) {
1424      if( $aOff < 0.0 || $aOff > 1.0 )
1425          JpGraphError::Raise("<b>JpGraph Error:</b> Offset for vertical line must be in range [0,1]");
1426      $this->iDayOffset = $aOff;
1427      }
1428      
1429      function SetTitleMargin($aMarg) {
1430      $this->title_margin = $aMarg;
1431      }
1432      
1433      function Stroke($aImg,$aScale) {
1434      $x = $aScale->TranslateDate($aScale->NormalizeDate($this->iStart)+$this->iDayOffset*SECPERDAY);    
1435      $y1 = $aScale->iVertHeaderSize+$aImg->top_margin;
1436      $y2 = $aImg->height - $aImg->bottom_margin;
1437      $this->iLine->Stroke($aImg,$x,$y1,$x,$y2);
1438      $this->title->Align("center","top");
1439      $this->title->Stroke($aImg,$x,$y2+$this->title_margin);
1440      }    
1441  }
1442  
1443  // <EOF>
1444  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7