Drawing the diagram

From TaskDepender
Jump to: navigation, search
(Created page with "''This page describes how the GUI can draw the diagram.'' == Introduction == == Design == ----")
 
 
Line 1: Line 1:
 
''This page describes how the [[GUI]] can draw the diagram.''
 
''This page describes how the [[GUI]] can draw the diagram.''
  
== Introduction ==
+
== Description ==
  
 
== Design ==
 
== Design ==
 +
 +
 +
== Implementation ==
 +
 +
=== Draw diagram ===
 +
 +
<syntaxhighlight lang="cpp">
 +
void TMainForm::DrawDiagram(void)
 +
{
 +
  // Clear
 +
  DiagramImage->Canvas->Brush->Color = clWhite;
 +
  DiagramImage->Canvas->FillRect(TRect(0, 0, DiagramImage->Width, DiagramImage->Height));
 +
 +
  DrawDeliverables();
 +
  DrawTasks();
 +
  DrawLines();
 +
 +
  if( DiagramCursorState == "Selecting" )
 +
  {
 +
    DiagramImage->Canvas->Brush->Style = bsClear;
 +
    DiagramImage->Canvas->Pen->Color = clBlack;
 +
    DiagramImage->Canvas->Pen->Width = 1;
 +
    DiagramImage->Canvas->Pen->Style = psDash;
 +
    DiagramImage->Canvas->Rectangle(BeginXpos,BeginYpos,EndXpos,EndYpos);
 +
  }
 +
 +
  DiagramImage->Repaint();
 +
}
 +
</syntaxhighlight>
 +
 +
=== Draw tasks ===
 +
 +
<syntaxhighlight lang="cpp">
 +
