Fossil SCM
Merge graph layout enhancements from trunk.
Commit
980adfa6bdc917ffb10e663dfbab9bcfbd0019920626a04f1ddd5c3c76b687e2
Parent
3850b32ceae21d5…
1 file changed
+19
-13
+19
-13
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -73,10 +73,11 @@ | ||
| 73 | 73 | u8 isLeaf; /* True if this is a leaf node */ |
| 74 | 74 | u8 isStepParent; /* pChild is actually a step-child */ |
| 75 | 75 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 76 | 76 | u8 timeWarp; /* Child is earlier in time */ |
| 77 | 77 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 78 | + u8 selfUp; /* Space above this node but belonging */ | |
| 78 | 79 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 79 | 80 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 80 | 81 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 81 | 82 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 82 | 83 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| @@ -319,11 +320,13 @@ | ||
| 319 | 320 | } |
| 320 | 321 | /* Mask of additional rows for the riser to infinity */ |
| 321 | 322 | if( !pPrior->isLeaf && (tmFlags & TIMELINE_DISJOINT)==0 ){ |
| 322 | 323 | int n = RISER_MARGIN; |
| 323 | 324 | GraphRow *p; |
| 325 | + pPrior->selfUp = 0; | |
| 324 | 326 | for(p=pPrior; p && (n--)>0; p=p->pPrev){ |
| 327 | + pPrior->selfUp++; | |
| 325 | 328 | p->railInUse |= mask; |
| 326 | 329 | } |
| 327 | 330 | } |
| 328 | 331 | } |
| 329 | 332 | |
| @@ -345,16 +348,17 @@ | ||
| 345 | 348 | if( u>0 && u<pChild->idx ){ |
| 346 | 349 | /* The thick arrow up to the next primary child of pDesc goes |
| 347 | 350 | ** further up than the thin merge arrow riser, so draw them both |
| 348 | 351 | ** on the same rail. */ |
| 349 | 352 | pParent->mergeOut = pParent->iRail; |
| 353 | + }else if( pParent->idx - pChild->idx < pParent->selfUp ){ | |
| 354 | + pParent->mergeOut = pParent->iRail; | |
| 350 | 355 | }else{ |
| 351 | 356 | /* The thin merge arrow riser is taller than the thick primary |
| 352 | 357 | ** child riser, so use separate rails. */ |
| 353 | 358 | int iTarget = pParent->iRail; |
| 354 | - int iBtm = pParent->idx - (u==0 ? RISER_MARGIN : 1); | |
| 355 | - pParent->mergeOut = findFreeRail(p, pChild->idx, iBtm, iTarget); | |
| 359 | + pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget); | |
| 356 | 360 | mask = BIT(pParent->mergeOut); |
| 357 | 361 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 358 | 362 | pLoop=pLoop->pNext){ |
| 359 | 363 | pLoop->railInUse |= mask; |
| 360 | 364 | } |
| @@ -424,10 +428,11 @@ | ||
| 424 | 428 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 425 | 429 | int i, j; |
| 426 | 430 | u64 mask; |
| 427 | 431 | int hasDup = 0; /* True if one or more isDup entries */ |
| 428 | 432 | const char *zTrunk; |
| 433 | + u8 *aMap; /* Copy of p->aiRailMap */ | |
| 429 | 434 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 430 | 435 | |
| 431 | 436 | /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser |
| 432 | 437 | ** coming up from the bottom of the graph from off-screen check-in Y |
| 433 | 438 | ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0. |
| @@ -719,24 +724,25 @@ | ||
| 719 | 724 | find_max_rail(p); |
| 720 | 725 | |
| 721 | 726 | /* |
| 722 | 727 | ** Compute the rail mapping. |
| 723 | 728 | */ |
| 724 | - for(i=0; i<=p->mxRail; i++) p->aiRailMap[i] = i; | |
| 729 | + aMap = p->aiRailMap; | |
| 730 | + for(i=0; i<=p->mxRail; i++) aMap[i] = i; | |
| 725 | 731 | if( zLeftBranch ){ |
| 726 | 732 | char *zLeft = persistBranchName(p, zLeftBranch); |
| 727 | - for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ | |
| 728 | - if( pRow->zBranch==zLeft ){ | |
| 729 | - int iLeftRail = pRow->iRail; | |
| 730 | - p->aiRailMap[iLeftRail] = 0; | |
| 731 | - for(i=0, j=1; i<=p->mxRail; i++){ | |
| 732 | - if( i==iLeftRail ) continue; | |
| 733 | - p->aiRailMap[i] = j++; | |
| 734 | - } | |
| 735 | - assert( j==p->mxRail+1 ); | |
| 736 | - break; | |
| 733 | + j = 0; | |
| 734 | + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ | |
| 735 | + if( pRow->zBranch==zLeft && aMap[pRow->iRail]>=j ){ | |
| 736 | + for(i=0; i<=p->mxRail; i++){ | |
| 737 | + if( aMap[i]>=j && aMap[i]<=pRow->iRail ) aMap[i]++; | |
| 738 | + } | |
| 739 | + aMap[pRow->iRail] = j++; | |
| 737 | 740 | } |
| 738 | 741 | } |
| 742 | + cgi_printf("<!-- aiRailMap ="); | |
| 743 | + for(i=0; i<=p->mxRail; i++) cgi_printf(" %d", aMap[i]); | |
| 744 | + cgi_printf(" -->\n"); | |
| 739 | 745 | } |
| 740 | 746 | |
| 741 | 747 | p->nErr = 0; |
| 742 | 748 | } |
| 743 | 749 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -73,10 +73,11 @@ | |
| 73 | u8 isLeaf; /* True if this is a leaf node */ |
| 74 | u8 isStepParent; /* pChild is actually a step-child */ |
| 75 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 76 | u8 timeWarp; /* Child is earlier in time */ |
| 77 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 78 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 79 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 80 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 81 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 82 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| @@ -319,11 +320,13 @@ | |
| 319 | } |
| 320 | /* Mask of additional rows for the riser to infinity */ |
| 321 | if( !pPrior->isLeaf && (tmFlags & TIMELINE_DISJOINT)==0 ){ |
| 322 | int n = RISER_MARGIN; |
| 323 | GraphRow *p; |
| 324 | for(p=pPrior; p && (n--)>0; p=p->pPrev){ |
| 325 | p->railInUse |= mask; |
| 326 | } |
| 327 | } |
| 328 | } |
| 329 | |
| @@ -345,16 +348,17 @@ | |
| 345 | if( u>0 && u<pChild->idx ){ |
| 346 | /* The thick arrow up to the next primary child of pDesc goes |
| 347 | ** further up than the thin merge arrow riser, so draw them both |
| 348 | ** on the same rail. */ |
| 349 | pParent->mergeOut = pParent->iRail; |
| 350 | }else{ |
| 351 | /* The thin merge arrow riser is taller than the thick primary |
| 352 | ** child riser, so use separate rails. */ |
| 353 | int iTarget = pParent->iRail; |
| 354 | int iBtm = pParent->idx - (u==0 ? RISER_MARGIN : 1); |
| 355 | pParent->mergeOut = findFreeRail(p, pChild->idx, iBtm, iTarget); |
| 356 | mask = BIT(pParent->mergeOut); |
| 357 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 358 | pLoop=pLoop->pNext){ |
| 359 | pLoop->railInUse |= mask; |
| 360 | } |
| @@ -424,10 +428,11 @@ | |
| 424 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 425 | int i, j; |
| 426 | u64 mask; |
| 427 | int hasDup = 0; /* True if one or more isDup entries */ |
| 428 | const char *zTrunk; |
| 429 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 430 | |
| 431 | /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser |
| 432 | ** coming up from the bottom of the graph from off-screen check-in Y |
| 433 | ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0. |
| @@ -719,24 +724,25 @@ | |
| 719 | find_max_rail(p); |
| 720 | |
| 721 | /* |
| 722 | ** Compute the rail mapping. |
| 723 | */ |
| 724 | for(i=0; i<=p->mxRail; i++) p->aiRailMap[i] = i; |
| 725 | if( zLeftBranch ){ |
| 726 | char *zLeft = persistBranchName(p, zLeftBranch); |
| 727 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 728 | if( pRow->zBranch==zLeft ){ |
| 729 | int iLeftRail = pRow->iRail; |
| 730 | p->aiRailMap[iLeftRail] = 0; |
| 731 | for(i=0, j=1; i<=p->mxRail; i++){ |
| 732 | if( i==iLeftRail ) continue; |
| 733 | p->aiRailMap[i] = j++; |
| 734 | } |
| 735 | assert( j==p->mxRail+1 ); |
| 736 | break; |
| 737 | } |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | p->nErr = 0; |
| 742 | } |
| 743 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -73,10 +73,11 @@ | |
| 73 | u8 isLeaf; /* True if this is a leaf node */ |
| 74 | u8 isStepParent; /* pChild is actually a step-child */ |
| 75 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 76 | u8 timeWarp; /* Child is earlier in time */ |
| 77 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 78 | u8 selfUp; /* Space above this node but belonging */ |
| 79 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 80 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 81 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 82 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 83 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| @@ -319,11 +320,13 @@ | |
| 320 | } |
| 321 | /* Mask of additional rows for the riser to infinity */ |
| 322 | if( !pPrior->isLeaf && (tmFlags & TIMELINE_DISJOINT)==0 ){ |
| 323 | int n = RISER_MARGIN; |
| 324 | GraphRow *p; |
| 325 | pPrior->selfUp = 0; |
| 326 | for(p=pPrior; p && (n--)>0; p=p->pPrev){ |
| 327 | pPrior->selfUp++; |
| 328 | p->railInUse |= mask; |
| 329 | } |
| 330 | } |
| 331 | } |
| 332 | |
| @@ -345,16 +348,17 @@ | |
| 348 | if( u>0 && u<pChild->idx ){ |
| 349 | /* The thick arrow up to the next primary child of pDesc goes |
| 350 | ** further up than the thin merge arrow riser, so draw them both |
| 351 | ** on the same rail. */ |
| 352 | pParent->mergeOut = pParent->iRail; |
| 353 | }else if( pParent->idx - pChild->idx < pParent->selfUp ){ |
| 354 | pParent->mergeOut = pParent->iRail; |
| 355 | }else{ |
| 356 | /* The thin merge arrow riser is taller than the thick primary |
| 357 | ** child riser, so use separate rails. */ |
| 358 | int iTarget = pParent->iRail; |
| 359 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget); |
| 360 | mask = BIT(pParent->mergeOut); |
| 361 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 362 | pLoop=pLoop->pNext){ |
| 363 | pLoop->railInUse |= mask; |
| 364 | } |
| @@ -424,10 +428,11 @@ | |
| 428 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 429 | int i, j; |
| 430 | u64 mask; |
| 431 | int hasDup = 0; /* True if one or more isDup entries */ |
| 432 | const char *zTrunk; |
| 433 | u8 *aMap; /* Copy of p->aiRailMap */ |
| 434 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 435 | |
| 436 | /* If mergeRiserFrom[X]==Y that means rail X holds a merge riser |
| 437 | ** coming up from the bottom of the graph from off-screen check-in Y |
| 438 | ** where Y is the RID. There is no riser on rail X if mergeRiserFrom[X]==0. |
| @@ -719,24 +724,25 @@ | |
| 724 | find_max_rail(p); |
| 725 | |
| 726 | /* |
| 727 | ** Compute the rail mapping. |
| 728 | */ |
| 729 | aMap = p->aiRailMap; |
| 730 | for(i=0; i<=p->mxRail; i++) aMap[i] = i; |
| 731 | if( zLeftBranch ){ |
| 732 | char *zLeft = persistBranchName(p, zLeftBranch); |
| 733 | j = 0; |
| 734 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 735 | if( pRow->zBranch==zLeft && aMap[pRow->iRail]>=j ){ |
| 736 | for(i=0; i<=p->mxRail; i++){ |
| 737 | if( aMap[i]>=j && aMap[i]<=pRow->iRail ) aMap[i]++; |
| 738 | } |
| 739 | aMap[pRow->iRail] = j++; |
| 740 | } |
| 741 | } |
| 742 | cgi_printf("<!-- aiRailMap ="); |
| 743 | for(i=0; i<=p->mxRail; i++) cgi_printf(" %d", aMap[i]); |
| 744 | cgi_printf(" -->\n"); |
| 745 | } |
| 746 | |
| 747 | p->nErr = 0; |
| 748 | } |
| 749 |