Fossil

Check-in [313cd3c832]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improvements to the layout of merge arrows in the graph.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 313cd3c8322e2ab9a27845e432139407004ecdf9
User & Date: drh 2011-03-14 18:26:48.332
Context
2011-03-14
20:14
Further improvements to the layout of merge arrows. ... (check-in: a6934b4437 user: drh tags: trunk)
18:26
Improvements to the layout of merge arrows in the graph. ... (check-in: 313cd3c832 user: drh tags: trunk)
13:22
Fix a bug in the merge file-rename detection logic, a bug introduced by the path refactoring changes. ... (check-in: 66951fa6bd user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/graph.c.
251
252
253
254
255
256
257





































258
259
260
261
262
263
264
      pPrior->railInUse |= mask;
      pPrior = pPrior->pPrev;
      assert( pPrior!=0 );
    }
  }
}







































/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
  GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
  int i;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
      pPrior->railInUse |= mask;
      pPrior = pPrior->pPrev;
      assert( pPrior!=0 );
    }
  }
}

/*
** Create a merge-arrow riser going from pParent up to pChild.
*/
static void createMergeRiser(
  GraphContext *p,
  GraphRow *pParent,
  GraphRow *pChild
){
  int u;
  u32 mask;
  GraphRow *pLoop;

  if( pParent->mergeOut<0 ){
    u = pParent->aiRiser[pParent->iRail];
    if( u>0 && u<pChild->idx ){
      /* The thick arrow up to the next primary child of pDesc goes
      ** further up than the thin merge arrow riser, so draw them both
      ** on the same rail. */
      pParent->mergeOut = pParent->iRail;
      pParent->mergeUpto = pChild->idx;
    }else{
      /* The thin merge arrow riser is taller than the thick primary
      ** child riser, so use separate rails. */
      int iTarget = pParent->iRail;
      pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1,
                                       0, iTarget);
      pParent->mergeUpto = pChild->idx;
      mask = 1<<pParent->mergeOut;
      for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
           pLoop=pLoop->pNext){
        pLoop->railInUse |= mask;
      }
    }
  }
  pChild->mergeIn |= 1<<pParent->mergeOut;
}


/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
  GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
  int i;
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
        pRow->mergeIn |= mask;
        pRow->mergeDown |= mask;
        for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
          pLoop->railInUse |= mask;
        }
      }else{
        /* Merge from an on-screen node */
        if( pDesc->mergeOut<0 ){
          int iTarget = (pRow->iRail + pDesc->iRail)/2;
          pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1,0,iTarget);
          pDesc->mergeUpto = pRow->idx;
          mask = 1<<pDesc->mergeOut;
          for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid;
               pLoop=pLoop->pNext){
            pLoop->railInUse |= mask;
          }
        }
        pRow->mergeIn |= 1<<pDesc->mergeOut;
      }
    }
  }

  /*
  ** Insert merge rails from primaries to duplicates. 
  */
  if( hasDup ){
    for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
      if( !pRow->isDup ) continue;
      pDesc = hashFind(p, pRow->rid);
      assert( pDesc!=0 && pDesc!=pRow );
      if( pDesc->mergeOut<0 ){
        int iTarget = (pRow->iRail + pDesc->iRail)/2;
        pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1, 0, iTarget);
        pDesc->mergeUpto = pRow->idx;
        mask = 1<<pDesc->mergeOut;
        for(pLoop=pRow->pNext; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){
          pLoop->railInUse |= mask;
        }
      }
      pRow->mergeIn |= 1<<pDesc->mergeOut;
    }
  }

  /*
  ** Find the maximum rail number.
  */
  p->mxRail = 0;







|
<
<
<
<
<
<
<
<
<
<












|
<
<
<
<
<
<
<
<
<







466
467
468
469
470
471
472
473










474
475
476
477
478
479
480
481
482
483
484
485
486









487
488
489
490
491
492
493
        pRow->mergeIn |= mask;
        pRow->mergeDown |= mask;
        for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
          pLoop->railInUse |= mask;
        }
      }else{
        /* Merge from an on-screen node */
        createMergeRiser(p, pDesc, pRow);










      }
    }
  }

  /*
  ** Insert merge rails from primaries to duplicates. 
  */
  if( hasDup ){
    for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
      if( !pRow->isDup ) continue;
      pDesc = hashFind(p, pRow->rid);
      assert( pDesc!=0 && pDesc!=pRow );
      createMergeRiser(p, pDesc, pRow);









    }
  }

  /*
  ** Find the maximum rail number.
  */
  p->mxRail = 0;
Changes to src/timeline.c.
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
    **        node has no merge children and no merge-out line is drawn.
    **   mu:  The id of the row which is the top of the merge-out arrow.
    **   md:  A bitmask of rails on which merge-arrow descenders should be
    **        drawn from this row to the bottom of the page.  The least
    **        significant bit (1) corresponds to rail 0.  The 2-bit corresponds
    **        to rail 1.  And so forth.  This value is 0 if there are no
    **        merge-arrow descenders.
    **    u:  Draw a think child-line out of the top of this node and up to
    **        the node with an id equal to this value.  0 if there is no
    **        thick-line riser.
    **   au:  An array of integers that define thick-line risers for branches.
    **        The integers are in pairs.  For each pair, the first integer is
    **        is the rail on which the riser should run and the second integer
    **        is the id of the node upto which the riser should run.
    **   mi:  "merge-in".  An array of integer rail numbers from which
    **        merge arrows should be drawn into this node.
    */
    cgi_printf("var rowinfo = [\n");
    for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
      cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
        pRow->idx,
        pRow->zBgClr,
        pRow->iRail,
        pRow->bDescender,
        pRow->mergeOut+1,
        pRow->mergeUpto,
        pRow->mergeDown,
        pRow->aiRiser[pRow->iRail]
      );

      cSep = '[';
      for(i=0; i<GR_MAX_RAIL; i++){
        if( i==pRow->iRail ) continue;
        if( pRow->aiRiser[i]>0 ){
          cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
          cSep = ',';
        }
      }
      if( cSep=='[' ) cgi_printf("[");
      cgi_printf("],mi:");

      cSep = '[';
      for(i=0; i<GR_MAX_RAIL; i++){
        if( pRow->mergeIn & (1<<i) ){
          cgi_printf("%c%d", cSep, i);
          cSep = ',';
        }
      }







