|
@@ -198,6 +198,9 @@ namespace InABox.DynamicGrid
|
|
|
public event CreateVariableHandler? OnCreateVariable;
|
|
|
public event EditVariableHandler? OnEditVariable;
|
|
|
|
|
|
+ public delegate void CustomiseElementContextMenuHandler(ContextMenu menu, DFLayoutElement element);
|
|
|
+ public event CustomiseElementContextMenuHandler? CustomiseElementContextMenu;
|
|
|
+
|
|
|
public IList<DigitalFormVariable> Variables
|
|
|
{
|
|
|
get => _variables;
|
|
@@ -276,18 +279,20 @@ namespace InABox.DynamicGrid
|
|
|
public string Caption { get; set; }
|
|
|
public Type ElementType { get; set; }
|
|
|
public string Category { get; set; }
|
|
|
- public FrameworkElement? Element { get; set; }
|
|
|
public bool AllowDuplicate { get; set; }
|
|
|
+ public object? Tag { get; set; }
|
|
|
+ public Func<object?, DFLayoutElement>? CreateElement { get; set; }
|
|
|
|
|
|
public bool Visible { get; set; }
|
|
|
|
|
|
- public DynamicFormElement(string caption, Type elementType, string category, FrameworkElement? element, bool allowDuplicate, bool visible)
|
|
|
+ public DynamicFormElement(string caption, Type elementType, string category, bool allowDuplicate, bool visible, object? tag, Func<object?, DFLayoutElement>? createElement)
|
|
|
{
|
|
|
Caption = caption;
|
|
|
ElementType = elementType;
|
|
|
Category = category;
|
|
|
- Element = element;
|
|
|
AllowDuplicate = allowDuplicate;
|
|
|
+ Tag = tag;
|
|
|
+ CreateElement = createElement;
|
|
|
Visible = visible;
|
|
|
}
|
|
|
}
|
|
@@ -319,10 +324,20 @@ namespace InABox.DynamicGrid
|
|
|
{
|
|
|
AddElement(typeof(TElement), caption, category, allowduplicate, visible: visible);
|
|
|
}
|
|
|
+ public void AddElement<TElement, TTag>(string caption, string category, TTag tag, Func<TTag, TElement> createElement, bool allowduplicate = false, bool visible = true)
|
|
|
+ where TElement : DFLayoutElement
|
|
|
+ {
|
|
|
+ AddElement(typeof(TElement), caption, category, tag, createElement, allowduplicate, visible: visible);
|
|
|
+ }
|
|
|
|
|
|
public void AddElement(Type TElement, string caption, string category, bool allowduplicate = false, bool visible = true)
|
|
|
{
|
|
|
- _elements.Add(new DynamicFormElement(caption, TElement, category, null, allowduplicate, visible));
|
|
|
+ _elements.Add(new DynamicFormElement(caption, TElement, category, allowduplicate, visible, null, null));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AddElement<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)
|
|
@@ -401,14 +416,6 @@ namespace InABox.DynamicGrid
|
|
|
return string.Format("{0}px", length.Value);
|
|
|
}
|
|
|
|
|
|
- private static MenuItem CreateMenuItem<TTag>(string caption, TTag tag, Action<TTag>? click)
|
|
|
- {
|
|
|
- var result = new MenuItem { Header = caption, Tag = tag };
|
|
|
- if (click != null)
|
|
|
- result.Click += (o, e) => click((TTag)(o as MenuItem)!.Tag);
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
private static void AddClick<TTag>(ButtonBase button, TTag tag, Action<TTag> click)
|
|
|
{
|
|
|
button.Tag = tag;
|
|
@@ -1318,16 +1325,16 @@ namespace InABox.DynamicGrid
|
|
|
|
|
|
private void PopulateRowMenu(ContextMenu menu, int row)
|
|
|
{
|
|
|
- menu.Items.Add(CreateMenuItem("Add Row Before", row, AddRowBeforeClick));
|
|
|
- menu.Items.Add(CreateMenuItem("Add Row After", row, AddRowAfterClick));
|
|
|
- menu.Items.Add(new Separator());
|
|
|
- menu.Items.Add(CreateMenuItem("Split Row", row, SplitRowClick));
|
|
|
- var propertiesSeparator = new Separator();
|
|
|
- var propertiesMenu = CreateMenuItem("Row Properties", row, RowPropertiesClick);
|
|
|
- menu.Items.Add(propertiesSeparator);
|
|
|
- menu.Items.Add(propertiesMenu);
|
|
|
- menu.Items.Add(new Separator());
|
|
|
- menu.Items.Add(CreateMenuItem("Delete Row", new Range(row, row), DeleteRows));
|
|
|
+ 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 propertiesSeparator = menu.AddSeparator();
|
|
|
+ var propertiesMenu = menu.AddItem("Row Properties", null, row, RowPropertiesClick);
|
|
|
+
|
|
|
+ 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;
|
|
@@ -1451,16 +1458,14 @@ namespace InABox.DynamicGrid
|
|
|
|
|
|
private void PopulateColumnMenu(ContextMenu menu, int column)
|
|
|
{
|
|
|
- menu.Items.Add(CreateMenuItem("Add Column Before", column, AddColumnBeforeClick));
|
|
|
- menu.Items.Add(CreateMenuItem("Add Column After", column, AddColumnAfterClick));
|
|
|
- menu.Items.Add(new Separator());
|
|
|
- menu.Items.Add(CreateMenuItem("Split Column", column, SplitColumnClick));
|
|
|
- var propertiesSeparator = new Separator();
|
|
|
- var propertiesMenu = CreateMenuItem("Column Properties", column, ColumnPropertiesClick);
|
|
|
- menu.Items.Add(propertiesSeparator);
|
|
|
- menu.Items.Add(propertiesMenu);
|
|
|
- menu.Items.Add(new Separator());
|
|
|
- menu.Items.Add(CreateMenuItem("Delete Column", new Range(column, column), DeleteColumns));
|
|
|
+ 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;
|
|
@@ -1480,10 +1485,22 @@ namespace InABox.DynamicGrid
|
|
|
|
|
|
#region Add Element
|
|
|
|
|
|
- private void AddNewElement<TElement>(CellRange range)
|
|
|
+ private void AddNewElement<TElement>(DynamicFormElement elementDef, CellRange range)
|
|
|
where TElement : DFLayoutElement, new()
|
|
|
{
|
|
|
- var element = new TElement();
|
|
|
+ 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 });
|
|
@@ -1494,12 +1511,12 @@ namespace InABox.DynamicGrid
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void AddElementClick(Tuple<Type, CellRange> tuple)
|
|
|
+ private void AddElementClick(Tuple<DynamicFormElement, CellRange> tuple)
|
|
|
{
|
|
|
var method = typeof(DynamicFormDesignGrid)
|
|
|
.GetMethod(nameof(AddNewElement), BindingFlags.NonPublic | BindingFlags.Instance)!
|
|
|
- .MakeGenericMethod(tuple.Item1);
|
|
|
- method.Invoke(this, new object[] { tuple.Item2 });
|
|
|
+ .MakeGenericMethod(tuple.Item1.ElementType);
|
|
|
+ method.Invoke(this, new object[] { tuple.Item1, tuple.Item2 });
|
|
|
}
|
|
|
|
|
|
private void ElementActionClick(Tuple<DynamicFormElementAction, CellRange> tuple)
|
|
@@ -1619,7 +1636,7 @@ namespace InABox.DynamicGrid
|
|
|
menu.Items.Remove(fields);
|
|
|
}
|
|
|
|
|
|
- var elements = CreateMenuItem("Add Object", 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();
|
|
@@ -1630,8 +1647,7 @@ namespace InABox.DynamicGrid
|
|
|
var parentMenu = elements;
|
|
|
if (!string.IsNullOrWhiteSpace(cat))
|
|
|
{
|
|
|
- parentMenu = new MenuItem { Header = cat };
|
|
|
- elements.Items.Add(parentMenu);
|
|
|
+ parentMenu = elements.AddItem(cat, null, null);
|
|
|
}
|
|
|
|
|
|
foreach(var action in _elementActions.Where(x => x.Category == cat))
|
|
@@ -1642,12 +1658,12 @@ namespace InABox.DynamicGrid
|
|
|
parentMenu.AddSeparatorIfNeeded();
|
|
|
|
|
|
foreach (var element in available.Where(x => string.Equals(x.Category, cat)))
|
|
|
- parentMenu.AddItem(element.Caption, null, new Tuple<Type, CellRange>(element.ElementType, cellRange), AddElementClick);
|
|
|
+ parentMenu.AddItem(element.Caption, null, new Tuple<DynamicFormElement, CellRange>(element, cellRange), AddElementClick);
|
|
|
parentMenu.RemoveUnnecessarySeparators();
|
|
|
}
|
|
|
|
|
|
- if (elements.Items.Count > 0)
|
|
|
- menu.Items.Add(elements);
|
|
|
+ if (elements.Items.Count == 0)
|
|
|
+ menu.Items.Remove(elements);
|
|
|
}
|
|
|
|
|
|
private ContextMenu CreateEmptyCellMenu(Border border, int row, int column)
|
|
@@ -1759,22 +1775,26 @@ namespace InABox.DynamicGrid
|
|
|
if(menu.Items.Count > 0) return;
|
|
|
}
|
|
|
|
|
|
- menu.Items.Add(CreateMenuItem("Edit Properties", control, ElementPropertiesClick));
|
|
|
+ menu.AddItem("Edit Properties", null, control, ElementPropertiesClick);
|
|
|
if (OnEditVariable is not null && control is DFLayoutField field)
|
|
|
{
|
|
|
- menu.Items.Add(CreateMenuItem("Edit Variable", field, EditVariableClick));
|
|
|
+ menu.AddItem("Edit Variable", null, field, EditVariableClick);
|
|
|
+ }
|
|
|
+ else if (control is DFLayoutLabel label)
|
|
|
+ {
|
|
|
+ menu.AddItem("Convert to Header", null, label, ConvertToHeaderClick);
|
|
|
}
|
|
|
- if (control is DFLayoutLabel label)
|
|
|
+ else if (control is DFLayoutHeader header)
|
|
|
{
|
|
|
- menu.Items.Add(CreateMenuItem("Convert to Header", label, ConvertToHeaderClick));
|
|
|
+ menu.AddItem("Convert to Label", null, header, ConvertToLabelClick);
|
|
|
}
|
|
|
- if (control is DFLayoutHeader header)
|
|
|
+ else if(control is DFLayoutElement element)
|
|
|
{
|
|
|
- menu.Items.Add(CreateMenuItem("Convert to Label", header, ConvertToLabelClick));
|
|
|
+ CustomiseElementContextMenu?.Invoke(menu, element);
|
|
|
}
|
|
|
- menu.Items.Add(new Separator());
|
|
|
+ menu.AddSeparatorIfNeeded();
|
|
|
menu.AddItem("Resize Item", null, control, ResizeItem);
|
|
|
- menu.Items.Add(CreateMenuItem("Delete Item", control, DeleteElementClick));
|
|
|
+ menu.AddItem("Delete Item", null, control, DeleteElementClick);
|
|
|
}
|
|
|
|
|
|
private ContextMenu CreateElementContextMenu(FrameworkElement element, DFLayoutControl control)
|