void TMainForm::DrawTasks(void)
 +
{
 +
  TaskC *task;
 +
  TStringList *taskName;
 +
  uint  h;
 +
  uint  w;
 +
 +
  task = Admin->TasksAdmin->First();
 +
 +
  // All tasks belonging to the current container.
 +
 +
  for( uint k=0; k<Admin->TasksAdmin->NumElements; k++)
 +
  {
 +
    if( task->Container != Admin->CurrentContainerId )
 +
    {
 +
      // Task does not belong to this level.
 +
      task = task->next();
 +
      continue;
 +
    }
 +
 +
    taskName = new TStringList();
 +
    taskName->Delimiter = DELIMITER_CHAR;
 +
    taskName->QuoteChar = QUOTE_CHAR;
 +
    taskName->DelimitedText = AnsiString( task->Name );
 +
 +
    // -- Determine required rectangle to wrap around the text --
 +
    task->Height = 0;
 +
    task->Width  = 0;
 +
    for(int line=0; line<taskName->Count; line++ )
 +
    {
 +
      task->Height += DiagramImage->Canvas->TextHeight(taskName->Strings[line]);
 +
 +
      w = DiagramImage->Canvas->TextWidth(taskName->Strings[line]);
 +
      if( task->Width < w )
 +
      {
 +
        // Maximum width.
 +
        task->Width  = w;
 +
      }
 +
    }
 +
 +
    // Set colors.
 +
    DiagramImage->Canvas->Pen->Style = psSolid;
 +
    DiagramImage->Canvas->Pen->Color = clBlack;
 +
    DiagramImage->Canvas->Pen->Width = 1;
 +
 +
    if( task->NumContainedElements > 0 )
 +
    {
 +
      DiagramImage->Canvas->Brush->Color = clBlue;
 +
      DiagramImage->Canvas->Font->Color  = clWhite;
 +
    }
 +
    else
 +
    {
 +
      DiagramImage->Canvas->Brush->Color = clAqua;
 +
      DiagramImage->Canvas->Font->Color  = clBlack;
 +
    }
 +
    DiagramImage->Canvas->Rectangle(
 +
      task->Position.X-task->Width/2-Edge,
 +
      task->Position.Y-task->Height/2-Edge,
 +
      task->Position.X+task->Width/2+Edge,
 +
      task->Position.Y+task->Height/2+Edge );
 +
 +
    // Output the name lines.
 +
    h = 0;
 +
    for( int line=0;line < taskName->Count; line++ )
 +
    {
 +
      w = DiagramImage->Canvas->TextWidth(taskName->Strings[line]);
 +
      DiagramImage->Canvas->TextOut(
 +
        task->Position.X-w/2,
 +
        task->Position.Y-task->Height/2+h,
 +
        taskName->Strings[line] );
 +
      h += DiagramImage->Canvas->TextHeight(taskName->Strings[line]);
 +
    }
 +
 +
    // Output the resource
 +
 +
    if( task->ResourceId != NULL )
 +
    {
 +
      int s = DiagramImage->Canvas->Font->Size;
 +
      DiagramImage->Canvas->Font->Size = 6;
 +
 +
      DiagramImage->Canvas->Font->Color  = clBlack;
 +
      DiagramImage->Canvas->Brush->Color  = clWhite;
 +
      w = DiagramImage->Canvas->TextWidth(AnsiString(task->ResourceId));
 +
      h = DiagramImage->Canvas->TextHeight(AnsiString(task->ResourceId));
 +
      DiagramImage->Canvas->TextOut(
 +
        task->Position.X-w/2,
 +
        task->Position.Y-task->Height/2-1.3*h,
 +
        AnsiString(task->ResourceId) );
 +
 +
      DiagramImage->Canvas->Font->Size = s;
 +
    }
 +
 +
    if( Admin->SelectedTasksIds->Find(task->Id) )
 +
    {
 +
      // Draw selection lines around selected task.
 +
      DiagramImage->Canvas->Brush->Color = clRed;
 +
      DiagramImage->Canvas->PenPos.x = task->Position.X-task->Width/2;
 +
      DiagramImage->Canvas->PenPos.y = task->Position.Y-task->Height/2;
 +
 +
      // Topleft
 +
      DiagramImage->Canvas->Ellipse( task->Position.X-task->Width/2-3-Edge,
 +
                                    task->Position.Y-task->Height/2-3-Edge,
 +
                                    task->Position.X-task->Width/2+3-Edge,
 +
                                    task->Position.Y-task->Height/2+3-Edge );
 +
      // TopRight
 +
      DiagramImage->Canvas->Ellipse( task->Position.X+task->Width/2-3+Edge,
 +
                                    task->Position.Y-task->Height/2-3-Edge,
 +
                                    task->Position.X+task->Width/2+3+Edge,
 +
                                    task->Position.Y-task->Height/2+3-Edge );
 +
 +
      // Bottom right
 +
      DiagramImage->Canvas->Ellipse( task->Position.X+task->Width/2-3+Edge,
 +
                                    task->Position.Y+task->Height/2-3+Edge,
 +
                                    task->Position.X+task->Width/2+3+Edge,
 +
                                    task->Position.Y+task->Height/2+3+Edge );
 +
 +
      // Bottom left
 +
      DiagramImage->Canvas->Ellipse( task->Position.X-task->Width/2-3-Edge,
 +
                                    task->Position.Y+task->Height/2-3+Edge,
 +
                                    task->Position.X-task->Width/2+3-Edge,
 +
                                    task->Position.Y+task->Height/2+3+Edge );
 +
 +
    }
 +
 +
 +
    task = task->next();
 +
 +
    delete taskName;
 +
  }
 +
 +
  // Print name of container task.
 +
 +
  TaskC *containerTask = Admin->TasksAdmin->FindTask(Admin->CurrentContainerId);
 +
  if( containerTask != NULL )
 +
  {
 +
    // Inside a container.
 +
 +
    // Set color
 +
    DiagramImage->Canvas->Brush->Color = clWhite;
 +
   
 +
    taskName = new TStringList();
 +
    taskName->Delimiter = DELIMITER_CHAR;
 +
    taskName->QuoteChar = QUOTE_CHAR;
 +
    taskName->DelimitedText = AnsiString( containerTask->Name );
 +
 +
    AnsiString  nameString = "";
 +
    for( int i=0; i<taskName->Count; i++ )
 +
    {
 +
      nameString = nameString + " " + taskName->Strings[i];
 +
    }
 +
 +
    h = DiagramImage->Canvas->TextHeight( nameString );
 +
    w = DiagramImage->Canvas->TextWidth( nameString );
 +
 +
    DiagramImage->Canvas->TextOut( (DiagramImage->Width-w)/2, Edge, nameString );
 +
 +
    delete taskName;
 +
  }
 +
 +
}
 +
</syntaxhighlight>
 +
 +