|












|
|
|
|
|
|
|
|

>










>







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
    **        node has no merge children and no merge-out line is drawn.
    **   mu:  The id of the row which is the top of the merge-out arrow.
    **   md:  A bitmask of rails on which merge-arrow descenders should be
    **        drawn from this row to the bottom of the page.  The least
    **        significant bit (1) corresponds to rail 0.  The 2-bit corresponds
    **        to rail 1.  And so forth.  This value is 0 if there are no
    **        merge-arrow descenders.
    **    u:  Draw a thick child-line out of the top of this node and up to
    **        the node with an id equal to this value.  0 if there is no
    **        thick-line riser.
    **   au:  An array of integers that define thick-line risers for branches.
    **        The integers are in pairs.  For each pair, the first integer is
    **        is the rail on which the riser should run and the second integer
    **        is the id of the node upto which the riser should run.
    **   mi:  "merge-in".  An array of integer rail numbers from which
    **        merge arrows should be drawn into this node.
    */
    cgi_printf("var rowinfo = [\n");
    for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
      cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
        pRow->idx,                      /* id */
        pRow->zBgClr,                   /* bg */
        pRow->iRail,                    /* r */
        pRow->bDescender,               /* d */
        pRow->mergeOut+1,               /* mo */
        pRow->mergeUpto,                /* mu */
        pRow->mergeDown,                /* md */
        pRow->aiRiser[pRow->iRail]      /* u */
      );
      /* u */
      cSep = '[';
      for(i=0; i<GR_MAX_RAIL; i++){
        if( i==pRow->iRail ) continue;
        if( pRow->aiRiser[i]>0 ){
          cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
          cSep = ',';
        }
      }
      if( cSep=='[' ) cgi_printf("[");
      cgi_printf("],mi:");
      /* mi */
      cSep = '[';
      for(i=0; i<GR_MAX_RAIL; i++){
        if( pRow->mergeIn & (1<<i) ){
          cgi_printf("%c%d", cSep, i);
          cSep = ',';
        }
      }
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    @     var u = rowinfo[p.u-1];
    @     drawUpArrow(p.x, u.y+6, p.y-5);
    @   }
    @   if( p.d ){
    @     drawUpArrow(p.x, p.y+6, btm);
    @   } 
    @   if( p.mo>0 ){
    @     var x1 = (p.mo-1)*20 + left;
    @     var y1 = p.y-3;
    @     var x0 = x1>p.x ? p.x+7 : p.x-6;
    @     var u = rowinfo[p.mu-1];
    @     var y0 = u.y+5;
    @     if( x1==p.x ){
    @       y1 -= 2;
    @     }else{
    @       drawThinLine(x0,y1,x1,y1);
    @     }
    @     drawThinLine(x1,y0,x1,y1);
    @   }
    @   var n = p.au.length;
    @   for(var i=0; i<n; i+=2){







|




|
|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
    @     var u = rowinfo[p.u-1];
    @     drawUpArrow(p.x, u.y+6, p.y-5);
    @   }
    @   if( p.d ){
    @     drawUpArrow(p.x, p.y+6, btm);
    @   } 
    @   if( p.mo>0 ){
    @     var x1 = (p.mo-1)*20 + left + 4;
    @     var y1 = p.y-3;
    @     var x0 = x1>p.x ? p.x+7 : p.x-6;
    @     var u = rowinfo[p.mu-1];
    @     var y0 = u.y+5;
    @     if( x1==p.x+4 ){
    @       y1 = p.y-5;
    @     }else{
    @       drawThinLine(x0,y1,x1,y1);
    @     }
    @     drawThinLine(x1,y0,x1,y1);
    @   }
    @   var n = p.au.length;
    @   for(var i=0; i<n; i+=2){
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
    @       drawBox("#600000",x1,u.y,u.x-6,u.y+1);
    @       drawBox("#600000",u.x-9,u.y-1,u.x-8,u.y+2);
    @       drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
    @     }
    @   }
    @   for(var j in p.mi){
    @     var y0 = p.y+5;
    @     var mx = p.mi[j]*20 + left;
    @     if( mx>p.x ){
    @       drawThinArrow(y0,mx,p.x+6);
    @     }else{
    @       drawThinArrow(y0,mx,p.x-5);
    @     }
    @     if( (1<<p.mi[j])&p.md ){
    @       drawThinLine(mx,y0,mx,btm);







|







546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
    @       drawBox("#600000",x1,u.y,u.x-6,u.y+1);
    @       drawBox("#600000",u.x-9,u.y-1,u.x-8,u.y+2);
    @       drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
    @     }
    @   }
    @   for(var j in p.mi){
    @     var y0 = p.y+5;
    @     var mx = p.mi[j]*20 + left + 4;
    @     if( mx>p.x ){
    @       drawThinArrow(y0,mx,p.x+6);
    @     }else{
    @       drawThinArrow(y0,mx,p.x-5);
    @     }
    @     if( (1<<p.mi[j])&p.md ){
    @       drawThinLine(mx,y0,mx,btm);