diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll index d898052d..bb37fc13 100644 Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb index 4458eb12..0befdad4 100644 Binary files a/Bin/SunnyUI.pdb and b/Bin/SunnyUI.pdb differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe index 0aff5573..b2f606d0 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe and b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.dll b/SunnyUI.Demo/Bin/SunnyUI.dll index d898052d..bb37fc13 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs b/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs new file mode 100644 index 00000000..8764beac --- /dev/null +++ b/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs @@ -0,0 +1,153 @@ +namespace Sunny.UI.Demo.Charts +{ + partial class FDoughnutChart + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; + } +} \ No newline at end of file diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.cs b/SunnyUI.Demo/Charts/FDoughnutChart.cs new file mode 100644 index 00000000..e3e55a96 --- /dev/null +++ b/SunnyUI.Demo/Charts/FDoughnutChart.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.resx b/SunnyUI.Demo/Charts/FDoughnutChart.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/SunnyUI.Demo/Charts/FDoughnutChart.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SunnyUI.Demo/Controls/FOther.Designer.cs b/SunnyUI.Demo/Controls/FOther.Designer.cs index e367588e..81c5bd40 100644 --- a/SunnyUI.Demo/Controls/FOther.Designer.cs +++ b/SunnyUI.Demo/Controls/FOther.Designer.cs @@ -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; diff --git a/SunnyUI.Demo/FMain.cs b/SunnyUI.Demo/FMain.cs index 9294390e..cf58a10e 100644 --- a/SunnyUI.Demo/FMain.cs +++ b/SunnyUI.Demo/FMain.cs @@ -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(); diff --git a/SunnyUI.Demo/SunnyUI.Demo.csproj b/SunnyUI.Demo/SunnyUI.Demo.csproj index 1ffe9e22..45c8e4f4 100644 --- a/SunnyUI.Demo/SunnyUI.Demo.csproj +++ b/SunnyUI.Demo/SunnyUI.Demo.csproj @@ -53,6 +53,12 @@ FBarChart.cs + + Form + + + FDoughnutChart.cs + Form @@ -286,6 +292,9 @@ FBarChart.cs + + FDoughnutChart.cs + FAvatar.cs diff --git a/SunnyUI/Charts/UIDoughnutChart.cs b/SunnyUI/Charts/UIDoughnutChart.cs new file mode 100644 index 00000000..9d0b206a --- /dev/null +++ b/SunnyUI/Charts/UIDoughnutChart.cs @@ -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()); + + 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 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> Angles = new ConcurrentDictionary>(); + + [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; } + } + } +} \ No newline at end of file diff --git a/SunnyUI/Charts/UIPieChart.cs b/SunnyUI/Charts/UIPieChart.cs index b1ae2618..0083b8c5 100644 --- a/SunnyUI/Charts/UIPieChart.cs +++ b/SunnyUI/Charts/UIPieChart.cs @@ -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; } } } } \ No newline at end of file diff --git a/SunnyUI/Charts/UIPieChartOption.cs b/SunnyUI/Charts/UIPieChartOption.cs index 3e983670..e5c1a611 100644 --- a/SunnyUI/Charts/UIPieChartOption.cs +++ b/SunnyUI/Charts/UIPieChartOption.cs @@ -28,13 +28,13 @@ namespace Sunny.UI public int SeriesCount => Series.Count; } - public class UIDoughnutPieOption : UIOption, IDisposable + public class UIDoughnutOption : UIOption, IDisposable { - public List Series = new List(); + public List Series = new List(); 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 Data = new List(); + 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 Data = new List(); + 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 + } } \ No newline at end of file diff --git a/SunnyUI/Controls/UINavMenu.cs b/SunnyUI/Controls/UINavMenu.cs index 4288178a..c0e2f78f 100644 --- a/SunnyUI/Controls/UINavMenu.cs +++ b/SunnyUI/Controls/UINavMenu.cs @@ -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) diff --git a/SunnyUI/Static/UGDI.cs b/SunnyUI/Static/UGDI.cs index 1e5cfdad..d8e5c32b 100644 --- a/SunnyUI/Static/UGDI.cs +++ b/SunnyUI/Static/UGDI.cs @@ -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); diff --git a/SunnyUI/SunnyUI.csproj b/SunnyUI/SunnyUI.csproj index 7fdf1a41..7cd46378 100644 --- a/SunnyUI/SunnyUI.csproj +++ b/SunnyUI/SunnyUI.csproj @@ -59,6 +59,9 @@ Component + + Component +