mirror of
https://github.com/Rayerd/dfl.git
synced 2025-04-26 21:30:25 +03:00
Add dfl.chart.LineGraphRenderer
Update TableRenderer
This commit is contained in:
parent
d2e832ec54
commit
262711208a
13 changed files with 829 additions and 36 deletions
|
@ -5,10 +5,10 @@ DFL is a Win32 windowing library for the D language.
|
||||||
|
|
||||||
## Recent major features
|
## Recent major features
|
||||||
- **Module "dfl.chart" is now comming.**
|
- **Module "dfl.chart" is now comming.**
|
||||||
- **TableRenderer (with example)**
|
- TableRenderer (with example)
|
||||||
- ~LineGraphRenderer~
|
- **LineGraphRenderer (with example)**
|
||||||
- ~TimeChartRenderer~
|
- ~TimeChartRenderer~
|
||||||
- **Add simple clock "Dclock" as an example of DFL application.**
|
- Add simple clock "Dclock" as an example of DFL application.
|
||||||
- Module "dfl.printing" is now comming.
|
- Module "dfl.printing" is now comming.
|
||||||
- PrintDialog
|
- PrintDialog
|
||||||
- PrintSetupDialog
|
- PrintSetupDialog
|
||||||
|
@ -40,6 +40,7 @@ DFL is a Win32 windowing library for the D language.
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## Build and Install (dfl.lib and dfl_debug.lib)
|
## Build and Install (dfl.lib and dfl_debug.lib)
|
||||||
### 1. Set environment variables
|
### 1. Set environment variables
|
||||||
|
|
16
examples/linegraphrenderer/.gitignore
vendored
Normal file
16
examples/linegraphrenderer/.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/linegraphrenderer/.vscode/launch.json
vendored
Normal file
13
examples/linegraphrenderer/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "C++ Launch (Windows) linegraphrenderer",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"program": "./bin/linegraphrenderer.exe",
|
||||||
|
"console": "internalConsole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
20
examples/linegraphrenderer/.vscode/tasks.json
vendored
Normal file
20
examples/linegraphrenderer/.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 linegraphrenderer_sample",
|
||||||
|
"detail": "dub build --compiler=dmd.EXE -a=x86_64 -b=debug -c=application"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
2
examples/linegraphrenderer/README.md
Normal file
2
examples/linegraphrenderer/README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Screen Shot
|
||||||
|

