Skip to content

Commit 8aec703

Browse files
committed
add themed hover styling
1 parent 273d0b9 commit 8aec703

File tree

9 files changed

+436
-100
lines changed

9 files changed

+436
-100
lines changed

Shared Files/Resources/reportparts.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
<ReportPart Name="CoverageTableActiveSortColour" SelectedThemeColourName="EnvironmentColors.SystemHighlightColorKey" />
1919
<ReportPart Name="CoverageTableInactiveSortColour" SelectedThemeColourName="EnvironmentColors.ToolWindowTextColorKey" />
2020
<ReportPart Name="CoverageTableExpandCollapseIconColour" SelectedThemeColourName="EnvironmentColors.ToolWindowTextColorKey" />
21-
<ReportPart Name="CoverageTableRowHoverBackgroundColour" SelectedThemeColourName="EnvironmentColors.ToolWindowBackgroundColorKey" />
21+
<ReportPart Name="CoverageTableRowHoverBackgroundColour" SelectedThemeColourName="EnvironmentColors.ToolWindowTextColorKey" />
22+
<ReportPart Name="CoverageTableRowHoverColour" SelectedThemeColourName="EnvironmentColors.ToolWindowBackgroundColorKey" />
2223
<ReportPart Name="TabBackgroundColour" SelectedThemeColourName="EnvironmentColors.FileTabBackgroundColorKey" />
2324
<ReportPart Name="DivHeaderBackgroundColour" SelectedThemeColourName="EnvironmentColors.ToolWindowBackgroundColorKey" />
2425
<ReportPart Name="HeaderFontColour" SelectedThemeColourName="EnvironmentColors.FileTabTextColorKey" />
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
using System;
2+
3+
namespace FineCodeCoverage.Engine.ReportGenerator
4+
{
5+
/*
6+
Conversions from https://www.codeproject.com/Articles/19045/Manipulating-colors-in-NET-Part-1#hsb
7+
This is potentially better https://github.com/tompazourek/Colourful/
8+
9+
*/
10+
public struct RGB
11+
{
12+
/// <summary>
13+
/// Gets an empty RGB structure;
14+
/// </summary>
15+
public static readonly RGB Empty = new RGB();
16+
17+
private int red;
18+
private int green;
19+
private int blue;
20+
21+
public static bool operator ==(RGB item1, RGB item2)
22+
{
23+
return (
24+
item1.Red == item2.Red
25+
&& item1.Green == item2.Green
26+
&& item1.Blue == item2.Blue
27+
);
28+
}
29+
30+
public static bool operator !=(RGB item1, RGB item2)
31+
{
32+
return (
33+
item1.Red != item2.Red
34+
|| item1.Green != item2.Green
35+
|| item1.Blue != item2.Blue
36+
);
37+
}
38+
39+
/// <summary>
40+
/// Gets or sets red value.
41+
/// </summary>
42+
public int Red
43+
{
44+
get
45+
{
46+
return red;
47+
}
48+
set
49+
{
50+
red = (value > 255) ? 255 : ((value < 0) ? 0 : value);
51+
}
52+
}
53+
54+
/// <summary>
55+
/// Gets or sets red value.
56+
/// </summary>
57+
public int Green
58+
{
59+
get
60+
{
61+
return green;
62+
}
63+
set
64+
{
65+
green = (value > 255) ? 255 : ((value < 0) ? 0 : value);
66+
}
67+
}
68+
69+
/// <summary>
70+
/// Gets or sets red value.
71+
/// </summary>
72+
public int Blue
73+
{
74+
get
75+
{
76+
return blue;
77+
}
78+
set
79+
{
80+
blue = (value > 255) ? 255 : ((value < 0) ? 0 : value);
81+
}
82+
}
83+
84+
public RGB(int R, int G, int B)
85+
{
86+
this.red = (R > 255) ? 255 : ((R < 0) ? 0 : R);
87+
this.green = (G > 255) ? 255 : ((G < 0) ? 0 : G);
88+
this.blue = (B > 255) ? 255 : ((B < 0) ? 0 : B);
89+
}
90+
91+
public override bool Equals(Object obj)
92+
{
93+
if (obj == null || GetType() != obj.GetType()) return false;
94+
95+
return (this == (RGB)obj);
96+
}
97+
98+
public override int GetHashCode()
99+
{
100+
return Red.GetHashCode() ^ Green.GetHashCode() ^ Blue.GetHashCode();
101+
}
102+
}
103+
public static class ColorConversion
104+
{
105+
/// <summary>
106+
/// Converts HSL to RGB.
107+
/// </summary>
108+
/// <param name="h">Hue, must be in [0, 360].</param>
109+
/// <param name="s">Saturation, must be in [0, 1].</param>
110+
/// <param name="l">Luminance, must be in [0, 1].</param>
111+
public static RGB HSLtoRGB(double h, double s, double l)
112+
{
113+
if (s == 0)
114+
{
115+
// achromatic color (gray scale)
116+
return new RGB(
117+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
118+
l * 255.0))),
119+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
120+
l * 255.0))),
121+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
122+
l * 255.0)))
123+
);
124+
}
125+
else
126+
{
127+
double q = (l < 0.5) ? (l * (1.0 + s)) : (l + s - (l * s));
128+
double p = (2.0 * l) - q;
129+
130+
double Hk = h / 360.0;
131+
double[] T = new double[3];
132+
T[0] = Hk + (1.0 / 3.0); // Tr
133+
T[1] = Hk; // Tb
134+
T[2] = Hk - (1.0 / 3.0); // Tg
135+
136+
for (int i = 0; i < 3; i++)
137+
{
138+
if (T[i] < 0) T[i] += 1.0;
139+
if (T[i] > 1) T[i] -= 1.0;
140+
141+
if ((T[i] * 6) < 1)
142+
{
143+
T[i] = p + ((q - p) * 6.0 * T[i]);
144+
}
145+
else if ((T[i] * 2.0) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5
146+
{
147+
T[i] = q;
148+
}
149+
else if ((T[i] * 3.0) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0)
150+
{
151+
T[i] = p + (q - p) * ((2.0 / 3.0) - T[i]) * 6.0;
152+
}
153+
else T[i] = p;
154+
}
155+
156+
return new RGB(
157+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
158+
T[0] * 255.0))),
159+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
160+
T[1] * 255.0))),
161+
Convert.ToInt32(Double.Parse(String.Format("{0:0.00}",
162+
T[2] * 255.0)))
163+
);
164+
}
165+
}
166+
167+
public static HSL RGBtoHSL(int red, int green, int blue)
168+
{
169+
double h = 0, s = 0, l = 0;
170+
171+
// normalize red, green, blue values
172+
double r = (double)red / 255.0;
173+
double g = (double)green / 255.0;
174+
double b = (double)blue / 255.0;
175+
176+
double max = Math.Max(r, Math.Max(g, b));
177+
double min = Math.Min(r, Math.Min(g, b));
178+
179+
// hue
180+
if (max == min)
181+
{
182+
h = 0; // undefined
183+
}
184+
else if (max == r && g >= b)
185+
{
186+
h = 60.0 * (g - b) / (max - min);
187+
}
188+
else if (max == r && g < b)
189+
{
190+
h = 60.0 * (g - b) / (max - min) + 360.0;
191+
}
192+
else if (max == g)
193+
{
194+
h = 60.0 * (b - r) / (max - min) + 120.0;
195+
}
196+
else if (max == b)
197+
{
198+
h = 60.0 * (r - g) / (max - min) + 240.0;
199+
}
200+
201+
// luminance
202+
l = (max + min) / 2.0;
203+
204+
// saturation
205+
if (l == 0 || max == min)
206+
{
207+
s = 0;
208+
}
209+
else if (0 < l && l <= 0.5)
210+
{
211+
s = (max - min) / (max + min);
212+
}
213+
else if (l > 0.5)
214+
{
215+
s = (max - min) / (2 - (max + min)); //(max-min > 0)?
216+
}
217+
218+
return new HSL(
219+
Double.Parse(String.Format("{0:0.##}", h)),
220+
Double.Parse(String.Format("{0:0.##}", s)),
221+
Double.Parse(String.Format("{0:0.##}", l))
222+
);
223+
}
224+
}
225+
226+
public struct HSL
227+
{
228+
/// <summary>
229+
/// Gets an empty HSL structure;
230+
/// </summary>
231+
public static readonly HSL Empty = new HSL();
232+
233+
private double hue;
234+
private double saturation;
235+
private double luminance;
236+
237+
public static bool operator ==(HSL item1, HSL item2)
238+
{
239+
return (
240+
item1.Hue == item2.Hue
241+
&& item1.Saturation == item2.Saturation
242+
&& item1.Luminance == item2.Luminance
243+
);
244+
}
245+
246+
public static bool operator !=(HSL item1, HSL item2)
247+
{
248+
return (
249+
item1.Hue != item2.Hue
250+
|| item1.Saturation != item2.Saturation
251+
|| item1.Luminance != item2.Luminance
252+
);
253+
}
254+
255+
/// <summary>
256+
/// Gets or sets the hue component.
257+
/// </summary>
258+
public double Hue
259+
{
260+
get
261+
{
262+
return hue;
263+
}
264+
set
265+
{
266+
hue = (value > 360) ? 360 : ((value < 0) ? 0 : value);
267+
}
268+
}
269+
270+
/// <summary>
271+
/// Gets or sets saturation component.
272+
/// </summary>
273+
public double Saturation
274+
{
275+
get
276+
{
277+
return saturation;
278+
}
279+
set
280+
{
281+
saturation = (value > 1) ? 1 : ((value < 0) ? 0 : value);
282+
}
283+
}
284+
285+
/// <summary>
286+
/// Gets or sets the luminance component.
287+
/// </summary>
288+
public double Luminance
289+
{
290+
get
291+
{
292+
return luminance;
293+
}
294+
set
295+
{
296+
luminance = (value > 1) ? 1 : ((value < 0) ? 0 : value);
297+
}
298+
}
299+
300+
/// <summary>
301+
/// Creates an instance of a HSL structure.
302+
/// </summary>
303+
/// <param name="h">Hue value.</param>
304+
/// <param name="s">Saturation value.</param>
305+
/// <param name="l">Lightness value.</param>
306+
public HSL(double h, double s, double l)
307+
{
308+
this.hue = (h > 360) ? 360 : ((h < 0) ? 0 : h);
309+
this.saturation = (s > 1) ? 1 : ((s < 0) ? 0 : s);
310+
this.luminance = (l > 1) ? 1 : ((l < 0) ? 0 : l);
311+
}
312+
313+
public override bool Equals(Object obj)
314+
{
315+
if (obj == null || GetType() != obj.GetType()) return false;
316+
317+
return (this == (HSL)obj);
318+
}
319+
320+
public override int GetHashCode()
321+
{
322+
return Hue.GetHashCode() ^ Saturation.GetHashCode() ^
323+
Luminance.GetHashCode();
324+
}
325+
}
326+
public static class LightenssApplier
327+
{
328+
public static System.Drawing.Color Swap(System.Drawing.Color lightnessColor, System.Drawing.Color applyToColor)
329+
{
330+
var hsl = ColorConversion.RGBtoHSL(lightnessColor.R, lightnessColor.G, lightnessColor.B);
331+
var hsl2 = ColorConversion.RGBtoHSL(applyToColor.R, applyToColor.G, applyToColor.B);
332+
hsl2.Luminance = hsl.Luminance;
333+
var rgb = ColorConversion.HSLtoRGB(hsl2.Hue, hsl2.Saturation, hsl2.Luminance);
334+
return System.Drawing.Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
335+
}
336+
}
337+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
3+
namespace FineCodeCoverage.Engine.ReportGenerator
4+
{
5+
internal static class LuminanceContrastColourExtensions
6+
{
7+
public static double Contrast(this System.Drawing.Color color, System.Drawing.Color color2)
8+
{
9+
var l1 = color.Luminance();
10+
var l2 = color2.Luminance();
11+
return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
12+
13+
}
14+
15+
public static double Luminance(this System.Drawing.Color color)
16+
{
17+
return Luminance(color.R, color.G, color.B);
18+
}
19+
20+
private static double Luminance(int r, int g, int b)
21+
{
22+
var lr = LuminanceX(r);
23+
var lg = LuminanceX(g);
24+
var lb = LuminanceX(b);
25+
return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;
26+
27+
}
28+
29+
private static double LuminanceX(int x)
30+
{
31+
x /= 255;
32+
return x <= 0.03928 ? x / 12.92 : Math.Pow((x + 0.055) / 1.055, 2.4);
33+
34+
}
35+
}
36+
}

SharedProject/Core/ReportGenerator/IReportColours.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ internal interface IReportColours
2424
Color CoverageTableInactiveSortColour { get; }
2525

2626
Color CoverageTableRowHoverBackgroundColour { get; }
27+
Color CoverageTableRowHoverColour { get; }
2728

2829
Color DivHeaderBackgroundColour { get; }
2930

0 commit comments

Comments
 (0)