=== Draw the deliverables ===
 +
 +
<syntaxhighlight lang="cpp">
 +
void TMainForm::DrawDeliverables(void)
 +
{
 +
 +
  TStringList *deliverableName;
 +
  uint  h;
 +
  uint  w;
 +
 +
  DeliverableC *deliverable = Admin->DeliverablesAdmin->First();
 +
 +
  // All deliverables in this container.
 +
 +
  while( deliverable != NULL )
 +
  {
 +
    if( deliverable->Container != Admin->CurrentContainerId)
 +
    {
 +
      // Deliverable does not belong to this level.
 +
      deliverable = deliverable->next();
 +
      continue;
 +
    }
 +
 +
    deliverableName = new TStringList();
 +
    deliverableName->Delimiter = DELIMITER_CHAR;
 +
    deliverableName->QuoteChar = QUOTE_CHAR;
 +
    deliverableName->DelimitedText = AnsiString( deliverable->Name );
 +
 +
    // -- Determine required size of the rectangle to wrap around the text --
 +
 +
    deliverable->Height = 0;
 +
    deliverable->Width  = 0;
 +
    for(int line=0; line<deliverableName->Count; line++ )
 +
    {
 +
      deliverable->Height += DiagramImage->Canvas->TextHeight(deliverableName->Strings[line]);
 +
 +
      w = DiagramImage->Canvas->TextWidth(deliverableName->Strings[line]);
 +
      if( deliverable->Width < w )
 +
      {
 +
        // Maximum width.
 +
        deliverable->Width  = w;
 +
      }
 +
    }
 +
 +
    // -- Set colors --
 +
 +
    DiagramImage->Canvas->Pen->Style = psSolid;
 +
    DiagramImage->Canvas->Pen->Color = clBlack;
 +
    DiagramImage->Canvas->Pen->Width = 1;
 +
 +
    if( deliverable->Available )
 +
    {
 +
      if( deliverable->CloneId == 0 )
 +
      {
 +
        DiagramImage->Canvas->Brush->Color = clGreen;
 +
        DiagramImage->Canvas->Font->Color  = clWhite;
 +
      }
 +
      else
 +
      {
 +
        DiagramImage->Canvas->Pen->Color  = clGreen;
 +
        DiagramImage->Canvas->Brush->Color = clWhite;
 +
        DiagramImage->Canvas->Font->Color  = clBlack;
 +
      }
 +
    }
 +
    else
 +
    {
 +
      // Deliverable not available yet.
 +
 +
      if( deliverable->CloneId == 0 )
 +
      {
 +
        DiagramImage->Canvas->Brush->Color = clRed;
 +
        DiagramImage->Canvas->Font->Color  = clWhite;
 +
      }
 +
      else
 +
      {
 +
        DiagramImage->Canvas->Pen->Color  = clRed;
 +
        DiagramImage->Canvas->Brush->Color = clWhite;
 +
        DiagramImage->Canvas->Font->Color  = clBlack;
 +
      }
 +
 +
      // Make edge green if link available.
 +
      if( AnsiString(deliverable->Link) != "" )
 +
      {
 +
        DiagramImage->Canvas->Font->Color  = clGreen;
 +
      }
 +
    }
 +
 +
    // -- Draw the rounded rectangle for the deliverable --
 +
   
 +
    DiagramImage->Canvas->RoundRect(
 +
      deliverable->Position.X-deliverable->Width/2-Edge,
 +
      deliverable->Position.Y-deliverable->Height/2-Edge,
 +
      deliverable->Position.X+deliverable->Width/2+Edge,
 +
      deliverable->Position.Y+deliverable->Height/2+Edge,
 +
      4*Edge, 4*Edge );
 +
 +
    // -- Deliverable or dependency indicator for clone --
 +
 +
    if( ( deliverable->CloneId != 0 ) && ( deliverable->CloneId != MaxInt) )
 +
    {
 +
      TaskC *container = Admin->TasksAdmin->FindTask(deliverable->Container);
 +
      DiagramImage->Canvas->Pen->Width = 1;
 +
      if( container->Dependencies->Find(deliverable->CloneId) )
 +
      {
 +
        // Parent of clone is a dependency of the container task.
 +
 +
        DiagramImage->Canvas->Pen->Color = clRed;
 +
 +
        DiagramImage->Canvas->MoveTo( deliverable->Position.X-7, deliverable->Position.Y+deliverable->Height/2+8 );
 +
        DiagramImage->Canvas->LineTo(deliverable->Position.X+4, deliverable->Position.Y+deliverable->Height/2+8 );
 +
 +
        DiagramImage->Canvas->LineTo(deliverable->Position.X, deliverable->Position.Y+deliverable->Height/2+6 );
 +
 +
        DiagramImage->Canvas->MoveTo( deliverable->Position.X+4, deliverable->Position.Y+deliverable->Height/2+8 );
 +
        DiagramImage->Canvas->LineTo(deliverable->Position.X, deliverable->Position.Y+deliverable->Height/2+11 );
 +
 +
        DiagramImage->Canvas->Rectangle( deliverable->Position.X+5, deliverable->Position.Y+deliverable->Height/2+8-2,
 +
                                        deliverable->Position.X+10, deliverable->Position.Y+deliverable->Height/2+8+3  );
 +
 +
      }
 +
      else
 +
      {
 +
 +
        // Parent of clone is a deliverable of the container task.
 +
 +
        DiagramImage->Canvas->Pen->Color = clGreen;
 +
 +
        DiagramImage->Canvas->Rectangle( deliverable->Position.X-7, deliverable->Position.Y+deliverable->Height/2+8-2,
 +
                                        deliverable->Position.X-2, deliverable->Position.Y+deliverable->Height/2+8+3  );
 +
 +
        DiagramImage->Canvas->MoveTo( deliverable->Position.X-2, deliverable->Position.Y+deliverable->Height/2+8 );
 +
        DiagramImage->Canvas->LineTo( deliverable->Position.X+10, deliverable->Position.Y+deliverable->Height/2+8 );
 +
 +
        DiagramImage->Canvas->LineTo(deliverable->Position.X+6, deliverable->Position.Y+deliverable->Height/2+6 );
 +
 +
        DiagramImage->Canvas->MoveTo( deliverable->Position.X+10, deliverable->Position.Y+deliverable->Height/2+8 );
 +
        DiagramImage->Canvas->LineTo(deliverable->Position.X+6, deliverable->Position.Y+deliverable->Height/2+11 );
 +
      }
 +
    }
 +
 +
    // -- Name lines --
 +
 +
    h = 0; // Keep track of the required height.
 +
    for( int line=0;line < deliverableName->Count; line++ )
 +
    {
 +
      w = DiagramImage->Canvas->TextWidth(deliverableName->Strings[line]);
 +
      DiagramImage->Canvas->TextOut(
 +
        deliverable->Position.X-w/2,
 +
        deliverable->Position.Y-deliverable->Height/2+h,
 +
        deliverableName->Strings[line] );
 +
      h += DiagramImage->Canvas->TextHeight(deliverableName->Strings[line]);
 +
    }
 +
 +
    if( deliverable->ResourceId != NULL )
 +
    {
 +
      int s = DiagramImage->Canvas->Font->Size;
 +
      DiagramImage->Canvas->Font->Size = 6;
 +
 +
      DiagramImage->Canvas->Font->Color  = clBlack;
 +
      DiagramImage->Canvas->Brush->Color  = clWhite;
 +
      w = DiagramImage->Canvas->TextWidth(AnsiString(deliverable->ResourceId));
 +
      h = DiagramImage->Canvas->TextHeight(AnsiString(deliverable->ResourceId));
 +
      DiagramImage->Canvas->TextOut(
 +
        deliverable->Position.X-w/2,
 +
        deliverable->Position.Y-deliverable->Height/2-1.3*h,
 +
        AnsiString(deliverable->ResourceId) );
 +
 +
      DiagramImage->Canvas->Font->Size = s;
 +
    }
 +
 +
    // -- Selection box --
 +
 +
    if( Admin->SelectedDeliverablesIds->Find(deliverable->Id) )
 +
    {
 +
      // Deliverable is selected, draw selection lines around selected deliverable.
 +
      DiagramImage->Canvas->Brush->Color = clRed;
 +
      DiagramImage->Canvas->Pen->Color = clBlack;
 +
      DiagramImage->Canvas->Pen->Width = 1;
 +
 +
      DiagramImage->Canvas->PenPos.x = deliverable->Position.X-deliverable->Width/2;
 +
      DiagramImage->Canvas->PenPos.y = deliverable->Position.Y-deliverable->Height/2;
 +
 +
      // Topleft
 +
      DiagramImage->Canvas->Ellipse( deliverable->Position.X-deliverable->Width/2-3-Edge,
 +
                                    deliverable->Position.Y-deliverable->Height/2-3-Edge,
 +
                                    deliverable->Position.X-deliverable->Width/2+3-Edge,
 +
                                    deliverable->Position.Y-deliverable->Height/2+3-Edge );
 +
      // TopRight
 +
      DiagramImage->Canvas->Ellipse( deliverable->Position.X+deliverable->Width/2-3+Edge,
 +
                                    deliverable->Position.Y-deliverable->Height/2-3-Edge,
 +
                                    deliverable->Position.X+deliverable->Width/2+3+Edge,
 +
                                    deliverable->Position.Y-deliverable->Height/2+3-Edge );
 +
 +
      // Bottom right
 +
      DiagramImage->Canvas->Ellipse( deliverable->Position.X+deliverable->Width/2-3+Edge,
 +
                                    deliverable->Position.Y+deliverable->Height/2-3+Edge,
 +
                                    deliverable->Position.X+deliverable->Width/2+3+Edge,
 +
                                    deliverable->Position.Y+deliverable->Height/2+3+Edge );
 +
 +
      // Bottom left
 +
      DiagramImage->Canvas->Ellipse( deliverable->Position.X-deliverable->Width/2-3-Edge,
 +
                                    deliverable->Position.Y+deliverable->Height/2-3+Edge,
 +
                                    deliverable->Position.X-deliverable->Width/2+3-Edge,
 +
                                    deliverable->Position.Y+deliverable->Height/2+3+Edge );
 +
 +
    }
 +
 +
    deliverable = deliverable->next();
 +
 +
    delete deliverableName;
 +
  }
 +
}
 +
