Skip to content

Commit 021d7f0

Browse files
committed
imp - Improved BreakdownChart rendering (vertical)
--- We've improved rendering the vertical breakdown charts to better visualize data. --- Type: imp Breaking: False Doc Required: False Backport Required: False Part: 1/2
1 parent 706e3b5 commit 021d7f0

File tree

1 file changed

+58
-77
lines changed

1 file changed

+58
-77
lines changed

public/Terminaux/Writer/CyclicWriters/Graphical/BreakdownChart.cs

+58-77
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Linq;
2222
using System.Text;
2323
using Terminaux.Base.Extensions;
24+
using Terminaux.Base.Structures;
2425
using Terminaux.Colors;
2526
using Terminaux.Colors.Data;
2627
using Terminaux.Writer.ConsoleWriters;
@@ -31,7 +32,6 @@ namespace Terminaux.Writer.CyclicWriters.Graphical
3132
/// <summary>
3233
/// Breakdown chart renderable
3334
/// </summary>
34-
// TODO: Make it actually work as a graphical renderable!
3535
public class BreakdownChart : GraphicalCyclicWriter
3636
{
3737
private ChartElement[] elements = [];
@@ -75,108 +75,89 @@ public ChartElement[] Elements
7575
set => elements = value;
7676
}
7777

