Fossil SCM
Graph layout: Strive harder for merge arrows to come straight up out of the top of leaf nodes.
Commit
a3bfe425e0eb18eab6b3291d5f051a1ee7fa39ce5bf08759dd82da1402297b7d
Parent
59dfca5ed575d6e…
1 file changed
+26
-4
+26
-4
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -369,26 +369,48 @@ | ||
| 369 | 369 | p->railInUse |= mask; |
| 370 | 370 | } |
| 371 | 371 | } |
| 372 | 372 | } |
| 373 | 373 | |
| 374 | + | |
| 375 | +/* | |
| 376 | +** Check to see if rail iRail is clear from pBottom up to and including | |
| 377 | +** pTop. | |
| 378 | +*/ | |
| 379 | +static int railIsClear(GraphRow *pBottom, int iTop, int iRail){ | |
| 380 | + u64 m = BIT(iRail); | |
| 381 | + while( pBottom && pBottom->idx>=iTop ){ | |
| 382 | + if( pBottom->railInUse & m ) return 0; | |
| 383 | + pBottom = pBottom->pPrev; | |
| 384 | + } | |
| 385 | + return 1; | |
| 386 | +} | |
| 387 | + | |
| 374 | 388 | /* |
| 375 | 389 | ** Create a merge-arrow riser going from pParent up to pChild. |
| 376 | 390 | */ |
| 377 | 391 | static void createMergeRiser( |
| 378 | 392 | GraphContext *p, |
| 379 | - GraphRow *pParent, | |
| 380 | - GraphRow *pChild, | |
| 381 | - int isCherrypick | |
| 393 | + GraphRow *pParent, /* Lower node from which the merge line begins */ | |
| 394 | + GraphRow *pChild, /* Upper node at which the merge line ends */ | |
| 395 | + int isCherrypick /* True for a cherry-pick merge */ | |
| 382 | 396 | ){ |
| 383 | 397 | int u; |
| 384 | 398 | u64 mask; |
| 385 | 399 | GraphRow *pLoop; |
| 386 | 400 | |
| 387 | 401 | if( pParent->mergeOut<0 ){ |
| 388 | 402 | u = pParent->aiRiser[pParent->iRail]; |
| 389 | - if( u>0 && u<pChild->idx ){ | |
| 403 | + if( u<0 && railIsClear(pParent->pPrev, pChild->idx-1, pParent->iRail) ){ | |
| 404 | + /* pParent is a leaf and the merge-line can be drawn straight up.*/ | |
| 405 | + pParent->mergeOut = pParent->iRail; | |
| 406 | + mask = BIT(pParent->iRail); | |
| 407 | + for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; | |
| 408 | + pLoop=pLoop->pNext){ | |
| 409 | + pLoop->railInUse |= mask; | |
| 410 | + } | |
| 411 | + }else if( u>0 && u<pChild->idx ){ | |
| 390 | 412 | /* The thick arrow up to the next primary child of pDesc goes |
| 391 | 413 | ** further up than the thin merge arrow riser, so draw them both |
| 392 | 414 | ** on the same rail. */ |
| 393 | 415 | pParent->mergeOut = pParent->iRail; |
| 394 | 416 | }else if( pParent->idx - pChild->idx < pParent->selfUp ){ |
| 395 | 417 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -369,26 +369,48 @@ | |
| 369 | p->railInUse |= mask; |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | /* |
| 375 | ** Create a merge-arrow riser going from pParent up to pChild. |
| 376 | */ |
| 377 | static void createMergeRiser( |
| 378 | GraphContext *p, |
| 379 | GraphRow *pParent, |
| 380 | GraphRow *pChild, |
| 381 | int isCherrypick |
| 382 | ){ |
| 383 | int u; |
| 384 | u64 mask; |
| 385 | GraphRow *pLoop; |
| 386 | |
| 387 | if( pParent->mergeOut<0 ){ |
| 388 | u = pParent->aiRiser[pParent->iRail]; |
| 389 | if( u>0 && u<pChild->idx ){ |
| 390 | /* The thick arrow up to the next primary child of pDesc goes |
| 391 | ** further up than the thin merge arrow riser, so draw them both |
| 392 | ** on the same rail. */ |
| 393 | pParent->mergeOut = pParent->iRail; |
| 394 | }else if( pParent->idx - pChild->idx < pParent->selfUp ){ |
| 395 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -369,26 +369,48 @@ | |
| 369 | p->railInUse |= mask; |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | |
| 375 | /* |
| 376 | ** Check to see if rail iRail is clear from pBottom up to and including |
| 377 | ** pTop. |
| 378 | */ |
| 379 | static int railIsClear(GraphRow *pBottom, int iTop, int iRail){ |
| 380 | u64 m = BIT(iRail); |
| 381 | while( pBottom && pBottom->idx>=iTop ){ |
| 382 | if( pBottom->railInUse & m ) return 0; |
| 383 | pBottom = pBottom->pPrev; |
| 384 | } |
| 385 | return 1; |
| 386 | } |
| 387 | |
| 388 | /* |
| 389 | ** Create a merge-arrow riser going from pParent up to pChild. |
| 390 | */ |
| 391 | static void createMergeRiser( |
| 392 | GraphContext *p, |
| 393 | GraphRow *pParent, /* Lower node from which the merge line begins */ |
| 394 | GraphRow *pChild, /* Upper node at which the merge line ends */ |
| 395 | int isCherrypick /* True for a cherry-pick merge */ |
| 396 | ){ |
| 397 | int u; |
| 398 | u64 mask; |
| 399 | GraphRow *pLoop; |
| 400 | |
| 401 | if( pParent->mergeOut<0 ){ |
| 402 | u = pParent->aiRiser[pParent->iRail]; |
| 403 | if( u<0 && railIsClear(pParent->pPrev, pChild->idx-1, pParent->iRail) ){ |
| 404 | /* pParent is a leaf and the merge-line can be drawn straight up.*/ |
| 405 | pParent->mergeOut = pParent->iRail; |
| 406 | mask = BIT(pParent->iRail); |
| 407 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 408 | pLoop=pLoop->pNext){ |
| 409 | pLoop->railInUse |= mask; |
| 410 | } |
| 411 | }else if( u>0 && u<pChild->idx ){ |
| 412 | /* The thick arrow up to the next primary child of pDesc goes |
| 413 | ** further up than the thin merge arrow riser, so draw them both |
| 414 | ** on the same rail. */ |
| 415 | pParent->mergeOut = pParent->iRail; |
| 416 | }else if( pParent->idx - pChild->idx < pParent->selfUp ){ |
| 417 |