Fossil SCM
Improvements to the display of the "Context" graph on check-in /info pages.
Commit
01d8bf97e206fc8eeae4c59e6046a9ae148d6ba8a3e56a17782904ab84199869
Parent
aa149371ed6ade8…
5 files changed
+6
+23
-2
+9
-1
+1
-2
+9
-1
+6
| --- src/default_css.txt | ||
| +++ src/default_css.txt | ||
| @@ -189,10 +189,16 @@ | ||
| 189 | 189 | border-left: 7px solid #600000; |
| 190 | 190 | } |
| 191 | 191 | .tl-line.warp { |
| 192 | 192 | background: #600000; |
| 193 | 193 | } |
| 194 | +.tl-line.dotted { | |
| 195 | + width: 0px; | |
| 196 | + border-top: 0px dotted #888; | |
| 197 | + border-left: 2px dotted #888; | |
| 198 | + background: rgba(255,255,255,0); | |
| 199 | +} | |
| 194 | 200 | span.tagDsp { |
| 195 | 201 | font-weight: bold; |
| 196 | 202 | } |
| 197 | 203 | span.wikiError { |
| 198 | 204 | font-weight: bold; |
| 199 | 205 |
| --- src/default_css.txt | |
| +++ src/default_css.txt | |
| @@ -189,10 +189,16 @@ | |
| 189 | border-left: 7px solid #600000; |
| 190 | } |
| 191 | .tl-line.warp { |
| 192 | background: #600000; |
| 193 | } |
| 194 | span.tagDsp { |
| 195 | font-weight: bold; |
| 196 | } |
| 197 | span.wikiError { |
| 198 | font-weight: bold; |
| 199 |
| --- src/default_css.txt | |
| +++ src/default_css.txt | |
| @@ -189,10 +189,16 @@ | |
| 189 | border-left: 7px solid #600000; |
| 190 | } |
| 191 | .tl-line.warp { |
| 192 | background: #600000; |
| 193 | } |
| 194 | .tl-line.dotted { |
| 195 | width: 0px; |
| 196 | border-top: 0px dotted #888; |
| 197 | border-left: 2px dotted #888; |
| 198 | background: rgba(255,255,255,0); |
| 199 | } |
| 200 | span.tagDsp { |
| 201 | font-weight: bold; |
| 202 | } |
| 203 | span.wikiError { |
| 204 | font-weight: bold; |
| 205 |
+23
-2
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -49,10 +49,11 @@ | ||
| 49 | 49 | int idx; /* Row index. First is 1. 0 used for "none" */ |
| 50 | 50 | int idxTop; /* Direct descendent highest up on the graph */ |
| 51 | 51 | GraphRow *pChild; /* Child immediately above this node */ |
| 52 | 52 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 53 | 53 | u8 isLeaf; /* True if this is a leaf node */ |
| 54 | + u8 isStepParent; /* pChild is actually a step-child */ | |
| 54 | 55 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 55 | 56 | u8 timeWarp; /* Child is earlier in time */ |
| 56 | 57 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 57 | 58 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 58 | 59 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| @@ -69,12 +70,12 @@ | ||
| 69 | 70 | /* Context while building a graph |
| 70 | 71 | */ |
| 71 | 72 | struct GraphContext { |
| 72 | 73 | int nErr; /* Number of errors encountered */ |
| 73 | 74 | int mxRail; /* Number of rails required to render the graph */ |
| 74 | - GraphRow *pFirst; /* First row in the list */ | |
| 75 | - GraphRow *pLast; /* Last row in the list */ | |
| 75 | + GraphRow *pFirst; /* First row in the list. Top row of graph. */ | |
| 76 | + GraphRow *pLast; /* Last row in the list. Bottom row of graph. */ | |
| 76 | 77 | int nBranch; /* Number of distinct branches */ |
| 77 | 78 | char **azBranch; /* Names of the branches */ |
| 78 | 79 | int nRow; /* Number of rows */ |
| 79 | 80 | int nHash; /* Number of slots in apHash[] */ |
| 80 | 81 | GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ |
| @@ -477,10 +478,30 @@ | ||
| 477 | 478 | if( pRow->idxTop < pParent->idxTop ){ |
| 478 | 479 | pParent->pChild = pRow; |
| 479 | 480 | pParent->idxTop = pRow->idxTop; |
| 480 | 481 | } |
| 481 | 482 | } |
| 483 | + | |
| 484 | + /* If a node has no pChild, and there is a later node (a node higher | |
| 485 | + ** up on the graph) in the same branch that has no parent, then make | |
| 486 | + ** the lower node a step-child of the upper node. | |
| 487 | + */ | |
| 488 | + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ | |
| 489 | + if( pRow->pChild ) continue; | |
| 490 | + for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){ | |
| 491 | + if( pLoop->nParent>0 | |
| 492 | + && pLoop->zBranch==pRow->zBranch | |
| 493 | + && hashFind(p,pLoop->aParent[0])==0 | |
| 494 | + ){ | |
| 495 | + pRow->pChild = pLoop; | |
| 496 | + pRow->idxTop = pLoop->idxTop; | |
| 497 | + pRow->isStepParent = 1; | |
| 498 | + pLoop->aParent[0] = pRow->rid; | |
| 499 | + break; | |
| 500 | + } | |
| 501 | + } | |
| 502 | + } | |
| 482 | 503 | |
| 483 | 504 | /* Identify rows where the primary parent is off screen. Assign |
| 484 | 505 | ** each to a rail and draw descenders to the bottom of the screen. |
| 485 | 506 | ** |
| 486 | 507 | ** Strive to put the "trunk" branch on far left. |
| 487 | 508 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -49,10 +49,11 @@ | |
| 49 | int idx; /* Row index. First is 1. 0 used for "none" */ |
| 50 | int idxTop; /* Direct descendent highest up on the graph */ |
| 51 | GraphRow *pChild; /* Child immediately above this node */ |
| 52 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 53 | u8 isLeaf; /* True if this is a leaf node */ |
| 54 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 55 | u8 timeWarp; /* Child is earlier in time */ |
| 56 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 57 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 58 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| @@ -69,12 +70,12 @@ | |
| 69 | /* Context while building a graph |
| 70 | */ |
| 71 | struct GraphContext { |
| 72 | int nErr; /* Number of errors encountered */ |
| 73 | int mxRail; /* Number of rails required to render the graph */ |
| 74 | GraphRow *pFirst; /* First row in the list */ |
| 75 | GraphRow *pLast; /* Last row in the list */ |
| 76 | int nBranch; /* Number of distinct branches */ |
| 77 | char **azBranch; /* Names of the branches */ |
| 78 | int nRow; /* Number of rows */ |
| 79 | int nHash; /* Number of slots in apHash[] */ |
| 80 | GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ |
| @@ -477,10 +478,30 @@ | |
| 477 | if( pRow->idxTop < pParent->idxTop ){ |
| 478 | pParent->pChild = pRow; |
| 479 | pParent->idxTop = pRow->idxTop; |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | /* Identify rows where the primary parent is off screen. Assign |
| 484 | ** each to a rail and draw descenders to the bottom of the screen. |
| 485 | ** |
| 486 | ** Strive to put the "trunk" branch on far left. |
| 487 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -49,10 +49,11 @@ | |
| 49 | int idx; /* Row index. First is 1. 0 used for "none" */ |
| 50 | int idxTop; /* Direct descendent highest up on the graph */ |
| 51 | GraphRow *pChild; /* Child immediately above this node */ |
| 52 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 53 | u8 isLeaf; /* True if this is a leaf node */ |
| 54 | u8 isStepParent; /* pChild is actually a step-child */ |
| 55 | u8 hasNormalOutMerge; /* Is parent of at laest 1 non-cherrypick merge */ |
| 56 | u8 timeWarp; /* Child is earlier in time */ |
| 57 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 58 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 59 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| @@ -69,12 +70,12 @@ | |
| 70 | /* Context while building a graph |
| 71 | */ |
| 72 | struct GraphContext { |
| 73 | int nErr; /* Number of errors encountered */ |
| 74 | int mxRail; /* Number of rails required to render the graph */ |
| 75 | GraphRow *pFirst; /* First row in the list. Top row of graph. */ |
| 76 | GraphRow *pLast; /* Last row in the list. Bottom row of graph. */ |
| 77 | int nBranch; /* Number of distinct branches */ |
| 78 | char **azBranch; /* Names of the branches */ |
| 79 | int nRow; /* Number of rows */ |
| 80 | int nHash; /* Number of slots in apHash[] */ |
| 81 | GraphRow **apHash; /* Hash table of GraphRow objects. Key: rid */ |
| @@ -477,10 +478,30 @@ | |
| 478 | if( pRow->idxTop < pParent->idxTop ){ |
| 479 | pParent->pChild = pRow; |
| 480 | pParent->idxTop = pRow->idxTop; |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | /* If a node has no pChild, and there is a later node (a node higher |
| 485 | ** up on the graph) in the same branch that has no parent, then make |
| 486 | ** the lower node a step-child of the upper node. |
| 487 | */ |
| 488 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 489 | if( pRow->pChild ) continue; |
| 490 | for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){ |
| 491 | if( pLoop->nParent>0 |
| 492 | && pLoop->zBranch==pRow->zBranch |
| 493 | && hashFind(p,pLoop->aParent[0])==0 |
| 494 | ){ |
| 495 | pRow->pChild = pLoop; |
| 496 | pRow->idxTop = pLoop->idxTop; |
| 497 | pRow->isStepParent = 1; |
| 498 | pLoop->aParent[0] = pRow->rid; |
| 499 | break; |
| 500 | } |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | /* Identify rows where the primary parent is off screen. Assign |
| 505 | ** each to a rail and draw descenders to the bottom of the screen. |
| 506 | ** |
| 507 | ** Strive to put the "trunk" branch on far left. |
| 508 |
+9
-1
| --- src/graph.js | ||
| +++ src/graph.js | ||
| @@ -92,11 +92,11 @@ | ||
| 92 | 92 | |
| 93 | 93 | var elems = {}; |
| 94 | 94 | var elemClasses = [ |
| 95 | 95 | "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", |
| 96 | 96 | "arrow merge r", "line merge", "arrow warp", "line warp", |
| 97 | - "line cherrypick" | |
| 97 | + "line cherrypick", "line dotted" | |
| 98 | 98 | ]; |
| 99 | 99 | for( var i=0; i<elemClasses.length; i++ ){ |
| 100 | 100 | var cls = elemClasses[i]; |
| 101 | 101 | var elem = document.createElement("div"); |
| 102 | 102 | elem.className = "tl-" + cls; |
| @@ -115,10 +115,11 @@ | ||
| 115 | 115 | mArrow = elems.arrow_merge_r; |
| 116 | 116 | mLine = elems.line_merge; |
| 117 | 117 | cpLine = elems.line_cherrypick; |
| 118 | 118 | wArrow = elems.arrow_warp; |
| 119 | 119 | wLine = elems.line_warp; |
| 120 | + dotLine = elems.line_dotted; | |
| 120 | 121 | |
| 121 | 122 | var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); |
| 122 | 123 | if( window.innerWidth<400 ){ |
| 123 | 124 | railPitch = minRailPitch; |
| 124 | 125 | }else{ |
| @@ -196,10 +197,16 @@ | ||
| 196 | 197 | drawLine(line,color,x,y0,null,y1); |
| 197 | 198 | x = to.x + (node.w-arw.w)/2; |
| 198 | 199 | var n = drawBox(arw.cls,null,x,y); |
| 199 | 200 | if(color) n.style.borderBottomColor = color; |
| 200 | 201 | } |
| 202 | + function drawUpDotted(from,to,color){ | |
| 203 | + var x = to.x + (node.w-line.w)/2; | |
| 204 | + var y0 = from.y + node.h/2; | |
| 205 | + var y1 = Math.ceil(to.y + node.h); | |
| 206 | + drawLine(dotLine,color,x,y0,null,y1); | |
| 207 | + } | |
| 201 | 208 | /* Draw thin horizontal or vertical lines representing merges */ |
| 202 | 209 | function drawMergeLine(x0,y0,x1,y1){ |
| 203 | 210 | drawLine(mLine,null,x0,y0,x1,y1); |
| 204 | 211 | } |
| 205 | 212 | function drawCherrypickLine(x0,y0,x1,y1){ |
| @@ -236,10 +243,11 @@ | ||
| 236 | 243 | e = document.getElementById("md"+p.id); |
| 237 | 244 | if(e) e.style.backgroundColor = p.bg; |
| 238 | 245 | } |
| 239 | 246 | if( p.r<0 ) return; |
| 240 | 247 | if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg); |
| 248 | + if( p.sb>0 ) drawUpDotted(p,tx.rowinfo[p.sb-tx.iTopRow],p.fg); | |
| 241 | 249 | var cls = node.cls; |
| 242 | 250 | if( p.hasOwnProperty('mi') && p.mi.length ) cls += " merge"; |
| 243 | 251 | if( p.f&1 ) cls += " leaf"; |
| 244 | 252 | var n = drawBox(cls,p.bg,p.x,p.y); |
| 245 | 253 | n.id = "tln"+p.id; |
| 246 | 254 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -92,11 +92,11 @@ | |
| 92 | |
| 93 | var elems = {}; |
| 94 | var elemClasses = [ |
| 95 | "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", |
| 96 | "arrow merge r", "line merge", "arrow warp", "line warp", |
| 97 | "line cherrypick" |
| 98 | ]; |
| 99 | for( var i=0; i<elemClasses.length; i++ ){ |
| 100 | var cls = elemClasses[i]; |
| 101 | var elem = document.createElement("div"); |
| 102 | elem.className = "tl-" + cls; |
| @@ -115,10 +115,11 @@ | |
| 115 | mArrow = elems.arrow_merge_r; |
| 116 | mLine = elems.line_merge; |
| 117 | cpLine = elems.line_cherrypick; |
| 118 | wArrow = elems.arrow_warp; |
| 119 | wLine = elems.line_warp; |
| 120 | |
| 121 | var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); |
| 122 | if( window.innerWidth<400 ){ |
| 123 | railPitch = minRailPitch; |
| 124 | }else{ |
| @@ -196,10 +197,16 @@ | |
| 196 | drawLine(line,color,x,y0,null,y1); |
| 197 | x = to.x + (node.w-arw.w)/2; |
| 198 | var n = drawBox(arw.cls,null,x,y); |
| 199 | if(color) n.style.borderBottomColor = color; |
| 200 | } |
| 201 | /* Draw thin horizontal or vertical lines representing merges */ |
| 202 | function drawMergeLine(x0,y0,x1,y1){ |
| 203 | drawLine(mLine,null,x0,y0,x1,y1); |
| 204 | } |
| 205 | function drawCherrypickLine(x0,y0,x1,y1){ |
| @@ -236,10 +243,11 @@ | |
| 236 | e = document.getElementById("md"+p.id); |
| 237 | if(e) e.style.backgroundColor = p.bg; |
| 238 | } |
| 239 | if( p.r<0 ) return; |
| 240 | if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg); |
| 241 | var cls = node.cls; |
| 242 | if( p.hasOwnProperty('mi') && p.mi.length ) cls += " merge"; |
| 243 | if( p.f&1 ) cls += " leaf"; |
| 244 | var n = drawBox(cls,p.bg,p.x,p.y); |
| 245 | n.id = "tln"+p.id; |
| 246 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -92,11 +92,11 @@ | |
| 92 | |
| 93 | var elems = {}; |
| 94 | var elemClasses = [ |
| 95 | "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", |
| 96 | "arrow merge r", "line merge", "arrow warp", "line warp", |
| 97 | "line cherrypick", "line dotted" |
| 98 | ]; |
| 99 | for( var i=0; i<elemClasses.length; i++ ){ |
| 100 | var cls = elemClasses[i]; |
| 101 | var elem = document.createElement("div"); |
| 102 | elem.className = "tl-" + cls; |
| @@ -115,10 +115,11 @@ | |
| 115 | mArrow = elems.arrow_merge_r; |
| 116 | mLine = elems.line_merge; |
| 117 | cpLine = elems.line_cherrypick; |
| 118 | wArrow = elems.arrow_warp; |
| 119 | wLine = elems.line_warp; |
| 120 | dotLine = elems.line_dotted; |
| 121 | |
| 122 | var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); |
| 123 | if( window.innerWidth<400 ){ |
| 124 | railPitch = minRailPitch; |
| 125 | }else{ |
| @@ -196,10 +197,16 @@ | |
| 197 | drawLine(line,color,x,y0,null,y1); |
| 198 | x = to.x + (node.w-arw.w)/2; |
| 199 | var n = drawBox(arw.cls,null,x,y); |
| 200 | if(color) n.style.borderBottomColor = color; |
| 201 | } |
| 202 | function drawUpDotted(from,to,color){ |
| 203 | var x = to.x + (node.w-line.w)/2; |
| 204 | var y0 = from.y + node.h/2; |
| 205 | var y1 = Math.ceil(to.y + node.h); |
| 206 | drawLine(dotLine,color,x,y0,null,y1); |
| 207 | } |
| 208 | /* Draw thin horizontal or vertical lines representing merges */ |
| 209 | function drawMergeLine(x0,y0,x1,y1){ |
| 210 | drawLine(mLine,null,x0,y0,x1,y1); |
| 211 | } |
| 212 | function drawCherrypickLine(x0,y0,x1,y1){ |
| @@ -236,10 +243,11 @@ | |
| 243 | e = document.getElementById("md"+p.id); |
| 244 | if(e) e.style.backgroundColor = p.bg; |
| 245 | } |
| 246 | if( p.r<0 ) return; |
| 247 | if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg); |
| 248 | if( p.sb>0 ) drawUpDotted(p,tx.rowinfo[p.sb-tx.iTopRow],p.fg); |
| 249 | var cls = node.cls; |
| 250 | if( p.hasOwnProperty('mi') && p.mi.length ) cls += " merge"; |
| 251 | if( p.f&1 ) cls += " leaf"; |
| 252 | var n = drawBox(cls,p.bg,p.x,p.y); |
| 253 | n.id = "tln"+p.id; |
| 254 |
+1
-2
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -281,12 +281,11 @@ | ||
| 281 | 281 | } |
| 282 | 282 | } |
| 283 | 283 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 284 | 284 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 285 | 285 | www_print_timeline(&q, |
| 286 | - TIMELINE_DISJOINT | |
| 287 | - |TIMELINE_GRAPH | |
| 286 | + TIMELINE_GRAPH | |
| 288 | 287 | |TIMELINE_NOSCROLL |
| 289 | 288 | |TIMELINE_CHPICK, |
| 290 | 289 | 0, 0, rid, 0); |
| 291 | 290 | db_finalize(&q); |
| 292 | 291 | } |
| 293 | 292 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -281,12 +281,11 @@ | |
| 281 | } |
| 282 | } |
| 283 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 284 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 285 | www_print_timeline(&q, |
| 286 | TIMELINE_DISJOINT |
| 287 | |TIMELINE_GRAPH |
| 288 | |TIMELINE_NOSCROLL |
| 289 | |TIMELINE_CHPICK, |
| 290 | 0, 0, rid, 0); |
| 291 | db_finalize(&q); |
| 292 | } |
| 293 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -281,12 +281,11 @@ | |
| 281 | } |
| 282 | } |
| 283 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 284 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 285 | www_print_timeline(&q, |
| 286 | TIMELINE_GRAPH |
| 287 | |TIMELINE_NOSCROLL |
| 288 | |TIMELINE_CHPICK, |
| 289 | 0, 0, rid, 0); |
| 290 | db_finalize(&q); |
| 291 | } |
| 292 |
+9
-1
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -879,10 +879,14 @@ | ||
| 879 | 879 | ** cu: Extend the mu merge arrow up to this row as a cherrypick |
| 880 | 880 | ** merge line, if this value exists. |
| 881 | 881 | ** u: Draw a thick child-line out of the top of this node and up to |
| 882 | 882 | ** the node with an id equal to this value. 0 if it is straight to |
| 883 | 883 | ** the top of the page, -1 if there is no thick-line riser. |
| 884 | + ** sb: Draw a dotted child-line out of the top of this node up to the | |
| 885 | + ** node with the id equal to the value. This is like "u" except | |
| 886 | + ** that the line is dotted instead of solid and has no arrow. | |
| 887 | + ** Mnemonic: "Same Branch". | |
| 884 | 888 | ** f: 0x01: a leaf node. |
| 885 | 889 | ** au: An array of integers that define thick-line risers for branches. |
| 886 | 890 | ** The integers are in pairs. For each pair, the first integer is |
| 887 | 891 | ** is the rail on which the riser should run and the second integer |
| 888 | 892 | ** is the id of the node upto which the riser should run. If there |
| @@ -911,11 +915,15 @@ | ||
| 911 | 915 | cgi_printf("\"mu\":%d,", pRow->mergeUpto); |
| 912 | 916 | if( pRow->cherrypickUpto>0 && pRow->cherrypickUpto<pRow->mergeUpto ){ |
| 913 | 917 | cgi_printf("\"cu\":%d,", pRow->cherrypickUpto); |
| 914 | 918 | } |
| 915 | 919 | } |
| 916 | - cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]); | |
| 920 | + if( pRow->isStepParent ){ | |
| 921 | + cgi_printf("\"sb\":%d,", pRow->aiRiser[pRow->iRail]); | |
| 922 | + }else{ | |
| 923 | + cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]); | |
| 924 | + } | |
| 917 | 925 | k = 0; |
| 918 | 926 | if( pRow->isLeaf ) k |= 1; |
| 919 | 927 | cgi_printf("\"f\":%d,",k); |
| 920 | 928 | for(i=k=0; i<GR_MAX_RAIL; i++){ |
| 921 | 929 | if( i==pRow->iRail ) continue; |
| 922 | 930 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -879,10 +879,14 @@ | |
| 879 | ** cu: Extend the mu merge arrow up to this row as a cherrypick |
| 880 | ** merge line, if this value exists. |
| 881 | ** u: Draw a thick child-line out of the top of this node and up to |
| 882 | ** the node with an id equal to this value. 0 if it is straight to |
| 883 | ** the top of the page, -1 if there is no thick-line riser. |
| 884 | ** f: 0x01: a leaf node. |
| 885 | ** au: An array of integers that define thick-line risers for branches. |
| 886 | ** The integers are in pairs. For each pair, the first integer is |
| 887 | ** is the rail on which the riser should run and the second integer |
| 888 | ** is the id of the node upto which the riser should run. If there |
| @@ -911,11 +915,15 @@ | |
| 911 | cgi_printf("\"mu\":%d,", pRow->mergeUpto); |
| 912 | if( pRow->cherrypickUpto>0 && pRow->cherrypickUpto<pRow->mergeUpto ){ |
| 913 | cgi_printf("\"cu\":%d,", pRow->cherrypickUpto); |
| 914 | } |
| 915 | } |
| 916 | cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]); |
| 917 | k = 0; |
| 918 | if( pRow->isLeaf ) k |= 1; |
| 919 | cgi_printf("\"f\":%d,",k); |
| 920 | for(i=k=0; i<GR_MAX_RAIL; i++){ |
| 921 | if( i==pRow->iRail ) continue; |
| 922 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -879,10 +879,14 @@ | |
| 879 | ** cu: Extend the mu merge arrow up to this row as a cherrypick |
| 880 | ** merge line, if this value exists. |
| 881 | ** u: Draw a thick child-line out of the top of this node and up to |
| 882 | ** the node with an id equal to this value. 0 if it is straight to |
| 883 | ** the top of the page, -1 if there is no thick-line riser. |
| 884 | ** sb: Draw a dotted child-line out of the top of this node up to the |
| 885 | ** node with the id equal to the value. This is like "u" except |
| 886 | ** that the line is dotted instead of solid and has no arrow. |
| 887 | ** Mnemonic: "Same Branch". |
| 888 | ** f: 0x01: a leaf node. |
| 889 | ** au: An array of integers that define thick-line risers for branches. |
| 890 | ** The integers are in pairs. For each pair, the first integer is |
| 891 | ** is the rail on which the riser should run and the second integer |
| 892 | ** is the id of the node upto which the riser should run. If there |
| @@ -911,11 +915,15 @@ | |
| 915 | cgi_printf("\"mu\":%d,", pRow->mergeUpto); |
| 916 | if( pRow->cherrypickUpto>0 && pRow->cherrypickUpto<pRow->mergeUpto ){ |
| 917 | cgi_printf("\"cu\":%d,", pRow->cherrypickUpto); |
| 918 | } |
| 919 | } |
| 920 | if( pRow->isStepParent ){ |
| 921 | cgi_printf("\"sb\":%d,", pRow->aiRiser[pRow->iRail]); |
| 922 | }else{ |
| 923 | cgi_printf("\"u\":%d,", pRow->aiRiser[pRow->iRail]); |
| 924 | } |
| 925 | k = 0; |
| 926 | if( pRow->isLeaf ) k |= 1; |
| 927 | cgi_printf("\"f\":%d,",k); |
| 928 | for(i=k=0; i<GR_MAX_RAIL; i++){ |
| 929 | if( i==pRow->iRail ) continue; |
| 930 |