diff --git a/CHANGELOG b/CHANGELOG index 136c172b58..02050c6681 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow configuration of default colors for graph and calendar * Sanitize RichtText fields content (issue9405) * Escape external string (issue9394) * Keep context in sessionStorage diff --git a/src/common.js b/src/common.js index fdc8ee4cb3..c2aafa0238 100644 --- a/src/common.js +++ b/src/common.js @@ -3673,4 +3673,100 @@ }); }; + Sao.common.COLOR_SCHEMES = { + 'red': '#cf1d1d', + 'green': '#3fb41b', + 'blue': '#224565', + 'grey': '#444444', + 'black': '#000000', + 'darkcyan': '#305755', + }; + + Sao.common.hex2rgb = function(hexstring, digits) { + digits = digits || 2; + var top = parseInt('f'.repeat(digits), 16); + var r = parseInt( + hexstring.substring(1, digits + 1), 16); + var g = parseInt( + hexstring.substring(digits + 1, digits * 2 + 1), 16); + var b = parseInt( + hexstring.substring(digits * 2 + 1, digits * 3 + 1), 16); + return [r / top, g / top, b / top]; + }; + + Sao.common.rgb2hex = function(rgb, digits) { + digits = digits || 2; + var top = parseInt('f'.repeat(digits), 16); + return '#' + rgb + .map(function(i) { return Math.round(i * top).toString(16); }) + .join(''); + }; + + Sao.common.rgb2hsv = function(rgb) { + var r = rgb[0], + g = rgb[1], + b = rgb[2]; + var maxc = Math.max.apply(null, rgb); + var minc = Math.min.apply(null, rgb); + var v = maxc; + if (minc == maxc) return [0, 0, v]; + var s = (maxc - minc) / maxc; + var rc = (maxc - r) / (maxc - minc); + var gc = (maxc - g) / (maxc - minc); + var bc = (maxc - b) / (maxc - minc); + var h; + if (r == maxc) { + h = bc - gc; + } else if (g == maxc) { + h = 2 + rc - bc; + } else { + h = 4 + gc - rc; + } + h = (h / 6) % 1; + return [h, s, v]; + }; + + Sao.common.hsv2rgb = function(hsv) { + var h = hsv[0], + s = hsv[1], + v = hsv[2]; + if (s == 0) return [v, v, v]; + var i = Math.trunc(h * 6); + var f = (h * 6) - i; + var p = v * (1 - s); + var q = v * (1 - s * f); + var t = v * (1 - s * (1 - f)); + i = i % 6; + + if (i == 0) return [v, t, p]; + else if (i == 1) return [q, v, p]; + else if (i == 2) return [p, v, t]; + else if (i == 3) return [p, q, v]; + else if (i == 4) return [t, p, v]; + else if (i == 5) return [v, p, q]; + }; + + Sao.common.generateColorscheme = function(masterColor, keys, light) { + if (light === undefined) { + light = 0.1; + } + var rgb = Sao.common.hex2rgb( + Sao.common.COLOR_SCHEMES[masterColor] || masterColor); + var hsv = Sao.common.rgb2hsv(rgb); + var h = hsv[0], + s = hsv[1], + v = hsv[2]; + if (keys.length) { + light = Math.min(light, (1 - v) / keys.length); + } + var golden_angle = 0.618033988749895; + var colors = {}; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + colors[key] = Sao.common.rgb2hex(Sao.common.hsv2rgb( + [(h + golden_angle * i) % 1, s, (v + light * i) % 1])); + } + return colors; + }; + }()); diff --git a/src/sao.js b/src/sao.js index ebc54449aa..1218c6d770 100644 --- a/src/sao.js +++ b/src/sao.js @@ -282,6 +282,8 @@ var Sao = {}; Sao.config.bug_url = 'https://bugs.tryton.org/'; Sao.config.title = 'Tryton'; Sao.config.icon_colors = '#3465a4,#555753,#cc0000'.split(','); + Sao.config.calendar_colors = '#fff,#3465a4'.split(','); + Sao.config.graph_color = '#3465a4'; Sao.config.bus_timeout = 10 * 60 * 1000; Sao.i18n = i18n(); diff --git a/src/view/calendar.js b/src/view/calendar.js index b0cfb5e9ed..51ae25784b 100644 --- a/src/view/calendar.js +++ b/src/view/calendar.js @@ -97,12 +97,12 @@ }, get_colors: function(record) { var colors = {}; - colors.text_color = 'black'; + colors.text_color = Sao.config.calendar_colors[0]; if (this.attributes.color) { colors.text_color = record.field_get( this.attributes.color); } - colors.background_color = 'lightblue'; + colors.background_color = Sao.config.calendar_colors[1]; if (this.attributes.background_color) { colors.background_color = record.field_get( this.attributes.background_color); diff --git a/src/view/graph.js b/src/view/graph.js index 22a1056eda..e388c6cb09 100644 --- a/src/view/graph.js +++ b/src/view/graph.js @@ -84,9 +84,10 @@ var fields2load = [this.xfield.name]; for (i = 0, len = this.yfields.length; i < len; i++) { yfield = this.yfields[i]; - data.columns.push([yfield.name]); - data.names[yfield.name] = yfield.string; - key2columns[yfield.key || yfield.name] = i + 1; + key = yfield.key || yfield.name; + data.columns.push([key]); + data.names[key] = yfield.string; + key2columns[key] = i + 1; fields2load.push(yfield.name); } @@ -207,17 +208,28 @@ } }; } - var colors = {}; - for (var i = 0; i < this.yfields.length; i++) { - var field = this.yfields[i]; - if (field.color) { - colors[field.name] = field.color; + var color = this.view.attributes.color || Sao.config.graph_color; + var rgb = Sao.common.hex2rgb( + Sao.common.COLOR_SCHEMES[color] || color); + var maxcolor = Math.max.apply(null, rgb); + var keys = []; + var i, yfield; + for (i = 0; i < this.yfields.length; i++) { + yfield = this.yfields[i]; + keys.push(yfield.key || yfield.name); + } + var colors = Sao.common.generateColorscheme( + color, keys, maxcolor / (keys.length || 1)); + for (i = 0; i < this.yfields.length; i++) { + yfield = this.yfields[i]; + if (yfield.color) { + colors[yfield.key || yfield.name] = field.color; } } c3_config.data.color = function(color, column) { // column is an object when called for legend - var name = column.id || column; - return colors[name] || color; + var key = column.id || column; + return colors[key] || color; }; return c3_config; },