2020.06.26
+ UIDoughnutChart:增加控件:环状图
This commit is contained in:
parent
9d12d58523
commit
6d93656a92
BIN
Bin/SunnyUI.dll
BIN
Bin/SunnyUI.dll
Binary file not shown.
BIN
Bin/SunnyUI.pdb
BIN
Bin/SunnyUI.pdb
Binary file not shown.
Binary file not shown.
Binary file not shown.
153
SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs
generated
Normal file
153
SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs
generated
Normal file
@ -0,0 +1,153 @@
|
||||
namespace Sunny.UI.Demo.Charts
|
||||
{
|
||||
partial class FDoughnutChart
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.DoughnutChart = new Sunny.UI.UIDoughnutChart();
|
||||
this.uiSymbolButton1 = new Sunny.UI.UISymbolButton();
|
||||
this.uiImageButton3 = new Sunny.UI.UIImageButton();
|
||||
this.uiImageButton2 = new Sunny.UI.UIImageButton();
|
||||
this.uiImageButton1 = new Sunny.UI.UIImageButton();
|
||||
this.uiLine1 = new Sunny.UI.UILine();
|
||||
this.PagePanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// PagePanel
|
||||
//
|
||||
this.PagePanel.Controls.Add(this.uiSymbolButton1);
|
||||
this.PagePanel.Controls.Add(this.uiImageButton3);
|
||||
this.PagePanel.Controls.Add(this.uiImageButton2);
|
||||
this.PagePanel.Controls.Add(this.uiImageButton1);
|
||||
this.PagePanel.Controls.Add(this.uiLine1);
|
||||
this.PagePanel.Controls.Add(this.DoughnutChart);
|
||||
this.PagePanel.Size = new System.Drawing.Size(800, 523);
|
||||
//
|
||||
// DoughnutChart
|
||||
//
|
||||
this.DoughnutChart.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
|
||||
this.DoughnutChart.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.DoughnutChart.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
|
||||
this.DoughnutChart.Location = new System.Drawing.Point(30, 48);
|
||||
this.DoughnutChart.Name = "DoughnutChart";
|
||||
this.DoughnutChart.Option = null;
|
||||
this.DoughnutChart.Size = new System.Drawing.Size(670, 400);
|
||||
this.DoughnutChart.TabIndex = 0;
|
||||
this.DoughnutChart.Text = "uiDoughnutChart1";
|
||||
//
|
||||
// uiSymbolButton1
|
||||
//
|
||||
this.uiSymbolButton1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.uiSymbolButton1.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.uiSymbolButton1.Location = new System.Drawing.Point(348, 466);
|
||||
this.uiSymbolButton1.Name = "uiSymbolButton1";
|
||||
this.uiSymbolButton1.Padding = new System.Windows.Forms.Padding(28, 0, 0, 0);
|
||||
this.uiSymbolButton1.Size = new System.Drawing.Size(100, 27);
|
||||
this.uiSymbolButton1.Symbol = 61952;
|
||||
this.uiSymbolButton1.TabIndex = 33;
|
||||
this.uiSymbolButton1.Text = "数据";
|
||||
this.uiSymbolButton1.Click += new System.EventHandler(this.uiSymbolButton1_Click);
|
||||
//
|
||||
// uiImageButton3
|
||||
//
|
||||
this.uiImageButton3.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.uiImageButton3.Image = global::Sunny.UI.Demo.Properties.Resources.ChartDarkStyle;
|
||||
this.uiImageButton3.Location = new System.Drawing.Point(242, 466);
|
||||
this.uiImageButton3.Name = "uiImageButton3";
|
||||
this.uiImageButton3.Size = new System.Drawing.Size(100, 27);
|
||||
this.uiImageButton3.TabIndex = 32;
|
||||
this.uiImageButton3.TabStop = false;
|
||||
this.uiImageButton3.Text = " Dark";
|
||||
this.uiImageButton3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.uiImageButton3.Click += new System.EventHandler(this.uiImageButton3_Click);
|
||||
//
|
||||
// uiImageButton2
|
||||
//
|
||||
this.uiImageButton2.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.uiImageButton2.Image = global::Sunny.UI.Demo.Properties.Resources.ChartPlainStyle;
|
||||
this.uiImageButton2.Location = new System.Drawing.Point(136, 466);
|
||||
this.uiImageButton2.Name = "uiImageButton2";
|
||||
this.uiImageButton2.Size = new System.Drawing.Size(100, 27);
|
||||
this.uiImageButton2.TabIndex = 31;
|
||||
this.uiImageButton2.TabStop = false;
|
||||
this.uiImageButton2.Text = " Plain";
|
||||
this.uiImageButton2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.uiImageButton2.Click += new System.EventHandler(this.uiImageButton2_Click);
|
||||
//
|
||||
// uiImageButton1
|
||||
//
|
||||
this.uiImageButton1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.uiImageButton1.Image = global::Sunny.UI.Demo.Properties.Resources.ChartDefaultStyle;
|
||||
this.uiImageButton1.Location = new System.Drawing.Point(30, 466);
|
||||
this.uiImageButton1.Name = "uiImageButton1";
|
||||
this.uiImageButton1.Size = new System.Drawing.Size(100, 27);
|
||||
this.uiImageButton1.TabIndex = 30;
|
||||
this.uiImageButton1.TabStop = false;
|
||||
this.uiImageButton1.Text = " Default";
|
||||
this.uiImageButton1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.uiImageButton1.Click += new System.EventHandler(this.uiImageButton1_Click);
|
||||
//
|
||||
// uiLine1
|
||||
//
|
||||
this.uiLine1.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.uiLine1.Location = new System.Drawing.Point(30, 20);
|
||||
this.uiLine1.MinimumSize = new System.Drawing.Size(16, 16);
|
||||
this.uiLine1.Name = "uiLine1";
|
||||
this.uiLine1.Size = new System.Drawing.Size(670, 20);
|
||||
this.uiLine1.TabIndex = 29;
|
||||
this.uiLine1.Text = "UIDoughnutChart";
|
||||
this.uiLine1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// FDoughnutChart
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 558);
|
||||
this.Name = "FDoughnutChart";
|
||||
this.Symbol = 62056;
|
||||
this.Text = "DoughnutChart";
|
||||
this.PagePanel.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private UIDoughnutChart DoughnutChart;
|
||||
private UISymbolButton uiSymbolButton1;
|
||||
private UIImageButton uiImageButton3;
|
||||
private UIImageButton uiImageButton2;
|
||||
private UIImageButton uiImageButton1;
|
||||
private UILine uiLine1;
|
||||
}
|
||||
}
|
77
SunnyUI.Demo/Charts/FDoughnutChart.cs
Normal file
77
SunnyUI.Demo/Charts/FDoughnutChart.cs
Normal file
@ -0,0 +1,77 @@
|
||||
namespace Sunny.UI.Demo.Charts
|
||||
{
|
||||
public partial class FDoughnutChart : UITitlePage
|
||||
{
|
||||
public FDoughnutChart()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void uiSymbolButton1_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
var option = new UIDoughnutOption();
|
||||
|
||||
//设置Title
|
||||
option.Title = new UITitle();
|
||||
option.Title.Text = "SunnyUI";
|
||||
option.Title.SubText = "Star";
|
||||
option.Title.Left = UILeftAlignment.Center;
|
||||
|
||||
//设置ToolTip
|
||||
option.ToolTip = new UIPieToolTip();
|
||||
|
||||
//设置Legend
|
||||
option.Legend = new UILegend();
|
||||
option.Legend.Orient = UIOrient.Vertical;
|
||||
option.Legend.Top = UITopAlignment.Top;
|
||||
option.Legend.Left = UILeftAlignment.Left;
|
||||
|
||||
option.Legend.AddData("2020-05-19");
|
||||
option.Legend.AddData("2020-05-20");
|
||||
option.Legend.AddData("2020-05-21");
|
||||
option.Legend.AddData("2020-05-22");
|
||||
option.Legend.AddData("2020-05-23");
|
||||
option.Legend.AddData("2020-05-24");
|
||||
option.Legend.AddData("2020-05-25");
|
||||
|
||||
//设置Series
|
||||
var series = new UIDoughnutSeries();
|
||||
series.Name = "Star count";
|
||||
series.Center = new UICenter(50, 55);
|
||||
series.Radius.Inner = 40;
|
||||
series.Radius.Outer = 70;
|
||||
series.Label.Show = true;
|
||||
series.Label.Position = UIPieSeriesLabelPosition.Center;
|
||||
|
||||
//增加数据
|
||||
series.AddData("2020-05-19", 38);
|
||||
series.AddData("2020-05-20", 21);
|
||||
series.AddData("2020-05-21", 11);
|
||||
series.AddData("2020-05-22", 52);
|
||||
series.AddData("2020-05-23", 23);
|
||||
series.AddData("2020-05-24", 26);
|
||||
series.AddData("2020-05-25", 27);
|
||||
|
||||
//增加Series
|
||||
option.Series.Add(series);
|
||||
|
||||
//设置Option
|
||||
DoughnutChart.SetOption(option);
|
||||
}
|
||||
|
||||
private void uiImageButton1_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
DoughnutChart.ChartStyleType = UIChartStyleType.Default;
|
||||
}
|
||||
|
||||
private void uiImageButton2_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
DoughnutChart.ChartStyleType = UIChartStyleType.Plain;
|
||||
}
|
||||
|
||||
private void uiImageButton3_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
DoughnutChart.ChartStyleType = UIChartStyleType.Dark;
|
||||
}
|
||||
}
|
||||
}
|
120
SunnyUI.Demo/Charts/FDoughnutChart.resx
Normal file
120
SunnyUI.Demo/Charts/FDoughnutChart.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
2
SunnyUI.Demo/Controls/FOther.Designer.cs
generated
2
SunnyUI.Demo/Controls/FOther.Designer.cs
generated
@ -155,7 +155,7 @@
|
||||
// uiProgressIndicator1
|
||||
//
|
||||
this.uiProgressIndicator1.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.uiProgressIndicator1.Location = new System.Drawing.Point(30, 217);
|
||||
this.uiProgressIndicator1.Location = new System.Drawing.Point(30, 209);
|
||||
this.uiProgressIndicator1.Name = "uiProgressIndicator1";
|
||||
this.uiProgressIndicator1.Size = new System.Drawing.Size(119, 132);
|
||||
this.uiProgressIndicator1.TabIndex = 26;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using Sunny.UI.Demo.Controls;
|
||||
using Sunny.UI.Demo.Charts;
|
||||
using Sunny.UI.Demo.Controls;
|
||||
using Sunny.UI.Demo.Forms;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Sunny.UI.Demo.Charts;
|
||||
|
||||
namespace Sunny.UI.Demo
|
||||
{
|
||||
@ -35,24 +35,25 @@ namespace Sunny.UI.Demo
|
||||
Aside.CreateChildNode(parent, 62104, 24, AddPage(new FContextMenuStrip(), ++pageIndex));
|
||||
Aside.CreateChildNode(parent, 61668, 24, AddPage(new FMeter(), ++pageIndex));
|
||||
Aside.CreateChildNode(parent, 62173, 24, AddPage(new FOther(), ++pageIndex));
|
||||
Aside.SetNodeTipsText(parent.Nodes[0],"1");
|
||||
Aside.SetNodeTipsText(parent.Nodes[0], "1");
|
||||
|
||||
pageIndex = 2000;
|
||||
Header.SetNodePageIndex(Header.Nodes[1], pageIndex);
|
||||
Header.SetNodeSymbol(Header.Nodes[1], 61818);
|
||||
parent = Aside.CreateNode("Forms", 61818, 24, pageIndex);
|
||||
//通过设置GUID关联
|
||||
Aside.CreateChildNode(parent, 62160, 24, AddPage(new FDialogs(), Guid.NewGuid()));
|
||||
Aside.CreateChildNode(parent, 61508, 24, AddPage(new FEditor(), Guid.NewGuid()));
|
||||
Aside.CreateChildNode(parent, 61674, 24, AddPage(new FFrames(), Guid.NewGuid()));
|
||||
//通过设置GUID关联,节点字体图标和大小由UIPage设置
|
||||
Aside.CreateChildNode(parent, AddPage(new FDialogs(), Guid.NewGuid()));
|
||||
Aside.CreateChildNode(parent, AddPage(new FEditor(), Guid.NewGuid()));
|
||||
Aside.CreateChildNode(parent, AddPage(new FFrames(), Guid.NewGuid()));
|
||||
|
||||
pageIndex = 3000;
|
||||
Header.SetNodePageIndex(Header.Nodes[2], pageIndex);
|
||||
Header.SetNodeSymbol(Header.Nodes[2], 61950);
|
||||
parent = Aside.CreateNode("Charts", 61950, 24, pageIndex);
|
||||
//直接关联(默认自动生成GUID)
|
||||
Aside.CreateChildNode(parent, 61952, 24, AddPage(new FPieChart()));
|
||||
Aside.CreateChildNode(parent, 61568, 24, AddPage(new FBarChart()));
|
||||
Aside.CreateChildNode(parent, AddPage(new FPieChart()));
|
||||
Aside.CreateChildNode(parent, AddPage(new FBarChart()));
|
||||
Aside.CreateChildNode(parent, AddPage(new FDoughnutChart()));
|
||||
|
||||
Header.SetNodeSymbol(Header.Nodes[3], 61502);
|
||||
var styles = UIStyles.PopularStyles();
|
||||
|
@ -53,6 +53,12 @@
|
||||
<Compile Include="Charts\FBarChart.Designer.cs">
|
||||
<DependentUpon>FBarChart.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Charts\FDoughnutChart.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Charts\FDoughnutChart.Designer.cs">
|
||||
<DependentUpon>FDoughnutChart.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\FAvatar.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@ -286,6 +292,9 @@
|
||||
<EmbeddedResource Include="Charts\FBarChart.resx">
|
||||
<DependentUpon>FBarChart.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Charts\FDoughnutChart.resx">
|
||||
<DependentUpon>FDoughnutChart.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Controls\FAvatar.resx">
|
||||
<DependentUpon>FAvatar.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
263
SunnyUI/Charts/UIDoughnutChart.cs
Normal file
263
SunnyUI/Charts/UIDoughnutChart.cs
Normal file
@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Sunny.UI
|
||||
{
|
||||
[ToolboxItem(true), Description("甜甜圈图")]
|
||||
public class UIDoughnutChart : UIChart
|
||||
{
|
||||
protected override void CreateEmptyOption()
|
||||
{
|
||||
if (emptyOption != null) return;
|
||||
|
||||
UIDoughnutOption option = new UIDoughnutOption();
|
||||
|
||||
option.Title = new UITitle();
|
||||
option.Title.Text = "SunnyUI";
|
||||
option.Title.SubText = "DoughnutChart";
|
||||
|
||||
var series = new UIDoughnutSeries();
|
||||
series.Name = "饼状图";
|
||||
series.Center = new UICenter(50, 55);
|
||||
series.Radius.Inner = 40;
|
||||
series.Radius.Outer = 70;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
series.AddData("Data" + i, (i + 1) * 20);
|
||||
}
|
||||
|
||||
option.Series.Add(series);
|
||||
emptyOption = option;
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
base.OnSizeChanged(e);
|
||||
CalcData(DoughnutOption);
|
||||
}
|
||||
|
||||
protected override void DrawOption(Graphics g)
|
||||
{
|
||||
if (DoughnutOption == null) return;
|
||||
DrawTitle(g, DoughnutOption.Title);
|
||||
DrawSeries(g, DoughnutOption.Series);
|
||||
DrawLegend(g, DoughnutOption.Legend);
|
||||
}
|
||||
|
||||
protected override void CalcData(UIOption option)
|
||||
{
|
||||
Angles.Clear();
|
||||
UIDoughnutOption o = (UIDoughnutOption)option;
|
||||
if (o == null || o.Series == null || o.Series.Count == 0) return;
|
||||
UITemplate template = null;
|
||||
if (o.ToolTip != null)
|
||||
{
|
||||
template = new UITemplate(o.ToolTip.Formatter);
|
||||
}
|
||||
|
||||
for (int pieIndex = 0; pieIndex < o.Series.Count; pieIndex++)
|
||||
{
|
||||
var pie = o.Series[pieIndex];
|
||||
Angles.TryAdd(pieIndex, new ConcurrentDictionary<int, Angle>());
|
||||
|
||||
double all = 0;
|
||||
foreach (var data in pie.Data)
|
||||
{
|
||||
all += data.Value;
|
||||
}
|
||||
|
||||
if (all.IsZero()) return;
|
||||
float start = 0;
|
||||
for (int i = 0; i < pie.Data.Count; i++)
|
||||
{
|
||||
float angle = (float)(pie.Data[i].Value * 360.0f / all);
|
||||
float percent = (float)(pie.Data[i].Value * 100.0f / all);
|
||||
string text = "";
|
||||
if (o.ToolTip != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (template != null)
|
||||
{
|
||||
template.Set("a", pie.Name);
|
||||
template.Set("b", pie.Data[i].Name);
|
||||
template.Set("c", pie.Data[i].Value.ToString(o.ToolTip.ValueFormat));
|
||||
template.Set("d", percent.ToString("F2"));
|
||||
text = template.Render();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
text = pie.Data[i].Name + " : " + pie.Data[i].Value.ToString("F2") + "(" + percent.ToString("F2") + "%)";
|
||||
if (pie.Name.IsValid()) text = pie.Name + '\n' + text;
|
||||
}
|
||||
}
|
||||
|
||||
Angle pieAngle = new Angle(start, angle, text);
|
||||
GetSeriesRect(pie, ref pieAngle);
|
||||
Angles[pieIndex].AddOrUpdate(i, pieAngle);
|
||||
start += angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSeries(Graphics g, List<UIDoughnutSeries> series)
|
||||
{
|
||||
if (series == null || series.Count == 0) return;
|
||||
|
||||
for (int pieIndex = 0; pieIndex < series.Count; pieIndex++)
|
||||
{
|
||||
var pie = series[pieIndex];
|
||||
|
||||
for (int azIndex = 0; azIndex < pie.Data.Count; azIndex++)
|
||||
{
|
||||
Angle angle = Angles[pieIndex][azIndex];
|
||||
Color color = ChartStyle.SeriesColor[azIndex % ChartStyle.ColorCount];
|
||||
|
||||
if (ActiveAzIndex == azIndex)
|
||||
g.FillFan(color, angle.Center, angle.Inner, angle.Outer+5, angle.Start-90, angle.Sweep);
|
||||
else
|
||||
g.FillFan(color, angle.Center, angle.Inner, angle.Outer, angle.Start - 90, angle.Sweep);
|
||||
|
||||
Angles[pieIndex][azIndex].TextSize = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
|
||||
|
||||
if (pie.Label.Show && ActiveAzIndex == azIndex)
|
||||
{
|
||||
if (pie.Label.Position == UIPieSeriesLabelPosition.Center)
|
||||
{
|
||||
SizeF sf = g.MeasureString(pie.Data[azIndex].Name, Font);
|
||||
g.DrawString(pie.Data[azIndex].Name, Font, color, angle.Center.X- sf.Width/2.0f,angle.Center.Y-sf.Height/2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<int, ConcurrentDictionary<int, Angle>> Angles = new ConcurrentDictionary<int, ConcurrentDictionary<int, Angle>>();
|
||||
|
||||
[Browsable(false)]
|
||||
private UIDoughnutOption DoughnutOption
|
||||
{
|
||||
get
|
||||
{
|
||||
UIOption option = Option ?? EmptyOption;
|
||||
UIDoughnutOption o = (UIDoughnutOption)option;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
if (DoughnutOption.SeriesCount == 0)
|
||||
{
|
||||
SetPieAndAzIndex(-1, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int pieIndex = 0; pieIndex < DoughnutOption.SeriesCount; pieIndex++)
|
||||
{
|
||||
for (int azIndex = 0; azIndex < DoughnutOption.Series[pieIndex].Data.Count; azIndex++)
|
||||
{
|
||||
Angle angle = Angles[pieIndex][azIndex];
|
||||
PointF pf = angle.Center;
|
||||
if (MathEx.CalcDistance(e.Location, pf) > angle.Outer) continue;
|
||||
if (MathEx.CalcDistance(e.Location, pf) < angle.Inner) continue;
|
||||
double az = MathEx.CalcAngle(e.Location, pf);
|
||||
if (az >= angle.Start && az <= angle.Start + angle.Sweep)
|
||||
{
|
||||
SetPieAndAzIndex(pieIndex, azIndex);
|
||||
if (tip.Text != angle.Text)
|
||||
{
|
||||
tip.Text = angle.Text;
|
||||
tip.Size = new Size((int)angle.TextSize.Width + 4, (int)angle.TextSize.Height + 4);
|
||||
}
|
||||
|
||||
if (az >= 0 && az < 90)
|
||||
{
|
||||
tip.Top = e.Location.Y + 20;
|
||||
tip.Left = e.Location.X - tip.Width;
|
||||
}
|
||||
else if (az >= 90 && az < 180)
|
||||
{
|
||||
tip.Left = e.Location.X - tip.Width;
|
||||
tip.Top = e.Location.Y - tip.Height - 2;
|
||||
}
|
||||
else if (az >= 180 && az < 270)
|
||||
{
|
||||
tip.Left = e.Location.X;
|
||||
tip.Top = e.Location.Y - tip.Height - 2;
|
||||
}
|
||||
else if (az >= 270 && az < 360)
|
||||
{
|
||||
tip.Left = e.Location.X + 15;
|
||||
tip.Top = e.Location.Y + 20;
|
||||
}
|
||||
|
||||
if (!tip.Visible) tip.Visible = angle.Text.IsValid();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetPieAndAzIndex(-1, -1);
|
||||
tip.Visible = false;
|
||||
}
|
||||
|
||||
private int ActiveAzIndex = -1;
|
||||
private int ActivePieIndex = -1;
|
||||
|
||||
private void SetPieAndAzIndex(int pieIndex, int azIndex)
|
||||
{
|
||||
if (ActivePieIndex != pieIndex || ActiveAzIndex != azIndex)
|
||||
{
|
||||
ActivePieIndex = pieIndex;
|
||||
ActiveAzIndex = azIndex;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSeriesRect(UIDoughnutSeries series, ref Angle angle)
|
||||
{
|
||||
int left = series.Center.Left;
|
||||
int top = series.Center.Top;
|
||||
left = Width * left / 100;
|
||||
top = Height * top / 100;
|
||||
|
||||
angle.Center = new PointF(left, top);
|
||||
angle.Inner = Math.Min(Width, Height) * series.Radius.Inner / 200.0f;
|
||||
angle.Outer = Math.Min(Width, Height) * series.Radius.Outer / 200.0f;
|
||||
}
|
||||
|
||||
private class Angle
|
||||
{
|
||||
public float Start { get; set; }
|
||||
|
||||
public float Sweep { get; set; }
|
||||
|
||||
public float Inner { get; set; }
|
||||
|
||||
public float Outer { get; set; }
|
||||
|
||||
public PointF Center { get; set; }
|
||||
|
||||
public Angle(float start, float sweep, string text)
|
||||
{
|
||||
Start = start;
|
||||
Sweep = sweep;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public SizeF TextSize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -136,7 +136,7 @@ namespace Sunny.UI
|
||||
Color color = ChartStyle.SeriesColor[azIndex % ChartStyle.ColorCount];
|
||||
RectangleF rectx = new RectangleF(rect.X - 10, rect.Y - 10, rect.Width + 20, rect.Width + 20);
|
||||
g.FillPie(color, (ActivePieIndex == pieIndex && ActiveAzIndex == azIndex) ? rectx : rect, Angles[pieIndex][azIndex].Start - 90, Angles[pieIndex][azIndex].Sweep);
|
||||
Angles[pieIndex][azIndex].Size = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
|
||||
Angles[pieIndex][azIndex].TextSize = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,13 +177,14 @@ namespace Sunny.UI
|
||||
double az = MathEx.CalcAngle(e.Location, pf);
|
||||
for (int azIndex = 0; azIndex < PieOption.Series[pieIndex].Data.Count; azIndex++)
|
||||
{
|
||||
if (az >= Angles[pieIndex][azIndex].Start && az <= Angles[pieIndex][azIndex].Start + Angles[pieIndex][azIndex].Sweep)
|
||||
Angle angle = Angles[pieIndex][azIndex];
|
||||
if (az >= angle.Start && az <= angle.Start + angle.Sweep)
|
||||
{
|
||||
SetPieAndAzIndex(pieIndex, azIndex);
|
||||
if (tip.Text != Angles[pieIndex][azIndex].Text)
|
||||
if (tip.Text != angle.Text)
|
||||
{
|
||||
tip.Text = Angles[pieIndex][azIndex].Text;
|
||||
tip.Size = new Size((int)Angles[pieIndex][azIndex].Size.Width + 4, (int)Angles[pieIndex][azIndex].Size.Height + 4);
|
||||
tip.Text = angle.Text;
|
||||
tip.Size = new Size((int)angle.TextSize.Width + 4, (int)angle.TextSize.Height + 4);
|
||||
}
|
||||
|
||||
if (az >= 0 && az < 90)
|
||||
@ -207,7 +208,7 @@ namespace Sunny.UI
|
||||
tip.Top = e.Location.Y + 20;
|
||||
}
|
||||
|
||||
if (!tip.Visible) tip.Visible = Angles[pieIndex][azIndex].Text.IsValid();
|
||||
if (!tip.Visible) tip.Visible = angle.Text.IsValid();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -240,7 +241,7 @@ namespace Sunny.UI
|
||||
return new RectangleF(left - halfRadius, top - halfRadius, halfRadius * 2, halfRadius * 2);
|
||||
}
|
||||
|
||||
internal class Angle
|
||||
private class Angle
|
||||
{
|
||||
public float Start { get; set; }
|
||||
public float Sweep { get; set; }
|
||||
@ -254,7 +255,7 @@ namespace Sunny.UI
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public SizeF Size { get; set; }
|
||||
public SizeF TextSize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -28,13 +28,13 @@ namespace Sunny.UI
|
||||
public int SeriesCount => Series.Count;
|
||||
}
|
||||
|
||||
public class UIDoughnutPieOption : UIOption, IDisposable
|
||||
public class UIDoughnutOption : UIOption, IDisposable
|
||||
{
|
||||
public List<UIDoughnutPieSeries> Series = new List<UIDoughnutPieSeries>();
|
||||
public List<UIDoughnutSeries> Series = new List<UIDoughnutSeries>();
|
||||
|
||||
public UIPieToolTip ToolTip;
|
||||
|
||||
public void AddSeries(UIDoughnutPieSeries series)
|
||||
public void AddSeries(UIDoughnutSeries series)
|
||||
{
|
||||
Series.Clear();
|
||||
Series.Add(series);
|
||||
@ -72,6 +72,8 @@ namespace Sunny.UI
|
||||
|
||||
public readonly List<UIPieSeriesData> Data = new List<UIPieSeriesData>();
|
||||
|
||||
public UIPieSeriesLabel Label = new UIPieSeriesLabel();
|
||||
|
||||
public void AddData(string name, double value)
|
||||
{
|
||||
Data.Add(new UIPieSeriesData(name, value));
|
||||
@ -96,7 +98,7 @@ namespace Sunny.UI
|
||||
}
|
||||
}
|
||||
|
||||
public class UIDoughnutPieSeries : IDisposable
|
||||
public class UIDoughnutSeries : IDisposable
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
@ -108,6 +110,8 @@ namespace Sunny.UI
|
||||
|
||||
public readonly List<UIPieSeriesData> Data = new List<UIPieSeriesData>();
|
||||
|
||||
public UIPieSeriesLabel Label = new UIPieSeriesLabel();
|
||||
|
||||
public void AddData(string name, double value)
|
||||
{
|
||||
Data.Add(new UIPieSeriesData(name, value));
|
||||
@ -135,4 +139,20 @@ namespace Sunny.UI
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class UIPieSeriesLabel
|
||||
{
|
||||
public bool Show { get; set; } = false;
|
||||
|
||||
public UIPieSeriesLabelPosition Position { get; set; } = UIPieSeriesLabelPosition.Center;
|
||||
|
||||
public string Formatter { get; set; } = "{{b}}";
|
||||
}
|
||||
|
||||
public enum UIPieSeriesLabelPosition
|
||||
{
|
||||
Outside,
|
||||
Inside,
|
||||
Center
|
||||
}
|
||||
}
|
@ -715,7 +715,13 @@ namespace Sunny.UI
|
||||
|
||||
public TreeNode CreateChildNode(TreeNode parent, UIPage page)
|
||||
{
|
||||
return CreateChildNode(parent, new NavMenuItem(page));
|
||||
var childNode = CreateChildNode(parent, new NavMenuItem(page));
|
||||
if (page.Symbol > 0)
|
||||
{
|
||||
MenuHelper.SetSymbol(childNode, page.Symbol, page.SymbolSize);
|
||||
}
|
||||
|
||||
return childNode;
|
||||
}
|
||||
|
||||
public TreeNode CreateChildNode(TreeNode parent, NavMenuItem item)
|
||||
|
@ -470,12 +470,22 @@ namespace Sunny.UI
|
||||
return path;
|
||||
}
|
||||
|
||||
public static GraphicsPath CreateFanPath(this Graphics g, Point center, int d1, int d2, float startAngle, float sweepAngle)
|
||||
public static GraphicsPath CreateFanPath(this Graphics g, Point center, float d1, float d2, float startAngle, float sweepAngle)
|
||||
{
|
||||
return center.CreateFanPath(d1, d2, startAngle, sweepAngle);
|
||||
}
|
||||
|
||||
public static GraphicsPath CreateFanPath(this Point center, int d1, int d2, float startAngle, float sweepAngle)
|
||||
public static GraphicsPath CreateFanPath(this Graphics g, PointF center, float d1, float d2, float startAngle, float sweepAngle)
|
||||
{
|
||||
return center.CreateFanPath(d1, d2, startAngle, sweepAngle);
|
||||
}
|
||||
|
||||
public static GraphicsPath CreateFanPath(this Point center, float d1, float d2, float startAngle, float sweepAngle)
|
||||
{
|
||||
return new PointF(center.X,center.Y).CreateFanPath(d1,d2,startAngle,sweepAngle);
|
||||
}
|
||||
|
||||
public static GraphicsPath CreateFanPath(this PointF center, float d1, float d2, float startAngle, float sweepAngle)
|
||||
{
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
path.AddArc(center.X - d1, center.Y - d1, d1 * 2, d1 * 2, startAngle, sweepAngle);
|
||||
@ -490,14 +500,28 @@ namespace Sunny.UI
|
||||
g.DrawLine(color, center.X, center.Y - size, center.X, center.Y + size);
|
||||
}
|
||||
|
||||
public static void DrawFan(this Graphics g, Color color, Point center, int d1, int d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
public static void DrawFan(this Graphics g, Color color, Point center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
{
|
||||
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
|
||||
g.DrawPath(color, path, smooth);
|
||||
path.Dispose();
|
||||
}
|
||||
|
||||
public static void FillFan(this Graphics g, Color color, Point center, int d1, int d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
public static void DrawFan(this Graphics g, Color color, PointF center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
{
|
||||
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
|
||||
g.DrawPath(color, path, smooth);
|
||||
path.Dispose();
|
||||
}
|
||||
|
||||
public static void FillFan(this Graphics g, Color color, Point center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
{
|
||||
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
|
||||
g.FillPath(color, path, smooth);
|
||||
path.Dispose();
|
||||
}
|
||||
|
||||
public static void FillFan(this Graphics g, Color color, PointF center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
|
||||
{
|
||||
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
|
||||
g.FillPath(color, path, smooth);
|
||||
|
@ -59,6 +59,9 @@
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Charts\UIChartStyle.cs" />
|
||||
<Compile Include="Charts\UIDoughnutChart.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Charts\UIOption.cs" />
|
||||
<Compile Include="Charts\UIPieChartOption.cs" />
|
||||
<Compile Include="Controls\Color\UIColorBar.cs">
|
||||
|
Loading…
x
Reference in New Issue
Block a user