21
21
using System . Linq ;
22
22
using System . Text ;
23
23
using Terminaux . Base . Extensions ;
24
+ using Terminaux . Base . Structures ;
24
25
using Terminaux . Colors ;
25
26
using Terminaux . Colors . Data ;
26
27
using Terminaux . Writer . ConsoleWriters ;
@@ -31,7 +32,6 @@ namespace Terminaux.Writer.CyclicWriters.Graphical
31
32
/// <summary>
32
33
/// Breakdown chart renderable
33
34
/// </summary>
34
- // TODO: Make it actually work as a graphical renderable!
35
35
public class BreakdownChart : GraphicalCyclicWriter
36
36
{
37
37
private ChartElement [ ] elements = [ ] ;
@@ -75,108 +75,89 @@ public ChartElement[] Elements
75
75
set => elements = value ;
76
76
}
77
77
78
+ /// <summary>
79
+ /// Whether to render the bars upside down or not
80
+ /// </summary>
81
+ public bool UpsideDown { get ; set ; }
82
+
78
83
/// <summary>
79
84
/// Renders a breakdown chart
80
85
/// </summary>
81
86
/// <returns>Rendered text that will be used by the renderer</returns>
82
87
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 )
90
88
{
91
89
StringBuilder breakdownChart = new ( ) ;
92
90
if ( vertical )
93
91
{
94
92
// Some variables
95
- int maxNameLength = InteriorWidth / 4 ;
96
- int wholeLength = InteriorHeight - 1 ;
93
+ int maxNameLength = Width / 4 ;
97
94
var shownElements = elements . Where ( ( ce ) => ! ce . Hidden ) . ToArray ( ) ;
98
95
double maxValue = elements . Sum ( ( element ) => element . Value ) ;
99
96
double maxValueDisplay = shownElements . Max ( ( element ) => element . Value ) ;
100
97
int nameLength = shownElements . Max ( ( element ) => " ■ " . Length + ConsoleChar . EstimateCellWidth ( element . Name ) + $ " { element . Value } ". Length ) ;
101
98
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 ( ) ;
103
100
int showcaseLength = showcase ? nameLength + 3 : 0 ;
104
101
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
-
120
102
// Fill the breakdown chart with the showcase first
121
- for ( int i = 0 ; i < InteriorHeight ; i ++ )
103
+ if ( Showcase )
122
104
{
123
- // If showcase is on, show names and values.
124
- if ( showcase && i < shownElements . Length )
105
+ for ( int i = 0 ; i < shownElements . Length ; i ++ )
125
106
{
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 ) ;
126
112
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
130
115
breakdownChart . Append (
131
- ( useColor ? ColorTools . RenderSetConsoleColor ( element . Color ) : "" ) +
116
+ ConsolePositioning . RenderChangePosition ( coord . X , coord . Y ) +
117
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( element . Color ) : "" ) +
132
118
" ■ " +
133
- ( useColor ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Grey ) : "" ) +
119
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Grey ) : "" ) +
134
120
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
146
123
) ;
147
124
}
148
- else
125
+
126
+ // Show the separator
127
+ for ( int h = 0 ; h < Height ; h ++ )
149
128
{
129
+ Coordinate separatorCoord = new ( Left + nameLength , Top + h ) ;
150
130
breakdownChart . Append (
131
+ ConsolePositioning . RenderChangePosition ( separatorCoord . X , separatorCoord . Y ) +
151
132
" ┃ "
152
133
) ;
153
134
}
135
+ }
154
136
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 ;
167
144
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
+ }
176
160
}
177
-
178
- if ( i < InteriorHeight - 1 )
179
- breakdownChart . AppendLine ( ) ;
180
161
}
181
162
}
182
163
else
@@ -192,19 +173,19 @@ internal static string RenderBreakdownChart(ChartElement[] elements, int Interio
192
173
continue ;
193
174
194
175
// Render the element bar
195
- int length = ( int ) Math . Round ( value * InteriorWidth / maxValue ) ;
176
+ int length = ( int ) Math . Round ( value * Width / maxValue ) ;
196
177
breakdownChart . Append (
197
- ( useColor ? ColorTools . RenderSetConsoleColor ( color , true ) : "" ) +
178
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( color , true ) : "" ) +
198
179
new string ( ' ' , length ) +
199
- ( useColor ? ColorTools . RenderResetBackground ( ) : "" )
180
+ ( UseColors ? ColorTools . RenderResetBackground ( ) : "" )
200
181
) ;
201
182
}
202
183
203
184
// Then, if we're told to showcase the values and the names, write them below the breakdown chart
204
185
if ( showcase )
205
186
{
206
187
// Render the showcase elements
207
- int maxElementLength = InteriorWidth / 4 ;
188
+ int maxElementLength = Width / 4 ;
208
189
var shownElements = elements . Where ( ( ce ) => ! ce . Hidden ) . ToArray ( ) ;
209
190
int totalWidth = 0 ;
210
191
for ( int i = 0 ; i < shownElements . Length ; i ++ )
@@ -218,19 +199,19 @@ internal static string RenderBreakdownChart(ChartElement[] elements, int Interio
218
199
totalWidth += width + spaces . Length ;
219
200
220
201
// If the element would overflow, make a new line
221
- if ( totalWidth > InteriorWidth || i == 0 )
202
+ if ( totalWidth > Width || i == 0 )
222
203
{
223
204
breakdownChart . AppendLine ( ) ;
224
205
totalWidth = width + spaces . Length ;
225
206
}
226
207
227
208
// Render the showcase element
228
209
breakdownChart . Append (
229
- ( useColor ? ColorTools . RenderSetConsoleColor ( color ) : "" ) +
210
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( color ) : "" ) +
230
211
" ■ " +
231
- ( useColor ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Grey ) : "" ) +
212
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Grey ) : "" ) +
232
213
name + " " +
233
- ( useColor ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Silver ) : "" ) +
214
+ ( UseColors ? ColorTools . RenderSetConsoleColor ( ConsoleColors . Silver ) : "" ) +
234
215
value +
235
216
spaces
236
217
) ;
0 commit comments