78+
/// <summary>
79+
/// Whether to render the bars upside down or not
80+
/// </summary>
81+
public bool UpsideDown { get; set; }
82+
7883
/// <summary>
7984
/// Renders a breakdown chart
8085
/// </summary>
8186
/// <returns>Rendered text that will be used by the renderer</returns>
8287
public override string Render()
83-
{
84-
return TextWriterWhereColor.RenderWhere(
85-
RenderBreakdownChart(
86-
elements, Width, Height, Showcase, Vertical, UseColors), Left, Top);
87-
}
88-
89-
internal static string RenderBreakdownChart(ChartElement[] elements, int InteriorWidth, int InteriorHeight, bool showcase = false, bool vertical = false, bool useColor = true)
9088
{
9189
StringBuilder breakdownChart = new();
9290
if (vertical)
9391
{
9492
// Some variables
95-
int maxNameLength = InteriorWidth / 4;
96-
int wholeLength = InteriorHeight - 1;
93+
int maxNameLength = Width / 4;
9794
var shownElements = elements.Where((ce) => !ce.Hidden).ToArray();
9895
double maxValue = elements.Sum((element) => element.Value);
9996
double maxValueDisplay = shownElements.Max((element) => element.Value);
10097
int nameLength = shownElements.Max((element) => " ■ ".Length + ConsoleChar.EstimateCellWidth(element.Name) + $" {element.Value}".Length);
10198
nameLength = nameLength > maxNameLength ? maxNameLength : nameLength;
102-
var shownElementHeights = shownElements.Select((ce) => (ce, (int)Math.Round(ce.Value * wholeLength / maxValue))).ToArray();
99+
var shownElementHeights = shownElements.Select((ce) => (ce, (int)Math.Round(ce.Value * Height / maxValue) * 2)).OrderByDescending((ce) => ce.Item2).ToArray();
103100
int showcaseLength = showcase ? nameLength + 3 : 0;
104101

105-
// Get the height starts
106-
for (int e = 0; e < shownElementHeights.Length; e++)
107-
{
108-
var elementTuple = shownElementHeights[e];
109-
var elementSecond = e + 1 >= shownElementHeights.Length ? (null, 0) : shownElementHeights[e + 1];
110-
int sum = 0;
111-
for (int eh = e - 1; eh <= e; eh++)
112-
{
113-
eh = eh < 0 ? 0 : eh;
114-
var elementTupleCalc = shownElementHeights[eh];
115-
sum += elementTupleCalc.Item2;
116-
}
117-
shownElementHeights[e] = (elementTuple.ce, sum);
118-
}
119-
120102
// Fill the breakdown chart with the showcase first
121-
for (int i = 0; i < InteriorHeight; i++)
103+
if (Showcase)
122104
{
123-
// If showcase is on, show names and values.
124-
if (showcase && i < shownElements.Length)
105+
for (int i = 0; i < shownElements.Length; i++)
125106
{
107+
// Get the element showcase position and write it there
108+
bool canShow = Height > i;
109+
if (!canShow)
110+
break;
111+
Coordinate coord = new(Left, Top + i);
126112
var element = shownElements[i];
127-
int nameWidth = ConsoleChar.EstimateCellWidth(element.Name.Truncate(nameLength - 4 - $"{maxValue}".Length));
128-
int spaces = showcaseLength - (" ■ ".Length + nameWidth + 2 + $"{element.Value}".Length);
129-
spaces = spaces < 0 ? 0 : spaces;
113+
114+
// Now, write it at the selected position
130115
breakdownChart.Append(
131-
(useColor ? ColorTools.RenderSetConsoleColor(element.Color) : "") +
116+
ConsolePositioning.RenderChangePosition(coord.X, coord.Y) +
117+
(UseColors ? ColorTools.RenderSetConsoleColor(element.Color) : "") +
132118
" ■ " +
133-
(useColor ? ColorTools.RenderSetConsoleColor(ConsoleColors.Grey) : "") +
119+
(UseColors ? ColorTools.RenderSetConsoleColor(ConsoleColors.Grey) : "") +
134120
element.Name.Truncate(nameLength - 4 - $"{maxValueDisplay}".Length) + " " +
135-
(useColor ? ColorTools.RenderSetConsoleColor(ConsoleColors.Silver) : "") +
136-
element.Value +
137-
new string(' ', spaces) +
138-
" ┃ "
139-
);
140-
}
141-
else if (showcase)
142-
{
143-
breakdownChart.Append(
144-
new string(' ', showcaseLength) +
145-
" ┃ "
121+
(UseColors ? ColorTools.RenderSetConsoleColor(ConsoleColors.Silver) : "") +
122+
element.Value
146123
);
147124
}
148-
else
125+
126+
// Show the separator
127+
for (int h = 0; h < Height; h++)
149128
{
129+
Coordinate separatorCoord = new(Left + nameLength, Top + h);
150130
breakdownChart.Append(
131+
ConsolePositioning.RenderChangePosition(separatorCoord.X, separatorCoord.Y) +
151132
" ┃ "
152133
);
153134
}
135+
}
154136

155-
// Render all elements
156-
for (int e = 0; e < shownElementHeights.Length; e++)
157-
{
158-
var elementTuple = shownElementHeights[e];
159-
ChartElement? element = elementTuple.ce;
160-
int height = elementTuple.Item2;
161-
if (i > height)
162-
continue;
163-
164-
var color = element.Color;
165-
string name = element.Name;
166-
double value = element.Value;
137+
// Show the actual bar
138+
for (int e = 0; e < shownElementHeights.Length; e++)
139+
{
140+
// Get the element and the height
141+
var elementTuple = shownElementHeights[e];
142+
ChartElement element = elementTuple.ce;
143+
int height = elementTuple.Item2;
167144

168-
// Render the element and its value
169-
int length = (int)(value * wholeLength / maxValue);
170-
breakdownChart.Append(
171-
(useColor ? ColorTools.RenderSetConsoleColor(color, true) : "") +
172-
" " +
173-
(useColor ? ColorTools.RenderResetBackground() : "")
174-
);
175-
break;
145+
// Use the chart height to draw the stick
146+
for (int h = 0; h < Height; h++)
147+
{
148+
// Decide whether to draw this area or not
149+
int inverse = UpsideDown ? h : Height - h;
150+
Coordinate stickCoord = new(Left + showcaseLength, Top + h);
151+
if (inverse <= height)
152+
{
153+
breakdownChart.Append(
154+
ConsolePositioning.RenderChangePosition(stickCoord.X, stickCoord.Y) +
155+
(UseColors ? ColorTools.RenderSetConsoleColor(element.Color, true) : "") +
156+
" " +
157+
(UseColors ? ColorTools.RenderResetBackground() : "")
158+
);
159+
}
176160
}
177-
178-
if (i < InteriorHeight - 1)
179-
breakdownChart.AppendLine();
180161
}
181162
}
182163
else
@@ -192,19 +173,19 @@ internal static string RenderBreakdownChart(ChartElement[] elements, int Interio
192173
continue;
193174

194175
// Render the element bar
195-
int length = (int)Math.Round(value * InteriorWidth / maxValue);
176+
int length = (int)Math.Round(value * Width / maxValue);
196177
breakdownChart.Append(
197-
(useColor ? ColorTools.RenderSetConsoleColor(color, true) : "") +
178+
(UseColors ? ColorTools.RenderSetConsoleColor(color, true) : "") +
198179
new string(' ', length) +
199-
(useColor ? ColorTools.RenderResetBackground() : "")
180+
(UseColors ? ColorTools.RenderResetBackground() : "")
200181
);
201182
}
202183

203184
// Then, if we're told to showcase the values and the names, write them below the breakdown chart
204185
if (showcase)
205186
{
206187
// Render the showcase elements
207-
int maxElementLength = InteriorWidth / 4;
188+
int maxElementLength = Width / 4;
208189
var shownElements = elements.Where((ce) => !ce.Hidden).ToArray();
209190
int totalWidth = 0;
210191
for (int i = 0; i < shownElements.Length; i++)
@@ -218,19 +199,19 @@ internal static string RenderBreakdownChart(ChartElement[] elements, int Interio
218199
totalWidth += width + spaces.Length;
219200

220201
// If the element would overflow, make a new line
221-
if (totalWidth > InteriorWidth || i == 0)
202+
if (totalWidth > Width || i == 0)
222203
{
223204
breakdownChart.AppendLine();
224205
totalWidth = width + spaces.Length;
225206
}
226207

227208
// Render the showcase element
228209
breakdownChart.Append(
229-
(useColor ? ColorTools.RenderSetConsoleColor(color) : "") +
210+
(UseColors ? ColorTools.RenderSetConsoleColor(color) : "") +
230211
" ■ " +
231-
(useColor ? ColorTools.RenderSetConsoleColor(ConsoleColors.Grey) : "") +
212+
(UseColors ? ColorTools.RenderSetConsoleColor(ConsoleColors.Grey) : "") +
232213
name + " " +
233-
(useColor ? ColorTools.RenderSetConsoleColor(ConsoleColors.Silver) : "") +
214+
(UseColors ? ColorTools.RenderSetConsoleColor(ConsoleColors.Silver) : "") +
234215
value +
235216
spaces
236217
);

0 commit comments

Comments
 (0)