Fossil SCM
Fix to the graph layout for complex time-warp cases. Add tooltips to timewarp arrows.
Commit
5399c5dacb808e4cc5ec5a76fd4d8a4823d96f0b1a21d692d9c06522839c3ad3
Parent
55f56e91badb50c…
2 files changed
+13
-3
+10
-4
+13
-3
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -278,11 +278,12 @@ | ||
| 278 | 278 | } |
| 279 | 279 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 280 | 280 | if( (inUseMask & BIT(i))==0 ){ |
| 281 | 281 | int dist; |
| 282 | 282 | if( iNearto<=0 ){ |
| 283 | - return i; | |
| 283 | + iBest = i; | |
| 284 | + break; | |
| 284 | 285 | } |
| 285 | 286 | dist = i - iNearto; |
| 286 | 287 | if( dist<0 ) dist = -dist; |
| 287 | 288 | if( dist<iBestDist ){ |
| 288 | 289 | iBestDist = dist; |
| @@ -307,10 +308,11 @@ | ||
| 307 | 308 | pBottom->railInUse |= mask; |
| 308 | 309 | pPrior = pBottom; |
| 309 | 310 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 310 | 311 | assert( pPrior->idx > pCurrent->idx ); |
| 311 | 312 | assert( pCurrent->iRail<0 ); |
| 313 | + if( pPrior->timeWarp ) break; | |
| 312 | 314 | pCurrent->iRail = iRail; |
| 313 | 315 | pCurrent->railInUse |= mask; |
| 314 | 316 | pPrior->aiRiser[iRail] = pCurrent->idx; |
| 315 | 317 | while( pPrior->idx > pCurrent->idx ){ |
| 316 | 318 | pPrior->railInUse |= mask; |
| @@ -643,12 +645,20 @@ | ||
| 643 | 645 | assignChildrenToRail(pRow, tmFlags); |
| 644 | 646 | }else if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){ |
| 645 | 647 | if( !pRow->timeWarp ) riser_to_top(pRow); |
| 646 | 648 | } |
| 647 | 649 | if( pParent ){ |
| 648 | - for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ | |
| 649 | - pLoop->railInUse |= mask; | |
| 650 | + if( pParent->idx>pRow->idx ){ | |
| 651 | + /* Common case: Parent is below current row in the graph */ | |
| 652 | + for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ | |
| 653 | + pLoop->railInUse |= mask; | |
| 654 | + } | |
| 655 | + }else{ | |
| 656 | + /* Timewarp case: Parent is above current row in the graph */ | |
| 657 | + for(pLoop=pParent->pNext; pLoop && pLoop!=pRow; pLoop=pLoop->pNext){ | |
| 658 | + pLoop->railInUse |= mask; | |
| 659 | + } | |
| 650 | 660 | } |
| 651 | 661 | } |
| 652 | 662 | } |
| 653 | 663 | |
| 654 | 664 | /* |
| 655 | 665 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -278,11 +278,12 @@ | |
| 278 | } |
| 279 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 280 | if( (inUseMask & BIT(i))==0 ){ |
| 281 | int dist; |
| 282 | if( iNearto<=0 ){ |
| 283 | return i; |
| 284 | } |
| 285 | dist = i - iNearto; |
| 286 | if( dist<0 ) dist = -dist; |
| 287 | if( dist<iBestDist ){ |
| 288 | iBestDist = dist; |
| @@ -307,10 +308,11 @@ | |
| 307 | pBottom->railInUse |= mask; |
| 308 | pPrior = pBottom; |
| 309 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 310 | assert( pPrior->idx > pCurrent->idx ); |
| 311 | assert( pCurrent->iRail<0 ); |
| 312 | pCurrent->iRail = iRail; |
| 313 | pCurrent->railInUse |= mask; |
| 314 | pPrior->aiRiser[iRail] = pCurrent->idx; |
| 315 | while( pPrior->idx > pCurrent->idx ){ |
| 316 | pPrior->railInUse |= mask; |
| @@ -643,12 +645,20 @@ | |
| 643 | assignChildrenToRail(pRow, tmFlags); |
| 644 | }else if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){ |
| 645 | if( !pRow->timeWarp ) riser_to_top(pRow); |
| 646 | } |
| 647 | if( pParent ){ |
| 648 | for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ |
| 649 | pLoop->railInUse |= mask; |
| 650 | } |
| 651 | } |
| 652 | } |
| 653 | |
| 654 | /* |
| 655 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -278,11 +278,12 @@ | |
| 278 | } |
| 279 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 280 | if( (inUseMask & BIT(i))==0 ){ |
| 281 | int dist; |
| 282 | if( iNearto<=0 ){ |
| 283 | iBest = i; |
| 284 | break; |
| 285 | } |
| 286 | dist = i - iNearto; |
| 287 | if( dist<0 ) dist = -dist; |
| 288 | if( dist<iBestDist ){ |
| 289 | iBestDist = dist; |
| @@ -307,10 +308,11 @@ | |
| 308 | pBottom->railInUse |= mask; |
| 309 | pPrior = pBottom; |
| 310 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 311 | assert( pPrior->idx > pCurrent->idx ); |
| 312 | assert( pCurrent->iRail<0 ); |
| 313 | if( pPrior->timeWarp ) break; |
| 314 | pCurrent->iRail = iRail; |
| 315 | pCurrent->railInUse |= mask; |
| 316 | pPrior->aiRiser[iRail] = pCurrent->idx; |
| 317 | while( pPrior->idx > pCurrent->idx ){ |
| 318 | pPrior->railInUse |= mask; |
| @@ -643,12 +645,20 @@ | |
| 645 | assignChildrenToRail(pRow, tmFlags); |
| 646 | }else if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){ |
| 647 | if( !pRow->timeWarp ) riser_to_top(pRow); |
| 648 | } |
| 649 | if( pParent ){ |
| 650 | if( pParent->idx>pRow->idx ){ |
| 651 | /* Common case: Parent is below current row in the graph */ |
| 652 | for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){ |
| 653 | pLoop->railInUse |= mask; |
| 654 | } |
| 655 | }else{ |
| 656 | /* Timewarp case: Parent is above current row in the graph */ |
| 657 | for(pLoop=pParent->pNext; pLoop && pLoop!=pRow; pLoop=pLoop->pNext){ |
| 658 | pLoop->railInUse |= mask; |
| 659 | } |
| 660 | } |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | /* |
| 665 |
+10
-4
| --- src/graph.js | ||
| +++ src/graph.js | ||
| @@ -485,20 +485,26 @@ | ||
| 485 | 485 | x1 += line.w; |
| 486 | 486 | } |
| 487 | 487 | var y0 = p.y + (node.h-line.w)/2; |
| 488 | 488 | var u = tx.rowinfo[p.au[i+1]-tx.iTopRow]; |
| 489 | 489 | if( u.id<p.id ){ |
| 490 | + // normal thick up-arrow | |
| 490 | 491 | drawLine(line,u.fg,x0,y0,x1,null); |
| 491 | 492 | drawUpArrow(p,u,u.fg,u.id); |
| 492 | 493 | }else{ |
| 494 | + // timewarp: The child node occurs before the parent | |
| 493 | 495 | var y1 = u.y + (node.h-line.w)/2; |
| 494 | - drawLine(wLine,u.fg,x0,y0,x1,null); | |
| 495 | - drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); | |
| 496 | - drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); | |
| 496 | + var n = drawLine(wLine,u.fg,x0,y0,x1,null); | |
| 497 | + addToolTip(n,u.id) | |
| 498 | + n = drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); | |
| 499 | + addToolTip(n,u.id) | |
| 500 | + n = drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); | |
| 501 | + addToolTip(n,u.id) | |
| 497 | 502 | var x = u.x-wArrow.w; |
| 498 | 503 | var y = u.y+(node.h-wArrow.h)/2; |
| 499 | - var n = drawBox(wArrow.cls,null,x,y); | |
| 504 | + n = drawBox(wArrow.cls,null,x,y); | |
| 505 | + addToolTip(n,u.id) | |
| 500 | 506 | if( u.fg ) n.style.borderLeftColor = u.fg; |
| 501 | 507 | } |
| 502 | 508 | } |
| 503 | 509 | } |
| 504 | 510 | if( p.hasOwnProperty('mi') ){ |
| 505 | 511 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -485,20 +485,26 @@ | |
| 485 | x1 += line.w; |
| 486 | } |
| 487 | var y0 = p.y + (node.h-line.w)/2; |
| 488 | var u = tx.rowinfo[p.au[i+1]-tx.iTopRow]; |
| 489 | if( u.id<p.id ){ |
| 490 | drawLine(line,u.fg,x0,y0,x1,null); |
| 491 | drawUpArrow(p,u,u.fg,u.id); |
| 492 | }else{ |
| 493 | var y1 = u.y + (node.h-line.w)/2; |
| 494 | drawLine(wLine,u.fg,x0,y0,x1,null); |
| 495 | drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); |
| 496 | drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); |
| 497 | var x = u.x-wArrow.w; |
| 498 | var y = u.y+(node.h-wArrow.h)/2; |
| 499 | var n = drawBox(wArrow.cls,null,x,y); |
| 500 | if( u.fg ) n.style.borderLeftColor = u.fg; |
| 501 | } |
| 502 | } |
| 503 | } |
| 504 | if( p.hasOwnProperty('mi') ){ |
| 505 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -485,20 +485,26 @@ | |
| 485 | x1 += line.w; |
| 486 | } |
| 487 | var y0 = p.y + (node.h-line.w)/2; |
| 488 | var u = tx.rowinfo[p.au[i+1]-tx.iTopRow]; |
| 489 | if( u.id<p.id ){ |
| 490 | // normal thick up-arrow |
| 491 | drawLine(line,u.fg,x0,y0,x1,null); |
| 492 | drawUpArrow(p,u,u.fg,u.id); |
| 493 | }else{ |
| 494 | // timewarp: The child node occurs before the parent |
| 495 | var y1 = u.y + (node.h-line.w)/2; |
| 496 | var n = drawLine(wLine,u.fg,x0,y0,x1,null); |
| 497 | addToolTip(n,u.id) |
| 498 | n = drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); |
| 499 | addToolTip(n,u.id) |
| 500 | n = drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); |
| 501 | addToolTip(n,u.id) |
| 502 | var x = u.x-wArrow.w; |
| 503 | var y = u.y+(node.h-wArrow.h)/2; |
| 504 | n = drawBox(wArrow.cls,null,x,y); |
| 505 | addToolTip(n,u.id) |
| 506 | if( u.fg ) n.style.borderLeftColor = u.fg; |
| 507 | } |
| 508 | } |
| 509 | } |
| 510 | if( p.hasOwnProperty('mi') ){ |
| 511 |