mirror of
https://github.com/Rayerd/dfl.git
synced 2025-04-25 20:49:58 +03:00
Add dfl.chart.TimeChartRenderer with example code
This commit is contained in:
parent
ccca379024
commit
2f84718bd3
11 changed files with 683 additions and 3 deletions
|
@ -6,8 +6,8 @@ DFL is a Win32 windowing library for the D language.
|
|||
## Recent major features
|
||||
- **Module "dfl.chart" is now comming.**
|
||||
- TableRenderer (with example)
|
||||
- **LineGraphRenderer (with example)**
|
||||
- ~TimeChartRenderer~
|
||||
- LineGraphRenderer (with example)
|
||||
- **TimeChartRenderer (with example)**
|
||||
- Add simple clock "Dclock" as an example of DFL application.
|
||||
- Module "dfl.printing" is now comming.
|
||||
- PrintDialog
|
||||
|
@ -41,6 +41,7 @@ DFL is a Win32 windowing library for the D language.
|
|||

|
||||

|
||||

|
||||

|
||||
|
||||
## Build and Install (dfl.lib and dfl_debug.lib)
|
||||
### 1. Set environment variables
|
||||
|
|
16
examples/timechartrenderer/.gitignore
vendored
Normal file
16
examples/timechartrenderer/.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
.dub
|
||||
docs.json
|
||||
__dummy.html
|
||||
docs/
|
||||
/hello_dfl
|
||||
hello_dfl.so
|
||||
hello_dfl.dylib
|
||||
hello_dfl.dll
|
||||
hello_dfl.a
|
||||
hello_dfl.lib
|
||||
hello_dfl-test-*
|
||||
*.exe
|
||||
*.pdb
|
||||
*.o
|
||||
*.obj
|
||||
*.lst
|
13
examples/timechartrenderer/.vscode/launch.json
vendored
Normal file
13
examples/timechartrenderer/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C++ Launch (Windows) timechartrenderer",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"program": "./bin/timechartrenderer.exe",
|
||||
"console": "internalConsole"
|
||||
}
|
||||
]
|
||||
}
|
20
examples/timechartrenderer/.vscode/tasks.json
vendored
Normal file
20
examples/timechartrenderer/.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "dub",
|
||||
"run": false,
|
||||
"cwd": ".",
|
||||
"compiler": "$current",
|
||||
"archType": "$current",
|
||||
"buildType": "$current",
|
||||
"configuration": "$current",
|
||||
"problemMatcher": [
|
||||
"$dmd"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "dub: Build timechartrenderer_sample",
|
||||
"detail": "dub build --compiler=dmd.EXE -a=x86_64 -b=debug -c=application"
|
||||
}
|
||||
]
|
||||
}
|
2
examples/timechartrenderer/README.md
Normal file
2
examples/timechartrenderer/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Screen Shot
|
||||

