Fossil SCM

Change the graph layout to include ascenders for nodes that have off-screen children. Fix a bug in the leaf-tracker that became evident by this enhancement. (A rebuild is required to rebuild the leaf table after updating, or else some timeline graphs will not display correctly.)

drh 2011-03-15 01:34 trunk
Commit d7a0240f3963be22136155b857d52a60c28e11c5
+2 -2
--- src/finfo.c
+++ src/finfo.c
@@ -246,11 +246,11 @@
246246
int gidx;
247247
char zTime[10];
248248
char zShort[20];
249249
char zShortCkin[20];
250250
if( zBr==0 ) zBr = "trunk";
251
- gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr);
251
+ gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1);
252252
if( memcmp(zDate, zPrevDate, 10) ){
253253
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254254
@ <tr><td>
255255
@ <div class="divider">%s(zPrevDate)</div>
256256
@ </td></tr>
@@ -301,8 +301,8 @@
301301
@ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
302302
@ </td></tr>
303303
}
304304
}
305305
@ </table>
306
- timeline_output_graph_javascript(pGraph);
306
+ timeline_output_graph_javascript(pGraph, 1);
307307
style_footer();
308308
}
309309
--- src/finfo.c
+++ src/finfo.c
@@ -246,11 +246,11 @@
246 int gidx;
247 char zTime[10];
248 char zShort[20];
249 char zShortCkin[20];
250 if( zBr==0 ) zBr = "trunk";
251 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr);
252 if( memcmp(zDate, zPrevDate, 10) ){
253 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254 @ <tr><td>
255 @ <div class="divider">%s(zPrevDate)</div>
256 @ </td></tr>
@@ -301,8 +301,8 @@
301 @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
302 @ </td></tr>
303 }
304 }
305 @ </table>
306 timeline_output_graph_javascript(pGraph);
307 style_footer();
308 }
309
--- src/finfo.c
+++ src/finfo.c
@@ -246,11 +246,11 @@
246 int gidx;
247 char zTime[10];
248 char zShort[20];
249 char zShortCkin[20];
250 if( zBr==0 ) zBr = "trunk";
251 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1);
252 if( memcmp(zDate, zPrevDate, 10) ){
253 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254 @ <tr><td>
255 @ <div class="divider">%s(zPrevDate)</div>
256 @ </td></tr>
@@ -301,8 +301,8 @@
301 @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
302 @ </td></tr>
303 }
304 }
305 @ </table>
306 timeline_output_graph_javascript(pGraph, 1);
307 style_footer();
308 }
309
+23 -3
--- src/graph.c
+++ src/graph.c
@@ -42,10 +42,12 @@
4242
4343
int idx; /* Row index. First is 1. 0 used for "none" */
4444
int idxTop; /* Direct descendent highest up on the graph */
4545
GraphRow *pChild; /* Child immediately above this node */
4646
u8 isDup; /* True if this is duplicate of a prior entry */
47
+ u8 isLeaf; /* True if this is a leaf node */
48
+ u8 timeWarp; /* Child is earlier in time */
4749
u8 bDescender; /* True if riser from bottom of graph to here. */
4850
i8 iRail; /* Which rail this check-in appears on. 0-based.*/
4951
i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */
5052
u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */
5153
int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
@@ -163,11 +165,12 @@
163165
GraphContext *p, /* The context to which the row is added */
164166
int rid, /* RID for the check-in */
165167
int nParent, /* Number of parents */
166168
int *aParent, /* Array of parents */
167169
const char *zBranch, /* Branch for this check-in */
168
- const char *zBgClr /* Background color. NULL or "" for white. */
170
+ const char *zBgClr, /* Background color. NULL or "" for white. */
171
+ int isLeaf /* True if this row is a leaf */
169172
){
170173
GraphRow *pRow;
171174
int nByte;
172175
173176
if( p->nErr ) return 0;
@@ -176,10 +179,12 @@
176179
pRow = (GraphRow*)safeMalloc( nByte );
177180
pRow->aParent = (int*)&pRow[1];
178181
pRow->rid = rid;
179182
pRow->nParent = nParent;
180183
pRow->zBranch = persistBranchName(p, zBranch);
184
+ pRow->isLeaf = isLeaf;
185
+ memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
181186
if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white";
182187
pRow->zBgClr = persistBranchName(p, zBgClr);
183188
memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
184189
if( p->pFirst==0 ){
185190
p->pFirst = pRow;
@@ -224,10 +229,11 @@
224229
iBest = i;
225230
}
226231
}
227232
}
228233
if( iBestDist>1000 ) p->nErr++;
234
+ if( iBest>p->mxRail ) p->mxRail = iBest;
229235
return iBest;
230236
}
231237
232238
/*
233239
** Assign all children of node pBottom to the same rail as pBottom.
@@ -356,11 +362,14 @@
356362
if( pRow->isDup ) continue;
357363
if( pRow->nParent==0 ) continue; /* Root node */
358364
pParent = hashFind(p, pRow->aParent[0]);
359365
if( pParent==0 ) continue; /* Parent off-screen */
360366
if( pParent->zBranch!=pRow->zBranch ) continue; /* Different branch */
361
- if( pParent->idx <= pRow->idx ) continue; /* Time-warp */
367
+ if( pParent->idx <= pRow->idx ){
368
+ pParent->timeWarp = 1;
369
+ continue; /* Time-warp */
370
+ }
362371
if( pRow->idxTop < pParent->idxTop ){
363372
pParent->pChild = pRow;
364373
pParent->idxTop = pRow->idxTop;
365374
}
366375
}
@@ -401,11 +410,21 @@
401410
inUse = (1<<(p->mxRail+1))-1;
402411
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
403412
int parentRid;
404413
405414
if( pRow->iRail>=0 ){
406
- if( pRow->pChild==0 ) inUse &= ~(1<<pRow->iRail);
415
+ if( pRow->pChild==0 && !pRow->timeWarp ){
416
+ if( pRow->isLeaf || omitDescenders ){
417
+ inUse &= ~(1<<pRow->iRail);
418
+ }else{
419
+ pRow->aiRiser[pRow->iRail] = 0;
420
+ mask = 1<<pRow->iRail;
421
+ for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
422
+ pLoop->railInUse |= mask;
423
+ }
424
+ }
425
+ }
407426
continue;
408427
}
409428
if( pRow->isDup ){
410429
pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
411430
pDesc = pRow;
@@ -431,10 +450,11 @@
431450
if( iDownRail<1 ) iDownRail = ++p->mxRail;
432451
pRow->iRail = ++p->mxRail;
433452
pRow->railInUse = 1<<pRow->iRail;
434453
pParent->aiRiser[iDownRail] = pRow->idx;
435454
mask = 1<<iDownRail;
455
+ inUse |= mask;
436456
for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
437457
pLoop->railInUse |= mask;
438458
}
439459
}
440460
}
441461
--- src/graph.c
+++ src/graph.c
@@ -42,10 +42,12 @@
42
43 int idx; /* Row index. First is 1. 0 used for "none" */
44 int idxTop; /* Direct descendent highest up on the graph */
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. */
@@ -163,11 +165,12 @@
163 GraphContext *p, /* The context to which the row is added */
164 int rid, /* RID for the check-in */
165 int nParent, /* Number of parents */
166 int *aParent, /* Array of parents */
167 const char *zBranch, /* Branch for this check-in */
168 const char *zBgClr /* Background color. NULL or "" for white. */
 
169 ){
170 GraphRow *pRow;
171 int nByte;
172
173 if( p->nErr ) return 0;
@@ -176,10 +179,12 @@
176 pRow = (GraphRow*)safeMalloc( nByte );
177 pRow->aParent = (int*)&pRow[1];
178 pRow->rid = rid;
179 pRow->nParent = nParent;
180 pRow->zBranch = persistBranchName(p, zBranch);
 
 
181 if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white";
182 pRow->zBgClr = persistBranchName(p, zBgClr);
183 memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
184 if( p->pFirst==0 ){
185 p->pFirst = pRow;
@@ -224,10 +229,11 @@
224 iBest = i;
225 }
226 }
227 }
228 if( iBestDist>1000 ) p->nErr++;
 
229 return iBest;
230 }
231
232 /*
233 ** Assign all children of node pBottom to the same rail as pBottom.
@@ -356,11 +362,14 @@
356 if( pRow->isDup ) continue;
357 if( pRow->nParent==0 ) continue; /* Root node */
358 pParent = hashFind(p, pRow->aParent[0]);
359 if( pParent==0 ) continue; /* Parent off-screen */
360 if( pParent->zBranch!=pRow->zBranch ) continue; /* Different branch */
361 if( pParent->idx <= pRow->idx ) continue; /* Time-warp */
 
 
 
