diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll index faaf803b..3191f6db 100644 Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb index 2abecb18..95f9c3d7 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 a3ed4f2f..0c418460 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 faaf803b..3191f6db 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ diff --git a/SunnyUI.Demo/Charts/FPieChart.Designer.cs b/SunnyUI.Demo/Charts/FPieChart.Designer.cs index cf2952b7..ad6f321d 100644 --- a/SunnyUI.Demo/Charts/FPieChart.Designer.cs +++ b/SunnyUI.Demo/Charts/FPieChart.Designer.cs @@ -70,7 +70,6 @@ this.PieChart.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54))))); this.PieChart.Location = new System.Drawing.Point(26, 46); this.PieChart.Name = "PieChart"; - this.PieChart.Option = null; this.PieChart.RectSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.None; this.PieChart.Size = new System.Drawing.Size(687, 399); this.PieChart.TabIndex = 20; diff --git a/SunnyUI.Demo/Charts/FPieChart.cs b/SunnyUI.Demo/Charts/FPieChart.cs index 00a90162..6ec9993f 100644 --- a/SunnyUI.Demo/Charts/FPieChart.cs +++ b/SunnyUI.Demo/Charts/FPieChart.cs @@ -1,4 +1,6 @@ -namespace Sunny.UI.Demo.Controls +using System; + +namespace Sunny.UI.Demo.Controls { public partial class FPieChart : UITitlePage { @@ -22,9 +24,11 @@ PieChart.ChartStyleType = UIChartStyleType.Dark; } + + private void uiSymbolButton1_Click(object sender, System.EventArgs e) { - var option = new UIOption(); + var option = new UIPieOption(); //设置Title option.Title = new UITitle(); @@ -33,11 +37,11 @@ option.Title.Left = UILeftAlignment.Center; //设置ToolTip - option.ToolTip = new UIToolTip(); + option.ToolTip = new UIPieToolTip(); //设置Legend - option.Legend = new UILegend(); - option.Legend.Orient = Orient.Vertical; + option.Legend = new UIPieLegend(); + option.Legend.Orient = UIOrient.Vertical; option.Legend.Top = UITopAlignment.Top; option.Legend.Left = UILeftAlignment.Left; @@ -50,9 +54,8 @@ option.Legend.AddData("2020-05-25"); //设置Series - var series = new UISeries(); + var series = new UIPieSeries(); series.Name = "Star count"; - series.Type = UISeriesType.Pie; series.Center = new UICenter(50, 55); series.Radius = 70; diff --git a/SunnyUI.Demo/Forms/FEdit.Designer.cs b/SunnyUI.Demo/Forms/FEdit.Designer.cs index def2f599..ec829edc 100644 --- a/SunnyUI.Demo/Forms/FEdit.Designer.cs +++ b/SunnyUI.Demo/Forms/FEdit.Designer.cs @@ -52,10 +52,13 @@ // edtName // this.edtName.Cursor = System.Windows.Forms.Cursors.IBeam; + this.edtName.EnterAsTab = true; this.edtName.FillColor = System.Drawing.Color.White; this.edtName.Font = new System.Drawing.Font("微软雅黑", 12F); this.edtName.Location = new System.Drawing.Point(150, 55); this.edtName.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.edtName.Maximum = 2147483647D; + this.edtName.Minimum = -2147483648D; this.edtName.Name = "edtName"; this.edtName.Padding = new System.Windows.Forms.Padding(5); this.edtName.Size = new System.Drawing.Size(340, 29); @@ -113,6 +116,8 @@ this.edtAge.Font = new System.Drawing.Font("微软雅黑", 12F); this.edtAge.Location = new System.Drawing.Point(150, 135); this.edtAge.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.edtAge.Maximum = 2147483647D; + this.edtAge.Minimum = -2147483648D; this.edtAge.Name = "edtAge"; this.edtAge.Padding = new System.Windows.Forms.Padding(5); this.edtAge.Size = new System.Drawing.Size(170, 29); @@ -187,6 +192,8 @@ this.edtDate.Name = "edtDate"; this.edtDate.Padding = new System.Windows.Forms.Padding(0, 0, 30, 0); this.edtDate.Size = new System.Drawing.Size(170, 29); + this.edtDate.SymbolDropDown = 61555; + this.edtDate.SymbolNormal = 61555; this.edtDate.TabIndex = 5; this.edtDate.Text = "2020-05-08"; this.edtDate.TextAlignment = System.Drawing.ContentAlignment.MiddleLeft; @@ -199,6 +206,8 @@ this.edtAddress.Font = new System.Drawing.Font("微软雅黑", 12F); this.edtAddress.Location = new System.Drawing.Point(150, 254); this.edtAddress.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.edtAddress.Maximum = 2147483647D; + this.edtAddress.Minimum = -2147483648D; this.edtAddress.Name = "edtAddress"; this.edtAddress.Padding = new System.Windows.Forms.Padding(5); this.edtAddress.Size = new System.Drawing.Size(340, 29); diff --git a/SunnyUI/Charts/UIBarChart.cs b/SunnyUI/Charts/UIBarChart.cs new file mode 100644 index 00000000..29bd2558 --- /dev/null +++ b/SunnyUI/Charts/UIBarChart.cs @@ -0,0 +1,89 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using Sunny.UI.Charts; + +namespace Sunny.UI +{ + [ToolboxItem(false)] + public class UIBarChart : UIChart + { + protected override void CalcData(UIOption option) + { + Bars.Clear(); + UIBarOption o = (UIBarOption)option; + if (o == null || o.Series == null || o.Series.Count == 0) return; + + DrawOrigin = new Point(PieOption.Grid.Left,Height - PieOption.Grid.Bottom); + DrawSize = new Size(Width- PieOption.Grid.Left- PieOption.Grid.Right, + Height -PieOption.Grid.Top-PieOption.Grid.Bottom); + + if (DrawSize.Width<=0 || DrawSize.Height<=0) return; + if (o.XAxis.Data.Count==0) return; + + DrawBarWidth = DrawSize.Width / o.XAxis.Data.Count; + } + + private Point DrawOrigin; + private Size DrawSize; + private int DrawBarWidth; + private readonly ConcurrentDictionary Bars = new ConcurrentDictionary(); + + [Browsable(false)] + private UIBarOption PieOption + { + get + { + UIOption option = Option ?? EmptyOption; + UIBarOption o = (UIBarOption)option; + return o; + } + } + + protected override void CreateEmptyOption() + { + if (emptyOption != null) return; + + UIBarOption option = new UIBarOption(); + option.Title = new UITitle(); + option.Title = new UITitle(); + option.Title.Text = "SunnyUI"; + option.Title.SubText = "BarChart"; + + var series = new UIBarSeries(); + series.Name = "柱状图"; + series.AddData(1); + series.AddData(5); + series.AddData(2); + series.AddData(4); + series.AddData(3); + + option.XAxis.Data.Add("Mon"); + option.XAxis.Data.Add("Tue"); + option.XAxis.Data.Add("Wed"); + option.XAxis.Data.Add("Thu"); + option.XAxis.Data.Add("Fri"); + + option.Series.Add(series); + emptyOption = option; + } + + private void DrawTitle(Graphics g, UITitle title) + { + } + + private void DrawSeries(Graphics g, UIPieOption o, List series) + { + } + + private void DrawLegend(Graphics g, UIPieLegend legend) + { + } + + internal class BarInfo + { + public Rectangle Rect { get; set; } + } + } +} \ No newline at end of file diff --git a/SunnyUI/Charts/UIBarChartOption.cs b/SunnyUI/Charts/UIBarChartOption.cs new file mode 100644 index 00000000..a8995352 --- /dev/null +++ b/SunnyUI/Charts/UIBarChartOption.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; + +namespace Sunny.UI.Charts +{ + public class UIBarOption : UIOption, IDisposable + { + public UITitle Title; + + public UICategoryAxis XAxis { get; set; } = new UICategoryAxis(); + + public UIValueAxis YAxis { get; set; } = new UIValueAxis(); + + public List Series = new List(); + + public UIChartGrid Grid = new UIChartGrid(); + + //public UIPieLegend Legend; + + //public UIPieToolTip ToolTip; + + + public void AddSeries(UIBarSeries series) + { + Series.Add(series); + } + + public void Dispose() + { + foreach (var series in Series) + { + series?.Dispose(); + } + + Series.Clear(); + } + + public int SeriesCount => Series.Count; + } + + public class UIAxis + { + public string Name { get; set; } + + public UIAxisType Type { get; set; } + + /// + /// 坐标轴的分割段数,需要注意的是这个分割段数只是个预估值 + /// 最后实际显示的段数会在这个基础上根据分割后坐标轴刻度显示的易读程度作调整。 + /// 在类目轴中无效。 + /// + public int SplitNumber { get; set; } = 5; + } + + public class UICategoryAxis : UIAxis + { + public UICategoryAxis() + { + Type = UIAxisType.Category; + } + + public List Data = new List(); + + public void Clear() + { + Data.Clear(); + } + } + + public class UIValueAxis : UIAxis + { + public UIValueAxis() + { + Type = UIAxisType.Value; + } + } + + public class UIBarSeries : IDisposable + { + public string Name { get; set; } + + public UISeriesType Type => UISeriesType.Bar; + + public List Data = new List(); + + public void AddData(double value) + { + Data.Add(value); + } + + public void Dispose() + { + Data.Clear(); + } + } +} \ No newline at end of file diff --git a/SunnyUI/Charts/UIChart.cs b/SunnyUI/Charts/UIChart.cs index 3fc57a3a..1562bb3d 100644 --- a/SunnyUI/Charts/UIChart.cs +++ b/SunnyUI/Charts/UIChart.cs @@ -19,7 +19,6 @@ * 2020-06-06: V2.2.5 增加文件说明 ******************************************************************************/ -using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; @@ -60,22 +59,6 @@ namespace Sunny.UI tip.Visible = false; } - private int decimalNumber; - - [DefaultValue(0),Description("显示数据格式化小数点后位数")] - public int DecimalNumber - { - get => decimalNumber; - set - { - if (decimalNumber != value) - { - decimalNumber = value; - Invalidate(); - } - } - } - protected readonly UITransparentPanel tip = new UITransparentPanel(); private UIChartStyleType chartStyleType = UIChartStyleType.Plain; @@ -154,6 +137,7 @@ namespace Sunny.UI protected UIOption emptyOption; + [Browsable(false)] protected UIOption EmptyOption { get @@ -171,7 +155,11 @@ namespace Sunny.UI protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - DrawOption(e.Graphics, Option ?? EmptyOption); + DrawOption(e.Graphics); + } + + protected virtual void DrawOption(Graphics g) + { } protected virtual void CreateEmptyOption() @@ -180,26 +168,6 @@ namespace Sunny.UI protected UIChartStyle ChartStyle => UIChartStyles.GetChartStyle(ChartStyleType); - private void DrawOption(Graphics g, UIOption o) - { - if (o == null) return; - if (o.Title != null) DrawTitle(g, o.Title); - if (o.Series.Count > 0) DrawSeries(g,o, o.Series); - if (o.Legend != null) DrawLegend(g, o.Legend); - } - - protected virtual void DrawTitle(Graphics g, UITitle title) - { - } - - protected virtual void DrawSeries(Graphics g,UIOption o, List series) - { - } - - protected virtual void DrawLegend(Graphics g, UILegend legend) - { - } - public override void SetStyleColor(UIBaseStyle uiColor) { base.SetStyleColor(uiColor); diff --git a/SunnyUI/Charts/UIChartStyle.cs b/SunnyUI/Charts/UIChartStyle.cs new file mode 100644 index 00000000..8d82eb93 --- /dev/null +++ b/SunnyUI/Charts/UIChartStyle.cs @@ -0,0 +1,90 @@ +using System.Drawing; + +namespace Sunny.UI +{ + public class UIChartStyle + { + public virtual Color BackColor => Color.FromArgb(244, 244, 244); + + public virtual Color ForeColor => Color.FromArgb(54, 54, 54); + + public int ColorCount => 11; + + public virtual Color[] SeriesColor + { + get + { + return new[] + { + Color.FromArgb(241,42,38), + Color.FromArgb(43,71,85), + Color.FromArgb(69,161,168), + Color.FromArgb(229,125,96), + Color.FromArgb(125,200,175), + Color.FromArgb(101,159,132), + Color.FromArgb(216,130,27), + Color.FromArgb(195,160,152), + Color.FromArgb(109,112,115), + Color.FromArgb(79,101,112), + Color.FromArgb(193,204,211) + }; + } + } + } + + public class UIDefaultChartStyle : UIChartStyle + { + } + + public class UILightChartStyle : UIChartStyle + { + public override Color[] SeriesColor + { + get + { + return new[] + { + Color.FromArgb(0,163,219), + Color.FromArgb(0,199,235), + Color.FromArgb(0,227,230), + Color.FromArgb(131,232,187), + Color.FromArgb(255,217,91), + Color.FromArgb(255,153,120), + Color.FromArgb(255,104,139), + Color.FromArgb(245,89,168), + Color.FromArgb(247,139,205), + Color.FromArgb(241,185,242), + Color.FromArgb(156,149,245) + }; + } + } + } + + public class UIDarkChartStyle : UIChartStyle + { + public override Color BackColor => Color.FromArgb(54, 54, 54); + + public override Color ForeColor => Color.FromArgb(239, 239, 239); + + public override Color[] SeriesColor + { + get + { + return new[] + { + Color.FromArgb(242,99,95), + Color.FromArgb(103,154,160), + Color.FromArgb(246,152,130), + Color.FromArgb(122,194,170), + Color.FromArgb(255,119,74), + Color.FromArgb(244,220,120), + Color.FromArgb(98,163,117), + Color.FromArgb(83,186,189), + Color.FromArgb(105,137,170), + Color.FromArgb(124,203,143), + Color.FromArgb(255,154,59) + }; + } + } + } +} \ No newline at end of file diff --git a/SunnyUI/Charts/UIOption.cs b/SunnyUI/Charts/UIOption.cs index 89a8a2af..cca8542f 100644 --- a/SunnyUI/Charts/UIOption.cs +++ b/SunnyUI/Charts/UIOption.cs @@ -20,68 +20,35 @@ ******************************************************************************/ using System; -using System.Collections.Generic; -using System.Drawing; namespace Sunny.UI { - public class UIOption : IDisposable + public abstract class UIOption { - public UITitle Title; - - public List Series = new List(); - - public UILegend Legend; - - public UIToolTip ToolTip; - - public void AddSeries(UISeries series) - { - Series.Add(series); - } - - public void Dispose() - { - foreach (var series in Series) - { - series?.Dispose(); - } - - Series.Clear(); - } - - public int SeriesCount => Series.Count; } - public class UIToolTip + public class UIChartGrid { - public string formatter { get; set; } = "{{a}}" + '\n' + "{{b}} : {{c}} ({{d}}%)"; + public int Left { get; set; } = 80; + public int Right { get; set; } = 80; + public int Top { get; set; } = 40; + public int Bottom { get; set; } = 40; } - public class UILegend - { - public UILeftAlignment Left { get; set; } = UILeftAlignment.Center; - - public UITopAlignment Top { get; set; } = UITopAlignment.Top; - - public Orient Orient { get; set; } = Orient.Vertical; - - public readonly List Data = new List(); - - public int DataCount => Data.Count; - - public void AddData(string data) - { - Data.Add(data); - } - } - - public enum Orient + public enum UIOrient { Vertical, Horizontal } + public enum UIAxisType + { + Value, + Category, + Time, + Log + } + public class UITitle { public string Text { get; set; } = "UIPieChart"; @@ -107,29 +74,6 @@ namespace Sunny.UI Bottom } - public class UISeries : IDisposable - { - public string Name { get; set; } - - public UISeriesType Type { get; set; } - - public int Radius { get; set; } = 50; - - public UICenter Center { get; set; } = new UICenter(50, 50); - - public readonly List Data = new List(); - - public void AddData(string name, double value) - { - Data.Add(new UISeriesData(name, value)); - } - - public void Dispose() - { - Data.Clear(); - } - } - public class UICenter { public int Left { get; set; } @@ -147,23 +91,6 @@ namespace Sunny.UI } } - public class UISeriesData - { - public string Name { get; set; } - - public double Value { get; set; } - - public UISeriesData() - { - } - - public UISeriesData(string name, double value) - { - Name = name; - Value = value; - } - } - public enum UISeriesType { Pie, @@ -194,89 +121,94 @@ namespace Sunny.UI } } - public class UIChartStyle + public static class UIChartHelper { - public virtual Color BackColor => Color.FromArgb(244, 244, 244); - - public virtual Color ForeColor => Color.FromArgb(54, 54, 54); - - public int ColorCount => 11; - - public virtual Color[] SeriesColor + /// + /// 计算刻度 + /// 起始值必须小于结束值 + /// + /// 起始值 + /// 结束值 + /// 期望刻度数量,实际数接近此数 + /// 刻度起始值,须乘以间隔使用 + /// 刻度结束值,须乘以间隔使用 + /// 刻度间隔 + public static void CalcDegreeScale(double start, double end, int expect_num, + out int degree_start, out int degree_end, out double degree_gap) { - get + if (start >= end) { - return new[] - { - Color.FromArgb(241,42,38), - Color.FromArgb(43,71,85), - Color.FromArgb(69,161,168), - Color.FromArgb(229,125,96), - Color.FromArgb(125,200,175), - Color.FromArgb(101,159,132), - Color.FromArgb(216,130,27), - Color.FromArgb(195,160,152), - Color.FromArgb(109,112,115), - Color.FromArgb(79,101,112), - Color.FromArgb(193,204,211) - }; + throw new Exception("起始值必须小于结束值"); } + + double differ = end - start; + double differ_gap = differ / (expect_num - 1); //35, 4.6, 0.27 + + double exponent = Math.Log10(differ_gap) - 1; //0.54, -0.34, -1.57 + int _exponent = (int)exponent; //0, 0=>-1, -1=>-2 + if (exponent < 0 && Math.Abs(exponent) > 1e-8) + { + _exponent--; + } + + int step = (int)(differ_gap / Math.Pow(10, _exponent)); //35, 46, 27 + int[] fix_steps = new int[] { 10, 20, 25, 50, 100 }; + int fix_step = 10; //25, 50, 25 + for (int i = fix_steps.Length - 1; i >= 1; i--) + { + if (step > (fix_steps[i] + fix_steps[i - 1]) / 2) + { + fix_step = fix_steps[i]; + break; + } + } + + degree_gap = fix_step * Math.Pow(10, _exponent); //25, 5, 0.25 + + double start1 = start / degree_gap; + int start2 = (int)start1; + if (start1 < 0 && Math.Abs(start1 - start2) > 1e-8) + { + start2--; + } + + degree_start = start2; + + double end1 = end / degree_gap; + int end2 = (int)end1; + if (end1 >= 0 && Math.Abs(end1 - end2) > 1e-8) + { + end2++; + } + + degree_end = end2; } - } - public class UIDefaultChartStyle : UIChartStyle - { - } - - public class UILightChartStyle : UIChartStyle - { - public override Color[] SeriesColor + /// + /// 计算刻度 + /// 起始值必须小于结束值 + /// + /// 起始值 + /// 结束值 + /// 期望刻度数量,实际数接近此数 + /// 刻度列表 + public static double[] CalcDegreeScale(double start, double end, int expect_num) { - get + if (start >= end) { - return new[] - { - Color.FromArgb(0,163,219), - Color.FromArgb(0,199,235), - Color.FromArgb(0,227,230), - Color.FromArgb(131,232,187), - Color.FromArgb(255,217,91), - Color.FromArgb(255,153,120), - Color.FromArgb(255,104,139), - Color.FromArgb(245,89,168), - Color.FromArgb(247,139,205), - Color.FromArgb(241,185,242), - Color.FromArgb(156,149,245) - }; + throw new Exception("起始值必须小于结束值"); } - } - } - public class UIDarkChartStyle : UIChartStyle - { - public override Color BackColor => Color.FromArgb(54, 54, 54); + CalcDegreeScale(start, end, expect_num, out int degree_start, out int degree_end, + out double degree_gap); - public override Color ForeColor => Color.FromArgb(239, 239, 239); - - public override Color[] SeriesColor - { - get + double[] list = new double[degree_end - degree_start + 1]; + for (int i = degree_start; i <= degree_end; i++) { - return new[] - { - Color.FromArgb(242,99,95), - Color.FromArgb(103,154,160), - Color.FromArgb(246,152,130), - Color.FromArgb(122,194,170), - Color.FromArgb(255,119,74), - Color.FromArgb(244,220,120), - Color.FromArgb(98,163,117), - Color.FromArgb(83,186,189), - Color.FromArgb(105,137,170), - Color.FromArgb(124,203,143), - Color.FromArgb(255,154,59) - }; + list[i - degree_start] = i * degree_gap; } + + return list; } } } \ No newline at end of file diff --git a/SunnyUI/Charts/UIPieChart.cs b/SunnyUI/Charts/UIPieChart.cs index 683dd7b1..a84a2d66 100644 --- a/SunnyUI/Charts/UIPieChart.cs +++ b/SunnyUI/Charts/UIPieChart.cs @@ -35,15 +35,14 @@ namespace Sunny.UI { if (emptyOption != null) return; - emptyOption = new UIOption(); + UIPieOption option = new UIPieOption(); - emptyOption.Title = new UITitle(); - emptyOption.Title.Text = "SunnyUI"; - emptyOption.Title.SubText = "PieChart"; + option.Title = new UITitle(); + option.Title.Text = "SunnyUI"; + option.Title.SubText = "PieChart"; - var series = new UISeries(); + var series = new UIPieSeries(); series.Name = "饼状图"; - series.Type = UISeriesType.Pie; series.Center = new UICenter(50, 55); series.Radius = 70; for (int i = 0; i < 5; i++) @@ -51,10 +50,19 @@ namespace Sunny.UI series.AddData("Data" + i, (i + 1) * 20); } - emptyOption.Series.Add(series); + option.Series.Add(series); + emptyOption = option; } - protected override void DrawTitle(Graphics g, UITitle title) + protected override void DrawOption(Graphics g) + { + if (PieOption == null) return; + if (PieOption.Title != null) DrawTitle(g, PieOption.Title); + if (PieOption.Series.Count > 0) DrawSeries(g, PieOption.Series); + if (PieOption.Legend != null) DrawLegend(g, PieOption.Legend); + } + + private void DrawTitle(Graphics g, UITitle title) { if (title == null) return; SizeF sf = g.MeasureString(title.Text, Font); @@ -93,17 +101,17 @@ namespace Sunny.UI g.DrawString(title.SubText, subFont, ChartStyle.ForeColor, left, top); } - protected override void CalcData(UIOption o) + protected override void CalcData(UIOption option) { Angles.Clear(); + UIPieOption o = (UIPieOption)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); + template = new UITemplate(o.ToolTip.Formatter); } - for (int pieIndex = 0; pieIndex < o.Series.Count; pieIndex++) { var pie = o.Series[pieIndex]; @@ -130,14 +138,14 @@ namespace Sunny.UI { template.Set("a", pie.Name); template.Set("b", pie.Data[i].Name); - template.Set("c", pie.Data[i].Value.ToString("F" + DecimalNumber)); + 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("F" + DecimalNumber) + "(" + percent.ToString("F2") + "%)"; + text = pie.Data[i].Name + " : " + pie.Data[i].Value.ToString("F2") + "(" + percent.ToString("F2") + "%)"; if (pie.Name.IsValid()) text = pie.Name + '\n' + text; } } @@ -148,7 +156,7 @@ namespace Sunny.UI } } - protected override void DrawSeries(Graphics g, UIOption o, List series) + private void DrawSeries(Graphics g, List series) { if (series == null || series.Count == 0) return; @@ -168,7 +176,7 @@ namespace Sunny.UI private readonly ConcurrentDictionary> Angles = new ConcurrentDictionary>(); - protected override void DrawLegend(Graphics g, UILegend legend) + private void DrawLegend(Graphics g, UIPieLegend legend) { if (legend == null) return; @@ -191,7 +199,7 @@ namespace Sunny.UI float top = 0; float left = 0; - if (legend.Orient == Orient.Horizontal) + if (legend.Orient == UIOrient.Horizontal) { if (legend.Left == UILeftAlignment.Left) left = TextInterval; if (legend.Left == UILeftAlignment.Center) left = (Width - totalWidth) / 2.0f; @@ -202,7 +210,7 @@ namespace Sunny.UI if (legend.Top == UITopAlignment.Bottom) top = Height - oneHeight - TextInterval; } - if (legend.Orient == Orient.Vertical) + if (legend.Orient == UIOrient.Vertical) { if (legend.Left == UILeftAlignment.Left) left = TextInterval; if (legend.Left == UILeftAlignment.Center) left = (Width - maxWidth) / 2.0f - 10; @@ -219,7 +227,7 @@ namespace Sunny.UI { var data = legend.Data[i]; SizeF sf = g.MeasureString(data, LegendFont); - if (legend.Orient == Orient.Horizontal) + if (legend.Orient == UIOrient.Horizontal) { g.FillRoundRectangle(ChartStyle.SeriesColor[i % ChartStyle.ColorCount], (int)startleft, (int)top + 1, 18, (int)oneHeight - 2, 5); g.DrawString(data, LegendFont, ChartStyle.ForeColor, startleft + 20, top); @@ -227,7 +235,7 @@ namespace Sunny.UI startleft += sf.Width; } - if (legend.Orient == Orient.Vertical) + if (legend.Orient == UIOrient.Vertical) { g.FillRoundRectangle(ChartStyle.SeriesColor[i % ChartStyle.ColorCount], (int)left, (int)starttop + 1, 18, (int)oneHeight - 2, 5); g.DrawString(data, LegendFont, ChartStyle.ForeColor, left + 20, starttop); @@ -236,27 +244,37 @@ namespace Sunny.UI } } + [Browsable(false)] + private UIPieOption PieOption + { + get + { + UIOption option = Option ?? EmptyOption; + UIPieOption o = (UIPieOption)option; + return o; + } + } + protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); - UIOption option = Option ?? EmptyOption; - if (option.SeriesCount == 0) + if (PieOption.SeriesCount == 0) { SetPieAndAzIndex(-1, -1); return; } - for (int pieIndex = 0; pieIndex < option.SeriesCount; pieIndex++) + for (int pieIndex = 0; pieIndex < PieOption.SeriesCount; pieIndex++) { - RectangleF rect = GetSeriesRect(option.Series[pieIndex]); + RectangleF rect = GetSeriesRect(PieOption.Series[pieIndex]); if (!e.Location.InRect(rect)) continue; PointF pf = new PointF(rect.Left + rect.Width / 2.0f, rect.Top + rect.Height / 2.0f); if (MathEx.CalcDistance(e.Location, pf) * 2 > rect.Width) continue; double az = MathEx.CalcAngle(e.Location, pf); - for (int azIndex = 0; azIndex < option.Series[pieIndex].Data.Count; azIndex++) + 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) { @@ -311,7 +329,7 @@ namespace Sunny.UI } } - private RectangleF GetSeriesRect(UISeries series) + private RectangleF GetSeriesRect(UIPieSeries series) { int left = series.Center.Left; int top = series.Center.Top; @@ -321,7 +339,7 @@ namespace Sunny.UI return new RectangleF(left - halfRadius, top - halfRadius, halfRadius * 2, halfRadius * 2); } - public class Angle + internal class Angle { public float Start { get; set; } public float Sweep { get; set; } diff --git a/SunnyUI/Charts/UIPieChartOption.cs b/SunnyUI/Charts/UIPieChartOption.cs new file mode 100644 index 00000000..b1dd2696 --- /dev/null +++ b/SunnyUI/Charts/UIPieChartOption.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; + +namespace Sunny.UI +{ + public class UIPieOption : UIOption, IDisposable + { + public UITitle Title; + + public List Series = new List(); + + public UIPieLegend Legend; + + public UIPieToolTip ToolTip; + + public void AddSeries(UIPieSeries series) + { + Series.Clear(); + Series.Add(series); + } + + public void Dispose() + { + foreach (var series in Series) + { + series?.Dispose(); + } + + Series.Clear(); + } + + public int SeriesCount => Series.Count; + } + + public class UIDoughnutPieOption : UIOption, IDisposable + { + public UITitle Title; + + public List Series = new List(); + + public UIPieLegend Legend; + + public UIPieToolTip ToolTip; + + public void AddSeries(UIDoughnutPieSeries series) + { + Series.Clear(); + Series.Add(series); + } + + public void Dispose() + { + foreach (var series in Series) + { + series?.Dispose(); + } + + Series.Clear(); + } + + public int SeriesCount => Series.Count; + } + + public class UIPieToolTip + { + public string Formatter { get; set; } = "{{a}}" + '\n' + "{{b}} : {{c}} ({{d}}%)"; + + public string ValueFormat { get; set; } = "F0"; + } + + public class UIPieLegend + { + public UILeftAlignment Left { get; set; } = UILeftAlignment.Center; + + public UITopAlignment Top { get; set; } = UITopAlignment.Top; + + public UIOrient Orient { get; set; } = UIOrient.Vertical; + + public readonly List Data = new List(); + + public int DataCount => Data.Count; + + public void AddData(string data) + { + Data.Add(data); + } + } + + public class UIPieSeries : IDisposable + { + public string Name { get; set; } + + public UISeriesType Type => UISeriesType.Pie; + + public int Radius { get; set; } = 70; + + public UICenter Center { get; set; } = new UICenter(50, 50); + + public readonly List Data = new List(); + + public void AddData(string name, double value) + { + Data.Add(new UIPieSeriesData(name, value)); + } + + public void Dispose() + { + Data.Clear(); + } + } + + public class RadiusInOut + { + public int Inner { get; set; } + + public int Outer { get; set; } + + public RadiusInOut(int inner,int outer) + { + Inner = inner; + Outer = outer; + } + } + + public class UIDoughnutPieSeries : IDisposable + { + public string Name { get; set; } + + public UISeriesType Type { get; set; } + + public RadiusInOut Radius { get; set; } = new RadiusInOut(50,70); + + public UICenter Center { get; set; } = new UICenter(50, 50); + + public readonly List Data = new List(); + + public void AddData(string name, double value) + { + Data.Add(new UIPieSeriesData(name, value)); + } + + public void Dispose() + { + Data.Clear(); + } + } + + public class UIPieSeriesData + { + public string Name { get; set; } + + public double Value { get; set; } + + public UIPieSeriesData() + { + } + + public UIPieSeriesData(string name, double value) + { + Name = name; + Value = value; + } + } +} \ No newline at end of file diff --git a/SunnyUI/Controls/UITextBox.cs b/SunnyUI/Controls/UITextBox.cs index 6315c5c7..5f5647ff 100644 --- a/SunnyUI/Controls/UITextBox.cs +++ b/SunnyUI/Controls/UITextBox.cs @@ -25,7 +25,6 @@ using System.Collections; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; -using System.Drawing.Drawing2D; using System.Windows.Forms; namespace Sunny.UI @@ -86,7 +85,7 @@ namespace Sunny.UI private void OnMouseWheel(object sender, MouseEventArgs e) { base.OnMouseWheel(e); - if (bar!=null && bar.Visible && edit!=null) + if (bar != null && bar.Visible && edit != null) { var si = ScrollBarInfo.GetInfo(edit.Handle); if (e.Delta > 10) @@ -509,7 +508,6 @@ namespace Sunny.UI edit.Paste(text); } - internal class TextBoxAutoCompleteSourceConverter : EnumConverter { public TextBoxAutoCompleteSourceConverter(Type type) : base(type) @@ -541,6 +539,13 @@ namespace Sunny.UI set => edit.AcceptsTab = value; } + [DefaultValue(false)] + public bool EnterAsTab + { + get => edit.EnterAsTab; + set => edit.EnterAsTab = value; + } + [DefaultValue(true)] public bool ShortcutsEnabled { diff --git a/SunnyUI/SunnyUI.csproj b/SunnyUI/SunnyUI.csproj index 07cd9455..0ba4b3a9 100644 --- a/SunnyUI/SunnyUI.csproj +++ b/SunnyUI/SunnyUI.csproj @@ -51,10 +51,16 @@ + + Component + + Component + + Component diff --git a/Updates.txt b/Updates.txt index 54800027..e89d836c 100644 --- a/Updates.txt +++ b/Updates.txt @@ -1,5 +1,9 @@ + ӣ - ɾ * ޸ +2020.06.14 +* عͼؼ׼UIBarChart +* UITextBoxEnterAsTab + 2020.06.12 + UIComboBoxݰ󶨣DataSourceDisplayMemberValueMember