|
@@ -27,2369 +27,2367 @@ using Brush = System.Windows.Media.Brush;
|
|
|
using Color = System.Drawing.Color;
|
|
|
using Image = System.Windows.Controls.Image;
|
|
|
using Point = System.Windows.Point;
|
|
|
+using PointI = System.Drawing.Point;
|
|
|
using Rectangle = System.Windows.Shapes.Rectangle;
|
|
|
|
|
|
-namespace InABox.DynamicGrid
|
|
|
+namespace InABox.DynamicGrid;
|
|
|
+
|
|
|
+public class DynamicFormCreateElementArgs : EventArgs
|
|
|
{
|
|
|
- public class DynamicFormCreateElementArgs : EventArgs
|
|
|
+ public DynamicFormCreateElementArgs(DFLayoutElement element, string name)
|
|
|
{
|
|
|
- public DynamicFormCreateElementArgs(DFLayoutElement element, string name)
|
|
|
- {
|
|
|
- Element = element;
|
|
|
- Name = name;
|
|
|
- }
|
|
|
-
|
|
|
- public DFLayoutElement Element { get; }
|
|
|
-
|
|
|
- public string Name { get; }
|
|
|
+ Element = element;
|
|
|
+ Name = name;
|
|
|
}
|
|
|
|
|
|
- public delegate FrameworkElement DynamicFormCreateElementDelegate(object sender, DynamicFormCreateElementArgs e);
|
|
|
-
|
|
|
- public delegate void DynamicFormAfterDesignDelegate(object sender);
|
|
|
+ public DFLayoutElement Element { get; }
|
|
|
|
|
|
- public delegate void DynamicFormAfterRenderDelegate(DynamicFormDesignGrid sender);
|
|
|
+ public string Name { get; }
|
|
|
+}
|
|
|
|
|
|
- public delegate void DynamicFormOnChangedDelegate(DynamicFormDesignGrid sender, string fieldName);
|
|
|
+public delegate FrameworkElement DynamicFormCreateElementDelegate(object sender, DynamicFormCreateElementArgs e);
|
|
|
|
|
|
- public enum FormMode
|
|
|
- {
|
|
|
- /// <summary>
|
|
|
- /// The form is read-only.
|
|
|
- /// </summary>
|
|
|
- ReadOnly,
|
|
|
- /// <summary>
|
|
|
- /// Standard option for when the form is being filled in by the associated employee.
|
|
|
- /// </summary>
|
|
|
- Filling,
|
|
|
- /// <summary>
|
|
|
- /// Standard option for when the form is being previewed - that is, it is acting with placeholder values that will not get saved.
|
|
|
- /// It is still editable.
|
|
|
- /// </summary>
|
|
|
- Preview,
|
|
|
- /// <summary>
|
|
|
- /// Once the form has been completed, or the person editing is not the employee the form applies to, then they are put in Editing Mode.<br/>
|
|
|
- /// This is only possible if <see cref="CanEditCompletedForms"/> is enabled.
|
|
|
- /// </summary>
|
|
|
- Editing,
|
|
|
- /// <summary>
|
|
|
- /// The form layout is being designed
|
|
|
- /// </summary>
|
|
|
- Designing
|
|
|
- }
|
|
|
+public delegate void DynamicFormAfterDesignDelegate(object sender);
|
|
|
|
|
|
- public class DynamicFormDesignGrid : Grid, IDFRenderer
|
|
|
- {
|
|
|
+public delegate void DynamicFormAfterRenderDelegate(DynamicFormDesignGrid sender);
|
|
|
|
|
|
+public delegate void DynamicFormOnChangedDelegate(DynamicFormDesignGrid sender, string fieldName);
|
|
|
|
|
|
- //private bool _designing;
|
|
|
+public enum FormMode
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// The form is read-only.
|
|
|
+ /// </summary>
|
|
|
+ ReadOnly,
|
|
|
+ /// <summary>
|
|
|
+ /// Standard option for when the form is being filled in by the associated employee.
|
|
|
+ /// </summary>
|
|
|
+ Filling,
|
|
|
+ /// <summary>
|
|
|
+ /// Standard option for when the form is being previewed - that is, it is acting with placeholder values that will not get saved.
|
|
|
+ /// It is still editable.
|
|
|
+ /// </summary>
|
|
|
+ Preview,
|
|
|
+ /// <summary>
|
|
|
+ /// Once the form has been completed, or the person editing is not the employee the form applies to, then they are put in Editing Mode.<br/>
|
|
|
+ /// This is only possible if <see cref="CanEditCompletedForms"/> is enabled.
|
|
|
+ /// </summary>
|
|
|
+ Editing,
|
|
|
+ /// <summary>
|
|
|
+ /// The form layout is being designed
|
|
|
+ /// </summary>
|
|
|
+ Designing
|
|
|
+}
|
|
|
+
|
|
|
+public class DynamicFormDesignGrid : Grid, IDFRenderer
|
|
|
+{
|
|
|
+ //private bool _designing;
|
|
|
|
|
|
- public bool GridInitialized { get; private set; } = false;
|
|
|
+ public bool GridInitialized { get; private set; } = false;
|
|
|
|
|
|
- //private bool _readonly;
|
|
|
+ //private bool _readonly;
|
|
|
|
|
|
|
|
|
- private readonly SolidColorBrush BackgroundBrush = new(Colors.WhiteSmoke);
|
|
|
- private readonly SolidColorBrush BorderBrush = new(Colors.Silver);
|
|
|
+ private readonly SolidColorBrush BackgroundBrush = new(Colors.WhiteSmoke);
|
|
|
+ private readonly SolidColorBrush BorderBrush = new(Colors.Silver);
|
|
|
|
|
|
- private readonly Dictionary<Type, IDynamicGrid> elementgrids = new();
|
|
|
+ private readonly Dictionary<Type, IDynamicGrid> elementgrids = new();
|
|
|
|
|
|
- private readonly Dictionary<DFLayoutControl, FrameworkElement> elementmap = new();
|
|
|
- private readonly Dictionary<DFLayoutControl, Border> borderMap = new();
|
|
|
- private readonly SolidColorBrush FieldBrush = new(Colors.LightYellow);
|
|
|
+ private readonly Dictionary<DFLayoutControl, FrameworkElement> elementmap = new();
|
|
|
+ private readonly Dictionary<DFLayoutControl, Border> borderMap = new();
|
|
|
+ private readonly SolidColorBrush FieldBrush = new(Colors.LightYellow);
|
|
|
|
|
|
|
|
|
- private readonly SolidColorBrush RequiredFieldBrush = new(Colors.Orange);
|
|
|
+ private readonly SolidColorBrush RequiredFieldBrush = new(Colors.Orange);
|
|
|
|
|
|
- public DynamicFormDesignGrid()
|
|
|
- {
|
|
|
- PreviewMouseLeftButtonDown += Grid_PreviewMouseLeftButtonDown;
|
|
|
- PreviewMouseMove += Grid_PreviewMouseMove;
|
|
|
- PreviewMouseLeftButtonUp += Grid_PreviewMouseLeftButtonUp;
|
|
|
- }
|
|
|
+ public DynamicFormDesignGrid()
|
|
|
+ {
|
|
|
+ PreviewMouseLeftButtonDown += Grid_PreviewMouseLeftButtonDown;
|
|
|
+ PreviewMouseMove += Grid_PreviewMouseMove;
|
|
|
+ PreviewMouseLeftButtonUp += Grid_PreviewMouseLeftButtonUp;
|
|
|
+ }
|
|
|
|
|
|
- #region Backing Properties
|
|
|
+ #region Backing Properties
|
|
|
|
|
|
- private readonly List<DynamicFormElement> _elements = new();
|
|
|
- private readonly List<DynamicFormElementAction> _elementActions = new();
|
|
|
- private bool _showBorders = true;
|
|
|
- private IDigitalFormDataModel? _datamodel;
|
|
|
- private DFLayout form = new();
|
|
|
- private FormMode _mode;
|
|
|
- private IList<DigitalFormVariable> _variables = new List<DigitalFormVariable>();
|
|
|
- private bool _isChanged;
|
|
|
- private bool _changing = false;
|
|
|
+ private readonly List<DynamicFormElement> _elements = new();
|
|
|
+ private readonly List<DynamicFormElementAction> _elementActions = new();
|
|
|
+ private bool _showBorders = true;
|
|
|
+ private IDigitalFormDataModel? _datamodel;
|
|
|
+ private DFLayout form = new();
|
|
|
+ private FormMode _mode;
|
|
|
+ private IList<DigitalFormVariable> _variables = new List<DigitalFormVariable>();
|
|
|
+ private bool _isChanged;
|
|
|
+ private bool _changing = false;
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Public Properties
|
|
|
+ #region Public Properties
|
|
|
|
|
|
- public bool ShowBorders
|
|
|
+ public bool ShowBorders
|
|
|
+ {
|
|
|
+ get => _showBorders || _mode == FormMode.Designing;
|
|
|
+ set
|
|
|
{
|
|
|
- get => _showBorders || _mode == FormMode.Designing;
|
|
|
- set
|
|
|
- {
|
|
|
- _showBorders = value;
|
|
|
- CheckRefresh();
|
|
|
- }
|
|
|
+ _showBorders = value;
|
|
|
+ CheckRefresh();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public IDigitalFormDataModel? DataModel
|
|
|
+ public IDigitalFormDataModel? DataModel
|
|
|
+ {
|
|
|
+ get => _datamodel;
|
|
|
+ set
|
|
|
{
|
|
|
- get => _datamodel;
|
|
|
- set
|
|
|
+ _datamodel = value;
|
|
|
+ if(_datamodel != null)
|
|
|
{
|
|
|
- _datamodel = value;
|
|
|
- if(_datamodel != null)
|
|
|
+ var task = Task.Run(() =>
|
|
|
{
|
|
|
- var task = Task.Run(() =>
|
|
|
- {
|
|
|
- var waiting = true;
|
|
|
- _datamodel.Load(m => { waiting = false; });
|
|
|
- while (waiting) ;
|
|
|
- });
|
|
|
- task.Wait();
|
|
|
- }
|
|
|
-
|
|
|
- CheckRefresh();
|
|
|
+ var waiting = true;
|
|
|
+ _datamodel.Load(m => { waiting = false; });
|
|
|
+ while (waiting) ;
|
|
|
+ });
|
|
|
+ task.Wait();
|
|
|
}
|
|
|
+
|
|
|
+ CheckRefresh();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public DFLayout Form
|
|
|
+ public DFLayout Form
|
|
|
+ {
|
|
|
+ get => form;
|
|
|
+ set
|
|
|
{
|
|
|
- get => form;
|
|
|
- set
|
|
|
- {
|
|
|
- form = value;
|
|
|
- form.Renderer = this;
|
|
|
+ form = value;
|
|
|
+ form.Renderer = this;
|
|
|
|
|
|
- CheckRefresh();
|
|
|
- }
|
|
|
+ CheckRefresh();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public FormMode Mode
|
|
|
+ public FormMode Mode
|
|
|
+ {
|
|
|
+ get => _mode;
|
|
|
+ set
|
|
|
{
|
|
|
- get => _mode;
|
|
|
- set
|
|
|
+ if (_mode != value)
|
|
|
{
|
|
|
- if (_mode != value)
|
|
|
+ var oldMode = _mode;
|
|
|
+ if (_mode == FormMode.Designing)
|
|
|
{
|
|
|
- var oldMode = _mode;
|
|
|
- if (_mode == FormMode.Designing)
|
|
|
- {
|
|
|
- OnAfterDesign?.Invoke(this);
|
|
|
- }
|
|
|
+ OnAfterDesign?.Invoke(this);
|
|
|
+ }
|
|
|
|
|
|
- _mode = value;
|
|
|
+ _mode = value;
|
|
|
|
|
|
- CheckRefresh(oldMode != FormMode.Designing);
|
|
|
- }
|
|
|
+ CheckRefresh(oldMode != FormMode.Designing);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public bool IsDesigning { get => _mode == FormMode.Designing; }
|
|
|
- public bool IsReadOnly { get => _mode == FormMode.ReadOnly; }
|
|
|
- public bool IsEditing { get => _mode == FormMode.Editing || _mode == FormMode.Filling; }
|
|
|
- public bool IsChanged => _isChanged;
|
|
|
+ public bool IsDesigning { get => _mode == FormMode.Designing; }
|
|
|
+ public bool IsReadOnly { get => _mode == FormMode.ReadOnly; }
|
|
|
+ public bool IsEditing { get => _mode == FormMode.Editing || _mode == FormMode.Filling; }
|
|
|
+ public bool IsChanged => _isChanged;
|
|
|
|
|
|
- public delegate DigitalFormVariable? CreateVariableHandler(Type fieldType);
|
|
|
- public delegate bool EditVariableHandler(DigitalFormVariable variable);
|
|
|
+ public delegate DigitalFormVariable? CreateVariableHandler(Type fieldType);
|
|
|
+ public delegate bool EditVariableHandler(DigitalFormVariable variable);
|
|
|
|
|
|
- public event CreateVariableHandler? OnCreateVariable;
|
|
|
- public event EditVariableHandler? OnEditVariable;
|
|
|
+ public event CreateVariableHandler? OnCreateVariable;
|
|
|
+ public event EditVariableHandler? OnEditVariable;
|
|
|
|
|
|
- public delegate void CustomiseElementContextMenuHandler(ContextMenu menu, DFLayoutElement element);
|
|
|
- public event CustomiseElementContextMenuHandler? CustomiseElementContextMenu;
|
|
|
+ public delegate void CustomiseElementContextMenuHandler(ContextMenu menu, DFLayoutElement element);
|
|
|
+ public event CustomiseElementContextMenuHandler? CustomiseElementContextMenu;
|
|
|
|
|
|
- public IList<DigitalFormVariable> Variables
|
|
|
+ public IList<DigitalFormVariable> Variables
|
|
|
+ {
|
|
|
+ get => _variables;
|
|
|
+ set
|
|
|
{
|
|
|
- get => _variables;
|
|
|
- set
|
|
|
- {
|
|
|
- _variables = value;
|
|
|
- CheckRefresh();
|
|
|
- }
|
|
|
+ _variables = value;
|
|
|
+ CheckRefresh();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Events
|
|
|
+ #region Events
|
|
|
|
|
|
- public event DynamicFormAfterDesignDelegate? OnAfterDesign;
|
|
|
+ public event DynamicFormAfterDesignDelegate? OnAfterDesign;
|
|
|
|
|
|
- public event DynamicFormCreateElementDelegate? OnCreateElement;
|
|
|
+ public event DynamicFormCreateElementDelegate? OnCreateElement;
|
|
|
|
|
|
- public event DynamicFormAfterRenderDelegate? OnAfterRender;
|
|
|
+ public event DynamicFormAfterRenderDelegate? OnAfterRender;
|
|
|
|
|
|
- public event DynamicFormOnChangedDelegate? OnChanged;
|
|
|
+ public event DynamicFormOnChangedDelegate? OnChanged;
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Rows
|
|
|
+ #region Rows
|
|
|
|
|
|
- class RowData
|
|
|
- {
|
|
|
- public string RowHeight { get; set; }
|
|
|
+ class RowData
|
|
|
+ {
|
|
|
+ public string RowHeight { get; set; }
|
|
|
|
|
|
- public RowData(string rowHeight)
|
|
|
- {
|
|
|
- RowHeight = rowHeight;
|
|
|
- }
|
|
|
+ public RowData(string rowHeight)
|
|
|
+ {
|
|
|
+ RowHeight = rowHeight;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- internal void CollapseRows(FormHeader header, bool collapsed)
|
|
|
- {
|
|
|
- var startRow = this.GetRow(header) + this.GetRowSpan(header);
|
|
|
+ internal void CollapseRows(FormHeader header, bool collapsed)
|
|
|
+ {
|
|
|
+ var startRow = this.GetRow(header) + this.GetRowSpan(header);
|
|
|
+
|
|
|
+ var nextRow = elementmap
|
|
|
+ .Where(x => x.Value is DFHeaderControl headerControl && headerControl.Header != header)
|
|
|
+ .Select(x => this.GetRow(x.Value))
|
|
|
+ .Where(x => x >= startRow).DefaultIfEmpty(-1).Min();
|
|
|
|
|
|
- var nextRow = elementmap
|
|
|
- .Where(x => x.Value is DFHeaderControl headerControl && headerControl.Header != header)
|
|
|
- .Select(x => this.GetRow(x.Value))
|
|
|
- .Where(x => x >= startRow).DefaultIfEmpty(-1).Min();
|
|
|
+ if (nextRow == -1)
|
|
|
+ {
|
|
|
+ nextRow = RowDefinitions.Count;
|
|
|
+ }
|
|
|
|
|
|
- if (nextRow == -1)
|
|
|
+ for (int row = startRow; row < nextRow; ++row)
|
|
|
+ {
|
|
|
+ var rowDefinition = RowDefinitions[row];
|
|
|
+ if(rowDefinition.Tag is not RowData rowData)
|
|
|
{
|
|
|
- nextRow = RowDefinitions.Count;
|
|
|
+ throw new Exception("Row definition tag is not RowData");
|
|
|
}
|
|
|
|
|
|
- for (int row = startRow; row < nextRow; ++row)
|
|
|
+ if (collapsed)
|
|
|
{
|
|
|
- var rowDefinition = RowDefinitions[row];
|
|
|
- if(rowDefinition.Tag is not RowData rowData)
|
|
|
- {
|
|
|
- throw new Exception("Row definition tag is not RowData");
|
|
|
- }
|
|
|
-
|
|
|
- if (collapsed)
|
|
|
- {
|
|
|
- rowDefinition.Height = new GridLength(0);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rowDefinition.Height = StringToGridLength(rowData.RowHeight);
|
|
|
- }
|
|
|
+ rowDefinition.Height = new GridLength(0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rowDefinition.Height = StringToGridLength(rowData.RowHeight);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region Elements
|
|
|
+ #endregion
|
|
|
|
|
|
- class DynamicFormElement
|
|
|
- {
|
|
|
- public string Caption { get; set; }
|
|
|
- public Type ElementType { get; set; }
|
|
|
- public string Category { get; set; }
|
|
|
- public bool AllowDuplicate { get; set; }
|
|
|
- public object? Tag { get; set; }
|
|
|
- public Func<object?, DFLayoutElement>? CreateElement { get; set; }
|
|
|
+ #region Elements
|
|
|
|
|
|
- public bool Visible { get; set; }
|
|
|
+ class DynamicFormElement
|
|
|
+ {
|
|
|
+ public string Caption { get; set; }
|
|
|
+ public Type ElementType { get; set; }
|
|
|
+ public string Category { get; set; }
|
|
|
+ public bool AllowDuplicate { get; set; }
|
|
|
+ public object? Tag { get; set; }
|
|
|
+ public Func<object?, DFLayoutElement>? CreateElement { get; set; }
|
|
|
|
|
|
- public DynamicFormElement(string caption, Type elementType, string category, bool allowDuplicate, bool visible, object? tag, Func<object?, DFLayoutElement>? createElement)
|
|
|
- {
|
|
|
- Caption = caption;
|
|
|
- ElementType = elementType;
|
|
|
- Category = category;
|
|
|
- AllowDuplicate = allowDuplicate;
|
|
|
- Tag = tag;
|
|
|
- CreateElement = createElement;
|
|
|
- Visible = visible;
|
|
|
- }
|
|
|
- }
|
|
|
+ public bool Visible { get; set; }
|
|
|
|
|
|
- class DynamicFormElementAction
|
|
|
+ public DynamicFormElement(string caption, Type elementType, string category, bool allowDuplicate, bool visible, object? tag, Func<object?, DFLayoutElement>? createElement)
|
|
|
{
|
|
|
- public string Caption { get; set; }
|
|
|
+ Caption = caption;
|
|
|
+ ElementType = elementType;
|
|
|
+ Category = category;
|
|
|
+ AllowDuplicate = allowDuplicate;
|
|
|
+ Tag = tag;
|
|
|
+ CreateElement = createElement;
|
|
|
+ Visible = visible;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- public Bitmap? Image { get; set; }
|
|
|
+ class DynamicFormElementAction
|
|
|
+ {
|
|
|
+ public string Caption { get; set; }
|
|
|
|
|
|
- public string Category { get; set; }
|
|
|
+ public Bitmap? Image { get; set; }
|
|
|
|
|
|
- public object? Tag { get; set; }
|
|
|
+ public string Category { get; set; }
|
|
|
|
|
|
- public Func<object?, DFLayoutElement?> OnClick { get; set; }
|
|
|
+ public object? Tag { get; set; }
|
|
|
|
|
|
- public DynamicFormElementAction(string caption, Bitmap? image, string category, object? tag, Func<object?, DFLayoutElement> onClick)
|
|
|
- {
|
|
|
- Caption = caption;
|
|
|
- Image = image;
|
|
|
- Category = category;
|
|
|
- Tag = tag;
|
|
|
- OnClick = onClick;
|
|
|
- }
|
|
|
- }
|
|
|
+ public Func<object?, DFLayoutElement?> OnClick { get; set; }
|
|
|
|
|
|
- public void ClearElementTypesAndActions()
|
|
|
+ public DynamicFormElementAction(string caption, Bitmap? image, string category, object? tag, Func<object?, DFLayoutElement> onClick)
|
|
|
{
|
|
|
- _elements.Clear();
|
|
|
- _elementActions.Clear();
|
|
|
+ Caption = caption;
|
|
|
+ Image = image;
|
|
|
+ Category = category;
|
|
|
+ Tag = tag;
|
|
|
+ OnClick = onClick;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public void AddElementType<TElement>(string caption, string category, bool allowduplicate = false, bool visible = true)
|
|
|
- where TElement : DFLayoutElement
|
|
|
- {
|
|
|
- AddElementType(typeof(TElement), caption, category, allowduplicate, visible: visible);
|
|
|
- }
|
|
|
- public void AddElementType<TElement, TTag>(string caption, string category, TTag tag, Func<TTag, TElement> createElement, bool allowduplicate = false, bool visible = true)
|
|
|
- where TElement : DFLayoutElement
|
|
|
- {
|
|
|
- AddElementType(typeof(TElement), caption, category, tag, createElement, allowduplicate, visible: visible);
|
|
|
- }
|
|
|
+ public void ClearElementTypesAndActions()
|
|
|
+ {
|
|
|
+ _elements.Clear();
|
|
|
+ _elementActions.Clear();
|
|
|
+ }
|
|
|
|
|
|
- public void AddElementType(Type TElement, string caption, string category, bool allowduplicate = false, bool visible = true)
|
|
|
- {
|
|
|
- _elements.Add(new DynamicFormElement(caption, TElement, category, allowduplicate, visible, null, null));
|
|
|
- }
|
|
|
+ public void AddElementType<TElement>(string caption, string category, bool allowduplicate = false, bool visible = true)
|
|
|
+ where TElement : DFLayoutElement
|
|
|
+ {
|
|
|
+ AddElementType(typeof(TElement), caption, category, allowduplicate, visible: visible);
|
|
|
+ }
|
|
|
+ public void AddElementType<TElement, TTag>(string caption, string category, TTag tag, Func<TTag, TElement> createElement, bool allowduplicate = false, bool visible = true)
|
|
|
+ where TElement : DFLayoutElement
|
|
|
+ {
|
|
|
+ AddElementType(typeof(TElement), caption, category, tag, createElement, allowduplicate, visible: visible);
|
|
|
+ }
|
|
|
|
|
|
- public void AddElementType<TTag>(Type TElement, string caption, string category, TTag tag, Func<TTag, DFLayoutElement> createElement, bool allowduplicate = false, bool visible = true)
|
|
|
- {
|
|
|
- _elements.Add(new DynamicFormElement(caption, TElement, category, allowduplicate, visible, tag, x => createElement((TTag)x)));
|
|
|
- }
|
|
|
+ public void AddElementType(Type TElement, string caption, string category, bool allowduplicate = false, bool visible = true)
|
|
|
+ {
|
|
|
+ _elements.Add(new DynamicFormElement(caption, TElement, category, allowduplicate, visible, null, null));
|
|
|
+ }
|
|
|
|
|
|
- public void AddElementAction<TTag>(string caption, Bitmap? image, string category, TTag tag, Func<TTag, DFLayoutElement?> onClick)
|
|
|
- {
|
|
|
- _elementActions.Add(new(caption, image, category, tag, x => onClick((TTag)x)));
|
|
|
- }
|
|
|
+ public void AddElementType<TTag>(Type TElement, string caption, string category, TTag tag, Func<TTag, DFLayoutElement> createElement, bool allowduplicate = false, bool visible = true)
|
|
|
+ {
|
|
|
+ _elements.Add(new DynamicFormElement(caption, TElement, category, allowduplicate, visible, tag, x => createElement((TTag)x)));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AddElementAction<TTag>(string caption, Bitmap? image, string category, TTag tag, Func<TTag, DFLayoutElement?> onClick)
|
|
|
+ {
|
|
|
+ _elementActions.Add(new(caption, image, category, tag, x => onClick((TTag)x)));
|
|
|
+ }
|
|
|
|
|
|
- internal FrameworkElement? CreateElement(DFLayoutElement element)
|
|
|
+ internal FrameworkElement? CreateElement(DFLayoutElement element)
|
|
|
+ {
|
|
|
+ var elementType = element.GetType();
|
|
|
+ if(_elements.FirstOrDefault(x => x.ElementType == elementType) is DynamicFormElement el)
|
|
|
{
|
|
|
- var elementType = element.GetType();
|
|
|
- if(_elements.FirstOrDefault(x => x.ElementType == elementType) is DynamicFormElement el)
|
|
|
- {
|
|
|
- return OnCreateElement?.Invoke(this, new DynamicFormCreateElementArgs(element, el.Caption));
|
|
|
- }
|
|
|
- return null;
|
|
|
+ return OnCreateElement?.Invoke(this, new DynamicFormCreateElementArgs(element, el.Caption));
|
|
|
}
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Utilities
|
|
|
+ #region Utilities
|
|
|
|
|
|
- private static VerticalAlignment GetVerticalAlignment(DFLayoutAlignment alignment)
|
|
|
- {
|
|
|
- return alignment == DFLayoutAlignment.Start
|
|
|
- ? VerticalAlignment.Top
|
|
|
- : alignment == DFLayoutAlignment.End
|
|
|
- ? VerticalAlignment.Bottom
|
|
|
- : alignment == DFLayoutAlignment.Middle
|
|
|
- ? VerticalAlignment.Center
|
|
|
- : VerticalAlignment.Stretch;
|
|
|
- }
|
|
|
+ private static VerticalAlignment GetVerticalAlignment(DFLayoutAlignment alignment)
|
|
|
+ {
|
|
|
+ return alignment == DFLayoutAlignment.Start
|
|
|
+ ? VerticalAlignment.Top
|
|
|
+ : alignment == DFLayoutAlignment.End
|
|
|
+ ? VerticalAlignment.Bottom
|
|
|
+ : alignment == DFLayoutAlignment.Middle
|
|
|
+ ? VerticalAlignment.Center
|
|
|
+ : VerticalAlignment.Stretch;
|
|
|
+ }
|
|
|
|
|
|
- private static HorizontalAlignment GetHorizontalAlignment(DFLayoutAlignment alignment)
|
|
|
- {
|
|
|
- return alignment == DFLayoutAlignment.Start
|
|
|
- ? HorizontalAlignment.Left
|
|
|
- : alignment == DFLayoutAlignment.End
|
|
|
- ? HorizontalAlignment.Right
|
|
|
- : alignment == DFLayoutAlignment.Middle
|
|
|
- ? HorizontalAlignment.Center
|
|
|
- : HorizontalAlignment.Stretch;
|
|
|
- }
|
|
|
+ private static HorizontalAlignment GetHorizontalAlignment(DFLayoutAlignment alignment)
|
|
|
+ {
|
|
|
+ return alignment == DFLayoutAlignment.Start
|
|
|
+ ? HorizontalAlignment.Left
|
|
|
+ : alignment == DFLayoutAlignment.End
|
|
|
+ ? HorizontalAlignment.Right
|
|
|
+ : alignment == DFLayoutAlignment.Middle
|
|
|
+ ? HorizontalAlignment.Center
|
|
|
+ : HorizontalAlignment.Stretch;
|
|
|
+ }
|
|
|
|
|
|
- private static GridLength StringToGridLength(string length)
|
|
|
- {
|
|
|
- if (string.IsNullOrWhiteSpace(length) || string.Equals(length.ToUpper(), "AUTO"))
|
|
|
- return new GridLength(1, GridUnitType.Auto);
|
|
|
+ private static GridLength StringToGridLength(string length)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(length) || string.Equals(length.ToUpper(), "AUTO"))
|
|
|
+ return new GridLength(1, GridUnitType.Auto);
|
|
|
|
|
|
- if (!double.TryParse(length.Replace("*", ""), out var value))
|
|
|
- value = 1.0F;
|
|
|
- var type = length.Contains('*') ? GridUnitType.Star : GridUnitType.Pixel;
|
|
|
- return new GridLength(value, type);
|
|
|
- }
|
|
|
+ if (!double.TryParse(length.Replace("*", ""), out var value))
|
|
|
+ value = 1.0F;
|
|
|
+ var type = length.Contains('*') ? GridUnitType.Star : GridUnitType.Pixel;
|
|
|
+ return new GridLength(value, type);
|
|
|
+ }
|
|
|
|
|
|
- private static string GridLengthToString(GridLength length)
|
|
|
- {
|
|
|
- if (length.IsStar)
|
|
|
- return length.Value == 1.0F ? "*" : string.Format("{0}*", length.Value);
|
|
|
- if (length.IsAuto)
|
|
|
- return "Auto";
|
|
|
- return length.Value.ToString();
|
|
|
- }
|
|
|
+ private static string GridLengthToString(GridLength length)
|
|
|
+ {
|
|
|
+ if (length.IsStar)
|
|
|
+ return length.Value == 1.0F ? "*" : string.Format("{0}*", length.Value);
|
|
|
+ if (length.IsAuto)
|
|
|
+ return "Auto";
|
|
|
+ return length.Value.ToString();
|
|
|
+ }
|
|
|
|
|
|
- private static string FormatGridLength(GridLength length, IEnumerable<GridLength> others)
|
|
|
+ private static string FormatGridLength(GridLength length, IEnumerable<GridLength> others)
|
|
|
+ {
|
|
|
+ if (length.IsStar)
|
|
|
{
|
|
|
- if (length.IsStar)
|
|
|
- {
|
|
|
- double total = 0.0F;
|
|
|
- foreach (var other in others.Where(x => x.IsStar))
|
|
|
- total += other.Value;
|
|
|
- return string.Format("{0:F0}%", total != 0 ? length.Value * 100.0F / total : 0);
|
|
|
- }
|
|
|
-
|
|
|
- if (length.IsAuto)
|
|
|
- return "Auto";
|
|
|
- return string.Format("{0}px", length.Value);
|
|
|
+ double total = 0.0F;
|
|
|
+ foreach (var other in others.Where(x => x.IsStar))
|
|
|
+ total += other.Value;
|
|
|
+ return string.Format("{0:F0}%", total != 0 ? length.Value * 100.0F / total : 0);
|
|
|
}
|
|
|
|
|
|
- private static void AddClick<TTag>(ButtonBase button, TTag tag, Action<TTag> click)
|
|
|
- {
|
|
|
- button.Tag = tag;
|
|
|
- button.Click += (o, e) => click((TTag)(o as FrameworkElement)!.Tag);
|
|
|
- }
|
|
|
+ if (length.IsAuto)
|
|
|
+ return "Auto";
|
|
|
+ return string.Format("{0}px", length.Value);
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ private static void AddClick<TTag>(ButtonBase button, TTag tag, Action<TTag> click)
|
|
|
+ {
|
|
|
+ button.Tag = tag;
|
|
|
+ button.Click += (o, e) => click((TTag)(o as FrameworkElement)!.Tag);
|
|
|
+ }
|
|
|
|
|
|
- #region Design Mode
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Selection
|
|
|
+ #region Design Mode
|
|
|
|
|
|
- private class CellSelection : Border
|
|
|
- {
|
|
|
- private static readonly System.Windows.Media.Color MainSelectionBorder = Colors.LightBlue;
|
|
|
+ #region Selection
|
|
|
|
|
|
- private int startRow;
|
|
|
- private int endRow;
|
|
|
- private int startColumn;
|
|
|
- private int endColumn;
|
|
|
+ private class CellSelection : Border
|
|
|
+ {
|
|
|
+ private static readonly System.Windows.Media.Color MainSelectionBorder = Colors.LightBlue;
|
|
|
+
|
|
|
+ private int startRow;
|
|
|
+ private int endRow;
|
|
|
+ private int startColumn;
|
|
|
+ private int endColumn;
|
|
|
|
|
|
- public int StartRow
|
|
|
+ public int StartRow
|
|
|
+ {
|
|
|
+ get => startRow;
|
|
|
+ set
|
|
|
{
|
|
|
- get => startRow;
|
|
|
- set
|
|
|
- {
|
|
|
- startRow = value;
|
|
|
- UpdatePosition();
|
|
|
- }
|
|
|
+ startRow = value;
|
|
|
+ UpdatePosition();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public int StartColumn
|
|
|
+ public int StartColumn
|
|
|
+ {
|
|
|
+ get => startColumn;
|
|
|
+ set
|
|
|
{
|
|
|
- get => startColumn;
|
|
|
- set
|
|
|
- {
|
|
|
- startColumn = value;
|
|
|
- UpdatePosition();
|
|
|
- }
|
|
|
+ startColumn = value;
|
|
|
+ UpdatePosition();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public int EndRow
|
|
|
+ public int EndRow
|
|
|
+ {
|
|
|
+ get => endRow;
|
|
|
+ set
|
|
|
{
|
|
|
- get => endRow;
|
|
|
- set
|
|
|
- {
|
|
|
- endRow = value;
|
|
|
- UpdatePosition();
|
|
|
- }
|
|
|
+ endRow = value;
|
|
|
+ UpdatePosition();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public int EndColumn
|
|
|
+ public int EndColumn
|
|
|
+ {
|
|
|
+ get => endColumn;
|
|
|
+ set
|
|
|
{
|
|
|
- get => endColumn;
|
|
|
- set
|
|
|
- {
|
|
|
- endColumn = value;
|
|
|
- UpdatePosition();
|
|
|
- }
|
|
|
+ endColumn = value;
|
|
|
+ UpdatePosition();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public bool Selecting = true;
|
|
|
+ public bool Selecting = true;
|
|
|
|
|
|
- public enum SelectionTypes
|
|
|
- {
|
|
|
- Main,
|
|
|
- Secondary,
|
|
|
- Resizable,
|
|
|
- ResizeBackground
|
|
|
- }
|
|
|
+ public enum SelectionTypes
|
|
|
+ {
|
|
|
+ Main,
|
|
|
+ Secondary,
|
|
|
+ Resizable,
|
|
|
+ ResizeBackground
|
|
|
+ }
|
|
|
|
|
|
- public SelectionTypes SelectionType;
|
|
|
+ public SelectionTypes SelectionType;
|
|
|
|
|
|
- public enum Direction
|
|
|
- {
|
|
|
- None,
|
|
|
- Left,
|
|
|
- Right,
|
|
|
- Top,
|
|
|
- Bottom,
|
|
|
- All
|
|
|
- }
|
|
|
- public Direction DragDirection;
|
|
|
- public bool IsDragging => DragDirection != Direction.None;
|
|
|
+ public enum Direction
|
|
|
+ {
|
|
|
+ None,
|
|
|
+ Left,
|
|
|
+ Right,
|
|
|
+ Top,
|
|
|
+ Bottom,
|
|
|
+ All
|
|
|
+ }
|
|
|
+ public Direction DragDirection;
|
|
|
+ public bool IsDragging => DragDirection != Direction.None;
|
|
|
|
|
|
- public bool IsRowSelection => StartColumn == 0;
|
|
|
- public bool IsColumnSelection => StartRow == 0;
|
|
|
+ public bool IsRowSelection => StartColumn == 0;
|
|
|
+ public bool IsColumnSelection => StartRow == 0;
|
|
|
|
|
|
- public CellSelection(int startRow, int startColumn, int endRow, int endColumn, SelectionTypes selectionType)
|
|
|
+ public CellSelection(int startRow, int startColumn, int endRow, int endColumn, SelectionTypes selectionType)
|
|
|
+ {
|
|
|
+ SelectionType = selectionType;
|
|
|
+ switch (selectionType)
|
|
|
{
|
|
|
- SelectionType = selectionType;
|
|
|
- switch (selectionType)
|
|
|
- {
|
|
|
- case SelectionTypes.Main:
|
|
|
- InitialiseMain();
|
|
|
- break;
|
|
|
- case SelectionTypes.Secondary:
|
|
|
- InitialiseSecondary();
|
|
|
- break;
|
|
|
- case SelectionTypes.Resizable:
|
|
|
- InitializeResizable();
|
|
|
- break;
|
|
|
- case SelectionTypes.ResizeBackground:
|
|
|
- InitializeResizeBackground();
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- this.startRow = startRow;
|
|
|
- this.startColumn = startColumn;
|
|
|
- this.endRow = endRow;
|
|
|
- this.endColumn = endColumn;
|
|
|
- UpdatePosition();
|
|
|
+ case SelectionTypes.Main:
|
|
|
+ InitialiseMain();
|
|
|
+ break;
|
|
|
+ case SelectionTypes.Secondary:
|
|
|
+ InitialiseSecondary();
|
|
|
+ break;
|
|
|
+ case SelectionTypes.Resizable:
|
|
|
+ InitializeResizable();
|
|
|
+ break;
|
|
|
+ case SelectionTypes.ResizeBackground:
|
|
|
+ InitializeResizeBackground();
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- private void InitialiseMain()
|
|
|
+ this.startRow = startRow;
|
|
|
+ this.startColumn = startColumn;
|
|
|
+ this.endRow = endRow;
|
|
|
+ this.endColumn = endColumn;
|
|
|
+ UpdatePosition();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitialiseMain()
|
|
|
+ {
|
|
|
+ var colour = MainSelectionBorder;
|
|
|
+ BorderBrush = new SolidColorBrush(colour);
|
|
|
+ Background = new SolidColorBrush(new System.Windows.Media.Color
|
|
|
{
|
|
|
- var colour = MainSelectionBorder;
|
|
|
- BorderBrush = new SolidColorBrush(colour);
|
|
|
- Background = new SolidColorBrush(new System.Windows.Media.Color
|
|
|
- {
|
|
|
- A = (byte)(colour.A / 2),
|
|
|
- R = colour.R,
|
|
|
- G = colour.G,
|
|
|
- B = colour.B
|
|
|
- });
|
|
|
- SetZIndex(this, 2);
|
|
|
- BorderThickness = new Thickness(1);
|
|
|
- }
|
|
|
+ A = (byte)(colour.A / 2),
|
|
|
+ R = colour.R,
|
|
|
+ G = colour.G,
|
|
|
+ B = colour.B
|
|
|
+ });
|
|
|
+ SetZIndex(this, 2);
|
|
|
+ BorderThickness = new Thickness(1);
|
|
|
+ }
|
|
|
|
|
|
- private void InitialiseSecondary()
|
|
|
+ private void InitialiseSecondary()
|
|
|
+ {
|
|
|
+ var rectangle = new Rectangle
|
|
|
{
|
|
|
- var rectangle = new Rectangle
|
|
|
- {
|
|
|
- StrokeDashArray = new DoubleCollection { 4, 4 },
|
|
|
- Stroke = new SolidColorBrush(Colors.Gray),
|
|
|
- StrokeThickness = 1.5
|
|
|
- };
|
|
|
- rectangle.SetBinding(Rectangle.WidthProperty, new Binding("ActualWidth") { Source = this });
|
|
|
- rectangle.SetBinding(Rectangle.HeightProperty, new Binding("ActualHeight") { Source = this });
|
|
|
- var brush = new VisualBrush { Visual = rectangle };
|
|
|
+ StrokeDashArray = new DoubleCollection { 4, 4 },
|
|
|
+ Stroke = new SolidColorBrush(Colors.Gray),
|
|
|
+ StrokeThickness = 1.5
|
|
|
+ };
|
|
|
+ rectangle.SetBinding(Rectangle.WidthProperty, new Binding("ActualWidth") { Source = this });
|
|
|
+ rectangle.SetBinding(Rectangle.HeightProperty, new Binding("ActualHeight") { Source = this });
|
|
|
+ var brush = new VisualBrush { Visual = rectangle };
|
|
|
|
|
|
- BorderBrush = brush;
|
|
|
- BorderThickness = new Thickness(1.5);
|
|
|
- Margin = new Thickness(3);
|
|
|
- }
|
|
|
+ BorderBrush = brush;
|
|
|
+ BorderThickness = new Thickness(1.5);
|
|
|
+ Margin = new Thickness(3);
|
|
|
+ }
|
|
|
|
|
|
- private void InitializeResizable()
|
|
|
+ private void InitializeResizable()
|
|
|
+ {
|
|
|
+ var rectangle = new Rectangle
|
|
|
{
|
|
|
- var rectangle = new Rectangle
|
|
|
- {
|
|
|
- StrokeDashArray = new DoubleCollection { 4, 4 },
|
|
|
- Stroke = new SolidColorBrush(Colors.Gray),
|
|
|
- StrokeThickness = 3
|
|
|
- };
|
|
|
- rectangle.SetBinding(Rectangle.WidthProperty, new Binding("ActualWidth") { Source = this });
|
|
|
- rectangle.SetBinding(Rectangle.HeightProperty, new Binding("ActualHeight") { Source = this });
|
|
|
- var brush = new VisualBrush { Visual = rectangle };
|
|
|
+ StrokeDashArray = new DoubleCollection { 4, 4 },
|
|
|
+ Stroke = new SolidColorBrush(Colors.Gray),
|
|
|
+ StrokeThickness = 3
|
|
|
+ };
|
|
|
+ rectangle.SetBinding(Rectangle.WidthProperty, new Binding("ActualWidth") { Source = this });
|
|
|
+ rectangle.SetBinding(Rectangle.HeightProperty, new Binding("ActualHeight") { Source = this });
|
|
|
+ var brush = new VisualBrush { Visual = rectangle };
|
|
|
|
|
|
- BorderBrush = brush;
|
|
|
+ BorderBrush = brush;
|
|
|
|
|
|
- Background = new SolidColorBrush(Colors.Transparent);
|
|
|
- SetZIndex(this, 2);
|
|
|
- BorderThickness = new Thickness(10);
|
|
|
+ Background = new SolidColorBrush(Colors.Transparent);
|
|
|
+ SetZIndex(this, 2);
|
|
|
+ BorderThickness = new Thickness(10);
|
|
|
|
|
|
- MouseMove += Resizable_MouseMove;
|
|
|
- }
|
|
|
+ MouseMove += Resizable_MouseMove;
|
|
|
+ }
|
|
|
|
|
|
- private void InitializeResizeBackground()
|
|
|
+ private void InitializeResizeBackground()
|
|
|
+ {
|
|
|
+ var colour = Colors.WhiteSmoke;
|
|
|
+ Background = new SolidColorBrush(new System.Windows.Media.Color
|
|
|
{
|
|
|
- var colour = Colors.WhiteSmoke;
|
|
|
- Background = new SolidColorBrush(new System.Windows.Media.Color
|
|
|
- {
|
|
|
- A = (byte)(colour.A / 2),
|
|
|
- R = colour.R,
|
|
|
- G = colour.G,
|
|
|
- B = colour.B
|
|
|
- });
|
|
|
- SetZIndex(this, 1);
|
|
|
- BorderThickness = new Thickness(0);
|
|
|
- }
|
|
|
+ A = (byte)(colour.A / 2),
|
|
|
+ R = colour.R,
|
|
|
+ G = colour.G,
|
|
|
+ B = colour.B
|
|
|
+ });
|
|
|
+ SetZIndex(this, 1);
|
|
|
+ BorderThickness = new Thickness(0);
|
|
|
+ }
|
|
|
|
|
|
- public bool StartDragging(Point position)
|
|
|
- {
|
|
|
- if (!IsMouseDirectlyOver) return false;
|
|
|
+ public bool StartDragging(Point position)
|
|
|
+ {
|
|
|
+ if (!IsMouseDirectlyOver) return false;
|
|
|
|
|
|
- var dX = Math.Min(position.X, ActualWidth - position.X);
|
|
|
- var dY = Math.Min(position.Y, ActualHeight - position.Y);
|
|
|
- if(Math.Min(dX, dY) < 10)
|
|
|
+ var dX = Math.Min(position.X, ActualWidth - position.X);
|
|
|
+ var dY = Math.Min(position.Y, ActualHeight - position.Y);
|
|
|
+ if(Math.Min(dX, dY) < 10)
|
|
|
+ {
|
|
|
+ if (dX < dY)
|
|
|
{
|
|
|
- if (dX < dY)
|
|
|
- {
|
|
|
- DragDirection = position.X < ActualWidth / 2 ? Direction.Left : Direction.Right;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- DragDirection = position.Y < ActualHeight / 2 ? Direction.Top : Direction.Bottom;
|
|
|
- }
|
|
|
+ DragDirection = position.X < ActualWidth / 2 ? Direction.Left : Direction.Right;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- DragDirection = Direction.All;
|
|
|
- return false;
|
|
|
+ DragDirection = position.Y < ActualHeight / 2 ? Direction.Top : Direction.Bottom;
|
|
|
}
|
|
|
- return true;
|
|
|
}
|
|
|
-
|
|
|
- private void Resizable_MouseMove(object sender, MouseEventArgs e)
|
|
|
+ else
|
|
|
{
|
|
|
- if (!IsMouseDirectlyOver || IsDragging) return;
|
|
|
+ DragDirection = Direction.All;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Resizable_MouseMove(object sender, MouseEventArgs e)
|
|
|
+ {
|
|
|
+ if (!IsMouseDirectlyOver || IsDragging) return;
|
|
|
|
|
|
- var position = e.GetPosition(this);
|
|
|
+ var position = e.GetPosition(this);
|
|
|
|
|
|
- var dX = Math.Min(position.X, ActualWidth - position.X);
|
|
|
- var dY = Math.Min(position.Y, ActualHeight - position.Y);
|
|
|
- if (Math.Min(dX, dY) < 10)
|
|
|
+ var dX = Math.Min(position.X, ActualWidth - position.X);
|
|
|
+ var dY = Math.Min(position.Y, ActualHeight - position.Y);
|
|
|
+ if (Math.Min(dX, dY) < 10)
|
|
|
+ {
|
|
|
+ if (dX < dY)
|
|
|
{
|
|
|
- if (dX < dY)
|
|
|
- {
|
|
|
- Cursor = Cursors.SizeWE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Cursor = Cursors.SizeNS;
|
|
|
- }
|
|
|
+ Cursor = Cursors.SizeWE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- Cursor = Cursors.Arrow;
|
|
|
+ Cursor = Cursors.SizeNS;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- public void SetEnd(int endRow, int endColumn)
|
|
|
+ else
|
|
|
{
|
|
|
- this.endRow = endRow;
|
|
|
- this.endColumn = endColumn;
|
|
|
- UpdatePosition();
|
|
|
+ Cursor = Cursors.Arrow;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public void SetSize(int startRow, int startColumn, int endRow, int endColumn)
|
|
|
- {
|
|
|
- this.startRow = startRow;
|
|
|
- this.startColumn = startColumn;
|
|
|
- this.endRow = endRow;
|
|
|
- this.endColumn = endColumn;
|
|
|
- UpdatePosition();
|
|
|
- }
|
|
|
+ public void SetEnd(int endRow, int endColumn)
|
|
|
+ {
|
|
|
+ this.endRow = endRow;
|
|
|
+ this.endColumn = endColumn;
|
|
|
+ UpdatePosition();
|
|
|
+ }
|
|
|
|
|
|
- private void UpdatePosition()
|
|
|
- {
|
|
|
- Grid.SetRow(this, Math.Min(startRow, endRow));
|
|
|
- Grid.SetRowSpan(this, Math.Abs(endRow - startRow) + 1);
|
|
|
+ public void SetSize(int startRow, int startColumn, int endRow, int endColumn)
|
|
|
+ {
|
|
|
+ this.startRow = startRow;
|
|
|
+ this.startColumn = startColumn;
|
|
|
+ this.endRow = endRow;
|
|
|
+ this.endColumn = endColumn;
|
|
|
+ UpdatePosition();
|
|
|
+ }
|
|
|
|
|
|
- Grid.SetColumn(this, Math.Min(startColumn, endColumn));
|
|
|
- Grid.SetColumnSpan(this, Math.Abs(endColumn - startColumn) + 1);
|
|
|
- }
|
|
|
+ private void UpdatePosition()
|
|
|
+ {
|
|
|
+ Grid.SetRow(this, Math.Min(startRow, endRow));
|
|
|
+ Grid.SetRowSpan(this, Math.Abs(endRow - startRow) + 1);
|
|
|
|
|
|
- public CellRange ToRange() => new CellRange(StartRow, StartColumn, EndRow, EndColumn);
|
|
|
+ Grid.SetColumn(this, Math.Min(startColumn, endColumn));
|
|
|
+ Grid.SetColumnSpan(this, Math.Abs(endColumn - startColumn) + 1);
|
|
|
}
|
|
|
|
|
|
- private CellSelection? Selection;
|
|
|
- private Dictionary<DFLayoutControl, CellSelection> SelectedItemsSelections = new();
|
|
|
+ public CellRange ToRange() => new CellRange(StartRow, StartColumn, EndRow, EndColumn);
|
|
|
+ }
|
|
|
|
|
|
- private class Range
|
|
|
- {
|
|
|
- public int Start { get; set; }
|
|
|
+ private CellSelection? Selection;
|
|
|
+ private Dictionary<DFLayoutControl, CellSelection> SelectedItemsSelections = new();
|
|
|
|
|
|
- public int End { get; set; }
|
|
|
+ private class Range
|
|
|
+ {
|
|
|
+ public int Start { get; set; }
|
|
|
|
|
|
- public int Min => Math.Min(Start, End);
|
|
|
- public int Max => Math.Max(Start, End);
|
|
|
+ public int End { get; set; }
|
|
|
|
|
|
- public Range(int start, int end)
|
|
|
- {
|
|
|
- Start = start;
|
|
|
- End = end;
|
|
|
- }
|
|
|
+ public int Min => Math.Min(Start, End);
|
|
|
+ public int Max => Math.Max(Start, End);
|
|
|
|
|
|
- public override string ToString() => $"{Start} -> {End}";
|
|
|
+ public Range(int start, int end)
|
|
|
+ {
|
|
|
+ Start = start;
|
|
|
+ End = end;
|
|
|
}
|
|
|
+
|
|
|
+ public override string ToString() => $"{Start} -> {End}";
|
|
|
+ }
|
|
|
+
|
|
|
+ private class CellRange
|
|
|
+ {
|
|
|
+ public int StartRow { get; set; }
|
|
|
+ public int StartColumn { get; set; }
|
|
|
+ public int EndRow { get; set; }
|
|
|
+ public int EndColumn { get; set; }
|
|
|
+
|
|
|
+ public int MinRow => Math.Min(StartRow, EndRow);
|
|
|
+ public int MinColumn => Math.Min(StartColumn, EndColumn);
|
|
|
|
|
|
- private class CellRange
|
|
|
+ public int MaxRow => Math.Max(StartRow, EndRow);
|
|
|
+ public int MaxColumn => Math.Max(StartColumn, EndColumn);
|
|
|
+
|
|
|
+ public int RowSpan => Math.Abs(EndRow - StartRow) + 1;
|
|
|
+ public int ColumnSpan => Math.Abs(EndColumn - StartColumn) + 1;
|
|
|
+
|
|
|
+ public CellRange(int row, int column)
|
|
|
{
|
|
|
- public int StartRow { get; set; }
|
|
|
- public int StartColumn { get; set; }
|
|
|
- public int EndRow { get; set; }
|
|
|
- public int EndColumn { get; set; }
|
|
|
+ StartRow = row;
|
|
|
+ EndRow = row;
|
|
|
+ StartColumn = column;
|
|
|
+ EndColumn = column;
|
|
|
+ }
|
|
|
|
|
|
- public int MinRow => Math.Min(StartRow, EndRow);
|
|
|
- public int MinColumn => Math.Min(StartColumn, EndColumn);
|
|
|
-
|
|
|
- public int MaxRow => Math.Max(StartRow, EndRow);
|
|
|
- public int MaxColumn => Math.Max(StartColumn, EndColumn);
|
|
|
+ public CellRange(int startRow, int startColumn, int endRow, int endColumn)
|
|
|
+ {
|
|
|
+ StartRow = startRow;
|
|
|
+ EndRow = endRow;
|
|
|
+ StartColumn = startColumn;
|
|
|
+ EndColumn = endColumn;
|
|
|
+ }
|
|
|
|
|
|
- public int RowSpan => Math.Abs(EndRow - StartRow) + 1;
|
|
|
- public int ColumnSpan => Math.Abs(EndColumn - StartColumn) + 1;
|
|
|
+ public override string ToString() => $"({StartColumn}, {StartRow}) -> ({EndColumn}, {EndRow})";
|
|
|
+ }
|
|
|
|
|
|
- public CellRange(int row, int column)
|
|
|
- {
|
|
|
- StartRow = row;
|
|
|
- EndRow = row;
|
|
|
- StartColumn = column;
|
|
|
- EndColumn = column;
|
|
|
- }
|
|
|
-
|
|
|
- public CellRange(int startRow, int startColumn, int endRow, int endColumn)
|
|
|
- {
|
|
|
- StartRow = startRow;
|
|
|
- EndRow = endRow;
|
|
|
- StartColumn = startColumn;
|
|
|
- EndColumn = endColumn;
|
|
|
- }
|
|
|
-
|
|
|
- public override string ToString() => $"({StartColumn}, {StartRow}) -> ({EndColumn}, {EndRow})";
|
|
|
- }
|
|
|
-
|
|
|
- private void ClearSelection()
|
|
|
- {
|
|
|
- if (Selection is null) return;
|
|
|
+ private void ClearSelection()
|
|
|
+ {
|
|
|
+ if (Selection is null) return;
|
|
|
|
|
|
- Children.Remove(Selection);
|
|
|
- Selection = null;
|
|
|
+ Children.Remove(Selection);
|
|
|
+ Selection = null;
|
|
|
|
|
|
- UpdateSecondarySelection();
|
|
|
- }
|
|
|
+ UpdateSecondarySelection();
|
|
|
+ }
|
|
|
|
|
|
- private void StartSelection(int row, int column)
|
|
|
- {
|
|
|
- if (Selection is not null) ClearSelection();
|
|
|
+ private void StartSelection(int row, int column)
|
|
|
+ {
|
|
|
+ if (Selection is not null) ClearSelection();
|
|
|
|
|
|
- Selection = new CellSelection(row, column, row, column, CellSelection.SelectionTypes.Main);
|
|
|
- Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
- Children.Add(Selection);
|
|
|
+ Selection = new CellSelection(row, column, row, column, CellSelection.SelectionTypes.Main);
|
|
|
+ Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
+ Children.Add(Selection);
|
|
|
|
|
|
- UpdateSecondarySelection();
|
|
|
- }
|
|
|
- private void StartRowSelection(int row)
|
|
|
- {
|
|
|
- if (Selection is not null) ClearSelection();
|
|
|
+ UpdateSecondarySelection();
|
|
|
+ }
|
|
|
+ private void StartRowSelection(int row)
|
|
|
+ {
|
|
|
+ if (Selection is not null) ClearSelection();
|
|
|
|
|
|
- Selection = new CellSelection(row, 0, row, ColumnDefinitions.Count - 1, CellSelection.SelectionTypes.Main);
|
|
|
- Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
- Children.Add(Selection);
|
|
|
+ Selection = new CellSelection(row, 0, row, ColumnDefinitions.Count - 1, CellSelection.SelectionTypes.Main);
|
|
|
+ Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
+ Children.Add(Selection);
|
|
|
|
|
|
- UpdateSecondarySelection();
|
|
|
- }
|
|
|
- private void StartColumnSelection(int column)
|
|
|
- {
|
|
|
- if (Selection is not null) ClearSelection();
|
|
|
+ UpdateSecondarySelection();
|
|
|
+ }
|
|
|
+ private void StartColumnSelection(int column)
|
|
|
+ {
|
|
|
+ if (Selection is not null) ClearSelection();
|
|
|
|
|
|
- Selection = new CellSelection(0, column, RowDefinitions.Count - 1, column, CellSelection.SelectionTypes.Main);
|
|
|
- Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
- Children.Add(Selection);
|
|
|
+ Selection = new CellSelection(0, column, RowDefinitions.Count - 1, column, CellSelection.SelectionTypes.Main);
|
|
|
+ Selection.MouseRightButtonDown += Selection_MouseRightButtonDown;
|
|
|
+ Children.Add(Selection);
|
|
|
|
|
|
- UpdateSecondarySelection();
|
|
|
- }
|
|
|
+ UpdateSecondarySelection();
|
|
|
+ }
|
|
|
|
|
|
- private Tuple<int, int> GetRowColIndex(Point point)
|
|
|
+ private Tuple<int, int> GetRowColIndex(Point point)
|
|
|
+ {
|
|
|
+ int rowIdx = -1;
|
|
|
+ int colIdx = -1;
|
|
|
+ for(var c = 0; c < ColumnDefinitions.Count; ++c)
|
|
|
{
|
|
|
- int rowIdx = -1;
|
|
|
- int colIdx = -1;
|
|
|
- for(var c = 0; c < ColumnDefinitions.Count; ++c)
|
|
|
+ var column = ColumnDefinitions[c];
|
|
|
+ if(point.X >= column.Offset && point.X < column.Offset + column.ActualWidth)
|
|
|
{
|
|
|
- var column = ColumnDefinitions[c];
|
|
|
- if(point.X >= column.Offset && point.X < column.Offset + column.ActualWidth)
|
|
|
- {
|
|
|
- colIdx = c;
|
|
|
- break;
|
|
|
- }
|
|
|
+ colIdx = c;
|
|
|
+ break;
|
|
|
}
|
|
|
- for(var r = 0; r < RowDefinitions.Count; ++r)
|
|
|
+ }
|
|
|
+ for(var r = 0; r < RowDefinitions.Count; ++r)
|
|
|
+ {
|
|
|
+ var row = RowDefinitions[r];
|
|
|
+ if(point.Y >= row.Offset && point.Y < row.Offset + row.ActualHeight)
|
|
|
{
|
|
|
- var row = RowDefinitions[r];
|
|
|
- if(point.Y >= row.Offset && point.Y < row.Offset + row.ActualHeight)
|
|
|
- {
|
|
|
- rowIdx = r;
|
|
|
- break;
|
|
|
- }
|
|
|
+ rowIdx = r;
|
|
|
+ break;
|
|
|
}
|
|
|
- return new Tuple<int, int>(rowIdx, colIdx);
|
|
|
}
|
|
|
+ return new Tuple<int, int>(rowIdx, colIdx);
|
|
|
+ }
|
|
|
|
|
|
- private void UpdateSecondarySelection()
|
|
|
+ private void UpdateSecondarySelection()
|
|
|
+ {
|
|
|
+ List<DFLayoutControl> items;
|
|
|
+ if (Selection is null || Selection.IsRowSelection || Selection.IsColumnSelection)
|
|
|
{
|
|
|
- List<DFLayoutControl> items;
|
|
|
- if (Selection is null || Selection.IsRowSelection || Selection.IsColumnSelection)
|
|
|
- {
|
|
|
- items = new List<DFLayoutControl>();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- items = GetSelectedItems().ToList();
|
|
|
- }
|
|
|
+ items = new List<DFLayoutControl>();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ items = GetSelectedItems().ToList();
|
|
|
+ }
|
|
|
|
|
|
- var removes = new List<DFLayoutControl>();
|
|
|
- foreach(var (control, selection) in SelectedItemsSelections)
|
|
|
- {
|
|
|
- if (!items.Contains(control))
|
|
|
- {
|
|
|
- removes.Add(control);
|
|
|
- Children.Remove(selection);
|
|
|
- }
|
|
|
- }
|
|
|
- foreach(var remove in removes)
|
|
|
+ var removes = new List<DFLayoutControl>();
|
|
|
+ foreach(var (control, selection) in SelectedItemsSelections)
|
|
|
+ {
|
|
|
+ if (!items.Contains(control))
|
|
|
{
|
|
|
- SelectedItemsSelections.Remove(remove);
|
|
|
+ removes.Add(control);
|
|
|
+ Children.Remove(selection);
|
|
|
}
|
|
|
+ }
|
|
|
+ foreach(var remove in removes)
|
|
|
+ {
|
|
|
+ SelectedItemsSelections.Remove(remove);
|
|
|
+ }
|
|
|
|
|
|
- foreach(var item in items)
|
|
|
+ foreach(var item in items)
|
|
|
+ {
|
|
|
+ if (!SelectedItemsSelections.ContainsKey(item))
|
|
|
{
|
|
|
- if (!SelectedItemsSelections.ContainsKey(item))
|
|
|
- {
|
|
|
- var selection = new CellSelection(
|
|
|
- item.Row, item.Column,
|
|
|
- item.Row + item.RowSpan - 1, item.Column + item.ColumnSpan - 1,
|
|
|
- CellSelection.SelectionTypes.Secondary);
|
|
|
- SelectedItemsSelections.Add(item, selection);
|
|
|
- Children.Add(selection);
|
|
|
- }
|
|
|
+ var selection = new CellSelection(
|
|
|
+ item.Row, item.Column,
|
|
|
+ item.Row + item.RowSpan - 1, item.Column + item.ColumnSpan - 1,
|
|
|
+ CellSelection.SelectionTypes.Secondary);
|
|
|
+ SelectedItemsSelections.Add(item, selection);
|
|
|
+ Children.Add(selection);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void ContinueSelection(int row, int column)
|
|
|
- {
|
|
|
- if (Selection is null) return;
|
|
|
+ private void ContinueSelection(int row, int column)
|
|
|
+ {
|
|
|
+ if (Selection is null) return;
|
|
|
|
|
|
- row = Math.Max(row, 1);
|
|
|
- column = Math.Max(column, 1);
|
|
|
+ row = Math.Max(row, 1);
|
|
|
+ column = Math.Max(column, 1);
|
|
|
|
|
|
- Selection.Selecting = true;
|
|
|
+ Selection.Selecting = true;
|
|
|
|
|
|
- if (Selection.IsRowSelection)
|
|
|
- {
|
|
|
- Selection.EndRow = row;
|
|
|
- }
|
|
|
- else if (Selection.IsColumnSelection)
|
|
|
- {
|
|
|
- Selection.EndColumn = column;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Selection.SetEnd(row, column);
|
|
|
- }
|
|
|
-
|
|
|
- UpdateSecondarySelection();
|
|
|
+ if (Selection.IsRowSelection)
|
|
|
+ {
|
|
|
+ Selection.EndRow = row;
|
|
|
+ }
|
|
|
+ else if (Selection.IsColumnSelection)
|
|
|
+ {
|
|
|
+ Selection.EndColumn = column;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Selection.SetEnd(row, column);
|
|
|
}
|
|
|
|
|
|
- private void Grid_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
+ UpdateSecondarySelection();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Grid_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
+ {
|
|
|
+ if (!IsDesigning) return;
|
|
|
+ if(Resizer is not null)
|
|
|
{
|
|
|
- if (!IsDesigning) return;
|
|
|
- if(Resizer is not null)
|
|
|
+ if (Resizer.StartDragging(e.GetPosition(Resizer)))
|
|
|
{
|
|
|
- if (Resizer.StartDragging(e.GetPosition(Resizer)))
|
|
|
+ Cursor = Resizer.DragDirection switch
|
|
|
{
|
|
|
- Cursor = Resizer.DragDirection switch
|
|
|
- {
|
|
|
- CellSelection.Direction.All => Cursors.SizeAll,
|
|
|
- CellSelection.Direction.Left or CellSelection.Direction.Right => Cursors.SizeWE,
|
|
|
- _ => Cursors.SizeNS
|
|
|
- };
|
|
|
- if(Resizer.DragDirection == CellSelection.Direction.All)
|
|
|
- {
|
|
|
- StartDragPosition = GetRowColIndex(e.GetPosition(this));
|
|
|
- }
|
|
|
+ CellSelection.Direction.All => Cursors.SizeAll,
|
|
|
+ CellSelection.Direction.Left or CellSelection.Direction.Right => Cursors.SizeWE,
|
|
|
+ _ => Cursors.SizeNS
|
|
|
+ };
|
|
|
+ if(Resizer.DragDirection == CellSelection.Direction.All)
|
|
|
+ {
|
|
|
+ StartDragPosition = GetRowColIndex(e.GetPosition(this));
|
|
|
}
|
|
|
- return;
|
|
|
}
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
+ var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
|
|
|
- if(Selection is not null && (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
|
|
|
+ if(Selection is not null && (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
|
|
|
+ {
|
|
|
+ ContinueSelection(row, column);
|
|
|
+ }
|
|
|
+ else if(Selection is not null && Selection.Selecting)
|
|
|
+ {
|
|
|
+ Selection.Selecting = false;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (column == 0)
|
|
|
{
|
|
|
- ContinueSelection(row, column);
|
|
|
+ if (row == 0) return;
|
|
|
+ StartRowSelection(row);
|
|
|
}
|
|
|
- else if(Selection is not null && Selection.Selecting)
|
|
|
+ else if (row == 0)
|
|
|
{
|
|
|
- Selection.Selecting = false;
|
|
|
+ if (column == 0) return;
|
|
|
+ StartColumnSelection(column);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (column == 0)
|
|
|
- {
|
|
|
- if (row == 0) return;
|
|
|
- StartRowSelection(row);
|
|
|
- }
|
|
|
- else if (row == 0)
|
|
|
- {
|
|
|
- if (column == 0) return;
|
|
|
- StartColumnSelection(column);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- StartSelection(row, column);
|
|
|
- }
|
|
|
+ StartSelection(row, column);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void Grid_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
|
|
+ private void Grid_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
|
|
+ {
|
|
|
+ if (!IsDesigning) return;
|
|
|
+
|
|
|
+ var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
+ if (Resizer is not null)
|
|
|
{
|
|
|
- if (!IsDesigning) return;
|
|
|
+ ResizeMouseMove(sender, e);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
- if (Resizer is not null)
|
|
|
- {
|
|
|
- ResizeMouseMove(sender, e);
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (Selection is null || !Selection.Selecting) return;
|
|
|
+
|
|
|
+ ContinueSelection(row, column);
|
|
|
+ }
|
|
|
|
|
|
- if (Selection is null || !Selection.Selecting) return;
|
|
|
-
|
|
|
- ContinueSelection(row, column);
|
|
|
+ private void Grid_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
+ {
|
|
|
+ if(Resizer is not null)
|
|
|
+ {
|
|
|
+ Resizer.DragDirection = CellSelection.Direction.None;
|
|
|
+ Cursor = Cursors.Arrow;
|
|
|
}
|
|
|
-
|
|
|
- private void Grid_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
+ else if (Selection is not null)
|
|
|
{
|
|
|
- if(Resizer is not null)
|
|
|
- {
|
|
|
- Resizer.DragDirection = CellSelection.Direction.None;
|
|
|
- Cursor = Cursors.Arrow;
|
|
|
- }
|
|
|
- else if (Selection is not null)
|
|
|
- {
|
|
|
- Selection.Selecting = false;
|
|
|
- }
|
|
|
+ Selection.Selecting = false;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private IEnumerable<Tuple<DFLayoutControl, FrameworkElement>> GetSelectedMaps(CellRange? range = null)
|
|
|
- {
|
|
|
- range ??= Selection?.ToRange();
|
|
|
- if (range is null) yield break;
|
|
|
+ private IEnumerable<Tuple<DFLayoutControl, FrameworkElement>> GetSelectedMaps(CellRange? range = null)
|
|
|
+ {
|
|
|
+ range ??= Selection?.ToRange();
|
|
|
+ if (range is null) yield break;
|
|
|
|
|
|
- var minRow = Math.Min(range.StartRow, range.EndRow);
|
|
|
- var maxRow = Math.Max(range.StartRow, range.EndRow);
|
|
|
- var minCol = Math.Min(range.StartColumn, range.EndColumn);
|
|
|
- var maxCol = Math.Max(range.StartColumn, range.EndColumn);
|
|
|
+ var minRow = Math.Min(range.StartRow, range.EndRow);
|
|
|
+ var maxRow = Math.Max(range.StartRow, range.EndRow);
|
|
|
+ var minCol = Math.Min(range.StartColumn, range.EndColumn);
|
|
|
+ var maxCol = Math.Max(range.StartColumn, range.EndColumn);
|
|
|
|
|
|
- foreach(var (control, element) in elementmap)
|
|
|
+ foreach(var (control, element) in elementmap)
|
|
|
+ {
|
|
|
+ if(control.Row <= maxRow && control.Row + control.RowSpan - 1 >= minRow
|
|
|
+ && control.Column <= maxCol && control.Column + control.ColumnSpan - 1 >= minCol)
|
|
|
{
|
|
|
- if(control.Row <= maxRow && control.Row + control.RowSpan - 1 >= minRow
|
|
|
- && control.Column <= maxCol && control.Column + control.ColumnSpan - 1 >= minCol)
|
|
|
- {
|
|
|
- yield return new(control, element);
|
|
|
- }
|
|
|
+ yield return new(control, element);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private IEnumerable<DFLayoutControl> GetSelectedItems(CellRange? range = null) => GetSelectedMaps(range).Select(x => x.Item1);
|
|
|
+ private IEnumerable<DFLayoutControl> GetSelectedItems(CellRange? range = null) => GetSelectedMaps(range).Select(x => x.Item1);
|
|
|
|
|
|
- private void PopulateSelectionMenu(ContextMenu menu)
|
|
|
- {
|
|
|
- if (Selection is null) return;
|
|
|
+ private void PopulateSelectionMenu(ContextMenu menu)
|
|
|
+ {
|
|
|
+ if (Selection is null) return;
|
|
|
|
|
|
- if (Selection.IsRowSelection)
|
|
|
+ if (Selection.IsRowSelection)
|
|
|
+ {
|
|
|
+ var nRows = Math.Abs(Selection.EndRow - Selection.StartRow) + 1;
|
|
|
+ if (nRows == 1)
|
|
|
{
|
|
|
- var nRows = Math.Abs(Selection.EndRow - Selection.StartRow) + 1;
|
|
|
- if (nRows == 1)
|
|
|
- {
|
|
|
- PopulateRowMenu(menu, Selection.StartRow - 1);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- menu.AddItem(nRows == 1 ? "Delete Row" : "Delete Rows", null, new Range(Selection.StartRow - 1, Selection.EndRow - 1), DeleteRows);
|
|
|
- }
|
|
|
+ PopulateRowMenu(menu, Selection.StartRow - 1);
|
|
|
}
|
|
|
- else if (Selection.IsColumnSelection)
|
|
|
+ else
|
|
|
{
|
|
|
- var nColumns = Math.Abs(Selection.EndColumn - Selection.StartColumn) + 1;
|
|
|
- if (nColumns == 1)
|
|
|
- {
|
|
|
- PopulateColumnMenu(menu, Selection.StartColumn - 1);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- menu.AddItem(nColumns == 1 ? "Delete Column" : "Delete Columns", null, new Range(Selection.StartColumn - 1, Selection.EndColumn - 1), DeleteColumns);
|
|
|
- }
|
|
|
+ menu.AddItem(nRows == 1 ? "Delete Row" : "Delete Rows", null, new Range(Selection.StartRow - 1, Selection.EndRow - 1), DeleteRows);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (Selection.IsColumnSelection)
|
|
|
+ {
|
|
|
+ var nColumns = Math.Abs(Selection.EndColumn - Selection.StartColumn) + 1;
|
|
|
+ if (nColumns == 1)
|
|
|
+ {
|
|
|
+ PopulateColumnMenu(menu, Selection.StartColumn - 1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var selectedItems = GetSelectedItems().ToList();
|
|
|
- if (selectedItems.Count == 0)
|
|
|
- {
|
|
|
- PopulateEmptyCellMenu(menu, Selection.ToRange());
|
|
|
- }
|
|
|
- if (selectedItems.Count == 1)
|
|
|
- {
|
|
|
- var item = selectedItems.First();
|
|
|
+ menu.AddItem(nColumns == 1 ? "Delete Column" : "Delete Columns", null, new Range(Selection.StartColumn - 1, Selection.EndColumn - 1), DeleteColumns);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var selectedItems = GetSelectedItems().ToList();
|
|
|
+ if (selectedItems.Count == 0)
|
|
|
+ {
|
|
|
+ PopulateEmptyCellMenu(menu, Selection.ToRange());
|
|
|
+ }
|
|
|
+ if (selectedItems.Count == 1)
|
|
|
+ {
|
|
|
+ var item = selectedItems.First();
|
|
|
|
|
|
- PopulateElementContextMenu(menu, item);
|
|
|
- }
|
|
|
- else if (selectedItems.Count > 1)
|
|
|
- {
|
|
|
- menu.AddItem("Delete Items", null, selectedItems, DeleteElements);
|
|
|
- }
|
|
|
+ PopulateElementContextMenu(menu, item);
|
|
|
+ }
|
|
|
+ else if (selectedItems.Count > 1)
|
|
|
+ {
|
|
|
+ menu.AddItem("Delete Items", null, selectedItems, DeleteElements);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void Selection_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
- {
|
|
|
- if (!IsDesigning || Selection is null) return;
|
|
|
+ private void Selection_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
+ {
|
|
|
+ if (!IsDesigning || Selection is null) return;
|
|
|
|
|
|
- var menu = new ContextMenu();
|
|
|
+ var menu = new ContextMenu();
|
|
|
|
|
|
- PopulateSelectionMenu(menu);
|
|
|
+ PopulateSelectionMenu(menu);
|
|
|
|
|
|
- if(menu.Items.Count == 0)
|
|
|
- {
|
|
|
- menu.AddItem("No actions available", null, null, false);
|
|
|
- }
|
|
|
- menu.IsOpen = true;
|
|
|
+ if(menu.Items.Count == 0)
|
|
|
+ {
|
|
|
+ menu.AddItem("No actions available", null, null, false);
|
|
|
}
|
|
|
+ menu.IsOpen = true;
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Resizing
|
|
|
+ #region Resizing
|
|
|
|
|
|
- private CellSelection? Resizer;
|
|
|
- private Tuple<int, int> StartDragPosition;
|
|
|
+ private CellSelection? Resizer;
|
|
|
+ private Tuple<int, int> StartDragPosition;
|
|
|
|
|
|
- private CellSelection? TopResizeBackground;
|
|
|
- private CellSelection? LeftResizeBackground;
|
|
|
- private CellSelection? RightResizeBackground;
|
|
|
- private CellSelection? BottomResizeBackground;
|
|
|
+ private CellSelection? TopResizeBackground;
|
|
|
+ private CellSelection? LeftResizeBackground;
|
|
|
+ private CellSelection? RightResizeBackground;
|
|
|
+ private CellSelection? BottomResizeBackground;
|
|
|
|
|
|
- private DFLayoutControl? ResizingControl;
|
|
|
+ private DFLayoutControl? ResizingControl;
|
|
|
|
|
|
- private CellSelection GetResizeBackground(ref CellSelection? background)
|
|
|
+ private CellSelection GetResizeBackground(ref CellSelection? background)
|
|
|
+ {
|
|
|
+ if(background is null)
|
|
|
{
|
|
|
- if(background is null)
|
|
|
- {
|
|
|
- background = new CellSelection(0, 0, 0, 0, CellSelection.SelectionTypes.ResizeBackground);
|
|
|
- background.PreviewMouseDown += ResizerBackground_PreviewMouseDown;
|
|
|
- Children.Add(background);
|
|
|
- }
|
|
|
- return background;
|
|
|
+ background = new CellSelection(0, 0, 0, 0, CellSelection.SelectionTypes.ResizeBackground);
|
|
|
+ background.PreviewMouseDown += ResizerBackground_PreviewMouseDown;
|
|
|
+ Children.Add(background);
|
|
|
}
|
|
|
- private void ClearResizeBackground(ref CellSelection? background)
|
|
|
+ return background;
|
|
|
+ }
|
|
|
+ private void ClearResizeBackground(ref CellSelection? background)
|
|
|
+ {
|
|
|
+ if(background is not null)
|
|
|
{
|
|
|
- if(background is not null)
|
|
|
- {
|
|
|
- Children.Remove(background);
|
|
|
- background = null;
|
|
|
- }
|
|
|
+ Children.Remove(background);
|
|
|
+ background = null;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void ResizerBackground_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
|
|
- {
|
|
|
- FinishResize();
|
|
|
- }
|
|
|
+ private void ResizerBackground_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
|
|
+ {
|
|
|
+ FinishResize();
|
|
|
+ }
|
|
|
|
|
|
- private void SetResizerBackgroundSize(CellSelection background, int startRow, int startColumn, int endRow, int endColumn)
|
|
|
- {
|
|
|
- background.SetSize(startRow, startColumn, endRow, endColumn);
|
|
|
- background.Visibility = endColumn >= startColumn && endRow >= startRow ? Visibility.Visible : Visibility.Collapsed;
|
|
|
- }
|
|
|
+ private void SetResizerBackgroundSize(CellSelection background, int startRow, int startColumn, int endRow, int endColumn)
|
|
|
+ {
|
|
|
+ background.SetSize(startRow, startColumn, endRow, endColumn);
|
|
|
+ background.Visibility = endColumn >= startColumn && endRow >= startRow ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ }
|
|
|
|
|
|
- private void UpdateResizer(CellRange newSize)
|
|
|
- {
|
|
|
- if (Resizer is null) return;
|
|
|
+ private void UpdateResizer(CellRange newSize)
|
|
|
+ {
|
|
|
+ if (Resizer is null) return;
|
|
|
|
|
|
- Resizer.StartRow = newSize.StartRow;
|
|
|
- Resizer.StartColumn = newSize.StartColumn;
|
|
|
- Resizer.EndRow = newSize.EndRow;
|
|
|
- Resizer.EndColumn = newSize.EndColumn;
|
|
|
+ Resizer.StartRow = newSize.StartRow;
|
|
|
+ Resizer.StartColumn = newSize.StartColumn;
|
|
|
+ Resizer.EndRow = newSize.EndRow;
|
|
|
+ Resizer.EndColumn = newSize.EndColumn;
|
|
|
|
|
|
- SetResizerBackgroundSize(GetResizeBackground(ref LeftResizeBackground), 0, 0, RowDefinitions.Count - 1, newSize.MinColumn - 1);
|
|
|
- SetResizerBackgroundSize(GetResizeBackground(ref RightResizeBackground), 0, newSize.MaxColumn + 1, RowDefinitions.Count - 1, ColumnDefinitions.Count - 1);
|
|
|
- SetResizerBackgroundSize(GetResizeBackground(ref TopResizeBackground), 0, newSize.MinColumn, newSize.MinRow - 1, newSize.MaxColumn);
|
|
|
- SetResizerBackgroundSize(GetResizeBackground(ref BottomResizeBackground), newSize.MaxRow + 1, newSize.MinColumn, RowDefinitions.Count - 1, newSize.MaxColumn);
|
|
|
- }
|
|
|
+ SetResizerBackgroundSize(GetResizeBackground(ref LeftResizeBackground), 0, 0, RowDefinitions.Count - 1, newSize.MinColumn - 1);
|
|
|
+ SetResizerBackgroundSize(GetResizeBackground(ref RightResizeBackground), 0, newSize.MaxColumn + 1, RowDefinitions.Count - 1, ColumnDefinitions.Count - 1);
|
|
|
+ SetResizerBackgroundSize(GetResizeBackground(ref TopResizeBackground), 0, newSize.MinColumn, newSize.MinRow - 1, newSize.MaxColumn);
|
|
|
+ SetResizerBackgroundSize(GetResizeBackground(ref BottomResizeBackground), newSize.MaxRow + 1, newSize.MinColumn, RowDefinitions.Count - 1, newSize.MaxColumn);
|
|
|
+ }
|
|
|
|
|
|
- private void ResizeMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
|
|
- {
|
|
|
- if (Resizer is null) return;
|
|
|
- if (!Resizer.IsDragging) return;
|
|
|
+ private void ResizeMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
|
|
|
+ {
|
|
|
+ if (Resizer is null) return;
|
|
|
+ if (!Resizer.IsDragging) return;
|
|
|
|
|
|
- var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
+ var (row, column) = GetRowColIndex(e.GetPosition(this));
|
|
|
|
|
|
- var newSize = Resizer.ToRange();
|
|
|
+ var newSize = Resizer.ToRange();
|
|
|
|
|
|
- switch (Resizer.DragDirection)
|
|
|
- {
|
|
|
- case CellSelection.Direction.Right:
|
|
|
- var startColumn = newSize.MinColumn;
|
|
|
- for (int c = column; c >= startColumn; --c)
|
|
|
+ switch (Resizer.DragDirection)
|
|
|
+ {
|
|
|
+ case CellSelection.Direction.Right:
|
|
|
+ var startColumn = newSize.MinColumn;
|
|
|
+ for (int c = column; c >= startColumn; --c)
|
|
|
+ {
|
|
|
+ newSize.StartColumn = startColumn;
|
|
|
+ newSize.EndColumn = Math.Max(c, startColumn);
|
|
|
+ if (ResizeAllowed(newSize))
|
|
|
{
|
|
|
- newSize.StartColumn = startColumn;
|
|
|
- newSize.EndColumn = Math.Max(c, startColumn);
|
|
|
- if (ResizeAllowed(newSize))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
- case CellSelection.Direction.Left:
|
|
|
- var endColumn = newSize.MaxColumn;
|
|
|
- for (int c = column; c <= endColumn; ++c)
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CellSelection.Direction.Left:
|
|
|
+ var endColumn = newSize.MaxColumn;
|
|
|
+ for (int c = column; c <= endColumn; ++c)
|
|
|
+ {
|
|
|
+ newSize.StartColumn = Math.Min(c, endColumn);
|
|
|
+ newSize.EndColumn = endColumn;
|
|
|
+ if (ResizeAllowed(newSize))
|
|
|
{
|
|
|
- newSize.StartColumn = Math.Min(c, endColumn);
|
|
|
- newSize.EndColumn = endColumn;
|
|
|
- if (ResizeAllowed(newSize))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
- case CellSelection.Direction.Bottom:
|
|
|
- var startRow = newSize.MinRow;
|
|
|
- for (int r = row; r >= startRow; --r)
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CellSelection.Direction.Bottom:
|
|
|
+ var startRow = newSize.MinRow;
|
|
|
+ for (int r = row; r >= startRow; --r)
|
|
|
+ {
|
|
|
+ newSize.StartRow = startRow;
|
|
|
+ newSize.EndRow = Math.Max(r, startRow);
|
|
|
+ if (ResizeAllowed(newSize))
|
|
|
{
|
|
|
- newSize.StartRow = startRow;
|
|
|
- newSize.EndRow = Math.Max(r, startRow);
|
|
|
- if (ResizeAllowed(newSize))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
- case CellSelection.Direction.Top:
|
|
|
- var endRow = newSize.MaxRow;
|
|
|
- for (int r = row; r <= endRow; ++r)
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CellSelection.Direction.Top:
|
|
|
+ var endRow = newSize.MaxRow;
|
|
|
+ for (int r = row; r <= endRow; ++r)
|
|
|
+ {
|
|
|
+ newSize.StartRow = Math.Min(r, endRow);
|
|
|
+ newSize.EndRow = endRow;
|
|
|
+ if (ResizeAllowed(newSize))
|
|
|
{
|
|
|
- newSize.StartRow = Math.Min(r, endRow);
|
|
|
- newSize.EndRow = endRow;
|
|
|
- if (ResizeAllowed(newSize))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
- case CellSelection.Direction.None:
|
|
|
- return;
|
|
|
- }
|
|
|
- UpdateResizer(newSize);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CellSelection.Direction.None:
|
|
|
+ return;
|
|
|
}
|
|
|
+ UpdateResizer(newSize);
|
|
|
+ }
|
|
|
|
|
|
- private bool ResizeAllowed(CellRange range)
|
|
|
- {
|
|
|
- var items = GetSelectedItems(range).ToList();
|
|
|
- if (items.Count > 1) return false;
|
|
|
- return items.Count == 0 ||
|
|
|
- (items.Count == 1 && items.First() == ResizingControl);
|
|
|
- }
|
|
|
+ private bool ResizeAllowed(CellRange range)
|
|
|
+ {
|
|
|
+ var items = GetSelectedItems(range).ToList();
|
|
|
+ if (items.Count > 1) return false;
|
|
|
+ return items.Count == 0 ||
|
|
|
+ (items.Count == 1 && items.First() == ResizingControl);
|
|
|
+ }
|
|
|
|
|
|
- private void ClearResize()
|
|
|
- {
|
|
|
- if (Resizer is null) return;
|
|
|
+ private void ClearResize()
|
|
|
+ {
|
|
|
+ if (Resizer is null) return;
|
|
|
|
|
|
- Children.Remove(Resizer);
|
|
|
- Resizer = null;
|
|
|
- ResizingControl = null;
|
|
|
+ Children.Remove(Resizer);
|
|
|
+ Resizer = null;
|
|
|
+ ResizingControl = null;
|
|
|
|
|
|
- ClearResizeBackground(ref LeftResizeBackground);
|
|
|
- ClearResizeBackground(ref RightResizeBackground);
|
|
|
- ClearResizeBackground(ref TopResizeBackground);
|
|
|
- ClearResizeBackground(ref BottomResizeBackground);
|
|
|
- }
|
|
|
+ ClearResizeBackground(ref LeftResizeBackground);
|
|
|
+ ClearResizeBackground(ref RightResizeBackground);
|
|
|
+ ClearResizeBackground(ref TopResizeBackground);
|
|
|
+ ClearResizeBackground(ref BottomResizeBackground);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void FinishResize()
|
|
|
+ {
|
|
|
+ if (Resizer is null) return;
|
|
|
|
|
|
- private void FinishResize()
|
|
|
+ var range = Resizer.ToRange();
|
|
|
+
|
|
|
+ if(ResizingControl is not null)
|
|
|
{
|
|
|
- if (Resizer is null) return;
|
|
|
+ ResizingControl.Row = range.MinRow;
|
|
|
+ ResizingControl.Column = range.MinColumn;
|
|
|
+ ResizingControl.RowSpan = range.RowSpan;
|
|
|
+ ResizingControl.ColumnSpan = range.ColumnSpan;
|
|
|
+ }
|
|
|
+
|
|
|
+ ClearResize();
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- var range = Resizer.ToRange();
|
|
|
+ private void ResizeItem(DFLayoutControl control)
|
|
|
+ {
|
|
|
+ ClearSelection();
|
|
|
+ ClearResize();
|
|
|
|
|
|
- if(ResizingControl is not null)
|
|
|
- {
|
|
|
- ResizingControl.Row = range.MinRow;
|
|
|
- ResizingControl.Column = range.MinColumn;
|
|
|
- ResizingControl.RowSpan = range.RowSpan;
|
|
|
- ResizingControl.ColumnSpan = range.ColumnSpan;
|
|
|
- }
|
|
|
+ Resizer = new CellSelection(
|
|
|
+ control.Row, control.Column,
|
|
|
+ control.Row + control.RowSpan - 1, control.Column + control.ColumnSpan - 1,
|
|
|
+ CellSelection.SelectionTypes.Resizable);
|
|
|
+ ResizingControl = control;
|
|
|
+ Children.Add(Resizer);
|
|
|
|
|
|
- ClearResize();
|
|
|
- Render();
|
|
|
- }
|
|
|
+ UpdateResizer(Resizer.ToRange());
|
|
|
+ }
|
|
|
|
|
|
- private void ResizeItem(DFLayoutControl control)
|
|
|
+ public void HandleKeyDown(KeyEventArgs e)
|
|
|
+ {
|
|
|
+ if (Resizer is null) return;
|
|
|
+ if(e.Key == Key.Enter)
|
|
|
+ {
|
|
|
+ FinishResize();
|
|
|
+ }
|
|
|
+ else if(e.Key == Key.Escape)
|
|
|
{
|
|
|
- ClearSelection();
|
|
|
ClearResize();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- Resizer = new CellSelection(
|
|
|
- control.Row, control.Column,
|
|
|
- control.Row + control.RowSpan - 1, control.Column + control.ColumnSpan - 1,
|
|
|
- CellSelection.SelectionTypes.Resizable);
|
|
|
- ResizingControl = control;
|
|
|
- Children.Add(Resizer);
|
|
|
+ #endregion
|
|
|
|
|
|
- UpdateResizer(Resizer.ToRange());
|
|
|
- }
|
|
|
+ #region Rows
|
|
|
|
|
|
- public void HandleKeyDown(KeyEventArgs e)
|
|
|
- {
|
|
|
- if (Resizer is null) return;
|
|
|
- if(e.Key == Key.Enter)
|
|
|
- {
|
|
|
- FinishResize();
|
|
|
- }
|
|
|
- else if(e.Key == Key.Escape)
|
|
|
- {
|
|
|
- ClearResize();
|
|
|
- }
|
|
|
- }
|
|
|
+ private void ShiftDown(int row)
|
|
|
+ {
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Row > row)
|
|
|
+ element.Row++;
|
|
|
+ else if (element.Row + element.RowSpan - 1 > row)
|
|
|
+ element.RowSpan++;
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ private void AddRowBeforeClick(int row)
|
|
|
+ {
|
|
|
+ var length = new GridLength(1.0F, GridUnitType.Auto);
|
|
|
+ var result = GridLengthToString(length);
|
|
|
+ if (form.RowHeights.Count == 0)
|
|
|
+ form.RowHeights.Add(result);
|
|
|
+ else
|
|
|
+ form.RowHeights.Insert(row, result);
|
|
|
+ ShiftDown(row);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- #region Rows
|
|
|
+ private void AddRowAfterClick(int row)
|
|
|
+ {
|
|
|
+ var length = new GridLength(1.0F, GridUnitType.Auto);
|
|
|
+ var result = GridLengthToString(length);
|
|
|
+ if (row == form.RowHeights.Count - 1)
|
|
|
+ form.RowHeights.Add(result);
|
|
|
+ else
|
|
|
+ form.RowHeights.Insert(row + 1, result);
|
|
|
+ ShiftDown(row + 1);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void ShiftDown(int row)
|
|
|
- {
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Row > row)
|
|
|
- element.Row++;
|
|
|
- else if (element.Row + element.RowSpan - 1 > row)
|
|
|
- element.RowSpan++;
|
|
|
- }
|
|
|
+ private void SplitRow(int row)
|
|
|
+ {
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Row > row)
|
|
|
+ element.Row++;
|
|
|
+ else if (element.Row == row)
|
|
|
+ element.RowSpan++;
|
|
|
+ else if (element.Row + element.RowSpan - 1 >= row)
|
|
|
+ element.RowSpan++;
|
|
|
+ }
|
|
|
|
|
|
- private void AddRowBeforeClick(int row)
|
|
|
- {
|
|
|
- var length = new GridLength(1.0F, GridUnitType.Auto);
|
|
|
- var result = GridLengthToString(length);
|
|
|
- if (form.RowHeights.Count == 0)
|
|
|
- form.RowHeights.Add(result);
|
|
|
- else
|
|
|
- form.RowHeights.Insert(row, result);
|
|
|
- ShiftDown(row);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ private void SplitRowClick(int row)
|
|
|
+ {
|
|
|
+ var height = StringToGridLength(form.RowHeights[row]);
|
|
|
+ var newHeight = height.GridUnitType == GridUnitType.Auto
|
|
|
+ ? height
|
|
|
+ : new GridLength(height.Value / 2, height.GridUnitType);
|
|
|
+ var result = GridLengthToString(newHeight);
|
|
|
+ form.RowHeights[row] = result;
|
|
|
+
|
|
|
+ if (row == form.RowHeights.Count - 1)
|
|
|
+ form.RowHeights.Add(result);
|
|
|
+ else
|
|
|
+ form.RowHeights.Insert(row + 1, result);
|
|
|
+ SplitRow(row + 1);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RowPropertiesClick(int row)
|
|
|
+ {
|
|
|
+ var length = StringToGridLength(form.RowHeights[row]);
|
|
|
|
|
|
- private void AddRowAfterClick(int row)
|
|
|
+ var editor = new DynamicFormDesignLength(length);
|
|
|
+ if (editor.ShowDialog() == true)
|
|
|
{
|
|
|
- var length = new GridLength(1.0F, GridUnitType.Auto);
|
|
|
- var result = GridLengthToString(length);
|
|
|
- if (row == form.RowHeights.Count - 1)
|
|
|
- form.RowHeights.Add(result);
|
|
|
- else
|
|
|
- form.RowHeights.Insert(row + 1, result);
|
|
|
- ShiftDown(row + 1);
|
|
|
+ form.RowHeights[row] = GridLengthToString(editor.GridLength);
|
|
|
Render();
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ShiftUp(int row)
|
|
|
+ {
|
|
|
+ var deletes = new List<DFLayoutControl>();
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Row > row)
|
|
|
+ element.Row--;
|
|
|
+ else if (element.Row == row && element.RowSpan <= 1)
|
|
|
+ deletes.Add(element);
|
|
|
+ else if (element.Row + element.RowSpan - 1 >= row)
|
|
|
+ element.RowSpan--;
|
|
|
+ foreach (var delete in deletes)
|
|
|
+ form.Elements.Remove(delete);
|
|
|
+ }
|
|
|
|
|
|
- private void SplitRow(int row)
|
|
|
+ private void DeleteRows(Range rows)
|
|
|
+ {
|
|
|
+ for(var row = rows.Max; row >= rows.Min; --row)
|
|
|
{
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Row > row)
|
|
|
- element.Row++;
|
|
|
- else if (element.Row == row)
|
|
|
- element.RowSpan++;
|
|
|
- else if (element.Row + element.RowSpan - 1 >= row)
|
|
|
- element.RowSpan++;
|
|
|
+ form.RowHeights.RemoveAt(row);
|
|
|
+ ShiftUp(row + 1);
|
|
|
}
|
|
|
-
|
|
|
- private void SplitRowClick(int row)
|
|
|
+ if(form.RowHeights.Count == 0)
|
|
|
{
|
|
|
- var height = StringToGridLength(form.RowHeights[row]);
|
|
|
- var newHeight = height.GridUnitType == GridUnitType.Auto
|
|
|
- ? height
|
|
|
- : new GridLength(height.Value / 2, height.GridUnitType);
|
|
|
- var result = GridLengthToString(newHeight);
|
|
|
- form.RowHeights[row] = result;
|
|
|
-
|
|
|
- if (row == form.RowHeights.Count - 1)
|
|
|
- form.RowHeights.Add(result);
|
|
|
- else
|
|
|
- form.RowHeights.Insert(row + 1, result);
|
|
|
- SplitRow(row + 1);
|
|
|
- Render();
|
|
|
+ form.RowHeights.Add("Auto");
|
|
|
}
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void RowPropertiesClick(int row)
|
|
|
- {
|
|
|
- var length = StringToGridLength(form.RowHeights[row]);
|
|
|
+ private void PopulateRowMenu(ContextMenu menu, int row)
|
|
|
+ {
|
|
|
+ menu.AddItem("Add Row Before", null, row, AddRowBeforeClick);
|
|
|
+ menu.AddItem("Add Row After", null, row, AddRowAfterClick);
|
|
|
+ menu.AddSeparator();
|
|
|
+ menu.AddItem("Split Row", null, row, SplitRowClick);
|
|
|
|
|
|
- var editor = new DynamicFormDesignLength(length);
|
|
|
- if (editor.ShowDialog() == true)
|
|
|
- {
|
|
|
- form.RowHeights[row] = GridLengthToString(editor.GridLength);
|
|
|
- Render();
|
|
|
- }
|
|
|
- }
|
|
|
+ var propertiesSeparator = menu.AddSeparator();
|
|
|
+ var propertiesMenu = menu.AddItem("Row Properties", null, row, RowPropertiesClick);
|
|
|
|
|
|
- private void ShiftUp(int row)
|
|
|
+ menu.AddSeparator();
|
|
|
+ menu.AddItem("Delete Row", null, new Range(row, row), DeleteRows);
|
|
|
+ menu.Opened += (o, e) =>
|
|
|
{
|
|
|
- var deletes = new List<DFLayoutControl>();
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Row > row)
|
|
|
- element.Row--;
|
|
|
- else if (element.Row == row && element.RowSpan <= 1)
|
|
|
- deletes.Add(element);
|
|
|
- else if (element.Row + element.RowSpan - 1 >= row)
|
|
|
- element.RowSpan--;
|
|
|
- foreach (var delete in deletes)
|
|
|
- form.Elements.Remove(delete);
|
|
|
- }
|
|
|
+ propertiesSeparator.Visibility = form.RowHeights.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ propertiesMenu.Visibility = form.RowHeights.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
- private void DeleteRows(Range rows)
|
|
|
- {
|
|
|
- for(var row = rows.Max; row >= rows.Min; --row)
|
|
|
- {
|
|
|
- form.RowHeights.RemoveAt(row);
|
|
|
- ShiftUp(row + 1);
|
|
|
- }
|
|
|
- if(form.RowHeights.Count == 0)
|
|
|
- {
|
|
|
- form.RowHeights.Add("Auto");
|
|
|
- }
|
|
|
- Render();
|
|
|
- }
|
|
|
+ private ContextMenu CreateRowMenu(Button button, int row)
|
|
|
+ {
|
|
|
+ var result = new ContextMenu();
|
|
|
+ PopulateRowMenu(result, row);
|
|
|
+ button.SetValue(ContextMenuProperty, result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- private void PopulateRowMenu(ContextMenu menu, int row)
|
|
|
- {
|
|
|
- menu.AddItem("Add Row Before", null, row, AddRowBeforeClick);
|
|
|
- menu.AddItem("Add Row After", null, row, AddRowAfterClick);
|
|
|
- menu.AddSeparator();
|
|
|
- menu.AddItem("Split Row", null, row, SplitRowClick);
|
|
|
+ #endregion
|
|
|
|
|
|
- var propertiesSeparator = menu.AddSeparator();
|
|
|
- var propertiesMenu = menu.AddItem("Row Properties", null, row, RowPropertiesClick);
|
|
|
+ #region Columns
|
|
|
|
|
|
- menu.AddSeparator();
|
|
|
- menu.AddItem("Delete Row", null, new Range(row, row), DeleteRows);
|
|
|
- menu.Opened += (o, e) =>
|
|
|
- {
|
|
|
- propertiesSeparator.Visibility = form.RowHeights.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
- propertiesMenu.Visibility = form.RowHeights.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
- };
|
|
|
- }
|
|
|
+ private void ShiftRight(int column)
|
|
|
+ {
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Column > column)
|
|
|
+ element.Column++;
|
|
|
+ else if (element.Column + element.ColumnSpan - 1 > column)
|
|
|
+ element.ColumnSpan++;
|
|
|
+ }
|
|
|
|
|
|
- private ContextMenu CreateRowMenu(Button button, int row)
|
|
|
- {
|
|
|
- var result = new ContextMenu();
|
|
|
- PopulateRowMenu(result, row);
|
|
|
- button.SetValue(ContextMenuProperty, result);
|
|
|
- return result;
|
|
|
- }
|
|
|
+ private void AddColumnBeforeClick(int column)
|
|
|
+ {
|
|
|
+ var length = new GridLength(1.0F, form.ColumnWidths.Count == 0 ? GridUnitType.Star : GridUnitType.Auto);
|
|
|
+ var result = GridLengthToString(length);
|
|
|
+ if (form.ColumnWidths.Count == 0)
|
|
|
+ form.ColumnWidths.Add(result);
|
|
|
+ else
|
|
|
+ form.ColumnWidths.Insert(column, result);
|
|
|
+ ShiftRight(column);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ private void AddColumnAfterClick(int column)
|
|
|
+ {
|
|
|
+ var length = new GridLength(1.0F, form.ColumnWidths.Count == 0 ? GridUnitType.Star : GridUnitType.Auto);
|
|
|
+
|
|
|
+ var result = GridLengthToString(length);
|
|
|
+ if (column == form.ColumnWidths.Count - 1)
|
|
|
+ form.ColumnWidths.Add(result);
|
|
|
+ else
|
|
|
+ form.ColumnWidths.Insert(column + 1, result);
|
|
|
+ ShiftRight(column + 1);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- #region Columns
|
|
|
+ private void SplitColumn(int column)
|
|
|
+ {
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Column > column)
|
|
|
+ element.Column++;
|
|
|
+ else if (element.Column == column)
|
|
|
+ element.ColumnSpan++;
|
|
|
+ else if (element.Column + element.ColumnSpan - 1 >= column)
|
|
|
+ element.ColumnSpan++;
|
|
|
+ }
|
|
|
|
|
|
- private void ShiftRight(int column)
|
|
|
- {
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Column > column)
|
|
|
- element.Column++;
|
|
|
- else if (element.Column + element.ColumnSpan - 1 > column)
|
|
|
- element.ColumnSpan++;
|
|
|
- }
|
|
|
+ private void SplitColumnClick(int column)
|
|
|
+ {
|
|
|
+ var length = StringToGridLength(form.ColumnWidths[column]);
|
|
|
+ var newLength = length.GridUnitType == GridUnitType.Auto
|
|
|
+ ? length
|
|
|
+ : new GridLength(length.Value / 2, length.GridUnitType);
|
|
|
+ var result = GridLengthToString(newLength);
|
|
|
+ form.ColumnWidths[column] = result;
|
|
|
+
|
|
|
+ if (column == form.ColumnWidths.Count - 1)
|
|
|
+ form.ColumnWidths.Add(result);
|
|
|
+ else
|
|
|
+ form.ColumnWidths.Insert(column + 1, result);
|
|
|
+ SplitColumn(column + 1);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void AddColumnBeforeClick(int column)
|
|
|
+ private void ColumnPropertiesClick(int column)
|
|
|
+ {
|
|
|
+ var length = StringToGridLength(form.ColumnWidths[column]);
|
|
|
+
|
|
|
+ var editor = new DynamicFormDesignLength(length);
|
|
|
+ if (editor.ShowDialog() == true)
|
|
|
{
|
|
|
- var length = new GridLength(1.0F, form.ColumnWidths.Count == 0 ? GridUnitType.Star : GridUnitType.Auto);
|
|
|
- var result = GridLengthToString(length);
|
|
|
- if (form.ColumnWidths.Count == 0)
|
|
|
- form.ColumnWidths.Add(result);
|
|
|
- else
|
|
|
- form.ColumnWidths.Insert(column, result);
|
|
|
- ShiftRight(column);
|
|
|
+ form.ColumnWidths[column] = GridLengthToString(editor.GridLength);
|
|
|
Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void AddColumnAfterClick(int column)
|
|
|
- {
|
|
|
- var length = new GridLength(1.0F, form.ColumnWidths.Count == 0 ? GridUnitType.Star : GridUnitType.Auto);
|
|
|
+ private void ShiftLeft(int column)
|
|
|
+ {
|
|
|
+ var deletes = new List<DFLayoutControl>();
|
|
|
+ foreach (var element in form.Elements)
|
|
|
+ if (element.Column > column)
|
|
|
+ element.Column--;
|
|
|
+ else if (element.Column == column && element.ColumnSpan <= 1)
|
|
|
+ deletes.Add(element);
|
|
|
+ else if (element.Column + element.ColumnSpan - 1 >= column)
|
|
|
+ element.ColumnSpan--;
|
|
|
+ foreach (var delete in deletes)
|
|
|
+ form.Elements.Remove(delete);
|
|
|
+ }
|
|
|
|
|
|
- var result = GridLengthToString(length);
|
|
|
- if (column == form.ColumnWidths.Count - 1)
|
|
|
- form.ColumnWidths.Add(result);
|
|
|
- else
|
|
|
- form.ColumnWidths.Insert(column + 1, result);
|
|
|
- ShiftRight(column + 1);
|
|
|
- Render();
|
|
|
+ private void DeleteColumns(Range columns)
|
|
|
+ {
|
|
|
+ for(var column = columns.Max; column >= columns.Min; --column)
|
|
|
+ {
|
|
|
+ form.ColumnWidths.RemoveAt(column);
|
|
|
+ ShiftLeft(column + 1);
|
|
|
}
|
|
|
-
|
|
|
- private void SplitColumn(int column)
|
|
|
+ if(form.ColumnWidths.Count == 0)
|
|
|
{
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Column > column)
|
|
|
- element.Column++;
|
|
|
- else if (element.Column == column)
|
|
|
- element.ColumnSpan++;
|
|
|
- else if (element.Column + element.ColumnSpan - 1 >= column)
|
|
|
- element.ColumnSpan++;
|
|
|
+ form.ColumnWidths.Add("*");
|
|
|
}
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void SplitColumnClick(int column)
|
|
|
- {
|
|
|
- var length = StringToGridLength(form.ColumnWidths[column]);
|
|
|
- var newLength = length.GridUnitType == GridUnitType.Auto
|
|
|
- ? length
|
|
|
- : new GridLength(length.Value / 2, length.GridUnitType);
|
|
|
- var result = GridLengthToString(newLength);
|
|
|
- form.ColumnWidths[column] = result;
|
|
|
+ private void PopulateColumnMenu(ContextMenu menu, int column)
|
|
|
+ {
|
|
|
+ menu.AddItem("Add Column Before", null, column, AddColumnBeforeClick);
|
|
|
+ menu.AddItem("Add Column After", null, column, AddColumnAfterClick);
|
|
|
+ menu.AddSeparator();
|
|
|
+ menu.AddItem("Split Column", null, column, SplitColumnClick);
|
|
|
+ var propertiesSeparator = menu.AddSeparator();
|
|
|
+ var propertiesMenu = menu.AddItem("Column Properties", null, column, ColumnPropertiesClick);
|
|
|
+ menu.AddSeparator();
|
|
|
+ menu.AddItem("Delete Column", null, new Range(column, column), DeleteColumns);
|
|
|
+ menu.Opened += (o, e) =>
|
|
|
+ {
|
|
|
+ propertiesSeparator.Visibility = form.ColumnWidths.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ propertiesMenu.Visibility = form.ColumnWidths.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
- if (column == form.ColumnWidths.Count - 1)
|
|
|
- form.ColumnWidths.Add(result);
|
|
|
- else
|
|
|
- form.ColumnWidths.Insert(column + 1, result);
|
|
|
- SplitColumn(column + 1);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ private ContextMenu CreateColumnMenu(Button button, int column)
|
|
|
+ {
|
|
|
+ var result = new ContextMenu();
|
|
|
+ PopulateColumnMenu(result, column);
|
|
|
+ button.SetValue(ContextMenuProperty, result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- private void ColumnPropertiesClick(int column)
|
|
|
- {
|
|
|
- var length = StringToGridLength(form.ColumnWidths[column]);
|
|
|
+ #endregion
|
|
|
|
|
|
- var editor = new DynamicFormDesignLength(length);
|
|
|
- if (editor.ShowDialog() == true)
|
|
|
- {
|
|
|
- form.ColumnWidths[column] = GridLengthToString(editor.GridLength);
|
|
|
- Render();
|
|
|
- }
|
|
|
- }
|
|
|
+ #region Add Element
|
|
|
|
|
|
- private void ShiftLeft(int column)
|
|
|
+ private void AddNewElement<TElement>(DynamicFormElement elementDef, CellRange range)
|
|
|
+ where TElement : DFLayoutElement, new()
|
|
|
+ {
|
|
|
+ TElement? element;
|
|
|
+ if (elementDef.CreateElement is not null)
|
|
|
{
|
|
|
- var deletes = new List<DFLayoutControl>();
|
|
|
- foreach (var element in form.Elements)
|
|
|
- if (element.Column > column)
|
|
|
- element.Column--;
|
|
|
- else if (element.Column == column && element.ColumnSpan <= 1)
|
|
|
- deletes.Add(element);
|
|
|
- else if (element.Column + element.ColumnSpan - 1 >= column)
|
|
|
- element.ColumnSpan--;
|
|
|
- foreach (var delete in deletes)
|
|
|
- form.Elements.Remove(delete);
|
|
|
+ element = elementDef.CreateElement(elementDef.Tag) as TElement;
|
|
|
}
|
|
|
-
|
|
|
- private void DeleteColumns(Range columns)
|
|
|
+ else
|
|
|
{
|
|
|
- for(var column = columns.Max; column >= columns.Min; --column)
|
|
|
- {
|
|
|
- form.ColumnWidths.RemoveAt(column);
|
|
|
- ShiftLeft(column + 1);
|
|
|
- }
|
|
|
- if(form.ColumnWidths.Count == 0)
|
|
|
- {
|
|
|
- form.ColumnWidths.Add("*");
|
|
|
- }
|
|
|
- Render();
|
|
|
+ element = new();
|
|
|
}
|
|
|
-
|
|
|
- private void PopulateColumnMenu(ContextMenu menu, int column)
|
|
|
+ if(element is null)
|
|
|
{
|
|
|
- menu.AddItem("Add Column Before", null, column, AddColumnBeforeClick);
|
|
|
- menu.AddItem("Add Column After", null, column, AddColumnAfterClick);
|
|
|
- menu.AddSeparator();
|
|
|
- menu.AddItem("Split Column", null, column, SplitColumnClick);
|
|
|
- var propertiesSeparator = menu.AddSeparator();
|
|
|
- var propertiesMenu = menu.AddItem("Column Properties", null, column, ColumnPropertiesClick);
|
|
|
- menu.AddSeparator();
|
|
|
- menu.AddItem("Delete Column", null, new Range(column, column), DeleteColumns);
|
|
|
- menu.Opened += (o, e) =>
|
|
|
- {
|
|
|
- propertiesSeparator.Visibility = form.ColumnWidths.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
- propertiesMenu.Visibility = form.ColumnWidths.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
- };
|
|
|
+ return;
|
|
|
}
|
|
|
+ SetControlRange(element, range);
|
|
|
|
|
|
- private ContextMenu CreateColumnMenu(Button button, int column)
|
|
|
+ var result = new FormControlGrid<TElement>().EditItems(new[] { element });
|
|
|
+ if (result)
|
|
|
{
|
|
|
- var result = new ContextMenu();
|
|
|
- PopulateColumnMenu(result, column);
|
|
|
- button.SetValue(ContextMenuProperty, result);
|
|
|
- return result;
|
|
|
+ form.Elements.Add(element);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
-
|
|
|
- #region Add Element
|
|
|
+ private void AddElementClick(Tuple<DynamicFormElement, CellRange> tuple)
|
|
|
+ {
|
|
|
+ var method = typeof(DynamicFormDesignGrid)
|
|
|
+ .GetMethod(nameof(AddNewElement), BindingFlags.NonPublic | BindingFlags.Instance)!
|
|
|
+ .MakeGenericMethod(tuple.Item1.ElementType);
|
|
|
+ method.Invoke(this, new object[] { tuple.Item1, tuple.Item2 });
|
|
|
+ }
|
|
|
|
|
|
- private void AddNewElement<TElement>(DynamicFormElement elementDef, CellRange range)
|
|
|
- where TElement : DFLayoutElement, new()
|
|
|
+ private void ElementActionClick(Tuple<DynamicFormElementAction, CellRange> tuple)
|
|
|
+ {
|
|
|
+ var element = tuple.Item1.OnClick(tuple.Item1.Tag);
|
|
|
+ if(element is not null)
|
|
|
{
|
|
|
- TElement? element;
|
|
|
- if (elementDef.CreateElement is not null)
|
|
|
- {
|
|
|
- element = elementDef.CreateElement(elementDef.Tag) as TElement;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- element = new();
|
|
|
- }
|
|
|
- if(element is null)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- SetControlRange(element, range);
|
|
|
-
|
|
|
- var result = new FormControlGrid<TElement>().EditItems(new[] { element });
|
|
|
- if (result)
|
|
|
- {
|
|
|
- form.Elements.Add(element);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ SetControlRange(element, tuple.Item2);
|
|
|
+ form.Elements.Add(element);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void AddElementClick(Tuple<DynamicFormElement, CellRange> tuple)
|
|
|
- {
|
|
|
- var method = typeof(DynamicFormDesignGrid)
|
|
|
- .GetMethod(nameof(AddNewElement), BindingFlags.NonPublic | BindingFlags.Instance)!
|
|
|
- .MakeGenericMethod(tuple.Item1.ElementType);
|
|
|
- method.Invoke(this, new object[] { tuple.Item1, tuple.Item2 });
|
|
|
- }
|
|
|
+ private void SetControlRange(DFLayoutControl control, CellRange range)
|
|
|
+ {
|
|
|
+ var minRow = Math.Min(range.StartRow, range.EndRow);
|
|
|
+ var maxRow = Math.Max(range.StartRow, range.EndRow);
|
|
|
+ var minColumn = Math.Min(range.StartColumn, range.EndColumn);
|
|
|
+ var maxColumn = Math.Max(range.StartColumn, range.EndColumn);
|
|
|
+
|
|
|
+ control.Row = minRow;
|
|
|
+ control.RowSpan = (maxRow - minRow) + 1;
|
|
|
+ control.Column = minColumn;
|
|
|
+ control.ColumnSpan = (maxColumn - minColumn) + 1;
|
|
|
+ }
|
|
|
|
|
|
- private void ElementActionClick(Tuple<DynamicFormElementAction, CellRange> tuple)
|
|
|
+ private void CreateLabelClick(CellRange range)
|
|
|
+ {
|
|
|
+ var label = new DFLayoutLabel();
|
|
|
+ SetControlRange(label, range);
|
|
|
+ var result = new FormControlGrid<DFLayoutLabel>().EditItems(new[] { label });
|
|
|
+ if (result)
|
|
|
{
|
|
|
- var element = tuple.Item1.OnClick(tuple.Item1.Tag);
|
|
|
- if(element is not null)
|
|
|
- {
|
|
|
- SetControlRange(element, tuple.Item2);
|
|
|
- form.Elements.Add(element);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ form.Elements.Add(label);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void SetControlRange(DFLayoutControl control, CellRange range)
|
|
|
+ private void CreateHeaderClick(CellRange range)
|
|
|
+ {
|
|
|
+ var header = new DFLayoutHeader();
|
|
|
+ SetControlRange(header, range);
|
|
|
+ var result = new FormControlGrid<DFLayoutHeader>().EditItems(new[] { header });
|
|
|
+ if (result)
|
|
|
{
|
|
|
- var minRow = Math.Min(range.StartRow, range.EndRow);
|
|
|
- var maxRow = Math.Max(range.StartRow, range.EndRow);
|
|
|
- var minColumn = Math.Min(range.StartColumn, range.EndColumn);
|
|
|
- var maxColumn = Math.Max(range.StartColumn, range.EndColumn);
|
|
|
-
|
|
|
- control.Row = minRow;
|
|
|
- control.RowSpan = (maxRow - minRow) + 1;
|
|
|
- control.Column = minColumn;
|
|
|
- control.ColumnSpan = (maxColumn - minColumn) + 1;
|
|
|
+ form.Elements.Add(header);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void CreateLabelClick(CellRange range)
|
|
|
+ private void CreateImageClick(CellRange range)
|
|
|
+ {
|
|
|
+ var image = new DFLayoutImage();
|
|
|
+ SetControlRange(image, range);
|
|
|
+ var result = new FormControlGrid<DFLayoutImage>().EditItems(new[] { image });
|
|
|
+ if (result)
|
|
|
{
|
|
|
- var label = new DFLayoutLabel();
|
|
|
- SetControlRange(label, range);
|
|
|
- var result = new FormControlGrid<DFLayoutLabel>().EditItems(new[] { label });
|
|
|
- if (result)
|
|
|
- {
|
|
|
- form.Elements.Add(label);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ form.Elements.Add(image);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void CreateHeaderClick(CellRange range)
|
|
|
+ private void AddVariable(Tuple<DigitalFormVariable, CellRange> tuple)
|
|
|
+ {
|
|
|
+ if(Activator.CreateInstance(tuple.Item1.FieldType()) is not DFLayoutField field)
|
|
|
{
|
|
|
- var header = new DFLayoutHeader();
|
|
|
- SetControlRange(header, range);
|
|
|
- var result = new FormControlGrid<DFLayoutHeader>().EditItems(new[] { header });
|
|
|
- if (result)
|
|
|
- {
|
|
|
- form.Elements.Add(header);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ MessageBox.Show(string.Format("{0}: Unknown Type {1}", tuple.Item1.Code, tuple.Item1.VariableType.ToString()));
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- private void CreateImageClick(CellRange range)
|
|
|
- {
|
|
|
- var image = new DFLayoutImage();
|
|
|
- SetControlRange(image, range);
|
|
|
- var result = new FormControlGrid<DFLayoutImage>().EditItems(new[] { image });
|
|
|
- if (result)
|
|
|
- {
|
|
|
- form.Elements.Add(image);
|
|
|
- Render();
|
|
|
- }
|
|
|
- }
|
|
|
+ field.Name = tuple.Item1.Code;
|
|
|
+ SetControlRange(field, tuple.Item2);
|
|
|
+ form.Elements.Add(field);
|
|
|
+ form.LoadVariable(tuple.Item1, field);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void AddVariable(Tuple<DigitalFormVariable, CellRange> tuple)
|
|
|
- {
|
|
|
- if(Activator.CreateInstance(tuple.Item1.FieldType()) is not DFLayoutField field)
|
|
|
- {
|
|
|
- MessageBox.Show(string.Format("{0}: Unknown Type {1}", tuple.Item1.Code, tuple.Item1.VariableType.ToString()));
|
|
|
- return;
|
|
|
- }
|
|
|
+ private void PopulateEmptyCellMenu(ContextMenu menu, CellRange cellRange)
|
|
|
+ {
|
|
|
+ menu.Items.Clear();
|
|
|
+ menu.AddItem("Add Label", null, cellRange, CreateLabelClick);
|
|
|
+ menu.AddItem("Add Header", null, cellRange, CreateHeaderClick);
|
|
|
+ menu.AddItem("Add Image", null, cellRange, CreateImageClick);
|
|
|
|
|
|
- field.Name = tuple.Item1.Code;
|
|
|
- SetControlRange(field, tuple.Item2);
|
|
|
- form.Elements.Add(field);
|
|
|
- form.LoadVariable(tuple.Item1, field);
|
|
|
- Render();
|
|
|
- }
|
|
|
+ var fields = menu.AddItem("Add Field", null, null);
|
|
|
|
|
|
- private void PopulateEmptyCellMenu(ContextMenu menu, CellRange cellRange)
|
|
|
+ if (OnCreateVariable is not null)
|
|
|
{
|
|
|
- menu.Items.Clear();
|
|
|
- menu.AddItem("Add Label", null, cellRange, CreateLabelClick);
|
|
|
- menu.AddItem("Add Header", null, cellRange, CreateHeaderClick);
|
|
|
- menu.AddItem("Add Image", null, cellRange, CreateImageClick);
|
|
|
+ var variables = fields.AddItem("Create new variable", null, null);
|
|
|
|
|
|
- var fields = menu.AddItem("Add Field", null, null);
|
|
|
-
|
|
|
- if (OnCreateVariable is not null)
|
|
|
+ foreach (var fieldType in DFUtils.GetFieldTypes())
|
|
|
{
|
|
|
- var variables = fields.AddItem("Create new variable", null, null);
|
|
|
-
|
|
|
- foreach (var fieldType in DFUtils.GetFieldTypes())
|
|
|
+ var caption = fieldType.GetCaption();
|
|
|
+ if (string.IsNullOrWhiteSpace(caption))
|
|
|
+ {
|
|
|
+ caption = CoreUtils.Neatify(fieldType.Name);
|
|
|
+ }
|
|
|
+ variables.AddItem(caption, null, new Tuple<Type, CellRange>(fieldType, cellRange), (tuple) =>
|
|
|
{
|
|
|
- var caption = fieldType.GetCaption();
|
|
|
- if (string.IsNullOrWhiteSpace(caption))
|
|
|
+ var variable = OnCreateVariable?.Invoke(tuple.Item1);
|
|
|
+ if (variable is not null)
|
|
|
{
|
|
|
- caption = CoreUtils.Neatify(fieldType.Name);
|
|
|
+ _variables.Add(variable);
|
|
|
+ AddVariable(new(variable, tuple.Item2));
|
|
|
}
|
|
|
- variables.AddItem(caption, null, new Tuple<Type, CellRange>(fieldType, cellRange), (tuple) =>
|
|
|
- {
|
|
|
- var variable = OnCreateVariable?.Invoke(tuple.Item1);
|
|
|
- if (variable is not null)
|
|
|
- {
|
|
|
- _variables.Add(variable);
|
|
|
- AddVariable(new(variable, tuple.Item2));
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ });
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- var filtered = _variables.Where(x => !x.Hidden && !form.Elements.Any(v => string.Equals((v as DFLayoutField)?.Name, x.Code)));
|
|
|
- fields.AddSeparatorIfNeeded();
|
|
|
- foreach (var variable in filtered)
|
|
|
- fields.AddItem(variable.Code, null, new Tuple<DigitalFormVariable, CellRange>(variable, cellRange), AddVariable);
|
|
|
- fields.RemoveUnnecessarySeparators();
|
|
|
- if(fields.Items.Count == 0)
|
|
|
- {
|
|
|
- menu.Items.Remove(fields);
|
|
|
- }
|
|
|
+ var filtered = _variables.Where(x => !x.Hidden && !form.Elements.Any(v => string.Equals((v as DFLayoutField)?.Name, x.Code)));
|
|
|
+ fields.AddSeparatorIfNeeded();
|
|
|
+ foreach (var variable in filtered)
|
|
|
+ fields.AddItem(variable.Code, null, new Tuple<DigitalFormVariable, CellRange>(variable, cellRange), AddVariable);
|
|
|
+ fields.RemoveUnnecessarySeparators();
|
|
|
+ if(fields.Items.Count == 0)
|
|
|
+ {
|
|
|
+ menu.Items.Remove(fields);
|
|
|
+ }
|
|
|
|
|
|
- var elements = menu.AddItem("Add Object", null, cellRange, null);
|
|
|
+ var elements = menu.AddItem("Add Object", null, cellRange, null);
|
|
|
|
|
|
- var available = _elements.Where(x => x.Visible && (x.AllowDuplicate || !form.Elements.Any(v => (v as DFLayoutElement)?.GetType() == x.ElementType)))
|
|
|
- .ToArray();
|
|
|
+ var available = _elements.Where(x => x.Visible && (x.AllowDuplicate || !form.Elements.Any(v => (v as DFLayoutElement)?.GetType() == x.ElementType)))
|
|
|
+ .ToArray();
|
|
|
|
|
|
- var cats = available.Select(x => x.Category).Concat(_elementActions.Select(x => x.Category)).Distinct().OrderBy(x => x);
|
|
|
- foreach (var cat in cats)
|
|
|
+ var cats = available.Select(x => x.Category).Concat(_elementActions.Select(x => x.Category)).Distinct().OrderBy(x => x);
|
|
|
+ foreach (var cat in cats)
|
|
|
+ {
|
|
|
+ var parentMenu = elements;
|
|
|
+ if (!string.IsNullOrWhiteSpace(cat))
|
|
|
{
|
|
|
- var parentMenu = elements;
|
|
|
- if (!string.IsNullOrWhiteSpace(cat))
|
|
|
- {
|
|
|
- parentMenu = elements.AddItem(cat, null, null);
|
|
|
- }
|
|
|
-
|
|
|
- foreach(var action in _elementActions.Where(x => x.Category == cat))
|
|
|
- {
|
|
|
- parentMenu.AddItem(action.Caption, action.Image, new Tuple<DynamicFormElementAction, CellRange>(action, cellRange), ElementActionClick);
|
|
|
- }
|
|
|
-
|
|
|
- parentMenu.AddSeparatorIfNeeded();
|
|
|
+ parentMenu = elements.AddItem(cat, null, null);
|
|
|
+ }
|
|
|
|
|
|
- foreach (var element in available.Where(x => string.Equals(x.Category, cat)))
|
|
|
- parentMenu.AddItem(element.Caption, null, new Tuple<DynamicFormElement, CellRange>(element, cellRange), AddElementClick);
|
|
|
- parentMenu.RemoveUnnecessarySeparators();
|
|
|
+ foreach(var action in _elementActions.Where(x => x.Category == cat))
|
|
|
+ {
|
|
|
+ parentMenu.AddItem(action.Caption, action.Image, new Tuple<DynamicFormElementAction, CellRange>(action, cellRange), ElementActionClick);
|
|
|
}
|
|
|
|
|
|
- if (elements.Items.Count == 0)
|
|
|
- menu.Items.Remove(elements);
|
|
|
+ parentMenu.AddSeparatorIfNeeded();
|
|
|
+
|
|
|
+ foreach (var element in available.Where(x => string.Equals(x.Category, cat)))
|
|
|
+ parentMenu.AddItem(element.Caption, null, new Tuple<DynamicFormElement, CellRange>(element, cellRange), AddElementClick);
|
|
|
+ parentMenu.RemoveUnnecessarySeparators();
|
|
|
}
|
|
|
|
|
|
- private ContextMenu CreateEmptyCellMenu(Border border, int row, int column)
|
|
|
- {
|
|
|
- var result = new ContextMenu();
|
|
|
- result.Opened += (o, e) =>
|
|
|
- {
|
|
|
- PopulateEmptyCellMenu(result, new CellRange(row, column));
|
|
|
- };
|
|
|
+ if (elements.Items.Count == 0)
|
|
|
+ menu.Items.Remove(elements);
|
|
|
+ }
|
|
|
|
|
|
- border.SetValue(ContextMenuProperty, result);
|
|
|
- return result;
|
|
|
- }
|
|
|
+ private ContextMenu CreateEmptyCellMenu(Border border, int row, int column)
|
|
|
+ {
|
|
|
+ var result = new ContextMenu();
|
|
|
+ result.Opened += (o, e) =>
|
|
|
+ {
|
|
|
+ PopulateEmptyCellMenu(result, new CellRange(row, column));
|
|
|
+ };
|
|
|
|
|
|
- #endregion
|
|
|
+ border.SetValue(ContextMenuProperty, result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- #region Element Context Menu
|
|
|
+ #endregion
|
|
|
|
|
|
- private void DeleteElements(IEnumerable<DFLayoutControl> controls)
|
|
|
- {
|
|
|
- foreach(var control in controls)
|
|
|
- {
|
|
|
- if (form.Elements.Contains(control))
|
|
|
- {
|
|
|
- form.Elements.Remove(control);
|
|
|
- }
|
|
|
- }
|
|
|
- Render();
|
|
|
- }
|
|
|
+ #region Element Context Menu
|
|
|
|
|
|
- private void DeleteElementClick(DFLayoutControl control)
|
|
|
+ private void DeleteElements(IEnumerable<DFLayoutControl> controls)
|
|
|
+ {
|
|
|
+ foreach(var control in controls)
|
|
|
{
|
|
|
if (form.Elements.Contains(control))
|
|
|
{
|
|
|
form.Elements.Remove(control);
|
|
|
- Render();
|
|
|
}
|
|
|
}
|
|
|
+ Render();
|
|
|
+ }
|
|
|
|
|
|
- private void ElementPropertiesClick(DFLayoutControl control)
|
|
|
+ private void DeleteElementClick(DFLayoutControl control)
|
|
|
+ {
|
|
|
+ if (form.Elements.Contains(control))
|
|
|
{
|
|
|
- if(!elementgrids.TryGetValue(control.GetType(), out var grid))
|
|
|
- {
|
|
|
- var type = typeof(FormControlGrid<>).MakeGenericType(control.GetType());
|
|
|
- grid = (Activator.CreateInstance(type) as IDynamicGrid)!;
|
|
|
- elementgrids[control.GetType()] = grid;
|
|
|
- }
|
|
|
-
|
|
|
- control.CommitChanges();
|
|
|
- if (grid.EditItems(new[] { control }))
|
|
|
- {
|
|
|
- Render();
|
|
|
- }
|
|
|
+ form.Elements.Remove(control);
|
|
|
+ Render();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void EditVariableClick(DFLayoutField field)
|
|
|
+ private void ElementPropertiesClick(DFLayoutControl control)
|
|
|
+ {
|
|
|
+ if(!elementgrids.TryGetValue(control.GetType(), out var grid))
|
|
|
{
|
|
|
- var variable = _variables.FirstOrDefault(x => x.Code == field.Name);
|
|
|
- if (variable is null) return;
|
|
|
-
|
|
|
- if(OnEditVariable?.Invoke(variable) == true)
|
|
|
- {
|
|
|
- field.LoadFromString(variable.Parameters);
|
|
|
- }
|
|
|
+ var type = typeof(FormControlGrid<>).MakeGenericType(control.GetType());
|
|
|
+ grid = (Activator.CreateInstance(type) as IDynamicGrid)!;
|
|
|
+ elementgrids[control.GetType()] = grid;
|
|
|
}
|
|
|
|
|
|
- private void ConvertToHeaderClick(DFLayoutLabel label)
|
|
|
+ control.CommitChanges();
|
|
|
+ if (grid.EditItems(new[] { control }))
|
|
|
{
|
|
|
- var header = new DFLayoutHeader
|
|
|
- {
|
|
|
- Row = label.Row,
|
|
|
- RowSpan = label.RowSpan,
|
|
|
- Column = label.Column,
|
|
|
- ColumnSpan = label.ColumnSpan,
|
|
|
- Collapsed = false,
|
|
|
- Header = label.Caption
|
|
|
- };
|
|
|
- header.Style.Synchronise(label.Style);
|
|
|
- header.Style.IsBold = true;
|
|
|
- form.Elements.Remove(label);
|
|
|
- form.Elements.Add(header);
|
|
|
Render();
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ private void EditVariableClick(DFLayoutField field)
|
|
|
+ {
|
|
|
+ var variable = _variables.FirstOrDefault(x => x.Code == field.Name);
|
|
|
+ if (variable is null) return;
|
|
|
|
|
|
- private void ConvertToLabelClick(DFLayoutHeader header)
|
|
|
+ if(OnEditVariable?.Invoke(variable) == true)
|
|
|
{
|
|
|
- var label = new DFLayoutLabel
|
|
|
- {
|
|
|
- Row = header.Row,
|
|
|
- RowSpan = header.RowSpan,
|
|
|
- Column = header.Column,
|
|
|
- ColumnSpan = header.ColumnSpan,
|
|
|
- Caption = header.Header
|
|
|
- };
|
|
|
- label.Style.Synchronise(header);
|
|
|
- label.Style.IsBold = false;
|
|
|
+ field.LoadFromString(variable.Parameters);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- form.Elements.Remove(header);
|
|
|
- form.Elements.Add(label);
|
|
|
- Render();
|
|
|
+ private void ConvertToHeaderClick(DFLayoutLabel label)
|
|
|
+ {
|
|
|
+ var header = new DFLayoutHeader
|
|
|
+ {
|
|
|
+ Row = label.Row,
|
|
|
+ RowSpan = label.RowSpan,
|
|
|
+ Column = label.Column,
|
|
|
+ ColumnSpan = label.ColumnSpan,
|
|
|
+ Collapsed = false,
|
|
|
+ Header = label.Caption
|
|
|
+ };
|
|
|
+ header.Style.Synchronise(label.Style);
|
|
|
+ header.Style.IsBold = true;
|
|
|
+ form.Elements.Remove(label);
|
|
|
+ form.Elements.Add(header);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ConvertToLabelClick(DFLayoutHeader header)
|
|
|
+ {
|
|
|
+ var label = new DFLayoutLabel
|
|
|
+ {
|
|
|
+ Row = header.Row,
|
|
|
+ RowSpan = header.RowSpan,
|
|
|
+ Column = header.Column,
|
|
|
+ ColumnSpan = header.ColumnSpan,
|
|
|
+ Caption = header.Header
|
|
|
+ };
|
|
|
+ label.Style.Synchronise(header);
|
|
|
+ label.Style.IsBold = false;
|
|
|
+
|
|
|
+ form.Elements.Remove(header);
|
|
|
+ form.Elements.Add(label);
|
|
|
+ Render();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void PopulateElementContextMenu(ContextMenu menu, DFLayoutControl control)
|
|
|
+ {
|
|
|
+ var selectedItems = GetSelectedItems().ToList();
|
|
|
+ if (selectedItems.Count > 1 && selectedItems.Contains(control))
|
|
|
+ {
|
|
|
+ PopulateSelectionMenu(menu);
|
|
|
+ if(menu.Items.Count > 0) return;
|
|
|
}
|
|
|
|
|
|
- private void PopulateElementContextMenu(ContextMenu menu, DFLayoutControl control)
|
|
|
+ menu.AddItem("Edit Properties", null, control, ElementPropertiesClick);
|
|
|
+ if (OnEditVariable is not null && control is DFLayoutField field)
|
|
|
{
|
|
|
- var selectedItems = GetSelectedItems().ToList();
|
|
|
- if (selectedItems.Count > 1 && selectedItems.Contains(control))
|
|
|
- {
|
|
|
- PopulateSelectionMenu(menu);
|
|
|
- if(menu.Items.Count > 0) return;
|
|
|
- }
|
|
|
-
|
|
|
- menu.AddItem("Edit Properties", null, control, ElementPropertiesClick);
|
|
|
- if (OnEditVariable is not null && control is DFLayoutField field)
|
|
|
- {
|
|
|
- menu.AddItem("Edit Variable", null, field, EditVariableClick);
|
|
|
- }
|
|
|
- else if (control is DFLayoutLabel label)
|
|
|
- {
|
|
|
- menu.AddItem("Convert to Header", null, label, ConvertToHeaderClick);
|
|
|
- }
|
|
|
- else if (control is DFLayoutHeader header)
|
|
|
- {
|
|
|
- menu.AddItem("Convert to Label", null, header, ConvertToLabelClick);
|
|
|
- }
|
|
|
- else if(control is DFLayoutElement element)
|
|
|
- {
|
|
|
- CustomiseElementContextMenu?.Invoke(menu, element);
|
|
|
- }
|
|
|
- menu.AddSeparatorIfNeeded();
|
|
|
- menu.AddItem("Resize Item", null, control, ResizeItem);
|
|
|
- menu.AddItem("Delete Item", null, control, DeleteElementClick);
|
|
|
+ menu.AddItem("Edit Variable", null, field, EditVariableClick);
|
|
|
}
|
|
|
-
|
|
|
- private ContextMenu CreateElementContextMenu(FrameworkElement element, DFLayoutControl control)
|
|
|
+ else if (control is DFLayoutLabel label)
|
|
|
{
|
|
|
- var result = new ContextMenu();
|
|
|
- result.Opened += (s, e) =>
|
|
|
- {
|
|
|
- result.Items.Clear();
|
|
|
- PopulateElementContextMenu(result, control);
|
|
|
- };
|
|
|
- element.SetValue(ContextMenuProperty, result);
|
|
|
- return result;
|
|
|
+ menu.AddItem("Convert to Header", null, label, ConvertToHeaderClick);
|
|
|
}
|
|
|
+ else if (control is DFLayoutHeader header)
|
|
|
+ {
|
|
|
+ menu.AddItem("Convert to Label", null, header, ConvertToLabelClick);
|
|
|
+ }
|
|
|
+ else if(control is DFLayoutElement element)
|
|
|
+ {
|
|
|
+ CustomiseElementContextMenu?.Invoke(menu, element);
|
|
|
+ }
|
|
|
+ menu.AddSeparatorIfNeeded();
|
|
|
+ menu.AddItem("Resize Item", null, control, ResizeItem);
|
|
|
+ menu.AddItem("Delete Item", null, control, DeleteElementClick);
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ private ContextMenu CreateElementContextMenu(FrameworkElement element, DFLayoutControl control)
|
|
|
+ {
|
|
|
+ var result = new ContextMenu();
|
|
|
+ result.Opened += (s, e) =>
|
|
|
+ {
|
|
|
+ result.Items.Clear();
|
|
|
+ PopulateElementContextMenu(result, control);
|
|
|
+ };
|
|
|
+ element.SetValue(ContextMenuProperty, result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Render
|
|
|
+ #endregion
|
|
|
|
|
|
- private static void SetDimensions(FrameworkElement element, int row, int column, int rowspan, int colspan, int offset)
|
|
|
- {
|
|
|
- if (column <= 0) return;
|
|
|
- if (row <= 0) return;
|
|
|
+ #region Render
|
|
|
|
|
|
- element.MinHeight = 50.0F;
|
|
|
- element.MinWidth = 50.0F;
|
|
|
- element.SetGridPosition(row - offset, column - offset, rowspan, colspan);
|
|
|
- }
|
|
|
+ private static void SetDimensions(FrameworkElement element, int row, int column, int rowspan, int colspan, int offset)
|
|
|
+ {
|
|
|
+ if (column <= 0) return;
|
|
|
+ if (row <= 0) return;
|
|
|
+
|
|
|
+ element.MinHeight = 50.0F;
|
|
|
+ element.MinWidth = 50.0F;
|
|
|
+ element.SetGridPosition(row - offset, column - offset, rowspan, colspan);
|
|
|
+ }
|
|
|
|
|
|
- private Border CreateBorder(int row, int column, int rowspan, int colspan, int offset, bool horzstar, bool vertstar)
|
|
|
+ private Border CreateBorder(int row, int column, int rowspan, int colspan, int offset, bool horzstar, bool vertstar)
|
|
|
+ {
|
|
|
+ var border = new Border();
|
|
|
+ if (ShowBorders)
|
|
|
{
|
|
|
- var border = new Border();
|
|
|
- if (ShowBorders)
|
|
|
- {
|
|
|
- border.BorderThickness = new Thickness(
|
|
|
- 0.0F,//!IsDesigning && column == 1 - offset ? 0.00F /*0.75F*/ : 0.0F,
|
|
|
- 0.0F,//!IsDesigning && row == 1 - offset ? 0.00F /*0.75F*/ : 0.0F,
|
|
|
- column - offset == ColumnDefinitions.Count - 1 ? horzstar ? 0.00F : 0.75F : 0.75F,
|
|
|
- row - offset == RowDefinitions.Count - 1 ? vertstar ? 0.00F : 0.75F : 0.75F
|
|
|
- );
|
|
|
+ border.BorderThickness = new Thickness(
|
|
|
+ 0.0F,//!IsDesigning && column == 1 - offset ? 0.00F /*0.75F*/ : 0.0F,
|
|
|
+ 0.0F,//!IsDesigning && row == 1 - offset ? 0.00F /*0.75F*/ : 0.0F,
|
|
|
+ column - offset == ColumnDefinitions.Count - 1 ? horzstar ? 0.00F : 0.75F : 0.75F,
|
|
|
+ row - offset == RowDefinitions.Count - 1 ? vertstar ? 0.00F : 0.75F : 0.75F
|
|
|
+ );
|
|
|
|
|
|
- border.BorderBrush = BorderBrush;
|
|
|
- }
|
|
|
+ border.BorderBrush = BorderBrush;
|
|
|
+ }
|
|
|
|
|
|
- border.Background = BackgroundBrush;
|
|
|
+ border.Background = BackgroundBrush;
|
|
|
|
|
|
- SetDimensions(border, row, column, rowspan, colspan, offset);
|
|
|
+ SetDimensions(border, row, column, rowspan, colspan, offset);
|
|
|
|
|
|
- return border;
|
|
|
- }
|
|
|
+ return border;
|
|
|
+ }
|
|
|
|
|
|
- private static BitmapImage HeaderClosed =Wpf.Resources.rightarrow.AsBitmapImage(32, 32);
|
|
|
- private static BitmapImage HeaderOpen =Wpf.Resources.downarrow.AsBitmapImage(32, 32);
|
|
|
+ private static BitmapImage HeaderClosed =Wpf.Resources.rightarrow.AsBitmapImage(32, 32);
|
|
|
+ private static BitmapImage HeaderOpen =Wpf.Resources.downarrow.AsBitmapImage(32, 32);
|
|
|
|
|
|
- private FrameworkElement CreateHeader(DFLayoutHeader header)
|
|
|
+ private FrameworkElement CreateHeader(DFLayoutHeader header)
|
|
|
+ {
|
|
|
+ var formHeader = new FormHeader
|
|
|
{
|
|
|
- var formHeader = new FormHeader
|
|
|
- {
|
|
|
- Collapsed = header.Collapsed,
|
|
|
- HeaderText = header.Header
|
|
|
- };
|
|
|
- formHeader.CollapsedChanged += (o, c) =>
|
|
|
- {
|
|
|
- CollapseRows(formHeader, c);
|
|
|
- };
|
|
|
- if (IsDesigning)
|
|
|
- {
|
|
|
- formHeader.IsEnabled = false;
|
|
|
- }
|
|
|
- return formHeader;
|
|
|
+ Collapsed = header.Collapsed,
|
|
|
+ HeaderText = header.Header
|
|
|
+ };
|
|
|
+ formHeader.CollapsedChanged += (o, c) =>
|
|
|
+ {
|
|
|
+ CollapseRows(formHeader, c);
|
|
|
+ };
|
|
|
+ if (IsDesigning)
|
|
|
+ {
|
|
|
+ formHeader.IsEnabled = false;
|
|
|
}
|
|
|
+ return formHeader;
|
|
|
+ }
|
|
|
|
|
|
- // DFLayoutField -> IDynamicFormFieldControl
|
|
|
- private static Dictionary<Type, Type>? _fieldControls;
|
|
|
- private DynamicFormControl? CreateFieldControl(DFLayoutField field)
|
|
|
+ // DFLayoutField -> IDynamicFormFieldControl
|
|
|
+ private static Dictionary<Type, Type>? _fieldControls;
|
|
|
+ private DynamicFormControl? CreateFieldControl(DFLayoutField field)
|
|
|
+ {
|
|
|
+ if (_fieldControls == null)
|
|
|
{
|
|
|
- if (_fieldControls == null)
|
|
|
- {
|
|
|
- _fieldControls = new();
|
|
|
- foreach (var controlType in CoreUtils.Entities.Where(x => x.IsClass && !x.IsGenericType && x.HasInterface<IDynamicFormFieldControl>()))
|
|
|
- {
|
|
|
- var superDefinition = controlType.GetSuperclassDefinition(typeof(DynamicFormFieldControl<,,,>));
|
|
|
- if (superDefinition != null)
|
|
|
- {
|
|
|
- _fieldControls[superDefinition.GenericTypeArguments[0]] = controlType;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var fieldControlType = _fieldControls.GetValueOrDefault(field.GetType());
|
|
|
- if (fieldControlType is not null)
|
|
|
+ _fieldControls = new();
|
|
|
+ foreach (var controlType in CoreUtils.Entities.Where(x => x.IsClass && !x.IsGenericType && x.HasInterface<IDynamicFormFieldControl>()))
|
|
|
{
|
|
|
- var element = (Activator.CreateInstance(fieldControlType) as DynamicFormControl)!;
|
|
|
-
|
|
|
- if(element is IDynamicFormFieldControl fieldControl)
|
|
|
+ var superDefinition = controlType.GetSuperclassDefinition(typeof(DynamicFormFieldControl<,,,>));
|
|
|
+ if (superDefinition != null)
|
|
|
{
|
|
|
- fieldControl.FieldChangedEvent += () =>
|
|
|
- {
|
|
|
- ChangeField(field.Name);
|
|
|
- };
|
|
|
+ _fieldControls[superDefinition.GenericTypeArguments[0]] = controlType;
|
|
|
}
|
|
|
-
|
|
|
- return element;
|
|
|
}
|
|
|
- return null;
|
|
|
}
|
|
|
|
|
|
- private DynamicFormControl? CreateFieldPlaceholder(DFLayoutField field)
|
|
|
+ var fieldControlType = _fieldControls.GetValueOrDefault(field.GetType());
|
|
|
+ if (fieldControlType is not null)
|
|
|
{
|
|
|
- var controlType = typeof(DFFieldPlaceholderControl<>).MakeGenericType(field.GetType());
|
|
|
- return Activator.CreateInstance(controlType) as DynamicFormControl;
|
|
|
- }
|
|
|
+ var element = (Activator.CreateInstance(fieldControlType) as DynamicFormControl)!;
|
|
|
|
|
|
- private DynamicFormControl? CreateControl(DFLayoutControl item)
|
|
|
- {
|
|
|
- if (item is DFLayoutField field)
|
|
|
+ if(element is IDynamicFormFieldControl fieldControl)
|
|
|
{
|
|
|
- if (IsDesigning)
|
|
|
+ fieldControl.FieldChangedEvent += () =>
|
|
|
{
|
|
|
- return CreateFieldPlaceholder(field);
|
|
|
- }
|
|
|
-
|
|
|
- return CreateFieldControl(field);
|
|
|
- }
|
|
|
- else if (item is DFLayoutElement)
|
|
|
- {
|
|
|
- return IsDesigning
|
|
|
- ? new DFElementPlaceholderControl()
|
|
|
- : new DFElementControl();
|
|
|
- }
|
|
|
- else if (item is DFLayoutLabel)
|
|
|
- {
|
|
|
- return new DFLabelControl();
|
|
|
- }
|
|
|
- else if (item is DFLayoutHeader)
|
|
|
- {
|
|
|
- return new DFHeaderControl();
|
|
|
- }
|
|
|
- else if (item is DFLayoutImage)
|
|
|
- {
|
|
|
- return new DFImageControl();
|
|
|
+ ChangeField(field.Name);
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- return null;
|
|
|
+ return element;
|
|
|
}
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private DynamicFormControl? CreateFieldPlaceholder(DFLayoutField field)
|
|
|
+ {
|
|
|
+ var controlType = typeof(DFFieldPlaceholderControl<>).MakeGenericType(field.GetType());
|
|
|
+ return Activator.CreateInstance(controlType) as DynamicFormControl;
|
|
|
+ }
|
|
|
|
|
|
- private FrameworkElement? CreateElement(DFLayoutControl item)
|
|
|
+ private DynamicFormControl? CreateControl(DFLayoutControl item)
|
|
|
+ {
|
|
|
+ if (item is DFLayoutField field)
|
|
|
{
|
|
|
- var control = CreateControl(item);
|
|
|
- if(control != null)
|
|
|
+ if (IsDesigning)
|
|
|
{
|
|
|
- control.FormDesignGrid = this;
|
|
|
- control.SetControl(item);
|
|
|
+ return CreateFieldPlaceholder(field);
|
|
|
}
|
|
|
- return control;
|
|
|
- }
|
|
|
|
|
|
- private Brush GetItemBackgroundBrush(DFLayoutControl item, Color? colour = null)
|
|
|
+ return CreateFieldControl(field);
|
|
|
+ }
|
|
|
+ else if (item is DFLayoutElement)
|
|
|
{
|
|
|
- if(colour != null)
|
|
|
- {
|
|
|
- var colourValue = colour.Value;
|
|
|
- return new SolidColorBrush(new System.Windows.Media.Color { R = colourValue.R, G = colourValue.G, B = colourValue.B, A = colourValue.A });
|
|
|
- }
|
|
|
+ return IsDesigning
|
|
|
+ ? new DFElementPlaceholderControl()
|
|
|
+ : new DFElementControl();
|
|
|
+ }
|
|
|
+ else if (item is DFLayoutLabel)
|
|
|
+ {
|
|
|
+ return new DFLabelControl();
|
|
|
+ }
|
|
|
+ else if (item is DFLayoutHeader)
|
|
|
+ {
|
|
|
+ return new DFHeaderControl();
|
|
|
+ }
|
|
|
+ else if (item is DFLayoutImage)
|
|
|
+ {
|
|
|
+ return new DFImageControl();
|
|
|
+ }
|
|
|
|
|
|
- if (item is DFLayoutField field)
|
|
|
- return field.GetPropertyValue<bool>("Required") ? RequiredFieldBrush : FieldBrush;
|
|
|
- else
|
|
|
- return IsDesigning ? FieldBrush : BackgroundBrush;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameworkElement? CreateElement(DFLayoutControl item)
|
|
|
+ {
|
|
|
+ var control = CreateControl(item);
|
|
|
+ if(control != null)
|
|
|
+ {
|
|
|
+ control.FormDesignGrid = this;
|
|
|
+ control.SetControl(item);
|
|
|
}
|
|
|
+ return control;
|
|
|
+ }
|
|
|
|
|
|
- private void RenderElement(DFLayoutControl item, int offset, bool horzstar, bool vertstar)
|
|
|
+ private Brush GetItemBackgroundBrush(DFLayoutControl item, Color? colour = null)
|
|
|
+ {
|
|
|
+ if(colour != null)
|
|
|
{
|
|
|
- var border = CreateBorder(item.Row, item.Column, item.RowSpan, item.ColumnSpan, offset, horzstar, vertstar);
|
|
|
+ var colourValue = colour.Value;
|
|
|
+ return new SolidColorBrush(new System.Windows.Media.Color { R = colourValue.R, G = colourValue.G, B = colourValue.B, A = colourValue.A });
|
|
|
+ }
|
|
|
|
|
|
- border.Background = GetItemBackgroundBrush(item);
|
|
|
+ if (item is DFLayoutField field)
|
|
|
+ return field.GetPropertyValue<bool>("Required") ? RequiredFieldBrush : FieldBrush;
|
|
|
+ else
|
|
|
+ return IsDesigning ? FieldBrush : BackgroundBrush;
|
|
|
+ }
|
|
|
|
|
|
- if (!ShowBorders)
|
|
|
- border.Padding = new Thickness(
|
|
|
- item.Column == 1 ? 4 : 2,
|
|
|
- item.Row == 1 ? 4 : 2,
|
|
|
- item.Column + item.ColumnSpan - 1 == ColumnDefinitions.Count ? 4 : 2,
|
|
|
- item.Row + item.RowSpan - 1 == RowDefinitions.Count ? 4 : 2
|
|
|
- );
|
|
|
- else
|
|
|
- border.Padding = new Thickness(5);
|
|
|
+ private void RenderElement(DFLayoutControl item, int offset, bool horzstar, bool vertstar)
|
|
|
+ {
|
|
|
+ var border = CreateBorder(item.Row, item.Column, item.RowSpan, item.ColumnSpan, offset, horzstar, vertstar);
|
|
|
|
|
|
- var element = CreateElement(item);
|
|
|
- border.Child = element;
|
|
|
- Children.Add(border);
|
|
|
- if (IsDesigning)
|
|
|
+ border.Background = GetItemBackgroundBrush(item);
|
|
|
+
|
|
|
+ if (!ShowBorders)
|
|
|
+ border.Padding = new Thickness(
|
|
|
+ item.Column == 1 ? 4 : 2,
|
|
|
+ item.Row == 1 ? 4 : 2,
|
|
|
+ item.Column + item.ColumnSpan - 1 == ColumnDefinitions.Count ? 4 : 2,
|
|
|
+ item.Row + item.RowSpan - 1 == RowDefinitions.Count ? 4 : 2
|
|
|
+ );
|
|
|
+ else
|
|
|
+ border.Padding = new Thickness(5);
|
|
|
+
|
|
|
+ var element = CreateElement(item);
|
|
|
+ border.Child = element;
|
|
|
+ Children.Add(border);
|
|
|
+ if (IsDesigning)
|
|
|
+ {
|
|
|
+ CreateElementContextMenu(border, item);
|
|
|
+ }
|
|
|
+ borderMap[item] = border;
|
|
|
+
|
|
|
+ if (element != null)
|
|
|
+ {
|
|
|
+ if(item is DFLayoutField)
|
|
|
{
|
|
|
- CreateElementContextMenu(border, item);
|
|
|
+ element.IsEnabled = element.IsEnabled && !IsReadOnly;
|
|
|
}
|
|
|
- borderMap[item] = border;
|
|
|
+ elementmap[item] = element;
|
|
|
|
|
|
- if (element != null)
|
|
|
+ element.HorizontalAlignment = GetHorizontalAlignment(item.HorizontalAlignment);
|
|
|
+ element.VerticalAlignment = GetVerticalAlignment(item.VerticalAlignment);
|
|
|
+ if (IsDesigning)
|
|
|
{
|
|
|
- if(item is DFLayoutField)
|
|
|
- {
|
|
|
- element.IsEnabled = element.IsEnabled && !IsReadOnly;
|
|
|
- }
|
|
|
- elementmap[item] = element;
|
|
|
-
|
|
|
- element.HorizontalAlignment = GetHorizontalAlignment(item.HorizontalAlignment);
|
|
|
- element.VerticalAlignment = GetVerticalAlignment(item.VerticalAlignment);
|
|
|
- if (IsDesigning)
|
|
|
- {
|
|
|
- CreateElementContextMenu(element, item);
|
|
|
- }
|
|
|
+ CreateElementContextMenu(element, item);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- private void AfterRender()
|
|
|
+ }
|
|
|
+
|
|
|
+ private void AfterRender()
|
|
|
+ {
|
|
|
+ if (!IsDesigning)
|
|
|
{
|
|
|
- if (!IsDesigning)
|
|
|
+ foreach (var header in elementmap.Where(x => x.Value is DFHeaderControl head).Select(x => x.Value).Cast<DFHeaderControl>())
|
|
|
{
|
|
|
- foreach (var header in elementmap.Where(x => x.Value is DFHeaderControl head).Select(x => x.Value).Cast<DFHeaderControl>())
|
|
|
+ if (header.Header.Collapsed)
|
|
|
{
|
|
|
- if (header.Header.Collapsed)
|
|
|
- {
|
|
|
- CollapseRows(header.Header, true);
|
|
|
- }
|
|
|
+ CollapseRows(header.Header, true);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- OnAfterRender?.Invoke(this);
|
|
|
}
|
|
|
|
|
|
- private void Render()
|
|
|
+ OnAfterRender?.Invoke(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Render()
|
|
|
+ {
|
|
|
+ ClearSelection();
|
|
|
+ ClearResize();
|
|
|
+
|
|
|
+ foreach (var item in elementmap.Keys)
|
|
|
{
|
|
|
- ClearSelection();
|
|
|
- ClearResize();
|
|
|
+ var e = elementmap[item];
|
|
|
+ if (VisualTreeHelper.GetParent(e) is Border parent)
|
|
|
+ parent.Child = null;
|
|
|
+ }
|
|
|
|
|
|
- foreach (var item in elementmap.Keys)
|
|
|
- {
|
|
|
- var e = elementmap[item];
|
|
|
- if (VisualTreeHelper.GetParent(e) is Border parent)
|
|
|
- parent.Child = null;
|
|
|
- }
|
|
|
+ elementmap.Clear();
|
|
|
|
|
|
- elementmap.Clear();
|
|
|
+ Children.Clear();
|
|
|
|
|
|
- Children.Clear();
|
|
|
+ ColumnDefinitions.Clear();
|
|
|
|
|
|
- ColumnDefinitions.Clear();
|
|
|
+ RowDefinitions.Clear();
|
|
|
|
|
|
- RowDefinitions.Clear();
|
|
|
+ if (form == null)
|
|
|
+ return;
|
|
|
|
|
|
- if (form == null)
|
|
|
- return;
|
|
|
+ foreach (var column in form.ColumnWidths)
|
|
|
+ ColumnDefinitions.Add(new ColumnDefinition { Width = StringToGridLength(column) });
|
|
|
|
|
|
- foreach (var column in form.ColumnWidths)
|
|
|
- ColumnDefinitions.Add(new ColumnDefinition { Width = StringToGridLength(column) });
|
|
|
+ foreach (var row in form.RowHeights)
|
|
|
+ RowDefinitions.Add(new RowDefinition { Height = StringToGridLength(row), Tag = new RowData(row) });
|
|
|
|
|
|
- foreach (var row in form.RowHeights)
|
|
|
- RowDefinitions.Add(new RowDefinition { Height = StringToGridLength(row), Tag = new RowData(row) });
|
|
|
+ var horzstar = ColumnDefinitions.Any(x => x.Width.IsStar);
|
|
|
+ var vertstar = RowDefinitions.Any(x => x.Height.IsStar);
|
|
|
|
|
|
- var horzstar = ColumnDefinitions.Any(x => x.Width.IsStar);
|
|
|
- var vertstar = RowDefinitions.Any(x => x.Height.IsStar);
|
|
|
+ var offset = 1;
|
|
|
+ if (IsDesigning)
|
|
|
+ {
|
|
|
+ ColumnDefinitions.Insert(0, new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
|
|
+ RowDefinitions.Insert(0, new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
|
|
|
|
|
|
- var offset = 1;
|
|
|
- if (IsDesigning)
|
|
|
+ var topleft = new Button();
|
|
|
+ topleft.SetValue(RowProperty, 0);
|
|
|
+ topleft.SetValue(ColumnProperty, 0);
|
|
|
+ topleft.Content =
|
|
|
+ ""; // new Image() { Source = _designing ? Wpf.Resources.view.AsBitmapImage() : Wpf.Resources.design.AsBitmapImage() };
|
|
|
+ topleft.BorderBrush = BorderBrush;
|
|
|
+ topleft.BorderThickness = new Thickness(
|
|
|
+ 0.00F,
|
|
|
+ 0.00F,
|
|
|
+ 0.75F,
|
|
|
+ 0.75F
|
|
|
+ );
|
|
|
+ topleft.Background = BackgroundBrush;
|
|
|
+ //topleft.Click += (o, e) =>
|
|
|
+ //{
|
|
|
+ // Designing = !Designing;
|
|
|
+ //};
|
|
|
+ Children.Add(topleft);
|
|
|
+
|
|
|
+ for (var i = 1; i < ColumnDefinitions.Count; i++)
|
|
|
{
|
|
|
- ColumnDefinitions.Insert(0, new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
|
|
- RowDefinitions.Insert(0, new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
|
|
|
-
|
|
|
- var topleft = new Button();
|
|
|
- topleft.SetValue(RowProperty, 0);
|
|
|
- topleft.SetValue(ColumnProperty, 0);
|
|
|
- topleft.Content =
|
|
|
- ""; // new Image() { Source = _designing ? Wpf.Resources.view.AsBitmapImage() : Wpf.Resources.design.AsBitmapImage() };
|
|
|
- topleft.BorderBrush = BorderBrush;
|
|
|
- topleft.BorderThickness = new Thickness(
|
|
|
- 0.00F,
|
|
|
- 0.00F,
|
|
|
- 0.75F,
|
|
|
+ var Button = new Button();
|
|
|
+ Button.SetValue(RowProperty, 0);
|
|
|
+ Button.SetValue(ColumnProperty, i);
|
|
|
+ Button.Content = FormatGridLength(ColumnDefinitions[i].Width, ColumnDefinitions.Select(x => x.Width));
|
|
|
+ Button.BorderBrush = BorderBrush;
|
|
|
+ Button.BorderThickness = new Thickness(
|
|
|
+ 0.00F, //(i == 1) ? 0.75F : 0.0F,
|
|
|
+ 0.00F, //0.75F,
|
|
|
+ i == ColumnDefinitions.Count - 1 ? horzstar ? 0.00F : 0.75F : 0.75F,
|
|
|
0.75F
|
|
|
);
|
|
|
- topleft.Background = BackgroundBrush;
|
|
|
- //topleft.Click += (o, e) =>
|
|
|
- //{
|
|
|
- // Designing = !Designing;
|
|
|
- //};
|
|
|
- Children.Add(topleft);
|
|
|
-
|
|
|
- for (var i = 1; i < ColumnDefinitions.Count; i++)
|
|
|
- {
|
|
|
- var Button = new Button();
|
|
|
- Button.SetValue(RowProperty, 0);
|
|
|
- Button.SetValue(ColumnProperty, i);
|
|
|
- Button.Content = FormatGridLength(ColumnDefinitions[i].Width, ColumnDefinitions.Select(x => x.Width));
|
|
|
- Button.BorderBrush = BorderBrush;
|
|
|
- Button.BorderThickness = new Thickness(
|
|
|
- 0.00F, //(i == 1) ? 0.75F : 0.0F,
|
|
|
- 0.00F, //0.75F,
|
|
|
- i == ColumnDefinitions.Count - 1 ? horzstar ? 0.00F : 0.75F : 0.75F,
|
|
|
- 0.75F
|
|
|
- );
|
|
|
- Button.Background = BackgroundBrush;
|
|
|
- Button.Padding = new Thickness(10);
|
|
|
- Button.MinHeight = 35;
|
|
|
- CreateColumnMenu(Button, i - 1);
|
|
|
- AddClick(Button, i - 1, ColumnPropertiesClick);
|
|
|
- Children.Add(Button);
|
|
|
- }
|
|
|
+ Button.Background = BackgroundBrush;
|
|
|
+ Button.Padding = new Thickness(10);
|
|
|
+ Button.MinHeight = 35;
|
|
|
+ CreateColumnMenu(Button, i - 1);
|
|
|
+ AddClick(Button, i - 1, ColumnPropertiesClick);
|
|
|
+ Children.Add(Button);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (var i = 1; i < RowDefinitions.Count; i++)
|
|
|
+ {
|
|
|
+ var Button = new Button();
|
|
|
+ Button.SetValue(RowProperty, i);
|
|
|
+ Button.SetValue(ColumnProperty, 0);
|
|
|
+ Button.Content = FormatGridLength(RowDefinitions[i].Height, RowDefinitions.Select(x => x.Height));
|
|
|
+ Button.BorderBrush = BorderBrush;
|
|
|
+ Button.BorderThickness = new Thickness(
|
|
|
+ 0.00F, //0.75F,
|
|
|
+ 0.00F, //(i == 1) ? 0.75F : 0.0F,
|
|
|
+ 0.75F,
|
|
|
+ i == RowDefinitions.Count - 1 ? vertstar ? 0.00F : 0.75F : 0.75F
|
|
|
+ );
|
|
|
+ Button.Background = BackgroundBrush;
|
|
|
+ Button.Padding = new Thickness(10);
|
|
|
+ CreateRowMenu(Button, i - 1);
|
|
|
+ AddClick(Button, i - 1, RowPropertiesClick);
|
|
|
+ Children.Add(Button);
|
|
|
+ }
|
|
|
+
|
|
|
+ offset = 0;
|
|
|
+ }
|
|
|
|
|
|
- for (var i = 1; i < RowDefinitions.Count; i++)
|
|
|
+ var filledcells = new HashSet<PointI>();
|
|
|
+ foreach (var item in form.GetElements(IsDesigning))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if(item.Row > 0 && item.Column > 0)
|
|
|
{
|
|
|
- var Button = new Button();
|
|
|
- Button.SetValue(RowProperty, i);
|
|
|
- Button.SetValue(ColumnProperty, 0);
|
|
|
- Button.Content = FormatGridLength(RowDefinitions[i].Height, RowDefinitions.Select(x => x.Height));
|
|
|
- Button.BorderBrush = BorderBrush;
|
|
|
- Button.BorderThickness = new Thickness(
|
|
|
- 0.00F, //0.75F,
|
|
|
- 0.00F, //(i == 1) ? 0.75F : 0.0F,
|
|
|
- 0.75F,
|
|
|
- i == RowDefinitions.Count - 1 ? vertstar ? 0.00F : 0.75F : 0.75F
|
|
|
- );
|
|
|
- Button.Background = BackgroundBrush;
|
|
|
- Button.Padding = new Thickness(10);
|
|
|
- CreateRowMenu(Button, i - 1);
|
|
|
- AddClick(Button, i - 1, RowPropertiesClick);
|
|
|
- Children.Add(Button);
|
|
|
+ RenderElement(item, offset, horzstar, vertstar);
|
|
|
+ for (var c = item.Column; c < item.Column + item.ColumnSpan; c++)
|
|
|
+ for (var r = item.Row; r < item.Row + item.RowSpan; r++)
|
|
|
+ filledcells.Add(new PointI(c, r));
|
|
|
}
|
|
|
-
|
|
|
- offset = 0;
|
|
|
}
|
|
|
-
|
|
|
- var filledcells = new List<Point>();
|
|
|
- foreach (var item in form.GetElements(IsDesigning))
|
|
|
+ catch (Exception e)
|
|
|
{
|
|
|
- try
|
|
|
+ Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (var c = 1; c <= form.ColumnWidths.Count; c++)
|
|
|
+ for (var r = 1; r <= form.RowHeights.Count; r++)
|
|
|
+ if (!filledcells.Contains(new(c, r)))
|
|
|
{
|
|
|
- if(item.Row > 0 && item.Column > 0)
|
|
|
+ var border = CreateBorder(r, c, 1, 1, offset, horzstar, vertstar);
|
|
|
+ if (IsDesigning)
|
|
|
{
|
|
|
- RenderElement(item, offset, horzstar, vertstar);
|
|
|
- for (var c = item.Column; c < item.Column + item.ColumnSpan; c++)
|
|
|
- for (var r = item.Row; r < item.Row + item.RowSpan; r++)
|
|
|
- filledcells.Add(new Point(c, r));
|
|
|
+ CreateEmptyCellMenu(border, r, c);
|
|
|
}
|
|
|
+ Children.Add(border);
|
|
|
}
|
|
|
- catch (Exception e)
|
|
|
- {
|
|
|
- Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- for (var c = 1; c <= form.ColumnWidths.Count; c++)
|
|
|
- for (var r = 1; r <= form.RowHeights.Count; r++)
|
|
|
- if (!filledcells.Any(x => x.X.Equals(c) && x.Y.Equals(r)))
|
|
|
- {
|
|
|
- var border = CreateBorder(r, c, 1, 1, offset, horzstar, vertstar);
|
|
|
- if (IsDesigning)
|
|
|
- {
|
|
|
- CreateEmptyCellMenu(border, r, c);
|
|
|
- }
|
|
|
- Children.Add(border);
|
|
|
- }
|
|
|
+ AfterRender();
|
|
|
+ }
|
|
|
|
|
|
- AfterRender();
|
|
|
- }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Renders the form; after this is called, any changes to properties triggers a refresh.
|
|
|
+ /// </summary>
|
|
|
+ /// <remarks>
|
|
|
+ /// This should be called before <see cref="LoadValues(Dictionary{string, object})"/> or <see cref="SaveValues"/>
|
|
|
+ /// </remarks>
|
|
|
+ public void Initialize()
|
|
|
+ {
|
|
|
+ GridInitialized = true;
|
|
|
+ CheckRefresh(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Refresh()
|
|
|
+ {
|
|
|
+ CheckRefresh(false);
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ private void CheckRefresh(bool keepValues = true)
|
|
|
+ {
|
|
|
+ if (!GridInitialized) return;
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Renders the form; after this is called, any changes to properties triggers a refresh.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// This should be called before <see cref="LoadValues(Dictionary{string, object})"/> or <see cref="SaveValues"/>
|
|
|
- /// </remarks>
|
|
|
- public void Initialize()
|
|
|
+ if (_mode == FormMode.Designing)
|
|
|
{
|
|
|
- GridInitialized = true;
|
|
|
- CheckRefresh(false);
|
|
|
+ Render();
|
|
|
}
|
|
|
-
|
|
|
- public void Refresh()
|
|
|
+ else if(keepValues)
|
|
|
{
|
|
|
- CheckRefresh(false);
|
|
|
+ var values = SaveValues();
|
|
|
+ Render();
|
|
|
+ LoadValues(values.ToLoadStorage());
|
|
|
}
|
|
|
-
|
|
|
- private void CheckRefresh(bool keepValues = true)
|
|
|
+ else
|
|
|
{
|
|
|
- if (!GridInitialized) return;
|
|
|
-
|
|
|
- if (_mode == FormMode.Designing)
|
|
|
- {
|
|
|
- Render();
|
|
|
- }
|
|
|
- else if(keepValues)
|
|
|
- {
|
|
|
- var values = SaveValues();
|
|
|
- Render();
|
|
|
- LoadValues(values.ToLoadStorage());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Render();
|
|
|
- Form.EvaluateExpressions();
|
|
|
- }
|
|
|
+ Render();
|
|
|
+ Form.EvaluateExpressions();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- #region Fields
|
|
|
+ #region Fields
|
|
|
|
|
|
- private void ChangeField(string fieldName)
|
|
|
+ private void ChangeField(string fieldName)
|
|
|
+ {
|
|
|
+ if (!_changing)
|
|
|
{
|
|
|
- if (!_changing)
|
|
|
- {
|
|
|
- form.ChangeField(fieldName);
|
|
|
- _isChanged = true;
|
|
|
- OnChanged?.Invoke(this, fieldName);
|
|
|
- }
|
|
|
+ form.ChangeField(fieldName);
|
|
|
+ _isChanged = true;
|
|
|
+ OnChanged?.Invoke(this, fieldName);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private IDynamicFormFieldControl? GetFieldControl(DFLayoutField field)
|
|
|
- {
|
|
|
- return elementmap.GetValueOrDefault(field) as IDynamicFormFieldControl;
|
|
|
- }
|
|
|
+ private IDynamicFormFieldControl? GetFieldControl(DFLayoutField field)
|
|
|
+ {
|
|
|
+ return elementmap.GetValueOrDefault(field) as IDynamicFormFieldControl;
|
|
|
+ }
|
|
|
|
|
|
- private void LoadFieldValue(string fieldName, DFLoadStorageEntry entry)
|
|
|
+ private void LoadFieldValue(string fieldName, DFLoadStorageEntry entry)
|
|
|
+ {
|
|
|
+ var field = form.Elements.FirstOrDefault(x => string.Equals(fieldName, (x as DFLayoutField)?.Name)) as DFLayoutField;
|
|
|
+ if (field != null)
|
|
|
{
|
|
|
- var field = form.Elements.FirstOrDefault(x => string.Equals(fieldName, (x as DFLayoutField)?.Name)) as DFLayoutField;
|
|
|
- if (field != null)
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ if (fieldControl != null)
|
|
|
{
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- if (fieldControl != null)
|
|
|
- {
|
|
|
- string? property = (DataModel != null) ? field.GetPropertyValue<string>("Property") : null;
|
|
|
- if (!property.IsNullOrWhiteSpace())
|
|
|
- fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
- else
|
|
|
- fieldControl.Deserialize(entry);
|
|
|
- }
|
|
|
+ string? property = (DataModel != null) ? field.GetPropertyValue<string>("Property") : null;
|
|
|
+ if (!property.IsNullOrWhiteSpace())
|
|
|
+ fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
+ else
|
|
|
+ fieldControl.Deserialize(entry);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- public void SetFieldValue(string fieldName, object? value)
|
|
|
+ public void SetFieldValue(string fieldName, object? value)
|
|
|
+ {
|
|
|
+ var field = form.Elements.FirstOrDefault(x => string.Equals(fieldName, (x as DFLayoutField)?.Name)) as DFLayoutField;
|
|
|
+ if (field != null)
|
|
|
{
|
|
|
- var field = form.Elements.FirstOrDefault(x => string.Equals(fieldName, (x as DFLayoutField)?.Name)) as DFLayoutField;
|
|
|
- if (field != null)
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ if (fieldControl != null)
|
|
|
{
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- if (fieldControl != null)
|
|
|
- {
|
|
|
- string? property = (DataModel != null) ? field.GetPropertyValue<string>("Property") : null;
|
|
|
- if (!property.IsNullOrWhiteSpace())
|
|
|
- fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
- else
|
|
|
- fieldControl.SetValue(value);
|
|
|
- }
|
|
|
+ string? property = (DataModel != null) ? field.GetPropertyValue<string>("Property") : null;
|
|
|
+ if (!property.IsNullOrWhiteSpace())
|
|
|
+ fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
+ else
|
|
|
+ fieldControl.SetValue(value);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- private void GetFieldValue(DFLayoutField field, DFSaveStorageEntry storage, out object? entityValue)
|
|
|
+ private void GetFieldValue(DFLayoutField field, DFSaveStorageEntry storage, out object? entityValue)
|
|
|
+ {
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ if(fieldControl != null)
|
|
|
{
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- if(fieldControl != null)
|
|
|
- {
|
|
|
- entityValue = fieldControl.GetEntityValue();
|
|
|
- fieldControl.Serialize(storage);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- entityValue = null;
|
|
|
- }
|
|
|
+ entityValue = fieldControl.GetEntityValue();
|
|
|
+ fieldControl.Serialize(storage);
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ entityValue = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- public object? GetFieldValue(string fieldName)
|
|
|
+ public object? GetFieldValue(string fieldName)
|
|
|
+ {
|
|
|
+ var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
+ if (field is null)
|
|
|
{
|
|
|
- var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
- if (field is null)
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- return fieldControl?.GetValue();
|
|
|
+ return null;
|
|
|
}
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ return fieldControl?.GetValue();
|
|
|
+ }
|
|
|
|
|
|
- public object? GetFieldData(string fieldName, string dataField)
|
|
|
+ public object? GetFieldData(string fieldName, string dataField)
|
|
|
+ {
|
|
|
+ var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
+ if (field is null)
|
|
|
{
|
|
|
- var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
- if (field is null)
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- return fieldControl?.GetData(dataField);
|
|
|
+ return null;
|
|
|
}
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ return fieldControl?.GetData(dataField);
|
|
|
+ }
|
|
|
|
|
|
- public void SetFieldColour(string fieldName, Color? colour)
|
|
|
+ public void SetFieldColour(string fieldName, Color? colour)
|
|
|
+ {
|
|
|
+ var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
+ if (field is null || !borderMap.TryGetValue(field, out var border))
|
|
|
{
|
|
|
- var field = form.Elements.Where(x => (x as DFLayoutField)?.Name == fieldName).FirstOrDefault() as DFLayoutField;
|
|
|
- if (field is null || !borderMap.TryGetValue(field, out var border))
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- border.Background = GetItemBackgroundBrush(field, colour);
|
|
|
+ return;
|
|
|
}
|
|
|
+ border.Background = GetItemBackgroundBrush(field, colour);
|
|
|
+ }
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Load values into editor; Must be called after <see cref="Initialize"/>.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// Resets <see cref="IsChanged"/>.
|
|
|
- /// </remarks>
|
|
|
- /// <param name="values">A storage object.</param>
|
|
|
- public void LoadValues(DFLoadStorage values)
|
|
|
+ /// <summary>
|
|
|
+ /// Load values into editor; Must be called after <see cref="Initialize"/>.
|
|
|
+ /// </summary>
|
|
|
+ /// <remarks>
|
|
|
+ /// Resets <see cref="IsChanged"/>.
|
|
|
+ /// </remarks>
|
|
|
+ /// <param name="values">A storage object.</param>
|
|
|
+ public void LoadValues(DFLoadStorage values)
|
|
|
+ {
|
|
|
+ _changing = true;
|
|
|
+ InitializeEntityValues();
|
|
|
+ foreach (var (key, value) in values.Items())
|
|
|
{
|
|
|
- _changing = true;
|
|
|
- InitializeEntityValues();
|
|
|
- foreach (var (key, value) in values.Items())
|
|
|
+ if (!key.Contains('.'))
|
|
|
{
|
|
|
- if (!key.Contains('.'))
|
|
|
- {
|
|
|
- LoadFieldValue(key, values.GetEntry(key));
|
|
|
- }
|
|
|
+ LoadFieldValue(key, values.GetEntry(key));
|
|
|
}
|
|
|
- Form.EvaluateExpressions();
|
|
|
- _changing = false;
|
|
|
- _isChanged = false;
|
|
|
}
|
|
|
+ Form.EvaluateExpressions();
|
|
|
+ _changing = false;
|
|
|
+ _isChanged = false;
|
|
|
+ }
|
|
|
|
|
|
- public void InitializeEntityValues()
|
|
|
+ public void InitializeEntityValues()
|
|
|
+ {
|
|
|
+ _changing = true;
|
|
|
+ foreach (var field in form.Elements.OfType<DFLayoutField>())
|
|
|
{
|
|
|
- _changing = true;
|
|
|
- foreach (var field in form.Elements.OfType<DFLayoutField>())
|
|
|
+ var property = DataModel != null ? field.GetPropertyValue<string>("Property") : null;
|
|
|
+ if (!property.IsNullOrWhiteSpace())
|
|
|
{
|
|
|
- var property = DataModel != null ? field.GetPropertyValue<string>("Property") : null;
|
|
|
- if (!property.IsNullOrWhiteSpace())
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ if(fieldControl != null)
|
|
|
{
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- if(fieldControl != null)
|
|
|
- {
|
|
|
- fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
- }
|
|
|
+ fieldControl.SetValue(DataModel!.GetEntityValue(property));
|
|
|
}
|
|
|
}
|
|
|
- Form.EvaluateExpressions();
|
|
|
- _changing = false;
|
|
|
- _isChanged = false;
|
|
|
}
|
|
|
+ Form.EvaluateExpressions();
|
|
|
+ _changing = false;
|
|
|
+ _isChanged = false;
|
|
|
+ }
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Takes values from editors and saves them to a dictionary; must be called after <see cref="Initialize"/>.
|
|
|
- /// </summary>
|
|
|
- /// <returns>A dictionary of <see cref="DigitalFormVariable.Code"/> -> value.</returns>
|
|
|
- public DFSaveStorage SaveValues()
|
|
|
- {
|
|
|
- var result = new DFSaveStorage();
|
|
|
- foreach (var formElement in form.Elements)
|
|
|
- if (formElement is DFLayoutField field)
|
|
|
- {
|
|
|
- GetFieldValue(field, result.GetEntry(field.Name), out var entityValue);
|
|
|
+ /// <summary>
|
|
|
+ /// Takes values from editors and saves them to a dictionary; must be called after <see cref="Initialize"/>.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>A dictionary of <see cref="DigitalFormVariable.Code"/> -> value.</returns>
|
|
|
+ public DFSaveStorage SaveValues()
|
|
|
+ {
|
|
|
+ var result = new DFSaveStorage();
|
|
|
+ foreach (var formElement in form.Elements)
|
|
|
+ if (formElement is DFLayoutField field)
|
|
|
+ {
|
|
|
+ GetFieldValue(field, result.GetEntry(field.Name), out var entityValue);
|
|
|
|
|
|
- if(DataModel != null)
|
|
|
- {
|
|
|
- var property = field.GetPropertyValue<string>("Property");
|
|
|
- if (!string.IsNullOrWhiteSpace(property))
|
|
|
- DataModel.SetEntityValue(property, entityValue);
|
|
|
- }
|
|
|
+ if(DataModel != null)
|
|
|
+ {
|
|
|
+ var property = field.GetPropertyValue<string>("Property");
|
|
|
+ if (!string.IsNullOrWhiteSpace(property))
|
|
|
+ DataModel.SetEntityValue(property, entityValue);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
- }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- public bool Validate(out List<string> messages)
|
|
|
+ public bool Validate(out List<string> messages)
|
|
|
+ {
|
|
|
+ messages = new List<string>();
|
|
|
+ var valid = true;
|
|
|
+ foreach(var formElement in form.Elements)
|
|
|
{
|
|
|
- messages = new List<string>();
|
|
|
- var valid = true;
|
|
|
- foreach(var formElement in form.Elements)
|
|
|
+ if(formElement is DFLayoutField field)
|
|
|
{
|
|
|
- if(formElement is DFLayoutField field)
|
|
|
+ var fieldControl = GetFieldControl(field);
|
|
|
+ if(fieldControl != null && !fieldControl.Validate(out var message))
|
|
|
{
|
|
|
- var fieldControl = GetFieldControl(field);
|
|
|
- if(fieldControl != null && !fieldControl.Validate(out var message))
|
|
|
- {
|
|
|
- messages.Add(message);
|
|
|
- valid = false;
|
|
|
- }
|
|
|
+ messages.Add(message);
|
|
|
+ valid = false;
|
|
|
}
|
|
|
}
|
|
|
- return valid;
|
|
|
}
|
|
|
+ return valid;
|
|
|
+ }
|
|
|
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- }
|
|
|
}
|