| File: System\Windows\Forms\Design\Behavior\SnapLine.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Windows.Forms.Design.Behavior; /// <summary> /// The SnapLine class represents a UI-guideline that will be rendered /// during control movement (drag, keyboard, and resize) operations. /// SnapLines will assist a user in aligning controls relative to one /// one another. Each SnapLine will have a type: top, bottom, etc... /// Only SnapLines of like-types are allowed to align with each other. /// The 'offset' will represent the distance from the origin (upper-left /// corner) of the control to where the SnapLine is located. And finally /// the 'filter' is a string used to define custom types of SnapLines. /// This enables a SnapLine with a filter of "TypeX" to only snap to /// other "TypeX" filtered lines. /// </summary> public sealed class SnapLine { // These are used in the SnapLine filter to define custom margin/padding SnapLines. // Margins will have special rules of equality, basically opposites will attract one another // (ex: margin right == margin left) and paddings will be attracted to like-margins. internal const string Margin = "Margin"; internal const string MarginRight = Margin + ".Right"; internal const string MarginLeft = Margin + ".Left"; internal const string MarginBottom = Margin + ".Bottom"; internal const string MarginTop = Margin + ".Top"; internal const string Padding = "Padding"; internal const string PaddingRight = Padding + ".Right"; internal const string PaddingLeft = Padding + ".Left"; internal const string PaddingBottom = Padding + ".Bottom"; internal const string PaddingTop = Padding + ".Top"; /// <summary> /// SnapLine constructor that takes the type and offset of SnapLine. /// </summary> public SnapLine(SnapLineType type, int offset) : this(type, offset, filter: null, SnapLinePriority.Low) { } /// <summary> /// SnapLine constructor that takes the type, offset and filter of SnapLine. /// </summary> public SnapLine(SnapLineType type, int offset, string? filter) : this(type, offset, filter, SnapLinePriority.Low) { } /// <summary> /// SnapLine constructor that takes the type, offset, and priority of SnapLine. /// </summary> public SnapLine(SnapLineType type, int offset, SnapLinePriority priority) : this(type, offset, filter: null, priority) { } /// <summary> /// SnapLine constructor that takes the type, offset, filter, and priority of the SnapLine. /// </summary> public SnapLine(SnapLineType type, int offset, string? filter, SnapLinePriority priority) { SnapLineType = type; Offset = offset; Filter = filter; Priority = priority; } /// <summary> /// This property returns a string representing an optional user-defined filter. /// Setting this filter will allow only those SnapLines with similar filters to align /// to one another. /// </summary> public string? Filter { get; } /// <summary> /// Returns true if the SnapLine is of a horizontal type. /// </summary> public bool IsHorizontal => SnapLineType is SnapLineType.Top or SnapLineType.Bottom or SnapLineType.Horizontal or SnapLineType.Baseline; /// <summary> /// Returns true if the SnapLine is of a vertical type. /// </summary> public bool IsVertical => SnapLineType is SnapLineType.Left or SnapLineType.Right or SnapLineType.Vertical; /// <summary> /// Read-only property that returns the distance from the origin to where this SnapLine is defined. /// </summary> public int Offset { get; private set; } /// <summary> /// Read-only property that returns the priority of the SnapLine. /// </summary> public SnapLinePriority Priority { get; } /// <summary> /// Read-only property that represents the 'type' of SnapLine. /// </summary> public SnapLineType SnapLineType { get; } /// <summary> /// Adjusts the offset property of the SnapLine. /// </summary> public void AdjustOffset(int adjustment) { Offset += adjustment; } /// <summary> /// Returns true if SnapLine s1 should snap to SnapLine s2. /// </summary> public static bool ShouldSnap(SnapLine line1, SnapLine line2) { // types must first be equal if (line1.SnapLineType != line2.SnapLineType) { return false; } // if the filters are both null - then return true if (line1.Filter is null && line2.Filter is null) { return true; } // at least one filter is non-null so if the other is null // then we don't have a match if (line1.Filter is null || line2.Filter is null) { return false; } // check for our special-cased margin filter if (line1.Filter.Contains(Margin)) { if ((line1.Filter.Equals(MarginRight) && (line2.Filter.Equals(MarginLeft) || line2.Filter.Equals(PaddingRight))) || (line1.Filter.Equals(MarginLeft) && (line2.Filter.Equals(MarginRight) || line2.Filter.Equals(PaddingLeft))) || (line1.Filter.Equals(MarginTop) && (line2.Filter.Equals(MarginBottom) || line2.Filter.Equals(PaddingTop))) || (line1.Filter.Equals(MarginBottom) && (line2.Filter.Equals(MarginTop) || line2.Filter.Equals(PaddingBottom)))) { return true; } return false; } // check for padding & margins if (line1.Filter.Contains(Padding)) { if ((line1.Filter.Equals(PaddingLeft) && line2.Filter.Equals(MarginLeft)) || (line1.Filter.Equals(PaddingRight) && line2.Filter.Equals(MarginRight)) || (line1.Filter.Equals(PaddingTop) && line2.Filter.Equals(MarginTop)) || (line1.Filter.Equals(PaddingBottom) && line2.Filter.Equals(MarginBottom))) { return true; } return false; } // basic filter equality if (line1.Filter.Equals(line2.Filter)) { return true; } // not equal! return false; } /// <summary> /// ToString implementation for SnapLines. /// </summary> public override string ToString() { return $"SnapLine: {{type = {SnapLineType}, offset = {Offset}, priority = {Priority}, filter = {Filter ?? "<null>"}}}"; } }