|
16
examples/timechartrenderer/dub.json
Normal file
16
examples/timechartrenderer/dub.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"authors": ["haru-s"],
|
||||
"copyright": "Copyright (C) 2024 haru-s",
|
||||
"description": "DFL sample code.",
|
||||
"name": "timechartrenderer",
|
||||
"targetType": "executable",
|
||||
"targetPath": "bin",
|
||||
"dependencies": {
|
||||
"dfl": {
|
||||
"path": "../../../dfl"
|
||||
}
|
||||
},
|
||||
"lflags-windows-x86_omf-dmd": ["/exet:nt/su:windows:6.0"],
|
||||
"lflags-windows-x86_mscoff-dmd": ["/SUBSYSTEM:WINDOWS", "/ENTRY:mainCRTStartup"],
|
||||
"lflags-windows-x86_64-dmd": ["/SUBSYSTEM:WINDOWS", "/ENTRY:mainCRTStartup"]
|
||||
}
|
BIN
examples/timechartrenderer/image/screenshot.png
Normal file
BIN
examples/timechartrenderer/image/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
3
examples/timechartrenderer/shell.bat
Normal file
3
examples/timechartrenderer/shell.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
set dmd_path=c:\d\dmd2\windows
|
||||
set dmc_path=c:\dmc\dm
|
||||
cmd
|
89
examples/timechartrenderer/source/timechartrenderer_sample.d
Normal file
89
examples/timechartrenderer/source/timechartrenderer_sample.d
Normal file
|
@ -0,0 +1,89 @@
|
|||
import dfl;
|
||||
|
||||
version(Have_dfl) // For DUB.
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
pragma(lib, "dfl.lib");
|
||||
}
|
||||
|
||||
class MainForm : Form
|
||||
{
|
||||
alias CustomTimeChartRenderer = TimeChartRenderer!(int,int,int,int,int,int,int,int,int);
|
||||
CustomTimeChartRenderer _graph;
|
||||
|
||||
alias CustomTableRenderer = TableRenderer!(int,int,int,int,int,int,int,int,int);
|
||||
CustomTableRenderer _table;
|
||||
|
||||
public this()
|
||||
{
|
||||
this.text = "TimeChartRenderer example";
|
||||
this.size = Size(600, 650);
|
||||
|
||||
string csv =
|
||||
"Time (ms),D1,D2,D3,D4,A1,A2,A3,A4\n" ~
|
||||
"0,0,0,0,0,0,0,0,0\n" ~
|
||||
"100,1,0,0,0,5,2,10,2\n" ~
|
||||
"200,0,1,0,0,6,3,10,-3\n" ~
|
||||
"300,1,1,1,0,7,4,9,4\n" ~
|
||||
"400,0,0,1,1,8,5,9,-5\n" ~
|
||||
"500,1,0,1,1,9,2,8,6\n" ~
|
||||
"600,0,0,0,1,8,3,8,-7\n" ~
|
||||
"700,1,1,0,1,7,4,7,8\n" ~
|
||||
"800,0,1,0,0,6,5,7,-9\n" ~
|
||||
"900,1,0,1,0,5,2,6,10\n" ~
|
||||
"1000,0,0,1,0,4,3,6,-10\n" ~
|
||||
"1100,1,1,1,0,3,4,5,9\n" ~
|
||||
"1200,0,1,0,1,2,5,5,-9\n" ~
|
||||
"1300,1,0,0,1,1,2,4,8\n" ~
|
||||
"1400,0,0,0,1,0,3,4,-8\n";
|
||||
_graph = new CustomTimeChartRenderer(csv, 15);
|
||||
_graph.location = Point(50, 50);
|
||||
_graph.chartMargins = ChartMargins(50, 50, 50, 50);
|
||||
_graph.seriesStyleList[0..4] = TimeChartSeriesStyle(true, Color.blue, 20); // Digital
|
||||
_graph.seriesStyleList[4..7] = TimeChartSeriesStyle(false, Color.red, 50, 0, 10); // Analog
|
||||
_graph.seriesStyleList[7] = TimeChartSeriesStyle(false, Color.red, 100, -10, 20,); // Analog
|
||||
_graph.plotAreaTopPadding = 20;
|
||||
_graph.plotAreaBottomPadding = 20;
|
||||
_graph.plotAreaLeftPadding = 20;
|
||||
_graph.plotAreaRightPadding = 20;
|
||||
_graph.plotAreaBoundsColor = Color.black;
|
||||
_graph.plotAreaAndHorizontalScaleSpanY = 10;
|
||||
_graph.hasHorizontalScale = true;
|
||||
_graph.horizontalScaleSpan = 20;
|
||||
_graph.horizontalScaleStep = 2;
|
||||
_graph.horizontalScaleLineInnerSide = 5;
|
||||
_graph.horizontalScaleLineOuterSide = 5;
|
||||
_graph.horizontalScaleHeight = 20;
|
||||
_graph.hasVerticalScale = true;
|
||||
_graph.verticalScaleWidth = 40;
|
||||
_graph.hasZeroLine = true;
|
||||
_graph.backColor = Color.white;
|
||||
|
||||
_table = new CustomTableRenderer(csv, 10);
|
||||
_table.location = Point(50, 500);
|
||||
_table.hasHeader = true;
|
||||
_table.showHeader = true;
|
||||
_table.headerLine = true;
|
||||
_table.width[] = 50;
|
||||
}
|
||||
|
||||
protected override void onPaint(PaintEventArgs e)
|
||||
{
|
||||
if (_graph)
|
||||
_graph.draw(e.graphics);
|
||||
// if (_table)
|
||||
// _table.draw(e.graphics);
|
||||
}
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
Application.enableVisualStyles();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
Application.run(new MainForm());
|
||||
}
|
12
examples/timechartrenderer/timechartrenderer.code-workspace
Normal file
12
examples/timechartrenderer/timechartrenderer.code-workspace
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"d.projectImportPaths": [
|
||||
"..\\..\\..\\dfl\\source"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -960,4 +960,512 @@ enum PlotPointForm
|
|||
RECTANGLE,
|
||||
CROSS,
|
||||
TRIANGLE,
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
class TimeChartRenderer(T...)
|
||||
{
|
||||
///
|
||||
this(string csv, int numRecords)
|
||||
{
|
||||
this(csv);
|
||||
_firstRecord = 0;
|
||||
_lastRecord = numRecords - 1;
|
||||
}
|
||||
/// ditto
|
||||
this(string csv, int first, int last)
|
||||
{
|
||||
this(csv);
|
||||
_firstRecord = first;
|
||||
_lastRecord = last;
|
||||
}
|
||||
/// ditto
|
||||
this(string csv) // deprecated
|
||||
{
|
||||
_csv = csv;
|
||||
_chartMargins = ChartMargins(50, 50, 50, 50);
|
||||
_backColor = Color.white;
|
||||
_plotAreaBoundsColor = Color.black;
|
||||
_plotAreaTopPadding = 20;
|
||||
_plotAreaBottomPadding = 20;
|
||||
_plotAreaLeftPadding = 20;
|
||||
_plotAreaRightPadding = 20;
|
||||
_plotAreaAndHorizontalScaleSpanY = 10;
|
||||
_hasVerticalScale = true;
|
||||
_verticalScaleWidth = 40;
|
||||
_hasHorizontalScale = true;
|
||||
_horizontalScaleSpan = 50;
|
||||
_horizontalScaleStep = 1;
|
||||
_horizontalScaleLineInnerSide = 5;
|
||||
_horizontalScaleLineOuterSide = 5;
|
||||
_horizontalScaleHeight = 25;
|
||||
_hasZeroLine = true;
|
||||
for (int i; i < cast(int)T.length - 1; i++)
|
||||
_seriesStyleList ~= TimeChartSeriesStyle(false);
|
||||
}
|
||||
|
||||
/// Draw records.
|
||||
void draw(Graphics g)
|
||||
{
|
||||
string hSubject = csvReader!(Tuple!T)(_csv, null).header.front;
|
||||
|
||||
enum HORIZONTAL_SCALE_AREA_AND_SUBJECT_SPAN_Y = 25; // TODO: fix.
|
||||
enum HORIZONTAL_SCALE_TEXT_HEIGHT = 12; // TODO: fix.
|
||||
|
||||
// Draw background.
|
||||
Rect backgroundRect = Rect(
|
||||
plotAreaBounds.x - _chartMargins.left,
|
||||
plotAreaBounds.y - _chartMargins.top,
|
||||
plotAreaBounds.width + _chartMargins.left + _chartMargins.right,
|
||||
plotAreaBounds.height + _chartMargins.top + _chartMargins.bottom
|
||||
);
|
||||
if (_hasVerticalScale)
|
||||
{
|
||||
backgroundRect.x = plotAreaBounds.x - _chartMargins.left - _verticalScaleWidth,
|
||||
backgroundRect.width = plotAreaBounds.width + _chartMargins.left + _chartMargins.right + _verticalScaleWidth;
|
||||
}
|
||||
if (_hasHorizontalScale)
|
||||
{
|
||||
backgroundRect.height += _horizontalScaleHeight + _plotAreaAndHorizontalScaleSpanY;
|
||||
if (hSubject != "")
|
||||
backgroundRect.height += HORIZONTAL_SCALE_AREA_AND_SUBJECT_SPAN_Y + HORIZONTAL_SCALE_TEXT_HEIGHT;
|
||||
}
|
||||
g.fillRectangle(new SolidBrush(_backColor), backgroundRect);
|
||||
// Draw bounds of plot area.
|
||||
g.drawRectangle(new Pen(_plotAreaBoundsColor), plotAreaBounds);
|
||||
// Draw vertical scale.
|
||||
if (_hasVerticalScale)
|
||||
{
|
||||
enum LINE_HEIGHT = 12f;
|
||||
Font f = new Font("MS Gothic", LINE_HEIGHT);
|
||||
int x = plotAreaBounds.x - _verticalScaleWidth;
|
||||
int seriesIndex;
|
||||
foreach (seriesName; csvReader!(Tuple!T)(_csv, null).header.dropOne)
|
||||
{
|
||||
// Draw vertical scalse label.
|
||||
enum VERTICAL_SCALE_LABEL_TWEAK = 5;
|
||||
int y = _seriesBaseY(seriesIndex) - cast(int)LINE_HEIGHT - VERTICAL_SCALE_LABEL_TWEAK;
|
||||
int currHeight = _seriesStyleList[cast(int)seriesIndex].height;
|
||||
g.drawText(seriesName, f, Color.black, Rect(x, y, 100, 100));
|
||||
// Draw analog scales.
|
||||
if (!_seriesStyleList[seriesIndex].isDigital)
|
||||
{
|
||||
enum TWEAK_X = 2;
|
||||
int maxValue = _seriesStyleList[cast(int)seriesIndex].max;
|
||||
string maxText = to!string(maxValue);
|
||||
g.drawText(
|
||||
maxText,
|
||||
f,
|
||||
Color.black,
|
||||
Rect(plotAreaBounds.x + TWEAK_X, _seriesBaseY(seriesIndex) - currHeight, 100, 100)
|
||||
);
|
||||
int minValue = _seriesStyleList[cast(int)seriesIndex].min;
|
||||
string minText = to!string(minValue);
|
||||
g.drawText(
|
||||
minText,
|
||||
f,
|
||||
Color.black,
|
||||
Rect(plotAreaBounds.x + TWEAK_X, y, 100, 100)
|
||||
);
|
||||
// Draw zero line and scale label.
|
||||
if (_hasZeroLine && minValue < 0)
|
||||
{
|
||||
g.drawLine(
|
||||
new Pen(Color.lightGray),
|
||||
plotAreaBounds.x,
|
||||
_seriesZeroY(seriesIndex),
|
||||
plotAreaBounds.right - 1,
|
||||
_seriesZeroY(seriesIndex),
|
||||
);
|
||||
g.drawText(
|
||||
"0",
|
||||
f,
|
||||
Color.black,
|
||||
Rect(plotAreaBounds.x + TWEAK_X, _seriesZeroY(seriesIndex) - cast(int)LINE_HEIGHT - VERTICAL_SCALE_LABEL_TWEAK, 100, 100)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Draw vertical scalse line.
|
||||
g.drawLine(
|
||||
new Pen(Color.lightGray),
|
||||
x,
|
||||
_seriesBaseY(seriesIndex),
|
||||
x + _verticalScaleWidth,
|
||||
_seriesBaseY(seriesIndex)
|
||||
);
|
||||
// Draw vertical zero line in plot area.
|
||||
if (_hasZeroLine)
|
||||
{
|
||||
g.drawLine(
|
||||
new Pen(Color.lightGray),
|
||||
x + _verticalScaleWidth,
|
||||
_seriesBaseY(seriesIndex),
|
||||
plotAreaBounds.right - 1,
|
||||
_seriesBaseY(seriesIndex)
|
||||
);
|
||||
}
|
||||
seriesIndex++;
|
||||
}
|
||||
}
|
||||
// Draw horizontal scale.
|
||||
if (_hasHorizontalScale)
|
||||
{
|
||||
// Draw horizontal scale label.
|
||||
int index;
|
||||
foreach (record; csvReader!(Tuple!T)(_csv, null).drop(_firstRecord).take(_lastRecord - _firstRecord + 1).stride(_horizontalScaleStep))
|
||||
{
|
||||
int x = plotAreaBounds.x + _plotAreaLeftPadding + index * _horizontalScaleSpan;
|
||||
int y = plotAreaBounds.bottom + _plotAreaAndHorizontalScaleSpanY;
|
||||
g.drawText(
|
||||
to!string(record[0]),
|
||||
new Font("MS Gothic", 12f),
|
||||
_plotAreaBoundsColor,
|
||||
Rect(x, y, _horizontalScaleSpan * _horizontalScaleStep, _horizontalScaleHeight)
|
||||
);
|
||||
index += _horizontalScaleStep;
|
||||
}
|
||||
// Draw horizontal scale line.
|
||||
for (int i; i < _lastRecord - _firstRecord + 1; i += _horizontalScaleStep)
|
||||
{
|
||||
int x = plotAreaBounds.x + _plotAreaLeftPadding + i * _horizontalScaleSpan;
|
||||
int y = plotAreaBounds.bottom;
|
||||
g.drawLine(
|
||||
new Pen(_plotAreaBoundsColor),
|
||||
x,
|
||||
y - _horizontalScaleLineInnerSide,
|
||||
x,
|
||||
y + _horizontalScaleLineOuterSide
|
||||
);
|
||||
}
|
||||
// Draw horizontal scale subject.
|
||||
{
|
||||
int x = plotAreaBounds.x;
|
||||
int y = plotAreaBounds.bottom + _horizontalScaleHeight + HORIZONTAL_SCALE_AREA_AND_SUBJECT_SPAN_Y;
|
||||
auto fmt = new TextFormat;
|
||||
fmt.alignment = TextAlignment.CENTER;
|
||||
g.drawText(
|
||||
hSubject,
|
||||
new Font("MS Gothic", 12f),
|
||||
_plotAreaBoundsColor,
|
||||
Rect(x, y, plotAreaBounds.width, HORIZONTAL_SCALE_TEXT_HEIGHT * 2),
|
||||
fmt
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw records.
|
||||
Tuple!T prevRecord;
|
||||
int x1 = plotAreaBounds.x + _plotAreaLeftPadding;
|
||||
int x2;
|
||||
bool isFirstRecord = true;
|
||||
auto csvRange = csvReader!(Tuple!T)(_csv, null).drop(_firstRecord).take(_lastRecord - _firstRecord + 1);
|
||||
foreach (currRecord; csvRange)
|
||||
{
|
||||
x2 = x1 + _horizontalScaleSpan;
|
||||
bool isFirstColumn = true;
|
||||
foreach (col, value; currRecord)
|
||||
{
|
||||
if (col != 0)
|
||||
{
|
||||
int seriesIndex = cast(int)col - 1;
|
||||
if (!isFirstRecord)
|
||||
{
|
||||
bool isDigital = _seriesStyleList[seriesIndex].isDigital;
|
||||
int currHeight = _seriesStyleList[seriesIndex].height;
|
||||
Color lineColor = _seriesStyleList[seriesIndex].color;
|
||||
if (isDigital)
|
||||
{ // Digital signal
|
||||
enum MODEST_HEIGHT_RATIO = 0.8;
|
||||
int toDigit(int v) { return v == 0 ? 0 : 1; }
|
||||
int y1 = cast(int)(_seriesBaseY(seriesIndex) - currHeight * toDigit(prevRecord[col]) * MODEST_HEIGHT_RATIO);
|
||||
int y2 = cast(int)(_seriesBaseY(seriesIndex) - currHeight * toDigit(value) * MODEST_HEIGHT_RATIO);
|
||||
g.drawLine(
|
||||
new Pen(lineColor),
|
||||
x1 - _horizontalScaleSpan,
|
||||
y1,
|
||||
x2 - _horizontalScaleSpan,
|
||||
y1
|
||||
);
|
||||
g.drawLine(
|
||||
new Pen(lineColor),
|
||||
x2 - _horizontalScaleSpan,
|
||||
y1,
|
||||
x2 - _horizontalScaleSpan,
|
||||
y2
|
||||
);
|
||||
}
|
||||
else
|
||||
{ // Analog signal
|
||||
double vRatio = cast(double)currHeight / (_seriesStyleList[seriesIndex].max - _seriesStyleList[seriesIndex].min);
|
||||
int y1 = cast(int)(_seriesBaseY(seriesIndex) - vRatio * prevRecord[col]);
|
||||
int y2 = cast(int)(_seriesBaseY(seriesIndex) - vRatio * value);
|
||||
// Offset the base line of zero point.
|
||||
if (_seriesStyleList[seriesIndex].min < 0)
|
||||
{
|
||||
y1 -= _seriesBaseY(seriesIndex) - _seriesZeroY(seriesIndex);
|
||||
y2 -= _seriesBaseY(seriesIndex) - _seriesZeroY(seriesIndex);
|
||||
}
|
||||
g.drawLine(
|
||||
new Pen(lineColor),
|
||||
x1 - _horizontalScaleSpan,
|
||||
y1,
|
||||
x2 - _horizontalScaleSpan,
|
||||
y2
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
isFirstColumn = false;
|
||||
}
|
||||
x1 = x1 + _horizontalScaleSpan;
|
||||
prevRecord = currRecord;
|
||||
isFirstRecord = false;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
Rect plotAreaBounds() const
|
||||
{
|
||||
return Rect(
|
||||
_originPoint.x,
|
||||
_originPoint.y,
|
||||
cast(int)((_lastRecord - _firstRecord) * _horizontalScaleSpan + _plotAreaLeftPadding + _plotAreaRightPadding),
|
||||
_plotAreaTopPadding + _verticalSeriesOffset(cast(int)T.length - 2) + _plotAreaBottomPadding
|
||||
);
|
||||
}
|
||||
|
||||
///
|
||||
deprecated void originPoint(Point pt)
|
||||
{
|
||||
_originPoint = pt;
|
||||
}
|
||||
///
|
||||
void location(Point pt)
|
||||
{
|
||||
_originPoint.x = pt.x + _chartMargins.top + _verticalScaleWidth;
|
||||
_originPoint.y = pt.y + _chartMargins.left;
|
||||
}
|
||||
|
||||
///
|
||||
void chartMargins(ChartMargins m)
|
||||
{
|
||||
_chartMargins = m;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaAndHorizontalScaleSpanY(int y)
|
||||
{
|
||||
_plotAreaAndHorizontalScaleSpanY = y;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaTopPadding(int y)
|
||||
{
|
||||
_plotAreaTopPadding = y;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaBottomPadding(int y)
|
||||
{
|
||||
_plotAreaBottomPadding = y;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaRightPadding(int x)
|
||||
{
|
||||
_plotAreaRightPadding = x;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaLeftPadding(int x)
|
||||
{
|
||||
_plotAreaLeftPadding = x;
|
||||
}
|
||||
|
||||
///
|
||||
void hasHorizontalScale(bool byes)
|
||||
{
|
||||
_hasHorizontalScale = byes;
|
||||
}
|
||||
|
||||
///
|
||||
void hasVerticalScale(bool byes)
|
||||
{
|
||||
_hasVerticalScale = byes;
|
||||
}
|
||||
|
||||
///
|
||||
void hasZeroLine(bool byes)
|
||||
{
|
||||
_hasZeroLine = byes;
|
||||
}
|
||||
|
||||
///
|
||||
void firstRecord(int i)
|
||||
{
|
||||
_firstRecord = i;
|
||||
}
|
||||
|
||||
///
|
||||
void lastRecord(int i)
|
||||
{
|
||||
_lastRecord = i;
|
||||
}
|
||||
|
||||
///
|
||||
void backColor(Color c)
|
||||
{
|
||||
_backColor = c;
|
||||
}
|
||||
|
||||
///
|
||||
void plotAreaBoundsColor(Color c)
|
||||
{
|
||||
_plotAreaBoundsColor = c;
|
||||
}
|
||||
|
||||
///
|
||||
void horizontalScaleSpan(int x)
|
||||
{
|
||||
_horizontalScaleSpan = x;
|
||||
}
|
||||
|
||||
///
|
||||
void horizontalScaleStep(int s)
|
||||
{
|
||||
if (s <= 0)
|
||||
throw new DflException("DFL: Invalid horizontal scale step.");
|
||||
_horizontalScaleStep = s;
|
||||
}
|
||||
|
||||
///
|
||||
void verticalScaleWidth(int w)
|
||||
{
|
||||
_verticalScaleWidth = w;
|
||||
}
|
||||
|
||||
///
|
||||
void horizontalScaleLineInnerSide(int h)
|
||||
{
|
||||
_horizontalScaleLineInnerSide = h;
|
||||
}
|
||||
|
||||
///
|
||||
void horizontalScaleLineOuterSide(int h)
|
||||
{
|
||||
_horizontalScaleLineOuterSide = h;
|
||||
}
|
||||
|
||||
///
|
||||
void horizontalScaleHeight(int h)
|
||||
{
|
||||
_horizontalScaleHeight = h;
|
||||
}
|
||||
|
||||
///
|
||||
struct TimeChartSeriesStyleObject // Internal struct.
|
||||
{
|
||||
///
|
||||
this(TimeChartSeriesStyle[] v)
|
||||
{
|
||||
_arr = v;
|
||||
}
|
||||
|
||||
/// Assign operator forwarding.
|
||||
void opIndexAssign(TimeChartSeriesStyle value)
|
||||
{
|
||||
_arr[] = value;
|
||||
}
|
||||
/// ditto
|
||||
void opIndexAssign(TimeChartSeriesStyle value, size_t i)
|
||||
{
|
||||
_arr[i] = value;
|
||||
}
|
||||
/// ditto
|
||||
void opSliceAssign(TimeChartSeriesStyle value, size_t i, size_t j)
|
||||
{
|
||||
_arr[i..j] = value;
|
||||
}
|
||||
|
||||
///
|
||||
TimeChartSeriesStyle opIndex(size_t i)
|
||||
{
|
||||
return _arr[i];
|
||||
}
|
||||
|
||||
private:
|
||||
TimeChartSeriesStyle[] _arr;
|
||||
}
|
||||
|
||||
///
|
||||
TimeChartSeriesStyleObject seriesStyleList()
|
||||
{
|
||||
return TimeChartSeriesStyleObject(_seriesStyleList);
|
||||
}
|
||||
|
||||
private:
|
||||
string _csv;
|
||||
int _firstRecord;
|
||||
int _lastRecord;
|
||||
Point _originPoint;
|
||||
ChartMargins _chartMargins;
|
||||
Color _backColor;
|
||||
Color _plotAreaBoundsColor;
|
||||
int _plotAreaTopPadding;
|
||||
int _plotAreaBottomPadding;
|
||||
int _plotAreaLeftPadding;
|
||||
int _plotAreaRightPadding;
|
||||
int _plotAreaAndHorizontalScaleSpanY;
|
||||
bool _hasHorizontalScale;
|
||||
int _horizontalScaleSpan;
|
||||
int _horizontalScaleStep;
|
||||
int _horizontalScaleHeight;
|
||||
int _horizontalScaleLineInnerSide;
|
||||
int _horizontalScaleLineOuterSide;
|
||||
bool _hasVerticalScale;
|
||||
int _verticalScaleWidth;
|
||||
bool _hasZeroLine;
|
||||
TimeChartSeriesStyle[] _seriesStyleList;
|
||||
|
||||
///
|
||||
int _verticalSeriesOffset(int seriesIndex) const
|
||||
{
|
||||
int y;
|
||||
for (int i; i <= seriesIndex; i++)
|
||||
y += _seriesStyleList[i].height;
|
||||
return y;
|
||||
}
|
||||
|
||||
///
|
||||
int _seriesBaseY(int seriesIndex) const
|
||||
{
|
||||
return plotAreaBounds.y + _plotAreaTopPadding + _verticalSeriesOffset(seriesIndex);
|
||||
}
|
||||
|
||||
///
|
||||
int _seriesZeroY(int seriesIndex)
|
||||
{
|
||||
int currHeight = _seriesStyleList[cast(int)seriesIndex].height;
|
||||
int maxValue = _seriesStyleList[cast(int)seriesIndex].max;
|
||||
int minValue = _seriesStyleList[cast(int)seriesIndex].min;
|
||||
return cast(int)(_seriesBaseY(seriesIndex) + cast(double)minValue * currHeight / (maxValue - minValue));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
struct TimeChartSeriesStyle
|
||||
{
|
||||
this(bool inIsDigital, Color inColor = Color.blue, int inHeight = 20, int inMin = 0, int inMax = 1)
|
||||
{
|
||||
isDigital = inIsDigital;
|
||||
color = inColor;
|
||||
height = inHeight;
|
||||
min = inMin;
|
||||
max = inMax;
|
||||
}
|
||||
bool isDigital;
|
||||
Color color;
|
||||
int height;
|
||||
int min;
|
||||
int max;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue