Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch click-graph-to-diff Excluding Merge-Ins
This is equivalent to a diff from 3e0f48c76d to 7b3def02ed
2012-11-30
| ||
15:22 | Click on the timeline graph once to select a node. Click on a different node to see a diff between the two nodes. Click on the selected node to unselect it. check-in: 5bff5e5cc5 user: drh tags: trunk | |
14:09 | fix testcase check-in: e08073d333 user: jan.nijtmans tags: trunk | |
13:27 | (experimental) command-line expansion for MinGW-w64. Should work on MSVC as well. Doesn't work with MinGW. check-in: b1036fe5bf user: jan.nijtmans tags: cmdline-expansion | |
12:36 | merge trunk. appears to work well again. check-in: 0c65916136 user: jan.nijtmans tags: ticket-d17d6e5b17 | |
03:33 | Fix the click coordinates so that they work even when the page has been scrolled. Closed-Leaf check-in: 7b3def02ed user: drh tags: click-graph-to-diff | |
03:14 | Fix compiler warning. check-in: 95cce92af0 user: drh tags: click-graph-to-diff | |
03:10 | Click on the timeline graph once to select a node. Click on a different node to see a diff between the two. Click on the selected node to undo the selection. Works with check-in timelines and file timelines. check-in: a7dde41fec user: drh tags: click-graph-to-diff | |
00:40 | Move the new utf8.c file into alphabetical order in the makemake.tcl tool. check-in: 3e0f48c76d user: mistachkin tags: trunk | |
00:38 | Update custom MinGW makefile with recent changes. check-in: 2d754ca84b user: mistachkin tags: trunk | |
Changes to src/finfo.c.
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 ... 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 ... 444 445 446 447 448 449 450 451 452 453 |
blob_reset(&sql); blob_zero(&title); blob_appendf(&title, "History of "); hyperlinked_path(zFilename, &title, 0); @ <h2>%b(&title)</h2> blob_reset(&title); pGraph = graph_init(); @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> @ <table id="timelineTable" class="timelineTable"> while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zCom = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); int fpid = db_column_int(&q, 3); int frid = db_column_int(&q, 4); ................................................................................ char zShortCkin[20]; if( zBr==0 ) zBr = "trunk"; if( uBg ){ zBgClr = hash_color(zUser); }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); } gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0); if( memcmp(zDate, zPrevDate, 10) ){ sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); @ <tr><td> @ <div class="divider">%s(zPrevDate)</div> @ </td><td></td><td></td></tr> } memcpy(zTime, &zDate[11], 5); ................................................................................ }else{ @ <tr><td></td><td> @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> @ </td><td></td></tr> } } @ </table> timeline_output_graph_javascript(pGraph, 0); style_footer(); } |
| > | > | |
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 ... 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 ... 446 447 448 449 450 451 452 453 454 455 |
blob_reset(&sql); blob_zero(&title); blob_appendf(&title, "History of "); hyperlinked_path(zFilename, &title, 0); @ <h2>%b(&title)</h2> blob_reset(&title); pGraph = graph_init(); @ <div id="canvas" style="position:relative;width:1px;height:1px;" @ onclick="clickOnGraph(event)"></div> @ <table id="timelineTable" class="timelineTable"> while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zCom = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); int fpid = db_column_int(&q, 3); int frid = db_column_int(&q, 4); ................................................................................ char zShortCkin[20]; if( zBr==0 ) zBr = "trunk"; if( uBg ){ zBgClr = hash_color(zUser); }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); } gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, zUuid, 0); if( memcmp(zDate, zPrevDate, 10) ){ sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); @ <tr><td> @ <div class="divider">%s(zPrevDate)</div> @ </td><td></td><td></td></tr> } memcpy(zTime, &zDate[11], 5); ................................................................................ }else{ @ <tr><td></td><td> @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> @ </td><td></td></tr> } } @ </table> timeline_output_graph_javascript(pGraph, 0, 1); style_footer(); } |
Changes to src/graph.c.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
*/
struct GraphRow {
int rid; /* The rid for the check-in */
i8 nParent; /* Number of parents */
int *aParent; /* Array of parents. 0 element is primary .*/
char *zBranch; /* Branch name */
char *zBgClr; /* Background Color */
GraphRow *pNext; /* Next row down in the list of all rows */
GraphRow *pPrev; /* Previous row */
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 */
................................................................................
int graph_add_row(
GraphContext *p, /* The context to which the row is added */
int rid, /* RID for the check-in */
int nParent, /* Number of parents */
int *aParent, /* Array of parents */
const char *zBranch, /* Branch for this check-in */
const char *zBgClr, /* Background color. NULL or "" for white. */
int isLeaf /* True if this row is a leaf */
){
GraphRow *pRow;
int nByte;
if( p->nErr ) return 0;
nByte = sizeof(GraphRow);
nByte += sizeof(pRow->aParent[0])*nParent;
pRow = (GraphRow*)safeMalloc( nByte );
pRow->aParent = (int*)&pRow[1];
pRow->rid = rid;
pRow->nParent = nParent;
pRow->zBranch = persistBranchName(p, zBranch);
pRow->isLeaf = isLeaf;
memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white";
pRow->zBgClr = persistBranchName(p, zBgClr);
memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
if( p->pFirst==0 ){
p->pFirst = pRow;
|
>
>
>
>
|
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
*/ struct GraphRow { int rid; /* The rid for the check-in */ i8 nParent; /* Number of parents */ int *aParent; /* Array of parents. 0 element is primary .*/ char *zBranch; /* Branch name */ char *zBgClr; /* Background Color */ char zUuid[17]; /* Check-in for file ID */ GraphRow *pNext; /* Next row down in the list of all rows */ GraphRow *pPrev; /* Previous row */ 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 */ ................................................................................ int graph_add_row( GraphContext *p, /* The context to which the row is added */ int rid, /* RID for the check-in */ int nParent, /* Number of parents */ int *aParent, /* Array of parents */ const char *zBranch, /* Branch for this check-in */ const char *zBgClr, /* Background color. NULL or "" for white. */ const char *zUuid, /* SHA1 hash of the object being graphed */ int isLeaf /* True if this row is a leaf */ ){ GraphRow *pRow; int nByte; if( p->nErr ) return 0; nByte = sizeof(GraphRow); nByte += sizeof(pRow->aParent[0])*nParent; pRow = (GraphRow*)safeMalloc( nByte ); pRow->aParent = (int*)&pRow[1]; pRow->rid = rid; pRow->nParent = nParent; pRow->zBranch = persistBranchName(p, zBranch); if( zUuid==0 ) zUuid = ""; sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid); pRow->isLeaf = isLeaf; memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser)); if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white"; pRow->zBgClr = persistBranchName(p, zBgClr); memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent); if( p->pFirst==0 ){ p->pFirst = pRow; |
Changes to src/timeline.c.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 ... 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 ... 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 ... 533 534 535 536 537 538 539 540 541 542 543 544 545 546 ... 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 ... 596 597 598 599 600 601 602 603 604 605 606 607 608 609 ... 697 698 699 700 701 702 703 704 705 706 707 708 709 710 ... 734 735 736 737 738 739 740 741 742 743 744 745 746 747 |
zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); if( tmFlags & TIMELINE_GRAPH ){ pGraph = graph_init(); /* style is not moved to css, because this is ** a technical div for the timeline graph */ @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> } db_static_prepare(&qbranch, "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", TAG_BRANCH ); @ <table id="timelineTable" class="timelineTable"> ................................................................................ " ORDER BY isprim DESC /*sort*/" ); db_bind_int(&qparent, ":rid", rid); while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){ aParent[nParent++] = db_column_int(&qparent, 0); } db_reset(&qparent); gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, isLeaf); db_reset(&qbranch); @ <div id="m%d(gidx)"></div> } @</td> if( zBgClr && zBgClr[0] ){ @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> }else{ ................................................................................ @ <tr><td></td><td> @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> @ </td><td></td></tr> } } @ </table> if( fchngQueryInit ) db_finalize(&fchngQuery); timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); } /* ** Generate all of the necessary javascript to generate a timeline ** graph. */ void timeline_output_graph_javascript(GraphContext *pGraph, int omitDescenders){ if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ GraphRow *pRow; int i; char cSep; @ <script type="text/JavaScript"> @ /* <![CDATA[ */ ................................................................................ ** 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{ ................................................................................ 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); graph_free(pGraph); @ var canvasDiv = gebi("canvas"); #if 0 @ var realCanvas = null; #endif ................................................................................ @ n.style.overflow = "hidden"; @ n.style.left = x0+"px"; @ n.style.top = y0+"px"; @ n.style.width = w+"px"; @ n.style.height = h+"px"; @ n.style.backgroundColor = color; @ canvasDiv.appendChild(n); @ } @ function absoluteY(id){ @ var obj = gebi(id); @ if( !obj ) return; @ var top = 0; @ if( obj.offsetParent ){ @ do{ ................................................................................ @ if( mx>p.x ){ @ drawThinArrow(y0,mx,p.x+6); @ }else{ @ drawThinArrow(y0,mx,p.x-5); @ } @ } @ } @ function renderGraph(){ @ var canvasDiv = gebi("canvas"); @ while( canvasDiv.hasChildNodes() ){ @ canvasDiv.removeChild(canvasDiv.firstChild); @ } @ var canvasY = absoluteY("timelineTable"); @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15; ................................................................................ @ context.fillStyle = color; @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); @ }; @ } #endif @ for(var i in rowinfo){ @ drawNode(rowinfo[i], left, btm); @ } @ } @ var lastId = "m"+rowinfo[rowinfo.length-1].id; @ var lastY = 0; @ function checkHeight(){ @ var h = absoluteY(lastId); @ if( h!=lastY ){ |
| > | > | | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 ... 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 ... 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 ... 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 ... 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 ... 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 ... 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 ... 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 |
zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); if( tmFlags & TIMELINE_GRAPH ){ pGraph = graph_init(); /* style is not moved to css, because this is ** a technical div for the timeline graph */ @ <div id="canvas" style="position:relative;width:1px;height:1px;" @ onclick="clickOnGraph(event)"></div> } db_static_prepare(&qbranch, "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", TAG_BRANCH ); @ <table id="timelineTable" class="timelineTable"> ................................................................................ " ORDER BY isprim DESC /*sort*/" ); db_bind_int(&qparent, ":rid", rid); while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){ aParent[nParent++] = db_column_int(&qparent, 0); } db_reset(&qparent); gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, zUuid, isLeaf); db_reset(&qbranch); @ <div id="m%d(gidx)"></div> } @</td> if( zBgClr && zBgClr[0] ){ @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> }else{ ................................................................................ @ <tr><td></td><td> @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> @ </td><td></td></tr> } } @ </table> if( fchngQueryInit ) db_finalize(&fchngQuery); timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0); } /* ** Generate all of the necessary javascript to generate a timeline ** graph. */ void timeline_output_graph_javascript( GraphContext *pGraph, /* The graph to be displayed */ int omitDescenders, /* True to omit descenders */ int fileDiff /* True for file diff. False for check-in diff */ ){ if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ GraphRow *pRow; int i; char cSep; @ <script type="text/JavaScript"> @ /* <![CDATA[ */ ................................................................................ ** 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. ** h: The SHA1 hash of the object being graphed */ cgi_printf("var rowinfo = [\n"); for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ int mo = pRow->mergeOut; if( mo<0 ){ mo = 0; }else{ ................................................................................ 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("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n"); } cgi_printf("var nrail = %d\n", pGraph->mxRail+1); graph_free(pGraph); @ var canvasDiv = gebi("canvas"); #if 0 @ var realCanvas = null; #endif ................................................................................ @ n.style.overflow = "hidden"; @ n.style.left = x0+"px"; @ n.style.top = y0+"px"; @ n.style.width = w+"px"; @ n.style.height = h+"px"; @ n.style.backgroundColor = color; @ canvasDiv.appendChild(n); @ return n; @ } @ function absoluteY(id){ @ var obj = gebi(id); @ if( !obj ) return; @ var top = 0; @ if( obj.offsetParent ){ @ do{ ................................................................................ @ if( mx>p.x ){ @ drawThinArrow(y0,mx,p.x+6); @ }else{ @ drawThinArrow(y0,mx,p.x-5); @ } @ } @ } @ var selBox = null; @ var selRow = null; @ function renderGraph(){ @ var canvasDiv = gebi("canvas"); @ while( canvasDiv.hasChildNodes() ){ @ canvasDiv.removeChild(canvasDiv.firstChild); @ } @ var canvasY = absoluteY("timelineTable"); @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15; ................................................................................ @ context.fillStyle = color; @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); @ }; @ } #endif @ for(var i in rowinfo){ @ drawNode(rowinfo[i], left, btm); @ } @ if( selRow!=null ) clickOnRow(selRow); @ } @ function clickOnGraph(event){ @ var x=event.clientX-absoluteX("canvas")+window.pageXOffset; @ var y=event.clientY-absoluteY("canvas")+window.pageYOffset; @ for(var i in rowinfo){ @ p = rowinfo[i]; @ if( p.y<y-10 ) continue; @ if( p.y>y+10 ) break; @ if( p.x>x-10 && p.x<x+10 ){ @ clickOnRow(p); @ break; @ } @ } @ } @ function clickOnRow(p){ @ if( selRow==null ){ @ selBox = drawBox("red",p.x-2,p.y-2,p.x+3,p.y+3); @ selRow = p; @ }else if( selRow==p ){ @ var canvasDiv = gebi("canvas"); @ canvasDiv.removeChild(selBox); @ selBox = null; @ selRow = null; @ }else{ if( fileDiff ){ @ location.href="%R/fdiff?v1="+selRow.h+"&v2="+p.h; }else{ @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h; } @ } @ } @ var lastId = "m"+rowinfo[rowinfo.length-1].id; @ var lastY = 0; @ function checkHeight(){ @ var h = absoluteY(lastId); @ if( h!=lastY ){ |