Index: skins/xekri/css.txt ================================================================== --- skins/xekri/css.txt +++ skins/xekri/css.txt @@ -1027,6 +1027,5 @@ } /* odd table row color */ tr.row1 { /* Use default */ } - Index: src/configure.c ================================================================== --- src/configure.c +++ src/configure.c @@ -93,10 +93,13 @@ { "background-mimetype", CONFIGSET_SKIN }, { "background-image", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, { "timeline-plaintext", CONFIGSET_SKIN }, + { "timeline-rail-arrows", CONFIGSET_SKIN }, + { "timeline-rail-circles", CONFIGSET_SKIN }, + { "timeline-rail-colors", CONFIGSET_SKIN }, { "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, { "white-foreground", CONFIGSET_SKIN }, Index: src/finfo.c ================================================================== --- src/finfo.c +++ src/finfo.c @@ -307,10 +307,13 @@ GraphContext *pGraph; int brBg = P("brbg")!=0; int uBg = P("ubg")!=0; int fDebug = atoi(PD("debug","0")); int fShowId = P("showid")!=0; + int showRailArrows = db_get_boolean("timeline-rail-arrows", 1); + int showRailCircles = db_get_boolean("timeline-rail-circles", 0); + int showRailColors = db_get_boolean("timeline-rail-colors", 0); login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } style_header("File History"); login_anonymous_available(); @@ -542,8 +545,9 @@ @
@ } } @ - timeline_output_graph_javascript(pGraph, 0, 1); + timeline_output_graph_javascript(pGraph, 0, 1, showRailArrows, + showRailCircles, showRailColors); style_footer(); } Index: src/json_config.c ================================================================== --- src/json_config.c +++ src/json_config.c @@ -63,10 +63,13 @@ { "background-mimetype", CONFIGSET_SKIN }, { "background-image", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, { "timeline-plaintext", CONFIGSET_SKIN }, +{ "timeline-rail-arrows", CONFIGSET_SKIN }, +{ "timeline-rail-circles", CONFIGSET_SKIN }, +{ "timeline-rail-colors", CONFIGSET_SKIN }, { "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, { "white-foreground", CONFIGSET_SKIN }, Index: src/setup.c ================================================================== --- src/setup.c +++ src/setup.c @@ -1339,10 +1339,29 @@ "timeline-plaintext", "tpt", 0, 0); @

In timeline displays, check-in comments are displayed literally, @ without any wiki or HTML interpretation. (Note: Use CSS to change @ display formatting features such as fonts and line-wrapping behavior.)

+ @
+ onoff_attribute("Show branch rail arrowheads", + "timeline-rail-arrows", "tra", 1, 0); + @

The rail (line) that connects check-ins may optionally display an + @ arrowhead indicating the linear progression of changes.

+ + @
+ onoff_attribute("Show check-in timeline nodes as circles", + "timeline-rail-circles", "trc", 0, 0); + @

By default, Fossil will display check-nodes as squares. Alternatively you + @ may prefer to display them as circles.

+ + @
+ onoff_attribute("Use branch background color for branch rails", + "timeline-rail-colors", "trl", 0, 0); + @

Fossil will display your branch rails using the color defined for the + @ branch background. (Note: Branch background colors may not have enough + @ contrast to be easily distinguishable from the timeline background.

+ @
onoff_attribute("Use Universal Coordinated Time (UTC)", "timeline-utc", "utc", 1, 0); @

Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or @ Zulu) instead of in local time. On this server, local time is currently Index: src/style.c ================================================================== --- src/style.c +++ src/style.c @@ -1227,12 +1227,14 @@ { "#usetupEditCapability", "format for capabilities string, mentioned on the user edit page", @ font-weight: bold; }, { "#canvas", "timeline graph node colors", - @ color: black; - @ background-color: white; + @ color: black; /* default rail/line color */ + @ background-color: white; /* default branch node/box color */ + @ border-color: black; /* leaf indicator color */ + @ outline-color: black; /* node/box border color */ }, { "table.adminLogTable", "Class for the /admin_log table", @ text-align: left; }, Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -217,10 +217,13 @@ const char *zThisUser, /* Suppress links to this user */ const char *zThisTag, /* Suppress links to this tag */ int selectedRid, /* Highlight the line with this RID value */ void (*xExtra)(int) /* Routine to call on each line of display */ ){ + int showRailArrows; + int showRailCircles; + int showRailColors; int mxWikiLen; Blob comment; int prevTagid = 0; int suppressCnt = 0; char zPrevDate[20]; @@ -236,10 +239,13 @@ if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){ vid = db_lget_int("checkout", 0); } zPrevDate[0] = 0; + showRailArrows = db_get_boolean("timeline-rail-arrows", 1); + showRailCircles = db_get_boolean("timeline-rail-circles", 0); + showRailColors = db_get_boolean("timeline-rail-colors", 0); mxWikiLen = db_get_int("timeline-max-comment", 0); dateFormat = db_get_int("timeline-date-format", 0); zDateFmt = P("datefmt"); if( zDateFmt ) dateFormat = atoi(zDateFmt); if( tmFlags & TIMELINE_GRAPH ){ @@ -594,21 +600,25 @@ @ } } @ if( fchngQueryInit ) db_finalize(&fchngQuery); - timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0); + timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0, + showRailArrows, showRailCircles, showRailColors); } /* ** 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 */ + int fileDiff, /* True for file diff. False for check-in diff */ + int showRailArrows, /* True to render rail arrow heads */ + int showRailCircles, /* True to render circles instead of squares */ + int showRailColors /* True to color rails by the branch background */ ){ if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ GraphRow *pRow; int i; char cSep; @@ -712,11 +722,12 @@ @ var cDiv = gebi("canvas"); @ var csty = window.getComputedStyle && window.getComputedStyle(cDiv,null); @ var lineClr = (csty && csty.getPropertyValue('color')) || 'black'; @ var bgClr = (csty && csty.getPropertyValue('background-color')) ||'white'; @ if( bgClr=='transparent' ) bgClr = 'white'; - @ var boxColor = lineClr; + @ var boxColor = (csty && csty.getPropertyValue('outline-color')) ||lineClr; + @ var leafColor = (csty && csty.getPropertyValue('border-color')) ||lineClr; @ function drawBox(color,x0,y0,x1,y1){ @ var n = document.createElement("div"); @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } @ var w = x1-x0+1; @@ -751,33 +762,44 @@ @ left += obj.offsetLeft; @ }while( obj = obj.offsetParent ); @ } @ return left; @ } - @ function drawUpArrow(x,y0,y1){ - @ drawBox(lineClr,x,y0+4,x+1,y1); + @ function getRailColor(clr){ + @ var railClr = lineClr; + if( showRailColors ) { + @ if ( bgClr == clr ) railClr = lineClr; + @ railClr = clr||railClr; + } + @ return railClr; + @ } + @ function drawRail(x,y0,y1,clr){ + @ var railClr = getRailColor(clr); + @ drawBox(railClr,x,y0+1,x+1,y1); @ var n = document.createElement("div"), @ l = x-2, @ t = y0; - @ n.style.position = "absolute"; - @ n.style.left = l+"px"; - @ n.style.top = t+"px"; - @ n.style.width = 0; - @ n.style.height = 0; - @ n.style.transform = "scale(.999)"; - @ n.style.borderWidth = 0; - @ n.style.borderStyle = "solid"; - @ n.style.borderColor = "transparent"; - @ n.style.borderRightWidth = "3px"; - @ n.style.borderBottomColor = lineClr; - @ n.style.borderLeftWidth = "3px"; - @ if( y0+10>=y1 ){ - @ n.style.borderBottomWidth = "5px"; - @ } else { - @ n.style.borderBottomWidth = "7px"; - @ } - @ cDiv.appendChild(n); + if( showRailArrows ){ + @ n.style.position = "absolute"; + @ n.style.left = l+"px"; + @ n.style.top = t+"px"; + @ n.style.width = 0; + @ n.style.height = 0; + @ n.style.transform = "scale(.999)"; + @ n.style.borderWidth = 0; + @ n.style.borderStyle = "solid"; + @ n.style.borderColor = "transparent"; + @ n.style.borderRightWidth = "3px"; + @ n.style.borderBottomColor = railClr; + @ n.style.borderLeftWidth = "3px"; + @ if( y0+10>=y1 ){ + @ n.style.borderBottomWidth = "5px"; + @ } else { + @ n.style.borderBottomWidth = "7px"; + @ } + @ cDiv.appendChild(n); + } @ } @ function drawThinArrow(y,xFrom,xTo){ @ var n = document.createElement("div"), @ t = y-2; @ n.style.position = "absolute"; @@ -805,25 +827,34 @@ @ } @ function drawThinLine(x0,y0,x1,y1){ @ drawBox(lineClr,x0,y0,x1,y1); @ } @ function drawNodeBox(color,x0,y0,x1,y1){ - @ drawBox(color,x0,y0,x1,y1).style.cursor = "pointer"; + @ var n = drawBox(color,x0,y0,x1,y1); + @ n.style.cursor = "pointer"; + if( showRailCircles ){ + @ n.style.borderRadius = "6px"; + } @ } @ function drawNode(p, left, btm){ + @ /* Current CheckIn node */ @ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6); @ drawNodeBox(p.bg||bgClr,p.x-4,p.y-4,p.x+5,p.y+5); - @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5); - @ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2); + @ /* Leaf indicator for CheckIn node */ + @ if( p.f&1 ) drawNodeBox(leafColor,p.x-1,p.y-1,p.x+2,p.y+2); + @ /* Branch rail to CheckIn's node */ + @ if( p.u>0 ) drawRail(p.x, rowinfo[p.u-1].y+6, p.y-6, rowinfo[p.u-1].bg); if( !omitDescenders ){ - @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5); - @ if( p.d ) drawUpArrow(p.x, p.y+6, btm); + @ /* Branch rails from bottom or to top of page */ + @ if( p.u==0 ) drawRail(p.x, 0, p.y-6,p.bg); + @ if( p.d ) drawRail(p.x, p.y+6, btm,p.bg); } + @ /* MergeOut horizontal rail */ @ 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 x0 = x1>p.x ? p.x+6 : 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{ @@ -836,13 +867,16 @@ @ for(var i=0; ip.x ? p.x+7 : p.x-6; @ var u = rowinfo[p.au[i+1]-1]; @ if(u.id