Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Further improvements to the layout of merge arrows. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
a6934b4437780904bf8813ec55c81bdc |
| User & Date: | drh 2011-03-14 20:14:01.751 |
Context
|
2011-03-14
| ||
| 21:36 | Fix an issue with the leaf-tracker that comes up if a check-in specifies a shunned check-in as its parent or merge parent. Ticket [398afa58def78f5]. ... (check-in: aa6abc5ed3 user: drh tags: trunk) | |
| 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) | |
Changes
Changes to src/graph.c.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 50 | int idx; /* Row index. First is 1. 0 used for "none" */ int idxTop; /* Direct descendent highest up on the graph */ GraphRow *pChild; /* Child immediately above this node */ u8 isDup; /* True if this is duplicate of a prior entry */ u8 bDescender; /* True if riser from bottom of graph to here. */ i8 iRail; /* Which rail this check-in appears on. 0-based.*/ i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ | > < | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | int idx; /* Row index. First is 1. 0 used for "none" */ int idxTop; /* Direct descendent highest up on the graph */ GraphRow *pChild; /* Child immediately above this node */ u8 isDup; /* True if this is duplicate of a prior entry */ u8 bDescender; /* True if riser from bottom of graph to here. */ i8 iRail; /* Which rail this check-in appears on. 0-based.*/ i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ int mergeUpto; /* Draw the mergeOut rail up to this level */ u32 mergeDown; /* Draw merge lines up from bottom of graph */ u32 railInUse; /* Mask of occupied rails at this row */ }; /* Context while building a graph |
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
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. */
| | > | | | | 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 |
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*4;
if( pParent->iRail<pChild->iRail ) pParent->mergeOut += 2;
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)*4 + 1;
pParent->mergeUpto = pChild->idx;
mask = 1<<(pParent->mergeOut/4);
for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
pLoop=pLoop->pNext){
pLoop->railInUse |= mask;
}
}
}
pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1;
}
/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
|
| ︙ | ︙ | |||
459 460 461 462 463 464 465 |
for(i=1; i<pRow->nParent; i++){
int parentRid = pRow->aParent[i];
pDesc = hashFind(p, parentRid);
if( pDesc==0 ){
/* Merge from a node that is off-screen */
int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0);
mask = 1<<iMrail;
| | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
for(i=1; i<pRow->nParent; i++){
int parentRid = pRow->aParent[i];
pDesc = hashFind(p, parentRid);
if( pDesc==0 ){
/* Merge from a node that is off-screen */
int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0);
mask = 1<<iMrail;
pRow->mergeIn[iMrail] = 2;
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);
|
| ︙ | ︙ | |||
489 490 491 492 493 494 495 |
/*
** Find the maximum rail number.
*/
p->mxRail = 0;
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
| | | 490 491 492 493 494 495 496 497 498 499 500 501 502 |
/*
** Find the maximum rail number.
*/
p->mxRail = 0;
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4;
while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){
p->mxRail++;
}
}
}
|
Changes to src/timeline.c.
| ︙ | ︙ | |||
386 387 388 389 390 391 392 |
** to get an actual id, prepend "m" to the integer. The top node
** is 1 and numbers increase moving down the timeline.
** bg: The background color for this row
** r: The "rail" that the node for this row sits on. The left-most
** rail is 0 and the number increases to the right.
** d: True if there is a "descender" - an arrow coming from the bottom
** of the page straight up to this node.
| | | < < < < < | | > > > > > > > > > | | < | > > | | 386 387 388 389 390 391 392 393 394 395 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 444 445 446 447 448 449 450 451 452 |
** to get an actual id, prepend "m" to the integer. The top node
** is 1 and numbers increase moving down the timeline.
** bg: The background color for this row
** r: The "rail" that the node for this row sits on. The left-most
** rail is 0 and the number increases to the right.
** d: True if there is a "descender" - an arrow coming from the bottom
** of the page straight up to this node.
** mo: "merge-out". If non-zero, this is one more than the x-coordinate
** for the upward portion of a merge arrow. The merge arrow goes up
** to the row identified by mu:. If this value is zero then
** 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.
** 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 x-coordinates from which
** merge arrows should be drawn into this node. If the value is
** negative, then the x-coordinate is the absolute value of mi[]
** and a thin merge-arrow descender is drawn to the bottom of
** the screen.
*/
cgi_printf("var rowinfo = [\n");
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
int mo = pRow->mergeOut;
if( mo<0 ){
mo = 0;
}else{
mo = (mo/4)*20 - 3 + 4*(mo&3);
}
cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:",
pRow->idx, /* id */
pRow->zBgClr, /* bg */
pRow->iRail, /* r */
pRow->bDescender, /* d */
mo, /* mo */
pRow->mergeUpto, /* mu */
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[i] ){
int mi = i*20 - 8 + 4*pRow->mergeIn[i];
if( pRow->mergeDown & (1<<i) ) mi = -mi;
cgi_printf("%c%d", cSep, mi);
cSep = ',';
}
}
if( cSep=='[' ) cgi_printf("[");
cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n");
}
cgi_printf("var nrail = %d\n", pGraph->mxRail+1);
|
| ︙ | ︙ | |||
516 517 518 519 520 521 522 |
@ 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 ){
| | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
@ 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 + left - 1;
@ 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-5 && x1<=p.x+5 ){
@ y1 = p.y-5;
@ }else{
@ drawThinLine(x0,y1,x1,y1);
@ }
@ drawThinLine(x1,y0,x1,y1);
@ }
@ var n = p.au.length;
|
| ︙ | ︙ | |||
546 547 548 549 550 551 552 |
@ 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;
| | > > > > > > < < < | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 |
@ 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];
@ if( mx<0 ){
@ mx = left-mx;
@ drawThinLine(mx,y0,mx,btm);
@ }else{
@ mx += left;
@ }
@ if( mx>p.x ){
@ drawThinArrow(y0,mx,p.x+6);
@ }else{
@ drawThinArrow(y0,mx,p.x-5);
@ }
@ }
@ }
@ function renderGraph(){
@ var canvasDiv = document.getElementById("canvas");
@ while( canvasDiv.hasChildNodes() ){
@ canvasDiv.removeChild(canvasDiv.firstChild);
@ }
|
| ︙ | ︙ |