using System; using System.Collections; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; using System.ComponentModel; using FastReport.Utils; using FastReport.Editor; using System.Collections.Generic; using FastReport.TypeConverters; namespace FastReport.Design.PageDesigners.Page { #if !DEBUG [DesignTimeVisible(false)] #endif internal class RulerBase : Control { public bool allowPaint = true; protected ToolTip toolTip; private ReportPageDesigner pageDesigner; private float offset; public float Offset { get { return offset; } set { offset = value; } } public ReportWorkspace Workspace { get { return pageDesigner.Workspace; } } public ReportPageDesigner PageDesigner { get { return pageDesigner; } } public Designer Designer { get { return pageDesigner.Designer; } } protected bool CheckGridStep(ref float kx, ref float ky) { bool al = ReportWorkspace.SnapToGrid; if (ModifierKeys == Keys.Alt) al = !al; bool result = true; float grid = ReportWorkspace.Grid.SnapSize; if (al) { result = kx >= grid || kx <= -grid || ky >= grid || ky <= -grid; if (result) { kx = (int)(kx / grid) * grid; ky = (int)(ky / grid) * grid; } } return result; } #if !MONO private const int WM_PAINT = 0x000F; protected override void WndProc(ref Message m) { if ((m.Msg != WM_PAINT) || (allowPaint && m.Msg == WM_PAINT)) { base.WndProc(ref m); } } #endif public RulerBase(ReportPageDesigner pd) : base() { pageDesigner = pd; toolTip = new ToolTip(); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); } } #if !DEBUG [DesignTimeVisible(false)] #endif internal class HorzRuler : RulerBase { private PointF lastMousePoint; private bool mouseDown; private bool mouseMoved; private int activeGuide; private bool saveAutoGuides; private void DrawRuler(Graphics g, float start, float size) { Font font = new Font("Tahoma", 6f * this.FontDpiMultiplier()); Brush brush = SystemBrushes.WindowText; Pen pen = SystemPens.WindowText; int w5 = 5; int w10 = 10; float dx = (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters || ReportWorkspace.Grid.GridUnits == PageUnits.Centimeters ? Units.Millimeters : Units.TenthsOfInch) * Designer.ZoomDpi; string s = (((int)Math.Round(size / dx)) / 10).ToString(); float maxw = g.MeasureString(s, font).Width; float i = start; int i1 = 0; while (i < start + size) { int h = 0; if (i1 == 0) h = 0; else if (i1 % w10 == 0) h = 6; else if (i1 % w5 == 0) h = 4; else h = 2; if (h == 2 && dx * w10 < this.LogicalToDevice(41)) h = 0; if (h == 4 && dx * w10 < this.LogicalToDevice(21)) h = 0; int w = 0; if (h == 6) { if (maxw > dx * w10 * 1.5f) w = w10 * 4; else if (maxw > dx * w10 * 0.7f) w = w10 * 2; else w = w10; } if (w != 0 && i1 % w == 0) { if (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters) s = (i1).ToString(); else if (ReportWorkspace.Grid.GridUnits == PageUnits.HundrethsOfInch) s = (i1 * 10).ToString(); else s = (i1 / 10).ToString(); SizeF sz = g.MeasureString(s, font); g.DrawString(s, font, brush, new PointF(Offset + i - sz.Width / 2 + 1, this.LogicalToDevice(7))); } else if (h != 0) { g.DrawLine(pen, Offset + i, this.LogicalToDevice(6 + (13 - h) / 2), Offset + i, this.LogicalToDevice(6 + (13 - h) / 2 + h - 1)); } i += dx; i1++; } } private void DrawRulerRtl(Graphics g, float start, float size) { Font font = new Font("Tahoma", 6f * this.FontDpiMultiplier()); Brush brush = SystemBrushes.WindowText; Pen pen = SystemPens.WindowText; int w5 = 5; int w10 = 10; float dx = (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters || ReportWorkspace.Grid.GridUnits == PageUnits.Centimeters ? Units.Millimeters : Units.TenthsOfInch) * Designer.ZoomDpi; string s = (((int)Math.Round(size / dx)) / 10).ToString(); float maxw = g.MeasureString(s, font).Width; float i = start + size; int i1 = 0; while (i > start) { int h = 0; if (i1 == 0) h = 0; else if (i1 % w10 == 0) h = 6; else if (i1 % w5 == 0) h = 4; else h = 2; if (h == 2 && dx * w10 < this.LogicalToDevice(41)) h = 0; if (h == 4 && dx * w10 < this.LogicalToDevice(21)) h = 0; int w = 0; if (h == 6) { if (maxw > dx * w10 * 1.5f) w = w10 * 4; else if (maxw > dx * w10 * 0.7f) w = w10 * 2; else w = w10; } if (w != 0 && i1 % w == 0) { if (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters) s = (i1).ToString(); else if (ReportWorkspace.Grid.GridUnits == PageUnits.HundrethsOfInch) s = (i1 * 10).ToString(); else s = (i1 / 10).ToString(); SizeF sz = g.MeasureString(s, font); g.DrawString(s, font, brush, new PointF(Offset + i - sz.Width / 2 + 1, this.LogicalToDevice(7))); } else if (h != 0) { g.DrawLine(pen, Offset + i, this.LogicalToDevice(6 + (13 - h) / 2), Offset + i, this.LogicalToDevice(6 + (13 - h) / 2 + h - 1)); } i -= dx; i1++; } } private void DrawGuides(Graphics g) { FloatCollection guides = Workspace.Page.Guides; if (guides == null) return; if (guides.Count > activeGuide && activeGuide != -1) { toolTip.Show(Converter.ToString((Workspace.Page.LeftMargin * Units.Millimeters + guides[activeGuide]) / ReportWorkspace.Grid.SnapSize * 10 / 4, typeof(PaperConverter)) + " | " + Converter.ToString((Workspace.Page.PaperWidth * Units.Millimeters - Workspace.Page.LeftMargin * Units.Millimeters - guides[activeGuide]) / ReportWorkspace.Grid.SnapSize * 10 / 4, typeof(PaperConverter)), this, (int)Math.Round(Offset + guides[activeGuide] * Designer.ZoomDpi - 4), 32 ); } if (activeGuide == -1) toolTip.Hide(this); for (int i = 0; i < guides.Count; i++) { Image b = this.GetImage(i == activeGuide ? 174 : 74); g.DrawImage(b, (int)Math.Round(Offset + guides[i] * Designer.ZoomDpi - 4), 16); } } private void MoveGuide(float kx) { Workspace.Guides.MoveVGuide(activeGuide, kx); float f = Workspace.Page.Guides[activeGuide]; f += kx; Workspace.Page.Guides[activeGuide] = Converter.DecreasePrecision(f, 2); Workspace.Refresh(); Refresh(); } private void FixGuide(bool remove) { float f = Workspace.Page.Guides[activeGuide]; if (remove || f < 0 || f > Workspace.Width / Designer.ZoomDpi) Workspace.Page.Guides.RemoveAt(activeGuide); activeGuide = -1; Refresh(); } protected override void OnPaint(PaintEventArgs e) { if (Workspace.Locked) return; Graphics g = e.Graphics; g.SetClip(new RectangleF(Height, 0, Width - Height, Height)); g.FillRectangle(SystemBrushes.Window, new RectangleF( Offset, this.LogicalToDevice(5), Workspace.Width, Height - this.LogicalToDevice(10))); if (Config.RightToLeft) { DrawRulerRtl(g, 0, Workspace.Width); } else { DrawRuler(g, 0, Workspace.Width); } DrawGuides(g); } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (Workspace.Locked) return; float scale = Designer.ZoomDpi; lastMousePoint = new PointF(e.X / scale, e.Y / scale); mouseDown = true; mouseMoved = false; if (activeGuide != -1) Workspace.Guides.BeforeMoveVGuide(activeGuide); saveAutoGuides = ReportWorkspace.AutoGuides; ReportWorkspace.AutoGuides = false; } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (Workspace.Locked) return; float scale = Designer.ZoomDpi; if (e.Button == MouseButtons.None) { // find guide FloatCollection guides = Workspace.Page.Guides; if (guides == null) return; float x = (e.X - Offset) / scale; activeGuide = -1; for (int i = 0; i < guides.Count; i++) { if (x > guides[i] - 5 && x < guides[i] + 5) { activeGuide = i; break; } } Refresh(); } else if (e.Button == MouseButtons.Left) { if (activeGuide == -1) return; float kx = e.X / scale - lastMousePoint.X; float ky = e.Y / scale - lastMousePoint.Y; if (!CheckGridStep(ref kx, ref ky)) return; mouseMoved = true; MoveGuide(kx); lastMousePoint.X += kx; lastMousePoint.Y += ky; } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (Workspace.Locked || !mouseDown) return; ReportWorkspace.AutoGuides = saveAutoGuides; mouseDown = false; if (mouseMoved) { FixGuide(e.Y < -5 || e.Y > Height + 5); Workspace.Designer.SetModified(null, "MoveGuide"); } else { // create new guide float x = (e.X - Offset) / Designer.ZoomDpi; if (x < Workspace.Width && e.Y > 5 && e.Y < 20) { if (ReportWorkspace.SnapToGrid) x = (int)(x / ReportWorkspace.Grid.SnapSize) * ReportWorkspace.Grid.SnapSize; if (Workspace.Page.Guides == null) Workspace.Page.Guides = new FloatCollection(); Workspace.Page.Guides.Add(x); Workspace.Designer.SetModified(null, "AddGuide"); } } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (Workspace.Locked) return; if (!mouseDown && activeGuide != -1) { activeGuide = -1; Refresh(); } } public HorzRuler(ReportPageDesigner pd) : base(pd) { activeGuide = -1; } } #if !DEBUG [DesignTimeVisible(false)] #endif internal class VertRuler : RulerBase { private PointF lastMousePoint; private bool mouseDown; private bool mouseMoved; private int activeGuide; private BandBase activeBand; private bool resizing; private bool saveAutoGuides; private void DrawRuler(Graphics g, float start, float size) { Font font = new Font("Tahoma", 6f * this.FontDpiMultiplier()); Brush brush = SystemBrushes.WindowText; Pen pen = SystemPens.WindowText; int w5 = 5; int w10 = 10; float dx = (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters || ReportWorkspace.Grid.GridUnits == PageUnits.Centimeters ? Units.Millimeters : Units.TenthsOfInch) * Designer.ZoomDpi; string s = (((int)Math.Round(size / dx)) / 10).ToString(); float maxw = g.MeasureString(s, font).Width; float i = start; int i1 = 0; while (i < start + size) { int h = 0; if (i1 == 0) h = 0; else if (i1 % w10 == 0) h = 6; else if (i1 % w5 == 0) h = 4; else h = 2; if (h == 2 && dx * w10 < this.LogicalToDevice(41)) h = 0; if (h == 4 && dx * w10 < this.LogicalToDevice(21)) h = 0; int w = 0; if (h == 6) { if (maxw > dx * w10 * 1.5f) w = w10 * 4; else if (maxw > dx * w10 * 0.7f) w = w10 * 2; else w = w10; } if (w != 0 && i1 % w == 0) { if (ReportWorkspace.Grid.GridUnits == PageUnits.Millimeters) s = (i1).ToString(); else if (ReportWorkspace.Grid.GridUnits == PageUnits.HundrethsOfInch) s = (i1 * 10).ToString(); else s = (i1 / 10).ToString(); SizeF sz = g.MeasureString(s, font); PointF p = new PointF(Width - sz.Height - this.LogicalToDevice(7), Offset + i + sz.Width / 2); GraphicsState state = g.Save(); g.TranslateTransform(p.X + sz.Height / 2, p.Y + sz.Width / 2); g.RotateTransform(-90); p.X /= 2; p.Y = -sz.Height / 2; g.DrawString(s, font, brush, p); g.Restore(state); } else if (h != 0) { g.DrawLine(pen, this.LogicalToDevice(6 + (13 - h) / 2), Offset + i, this.LogicalToDevice(6 + (13 - h) / 2 + h - 1), Offset + i); } i += dx; i1++; } } private void DrawGuides(Graphics g, BandBase band) { FloatCollection guides = band.Guides; if (guides == null) return; if (band == activeBand && guides.Count > activeGuide && activeGuide != -1) { toolTip.Show(Converter.ToString((Workspace.Page.TopMargin * Units.Millimeters + (band.Top + guides[activeGuide])) / ReportWorkspace.Grid.SnapSize * 10 / 4, typeof(PaperConverter)) + " | " + Converter.ToString((Workspace.Page.PaperHeight * Units.Millimeters - Workspace.Page.TopMargin * Units.Millimeters - (band.Top + guides[activeGuide])) / ReportWorkspace.Grid.SnapSize * 10 / 4, typeof(PaperConverter)), this, 32, (int)Math.Round(Offset + (band.Top + guides[activeGuide]) * Designer.ZoomDpi + 10) ); } if (activeGuide == -1) toolTip.Hide(this); for (int i = 0; i < guides.Count; i++) { Image b = this.GetImage(band == activeBand && i == activeGuide ? 173 : 73); g.DrawImage(b, 16, (int)Math.Round(Offset + (band.Top + guides[i]) * Designer.ZoomDpi - 4)); } } private BandCollection GetBands() { BandCollection bands = new BandCollection(); ObjectCollection objects = PageDesigner.Page.AllObjects; foreach (Base c in objects) { if (c is BandBase) bands.Add(c as BandBase); } return bands; } private BandBase BandAt(float y) { BandCollection bands = GetBands(); foreach (BandBase b in bands) { if (y >= b.Top && y <= b.Bottom + (ReportWorkspace.ClassicView ? BandBase.HeaderSize : 4)) return b; } return null; } private void MoveGuide(float ky) { Workspace.Guides.MoveHGuide(activeBand, activeGuide, ky); float f = activeBand.Guides[activeGuide]; f += ky; activeBand.Guides[activeGuide] = Converter.DecreasePrecision(f, 2); Workspace.Refresh(); Refresh(); } private void ResizeBand(float ky) { activeBand.Height += ky; activeBand.FixHeight(); Workspace.UpdateBands(); } private void FixGuide(bool remove) { float f = activeBand.Guides[activeGuide]; if (remove || f < 0 || f > activeBand.Height) activeBand.Guides.RemoveAt(activeGuide); activeGuide = -1; Refresh(); } protected override void OnPaint(PaintEventArgs e) { if (Workspace.Locked) return; Graphics g = e.Graphics; // highlight bands list Hashtable bandsToHighlight = new Hashtable(); if (ReportWorkspace.EnableBacklight) { foreach (Base obj in Designer.SelectedObjects) { BandBase band = null; if (obj is BandBase) band = obj as BandBase; else if (obj is ReportComponentBase) band = (obj as ReportComponentBase).Band; if (band != null) bandsToHighlight[band] = 1; } } float scale = Designer.ZoomDpi; BandCollection bands = GetBands(); foreach (BandBase b in bands) { Brush brush = bandsToHighlight.ContainsKey(b) ? Brushes.Gainsboro : SystemBrushes.Window; g.FillRectangle(brush, new RectangleF( this.LogicalToDevice(5), Offset + b.Top * scale, Width - this.LogicalToDevice(10), b.Height * scale + 1)); DrawRuler(g, b.Top * scale, b.Height * scale); DrawGuides(g, b); if (ReportWorkspace.ClassicView) { RectangleF fillRect = new RectangleF( this.LogicalToDevice(5), Offset + (b.Top - (BandBase.HeaderSize - 1)) * scale, Width - this.LogicalToDevice(10), (BandBase.HeaderSize - 1) * scale); if (b.Top == BandBase.HeaderSize) { fillRect.Y = 0; fillRect.Height += scale; } b.DrawBandHeader(g, fillRect, true); if (b.Top > BandBase.HeaderSize) { // draw splitter lines float lineY = fillRect.Top + fillRect.Height / 2 - this.LogicalToDevice(2); for (int i = 0; i < 6; i += 2) { g.DrawLine(SystemPens.ControlDarkDark, this.LogicalToDevice(9), lineY + this.LogicalToDevice(i), Width - this.LogicalToDevice(10), lineY + this.LogicalToDevice(i)); } } } } } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (Workspace.Locked) return; float scale = Designer.ZoomDpi; lastMousePoint = new PointF(e.X / scale, e.Y / scale); mouseDown = true; mouseMoved = false; if (activeBand != null && activeGuide != -1) Workspace.Guides.BeforeMoveHGuide(activeBand, activeGuide); saveAutoGuides = ReportWorkspace.AutoGuides; ReportWorkspace.AutoGuides = false; } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (Workspace.Locked) return; float scale = Designer.ZoomDpi; if (e.Button == MouseButtons.None) { // find band float y = (e.Y - Offset) / scale; Cursor = Cursors.Default; resizing = false; activeGuide = -1; activeBand = BandAt(y); if (activeBand != null) { // check band resize if (y > activeBand.Bottom - 1 && y < activeBand.Bottom + (ReportWorkspace.ClassicView ? BandBase.HeaderSize : 4)) { resizing = true; Cursor = Cursors.HSplit; } else { // check guides FloatCollection guides = activeBand.Guides; if (guides != null) { for (int i = 0; i < guides.Count; i++) { if (y > activeBand.Top + guides[i] - 5 && y < activeBand.Top + guides[i] + 5) { activeGuide = i; break; } } } } } Refresh(); } else if (e.Button == MouseButtons.Left) { float kx = e.X / scale - lastMousePoint.X; float ky = e.Y / scale - lastMousePoint.Y; if (!CheckGridStep(ref kx, ref ky)) return; if (activeBand != null) { if (resizing) { mouseMoved = true; ResizeBand(ky); } else if (activeGuide != -1) { mouseMoved = true; MoveGuide(ky); } } lastMousePoint.X += kx; lastMousePoint.Y += ky; } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (Workspace.Locked) return; ReportWorkspace.AutoGuides = saveAutoGuides; mouseDown = false; if (mouseMoved) { if (resizing) activeBand.FixHeight(); else FixGuide(e.X < -this.LogicalToDevice(5) || e.X > Width + this.LogicalToDevice(5)); Workspace.Designer.SetModified(null, resizing ? "ResizeBand" : "MoveGuide"); } else { // create new guide if (e.X > this.LogicalToDevice(5) && e.X < this.LogicalToDevice(20)) { float y = (e.Y - Offset) / Designer.ZoomDpi; BandBase band = BandAt(y); if (band != null) { y = y - band.Top; if (ReportWorkspace.SnapToGrid) y = (int)(y / ReportWorkspace.Grid.SnapSize) * ReportWorkspace.Grid.SnapSize; if (band.Guides == null) band.Guides = new FloatCollection(); band.Guides.Add(y); Workspace.Designer.SetModified(null, "AddGuide"); } } } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (Workspace.Locked) return; if (!mouseDown && activeGuide != -1) { activeGuide = -1; Refresh(); } } public VertRuler(ReportPageDesigner pd) : base(pd) { activeGuide = -1; } } #if !MONO /// /// Represent ruler with guides for forms of editors /// public class RulerWithGuides : EditRuler { private bool mouseDown = false; private Pen pen; private List rulerElements; private RulerElement activElement; private int countTabPos; private bool leftIndentIsActive = false; private bool rightIndentIsActive = false; #region Properties /// /// Get or set left indent position /// public int LeftIndent { get { return leftIndent.Indent; } set { leftIndent.Indent = value; Invalidate(); } } /// /// Get or set right indent position /// public int RightIndent { get { return rightIndent.Indent; } set { rightIndent.Indent = value; Invalidate(); } } /// /// Gets or sets tab positiions /// public int[] TabPositions { get { List result = new List(); foreach (var elem in rulerElements) { if(elem is TabPosition) { result.Add(elem.Bounds.X + 4); } } result.Sort(); return result.ToArray(); } set { for (int i = 0; i < rulerElements.Count; i++) { if (rulerElements[i] is TabPosition) { rulerElements.Remove(rulerElements[i]); i--; } } for (int i = 0; i < value.Length; i++) { rulerElements.Add(new TabPosition(value[i])); } Invalidate(); } } #endregion #region Protected method /// protected override void OnDoubleClick(EventArgs e) { base.OnDoubleClick(e); MouseEventArgs me = e as MouseEventArgs; if (me.X > RulerStart && me.X < RulerWidth && me.Button == MouseButtons.Left && !TabPosExist(me.X) && countTabPos + 1 <= 32 && !leftIndentIsActive && !rightIndentIsActive && activElement == null) { rulerElements.Add(new TabPosition(me.X)); countTabPos++; OnChange(this); } } /// protected override Rectangle GetIndentHitRect(RulerIndent Indent) { Rectangle result = Rectangle.Empty; if (Vertical) { //if (Indent.Orientation == IndentOrientation.Near) // result = new Rectangle(cRulerTop, RulerStart + Indent.Indent - EditConsts.DefaultRulerHitWidth, cRulerHeight, EditConsts.DefaultRulerHitWidth * 2); //else // result = new Rectangle(cRulerTop, PageStart + PageWidth - EditConsts.DefaultRulerHitWidth, cRulerHeight, EditConsts.DefaultRulerHitWidth * 2); } else { if (Indent.Orientation == IndentOrientation.Near) result = new Rectangle(RulerStart + Indent.Indent - EditConsts.DefaultRulerHitWidth, cRulerTop, EditConsts.DefaultRulerHitWidth * 2, cRulerHeight); else result = new Rectangle(RulerStart + RulerWidth - EditConsts.DefaultRulerHitWidth - Indent.Indent, cRulerTop, EditConsts.DefaultRulerHitWidth * 2, cRulerHeight); } return result; } /// protected override Rectangle GetIndentRect(RulerIndent indent) { Rectangle result = Rectangle.Empty; if (Vertical) { //if (indent.Orientation == IndentOrientation.Near) // result = new Rectangle(cRulerTop, RulerStart, cRulerHeight, indent.Indent); //else // result = new Rectangle(cRulerTop, PageWidth + PageStart, cRulerHeight, indent.Indent); } else { if (indent.Orientation == IndentOrientation.Near) result = new Rectangle(RulerStart, cRulerTop, indent.Indent, cRulerHeight); else result = new Rectangle(RulerWidth + RulerStart - indent.Indent, cRulerTop, indent.Indent, cRulerHeight); } return result; } /// protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); foreach(var elem in rulerElements) { elem.Draw(pe.Graphics); } } /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); mouseDown = true; if (RulerWidth - RightIndent + RulerStart + 2 >= e.X && RulerWidth - RightIndent + RulerStart - 4 <= e.X && e.Button != MouseButtons.Right) rightIndentIsActive = true; else if (LeftIndent + RulerStart - 4 <= e.X && LeftIndent + RulerStart + 2 >= e.X && e.Button != MouseButtons.Right) leftIndentIsActive = true; else foreach (var elem in rulerElements) { if (elem.Bounds.Contains(e.Location)) { if (e.Button == MouseButtons.Right && elem is TabPosition) { rulerElements.Remove(elem); countTabPos--; } else { activElement = elem; activElement.IsActive = true; if (e.X > RulerWidth + RulerStart - RightIndent) activElement.Move(new Point(RulerWidth + RulerStart - RightIndent, 0)); else if(e.X < RulerStart + LeftIndent) activElement.Move(new Point(RulerStart + LeftIndent, 0)); } break; } } OnChange(this); } /// protected override void OnMouseMove(MouseEventArgs e) { int oldLeftIndent = LeftIndent; base.OnMouseMove(e); if (mouseDown && activElement != null && e.X < RulerWidth + RulerStart - RightIndent && e.X > RulerStart + LeftIndent) { activElement.Move(e.Location); OnChange(this); } else if(mouseDown && leftIndentIsActive) { int dx = LeftIndent - oldLeftIndent; //if (dx != 0) dx += 4; foreach (var elem in rulerElements) { elem.Move(new Point(elem.Bounds.X + dx, 0)); } } } /// protected override void OnChange(object sender) { base.OnChange(sender); Invalidate(); } /// protected override void OnMouseCaptureChanged(EventArgs e) { base.OnMouseCaptureChanged(e); mouseDown = false; if (activElement != null) activElement.IsActive = false; activElement = null; leftIndentIsActive = false; rightIndentIsActive = false; OnChange(this); } /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); mouseDown = false; if(activElement != null) activElement.IsActive = false; activElement = null; leftIndentIsActive = false; rightIndentIsActive = false; OnChange(this); } /// protected override void InitLayout() { base.InitLayout(); pen = new Pen(Color.Black, 1); pen.DashStyle = DashStyle.Dash; pen.DashPattern = new float[] { 4, 4 }; rulerElements = new List(); } /// protected override void OnHandleDestroyed(EventArgs e) { pen.Dispose(); base.OnHandleDestroyed(e); } #endregion private bool TabPosExist(int x) { foreach (var elem in rulerElements) { if (elem.Bounds.Contains(x, elem.Bounds.Y) && elem is TabPosition) { return true; } } return false; } /// /// Method for drawing guides on element of form. /// /// /// public void DrawGuides(object sender, PaintEventArgs e) { if (mouseDown) { if(activElement != null) e.Graphics.DrawLine(pen, new Point(activElement.Bounds.X + 4, e.ClipRectangle.Top), new Point(activElement.Bounds.X + 4, e.ClipRectangle.Bottom)); else if(leftIndentIsActive) e.Graphics.DrawLine(pen, new Point(LeftIndent + RulerStart, e.ClipRectangle.Top), new Point(LeftIndent + RulerStart, e.ClipRectangle.Bottom)); else if (rightIndentIsActive) e.Graphics.DrawLine(pen, new Point(RulerWidth - RightIndent + RulerStart + 2, e.ClipRectangle.Top), new Point(RulerWidth - RightIndent + RulerStart + 2, e.ClipRectangle.Bottom)); } } /// /// Base class for elements of RulerWithGuides /// public class RulerElement { private bool isActive; private Rectangle bounds; /// /// Get or set bounds of object /// public Rectangle Bounds { get { return bounds; } set { bounds = value; } } /// /// Get or set state of object /// public bool IsActive { get { return isActive; } set { isActive = value; } } /// /// Draw element on graphics /// /// public virtual void Draw(Graphics g) { } /// /// Method for moving object by means of chenging bounds /// /// public virtual void Move(Point location) { } } /// /// Element of RulerWithGuides presenting position of tabs /// public class TabPosition : RulerElement { /// /// Constructor of class TabPosition /// /// public TabPosition(int x) { IsActive = false; Bounds = new Rectangle(x - 4, 16, 14, 14); } /// public override void Draw(Graphics g) { base.Draw(g); if(IsActive) g.DrawImage(Res.GetImage(174, 96), Bounds); else g.DrawImage(Res.GetImage(74, 96), Bounds); } /// public override void Move(Point location) { base.Move(location); Bounds = new Rectangle(location.X - 4, 16, 14, 14); } } } #endif }