</syntaxhighlight>
 +
 +
=== Draw lines ===
 +
 +
<syntaxhighlight lang="cpp">
 +
void TMainForm::DrawLines(void)
 +
{
 +
  // Loop through all the tasks and draw the in and output lines.
 +
 +
  TaskC        *task;
 +
  DeliverableC *deliverable;
 +
 +
  DiagramImage->Canvas->Pen->Style = psSolid;
 +
 +
  task = Admin->TasksAdmin->First();
 +
  while( task != NULL )
 +
  {
 +
    if( task->Container != Admin->CurrentContainerId )
 +
    {
 +
      // Not in the level.
 +
      task = task->next();
 +
      continue;
 +
    }
 +
    // Loop through all inputs.
 +
    DiagramImage->Canvas->Pen->Color = clRed;
 +
    DiagramImage->Canvas->Pen->Width = 1;
 +
    for( uint k=0; k < task->Dependencies->NumElements; k++ )
 +
    {
 +
      deliverable = Admin->DeliverablesAdmin->FindDeliverable( task->Dependencies->Element[k] );
 +
      if( deliverable != NULL )
 +
      {
 +
        // Draw arrow
 +
        DrawArrowLine( task, deliverable, true );
 +
 +
      }
 +
    }
 +
 +
    // Loop through all outputs.
 +
    DiagramImage->Canvas->Pen->Color = clGreen;
 +
    DiagramImage->Canvas->Pen->Width = 1;
 +
    for( uint k=0; k < task->Deliverables->NumElements; k++ )
 +
    {
 +
      deliverable = Admin->DeliverablesAdmin->FindDeliverable( task->Deliverables->Element[k] );
 +
      if( deliverable != NULL )
 +
      {
 +
        // Draw arrow
 +
        DrawArrowLine( task, deliverable, false );
 +
      }
 +
    }
 +
    task = task->next();
 +
  }
 +
}
 +
