View source
From TaskDepender
for
Drawing the diagram
Jump to:
navigation
,
search
''This page describes how the [[GUI]] can draw the diagram.'' == Description == == 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> ----
Return to
Drawing the diagram
.
Views
Page
Discussion
View source
History
Personal tools
Log in
Navigation
Main page
Recent changes
Help
Search
Toolbox
What links here
Related changes
Special pages