Fossil SCM

Improvements to the layout of merge arrows in the graph.

drh 2011-03-14 18:26 trunk
Commit 313cd3c8322e2ab9a27845e432139407004ecdf9
2 files changed +39 -21 +15 -13
+39 -21
--- src/graph.c
+++ src/graph.c
@@ -253,10 +253,47 @@
253253
assert( pPrior!=0 );
254254
}
255255
}
256256
}
257257
258
+/*
259
+** Create a merge-arrow riser going from pParent up to pChild.
260
+*/
261
+static void createMergeRiser(
262
+ GraphContext *p,
263
+ GraphRow *pParent,
264
+ GraphRow *pChild
265
+){
266
+ int u;
267
+ u32 mask;
268
+ GraphRow *pLoop;
269
+
270
+ if( pParent->mergeOut<0 ){
271
+ u = pParent->aiRiser[pParent->iRail];
272
+ if( u>0 && u<pChild->idx ){
273
+ /* The thick arrow up to the next primary child of pDesc goes
274
+ ** further up than the thin merge arrow riser, so draw them both
275
+ ** on the same rail. */
276
+ pParent->mergeOut = pParent->iRail;
277
+ pParent->mergeUpto = pChild->idx;
278
+ }else{
279
+ /* The thin merge arrow riser is taller than the thick primary
280
+ ** child riser, so use separate rails. */
281
+ int iTarget = pParent->iRail;
282
+ pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1,
283
+ 0, iTarget);
284
+ pParent->mergeUpto = pChild->idx;
285
+ mask = 1<<pParent->mergeOut;
286
+ for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
287
+ pLoop=pLoop->pNext){
288
+ pLoop->railInUse |= mask;
289
+ }
290
+ }
291
+ }
292
+ pChild->mergeIn |= 1<<pParent->mergeOut;
293
+}
294
+
258295
259296
/*
260297
** Compute the complete graph
261298
*/
262299
void graph_finish(GraphContext *p, int omitDescenders){
@@ -431,21 +468,11 @@
431468
for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
432469
pLoop->railInUse |= mask;
433470
}
434471
}else{
435472
/* Merge from an on-screen node */
436
- if( pDesc->mergeOut<0 ){
437
- int iTarget = (pRow->iRail + pDesc->iRail)/2;
438
- pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1,0,iTarget);
439
- pDesc->mergeUpto = pRow->idx;
440
- mask = 1<<pDesc->mergeOut;
441
- for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid;
442
- pLoop=pLoop->pNext){
443
- pLoop->railInUse |= mask;
444
- }
445
- }
446
- pRow->mergeIn |= 1<<pDesc->mergeOut;
473
+ createMergeRiser(p, pDesc, pRow);
447474
}
448475
}
449476
}
450477
451478
/*
@@ -454,20 +481,11 @@
454481
if( hasDup ){
455482
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
456483
if( !pRow->isDup ) continue;
457484
pDesc = hashFind(p, pRow->rid);
458485
assert( pDesc!=0 && pDesc!=pRow );
459
- if( pDesc->mergeOut<0 ){
460
- int iTarget = (pRow->iRail + pDesc->iRail)/2;
461
- pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1, 0, iTarget);
462
- pDesc->mergeUpto = pRow->idx;
463
- mask = 1<<pDesc->mergeOut;
464
- for(pLoop=pRow->pNext; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){
465
- pLoop->railInUse |= mask;
466
- }
467
- }
468
- pRow->mergeIn |= 1<<pDesc->mergeOut;
486
+ createMergeRiser(p, pDesc, pRow);
469487
}
470488
}
471489
472490
/*
473491
** Find the maximum rail number.
474492
--- src/graph.c
+++ src/graph.c
@@ -253,10 +253,47 @@
253 assert( pPrior!=0 );
254 }
255 }
256 }
257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
259 /*
260 ** Compute the complete graph
261 */
262 void graph_finish(GraphContext *p, int omitDescenders){
@@ -431,21 +468,11 @@
431 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
432 pLoop->railInUse |= mask;
433 }
434 }else{
435 /* Merge from an on-screen node */
436 if( pDesc->mergeOut<0 ){
437 int iTarget = (pRow->iRail + pDesc->iRail)/2;
438 pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1,0,iTarget);
439 pDesc->mergeUpto = pRow->idx;
440 mask = 1<<pDesc->mergeOut;
441 for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid;
442 pLoop=pLoop->pNext){
443 pLoop->railInUse |= mask;
444 }
445 }
446 pRow->mergeIn |= 1<<pDesc->mergeOut;
447 }
448 }
449 }
450
451 /*
@@ -454,20 +481,11 @@
454 if( hasDup ){
455 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
456 if( !pRow->isDup ) continue;
457 pDesc = hashFind(p, pRow->rid);
458 assert( pDesc!=0 && pDesc!=pRow );
459 if( pDesc->mergeOut<0 ){
460 int iTarget = (pRow->iRail + pDesc->iRail)/2;
461 pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1, 0, iTarget);
462 pDesc->mergeUpto = pRow->idx;
463 mask = 1<<pDesc->mergeOut;
464 for(pLoop=pRow->pNext; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){
465 pLoop->railInUse |= mask;
466 }
467 }
468 pRow->mergeIn |= 1<<pDesc->mergeOut;
469 }
470 }
471
472 /*
473 ** Find the maximum rail number.
474
--- src/graph.c
+++ src/graph.c
@@ -253,10 +253,47 @@
253 assert( pPrior!=0 );
254 }
255 }
256 }
257
258 /*
259 ** Create a merge-arrow riser going from pParent up to pChild.
260 */
261 static void createMergeRiser(
262 GraphContext *p,
263 GraphRow *pParent,
264 GraphRow *pChild
265 ){
266 int u;
267 u32 mask;
268 GraphRow *pLoop;
269
270 if( pParent->mergeOut<0 ){
271 u = pParent->aiRiser[pParent->iRail];
272 if( u>0 && u<pChild->idx ){
273 /* The thick arrow up to the next primary child of pDesc goes
274 ** further up than the thin merge arrow riser, so draw them both
275 ** on the same rail. */
276 pParent->mergeOut = pParent->iRail;
277 pParent->mergeUpto = pChild->idx;
278 }else{
279 /* The thin merge arrow riser is taller than the thick primary
280 ** child riser, so use separate rails. */
281 int iTarget = pParent->iRail;
282 pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1,
283 0, iTarget);
284 pParent->mergeUpto = pChild->idx;
285 mask = 1<<pParent->mergeOut;
286 for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
287 pLoop=pLoop->pNext){
288 pLoop->railInUse |= mask;
289 }
290 }
291 }
292 pChild->mergeIn |= 1<<pParent->mergeOut;
293 }
294
295
296 /*
297 ** Compute the complete graph
298 */
299 void graph_finish(GraphContext *p, int omitDescenders){
@@ -431,21 +468,11 @@
468 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
469 pLoop->railInUse |= mask;
470 }
471 }else{
472 /* Merge from an on-screen node */
473 createMergeRiser(p, pDesc, pRow);
 
 
 
 
 
 
 
 
 
 
474 }
475 }
476 }
477
478 /*
@@ -454,20 +481,11 @@
481 if( hasDup ){
482 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
483 if( !pRow->isDup ) continue;
484 pDesc = hashFind(p, pRow->rid);
485 assert( pDesc!=0 && pDesc!=pRow );
486 createMergeRiser(p, pDesc, pRow);
 
 
 
 
 
 
 
 
 
487 }
488 }
489
490 /*
491 ** Find the maximum rail number.
492
+15 -13
--- src/timeline.c
+++ src/timeline.c
@@ -398,11 +398,11 @@
398398
** md: A bitmask of rails on which merge-arrow descenders should be
399399
** drawn from this row to the bottom of the page. The least
400400
** significant bit (1) corresponds to rail 0. The 2-bit corresponds
401401
** to rail 1. And so forth. This value is 0 if there are no
402402
** merge-arrow descenders.
403
- ** u: Draw a think child-line out of the top of this node and up to
403
+ ** u: Draw a thick child-line out of the top of this node and up to
404404
** the node with an id equal to this value. 0 if there is no
405405
** thick-line riser.
406406
** au: An array of integers that define thick-line risers for branches.
407407
** The integers are in pairs. For each pair, the first integer is
408408
** is the rail on which the riser should run and the second integer
@@ -411,19 +411,20 @@
411411
** merge arrows should be drawn into this node.
412412
*/
413413
cgi_printf("var rowinfo = [\n");
414414
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
415415
cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
416
- pRow->idx,
417
- pRow->zBgClr,
418
- pRow->iRail,
419
- pRow->bDescender,
420
- pRow->mergeOut+1,
421
- pRow->mergeUpto,
422
- pRow->mergeDown,
423
- pRow->aiRiser[pRow->iRail]
416
+ pRow->idx, /* id */
417
+ pRow->zBgClr, /* bg */
418
+ pRow->iRail, /* r */
419
+ pRow->bDescender, /* d */
420
+ pRow->mergeOut+1, /* mo */
421
+ pRow->mergeUpto, /* mu */
422
+ pRow->mergeDown, /* md */
423
+ pRow->aiRiser[pRow->iRail] /* u */
424424
);
425
+ /* u */
425426
cSep = '[';
426427
for(i=0; i<GR_MAX_RAIL; i++){
427428
if( i==pRow->iRail ) continue;
428429
if( pRow->aiRiser[i]>0 ){
429430
cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -430,10 +431,11 @@
430431
cSep = ',';
431432
}
432433
}
433434
if( cSep=='[' ) cgi_printf("[");
434435
cgi_printf("],mi:");
436
+ /* mi */
435437
cSep = '[';
436438
for(i=0; i<GR_MAX_RAIL; i++){
437439
if( pRow->mergeIn & (1<<i) ){
438440
cgi_printf("%c%d", cSep, i);
439441
cSep = ',';
@@ -516,17 +518,17 @@
516518
@ }
517519
@ if( p.d ){
518520
@ drawUpArrow(p.x, p.y+6, btm);
519521
@ }
520522
@ if( p.mo>0 ){
521
- @ var x1 = (p.mo-1)*20 + left;
523
+ @ var x1 = (p.mo-1)*20 + left + 4;
522524
@ var y1 = p.y-3;
523525
@ var x0 = x1>p.x ? p.x+7 : p.x-6;
524526
@ var u = rowinfo[p.mu-1];
525527
@ var y0 = u.y+5;
526
- @ if( x1==p.x ){
527
- @ y1 -= 2;
528
+ @ if( x1==p.x+4 ){
529
+ @ y1 = p.y-5;
528530
@ }else{
529531
@ drawThinLine(x0,y1,x1,y1);
530532
@ }
531533
@ drawThinLine(x1,y0,x1,y1);
532534
@ }
@@ -546,11 +548,11 @@
546548
@ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
547549
@ }
548550
@ }
549551
@ for(var j in p.mi){
550552
@ var y0 = p.y+5;
551
- @ var mx = p.mi[j]*20 + left;
553
+ @ var mx = p.mi[j]*20 + left + 4;
552554
@ if( mx>p.x ){
553555
@ drawThinArrow(y0,mx,p.x+6);
554556
@ }else{
555557
@ drawThinArrow(y0,mx,p.x-5);
556558
@ }
557559
--- src/timeline.c
+++ src/timeline.c
@@ -398,11 +398,11 @@
398 ** md: A bitmask of rails on which merge-arrow descenders should be
399 ** drawn from this row to the bottom of the page. The least
400 ** significant bit (1) corresponds to rail 0. The 2-bit corresponds
401 ** to rail 1. And so forth. This value is 0 if there are no
402 ** merge-arrow descenders.
403 ** u: Draw a think child-line out of the top of this node and up to
404 ** the node with an id equal to this value. 0 if there is no
405 ** thick-line riser.
406 ** au: An array of integers that define thick-line risers for branches.
407 ** The integers are in pairs. For each pair, the first integer is
408 ** is the rail on which the riser should run and the second integer
@@ -411,19 +411,20 @@
411 ** merge arrows should be drawn into this node.
412 */
413 cgi_printf("var rowinfo = [\n");
414 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
415 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
416 pRow->idx,
417 pRow->zBgClr,
418 pRow->iRail,
419 pRow->bDescender,
420 pRow->mergeOut+1,
421 pRow->mergeUpto,
422 pRow->mergeDown,
423 pRow->aiRiser[pRow->iRail]
424 );
 