</syntaxhighlight>
 +
 +
 +
<syntaxhighlight lang="cpp">
 +
//---------------------------------------------------------------------------
 +
// DrawArrow
 +
// Draws an arrow onto the line between the task and the deliverable.
 +
//---------------------------------------------------------------------------
 +
void TMainForm::DrawArrowLine(TaskC *task, DeliverableC *deliverable, bool dependency )
 +
{
 +
  double x1,y1,x2,y2,x_left,x_right,y_top,y_bottom,a,c,
 +
  x_task,y_task,
 +
  x_deliverable,y_deliverable,
 +
  x_m,y_m;
 +
  bool vertical = false;
 +
  bool horizontal;
 +
  uint marginDeliverable, marginTask;
 +
 +
  if( dependency )
 +
  {
 +
    marginTask = 1;
 +
    marginDeliverable = 0;
 +
  }
 +
  else
 +
  {
 +
    marginTask = 0;
 +
    marginDeliverable = 1;
 +
  }
 +
 +
  // -- Determine the equation for the line --
 +
 +
  x1 = (double)task->Position.X;
 +
  y1 = (double)task->Position.Y;
 +
 +
  x2 = (double)deliverable->Position.X;
 +
  y2 = (double)deliverable->Position.Y;
 +
 +
  vertical = ( fabs(x1-x2) < 0.001 );
 +
 +
  if( !vertical)
 +
  {
 +
    horizontal = (fabs(y1-y2) < 0.001 );
 +
 +
    a = (y1-y2)/(x1-x2);
 +
    c = y1-a*x1;
 +
  }
 +
 +
  // -- Determine midpoint of the line by determining the crossing edge --
 +
 +
  // Determine crossing edge point for task.
 +
  if( !vertical )
 +
  {
 +
    x_left  = x1-(double)task->Width/2-Edge-marginTask;
 +
    x_right  = x1+(double)task->Width/2+Edge+marginTask;
 +
    y_top    = y1-(double)task->Height/2-Edge-marginTask;
 +
    y_bottom = y1+(double)task->Height/2+Edge+marginTask;
 +
 +
    if( !horizontal &&
 +
        y1>y2 &&
 +
        x_left<=(y_top-c)/a &&
 +
                (y_top-c)/a<=x_right )
 +
    {
 +
      // upper edge
 +
      x_task = (y_top-c)/a;
 +
      y_task = y_top;
 +
    }
 +
 +
    else if( x1<x2 &&
 +
            y_top<=(a*x_right+c) &&
 +
                    (a*x_right+c)<=y_bottom )
 +
    {
 +
      // Right edge
 +
      x_task = x_right;
 +
      y_task = a*x_right+c;
 +
    }
 +
    else if( !horizontal &&
 +
            y1<y2 &&
 +
            x_left<=(y_bottom-c)/a &&
 +
                    (y_bottom-c)/a<=x_right )
 +
    {
 +
      // Bottom edge
 +
      x_task = (y_bottom-c)/a;
 +
      y_task = y_bottom;
 +
    }
 +
    else
 +
    {
 +
      // Left edge
 +
      x_task = x_left;
 +
      y_task = a*x_left+c;
 +
    }
 +
  }
 +
  else
 +
  {
 +
    // -- Vertical --
 +
    if( y1>y2 )
 +
    {
 +
      // upper edge
 +
      x_task = x1;
 +
      y_task = y1-(double)task->Height/2-Edge-marginTask;
 +
    }
 +
    else
 +
    {
 +
      // Bottom edge
 +
      x_task = x1;
 +
      y_task = y1+(double)task->Height/2+Edge+marginTask;
 +
    }
 +
  }
 +
 +
  // Determine crossing edge point for deliverable.
 +
  if( !vertical )
 +
  {
 +
    x_left  = x2-(double)deliverable->Width/2-Edge-marginDeliverable;
 +
    x_right  = x2+(double)deliverable->Width/2+Edge+marginDeliverable;
 +
    y_top    = y2-(double)deliverable->Height/2-Edge-marginDeliverable;
 +
    y_bottom = y2+(double)deliverable->Height/2+Edge+marginDeliverable;
 +
 +
    if( !horizontal &&
 +
        y2>y1 &&
 +
        x_left<=(y_top-c)/a &&
 +
                (y_top-c)/a<=x_right )
 +
    {
 +
      // upper edge
 +
      x_deliverable = (y_top-c)/a;
 +
      y_deliverable = y_top;
 +
    }
 +
 +
    else if( x2<x1 &&
 +
            y_top<=(a*x_right+c) &&
 +
                    (a*x_right+c)<=y_bottom )
 +
    {
 +
      // Right edge
 +
      x_deliverable = x_right;
 +
      y_deliverable = a*x_right+c;
 +
    }
 +
    else if( !horizontal &&
 +
            y2<y1 &&
 +
            x_left<=(y_bottom-c)/a &&
 +
                    (y_bottom-c)/a<=x_right )
 +
    {
 +
      // Bottom edge
 +
      x_deliverable = (y_bottom-c)/a;
 +
      y_deliverable = y_bottom;
 +
    }
 +
    else
 +
    {
 +
      // Left edge
 +
      x_deliverable = x_left;
 +
      y_deliverable = a*x_left+c;
 +
    }
 +
  }
 +
  else
 +
  {
 +
    // -- Vertical --
 +
    if( y2>y1 )
 +
    {
 +
      // upper edge
 +
      x_deliverable = x2;
 +
      y_deliverable = y2-(double)deliverable->Height/2-Edge-marginDeliverable;
 +
    }
 +
    else
 +
    {
 +
      // Bottom edge
 +
      x_deliverable = x2;
 +
      y_deliverable = y2+(double)deliverable->Height/2+Edge+marginDeliverable;
 +
    }
 +
  }
 +
 +
  DiagramImage->Canvas->Pen->Width = 1;
 +
  if( dependency )
 +
  {
 +
    DiagramImage->Canvas->Pen->Color = clRed;
 +
    DrawArrow( x_deliverable, y_deliverable, x_task, y_task );
 +
  }
 +
  else
 +
  {
 +
    DiagramImage->Canvas->Pen->Color = clGreen;
 +
    DrawArrow( x_task, y_task, x_deliverable, y_deliverable );
 +
  }
 +
 +
}
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="cpp">
 +
