ChartTableControl: Add labels outside of pie chart

283209

Signed-off-by: Fritz Schinkel <Fritz.Schinkel@bsi-software.com>
Change-Id: Ia4610b52b32d1098a50082c420af7707f6f2af02
Reviewed-on: https://git.eclipse.org/r/c/scout/org.eclipse.scout.rt/+/173650
Tested-by: Scout Bot <scout-bot@eclipse.org>
Reviewed-by: Fritz Schinkel <fritz.schinkel@bsi-software.com>
diff --git a/eclipse-scout-chart/src/chart/ChartJsRenderer.js b/eclipse-scout-chart/src/chart/ChartJsRenderer.js
index 8d9dfa4..bc71d93 100644
--- a/eclipse-scout-chart/src/chart/ChartJsRenderer.js
+++ b/eclipse-scout-chart/src/chart/ChartJsRenderer.js
@@ -727,6 +727,27 @@
       }, plugins.datalabels);
       plugins.datalabels.display = 'auto';
     }
+    if (config.options.reformatLabels) {
+      let handleFormatter = formatter => {
+        return (value, context) => {
+          let label = formatter.call(context.chart, value, context);
+          return this._formatLabel(label);
+        };
+      };
+
+      if (config.data) {
+        let datasets = config.data.datasets;
+        datasets.forEach(dataset => {
+          if (dataset.datalabels && dataset.datalabels.formatter) {
+            dataset.datalabels.formatter = handleFormatter(dataset.datalabels.formatter);
+          }
+        });
+      }
+      if (plugins.datalabels.formatter) {
+        plugins.datalabels.formatter = handleFormatter(plugins.datalabels.formatter);
+      }
+    }
+
     plugins.datalabels = $.extend(true, {}, {
       formatter: this._datalabelsFormatter
     }, plugins.datalabels);
diff --git a/eclipse-scout-chart/src/table/controls/ChartTableControl.js b/eclipse-scout-chart/src/table/controls/ChartTableControl.js
index bb715a6..8e769d4 100644
--- a/eclipse-scout-chart/src/table/controls/ChartTableControl.js
+++ b/eclipse-scout-chart/src/table/controls/ChartTableControl.js
@@ -22,6 +22,7 @@
     };
     this.chartType = Chart.Type.BAR;
     this.oldChartType = null;
+    this.chartColorScheme = 'chart-table-control';
 
     // chart config selection
     this.$chartSelect = null;
@@ -709,7 +710,7 @@
       type: this.chartType,
       options: {
         handleResize: true,
-        colorScheme: 'chart-table-control',
+        colorScheme: this.chartColorScheme,
         maxSegments: 5,
         legend: {
           display: false
@@ -827,7 +828,7 @@
     segments.forEach(elem => {
       dataset.data.push(elem.value);
       dataset.deterministicKeys.push(elem.deterministicKey);
-      if (elem.label) {
+      if (!objects.isNullOrUndefined(elem.label)) {
         labels.push(elem.label);
       }
     });
@@ -836,6 +837,11 @@
       data.labels = labels;
     }
 
+    // duplicate the dataset for pie charts, this is necessary for datalabels on the segments and outside of the pie chart
+    if (this.chartType === Chart.Type.PIE) {
+      data.datasets[1] = $.extend(true, {}, dataset);
+    }
+
     return data;
   }
 
@@ -1045,6 +1051,21 @@
       return;
     }
 
+    // first dataset is hidden but datalabels are displayed outside of the chart
+    config.data.datasets[0].weight = 0;
+    config.data.datasets[0].datalabels = {
+      display: 'auto',
+      color: styles.get([this.chartColorScheme, this.chartType + '-chart', 'elements', 'label'], 'fill').fill,
+      formatter: (value, context) => {
+        return context.chart.data.labels[context.dataIndex];
+      },
+      anchor: 'end',
+      align: 'end',
+      clamp: true,
+      offset: 10,
+      padding: 4
+    };
+
     config.options = $.extend(true, {}, config.options, {
       plugins: {
         datalabels: {
@@ -1057,8 +1078,8 @@
     config.options = $.extend(true, {}, config.options, {
       layout: {
         padding: {
-          top: Math.sign(margin) < 0 ? Math.abs(margin) : 0,
-          bottom: Math.sign(margin) > 0 ? margin : 0
+          top: 30 + (Math.sign(margin) < 0 ? Math.abs(margin) : 0),
+          bottom: 30 + (Math.sign(margin) > 0 ? margin : 0)
         }
       }
     });
@@ -1105,6 +1126,7 @@
         checkedIndices.push(idx);
       }
     });
+    let datasetIndex = 0;
     if (this.chartType === Chart.Type.PIE) {
       let maxSegments = this.chart.config.options.maxSegments,
         collapsedIndices = arrays.init(deterministicKeys.length - maxSegments).map((elem, idx) => idx + maxSegments);
@@ -1112,13 +1134,16 @@
         arrays.remove(checkedIndices, maxSegments - 1);
       }
       arrays.removeAll(checkedIndices, collapsedIndices);
+
+      // first dataset is hidden on pie charts
+      datasetIndex = 1;
     }
 
     let checkedItems = [];
     if (checkedIndices.length) {
       checkedIndices.forEach(index => {
         checkedItems.push({
-          datasetIndex: 0,
+          datasetIndex: datasetIndex,
           dataIndex: index
         });
       });
@@ -1132,7 +1157,9 @@
     let filters = [];
     if (this.chart && this.chart.config.data) {
       let maxSegments = this.chart.config.options.maxSegments,
-        dataset = this.chart.config.data.datasets[0],
+        // first dataset is hidden on pie charts
+        datasetIndex = this.chartType === Chart.Type.PIE ? 1 : 0,
+        dataset = this.chart.config.data.datasets[datasetIndex],
         getFilters = index => ({deterministicKey: dataset.deterministicKeys[index]});
       if (this.chartType === Chart.Type.PIE) {
         getFilters = index => {
@@ -1144,7 +1171,7 @@
         };
       }
 
-      let checkedIndices = this.chart.checkedItems.filter(item => item.datasetIndex === 0)
+      let checkedIndices = this.chart.checkedItems.filter(item => item.datasetIndex === datasetIndex)
         .map(item => item.dataIndex);
       checkedIndices.forEach(index => {
         arrays.pushAll(filters, getFilters(index));
diff --git a/eclipse-scout-chart/test/table/controls/ChartTableControlSpec.js b/eclipse-scout-chart/test/table/controls/ChartTableControlSpec.js
index c02e24f..a81ea58 100644
--- a/eclipse-scout-chart/test/table/controls/ChartTableControlSpec.js
+++ b/eclipse-scout-chart/test/table/controls/ChartTableControlSpec.js
@@ -10,15 +10,6 @@
  */
 import {ChartTableControl} from '../../../src/index';
 
-/*
- * Copyright (c) 2014-2017 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the BSI CRM Software License v1.0
- * which accompanies this distribution as bsi-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- */
 /* global sandboxSession, createSimpleModel*/
 describe('ChartTableControl', () => {
   let $sandbox, session, chartTableControl, helper, $div;