using System; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; using FastReport.Utils; using System.ComponentModel; namespace FastReport.Controls { #if !DEBUG [DesignTimeVisible(false)] #endif internal class AngleControl : ContainerControl { private int angle; private bool showBorder; private NumericUpDown udAngle; private bool changed; private bool updating; public event EventHandler AngleChanged; public NumericUpDown NumericAngle { get { return udAngle; } } public int Angle { get { return angle; } set { updating = true; if (value < 0) value += 360; angle = value % 360; udAngle.Value = angle; Refresh(); updating = false; } } public bool ShowBorder { get { return showBorder; } set { showBorder = value; Refresh(); } } public bool Changed { get { return changed; } set { changed = value; } } private void RotateTo(int x, int y) { int size = Math.Min(Width, Height - 30); int cx = size / 2; int cy = cx; int r = x - cx == 0 ? (y > cy ? 90 : 270) : (int)(Math.Atan2((y - cy), (x - cx)) * 180 / Math.PI); Angle = (int)Math.Round(r / 15f) * 15; } private void udAngle_ValueChanged(object sender, EventArgs e) { if (updating) return; Angle = (int)udAngle.Value; Change(); } private void Change() { changed = true; if (AngleChanged != null) AngleChanged(this, EventArgs.Empty); } protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; Pen p = null; // draw control border if (showBorder) { using (p = new Pen(Color.FromArgb(127, 157, 185))) { g.DrawRectangle(p, 0, 0, Width - 1, Height - 1); } } g.SmoothingMode = SmoothingMode.AntiAlias; // draw ticks int size = Math.Min(Width, Height - 30); int cx = size / 2; int cy = cx; int radius = size / 2 - 10; p = new Pen(Color.Silver); p.DashStyle = DashStyle.Dot; g.DrawEllipse(p, 10, 10, size - 20, size - 20); p.Dispose(); for (int i = 0; i < 360; i += 45) { Rectangle rect = new Rectangle( cx + (int)(Math.Cos(Math.PI / 180 * i) * radius) - 2, cy + (int)(Math.Sin(Math.PI / 180 * i) * radius) - 2, this.LogicalToDevice(4), this.LogicalToDevice(4)); g.FillEllipse(i == angle ? Brushes.DarkOrange : SystemBrushes.Window, rect); g.DrawEllipse(i == angle ? Pens.DarkOrange : Pens.Black, rect); } // draw sample using (StringFormat sf = new StringFormat()) { sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; StandardTextRenderer.Draw(Res.Get("Misc,Sample"), GdiGraphics.FromGraphics(g), Font, SystemBrushes.WindowText, null, new RectangleF(cx - radius + 1, cy - radius + 1, radius * 2, radius * 2), sf, angle, 1); } } protected override void OnMouseDown(MouseEventArgs e) { RotateTo(e.X, e.Y); } protected override void OnMouseMove(MouseEventArgs e) { if (e.Button == MouseButtons.Left) RotateTo(e.X, e.Y); } protected override void OnMouseUp(MouseEventArgs e) { Change(); } public AngleControl() { udAngle = new NumericUpDown(); udAngle.Maximum = 360; udAngle.Increment = 15; udAngle.ValueChanged += new EventHandler(udAngle_ValueChanged); udAngle.Dock = DockStyle.Bottom; Controls.Add(udAngle); showBorder = true; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true); Size = new Size(100, 130); BackColor = SystemColors.Window; Padding = new Padding(4); } } }