Gantt chart の表示プログラム

/*    Program making the Gantt chart from the shceduling data  */
/*    by K. Tatsumi 2005.4.1                                   */
//
//  gcc gant.c -lm -L/usr/X11R6/lib -lX11 -I/usr/X11R6/include
//  2005/4/7 K.Tatsumi
/*  ver.2 再描画を出来るように改変
    XW_Graph でglobal 変数として定義してあった gDip, gGc, gWin をローカル変数に修正
    XW_RGB, XW_Line.. など多くの関数の修正が必要になった。掃除が必要?

 ver.3
  2005/4/8 K.Tatsumi
  mode 表示を可能にする。rctngl を三次元配列にして、再描画の計算量を減らした。

  2005/4/8 K.Tatsumi
  ver.4 
   windows を複数あけられるように修正。XW_graph を掃除して、必要な関数のみ gantt.c に追加。
   gantt.h を作成し、prototype宣言追加。

  2005/4/9 K.Tatsumi
  ver.5 リソースが0の仕事が描画されてしまうバグを修正(scd2caht()関数の修正)
  ver.6 画面の揺らぎを修正。Pixmap を使用して一括して画面の再描画を行う
        Backgrond が黒になってしまう理由が分からず、大きな白のBOXの描画でごまかし?
        "q" を押すと修了。
   4/10 K.Tatsumi
      Bug 修正
        ・COLOR_MAX, LABEL_MAX のdefine 定義をやめて直接 20 を用いる。
        ・show_all: XW_Text部分のモード表示修正
            XW_Text( gWin, label[CH_info[i].mode_num-1], ]
                                       -->  XW_Text( gWin, label[CH_info[i].mode_num],
        ・gantt.c(旧version の sgannt)の G_rctngl[][][] の初期化し忘れ修正
  ver 6.2 2005/4/12 K.Tatsumi
       1. 数値表示labelの上20を、無制限になるよう変更
          make_label 関数で必要な領域を確保して数字のASCIIコードを設定
       2. 構造 G_data を作成し、 x_size, y_size, height, h_graph, mode_fg をまとめて管理
           show_all等、表示関数の引き数などが変更になる。
       3. 一度は消した COLOR_MAX 復活させ、もし 必要色数がCOLOR_MAXを超えたら全色をランダムに
         割り振るよう修正
       4. int *** mk_rctngl(int rrs, int r_max, int time); を作成。G_rctngl の領域確保、初期
     化を行う
 */
       

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "config.h"
#include "gantt.h"
// #include "matrix.h"

Display *gDisp;
int gScreen;
Font gFont;
XEvent gEv;

//  Attributes of GC
XSetWindowAttributes gGcAtt;

// base GC
GC gGc;

// Set selected colors to the each activities   
void setColor(int *color[3], Size *pb_size){
  int i, k;
  int Dcolor[COLOR_MAX][3] = //
    {{0, 36, 85},{0, 109, 85},{0, 182, 85},{0, 182, 255},//
      {36,182, 170}, {255,109, 0},{0, 0, 255},{255,36, 0},//
      {255, 0,85},{128, 0, 128},{128, 255, 0}, {23, 170, 182},//
      {36,182, 170}, {255,109, 0},{24, 182, 25},{25,255, 182},//
      {0, 0, 170}, { 0,109, 0},{255, 12, 255},{0, 0, 255}};
  for(i=0; i< pb_size->j_num; i++){
    for(k=0; k<3; k++){
      *(color[k]+i) = Dcolor[i][k];
    }
  }
}

void setRandomColor(int *color[3], Size *pb_size){
  int i, k;
  
  srand(time(NULL));
  for(i=0; ij_num; i++){
    for(k=0; k<3; k++){
      *(color[k]+i) = rand()%255;
      //    printf("c%d",j[i].color[k]);
    }
    //  printf("\n");
  }
}

int measure_Tmax(chartinfo CH_info[], int j_num){
  int i, max =0;
  for(i=0; ir_num; k++){
    for(t=0; tt_lngth; t++) {
      pre_y=0;
      for(i=1; i<=pb_size->j_num; i++) {
        r_count=0;
        if(CH_info[i].st == t && CH_info[i].rr_de[k] != 0){
          for(r=pre_y; rr_bound[k]; r++) {
            if(G_rctngl[k][r][t]==0){
              for(rt=t; rt<(CH_info[i].st+CH_info[i].pt); rt++) {
                G_rctngl[k][r][rt]=CH_info[i].job_num;
              }
              r_count++;
            }
            if( r_count == CH_info[i].rr_de[k]){
              r++;
              pre_y = r;
              break;
            }
          }
	  if(r_count != CH_info[i].rr_de[k]){
            printf("Require resources goes over the bound!");
            exit(-1);
          }
        }
      }
    }
  }
  return 0;
}

