From 7b04578b40271608da18c231357975c9699e9a60 Mon Sep 17 00:00:00 2001
From: AndiMajore <andi.majore@googlemail.com>
Date: Thu, 30 Sep 2021 17:34:36 +0200
Subject: [PATCH] fixed render order and shadow application for pi-charts

---
 src/app/utils.ts | 69 ++++++++++++++++++++++++++++++------------------
 src/index.html   |  2 +-
 2 files changed, 44 insertions(+), 27 deletions(-)

diff --git a/src/app/utils.ts b/src/app/utils.ts
index d9a52735..6ef63356 100644
--- a/src/app/utils.ts
+++ b/src/app/utils.ts
@@ -1,7 +1,7 @@
 // From https://stackoverflow.com/a/27709336/3850564
 
-import { ɵisListLikeIterable } from "@angular/core";
-import { Node } from "./interfaces";
+import {ɵisListLikeIterable} from "@angular/core";
+import {Node} from "./interfaces";
 
 export function getGradientColor(startColor: string, endColor: string, percent: number) {
   // strip the leading # if it's there
@@ -59,16 +59,16 @@ export function removeUnderscoreFromKeys(obj) {
 }
 
 // https://gist.github.com/whitlockjc/9363016
-function trim (str) {
-  return str.replace(/^\s+|\s+$/gm,'');
+function trim(str) {
+  return str.replace(/^\s+|\s+$/gm, '');
 }
 
-export function rgbaToHex (rgba) {
+export function rgbaToHex(rgba) {
   const inParts = rgba.substring(rgba.indexOf("(")).split(","),
-      r = parseInt(trim(inParts[0].substring(1)), 10),
-      g = parseInt(trim(inParts[1]), 10),
-      b = parseInt(trim(inParts[2]), 10),
-      a: number = parseFloat(parseFloat(trim(inParts[3].substring(0, inParts[3].length - 1))).toFixed(2));
+    r = parseInt(trim(inParts[0].substring(1)), 10),
+    g = parseInt(trim(inParts[1]), 10),
+    b = parseInt(trim(inParts[2]), 10),
+    a: number = parseFloat(parseFloat(trim(inParts[3].substring(0, inParts[3].length - 1))).toFixed(2));
   const outParts = [
     r.toString(16),
     g.toString(16),
@@ -94,17 +94,17 @@ function componentToHex(c) {
 
 export function rgbToHex(rgb) {
   const inParts = rgb.substring(rgb.indexOf("(")).split(","),
-      r = parseInt(trim(inParts[0].substring(1)), 10),
-      g = parseInt(trim(inParts[1]), 10),
-      b = parseInt(trim(inParts[2]), 10);
+    r = parseInt(trim(inParts[0].substring(1)), 10),
+    g = parseInt(trim(inParts[1]), 10),
+    b = parseInt(trim(inParts[2]), 10);
   return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
 }
 
 // https://stackoverflow.com/questions/1573053/javascript-function-to-convert-color-names-to-hex-codes/47355187#47355187
-export function standardizeColor(str){
-	var ctx = document.createElement("canvas").getContext("2d");
-	ctx.fillStyle = str;
-	return ctx.fillStyle.toString();
+export function standardizeColor(str) {
+  var ctx = document.createElement("canvas").getContext("2d");
+  ctx.fillStyle = str;
+  return ctx.fillStyle.toString();
 }
 
 export function removeDuplicateObjectsFromList(nodes: Node[], attribute: string): Node[] {
@@ -126,7 +126,7 @@ export function removeDuplicateObjectsFromList(nodes: Node[], attribute: string)
  * @param type - type of the document.
  */
 export function downLoadFile(data: any, type: string, fmt: string) {
-  let blob = new Blob([data], { type: type});
+  let blob = new Blob([data], {type: type});
   var a = document.createElement("a");
   a.href = URL.createObjectURL(blob);
   a.download = `drugstone_network_${new Date().getTime()}.${fmt}`;
@@ -135,7 +135,12 @@ export function downLoadFile(data: any, type: string, fmt: string) {
 
 export function RGBAtoRGB(rgbaString) {
   const rgbaStringSplit = rgbaString.slice(5, -1).split(",");
-  const RGBA = {red: rgbaStringSplit[0], green: rgbaStringSplit[1], blue: rgbaStringSplit[2], alpha: rgbaStringSplit[3]};
+  const RGBA = {
+    red: rgbaStringSplit[0],
+    green: rgbaStringSplit[1],
+    blue: rgbaStringSplit[2],
+    alpha: rgbaStringSplit[3]
+  };
   // assume white background
   const bg = {red: 255, green: 255, blue: 255};
   const RGB = {red: undefined, green: undefined, blue: undefined};
@@ -146,9 +151,9 @@ export function RGBAtoRGB(rgbaString) {
   return `rgb(${RGB.red},${RGB.green},${RGB.blue})`;
 }
 
-export function pieChartContextRenderer({ ctx, x, y, state: { selected, hover }, style, label }) {
+export function pieChartContextRenderer({ctx, x, y, state: {selected, hover}, style, label}) {
   console.log(style)
-  ctx.drawPieLabel = function(style, x, y, label) {
+  ctx.drawPieLabel = function (style, x, y, label) {
     ctx.font = "normal 12px sans-serif";
     ctx.textAlign = "center";
     ctx.textBaseline = "middle";
@@ -156,35 +161,47 @@ export function pieChartContextRenderer({ ctx, x, y, state: { selected, hover },
     ctx.fillText(label, x, y + style.size + 12);
   }
 
-  ctx.drawPie = function(style, x, y) {
+  ctx.drawPie = function (style, x, y) {
     const total = 1;
 
     // draw shadow
     if (style.shadow) {
+      ctx.save()
       ctx.shadowColor = style.shadowColor;
       ctx.shadowOffsetX = style.shadowX;
       ctx.shadowOffsetY = style.shadowY;
       ctx.shadowBlur = 10;
     }
+    // draw white background circle
+    ctx.beginPath();
+    ctx.fillStyle = window.getComputedStyle(document.documentElement).getPropertyValue('--drgstn-background');
+    ctx.arc(x, y, style.size, 0, 2 * Math.PI,false);
+    ctx.fill();
+    ctx.stroke();
 
+    // prepare pi-chart
     ctx.fillStyle = style.color ? style.color : 'rgba(255, 0, 0, 1)';
     // set alpha value to 1
     // ctx.fillStyle = ctx.fillStyle.replace(/[^,]+(?=\))/, '1')
     ctx.fillStyle = RGBAtoRGB(ctx.fillStyle)
-    ctx.strokeStyle = "black";
-    ctx.lineWidth = 2;
     ctx.beginPath();
     ctx.moveTo(x, y);
-    const len = style.opacity/total * 2 * Math.PI;
-    ctx.arc(x , y, style.size, 0, 0 + len, false);
+    const len = style.opacity / total * 2 * Math.PI;
+    ctx.arc(x, y, style.size, 0, 0 + len, false);
     ctx.lineTo(x, y);
     ctx.fill();
+    if (style.shadow) {
+      // removing shadow application of future fill or stroke calls
+      ctx.restore();
+    }
+    ctx.strokeStyle = "black";
+    ctx.lineWidth = selected ? 3 : 2;
     if (style.opacity !== total) {
       // avoid the inner line when circle is complete
       ctx.stroke();
     }
 
-    // draw a cricle
+    // draw the surrounding border circle
     ctx.beginPath();
     ctx.arc(x, y, style.size, 0, 2 * Math.PI);
     ctx.stroke();
diff --git a/src/index.html b/src/index.html
index 37400260..6f45199e 100644
--- a/src/index.html
+++ b/src/index.html
@@ -45,7 +45,7 @@
 
   <network-expander id="netexp1"
                     pluginId="2"
-                    config='{"showLeftSidebar": true, "showSimpleAnalysis":true, "nodeGroups":{"patient":{"type":"patient","color":"black","font":{"color":"#ffffff"},"groupName":"Patient","shape":"image","image":"https://static.thenounproject.com/png/22780-200.png"},"condition":{"type":"condition","color":"black","font":{"color":"black"},"groupName":"Condition","shape":"text"},"important":{"type":"gene","color":"#ff881f","font":{"color":"#000000"},"groupName":"Important Gene","shape":"star"},"gene":{"type":"gene","color":"#4da300","font":{"color":"#000000"},"groupName":"Gene","shape":"circle"},"foundDrug":{"type":"drug","color":{"border":"#F12590","background":"#F12590","highlight":{"border":"#F12590","background":"#F12590"}},"font":{"color":"#f0f0f0"},"groupName":"Drug","shape":"diamond"}},"edgeGroups":{"genotype":{"color":"black","groupName":"Relevant Gene"},"has-condition":{"color":"#000000","groupName":"Has Condition","dashes":[2,2]},"default":{"color":"#000000","groupName":"default edge"},"ggi":{"color":"#000000","groupName":"Interaction","dashes":[3,2]}},"identifier":"symbol","title":"Breast cancer example network","nodeShadow":true,"edgeShadow":false,"autofillEdges":false,"showLegend":true}'
+                    config='{"showLeftSidebar": true, "showSimpleAnalysis":true, "nodeGroups":{"patient":{"type":"patient","color":"black","font":{"color":"#ffffff"},"groupName":"Patient","shape":"image","image":"https://static.thenounproject.com/png/22780-200.png"},"condition":{"type":"condition","color":"black","font":{"color":"black"},"groupName":"Condition","shape":"text"},"important":{"type":"gene","color":"#ff881f","font":{"color":"#000000"},"groupName":"Important Gene","shape":"star"},"gene":{"type":"gene","color":"#4da300","font":{"color":"#4da300"},"groupName":"Gene","shape":"circle"},"foundDrug":{"type":"drug","color":{"border":"#F12590","background":"#F12590","highlight":{"border":"#F12590","background":"#F12590"}},"font":{"color":"#f0f0f0"},"groupName":"Drug","shape":"diamond"}},"edgeGroups":{"genotype":{"color":"black","groupName":"Relevant Gene"},"has-condition":{"color":"#000000","groupName":"Has Condition","dashes":[2,2]},"default":{"color":"#000000","groupName":"default edge"},"ggi":{"color":"#000000","groupName":"Interaction","dashes":[3,2]}},"identifier":"symbol","title":"Breast cancer example network","nodeShadow":true,"edgeShadow":false,"autofillEdges":false,"showLegend":true}'
                     network='{"nodes":[{"id":"patient-1","group":"patient","x":592,"y":446},{"id":"patient-2","group":"patient","x":235,"y":87},{"id":"patient-3","group":"patient","x":105,"y":369},{"id":"ATM","label":"ATM","group":"gene","x":289,"y":242},{"id":"BARD1","label":"BARD1","group":"gene","x":44,"y":250},{"id":"BRCA1","label":"BRCA1","group":"gene","x":466,"y":576},{"id":"BRCA2","label":"BRCA2","group":"gene","x":507,"y":285},{"id":"BRIP1","label":"BRIP1","group":"gene","x":54,"y":474},{"id":"CHEK2","label":"CHEK2","group":"gene","x":216,"y":590},{"id":"CDH1","label":"CDH1","group":"gene","x":320,"y":-57},{"id":"NF1","label":"NF1","group":"gene","x":481,"y":111},{"id":"NBN","label":"NBN","group":"gene","x":-57,"y":314},{"id":"PALB2","label":"PALB2","group":"gene","x":450,"y":190},{"id":"PTEN","label":"PTEN","group":"important","x":305,"y":494},{"id":"RAD51C","label":"RAD51C","group":"gene","x":182,"y":-90},{"id":"RAD51D","label":"RAD51D","group":"gene","x":368,"y":73},{"id":"STK11","label":"STK11","group":"gene","x":686,"y":330},{"id":"TP53","label":"TP53","group":"important","x":333,"y":316},{"id":"subtype-1","label":"Subtype 1","group":"condition","x":556,"y":171},{"id":"subtype-2","label":"Subtype 2","group":"condition","x":-87,"y":221}],"edges":[{"from":"BRCA1","to":"BRCA2","group":"ggi"},{"from":"ATM","to":"BARD1","group":"ggi"},{"from":"BRCA1","to":"CHEK2","group":"ggi"},{"from":"RAD51C","to":"RAD51D","group":"ggi"},{"from":"STK11","to":"TP53","group":"ggi"},{"from":"TP53","to":"PALB2","group":"ggi"},{"from":"TP53","to":"RAD51D","group":"ggi"},{"from":"TP53","to":"NF1","group":"ggi"},{"from":"TP53","to":"BRCA1","group":"ggi"},{"from":"TP53","to":"BRCA2","group":"ggi"},{"from":"PTEN","to":"BRCA1","group":"ggi"},{"from":"PTEN","to":"BRCA2","group":"ggi"},{"from":"TP53","to":"PTEN","group":"ggi"},{"from":"ATM","to":"PTEN","group":"ggi"},{"from":"CDH1","to":"RAD51D","group":"ggi"},{"from":"CDH1","to":"PALB2","group":"ggi"},{"from":"NBN","to":"BRIP1","group":"ggi"},{"from":"BRIP1","to":"PTEN","group":"ggi"},{"from":"patient-1","to":"BRCA1","group":"genotype"},{"from":"patient-1","to":"TP53","group":"genotype"},{"from":"patient-1","to":"BRCA2","group":"genotype"},{"from":"patient-1","to":"PTEN","group":"genotype"},{"from":"patient-2","to":"TP53","group":"genotype"},{"from":"patient-2","to":"NF1","group":"genotype"},{"from":"patient-2","to":"BARD1","group":"genotype"},{"from":"patient-3","to":"TP53","group":"genotype"},{"from":"patient-3","to":"PTEN","group":"genotype"},{"from":"patient-3","to":"NBN","group":"genotype"},{"from":"patient-1","to":"subtype-1","group":"has-condition"},{"from":"patient-2","to":"subtype-1","group":"has-condition"},{"from":"patient-3","to":"subtype-2","group":"has-condition"}]}'>
   }'></network-expander>
 </div>
-- 
GitLab