home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol04 / 02b / project / classes / ganttwin.cls < prev    next >
Text File  |  1988-11-24  |  6KB  |  236 lines

  1. /* Maintain a Gantt chart in a Window. The GanttWindow is
  2.    responsible for drawing the project.
  3.  
  4.    GanttWindow descends from the Window class and inherits all
  5.    of its methods and instance variables.
  6. */!!
  7.  
  8. inherit(Window, #GanttWindow, #(project     /* the project */
  9. activities  /* in the project */
  10. barWidth    /* width of a unit */
  11. barHeight   /* based on scrnsize */
  12. activHeight /* bar + dead space */), 2, nil)!!
  13.  
  14. now(GanttWindowClass)!!
  15.  
  16. /* Return the name of this class's MS-Windows window class
  17.   either for registration or new window creation. */
  18. Def wndClass(self)
  19. { ^"GanttWindow"  }!!
  20.  
  21. /* Create a new window class Struct.
  22.    Change the cursor to a cross.  */
  23. Def newWClass(self, lpCl, lpIcon | wc)
  24. { wc := newWClass(self:WindowClass, lpCl, lpIcon);
  25.   putWord(wc, Call LoadCursor(0, IDC_CROSS), 14);
  26.   ^wc;
  27. } !!
  28.  
  29. now(GanttWindow)!!
  30.  
  31. /* For a Task, draw a critical bar.  Make sure we don't draw
  32.    draw over the titles if the node hasn't been hooked up yet.
  33.    Uses early binding, direct Windows calls for speed. */
  34. Def  drawTask(self, aNode, x, y, hDC | startX)
  35. {
  36.    startX := max(GW_STARTX, x - asInt(getTime(aNode)*barWidth));
  37.    Call FillRect(hDC, rect(startX:Int, y, x, y + barHeight), 
  38.           stock(BLACK_BRUSH));
  39. }!!
  40.  
  41. /* Create the window using a regular window style. */
  42. Def  create(self, par, wName, rect, style)
  43.   ^create(self:Window, par, wName, rect, 
  44.      WS_POPUPWIND);
  45. }!!
  46.  
  47. /* If we close, be sure to tell the parent. 
  48.    For testing a standalone Gantt chart delete this method. */
  49. Def  close(self)
  50. {
  51.   close(self:Window);
  52.   closeGantt(parent);  /* assumes parent is a ProjWindow */
  53. }!!
  54.  
  55. /* Make sure the parent window knows that the project
  56.    has changed. */
  57. Def  dirty(self)
  58. {
  59.   invalidate(self);
  60.   invalidate(parent);
  61. }!!
  62.  
  63. /* Set up a dummy project, menus and the method table. */
  64. Def  init(self)
  65. {  
  66.   setProject(self, new(Project));
  67.   recalc(project);  
  68.   setMenus(self);
  69.   setResolution(self);
  70. }!!
  71.  
  72. /* Set the resolution for the size of bars, spacing etc.
  73.    For CGA, bars should be smaller. */
  74. Def  setResolution(self | hDC, ts)
  75. {
  76.   hDC := getContext(self);
  77.   ts := textSize(self, hDC);
  78.   releaseContext(self, hDC);
  79.   barHeight := y(ts);
  80.   activHeight := asInt(1.25 * y(ts));
  81. }!!
  82.  
  83. /* Handle menu commands. */
  84. Def  command(self, wp, lp)
  85. {
  86.   select
  87.     case wp == GW_HELP
  88.       help(self);
  89.     endCase
  90.     
  91.     /* use the same accelerator to open and close */
  92.     
  93.     case wp == PW_VIEW_GANTT  
  94.       close(self);
  95.     endCase
  96.   endSelect;
  97. }!!
  98.  
  99. /* Load menu resources. */
  100. Def  setMenus(self)
  101. {
  102.   loadMenu(self, "GWMenus");
  103.   setMenu(self, hMenu);
  104. }
  105. !!
  106.  
  107. /* Display help information from resource file. */
  108. Def  help(self | dlg)
  109. {
  110.   dlg := new(Dialog);
  111.   checkRunModal(dlg, GW_HELP_BOX, self);
  112. }!!
  113.  
  114. /* Draw a Milestone diamond in the window. */
  115. Def  drawMilestone(self, aNode, x, y, hDC)
  116. {
  117.     draw(new(Polygon,
  118.       tuple(
  119.         point(x, y),                 /* top */
  120.         point(x - GW_DMWIDTH, 
  121.               y + barHeight/2),      /* left */
  122.         point(x, y + barHeight),     /* bottom */
  123.         point(x + GW_DMWIDTH,
  124.               y + barHeight/2)       /* right */
  125.       )), hDC);
  126. }!!
  127.  
  128. /* Draw a slack bar in the window. 
  129.    Uses direct Windows call for speed. */
  130. Def  drawSlackBar(self, aNode, x, y, hDC | hBrush)
  131. {
  132.    Call FillRect(hDC, rect(x:Int, y, 
  133.                 x + asInt(getSlack(aNode)*barWidth),
  134.                 y + barHeight), stock(GRAY_BRUSH)
  135.            );
  136. }!!
  137.  
  138. /* Draw text info in the window. */
  139. Def  drawTextInfo(self, aNode, x, y, hDC | str)
  140. {
  141.       if critical(aNode)
  142.         str := "*" + getName(aNode);
  143.       else
  144.         str := " " + getName(aNode);
  145.       endif;
  146.       Call TextOut(hDC, x, y, str, size(str));  
  147. }!!
  148.  
  149. /* Set the bar width so that the chart fits in the window. 
  150.    Adjust in case it's very large or very small. */
  151. Def  setBarWidth(self, time)
  152. {
  153.   barWidth := asInt((right(clientRect(self)) - GW_STARTX) / 
  154.                 (time + 1));
  155.   barWidth := min(75, max(2, barWidth));
  156. }!!
  157.  
  158. /* Set the project. */
  159. Def  setProject(self, aProject)
  160. {
  161.   project := aProject;
  162.   recalc(project);
  163. }!!
  164.  
  165. /* See if the user has clicked on a bar in the chart.
  166.    If so, bring up a dialog for editing. */
  167. Def  WM_LBUTTONDOWN(self, wP, lP | idx)
  168. {
  169.   idx:= (y(asPoint(lP)) - barHeight) / activHeight;
  170.   if idx <= size(activities) - 1 
  171.     if editInfo(activities[idx]) == IDOK
  172.       dirty(self);
  173.     endif;
  174.   else
  175.     beep();
  176.   endif;
  177. }!!
  178.  
  179. /* Draw the axis for the window. 
  180.    Uses direct Windows calls for speed. */
  181. Def  drawAxis(self, hDC | endX, endY, str)
  182. {
  183.     endX := GW_STARTX + barWidth * 
  184.                (max(2,asInt(getTime(project)+getSlack(project)))) ;  
  185.     endY := activHeight * (size(nodes(project))+1); 
  186.        
  187.     /* draw a rectangle for x and y axis */ 
  188.     
  189.     Call Rectangle(hDC, GW_STARTX, GW_STARTY, endX, endY+1);
  190.         
  191.     /* draw notches on the x axis */    
  192.     do(overBy(GW_STARTX, endX, barWidth),
  193.       {using(i) 
  194.         Call MoveTo(hDC, i, GW_STARTY);           /* top */
  195.         Call LineTo(hDC, i, GW_STARTY + GW_NOTCH);
  196.         Call MoveTo(hDC, i,endY);                 /* bot */
  197.         Call LineTo(hDC, i, endY - GW_NOTCH);
  198.     });
  199.     str := asString(getEarlyStart(project));
  200.     Call TextOut(hDC, GW_STARTX, endY + 10, str, size(str));  
  201. }!!
  202.  
  203. /* Respond to MS-Windows messages to paint the window. 
  204.    Show the project as a Gantt chart. 
  205.    Draw the axis, then for each node draw the graphics. */
  206. Def  paint(self, hDC | y, t)
  207. {
  208.   setBarWidth(self, asInt(getTime(project)+getSlack(project)));
  209.   activities := sortedActivities(project);
  210.   
  211.   drawAxis(self, hDC);
  212.   y := barHeight;         /* starting positions for bars */
  213.   
  214.   do(activities,
  215.     {using(aNode) 
  216.    
  217.      drawTextInfo(self, aNode, 10, y, hDC);
  218.      
  219.       /* make a temp to avoid calculating starting position */
  220.       t := max(GW_STARTX, GW_STARTX + barWidth *
  221.             asInt(getEarlyStart(aNode)-getEarlyStart(project)+getTime(aNode)));
  222.       
  223.       /* draw a slack bar if necessary. */  
  224.       if getSlack(aNode) > 0  
  225.         drawSlackBar(self, aNode, t, y, hDC)
  226.       endif;
  227.  
  228.       draw(aNode, self, t, y, hDC);  /* node knows how */
  229.  
  230.       y := y + activHeight;     /* move down for next bar */
  231.   });
  232. }!!
  233.  
  234.  
  235.