//
// Select Color
//
unsigned long XW_RGB( int r, int g, int b )
{
  Colormap cmap;
  XColor   col;

  cmap = DefaultColormap( gDisp, 0 );
  col.red   = 256 * r;
  col.green = 256 * g;
  col.blue  = 256 * b;
  XAllocColor( gDisp, cmap, &col );
  return  col.pixel ;
}

void XW_SetColor( int r, int g, int b )
{
  XSetForeground( gDisp, gGc, XW_RGB( r, g, b) );
}

// Open window
void XW_EndXWindow( Window gWin)
{
  XFreeGC( gDisp, gGc );
  XDestroyWindow( gDisp, gWin );
}


// Drawing Functions
void XW_Cls( Window gWin )
{
  XClearWindow( gDisp, gWin );
  XFlush( gDisp );
}

void XW_Text( Window gWin,char *str, int x, int y )
{
  XDrawString( gDisp, gWin, gGc, x, y, str, strlen(str) );
}

void XW_Line( Window gWin, int x1, int y1, int x2, int y2 )
{
  XSetLineAttributes( gDisp, gGc, 1, LineSolid, CapRound, JoinRound );
  XDrawLine( gDisp, gWin, gGc, x1, y1, x2, y2 );
}

void XW_BoxFill(Window gWin, int x1, int y1, int x2, int y2 )
{
  XSetLineAttributes( gDisp, gGc, 1, LineSolid, CapRound, JoinRound );
  XFillRectangle( gDisp, gWin, gGc, x1, y1, x2-x1, y2-y1 );  
}

void Draw_axes(Window gWin, Size *pb_size, G_data *gdata, int k){
  int i;
  
  XW_SetColor(182, 202, 225); // Set Palebule 
  for(i=1; iy_scale ; i++){ 
    XW_Line( gWin, (ORG), gdata->h_graph-(SCALE)*i-(ORG), //
             gdata->x_size-1-(SCALE-ORG), gdata->h_graph-(SCALE)*i-(ORG) );
  }
  // the graduation axes for Y-axis
  
  for(i=1; ix_scale ; i++){
    XW_Line( gWin, (SCALE)*i+(ORG), (SCALE-ORG)+gdata->h_graph - gdata->y_size, (SCALE)*i+(ORG), gdata->h_graph-(ORG) ); 
    // the graduation axes for X-axis
  }
  // Drawing axes 
  XW_SetColor( 0, 0, 0 ); // Set Black
  XW_Line( gWin, ORG, gdata->h_graph-(ORG), gdata->x_size-1, gdata->h_graph-(ORG)); // X-axis
  XW_Line( gWin, ORG, gdata->h_graph-gdata->y_size, ORG, gdata->h_graph-(ORG)); // Y-axis
  
  XW_SetColor( 0, 0, 0 ); // Set Black
  XW_Line( gWin, (ORG), gdata->h_graph-(SCALE)*(pb_size->r_bound[k])-(ORG),//
           gdata->x_size-1-(SCALE-ORG), gdata->h_graph-(SCALE)*(pb_size->r_bound[k])-(ORG) ); // Bound of the resource k
  
  for(i=4;ix_scale-4; i=i+5){  // the graduation of time
    XW_Text( gWin, gdata->label[i], ORG+(i+0.5)*(SCALE), gdata->h_graph-(ORG)*0.2);
    //    XW_Text( gWin, label[i], ORG+(0+0.5)*(SCALE), y_size-10 ); 
    XW_Text( gWin, "T", ORG+(pb_size->t_lngth-0.5)*(SCALE), gdata->h_graph-(ORG)*0.2);
  }
  for(i=2;iy_scale-2; i=i+3){  // the graduation of resource
    if(i>9){
      XW_Text( gWin, gdata->label[i], (ORG)*0.2, gdata->h_graph-(ORG)-(i+0.5)*(SCALE));
    }else{
      XW_Text( gWin, gdata->label[i], (ORG)*0.5, gdata->h_graph-(ORG)-(i+0.5)*(SCALE));
    }
    XW_Text( gWin, "R", (ORG)*0.5, ORG+gdata->h_graph-gdata->y_size);
  }
}


int gantt( chartinfo *CH_info, int jobs, int rrs, ivector rr_avail, int fg){
  int i, r, t, k, r_max=0;
  int ***G_rctngl; // a unit rectangle in the chart
  int all_y;
  int *color[3];
  int offset = (SCALE)*5;
  char string[10];
  Size pb_size;
  G_data gdata;
  
  Window gWin;
  Pixmap gPmap;
  KeySym key;
  
  pb_size.r_bound=(int *)malloc(sizeof(int)*rrs);
  pb_size.j_num = jobs-2;
  pb_size.r_num = rrs;
  
  for(r_max=0, i=0; i (pb_size.j_num+1)){
    gdata.height = all_y*(SCALE);
  }else{
    gdata.height = (pb_size.j_num+1)*(SCALE); 
  }
  
  gDisp = XOpenDisplay( NULL );  /* Xサーバに接続する */
  gScreen = DefaultScreen( gDisp );  /* スクリーン設定 */
  
  gWin = XCreateSimpleWindow(   /* ウィンドウを開く */
                                gDisp,                      /* Xサーバ */
                                RootWindow(gDisp,gScreen),   /* 親ウィンドウ */
                                0, 0,                     /* 表示時の左上隅の座標 x, y */
                                (gdata.x_size)+(offset), gdata.height, /* ウィンドウの幅と高さ */ 
                                //			     gdata.height, wide, /* ウィンドウの幅と高さ */ 
                                1, BlackPixel(gDisp,gScreen),/* ボーダーの幅と色 */
                                WhitePixel(gDisp,gScreen)    /* ウィンドウの背景色 */
                                );
  gPmap = XCreatePixmap(gDisp, gWin, (gdata.x_size)+(offset), gdata.height,
                        DefaultDepth(gDisp, 0));
  XSetStandardProperties(gDisp, gWin, "Gantt chart", "CanttChart",
                         None, NULL, 0, NULL);
  
  XSelectInput( gDisp, gWin, ExposureMask  |
                KeyPressMask );
  XMapWindow( gDisp, gWin );  /* ウィンドウのマッピング */
  
  //  XW_initWin(gWin, (gdata.x_size)+(offset), all_y*(SCALE));
  
  gGc = DefaultGC( gDisp, gScreen ); /* グラフィックコンテキストの設定 */
  XSetForeground( gDisp, gGc, BlackPixel(gDisp,gScreen) ); /* 描画色設定 */
  XSetBackground( gDisp, gGc, WhitePixel(gDisp,gScreen));
  
  if(fg == 0){   // Set colors to each activies at random
    setRandomColor(color, &pb_size);
  }else{
    if( COLOR_MAX < pb_size.j_num ){
      printf("colors are set at random!");
      setRandomColor(color, &pb_size);
    }else{
      setColor(color, &pb_size);
    }
  }
  
  while( 1 ){
    XNextEvent( gDisp, &gEv );
    switch( gEv.type ){
    case Expose:
      XW_SetColor( 255,255,255 ); // 白色
      XW_BoxFill( gPmap, 0,  0, (gdata.x_size)+(offset), gdata.height);
      
      // each rectangle initialization
      gdata.h_graph = 0;
      for(k=0; kt_lngth; t++){
    for(r=0; rr_bound[l]; r++){
      i = G_rctngl[l][r][t];
      if(i == 0){
      }else{
        XW_SetColor( *(color[0]+i-1), *(color[1]+i-1),*(color[2]+i-1) ); // 
        XW_BoxFill( gWin, ORG+ t*(SCALE), gdata->h_graph-(r+1)*(SCALE)-(ORG), //
                    (ORG)+ (t+1)*(SCALE), gdata->h_graph-(ORG)-r*(SCALE));
        XW_SetColor( 255,255,255 ); // 白色
        if(gdata->mode_fg==1){
          XW_Text( gWin, gdata->label[CH_info[i].mode_num], ORG+(t+0.4)*(SCALE), gdata->h_graph-(r+0.3)*(SCALE)-(ORG));
        }else{
          if( i < 10){
            XW_Text( gWin, gdata->label[i-1], ORG+(t+0.4)*(SCALE), gdata->h_graph-(r+0.3)*(SCALE)-(ORG));
          }
          else{
            XW_Text( gWin, gdata->label[i-1], ORG+(t+0.2)*(SCALE), gdata->h_graph-(r+0.3)*(SCALE)-(ORG));
          }
        }
      }
    }
  }
  return 0;
}

int show_description(Window gWin, int *color[3], G_data *gdata, int j_num){
  int i;
  for(i=0; ix_size+ORG, (SCALE)*(i+0.5), //
                gdata->x_size+ORG+(SCALE), (SCALE)*(i+1.5));
    XW_SetColor( 0, 0, 0 ); // Black
    XW_Text( gWin, "JOB", gdata->x_size+ORG+(SCALE)*1.2, (SCALE)*(i+1.3));
    XW_Text( gWin, gdata->label[i], gdata->x_size+ORG+(SCALE)*2.5, (SCALE)*(i+1.3));
  }
  return 0;
}

int ***mk_rctngl(int rrs, int r_max, int mtime){
  int t, r, i;
  int ***G_rctngl;

  G_rctngl = (int ***)malloc(rrs*sizeof(int **));
  for(t=0; t0){
    for(i=0; i