Fossil SCM
Further improvements to the layout of merge arrows.
Commit
a6934b4437780904bf8813ec55c81bdca55d57ab
Parent
313cd3c8322e2ab…
2 files changed
+8
-7
+28
-20
+8
-7
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -45,12 +45,12 @@ | ||
| 45 | 45 | GraphRow *pChild; /* Child immediately above this node */ |
| 46 | 46 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 47 | 47 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 48 | 48 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 49 | 49 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 50 | + u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ | |
| 50 | 51 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 51 | - u32 mergeIn; /* Merge in from other rails on this bitmask */ | |
| 52 | 52 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 53 | 53 | u32 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 54 | 54 | |
| 55 | 55 | u32 railInUse; /* Mask of occupied rails at this row */ |
| 56 | 56 | }; |
| @@ -271,27 +271,28 @@ | ||
| 271 | 271 | u = pParent->aiRiser[pParent->iRail]; |
| 272 | 272 | if( u>0 && u<pChild->idx ){ |
| 273 | 273 | /* The thick arrow up to the next primary child of pDesc goes |
| 274 | 274 | ** further up than the thin merge arrow riser, so draw them both |
| 275 | 275 | ** on the same rail. */ |
| 276 | - pParent->mergeOut = pParent->iRail; | |
| 276 | + pParent->mergeOut = pParent->iRail*4; | |
| 277 | + if( pParent->iRail<pChild->iRail ) pParent->mergeOut += 2; | |
| 277 | 278 | pParent->mergeUpto = pChild->idx; |
| 278 | 279 | }else{ |
| 279 | 280 | /* The thin merge arrow riser is taller than the thick primary |
| 280 | 281 | ** child riser, so use separate rails. */ |
| 281 | 282 | int iTarget = pParent->iRail; |
| 282 | 283 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 283 | - 0, iTarget); | |
| 284 | + 0, iTarget)*4 + 1; | |
| 284 | 285 | pParent->mergeUpto = pChild->idx; |
| 285 | - mask = 1<<pParent->mergeOut; | |
| 286 | + mask = 1<<(pParent->mergeOut/4); | |
| 286 | 287 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 287 | 288 | pLoop=pLoop->pNext){ |
| 288 | 289 | pLoop->railInUse |= mask; |
| 289 | 290 | } |
| 290 | 291 | } |
| 291 | 292 | } |
| 292 | - pChild->mergeIn |= 1<<pParent->mergeOut; | |
| 293 | + pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; | |
| 293 | 294 | } |
| 294 | 295 | |
| 295 | 296 | |
| 296 | 297 | /* |
| 297 | 298 | ** Compute the complete graph |
| @@ -461,11 +462,11 @@ | ||
| 461 | 462 | pDesc = hashFind(p, parentRid); |
| 462 | 463 | if( pDesc==0 ){ |
| 463 | 464 | /* Merge from a node that is off-screen */ |
| 464 | 465 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 465 | 466 | mask = 1<<iMrail; |
| 466 | - pRow->mergeIn |= mask; | |
| 467 | + pRow->mergeIn[iMrail] = 2; | |
| 467 | 468 | pRow->mergeDown |= mask; |
| 468 | 469 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 469 | 470 | pLoop->railInUse |= mask; |
| 470 | 471 | } |
| 471 | 472 | }else{ |
| @@ -491,11 +492,11 @@ | ||
| 491 | 492 | ** Find the maximum rail number. |
| 492 | 493 | */ |
| 493 | 494 | p->mxRail = 0; |
| 494 | 495 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 495 | 496 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 496 | - if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; | |
| 497 | + if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; | |
| 497 | 498 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 498 | 499 | p->mxRail++; |
| 499 | 500 | } |
| 500 | 501 | } |
| 501 | 502 | } |
| 502 | 503 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -45,12 +45,12 @@ | |
| 45 | GraphRow *pChild; /* Child immediately above this node */ |
| 46 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 47 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 48 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 49 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 50 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 51 | u32 mergeIn; /* Merge in from other rails on this bitmask */ |
| 52 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 53 | u32 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 54 | |
| 55 | u32 railInUse; /* Mask of occupied rails at this row */ |
| 56 | }; |
| @@ -271,27 +271,28 @@ | |
| 271 | u = pParent->aiRiser[pParent->iRail]; |
| 272 | if( u>0 && u<pChild->idx ){ |
| 273 | /* The thick arrow up to the next primary child of pDesc goes |
| 274 | ** further up than the thin merge arrow riser, so draw them both |
| 275 | ** on the same rail. */ |
| 276 | pParent->mergeOut = pParent->iRail; |
| 277 | pParent->mergeUpto = pChild->idx; |
| 278 | }else{ |
| 279 | /* The thin merge arrow riser is taller than the thick primary |
| 280 | ** child riser, so use separate rails. */ |
| 281 | int iTarget = pParent->iRail; |
| 282 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 283 | 0, iTarget); |
| 284 | pParent->mergeUpto = pChild->idx; |
| 285 | mask = 1<<pParent->mergeOut; |
| 286 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 287 | pLoop=pLoop->pNext){ |
| 288 | pLoop->railInUse |= mask; |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | pChild->mergeIn |= 1<<pParent->mergeOut; |
| 293 | } |
| 294 | |
| 295 | |
| 296 | /* |
| 297 | ** Compute the complete graph |
| @@ -461,11 +462,11 @@ | |
| 461 | pDesc = hashFind(p, parentRid); |
| 462 | if( pDesc==0 ){ |
| 463 | /* Merge from a node that is off-screen */ |
| 464 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 465 | mask = 1<<iMrail; |
| 466 | pRow->mergeIn |= mask; |
| 467 | pRow->mergeDown |= mask; |
| 468 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 469 | pLoop->railInUse |= mask; |
| 470 | } |
| 471 | }else{ |
| @@ -491,11 +492,11 @@ | |
| 491 | ** Find the maximum rail number. |
| 492 | */ |
| 493 | p->mxRail = 0; |
| 494 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 495 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 496 | if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; |
| 497 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 498 | p->mxRail++; |
| 499 | } |
| 500 | } |
| 501 | } |
| 502 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -45,12 +45,12 @@ | |
| 45 | GraphRow *pChild; /* Child immediately above this node */ |
| 46 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 47 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 48 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 49 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 50 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 51 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 52 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 53 | u32 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 54 | |
| 55 | u32 railInUse; /* Mask of occupied rails at this row */ |
| 56 | }; |
| @@ -271,27 +271,28 @@ | |
| 271 | u = pParent->aiRiser[pParent->iRail]; |
| 272 | if( u>0 && u<pChild->idx ){ |
| 273 | /* The thick arrow up to the next primary child of pDesc goes |
| 274 | ** further up than the thin merge arrow riser, so draw them both |
| 275 | ** on the same rail. */ |
| 276 | pParent->mergeOut = pParent->iRail*4; |
| 277 | if( pParent->iRail<pChild->iRail ) pParent->mergeOut += 2; |
| 278 | pParent->mergeUpto = pChild->idx; |
| 279 | }else{ |
| 280 | /* The thin merge arrow riser is taller than the thick primary |
| 281 | ** child riser, so use separate rails. */ |
| 282 | int iTarget = pParent->iRail; |
| 283 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 284 | 0, iTarget)*4 + 1; |
| 285 | pParent->mergeUpto = pChild->idx; |
| 286 | mask = 1<<(pParent->mergeOut/4); |
| 287 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 288 | pLoop=pLoop->pNext){ |
| 289 | pLoop->railInUse |= mask; |
| 290 | } |
| 291 | } |
| 292 | } |
| 293 | pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; |
| 294 | } |
| 295 | |
| 296 | |
| 297 | /* |
| 298 | ** Compute the complete graph |
| @@ -461,11 +462,11 @@ | |
| 462 | pDesc = hashFind(p, parentRid); |
| 463 | if( pDesc==0 ){ |
| 464 | /* Merge from a node that is off-screen */ |
| 465 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 466 | mask = 1<<iMrail; |
| 467 | pRow->mergeIn[iMrail] = 2; |
| 468 | pRow->mergeDown |= mask; |
| 469 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 470 | pLoop->railInUse |= mask; |
| 471 | } |
| 472 | }else{ |
| @@ -491,11 +492,11 @@ | |
| 492 | ** Find the maximum rail number. |
| 493 | */ |
| 494 | p->mxRail = 0; |
| 495 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 496 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 497 | if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; |
| 498 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 499 | p->mxRail++; |
| 500 | } |
| 501 | } |
| 502 | } |
| 503 |
+28
-20
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -388,40 +388,43 @@ | ||
| 388 | 388 | ** bg: The background color for this row |
| 389 | 389 | ** r: The "rail" that the node for this row sits on. The left-most |
| 390 | 390 | ** rail is 0 and the number increases to the right. |
| 391 | 391 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 392 | 392 | ** of the page straight up to this node. |
| 393 | - ** mo: "merge-out". If non-zero, this is one more than the rail on which | |
| 394 | - ** a merge arrow travels upward. The merge arrow is drawn upwards | |
| 393 | + ** mo: "merge-out". If non-zero, this is one more than the x-coordinate | |
| 394 | + ** for the upward portion of a merge arrow. The merge arrow goes up | |
| 395 | 395 | ** to the row identified by mu:. If this value is zero then |
| 396 | 396 | ** node has no merge children and no merge-out line is drawn. |
| 397 | 397 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 398 | - ** md: A bitmask of rails on which merge-arrow descenders should be | |
| 399 | - ** drawn from this row to the bottom of the page. The least | |
| 400 | - ** significant bit (1) corresponds to rail 0. The 2-bit corresponds | |
| 401 | - ** to rail 1. And so forth. This value is 0 if there are no | |
| 402 | - ** merge-arrow descenders. | |
| 403 | 398 | ** u: Draw a thick child-line out of the top of this node and up to |
| 404 | 399 | ** the node with an id equal to this value. 0 if there is no |
| 405 | 400 | ** thick-line riser. |
| 406 | 401 | ** au: An array of integers that define thick-line risers for branches. |
| 407 | 402 | ** The integers are in pairs. For each pair, the first integer is |
| 408 | 403 | ** is the rail on which the riser should run and the second integer |
| 409 | 404 | ** is the id of the node upto which the riser should run. |
| 410 | - ** mi: "merge-in". An array of integer rail numbers from which | |
| 411 | - ** merge arrows should be drawn into this node. | |
| 405 | + ** mi: "merge-in". An array of integer x-coordinates from which | |
| 406 | + ** merge arrows should be drawn into this node. If the value is | |
| 407 | + ** negative, then the x-coordinate is the absolute value of mi[] | |
| 408 | + ** and a thin merge-arrow descender is drawn to the bottom of | |
| 409 | + ** the screen. | |
| 412 | 410 | */ |
| 413 | 411 | cgi_printf("var rowinfo = [\n"); |
| 414 | 412 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 415 | - cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:", | |
| 413 | + int mo = pRow->mergeOut; | |
| 414 | + if( mo<0 ){ | |
| 415 | + mo = 0; | |
| 416 | + }else{ | |
| 417 | + mo = (mo/4)*20 - 3 + 4*(mo&3); | |
| 418 | + } | |
| 419 | + cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:", | |
| 416 | 420 | pRow->idx, /* id */ |
| 417 | 421 | pRow->zBgClr, /* bg */ |
| 418 | 422 | pRow->iRail, /* r */ |
| 419 | 423 | pRow->bDescender, /* d */ |
| 420 | - pRow->mergeOut+1, /* mo */ | |
| 424 | + mo, /* mo */ | |
| 421 | 425 | pRow->mergeUpto, /* mu */ |
| 422 | - pRow->mergeDown, /* md */ | |
| 423 | 426 | pRow->aiRiser[pRow->iRail] /* u */ |
| 424 | 427 | ); |
| 425 | 428 | /* u */ |
| 426 | 429 | cSep = '['; |
| 427 | 430 | for(i=0; i<GR_MAX_RAIL; i++){ |
| @@ -434,12 +437,14 @@ | ||
| 434 | 437 | if( cSep=='[' ) cgi_printf("["); |
| 435 | 438 | cgi_printf("],mi:"); |
| 436 | 439 | /* mi */ |
| 437 | 440 | cSep = '['; |
| 438 | 441 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 439 | - if( pRow->mergeIn & (1<<i) ){ | |
| 440 | - cgi_printf("%c%d", cSep, i); | |
| 442 | + if( pRow->mergeIn[i] ){ | |
| 443 | + int mi = i*20 - 8 + 4*pRow->mergeIn[i]; | |
| 444 | + if( pRow->mergeDown & (1<<i) ) mi = -mi; | |
| 445 | + cgi_printf("%c%d", cSep, mi); | |
| 441 | 446 | cSep = ','; |
| 442 | 447 | } |
| 443 | 448 | } |
| 444 | 449 | if( cSep=='[' ) cgi_printf("["); |
| 445 | 450 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| @@ -518,16 +523,16 @@ | ||
| 518 | 523 | @ } |
| 519 | 524 | @ if( p.d ){ |
| 520 | 525 | @ drawUpArrow(p.x, p.y+6, btm); |
| 521 | 526 | @ } |
| 522 | 527 | @ if( p.mo>0 ){ |
| 523 | - @ var x1 = (p.mo-1)*20 + left + 4; | |
| 528 | + @ var x1 = p.mo + left - 1; | |
| 524 | 529 | @ var y1 = p.y-3; |
| 525 | 530 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 526 | 531 | @ var u = rowinfo[p.mu-1]; |
| 527 | 532 | @ var y0 = u.y+5; |
| 528 | - @ if( x1==p.x+4 ){ | |
| 533 | + @ if( x1>=p.x-5 && x1<=p.x+5 ){ | |
| 529 | 534 | @ y1 = p.y-5; |
| 530 | 535 | @ }else{ |
| 531 | 536 | @ drawThinLine(x0,y1,x1,y1); |
| 532 | 537 | @ } |
| 533 | 538 | @ drawThinLine(x1,y0,x1,y1); |
| @@ -548,19 +553,22 @@ | ||
| 548 | 553 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 549 | 554 | @ } |
| 550 | 555 | @ } |
| 551 | 556 | @ for(var j in p.mi){ |
| 552 | 557 | @ var y0 = p.y+5; |
| 553 | - @ var mx = p.mi[j]*20 + left + 4; | |
| 558 | + @ var mx = p.mi[j]; | |
| 559 | + @ if( mx<0 ){ | |
| 560 | + @ mx = left-mx; | |
| 561 | + @ drawThinLine(mx,y0,mx,btm); | |
| 562 | + @ }else{ | |
| 563 | + @ mx += left; | |
| 564 | + @ } | |
| 554 | 565 | @ if( mx>p.x ){ |
| 555 | 566 | @ drawThinArrow(y0,mx,p.x+6); |
| 556 | 567 | @ }else{ |
| 557 | 568 | @ drawThinArrow(y0,mx,p.x-5); |
| 558 | 569 | @ } |
| 559 | - @ if( (1<<p.mi[j])&p.md ){ | |
| 560 | - @ drawThinLine(mx,y0,mx,btm); | |
| 561 | - @ } | |
| 562 | 570 | @ } |
| 563 | 571 | @ } |
| 564 | 572 | @ function renderGraph(){ |
| 565 | 573 | @ var canvasDiv = document.getElementById("canvas"); |
| 566 | 574 | @ while( canvasDiv.hasChildNodes() ){ |
| 567 | 575 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -388,40 +388,43 @@ | |
| 388 | ** bg: The background color for this row |
| 389 | ** r: The "rail" that the node for this row sits on. The left-most |
| 390 | ** rail is 0 and the number increases to the right. |
| 391 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 392 | ** of the page straight up to this node. |
| 393 | ** mo: "merge-out". If non-zero, this is one more than the rail on which |
| 394 | ** a merge arrow travels upward. The merge arrow is drawn upwards |
| 395 | ** to the row identified by mu:. If this value is zero then |
| 396 | ** node has no merge children and no merge-out line is drawn. |
| 397 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 398 | ** md: A bitmask of rails on which merge-arrow descenders should be |
| 399 | ** drawn from this row to the bottom of the page. The least |
| 400 | ** significant bit (1) corresponds to rail 0. The 2-bit corresponds |
| 401 | ** to rail 1. And so forth. This value is 0 if there are no |
| 402 | ** merge-arrow descenders. |
| 403 | ** u: Draw a thick child-line out of the top of this node and up to |
| 404 | ** the node with an id equal to this value. 0 if there is no |
| 405 | ** thick-line riser. |
| 406 | ** au: An array of integers that define thick-line risers for branches. |
| 407 | ** The integers are in pairs. For each pair, the first integer is |
| 408 | ** is the rail on which the riser should run and the second integer |
| 409 | ** is the id of the node upto which the riser should run. |
| 410 | ** mi: "merge-in". An array of integer rail numbers from which |
| 411 | ** merge arrows should be drawn into this node. |
| 412 | */ |
| 413 | cgi_printf("var rowinfo = [\n"); |
| 414 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 415 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:", |
| 416 | pRow->idx, /* id */ |
| 417 | pRow->zBgClr, /* bg */ |
| 418 | pRow->iRail, /* r */ |
| 419 | pRow->bDescender, /* d */ |
| 420 | pRow->mergeOut+1, /* mo */ |
| 421 | pRow->mergeUpto, /* mu */ |
| 422 | pRow->mergeDown, /* md */ |
| 423 | pRow->aiRiser[pRow->iRail] /* u */ |
| 424 | ); |
| 425 | /* u */ |
| 426 | cSep = '['; |
| 427 | for(i=0; i<GR_MAX_RAIL; i++){ |
| @@ -434,12 +437,14 @@ | |
| 434 | if( cSep=='[' ) cgi_printf("["); |
| 435 | cgi_printf("],mi:"); |
| 436 | /* mi */ |
| 437 | cSep = '['; |
| 438 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 439 | if( pRow->mergeIn & (1<<i) ){ |
| 440 | cgi_printf("%c%d", cSep, i); |
| 441 | cSep = ','; |
| 442 | } |
| 443 | } |
| 444 | if( cSep=='[' ) cgi_printf("["); |
| 445 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| @@ -518,16 +523,16 @@ | |
| 518 | @ } |
| 519 | @ if( p.d ){ |
| 520 | @ drawUpArrow(p.x, p.y+6, btm); |
| 521 | @ } |
| 522 | @ if( p.mo>0 ){ |
| 523 | @ var x1 = (p.mo-1)*20 + left + 4; |
| 524 | @ var y1 = p.y-3; |
| 525 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 526 | @ var u = rowinfo[p.mu-1]; |
| 527 | @ var y0 = u.y+5; |
| 528 | @ if( x1==p.x+4 ){ |
| 529 | @ y1 = p.y-5; |
| 530 | @ }else{ |
| 531 | @ drawThinLine(x0,y1,x1,y1); |
| 532 | @ } |
| 533 | @ drawThinLine(x1,y0,x1,y1); |
| @@ -548,19 +553,22 @@ | |
| 548 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 549 | @ } |
| 550 | @ } |
| 551 | @ for(var j in p.mi){ |
| 552 | @ var y0 = p.y+5; |
| 553 | @ var mx = p.mi[j]*20 + left + 4; |
| 554 | @ if( mx>p.x ){ |
| 555 | @ drawThinArrow(y0,mx,p.x+6); |
| 556 | @ }else{ |
| 557 | @ drawThinArrow(y0,mx,p.x-5); |
| 558 | @ } |
| 559 | @ if( (1<<p.mi[j])&p.md ){ |
| 560 | @ drawThinLine(mx,y0,mx,btm); |
| 561 | @ } |
| 562 | @ } |
| 563 | @ } |
| 564 | @ function renderGraph(){ |
| 565 | @ var canvasDiv = document.getElementById("canvas"); |
| 566 | @ while( canvasDiv.hasChildNodes() ){ |
| 567 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -388,40 +388,43 @@ | |
| 388 | ** bg: The background color for this row |
| 389 | ** r: The "rail" that the node for this row sits on. The left-most |
| 390 | ** rail is 0 and the number increases to the right. |
| 391 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 392 | ** of the page straight up to this node. |
| 393 | ** mo: "merge-out". If non-zero, this is one more than the x-coordinate |
| 394 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 395 | ** to the row identified by mu:. If this value is zero then |
| 396 | ** node has no merge children and no merge-out line is drawn. |
| 397 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 398 | ** u: Draw a thick child-line out of the top of this node and up to |
| 399 | ** the node with an id equal to this value. 0 if there is no |
| 400 | ** thick-line riser. |
| 401 | ** au: An array of integers that define thick-line risers for branches. |
| 402 | ** The integers are in pairs. For each pair, the first integer is |
| 403 | ** is the rail on which the riser should run and the second integer |
| 404 | ** is the id of the node upto which the riser should run. |
| 405 | ** mi: "merge-in". An array of integer x-coordinates from which |
| 406 | ** merge arrows should be drawn into this node. If the value is |
| 407 | ** negative, then the x-coordinate is the absolute value of mi[] |
| 408 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 409 | ** the screen. |
| 410 | */ |
| 411 | cgi_printf("var rowinfo = [\n"); |
| 412 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 413 | int mo = pRow->mergeOut; |
| 414 | if( mo<0 ){ |
| 415 | mo = 0; |
| 416 | }else{ |
| 417 | mo = (mo/4)*20 - 3 + 4*(mo&3); |
| 418 | } |
| 419 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:", |
| 420 | pRow->idx, /* id */ |
| 421 | pRow->zBgClr, /* bg */ |
| 422 | pRow->iRail, /* r */ |
| 423 | pRow->bDescender, /* d */ |
| 424 | mo, /* mo */ |
| 425 | pRow->mergeUpto, /* mu */ |
| 426 | pRow->aiRiser[pRow->iRail] /* u */ |
| 427 | ); |
| 428 | /* u */ |
| 429 | cSep = '['; |
| 430 | for(i=0; i<GR_MAX_RAIL; i++){ |
| @@ -434,12 +437,14 @@ | |
| 437 | if( cSep=='[' ) cgi_printf("["); |
| 438 | cgi_printf("],mi:"); |
| 439 | /* mi */ |
| 440 | cSep = '['; |
| 441 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 442 | if( pRow->mergeIn[i] ){ |
| 443 | int mi = i*20 - 8 + 4*pRow->mergeIn[i]; |
| 444 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 445 | cgi_printf("%c%d", cSep, mi); |
| 446 | cSep = ','; |
| 447 | } |
| 448 | } |
| 449 | if( cSep=='[' ) cgi_printf("["); |
| 450 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| @@ -518,16 +523,16 @@ | |
| 523 | @ } |
| 524 | @ if( p.d ){ |
| 525 | @ drawUpArrow(p.x, p.y+6, btm); |
| 526 | @ } |
| 527 | @ if( p.mo>0 ){ |
| 528 | @ var x1 = p.mo + left - 1; |
| 529 | @ var y1 = p.y-3; |
| 530 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 531 | @ var u = rowinfo[p.mu-1]; |
| 532 | @ var y0 = u.y+5; |
| 533 | @ if( x1>=p.x-5 && x1<=p.x+5 ){ |
| 534 | @ y1 = p.y-5; |
| 535 | @ }else{ |
| 536 | @ drawThinLine(x0,y1,x1,y1); |
| 537 | @ } |
| 538 | @ drawThinLine(x1,y0,x1,y1); |
| @@ -548,19 +553,22 @@ | |
| 553 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 554 | @ } |
| 555 | @ } |
| 556 | @ for(var j in p.mi){ |
| 557 | @ var y0 = p.y+5; |
| 558 | @ var mx = p.mi[j]; |
| 559 | @ if( mx<0 ){ |
| 560 | @ mx = left-mx; |
| 561 | @ drawThinLine(mx,y0,mx,btm); |
| 562 | @ }else{ |
| 563 | @ mx += left; |
| 564 | @ } |
| 565 | @ if( mx>p.x ){ |
| 566 | @ drawThinArrow(y0,mx,p.x+6); |
| 567 | @ }else{ |
| 568 | @ drawThinArrow(y0,mx,p.x-5); |
| 569 | @ } |
| 570 | @ } |
| 571 | @ } |
| 572 | @ function renderGraph(){ |
| 573 | @ var canvasDiv = document.getElementById("canvas"); |
| 574 | @ while( canvasDiv.hasChildNodes() ){ |
| 575 |