|
16
examples/linegraphrenderer/dub.json
Normal file
16
examples/linegraphrenderer/dub.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"authors": ["haru-s"],
|
||||||
|
"copyright": "Copyright (C) 2024 haru-s",
|
||||||
|
"description": "DFL sample code.",
|
||||||
|
"name": "linegraphrenderer",
|
||||||
|
"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/linegraphrenderer/image/screenshot.png
Normal file
BIN
examples/linegraphrenderer/image/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 123 KiB |
12
examples/linegraphrenderer/linegraphrenderer.code-workspace
Normal file
12
examples/linegraphrenderer/linegraphrenderer.code-workspace
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"d.projectImportPaths": [
|
||||||
|
"..\\..\\..\\dfl\\source"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
3
examples/linegraphrenderer/shell.bat
Normal file
3
examples/linegraphrenderer/shell.bat
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
set dmd_path=c:\d\dmd2\windows
|
||||||
|
set dmc_path=c:\dmc\dm
|
||||||
|
cmd
|
111
examples/linegraphrenderer/source/linegraphrenderer_sample.d
Normal file
111
examples/linegraphrenderer/source/linegraphrenderer_sample.d
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import dfl;
|
||||||
|
|
||||||
|
version(Have_dfl) // For DUB.
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pragma(lib, "dfl.lib");
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainForm : Form
|
||||||
|
{
|
||||||
|
alias CustomLineGraphRenderer = LineGraphRenderer!(string,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int);
|
||||||
|
CustomLineGraphRenderer _graph;
|
||||||
|
|
||||||
|
alias CustomLineGraphRenderer2 = LineGraphRenderer!(int,int,int);
|
||||||
|
CustomLineGraphRenderer2 _graph2;
|
||||||
|
|
||||||
|
// alias CustomTableRenderer = TableRenderer!(string,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int);
|
||||||
|
// CustomTableRenderer _table;
|
||||||
|
|
||||||
|
// alias CustomTableRenderer2 = TableRenderer!(int,int,int);
|
||||||
|
// CustomTableRenderer2 _table2;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this.text = "LineGraphRenderer example";
|
||||||
|
this.size = Size(1000, 800);
|
||||||
|
string csv =
|
||||||
|
"教科,山田,佐藤,井上,田中,木下,藤原,山本,大森,伊藤,高橋,鈴木,中村,小林,松井,木村,近藤\n" ~
|
||||||
|
"国語,70,80,80,75,68,65,55,48,45,38,35,25,20,10,5,1\n" ~
|
||||||
|
"算数,60,90,80,75,68,65,55,48,45,38,35,25,20,10,5,1\n" ~
|
||||||
|
"理科,80,70,80,75,68,65,55,48,45,38,35,25,20,10,5,1\n" ~
|
||||||
|
"社会,90,60,80,75,68,65,55,48,45,38,35,25,20,10,5,1\n";
|
||||||
|
_graph = new CustomLineGraphRenderer(csv, 4);
|
||||||
|
_graph.showLegend = true;
|
||||||
|
_graph.legendLineHeight = 18;
|
||||||
|
_graph.chartMargins = ChartMargins(50, 50, 50, 50);
|
||||||
|
_graph.plotPointSize = 10;
|
||||||
|
_graph.verticalZeroPosition = VerticalZeroPosition.BOTTOM;
|
||||||
|
_graph.plotAreaAndLegendSpanX = 50;
|
||||||
|
_graph.plotAreaAndHorizontalScaleSpanY = 10;
|
||||||
|
_graph.plotAreaLeftPadding = 20;
|
||||||
|
_graph.plotAreaRightPadding = 20;
|
||||||
|
_graph.plotAreaHeightOnDisplay = 300;
|
||||||
|
_graph.hasHorizontalScale = true;
|
||||||
|
_graph.horizontalScaleSpan = 100;
|
||||||
|
_graph.horizonScaleLineInnerSide = 0;
|
||||||
|
_graph.horizonScaleLineOuterSide = 5;
|
||||||
|
_graph.horizontalScaleHeight = 12;
|
||||||
|
_graph.hasVerticalScale = true;
|
||||||
|
_graph.verticalMaxScale = 110;
|
||||||
|
_graph.verticalScaleLineOuterSide = 5;
|
||||||
|
_graph.verticalScaleLineInnerSide = 0;
|
||||||
|
_graph.verticalScaleSpan = 20;
|
||||||
|
_graph.verticalScaleWidth = 40;
|
||||||
|
_graph.backColor = Color.white;
|
||||||
|
_graph.plotAreaBoundsColor = Color.black;
|
||||||
|
_graph.plotLineColorPalette[0] = Color.black;
|
||||||
|
_graph.plotPointFormList[4..8] = PlotPointForm.CROSS;
|
||||||
|
_graph.plotPointFormList[8..12] = PlotPointForm.RECTANGLE;
|
||||||
|
_graph.plotPointFormList[12..16] = PlotPointForm.TRIANGLE;
|
||||||
|
_graph.relocate = Point(50, 50); // Relocate origin point based on top-left margins.
|
||||||
|
|
||||||
|
string csv2 =
|
||||||
|
"A,B,C\n" ~
|
||||||
|
"70,80,80\n" ~
|
||||||
|
"60,90,80\n" ~
|
||||||
|
"80,70,80\n" ~
|
||||||
|
"90,60,80\n";
|
||||||
|
_graph2 = new CustomLineGraphRenderer2(csv2, 4);
|
||||||
|
_graph2.chartMargins = ChartMargins(10, 10, 10, 10);
|
||||||
|
_graph2.relocate = Point(600, 50);
|
||||||
|
|
||||||
|
// _table = new CustomTableRenderer(csv, 4);
|
||||||
|
// _table.location = Point(50, 500);
|
||||||
|
// _table.hasHeader = true;
|
||||||
|
// _table.showHeader = true;
|
||||||
|
// _table.headerLine = true;
|
||||||
|
// _table.width[] = 40;
|
||||||
|
|
||||||
|
// _table2 = new CustomTableRenderer2(csv2, 4);
|
||||||
|
// _table2.hasHeader = true;
|
||||||
|
// _table2.showHeader = true;
|
||||||
|
// _table2.headerLine = true;
|
||||||
|
// _table2.width[] = 40;
|
||||||
|
// _table2.location = Point(680, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void onPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
if (_graph)
|
||||||
|
_graph.draw(e.graphics);
|
||||||
|
if (_graph2)
|
||||||
|
_graph2.draw(e.graphics);
|
||||||
|
// if (_table)
|
||||||
|
// _table.draw(e.graphics);
|
||||||
|
// if (_table2)
|
||||||
|
// _table2.draw(e.graphics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
Application.enableVisualStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Application.run(new MainForm());
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 16 KiB |
|
@ -10,7 +10,7 @@ else
|
||||||
|
|
||||||
class MainForm : Form
|
class MainForm : Form
|
||||||
{
|
{
|
||||||
alias CustomTableRenderer = TableRenderer!(string, string, string);
|
alias CustomTableRenderer = TableRenderer!(string, int, int);
|
||||||
CustomTableRenderer _table;
|
CustomTableRenderer _table;
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
|
@ -18,19 +18,17 @@ class MainForm : Form
|
||||||
this.text = "TableRenderer example";
|
this.text = "TableRenderer example";
|
||||||
this.size = Size(450, 450);
|
this.size = Size(450, 450);
|
||||||
string csv =
|
string csv =
|
||||||
"ID,Name,Value\n" ~
|
"教科,大森,山田\n" ~
|
||||||
"1,Kyoto,100\n" ~
|
"国語,95,98\n" ~
|
||||||
"2,Osaka,50\n" ~
|
"理科,75,80\n" ~
|
||||||
"3,Tokyo,20\n" ~
|
"算数,90,78\n" ~
|
||||||
"4,Aomori,10\n";
|
"社会,80,76\n";
|
||||||
_table = new CustomTableRenderer(csv);
|
_table = new CustomTableRenderer(csv);
|
||||||
_table.height = 40;
|
_table.height = 40;
|
||||||
_table.width[0] = 50;
|
_table.width[] = 80;
|
||||||
_table.width[1] = 80;
|
|
||||||
_table.width[2] = 150;
|
|
||||||
_table.paddingX = 10;
|
_table.paddingX = 10;
|
||||||
_table.paddingY = 12;
|
_table.paddingY = 12;
|
||||||
_table.margin = Point(20, 20);
|
_table.location = Point(20, 20);
|
||||||
_table.hasHeader = true; // true : 1st line is header.
|
_table.hasHeader = true; // true : 1st line is header.
|
||||||
_table.showHeader = true;
|
_table.showHeader = true;
|
||||||
_table.firstRecord = 0;
|
_table.firstRecord = 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@ private import std.csv;
|
||||||
private import std.typecons;
|
private import std.typecons;
|
||||||
private import std.conv;
|
private import std.conv;
|
||||||
private import std.algorithm;
|
private import std.algorithm;
|
||||||
|
private import std.range;
|
||||||
|
|
||||||
///
|
///
|
||||||
class TableRenderer(T...)
|
class TableRenderer(T...)
|
||||||
|
@ -22,7 +23,14 @@ class TableRenderer(T...)
|
||||||
enum DEFAULT_PADDING_Y = 5; ///
|
enum DEFAULT_PADDING_Y = 5; ///
|
||||||
|
|
||||||
///
|
///
|
||||||
this(string csv)
|
this(string csv, int numRecords)
|
||||||
|
{
|
||||||
|
this(csv);
|
||||||
|
_firstRecord = 0;
|
||||||
|
_lastRecord = numRecords - 1;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
this(string csv) // deprecated
|
||||||
{
|
{
|
||||||
_csv = csv;
|
_csv = csv;
|
||||||
_columns = T.length;
|
_columns = T.length;
|
||||||
|
@ -47,10 +55,10 @@ class TableRenderer(T...)
|
||||||
g.fillRectangle(new SolidBrush(_backColor), bounds);
|
g.fillRectangle(new SolidBrush(_backColor), bounds);
|
||||||
// Draw top side line.
|
// Draw top side line.
|
||||||
if (_topSideLine)
|
if (_topSideLine)
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x, margin.y), Point(bounds.right, margin.y));
|
g.drawLine(new Pen(_lineColor), Point(location.x, location.y), Point(bounds.right, location.y));
|
||||||
// Draw header line.
|
// Draw header line.
|
||||||
if (_showHeader && _hasHeader && _headerLine)
|
if (_showHeader && _hasHeader && _headerLine)
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x, margin.y + height), Point(bounds.right, margin.y + height));
|
g.drawLine(new Pen(_lineColor), Point(location.x, location.y + height), Point(bounds.right, location.y + height));
|
||||||
// Draw header.
|
// Draw header.
|
||||||
int row; // -row- is line number in CSV.
|
int row; // -row- is line number in CSV.
|
||||||
int viewLine; // -viewLine- is line number on display.
|
int viewLine; // -viewLine- is line number on display.
|
||||||
|
@ -58,10 +66,10 @@ class TableRenderer(T...)
|
||||||
{
|
{
|
||||||
if (_showHeader)
|
if (_showHeader)
|
||||||
{
|
{
|
||||||
int y = margin.y + viewLine * height + _paddingY;
|
int y = location.y + viewLine * height + _paddingY;
|
||||||
foreach (col, value; csvReader!(Tuple!T)(_csv, null).header)
|
foreach (col, value; csvReader!(Tuple!T)(_csv, null).header)
|
||||||
{
|
{
|
||||||
int x = margin.x + sum(_width[0..col]) + _paddingX;
|
int x = location.x + sum(_width[0..col]) + _paddingX;
|
||||||
g.drawText(to!string(value), _headerFont, _textColor, Rect(x, y, _width[col] - _paddingX, _height - _paddingY), _headerTextFormat);
|
g.drawText(to!string(value), _headerFont, _textColor, Rect(x, y, _width[col] - _paddingX, _height - _paddingY), _headerTextFormat);
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
|
@ -79,17 +87,17 @@ class TableRenderer(T...)
|
||||||
int rows = (_hasHeader?1:0) + lastRecord - firstRecord + 1;
|
int rows = (_hasHeader?1:0) + lastRecord - firstRecord + 1;
|
||||||
if (firstRecord + (_hasHeader?1:0) <= row && row <= rows)
|
if (firstRecord + (_hasHeader?1:0) <= row && row <= rows)
|
||||||
{
|
{
|
||||||
int y = margin.y + viewLine * height + _paddingY;
|
int y = location.y + viewLine * height + _paddingY;
|
||||||
foreach (int col, value; record)
|
foreach (int col, value; record)
|
||||||
{
|
{
|
||||||
int x = margin.x + sum(_width[0..col]) + _paddingX;
|
int x = location.x + sum(_width[0..col]) + _paddingX;
|
||||||
g.drawText(to!string(value), _recordFont, _textColor, Rect(x, y, _width[col] - _paddingX, _height - _paddingY), _recordTextFormat);
|
g.drawText(to!string(value), _recordFont, _textColor, Rect(x, y, _width[col] - _paddingX, _height - _paddingY), _recordTextFormat);
|
||||||
}
|
}
|
||||||
// Draw horizontal line.
|
// Draw horizontal line.
|
||||||
if (_horizontalLine && viewLine < lastRecord - firstRecord + (_showHeader?1:0))
|
if (_horizontalLine && viewLine < lastRecord - firstRecord + (_showHeader?1:0))
|
||||||
{
|
{
|
||||||
int y2 = margin.y + height * (viewLine + 1);
|
int y2 = location.y + height * (viewLine + 1);
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x, y2), Point(bounds.right, y2));
|
g.drawLine(new Pen(_lineColor), Point(location.x, y2), Point(bounds.right, y2));
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
viewLine++;
|
viewLine++;
|
||||||
|
@ -102,22 +110,22 @@ class TableRenderer(T...)
|
||||||
}
|
}
|
||||||
// Draw left side line.
|
// Draw left side line.
|
||||||
if (_leftSideLine)
|
if (_leftSideLine)
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x, margin.y), Point(margin.x, margin.y + height * viewLine));
|
g.drawLine(new Pen(_lineColor), Point(location.x, location.y), Point(location.x, location.y + height * viewLine));
|
||||||
// Draw right side line.
|
// Draw right side line.
|
||||||
if (_rightSideLine)
|
if (_rightSideLine)
|
||||||
g.drawLine(new Pen(_lineColor), Point(bounds.right, margin.y), Point(bounds.right, margin.y + height * viewLine));
|
g.drawLine(new Pen(_lineColor), Point(bounds.right, location.y), Point(bounds.right, location.y + height * viewLine));
|
||||||
// Draw vertical line.
|
// Draw vertical line.
|
||||||
if (_verticalLine)
|
if (_verticalLine)
|
||||||
{
|
{
|
||||||
for (int i; i < _columns - 1; i++)
|
for (int i; i < _columns - 1; i++)
|
||||||
{
|
{
|
||||||
int w = sum(_width[0..i+1]);
|
int w = sum(_width[0..i+1]);
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x + w, margin.y), Point(margin.x + w, margin.y + height * viewLine));
|
g.drawLine(new Pen(_lineColor), Point(location.x + w, location.y), Point(location.x + w, location.y + height * viewLine));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Draw bottom side line.
|
// Draw bottom side line.
|
||||||
if (_bottomSideLine)
|
if (_bottomSideLine)
|
||||||
g.drawLine(new Pen(_lineColor), Point(margin.x, margin.y + height * viewLine), Point(bounds.right, margin.y + height * viewLine));
|
g.drawLine(new Pen(_lineColor), Point(location.x, location.y + height * viewLine), Point(bounds.right, location.y + height * viewLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -180,19 +188,28 @@ class TableRenderer(T...)
|
||||||
Rect bounds() const
|
Rect bounds() const
|
||||||
{
|
{
|
||||||
int rows = (_showHeader?1:0) + lastRecord - firstRecord + 1;
|
int rows = (_showHeader?1:0) + lastRecord - firstRecord + 1;
|
||||||
return Rect(_margin.x, _margin.y, sum(_width), height * rows);
|
return Rect(_location.x, _location.y, sum(_width), height * rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Left and Top margins.
|
/// Left and Top point.
|
||||||
void margin(Point pt)
|
void location(Point pt)
|
||||||
{
|
{
|
||||||
_margin.x = pt.x;
|
_location = pt;
|
||||||
_margin.y = pt.y;
|
|
||||||
}
|
}
|
||||||
/// ditto
|
/// ditto
|
||||||
Point margin() const
|
Point location() const
|
||||||
{
|
{
|
||||||
return _margin;
|
return _location;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
deprecated void margin(Point pt)
|
||||||
|
{
|
||||||
|
location = pt;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
deprecated Point margin()
|
||||||
|
{
|
||||||
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -250,16 +267,26 @@ class TableRenderer(T...)
|
||||||
struct WidthObject // Internal struct.
|
struct WidthObject // Internal struct.
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
this(ref int[] w)
|
this(int[] w)
|
||||||
{
|
{
|
||||||
_arr = w;
|
_arr = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
/// Assign operator forwarding.
|
||||||
|
void opIndexAssign(int value)
|
||||||
|
{
|
||||||
|
_arr[] = value;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
void opIndexAssign(int value, size_t i)
|
void opIndexAssign(int value, size_t i)
|
||||||
{
|
{
|
||||||
_arr[i] = value;
|
_arr[i] = value;
|
||||||
}
|
}
|
||||||
|
/// ditto
|
||||||
|
void opSliceAssign(int value, size_t i, size_t j)
|
||||||
|
{
|
||||||
|
_arr[i..j] = value;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
int opIndex(size_t i)
|
int opIndex(size_t i)
|
||||||
|
@ -321,7 +348,7 @@ class TableRenderer(T...)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _csv;
|
string _csv;
|
||||||
Point _margin;
|
Point _location;
|
||||||
int _paddingX;
|
int _paddingX;
|
||||||
int _paddingY;
|
int _paddingY;
|
||||||
int _columns;
|
int _columns;
|
||||||
|
@ -346,3 +373,577 @@ private:
|
||||||
TextFormat _headerTextFormat;
|
TextFormat _headerTextFormat;
|
||||||
TextFormat _recordTextFormat;
|
TextFormat _recordTextFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
class LineGraphRenderer(T...)
|
||||||
|
if (is(T[0] == string) && T.length <= 17 || !is(T[0] == string) && T.length <= 16) // Supported number of colors is 16.
|
||||||
|
{
|
||||||
|
///
|
||||||
|
this(string csv, int numRecords)
|
||||||
|
{
|
||||||
|
this(csv);
|
||||||
|
_firstRecord = 0;
|
||||||
|
_lastRecord = numRecords - 1;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
this(string csv) // deprecated
|
||||||
|
{
|
||||||
|
_csv = csv;
|
||||||
|
_vZeroPos = VerticalZeroPosition.BOTTOM;
|
||||||
|
_chartMargins = ChartMargins(50, 50, 50, 50);
|
||||||
|
_backColor = Color.white;
|
||||||
|
_plotAreaBoundsColor = Color.black;
|
||||||
|
_plotAreaHeightOnDisplay = 100;
|
||||||
|
_plotAreaLeftPadding = 20;
|
||||||
|
_plotAreaRightPadding = 20;
|
||||||
|
_plotAreaAndLegendSpanX = 50;
|
||||||
|
_plotAreaAndHorizontalScaleSpanY = 10;
|
||||||
|
_plotPointSize = 10;
|
||||||
|
_plotLineColorPalette = [
|
||||||
|
Color.black, // 0
|
||||||
|
Color.blue, // 1
|
||||||
|
Color.red, // 2
|
||||||
|
Color.purple, // 3
|
||||||
|
Color.yellowGreen, // 4
|
||||||
|
Color.lightBlue, // 5
|
||||||
|
Color(0xFF,0xC2,0x0E), // 6: Use Himawari color as yellow.
|
||||||
|
Color.lightGray, // 7
|
||||||
|
Color.black, // 8
|
||||||
|
Color.darkBlue, // 9
|
||||||
|
Color.darkRed, // 10
|
||||||
|
Color.mediumPurple, // 11
|
||||||
|
Color.darkGreen, // 12
|
||||||
|
Color.darkSeaGreen, // 13
|
||||||
|
Color.darkOrange, // 14
|
||||||
|
Color.darkGray // 15
|
||||||
|
];
|
||||||
|
for (int i; i < T.length; i++)
|
||||||
|
{
|
||||||
|
_plotPointFormList ~= PlotPointForm.CIRCLE;
|
||||||
|
}
|
||||||
|
_legendWidth = 100;
|
||||||
|
_legendLineHeight = 18;
|
||||||
|
_hasVerticalScale = false;
|
||||||
|
_verticalScaleWidth = 40;
|
||||||
|
_verticalMaxScale = 100;
|
||||||
|
_verticalScaleLineOuterSide = 5;
|
||||||
|
_verticalScaleLineInnerSide = 5;
|
||||||
|
_hasHorizontalScale = false;
|
||||||
|
_horizontalScaleSpan = 50;
|
||||||
|
_horizonScaleLineInnerSide = 5;
|
||||||
|
_horizonScaleLineOuterSide = 5;
|
||||||
|
_horizontalScaleHeight = 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw records.
|
||||||
|
void draw(Graphics g)
|
||||||
|
{
|
||||||
|
// 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 (_showLegend)
|
||||||
|
{
|
||||||
|
backgroundRect.width = plotAreaBounds.width + _chartMargins.left + _legendWidth + _chartMargins.right;
|
||||||
|
int legendBottom = _chartMargins.top + _legendLineHeight * (1 + cast(int)T.length) + _chartMargins.bottom;
|
||||||
|
if (legendBottom > backgroundRect.bottom)
|
||||||
|
backgroundRect.height = legendBottom;
|
||||||
|
}
|
||||||
|
if (_hasVerticalScale)
|
||||||
|
{
|
||||||
|
backgroundRect.x = plotAreaBounds.x - _chartMargins.left - _verticalScaleWidth,
|
||||||
|
backgroundRect.width = plotAreaBounds.width + _chartMargins.left + _legendWidth + _chartMargins.right + _verticalScaleWidth;
|
||||||
|
}
|
||||||
|
if (_hasHorizontalScale)
|
||||||
|
{
|
||||||
|
backgroundRect.height += _horizontalScaleHeight + _plotAreaAndHorizontalScaleSpanY;
|
||||||
|
}
|
||||||
|
g.fillRectangle(new SolidBrush(_backColor), backgroundRect);
|
||||||
|
// Draw bounds of plot area.
|
||||||
|
g.drawRectangle(new Pen(_plotAreaBoundsColor), plotAreaBounds);
|
||||||
|
// Draw vertical scale.
|
||||||
|
int baseY = (_vZeroPos == VerticalZeroPosition.BOTTOM ? 0: _plotAreaHeightOnDisplay);
|
||||||
|
double vRatio = cast(double)_plotAreaHeightOnDisplay / _verticalMaxScale;
|
||||||
|
if (_hasVerticalScale)
|
||||||
|
{
|
||||||
|
enum LINE_HEIGHT = 12f;
|
||||||
|
auto scaleList = iota(0, _verticalMaxScale, _verticalScaleSpan);
|
||||||
|
Font f = new Font("MS Gothic", LINE_HEIGHT);
|
||||||
|
int x = _originPoint.x - _verticalScaleWidth;
|
||||||
|
int index;
|
||||||
|
foreach (s; scaleList)
|
||||||
|
{
|
||||||
|
int y = cast(int)(baseY + _originPoint.y - LINE_HEIGHT / 2 + index * vRatio * _verticalScaleSpan * (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1: 1));
|
||||||
|
// Draw vertical scalse label.
|
||||||
|
g.drawText(to!string(index * _verticalScaleSpan), f, Color.black, Rect(x, y, 100, 100));
|
||||||
|
// Draw vertical scalse line.
|
||||||
|
g.drawLine(
|
||||||
|
new Pen(_plotAreaBoundsColor),
|
||||||
|
_originPoint.x - _verticalScaleLineOuterSide,
|
||||||
|
cast(int)(y + LINE_HEIGHT / 2 + (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1: 0)),
|
||||||
|
_originPoint.x + _verticalScaleLineInnerSide,
|
||||||
|
cast(int)(y + LINE_HEIGHT / 2 + (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1: 0))
|
||||||
|
);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Draw horizontal scale.
|
||||||
|
if (_hasHorizontalScale)
|
||||||
|
{
|
||||||
|
// Draw horizontal scale label.
|
||||||
|
static if (is(T[0] == string))
|
||||||
|
{{
|
||||||
|
int i;
|
||||||
|
foreach (label; csvReader!(Tuple!T)(_csv, null))
|
||||||
|
{
|
||||||
|
int x = _originPoint.x + _plotAreaLeftPadding + i * _horizontalScaleSpan - cast(int)_horizontalScaleHeight;
|
||||||
|
int y = baseY + _originPoint.y + (_vZeroPos == VerticalZeroPosition.BOTTOM ? _plotAreaAndHorizontalScaleSpanY: -_plotAreaAndHorizontalScaleSpanY - _horizontalScaleHeight);
|
||||||
|
g.drawText(
|
||||||
|
label[0],
|
||||||
|
new Font("MS Gothic", 12f),
|
||||||
|
_plotAreaBoundsColor,
|
||||||
|
Rect(x, y, _horizontalScaleSpan, _horizontalScaleHeight)
|
||||||
|
);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
//
|
||||||
|
for (int i; i < _lastRecord - _firstRecord + 1; i++)
|
||||||
|
{
|
||||||
|
int x = _originPoint.x + _plotAreaLeftPadding + i * _horizontalScaleSpan;
|
||||||
|
int y = baseY + _originPoint.y;
|
||||||
|
// Draw horizontal scale line.
|
||||||
|
g.drawLine(
|
||||||
|
new Pen(_plotAreaBoundsColor),
|
||||||
|
x,
|
||||||
|
y - _horizonScaleLineInnerSide * (_vZeroPos == VerticalZeroPosition.BOTTOM ? 1 : -1),
|
||||||
|
x,
|
||||||
|
y + _horizonScaleLineOuterSide * (_vZeroPos == VerticalZeroPosition.BOTTOM ? 1 : -1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Draw legend.
|
||||||
|
if (_showLegend)
|
||||||
|
{
|
||||||
|
int legendLine;
|
||||||
|
foreach (i, value; csvReader!(Tuple!T)(_csv, null).header)
|
||||||
|
{
|
||||||
|
static if (is(T[0] == string))
|
||||||
|
{
|
||||||
|
if (i == 0) continue;
|
||||||
|
}
|
||||||
|
int x = plotAreaBounds.right + _plotAreaAndLegendSpanX + _plotPointSize;
|
||||||
|
int y = plotAreaBounds.y + _legendLineHeight * cast(int)legendLine;
|
||||||
|
g.drawText(to!string(value), new Font("MS Gothic", 12f), Color.black, Rect(x, y, 100, 100));
|
||||||
|
_drawPlotPoint(
|
||||||
|
g,
|
||||||
|
new Pen(_plotLineColorPalette[legendLine]),
|
||||||
|
_plotPointFormList[legendLine],
|
||||||
|
_plotPointSize, x - _plotPointSize * 2, // Center X.
|
||||||
|
y + _legendLineHeight / 2 // Center Y.
|
||||||
|
);
|
||||||
|
legendLine++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Draw records.
|
||||||
|
Tuple!T prevRecord;
|
||||||
|
int x1 = _originPoint.x + _plotAreaLeftPadding;
|
||||||
|
int x2;
|
||||||
|
bool isFirstRecord = true;
|
||||||
|
auto csvRange = csvReader!(Tuple!T)(_csv, null).drop(_firstRecord);
|
||||||
|
foreach (currRecord; csvRange)
|
||||||
|
{
|
||||||
|
x2 = x1 + _horizontalScaleSpan;
|
||||||
|
bool isFirstColumn = true;
|
||||||
|
foreach (col, value; currRecord)
|
||||||
|
{
|
||||||
|
static if (!(is(T[0] == string) && col == 0))
|
||||||
|
{
|
||||||
|
int y1 = cast(int)(baseY + _originPoint.y + vRatio * prevRecord[col] * (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1: 1));
|
||||||
|
int y2 = cast(int)(baseY + _originPoint.y + vRatio * value * (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1: 1));
|
||||||
|
int seriesIndex = col - (is(T[0] == string)?1:0);
|
||||||
|
if (!isFirstRecord)
|
||||||
|
{
|
||||||
|
g.drawLine(
|
||||||
|
new Pen(_plotLineColorPalette[seriesIndex]),
|
||||||
|
x1 - _horizontalScaleSpan,
|
||||||
|
y1,
|
||||||
|
x2 - _horizontalScaleSpan,
|
||||||
|
y2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_drawPlotPoint(
|
||||||
|
g,
|
||||||
|
new Pen(_plotLineColorPalette[seriesIndex]),
|
||||||
|
_plotPointFormList[seriesIndex],
|
||||||
|
_plotPointSize,
|
||||||
|
x2 - _horizontalScaleSpan, // Center X.
|
||||||
|
y2 // Center Y.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
isFirstColumn = false;
|
||||||
|
}
|
||||||
|
x1 = x1 + _horizontalScaleSpan;
|
||||||
|
prevRecord = currRecord;
|
||||||
|
isFirstRecord = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
Rect plotAreaBounds() const
|
||||||
|
{
|
||||||
|
return Rect(
|
||||||
|
_originPoint.x,
|
||||||
|
_originPoint.y + _plotAreaHeightOnDisplay * (_vZeroPos == VerticalZeroPosition.BOTTOM ? -1 : 1),
|
||||||
|
cast(int)((_lastRecord - _firstRecord) * _horizontalScaleSpan) + _plotAreaLeftPadding + _plotAreaRightPadding,
|
||||||
|
_plotAreaHeightOnDisplay
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void originPoint(Point pt)
|
||||||
|
{
|
||||||
|
_originPoint = pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void relocate(Point pt)
|
||||||
|
{
|
||||||
|
final switch (_vZeroPos)
|
||||||
|
{
|
||||||
|
case VerticalZeroPosition.BOTTOM:
|
||||||
|
int x = _chartMargins.left + _verticalScaleWidth + pt.x;
|
||||||
|
int y = _chartMargins.top + _plotAreaHeightOnDisplay + pt.y;
|
||||||
|
originPoint = Point(x, y);
|
||||||
|
break;
|
||||||
|
case VerticalZeroPosition.TOP:
|
||||||
|
int x = _chartMargins.left + _verticalScaleWidth + pt.x;
|
||||||
|
int y = _chartMargins.top + pt.y - _plotAreaHeightOnDisplay;
|
||||||
|
originPoint = Point(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void verticalZeroPosition(VerticalZeroPosition vZeroPos) // setter
|
||||||
|
{
|
||||||
|
_vZeroPos = vZeroPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void chartMargins(ChartMargins m)
|
||||||
|
{
|
||||||
|
_chartMargins = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotPointSize(int size)
|
||||||
|
{
|
||||||
|
_plotPointSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void showLegend(bool byes)
|
||||||
|
{
|
||||||
|
_showLegend = byes;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotLineColorPalette(Color[] colors)
|
||||||
|
{
|
||||||
|
_plotLineColorPalette = colors;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
Color[] plotLineColorPalette()
|
||||||
|
{
|
||||||
|
return _plotLineColorPalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotAreaAndLegendSpanX(int x)
|
||||||
|
{
|
||||||
|
_plotAreaAndLegendSpanX = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotAreaAndHorizontalScaleSpanY(int y)
|
||||||
|
{
|
||||||
|
_plotAreaAndHorizontalScaleSpanY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void legendLineHeight(int h)
|
||||||
|
{
|
||||||
|
_legendLineHeight = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void legendWidth(int w)
|
||||||
|
{
|
||||||
|
_legendWidth = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotAreaRightPadding(int x)
|
||||||
|
{
|
||||||
|
_plotAreaRightPadding = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotAreaLeftPadding(int x)
|
||||||
|
{
|
||||||
|
_plotAreaLeftPadding = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
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 verticalMaxScale(int m)
|
||||||
|
{
|
||||||
|
_verticalMaxScale = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotAreaHeightOnDisplay(int h)
|
||||||
|
{
|
||||||
|
_plotAreaHeightOnDisplay = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void hasVerticalScale(bool byes)
|
||||||
|
{
|
||||||
|
_hasVerticalScale = byes;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void hasHorizontalScale(bool byes)
|
||||||
|
{
|
||||||
|
_hasHorizontalScale = byes;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void verticalScaleSpan(int scale)
|
||||||
|
{
|
||||||
|
_verticalScaleSpan = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void verticalScaleWidth(int w)
|
||||||
|
{
|
||||||
|
_verticalScaleWidth = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void verticalScaleLineOuterSide(int w)
|
||||||
|
{
|
||||||
|
_verticalScaleLineOuterSide = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void verticalScaleLineInnerSide(int w)
|
||||||
|
{
|
||||||
|
_verticalScaleLineInnerSide = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void horizonScaleLineInnerSide(int h)
|
||||||
|
{
|
||||||
|
_horizonScaleLineInnerSide = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void horizonScaleLineOuterSide(int h)
|
||||||
|
{
|
||||||
|
_horizonScaleLineOuterSide = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void horizontalScaleHeight(int h)
|
||||||
|
{
|
||||||
|
_horizontalScaleHeight = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
void plotPointFormList(PlotPointForm[] forms)
|
||||||
|
{
|
||||||
|
_plotPointFormList = forms;
|
||||||
|
}
|
||||||
|
/// ditto
|
||||||
|
PlotPointForm[] plotPointFormList()
|
||||||
|
{
|
||||||
|
return _plotPointFormList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _csv;
|
||||||
|
int _firstRecord;
|
||||||
|
int _lastRecord;
|
||||||
|
VerticalZeroPosition _vZeroPos;
|
||||||
|
Point _originPoint;
|
||||||
|
ChartMargins _chartMargins;
|
||||||
|
bool _showLegend;
|
||||||
|
int _legendLineHeight;
|
||||||
|
int _legendWidth;
|
||||||
|
Color _backColor;
|
||||||
|
Color _plotAreaBoundsColor;
|
||||||
|
int _plotAreaLeftPadding;
|
||||||
|
int _plotAreaRightPadding;
|
||||||
|
int _plotAreaHeightOnDisplay;
|
||||||
|
int _plotAreaAndLegendSpanX;
|
||||||
|
int _plotAreaAndHorizontalScaleSpanY;
|
||||||
|
int _plotPointSize;
|
||||||
|
Color[] _plotLineColorPalette;
|
||||||
|
PlotPointForm[] _plotPointFormList;
|
||||||
|
bool _hasHorizontalScale;
|
||||||
|
int _horizontalScaleSpan;
|
||||||
|
int _horizontalScaleHeight;
|
||||||
|
int _horizonScaleLineInnerSide;
|
||||||
|
int _horizonScaleLineOuterSide;
|
||||||
|
bool _hasVerticalScale;
|
||||||
|
int _verticalMaxScale;
|
||||||
|
int _verticalScaleSpan;
|
||||||
|
int _verticalScaleWidth;
|
||||||
|
int _verticalScaleLineOuterSide;
|
||||||
|
int _verticalScaleLineInnerSide;
|
||||||
|
|
||||||
|
///
|
||||||
|
void _drawPlotPoint(Graphics g, Pen pen, PlotPointForm form, int plotPointSize, int centerX, int centerY)
|
||||||
|
{
|
||||||
|
final switch (form)
|
||||||
|
{
|
||||||
|
case PlotPointForm.CIRCLE:
|
||||||
|
g.drawEllipse(
|
||||||
|
pen,
|
||||||
|
centerX - _plotPointSize / 2,
|
||||||
|
centerY - _plotPointSize / 2,
|
||||||
|
plotPointSize, // width
|
||||||
|
plotPointSize // height
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case PlotPointForm.RECTANGLE:
|
||||||
|
g.drawRectangle(
|
||||||
|
pen,
|
||||||
|
centerX - _plotPointSize / 2,
|
||||||
|
centerY - _plotPointSize / 2,
|
||||||
|
plotPointSize, // width
|
||||||
|
plotPointSize // height
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case PlotPointForm.CROSS:
|
||||||
|
g.drawLine(
|
||||||
|
pen,
|
||||||
|
centerX - _plotPointSize / 2,
|
||||||
|
centerY - _plotPointSize / 2,
|
||||||
|
centerX + _plotPointSize / 2 + 1,
|
||||||
|
centerY + _plotPointSize / 2 + 1
|
||||||
|
);
|
||||||
|
g.drawLine(
|
||||||
|
pen,
|
||||||
|
centerX + _plotPointSize / 2,
|
||||||
|
centerY - _plotPointSize / 2,
|
||||||
|
centerX - _plotPointSize / 2 - 1,
|
||||||
|
centerY + _plotPointSize / 2 + 1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case PlotPointForm.TRIANGLE:
|
||||||
|
g.drawLine(
|
||||||
|
pen,
|
||||||
|
centerX,
|
||||||
|
centerY - _plotPointSize * 2 / 3,
|
||||||
|
centerX + _plotPointSize / 2,
|
||||||
|
centerY + _plotPointSize / 3
|
||||||
|
);
|
||||||
|
g.drawLine(
|
||||||
|
pen,
|
||||||
|
centerX,
|
||||||
|
centerY - _plotPointSize * 2 / 3,
|
||||||
|
centerX - _plotPointSize / 2,
|
||||||
|
centerY + _plotPointSize / 3
|
||||||
|
);
|
||||||
|
g.drawLine(
|
||||||
|
pen,
|
||||||
|
centerX - _plotPointSize / 2,
|
||||||
|
centerY + _plotPointSize / 3,
|
||||||
|
centerX + _plotPointSize / 2,
|
||||||
|
centerY + _plotPointSize / 3
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
struct ChartMargins
|
||||||
|
{
|
||||||
|
int left; /// Left margin.
|
||||||
|
int top; /// Top margin.
|
||||||
|
int right; /// Right margin.
|
||||||
|
int bottom; /// Bottom margin.
|
||||||
|
|
||||||
|
///
|
||||||
|
this(int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
this.left = left;
|
||||||
|
this.top = top;
|
||||||
|
this.right = right;
|
||||||
|
this.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
string toString() const
|
||||||
|
{
|
||||||
|
|
||||||
|
string str = "[";
|
||||||
|
str ~= to!string(left) ~ " ,";
|
||||||
|
str ~= to!string(top) ~ " ,";
|
||||||
|
str ~= to!string(right) ~ " ,";
|
||||||
|
str ~= to!string(bottom) ~ "]";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
enum VerticalZeroPosition
|
||||||
|
{
|
||||||
|
TOP,
|
||||||
|
BOTTOM,
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
enum PlotPointForm
|
||||||
|
{
|
||||||
|
CIRCLE,
|
||||||
|
RECTANGLE,
|
||||||
|
CROSS,
|
||||||
|
TRIANGLE,
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue