Fossil SCM
JavaScript graph drawing enhancements using an HTML5 canvas (if available) suggested by Joshua Paine.
Commit
6fd91413684c87f09a9f722df77a372f2a6fd1cd
Parent
22b6887e40adf0c…
1 file changed
+28
-6
+28
-6
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -396,23 +396,25 @@ | ||
| 396 | 396 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| 397 | 397 | } |
| 398 | 398 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 399 | 399 | graph_free(pGraph); |
| 400 | 400 | @ var canvasDiv = document.getElementById("canvas"); |
| 401 | + @ var realCanvas = null; | |
| 401 | 402 | @ function drawBox(color,x0,y0,x1,y1){ |
| 402 | 403 | @ var n = document.createElement("div"); |
| 403 | 404 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 404 | 405 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 405 | 406 | @ var w = x1-x0+1; |
| 406 | 407 | @ var h = y1-y0+1; |
| 407 | - @ n.innerHTML="<div style=\"position:absolute;overflow:hidden;"+ | |
| 408 | - @ "left:"+x0+"px;"+ | |
| 409 | - @ "top:"+y0+"px;"+ | |
| 410 | - @ "width:"+w+"px;"+ | |
| 411 | - @ "height:"+h+"px;"+ | |
| 412 | - @ "background-color:"+color+";\"></div>" | |
| 413 | 408 | @ canvasDiv.appendChild(n); |
| 409 | + @ n.style.position = "absolute"; | |
| 410 | + @ n.style.overflow = "hidden"; | |
| 411 | + @ n.style.left = x0+"px"; | |
| 412 | + @ n.style.top = y0+"px"; | |
| 413 | + @ n.style.width = w+"px"; | |
| 414 | + @ n.style.height = h+"px"; | |
| 415 | + @ n.style.backgroundColor = color; | |
| 414 | 416 | @ } |
| 415 | 417 | @ function absoluteY(id){ |
| 416 | 418 | @ var obj = document.getElementById(id); |
| 417 | 419 | @ if( !obj ) return; |
| 418 | 420 | @ var top = 0; |
| @@ -500,15 +502,35 @@ | ||
| 500 | 502 | @ while( canvasDiv.hasChildNodes() ){ |
| 501 | 503 | @ canvasDiv.removeChild(canvasDiv.firstChild); |
| 502 | 504 | @ } |
| 503 | 505 | @ var canvasY = absoluteY("canvas"); |
| 504 | 506 | @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15; |
| 507 | + @ var width = left + nrail*20 + 20; | |
| 505 | 508 | @ for(var i in rowinfo){ |
| 506 | 509 | @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY; |
| 507 | 510 | @ rowinfo[i].x = left + rowinfo[i].r*20; |
| 508 | 511 | @ } |
| 509 | 512 | @ var btm = rowinfo[rowinfo.length-1].y + 20; |
| 513 | + @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+ | |
| 514 | + @ 'style="position:absolute;left:'+(left-5)+'px;"' + | |
| 515 | + @ ' width="'+(width-left+26)+'" height="'+btm+'"></canvas>'; | |
| 516 | + @ realCanvas = document.getElementById('timeline-canvas'); | |
| 517 | + @ var context; | |
| 518 | + @ if( realCanvas && realCanvas.getContext | |
| 519 | + @ && (context = realCanvas.getContext('2d'))) { | |
| 520 | + @ drawBox = function(color,x0,y0,x1,y1) { | |
| 521 | + @ var colors = { | |
| 522 | + @ 'white':'rgba(255,255,255,1)', | |
| 523 | + @ 'black':'rgba(0,0,0,1)' | |
| 524 | + @ }; | |
| 525 | + @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } | |
| 526 | + @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } | |
| 527 | + @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return; | |
| 528 | + @ context.fillStyle = colors[color]; | |
| 529 | + @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); | |
| 530 | + @ }; | |
| 531 | + @ } | |
| 510 | 532 | @ for(var i in rowinfo){ |
| 511 | 533 | @ drawNode(rowinfo[i], left, btm); |
| 512 | 534 | @ } |
| 513 | 535 | @ } |
| 514 | 536 | @ var lastId = rowinfo[rowinfo.length-1].id; |
| 515 | 537 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -396,23 +396,25 @@ | |
| 396 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| 397 | } |
| 398 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 399 | graph_free(pGraph); |
| 400 | @ var canvasDiv = document.getElementById("canvas"); |
| 401 | @ function drawBox(color,x0,y0,x1,y1){ |
| 402 | @ var n = document.createElement("div"); |
| 403 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 404 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 405 | @ var w = x1-x0+1; |
| 406 | @ var h = y1-y0+1; |
| 407 | @ n.innerHTML="<div style=\"position:absolute;overflow:hidden;"+ |
| 408 | @ "left:"+x0+"px;"+ |
| 409 | @ "top:"+y0+"px;"+ |
| 410 | @ "width:"+w+"px;"+ |
| 411 | @ "height:"+h+"px;"+ |
| 412 | @ "background-color:"+color+";\"></div>" |
| 413 | @ canvasDiv.appendChild(n); |
| 414 | @ } |
| 415 | @ function absoluteY(id){ |
| 416 | @ var obj = document.getElementById(id); |
| 417 | @ if( !obj ) return; |
| 418 | @ var top = 0; |
| @@ -500,15 +502,35 @@ | |
| 500 | @ while( canvasDiv.hasChildNodes() ){ |
| 501 | @ canvasDiv.removeChild(canvasDiv.firstChild); |
| 502 | @ } |
| 503 | @ var canvasY = absoluteY("canvas"); |
| 504 | @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15; |
| 505 | @ for(var i in rowinfo){ |
| 506 | @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY; |
| 507 | @ rowinfo[i].x = left + rowinfo[i].r*20; |
| 508 | @ } |
| 509 | @ var btm = rowinfo[rowinfo.length-1].y + 20; |
| 510 | @ for(var i in rowinfo){ |
| 511 | @ drawNode(rowinfo[i], left, btm); |
| 512 | @ } |
| 513 | @ } |
| 514 | @ var lastId = rowinfo[rowinfo.length-1].id; |
| 515 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -396,23 +396,25 @@ | |
| 396 | cgi_printf("]}%s", pRow->pNext ? ",\n" : "];\n"); |
| 397 | } |
| 398 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 399 | graph_free(pGraph); |
| 400 | @ var canvasDiv = document.getElementById("canvas"); |
| 401 | @ var realCanvas = null; |
| 402 | @ function drawBox(color,x0,y0,x1,y1){ |
| 403 | @ var n = document.createElement("div"); |
| 404 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 405 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 406 | @ var w = x1-x0+1; |
| 407 | @ var h = y1-y0+1; |
| 408 | @ canvasDiv.appendChild(n); |
| 409 | @ n.style.position = "absolute"; |
| 410 | @ n.style.overflow = "hidden"; |
| 411 | @ n.style.left = x0+"px"; |
| 412 | @ n.style.top = y0+"px"; |
| 413 | @ n.style.width = w+"px"; |
| 414 | @ n.style.height = h+"px"; |
| 415 | @ n.style.backgroundColor = color; |
| 416 | @ } |
| 417 | @ function absoluteY(id){ |
| 418 | @ var obj = document.getElementById(id); |
| 419 | @ if( !obj ) return; |
| 420 | @ var top = 0; |
| @@ -500,15 +502,35 @@ | |
| 502 | @ while( canvasDiv.hasChildNodes() ){ |
| 503 | @ canvasDiv.removeChild(canvasDiv.firstChild); |
| 504 | @ } |
| 505 | @ var canvasY = absoluteY("canvas"); |
| 506 | @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15; |
| 507 | @ var width = left + nrail*20 + 20; |
| 508 | @ for(var i in rowinfo){ |
| 509 | @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY; |
| 510 | @ rowinfo[i].x = left + rowinfo[i].r*20; |
| 511 | @ } |
| 512 | @ var btm = rowinfo[rowinfo.length-1].y + 20; |
| 513 | @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+ |
| 514 | @ 'style="position:absolute;left:'+(left-5)+'px;"' + |
| 515 | @ ' width="'+(width-left+26)+'" height="'+btm+'"></canvas>'; |
| 516 | @ realCanvas = document.getElementById('timeline-canvas'); |
| 517 | @ var context; |
| 518 | @ if( realCanvas && realCanvas.getContext |
| 519 | @ && (context = realCanvas.getContext('2d'))) { |
| 520 | @ drawBox = function(color,x0,y0,x1,y1) { |
| 521 | @ var colors = { |
| 522 | @ 'white':'rgba(255,255,255,1)', |
| 523 | @ 'black':'rgba(0,0,0,1)' |
| 524 | @ }; |
| 525 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 526 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 527 | @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return; |
| 528 | @ context.fillStyle = colors[color]; |
| 529 | @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); |
| 530 | @ }; |
| 531 | @ } |
| 532 | @ for(var i in rowinfo){ |
| 533 | @ drawNode(rowinfo[i], left, btm); |
| 534 | @ } |
| 535 | @ } |
| 536 | @ var lastId = rowinfo[rowinfo.length-1].id; |
| 537 |