using InABox.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace InABox.DynamicGrid
{
///
/// Interaction logic for EmbeddedDynamicEditorForm.xaml
///
public partial class EmbeddedDynamicEditorForm : UserControl, IDynamicEditorForm
{
public event OnBeforeLoad? OnBeforeLoad;
public void BeforeLoad() => OnBeforeLoad?.Invoke(this);
public event OnAfterLoad? OnAfterLoad;
public void AfterLoad() => OnAfterLoad?.Invoke(this);
public event EventHandler OnChanged;
public void DoChanged()
{
//OKButton.IsEnabled = true;
//CancelButton.IsEnabled = true;
OnChanged?.Invoke(this, EventArgs.Empty);
}
public delegate void OKEvent();
public delegate void CancelEvent();
public DynamicEditorPages Pages { get; private set; } = new();
private BaseObject[] _items;
public BaseObject[] Items
{
get => _items;
set
{
_items = value;
DynamicEditorFormModel.Slug = Items != null ? Items.Any() ? Items.First().GetType().EntityName().Split('.').Last() : "" : "";
Editor.Load(Pages);
foreach (var page in Pages)
page.OnChanged += (sender, args) => DoChanged();
}
}
public bool ReadOnly
{
get => Editor.ReadOnly;
set
{
OKButton.IsEnabled = !value;
CancelButton.IsEnabled = !value;
Editor.ReadOnly = value;
}
}
private bool _hideButtons = false;
public bool HideButtons
{
get => _hideButtons;
set
{
_hideButtons = value;
OKButton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
CancelButton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
}
}
private bool _highlightButtons = false;
public bool HighlightButtons
{
get => _highlightButtons;
set
{
_highlightButtons = value;
UpdateButtonHighlight(OKButton, Colors.DarkGreen, Colors.LimeGreen, Colors.White);
UpdateButtonHighlight(CancelButton, Colors.Firebrick, Colors.Red, Colors.White);
}
}
private void UpdateButtonHighlight(Button button, Color border, Color background, Color foreground)
{
button.BorderBrush = _highlightButtons
? new SolidColorBrush(border)
: new SolidColorBrush(Colors.Gray);
button.Background = _highlightButtons
? new SolidColorBrush(background)
: new SolidColorBrush(Colors.Gainsboro);
button.Foreground = _highlightButtons
? new SolidColorBrush(foreground)
: new SolidColorBrush(Colors.Black);
button.FontWeight = _highlightButtons
? FontWeights.Bold
: FontWeights.Normal;
}
public static readonly DependencyProperty ButtonsVisibleProperty =
DependencyProperty.Register(
nameof(ButtonsVisible),
typeof(bool),
typeof(EmbeddedDynamicEditorForm),
new UIPropertyMetadata(true)
);
public bool ButtonsVisible
{
get => (bool)GetValue(ButtonsVisibleProperty);
set
{
SetValue(ButtonsVisibleProperty, value);
UpdateButtonsRowVisibility();
}
}
private void UpdateButtonsRowVisibility()
{
ButtonRow.Height = ButtonsVisible
? new GridLength(40, GridUnitType.Pixel)
: new GridLength(0, GridUnitType.Pixel);
}
public static readonly DependencyProperty TabsVisibleProperty =
DependencyProperty.Register(
nameof(TabsVisible),
typeof(bool),
typeof(EmbeddedDynamicEditorForm),
new UIPropertyMetadata(true)
);
public bool TabsVisible
{
get => (bool)GetValue(TabsVisibleProperty);
set
{
SetValue(TabsVisibleProperty, value);
UpdateTabsVisibility();
}
}
private void UpdateTabsVisibility()
{
Editor.TabStripVisible = TabsVisible;
}
#region Events
public event OnValidateData? OnValidateData;
public OnCustomiseColumns? OnCustomiseColumns { get; set; }
public OnDefineFilter? OnDefineFilter { get; set; }
public OnDefineLookup? OnDefineLookups { get; set; }
public DefineEditorEventHandler? OnDefineEditor { get; set; }
public event OnFormCustomiseEditor? OnFormCustomiseEditor;
public OnReconfigureEditors? OnReconfigureEditors { get; set; }
public event EditorValueChangedHandler? OnEditorValueChanged;
public event OnAfterEditorValueChanged? OnAfterEditorValueChanged;
public event OnSelectPage? OnSelectPage;
public DynamicGridSaveEvent? OnSaveItem { get; set; }
public DynamicEditorGrid.EditorCreatedHandler? OnEditorCreated;
public event OKEvent? OnOK;
public event CancelEvent? OnCancel;
#endregion
public EmbeddedDynamicEditorForm()
{
InitializeComponent();
ReadOnly = false;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
UpdateButtonsRowVisibility();
UpdateTabsVisibility();
}
public EmbeddedDynamicEditorForm(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
Func? PageDataHandler = null, bool PreloadPages = false): this()
{
Setup(type, pages, buttons, PageDataHandler, PreloadPages);
}
private IFilter? Editor_OnDefineFilter(Type type)
{
return OnDefineFilter?.Invoke(type);
}
private void ClearEvents()
{
OnEditorValueChanged = null;
OnAfterEditorValueChanged = null;
OnSelectPage = null;
OnValidateData = null;
}
public void Setup(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
Func? PageDataHandler = null, bool PreloadPages = false)
{
ClearEvents();
Editor.UnderlyingType = type;
Editor.OnLoadPage = page => { page.Load(Items.First(), PageDataHandler); };
Editor.PreloadPages = PreloadPages;
Pages = pages ?? new DynamicEditorPages();
Buttons.Children.Clear();
if (buttons != null)
foreach (var button in buttons)
{
var btn = new Button();
UpdateButton(btn, button.Image, button.Name);
btn.Tag = button;
btn.Margin = new Thickness(5, 5, 0, 5);
btn.Padding = new Thickness(5, 0, 5, 0);
btn.Click += Btn_Click;
Buttons.Children.Add(btn);
button.Button = btn;
button.Form = this;
}
}
public void UnloadEditorPages(bool saved)
{
Editor.UnloadPages(saved);
}
protected void UpdateButton(Button button, BitmapImage? image, string text)
{
var stackPnl = new StackPanel();
stackPnl.Orientation = Orientation.Horizontal;
//stackPnl.Margin = new Thickness(2);
if (image != null)
{
var img = new Image();
img.Source = image;
img.Margin = new Thickness(2);
stackPnl.Children.Add(img);
}
if (!string.IsNullOrEmpty(text))
{
var lbl = new Label();
lbl.Content = text;
lbl.VerticalAlignment = VerticalAlignment.Stretch;
lbl.VerticalContentAlignment = VerticalAlignment.Center;
lbl.Margin = new Thickness(2, 0, 5, 0);
stackPnl.Children.Add(lbl);
}
button.Content = stackPnl;
}
private Dictionary EditorValueChanged(IDynamicEditorForm sender, string name, object value)
{
if (OnEditorValueChanged != null)
return OnEditorValueChanged(sender, name, value);
return DynamicGridUtils.UpdateEditorValue(_items, name, value);
}
private void Editor_OnEditorCreated(object sender, double height, double width)
{
OnEditorCreated?.Invoke(sender, height, width);
Editor.VerticalAlignment = VerticalAlignment.Stretch;
Editor.HorizontalAlignment = HorizontalAlignment.Stretch;
}
private void Editor_OnCustomiseColumns(object sender, DynamicGridColumns columns)
{
columns.Clear();
if (_items != null && _items.Any())
columns.ExtractColumns(_items.First().GetType());
OnCustomiseColumns?.Invoke(this, columns);
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var deb = (DynamicEditorButton)button.Tag;
deb.Click();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
var errors = OnValidateData?.Invoke(this, Items);
if (errors != null && errors.Any())
{
MessageBox.Show(
string.Format("The following errors have been found with your data!\nPlease correct them and try again.\n\n- {0}",
string.Join("\n- ", errors)), "Validation Error");
return;
}
OnOK?.Invoke();
//OKButton.IsEnabled = false;
//CancelButton.IsEnabled = false;
// Don't Commit the changes here, because we want to refer back to thos changes when we save the item
// to trigger specific processes in the database
//Close();
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
// However, if we cancel the edits, then we can safely revert the items back to their original (loaded) state
foreach (var item in _items)
item.CancelChanges();
OnCancel?.Invoke();
//OKButton.IsEnabled = false;
//CancelButton.IsEnabled = false;
//Close();
}
public void SaveItem(CancelEventArgs e)
{
OnSaveItem?.Invoke(this, e);
}
public bool TryFindEditor(string columnname, [NotNullWhen(true)] out IDynamicEditorControl? editor)
{
return Editor.TryFindEditor(columnname, out editor);
}
public IDynamicEditorControl FindEditor(string columnname)
{
return Editor.FindEditor(columnname);
}
public object? GetEditorValue(string columnName) => FindEditor(columnName).GetValue(columnName);
public void SetEditorValue(string columnName, object? value) => FindEditor(columnName).SetValue(columnName, value);
public void SetLayoutType() where T : DynamicEditorGridLayout => Editor.SetLayoutType();
private void Editor_OnSelectPage(DynamicEditorGrid sender, BaseObject[] items)
{
OnSelectPage?.Invoke(sender, items);
}
private void Editor_OnUnloadPage(IDynamicEditorPage page, bool saved)
{
if (!saved)
page.BeforeSave(Items.First());
else
page.AfterSave(Items.First());
}
private Dictionary? Editor_OnAfterEditorValueChanged(DynamicEditorGrid sender, AfterEditorValueChangedArgs args)
{
if(args.ChangedValues.Count > 0)
{
DoChanged();
}
return OnAfterEditorValueChanged?.Invoke(sender, args);
}
private void Editor_OnReconfigureEditors(DynamicEditorGrid sender)
{
OnReconfigureEditors?.Invoke(sender);
}
private void Editor_OnGridCustomiseEditor(DynamicEditorGrid sender, DynamicGridColumn column, BaseEditor editor)
{
OnFormCustomiseEditor?.Invoke(this, Items, column, editor);
}
private decimal Editor_OnGetSequence(DynamicGridColumn column)
{
if (_items.Any())
return CoreUtils.GetPropertySequence(_items.First().GetType(), column.ColumnName);
return 0.0M;
}
private void Editor_OnDefineLookups(ILookupEditorControl editor)
{
OnDefineLookups?.Invoke(editor);
}
private object?[] Editor_GetItems()
{
return _items;
}
private BaseEditor Editor_OnGetEditor(DynamicGridColumn column)
{
if (_items != null && _items.Any())
{
var property = DatabaseSchema.Property(Editor.UnderlyingType, column.ColumnName);
if (property == null) return new NullEditor();
if (property.Editor is NullEditor)
return property.Editor;
BaseEditor editor;
if (property is CustomProperty)
{
editor = property.Editor.CloneEditor();
}
else
{
editor = OnDefineEditor?.Invoke(_items[0], column) ?? column.Editor.CloneEditor();
var propEditor = property.Editor;
editor.Page = propEditor.Page;
editor.Caption = propEditor.Caption;
}
//if (ReadOnly && editor.Editable.IsEditable())
// editor.Editable = Editable.Disabled;
return editor;
}
return new NullEditor();
}
private object? Editor_OnGetPropertyValue(object sender, string column)
{
if (!_items.Any())
return null;
object? result;
try
{
result = CoreUtils.GetPropertyValue(_items.First(), column);
}
catch
{
result = _items.First().UserProperties.ContainsKey(column) ? _items.First().UserProperties[column] : null;
}
if (result == null)
return null;
foreach (var _item in _items)
{
object? curvalue;
try
{
curvalue = CoreUtils.GetPropertyValue(_item, column);
}
catch
{
curvalue = _item.UserProperties.ContainsKey(column) ? _item.UserProperties[column] : null;
}
if (curvalue == null)
return null;
if (!curvalue.Equals(result))
return null;
}
return result;
}
private void Editor_OnSetPropertyValue(object sender, string column, object value)
{
foreach (var _item in _items)
if (_item.UserProperties.ContainsKey(column))
_item.UserProperties[column] = value;
else
CoreUtils.SetPropertyValue(_item, column, value);
}
//public void EditLayout() => Editor.EditLayout();
//public void ResetLayout() => Editor.ResetLayout();
public void AddButton(Button button)
{
Buttons.Children.Add(button);
}
private Dictionary Editor_OnEditorValueChanged(DynamicEditorGrid sender, string name, object value)
{
return OnEditorValueChanged?.Invoke(this, name, value) ?? new();
}
}
}