362 if( pRow->idxTop < pParent->idxTop ){
363 pParent->pChild = pRow;
364 pParent->idxTop = pRow->idxTop;
365 }
366 }
@@ -401,11 +410,21 @@
401 inUse = (1<<(p->mxRail+1))-1;
402 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
403 int parentRid;
404
405 if( pRow->iRail>=0 ){
406 if( pRow->pChild==0 ) inUse &= ~(1<<pRow->iRail);
 
 
 
 
 
 
 
 
 
 
407 continue;
408 }
409 if( pRow->isDup ){
410 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
411 pDesc = pRow;
@@ -431,10 +450,11 @@
431 if( iDownRail<1 ) iDownRail = ++p->mxRail;
432 pRow->iRail = ++p->mxRail;
433 pRow->railInUse = 1<<pRow->iRail;
434 pParent->aiRiser[iDownRail] = pRow->idx;
435 mask = 1<<iDownRail;
 
436 for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
437 pLoop->railInUse |= mask;
438 }
439 }
440 }
441
--- src/graph.c
+++ src/graph.c
@@ -42,10 +42,12 @@
42
43 int idx; /* Row index. First is 1. 0 used for "none" */
44 int idxTop; /* Direct descendent highest up on the graph */
45 GraphRow *pChild; /* Child immediately above this node */
46 u8 isDup; /* True if this is duplicate of a prior entry */
47 u8 isLeaf; /* True if this is a leaf node */
48 u8 timeWarp; /* Child is earlier in time */
49 u8 bDescender; /* True if riser from bottom of graph to here. */
50 i8 iRail; /* Which rail this check-in appears on. 0-based.*/
51 i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */
52 u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */
53 int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
@@ -163,11 +165,12 @@
165 GraphContext *p, /* The context to which the row is added */
166 int rid, /* RID for the check-in */
167 int nParent, /* Number of parents */
168 int *aParent, /* Array of parents */
169 const char *zBranch, /* Branch for this check-in */
170 const char *zBgClr, /* Background color. NULL or "" for white. */
171 int isLeaf /* True if this row is a leaf */
172 ){
173 GraphRow *pRow;
174 int nByte;
175
176 if( p->nErr ) return 0;
@@ -176,10 +179,12 @@
179 pRow = (GraphRow*)safeMalloc( nByte );
180 pRow->aParent = (int*)&pRow[1];
181 pRow->rid = rid;
182 pRow->nParent = nParent;
183 pRow->zBranch = persistBranchName(p, zBranch);
184 pRow->isLeaf = isLeaf;
185 memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
186 if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white";
187 pRow->zBgClr = persistBranchName(p, zBgClr);
188 memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
189 if( p->pFirst==0 ){
190 p->pFirst = pRow;
@@ -224,10 +229,11 @@
229 iBest = i;
230 }
231 }
232 }
233 if( iBestDist>1000 ) p->nErr++;
234 if( iBest>p->mxRail ) p->mxRail = iBest;
235 return iBest;
236 }
237
238 /*
239 ** Assign all children of node pBottom to the same rail as pBottom.
@@ -356,11 +362,14 @@
362 if( pRow->isDup ) continue;
363 if( pRow->nParent==0 ) continue; /* Root node */
364 pParent = hashFind(p, pRow->aParent[0]);
365 if( pParent==0 ) continue; /* Parent off-screen */
366 if( pParent->zBranch!=pRow->zBranch ) continue; /* Different branch */
367 if( pParent->idx <= pRow->idx ){
368 pParent->timeWarp = 1;
369 continue; /* Time-warp */
370 }
371 if( pRow->idxTop < pParent->idxTop ){
372 pParent->pChild = pRow;
373 pParent->idxTop = pRow->idxTop;
374 }
375 }
@@ -401,11 +410,21 @@
410 inUse = (1<<(p->mxRail+1))-1;
411 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
412 int parentRid;
413
414 if( pRow->iRail>=0 ){
415 if( pRow->pChild==0 && !pRow->timeWarp ){
416 if( pRow->isLeaf || omitDescenders ){
417 inUse &= ~(1<<pRow->iRail);
418 }else{
419 pRow->aiRiser[pRow->iRail] = 0;
420 mask = 1<<pRow->iRail;
421 for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
422 pLoop->railInUse |= mask;
423 }
424 }
425 }
426 continue;
427 }
428 if( pRow->isDup ){
429 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
430 pDesc = pRow;
@@ -431,10 +450,11 @@
450 if( iDownRail<1 ) iDownRail = ++p->mxRail;
451 pRow->iRail = ++p->mxRail;
452 pRow->railInUse = 1<<pRow->iRail;
453 pParent->aiRiser[iDownRail] = pRow->idx;
454 mask = 1<<iDownRail;
455 inUse |= mask;
456 for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
457 pLoop->railInUse |= mask;
458 }
459 }
460 }
461
+3 -2
--- src/leaf.c
+++ src/leaf.c
@@ -40,11 +40,12 @@
4040
" EXCEPT"
4141
" SELECT pid FROM plink"
4242
" WHERE coalesce((SELECT value FROM tagxref"
4343
" WHERE tagid=%d AND rid=plink.pid),'trunk')"
4444
" == coalesce((SELECT value FROM tagxref"
45
- " WHERE tagid=%d AND rid=plink.cid),'trunk');",
45
+ " WHERE tagid=%d AND rid=plink.cid),'trunk')"
46
+ " AND isprim",
4647
TAG_BRANCH, TAG_BRANCH
4748
);
4849
}
4950
5051
/*
@@ -62,11 +63,11 @@
6263
static Stmt removeLeaf;
6364
int rc;
6465
6566
db_static_prepare(&checkIfLeaf,
6667
"SELECT 1 FROM plink"
67
- " WHERE pid=:rid"
68
+ " WHERE pid=:rid AND isprim"
6869
" AND coalesce((SELECT value FROM tagxref"
6970
" WHERE tagid=%d AND rid=:rid),'trunk')"
7071
" == coalesce((SELECT value FROM tagxref"
7172
" WHERE tagid=%d AND rid=plink.cid),'trunk');",
7273
TAG_BRANCH, TAG_BRANCH
7374
--- src/leaf.c
+++ src/leaf.c
@@ -40,11 +40,12 @@
40 " EXCEPT"
41 " SELECT pid FROM plink"
42 " WHERE coalesce((SELECT value FROM tagxref"
43 " WHERE tagid=%d AND rid=plink.pid),'trunk')"
44 " == coalesce((SELECT value FROM tagxref"
45 " WHERE tagid=%d AND rid=plink.cid),'trunk');",
 
46 TAG_BRANCH, TAG_BRANCH
47 );
48 }
49
50 /*
@@ -62,11 +63,11 @@
62 static Stmt removeLeaf;
63 int rc;
64
65 db_static_prepare(&checkIfLeaf,
66 "SELECT 1 FROM plink"
67 " WHERE pid=:rid"
68 " AND coalesce((SELECT value FROM tagxref"
69 " WHERE tagid=%d AND rid=:rid),'trunk')"
70 " == coalesce((SELECT value FROM tagxref"
71 " WHERE tagid=%d AND rid=plink.cid),'trunk');",
72 TAG_BRANCH, TAG_BRANCH
73
--- src/leaf.c
+++ src/leaf.c
@@ -40,11 +40,12 @@
40 " EXCEPT"
41 " SELECT pid FROM plink"
42 " WHERE coalesce((SELECT value FROM tagxref"
43 " WHERE tagid=%d AND rid=plink.pid),'trunk')"
44 " == coalesce((SELECT value FROM tagxref"
45 " WHERE tagid=%d AND rid=plink.cid),'trunk')"
46 " AND isprim",
47 TAG_BRANCH, TAG_BRANCH
48 );
49 }
50
51 /*
@@ -62,11 +63,11 @@
63 static Stmt removeLeaf;
64 int rc;
65
66 db_static_prepare(&checkIfLeaf,
67 "SELECT 1 FROM plink"
68 " WHERE pid=:rid AND isprim"
69 " AND coalesce((SELECT value FROM tagxref"
70 " WHERE tagid=%d AND rid=:rid),'trunk')"
71 " == coalesce((SELECT value FROM tagxref"
72 " WHERE tagid=%d AND rid=plink.cid),'trunk');",
73 TAG_BRANCH, TAG_BRANCH
74
+13 -12
--- src/timeline.c
+++ src/timeline.c
@@ -254,11 +254,11 @@
254254
if( db_step(&qbranch)==SQLITE_ROW ){
255255
zBr = db_column_text(&qbranch, 0);
256256
}else{
257257
zBr = "trunk";
258258
}
259
- gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr);
259
+ gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
260260
db_reset(&qbranch);
261261
@ <div id="m%d(gidx)"></div>
262262
}
263263
@</td>
264264
if( zBgClr && zBgClr[0] ){
@@ -362,18 +362,18 @@
362362
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
363363
@ </td></tr>
364364
}
365365
}
366366
@ </table>
367
- timeline_output_graph_javascript(pGraph);
367
+ timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
368368
}
369369
370370
/*
371371
** Generate all of the necessary javascript to generate a timeline
372372
** graph.
373373
*/
374
-void timeline_output_graph_javascript(GraphContext *pGraph){
374
+void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){
375375
if( pGraph && pGraph->nErr==0 ){
376376
GraphRow *pRow;
377377
int i;
378378
char cSep;
379379
@ <script type="text/JavaScript">
@@ -396,10 +396,11 @@
396396
** node has no merge children and no merge-out line is drawn.
397397
** mu: The id of the row which is the top of the merge-out arrow.
398398
** u: Draw a thick child-line out of the top of this node and up to
399399
** the node with an id equal to this value. 0 if there is no
400400
** thick-line riser.
401
+ ** f: 0x01: a leaf node.
401402
** au: An array of integers that define thick-line risers for branches.
402403
** The integers are in pairs. For each pair, the first integer is
403404
** is the rail on which the riser should run and the second integer
404405
** is the id of the node upto which the riser should run.
405406
** mi: "merge-in". An array of integer x-coordinates from which
@@ -414,18 +415,19 @@
414415
if( mo<0 ){
415416
mo = 0;
416417
}else{
417418
mo = (mo/4)*20 - 3 + 4*(mo&3);
418419
}
419
- cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:",
420
+ cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:",
420421
pRow->idx, /* id */
421422
pRow->zBgClr, /* bg */
422423
pRow->iRail, /* r */
423424
pRow->bDescender, /* d */
424425
mo, /* mo */
425426
pRow->mergeUpto, /* mu */
426
- pRow->aiRiser[pRow->iRail] /* u */
427
+ pRow->aiRiser[pRow->iRail], /* u */
428
+ pRow->isLeaf ? 1 : 0 /* f */
427429
);
428430
/* u */
429431
cSep = '[';
430432
for(i=0; i<GR_MAX_RAIL; i++){
431433
if( i==pRow->iRail ) continue;
@@ -515,17 +517,16 @@
515517
@ drawBox("black",x0,y0,x1,y1);
516518
@ }
517519
@ function drawNode(p, left, btm){
518520
@ drawBox("black",p.x-5,p.y-5,p.x+6,p.y+6);
519521
@ drawBox(p.bg,p.x-4,p.y-4,p.x+5,p.y+5);
520
- @ if( p.u>0 ){
521
- @ var u = rowinfo[p.u-1];
522
- @ drawUpArrow(p.x, u.y+6, p.y-5);
523
- @ }
524
- @ if( p.d ){
525
- @ drawUpArrow(p.x, p.y+6, btm);
526
- @ }
522
+ @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
523
+ if( !omitDescenders ){
524
+ @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
525
+ @ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2);
526
+ @ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
527
+ }
527528
@ if( p.mo>0 ){
528529
@ var x1 = p.mo + left - 1;
529530
@ var y1 = p.y-3;
530531
@ var x0 = x1>p.x ? p.x+7 : p.x-6;
531532
@ var u = rowinfo[p.mu-1];
532533
--- src/timeline.c
+++ src/timeline.c
@@ -254,11 +254,11 @@
254 if( db_step(&qbranch)==SQLITE_ROW ){
255 zBr = db_column_text(&qbranch, 0);
256 }else{
257 zBr = "trunk";
258 }
259 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr);
260 db_reset(&qbranch);
261 @ <div id="m%d(gidx)"></div>
262 }
263 @</td>
264 if( zBgClr && zBgClr[0] ){
@@ -362,18 +362,18 @@
362 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
363 @ </td></tr>
364 }
365 }
366 @ </table>
367 timeline_output_graph_javascript(pGraph);
368 }
369
370 /*
371 ** Generate all of the necessary javascript to generate a timeline
372 ** graph.
373 */
374 void timeline_output_graph_javascript(GraphContext *pGraph){
375 if( pGraph && pGraph->nErr==0 ){
376 GraphRow *pRow;
377 int i;
378 char cSep;
379 @ <script type="text/JavaScript">
@@ -396,10 +396,11 @@
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
@@ -414,18 +415,19 @@
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++){
431 if( i==pRow->iRail ) continue;
@@ -515,17 +517,16 @@
515 @ drawBox("black",x0,y0,x1,y1);
516 @ }
517 @ function drawNode(p, left, btm){
518 @ drawBox("black",p.x-5,p.y-5,p.x+6,p.y+6);
519 @ drawBox(p.bg,p.x-4,p.y-4,p.x+5,p.y+5);
520 @ if( p.u>0 ){
521 @ var u = rowinfo[p.u-1];
522 @ drawUpArrow(p.x, u.y+6, p.y-5);
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
--- src/timeline.c
+++ src/timeline.c
@@ -254,11 +254,11 @@
254 if( db_step(&qbranch)==SQLITE_ROW ){
255 zBr = db_column_text(&qbranch, 0);
256 }else{
257 zBr = "trunk";
258 }
259 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf);
260 db_reset(&qbranch);
261 @ <div id="m%d(gidx)"></div>
262 }
263 @</td>
264 if( zBgClr && zBgClr[0] ){
@@ -362,18 +362,18 @@
362 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
363 @ </td></tr>
364 }
365 }
366 @ </table>
367 timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
368 }
369
370 /*
371 ** Generate all of the necessary javascript to generate a timeline
372 ** graph.
373 */
374 void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){
375 if( pGraph && pGraph->nErr==0 ){
376 GraphRow *pRow;
377 int i;
378 char cSep;
379 @ <script type="text/JavaScript">
@@ -396,10 +396,11 @@
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 ** f: 0x01: a leaf node.
402 ** au: An array of integers that define thick-line risers for branches.
403 ** The integers are in pairs. For each pair, the first integer is
404 ** is the rail on which the riser should run and the second integer
405 ** is the id of the node upto which the riser should run.
406 ** mi: "merge-in". An array of integer x-coordinates from which
@@ -414,18 +415,19 @@
415 if( mo<0 ){
416 mo = 0;
417 }else{
418 mo = (mo/4)*20 - 3 + 4*(mo&3);
419 }
420 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:",
421 pRow->idx, /* id */
422 pRow->zBgClr, /* bg */
423 pRow->iRail, /* r */
424 pRow->bDescender, /* d */
425 mo, /* mo */
426 pRow->mergeUpto, /* mu */
427 pRow->aiRiser[pRow->iRail], /* u */
428 pRow->isLeaf ? 1 : 0 /* f */
429 );
430 /* u */
431 cSep = '[';
432 for(i=0; i<GR_MAX_RAIL; i++){
433 if( i==pRow->iRail ) continue;
@@ -515,17 +517,16 @@
517 @ drawBox("black",x0,y0,x1,y1);
518 @ }
519 @ function drawNode(p, left, btm){
520 @ drawBox("black",p.x-5,p.y-5,p.x+6,p.y+6);
521 @ drawBox(p.bg,p.x-4,p.y-4,p.x+5,p.y+5);
522 @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
523 if( !omitDescenders ){
524 @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
525 @ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2);
526 @ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
527 }
 
528 @ if( p.mo>0 ){
529 @ var x1 = p.mo + left - 1;
530 @ var y1 = p.y-3;
531 @ var x0 = x1>p.x ? p.x+7 : p.x-6;
532 @ var u = rowinfo[p.mu-1];
533

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button