void TMainForm::DrawArrow( double begin_x, double begin_y, double end_x, double end_y )
 +
{
 +
  Extended b;
 +
  Extended deltaX;
 +
  Extended deltaY;
 +
 +
  double angle = 30;
 +
  double length = 10;
 +
 +
  // Draw the line from begin to end.
 +
  DiagramImage->Canvas->MoveTo( begin_x, begin_y );
 +
  DiagramImage->Canvas->LineTo( end_x, end_y );
 +
 +
  if( begin_x != end_x ) // checks for division by zero
 +
  {
 +
    b = ArcTan2( end_y-begin_y, begin_x-end_x );
 +
 +
 +
    if (begin_x < end_x)
 +
    {
 +
      deltaX = length * cos(M_PI-b+DegToRad(angle));
 +
      deltaY = length * sin(M_PI-b+DegToRad(angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x - deltaX, (double)end_y - deltaY);
 +
 +
      deltaX = length * cos(M_PI-b-DegToRad(angle));
 +
      deltaY = length * sin(M_PI-b-DegToRad(angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x - deltaX, (double)end_y - deltaY);
 +
    }
 +
    else
 +
    {
 +
      deltaX = length * cos(b+DegToRad(angle));
 +
      deltaY = length * sin(b+DegToRad(angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y - deltaY);
 +
 +
      deltaX = length * cos(b-DegToRad(angle));
 +
      deltaY = length * sin(b-DegToRad(angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y - deltaY);
 +
    }
 +
  }
 +
  else
 +
  {
 +
    if( begin_y < end_y )
 +
    {
 +
      deltaX = length * cos(DegToRad(90-angle));
 +
      deltaY = length * sin(DegToRad(90-angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y - deltaY);
 +
 +
      deltaX = length * cos(DegToRad(90+angle));
 +
      deltaY = length * sin(DegToRad(90+angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y - deltaY);
 +
    }
 +
    else
 +
    {
 +
      deltaX = length * cos(DegToRad(90-angle));
 +
      deltaY = length * sin(DegToRad(90-angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y + deltaY);
 +
 +
      deltaX = length * cos(DegToRad(90+angle));
 +
      deltaY = length * sin(DegToRad(90+angle));
 +
 +
      DiagramImage->Canvas->MoveTo(end_x, end_y);
 +
      DiagramImage->Canvas->LineTo((double)end_x + deltaX, (double)end_y + deltaY);
 +
    }
 +
  }
 +
 +
}
 +
</syntaxhighlight>
 +
  
 
----
 
----

Latest revision as of 17:51, 14 October 2011

Personal tools