425 cSep = '[';
426 for(i=0; i<GR_MAX_RAIL; i++){
427 if( i==pRow->iRail ) continue;
428 if( pRow->aiRiser[i]>0 ){
429 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -430,10 +431,11 @@
430 cSep = ',';
431 }
432 }
433 if( cSep=='[' ) cgi_printf("[");
434 cgi_printf("],mi:");
 
435 cSep = '[';
436 for(i=0; i<GR_MAX_RAIL; i++){
437 if( pRow->mergeIn & (1<<i) ){
438 cgi_printf("%c%d", cSep, i);
439 cSep = ',';
@@ -516,17 +518,17 @@
516 @ }
517 @ if( p.d ){
518 @ drawUpArrow(p.x, p.y+6, btm);
519 @ }
520 @ if( p.mo>0 ){
521 @ var x1 = (p.mo-1)*20 + left;
522 @ var y1 = p.y-3;
523 @ var x0 = x1>p.x ? p.x+7 : p.x-6;
524 @ var u = rowinfo[p.mu-1];
525 @ var y0 = u.y+5;
526 @ if( x1==p.x ){
527 @ y1 -= 2;
528 @ }else{
529 @ drawThinLine(x0,y1,x1,y1);
530 @ }
531 @ drawThinLine(x1,y0,x1,y1);
532 @ }
@@ -546,11 +548,11 @@
546 @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
547 @ }
548 @ }
549 @ for(var j in p.mi){
550 @ var y0 = p.y+5;
551 @ var mx = p.mi[j]*20 + left;
552 @ if( mx>p.x ){
553 @ drawThinArrow(y0,mx,p.x+6);
554 @ }else{
555 @ drawThinArrow(y0,mx,p.x-5);
556 @ }
557
--- src/timeline.c
+++ src/timeline.c
@@ -398,11 +398,11 @@
398 ** md: A bitmask of rails on which merge-arrow descenders should be
399 ** drawn from this row to the bottom of the page. The least
400 ** significant bit (1) corresponds to rail 0. The 2-bit corresponds
401 ** to rail 1. And so forth. This value is 0 if there are no
402 ** merge-arrow descenders.
403 ** u: Draw a thick child-line out of the top of this node and up to
404 ** the node with an id equal to this value. 0 if there is no
405 ** thick-line riser.
406 ** au: An array of integers that define thick-line risers for branches.
407 ** The integers are in pairs. For each pair, the first integer is
408 ** is the rail on which the riser should run and the second integer
@@ -411,19 +411,20 @@
411 ** merge arrows should be drawn into this node.
412 */
413 cgi_printf("var rowinfo = [\n");
414 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
415 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
416 pRow->idx, /* id */
417 pRow->zBgClr, /* bg */
418 pRow->iRail, /* r */
419 pRow->bDescender, /* d */
420 pRow->mergeOut+1, /* mo */
421 pRow->mergeUpto, /* mu */
422 pRow->mergeDown, /* md */
423 pRow->aiRiser[pRow->iRail] /* u */
424 );
425 /* u */
426 cSep = '[';
427 for(i=0; i<GR_MAX_RAIL; i++){
428 if( i==pRow->iRail ) continue;
429 if( pRow->aiRiser[i]>0 ){
430 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -430,10 +431,11 @@
431 cSep = ',';
432 }
433 }
434 if( cSep=='[' ) cgi_printf("[");
435 cgi_printf("],mi:");
436 /* mi */
437 cSep = '[';
438 for(i=0; i<GR_MAX_RAIL; i++){
439 if( pRow->mergeIn & (1<<i) ){
440 cgi_printf("%c%d", cSep, i);
441 cSep = ',';
@@ -516,17 +518,17 @@
518 @ }
519 @ if( p.d ){
520 @ drawUpArrow(p.x, p.y+6, btm);
521 @ }
522 @ if( p.mo>0 ){
523 @ var x1 = (p.mo-1)*20 + left + 4;
524 @ var y1 = p.y-3;
525 @ var x0 = x1>p.x ? p.x+7 : p.x-6;
526 @ var u = rowinfo[p.mu-1];
527 @ var y0 = u.y+5;
528 @ if( x1==p.x+4 ){
529 @ y1 = p.y-5;
530 @ }else{
531 @ drawThinLine(x0,y1,x1,y1);
532 @ }
533 @ drawThinLine(x1,y0,x1,y1);
534 @ }
@@ -546,11 +548,11 @@
548 @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
549 @ }
550 @ }
551 @ for(var j in p.mi){
552 @ var y0 = p.y+5;
553 @ var mx = p.mi[j]*20 + left + 4;
554 @ if( mx>p.x ){
555 @ drawThinArrow(y0,mx,p.x+6);
556 @ }else{
557 @ drawThinArrow(y0,mx,p.x-5);
558 @ }
559

Keyboard Shortcuts

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