123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Interop;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using InABox.Core;
- using InABox.DynamicGrid.Properties;
- using InABox.Wpf;
- using InABox.WPF;
- using Syncfusion.Windows.Shared;
- using Syncfusion.Windows.Tools.Controls;
- namespace InABox.DynamicGrid
- {
- public delegate BaseEditor? DefineEditorEventHandler(object item, DynamicGridColumn column);
- public delegate void DynamicGridSaveEvent(object sender, CancelEventArgs args);
- public interface IDynamicEditorForm
- {
- }
- public class UtilityItem
- {
- public string Name { get; set; }
- public ImageSource Icon { get; set; }
- public string Text { get; set; }
- public SizeMode Mode { get; set; }
- public ICommand Command { get; set; }
- }
- public class UtilityViewModel
- {
- /// <summary>
- /// Constructor of the UtilityViewModel class.
- /// </summary>
- public UtilityViewModel()
- {
- var utilities = new ObservableCollection<UtilityItem>();
- utilities.Add(new UtilityItem
- { Name = "Help", Icon = Resources.help.AsBitmapImage(), Text = "", Mode = SizeMode.Normal, Command = HelpCommand });
- Utilities = utilities;
- }
- /// <summary>
- /// Collection containing the complete details of the items to be bound in the title bar.
- /// </summary>
- public ObservableCollection<UtilityItem> Utilities { get; }
- /// <summary>
- /// Commmand for the Help button.
- /// </summary>
- public DelegateCommand HelpCommand => new(HelpCommandAction);
- public static string Slug { get; set; }
- /// <summary>
- /// Action that is performed when clicking the help button.
- /// </summary>
- private void HelpCommandAction(object param)
- {
- Process.Start("https://prs-software.com.au/wiki/index.php/" + Slug);
- }
- }
- /// <summary>
- /// Interaction logic for DynamicEditor.xaml
- /// </summary>
- public partial class DynamicEditorForm : ThemableChromelessWindow, IDynamicEditorForm
- {
- public delegate Document? FindDocumentEvent(string FileName);
- public delegate Document? GetDocumentEvent(Guid id);
- public delegate void SaveDocumentEvent(Document document);
- private BaseObject[] _items;
- private Func<Type, CoreTable> _pagedatahandler = null;
- private bool _preloadpages = false;
- public DynamicEditorGrid Editor;
- public OnValidateData OnValidateData;
- public DynamicEditorForm(Type type, DynamicEditorPages pages = null, DynamicEditorButtons buttons = null,
- Func<Type, CoreTable>? PageDataHandler = null, bool PreloadPages = false)
- {
- ReadOnly = false;
- InitializeComponent();
- //this.Loaded += new RoutedEventHandler(ConfigureSystemMenu);
- var grid = Content as Grid;
- Editor = grid.Children.OfType<DynamicEditorGrid>().FirstOrDefault();
- Editor.UnderlyingType = type;
- Editor.OnCustomiseColumns += Editor_OnCustomiseColumns;
- Editor.OnDefineFilter += (sender, t) => OnDefineFilter(sender, t);
- Editor.OnEditorCreated += Editor_OnEditorCreated;
- Editor.OnLoadPage += page => { page.Load(Items.First(), PageDataHandler); };
- Editor.OnSelectPage += (tab, items) => { OnSelectPage?.Invoke(tab, items); };
- Editor.PreloadPages = PreloadPages;
- Editor.OnUnloadPage += (page, saved) =>
- {
- if (!saved)
- page.BeforeSave(Items.First());
- else
- page.AfterSave(Items.First());
- };
- //Editor.OnGetPropertyInfo += (o, c) => { return CoreUtils.GetProperty(_item.GetType(), c); };
- Editor.ReconfigureEditors += g => { ReconfigureEditors?.Invoke(g); };
- Editor.OnGetEditor += c =>
- {
- if (_items != null && _items.Any())
- {
- var property = DatabaseSchema.Property(type, c.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], c) ?? c.Editor.CloneEditor();
- var propEditor = property.Editor;
- editor.Page = propEditor.Page;
- editor.Caption = propEditor.Caption;
- }
- //defaultEditor.EditorSequence
- //EditorUtils.GetPropertyEditor(type, property, defaultEditor);
- /*BaseEditor editor = new NullEditor();
- var caption = "";
- var page = "";
- try
- {
- var comps = c.ColumnName.Split('.');
- for (var i = 0; i < comps.Length; i++)
- {
- var column = string.Join(".", comps.Take(i + 1));
- var prop = CoreUtils.GetProperty(type, column);
- if (column.Equals(c.ColumnName))
- {
- if (OnDefineEditor != null)
- editor = OnDefineEditor(_items[0], c);
- else
- editor = c.Editor != null ? c.Editor : new NullEditor();
- }
- else
- {
- var pedit = prop.GetEditor();
- if (pedit is NullEditor)
- return pedit;
- }
- editor = editor == null ? new NullEditor() : editor.Clone() as BaseEditor;
- var capattr = prop.GetCustomAttribute<Caption>();
- var subcap = capattr != null ? capattr.Text : comps[i];
- var path = capattr != null ? capattr.IncludePath : true;
- if (!string.IsNullOrWhiteSpace(subcap))
- caption = string.IsNullOrWhiteSpace(caption) || path == false ? subcap : string.Format("{0} {1}", caption, subcap);
- if (string.IsNullOrWhiteSpace(page))
- {
- var pageattr = prop.GetCustomAttribute<EditorSequence>();
- if (pageattr != null)
- page = pageattr.Page;
- }
- }
- editor.Caption = caption;
- editor.Page = page;
- }
- catch (Exception e)
- {
- var dmprop = DatabaseSchema.Property(_items[0].GetType(), c.ColumnName);
- if (dmprop is CustomProperty)
- {
- editor = dmprop.Editor.Clone() as BaseEditor;
- editor.Caption = dmprop.Caption;
- editor.Page = string.IsNullOrWhiteSpace(dmprop.Page) ? "Custom Fields" : dmprop.Page;
- }
- }*/
- if (ReadOnly && editor.Editable.Equals(Editable.Enabled))
- editor.Editable = Editable.Disabled;
- return editor;
- }
- return new NullEditor();
- };
- Editor.OnGridCustomiseEditor += (sender, column, editor) => OnFormCustomiseEditor?.Invoke(this, Items, column, editor);
- Editor.OnGetSequence += c => CoreUtils.GetPropertySequence(_items.First().GetType(), c.ColumnName);
- Editor.OnGetPropertyValue += (o, c) =>
- {
- if (!_items.Any())
- return null;
- object result = null;
- try
- {
- result = CoreUtils.GetPropertyValue(_items.First(), c);
- }
- catch
- {
- result = _items.First().UserProperties.ContainsKey(c) ? _items.First().UserProperties[c] : null;
- }
- if (result == null)
- return null;
- foreach (var _item in _items)
- {
- object curvalue = null;
- try
- {
- curvalue = CoreUtils.GetPropertyValue(_item, c);
- }
- catch
- {
- curvalue = _item.UserProperties.ContainsKey(c) ? _item.UserProperties[c] : null;
- }
- if (curvalue == null)
- return null;
- if (!curvalue.Equals(result))
- return null;
- }
- return result;
- };
- Editor.OnSetPropertyValue += (o, c, v) =>
- {
- foreach (var _item in _items)
- if (_item.UserProperties.ContainsKey(c))
- _item.UserProperties[c] = v;
- else
- CoreUtils.SetPropertyValue(_item, c, v);
- };
- Editor.OnEditorValueChanged += EditorValueChanged;
- Editor.OnDefineLookups += sender => { OnDefineLookups?.Invoke(sender); };
- Editor.OnLookupsDefined += sender => { OnLookupsDefined?.Invoke(sender); };
- Editor.OnGetDocument += id => { return OnGetDocument?.Invoke(id); };
- Editor.OnSaveDocument += doc => { OnSaveDocument?.Invoke(doc); };
- Editor.OnFindDocument += file => { return OnFindDocument?.Invoke(file); };
- Pages = pages;
- if (Pages == null || Pages.Count == 0)
- Editor.Margin = new Thickness(5, 5, 5, 0);
- 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 DynamicEditorPages Pages { get; }
- public BaseObject[] Items
- {
- get => _items;
- set
- {
- _items = value;
- UtilityViewModel.Slug = Items != null ? Items.Any() ? Items.First().GetType().EntityName().Split('.').Last() : "" : "";
- Editor.Load(_items.First().GetType().EntityName(), Pages);
- }
- }
- public bool ReadOnly { get; set; }
- public event OnCustomiseColumns OnCustomiseColumns;
- public event OnDefineFilter OnDefineFilter;
- public event DefineEditorEventHandler OnDefineEditor;
- public event OnFormCustomiseEditor OnFormCustomiseEditor;
- public event OnReconfigureEditors ReconfigureEditors;
- //public delegate void EditorValueChangedHandler(object sender, String name, object value, List<String> changes);
- //public event EditorValueChangedHandler OnEditorValueChanged;
- public event EditorValueChangedHandler OnEditorValueChanged;
- //public event DefineFilter OnDefineFilter;
- public event OnDefineLookup OnDefineLookups;
- public event OnLookupsDefined OnLookupsDefined;
- public event GetDocumentEvent OnGetDocument;
- public event FindDocumentEvent OnFindDocument;
- public event SaveDocumentEvent OnSaveDocument;
- public event OnSelectPage OnSelectPage;
- public void UnloadEditorPages(DynamicEditorPages pages, object item, 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<string, object> EditorValueChanged(object 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)
- {
- var screen = WpfScreen.GetScreenFrom(new Point(Left, Top));
- double spareheight = 90;
- double sparewidth = 25;
- var desiredheight = height + spareheight;
- var desiredwidth = width + sparewidth;
- if (Pages != null)
- foreach (var page in Pages)
- {
- if (desiredheight < page.MinimumSize().Height)
- desiredheight = page.MinimumSize().Height;
- if (desiredwidth < page.MinimumSize().Width)
- desiredwidth = page.MinimumSize().Width;
- }
- var maxheight = screen.WorkingArea.Height - 0;
- Height = desiredheight > maxheight ? maxheight : desiredheight;
- var maxwidth = screen.WorkingArea.Width - 0;
- Width = desiredwidth > maxwidth ? maxwidth : desiredwidth;
- Left = screen.DeviceBounds.Left + (screen.DeviceBounds.Width - Width) / 2.0F;
- Top = screen.DeviceBounds.Top + (screen.DeviceBounds.Height - Height) / 2.0F;
- Editor.VerticalAlignment = VerticalAlignment.Stretch;
- Editor.HorizontalAlignment = HorizontalAlignment.Stretch;
- var scaption = _items[0].GetType().GetCaption();
- Title = "Edit " + scaption.SplitCamelCase();
- if (Editor.IsCustomLayout)
- Title = Title + "*";
- OKButton.IsEnabled = !ReadOnly;
- }
-
- private DynamicGridColumns Editor_OnCustomiseColumns(object sender, DynamicGridColumns source)
- {
- var columns = new DynamicGridColumns();
- if (_items != null && _items.Any())
- columns.ExtractColumns(_items.First().GetType(), "");
- if (OnCustomiseColumns != null)
- columns = OnCustomiseColumns.Invoke(this, columns);
- return 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 != null ? OnValidateData.Invoke(this, Items) : null;
- 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;
- }
- // 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
- DialogResult = true;
- //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();
- DialogResult = false;
- //Close();
- }
- public IDynamicEditorControl FindEditor(string columnname)
- {
- return Editor.FindEditor(columnname);
- }
- public event DynamicGridSaveEvent OnSaveItem;
- private void Window_Closing(object sender, CancelEventArgs e)
- {
- if (DialogResult == true)
- OnSaveItem?.Invoke(this, e);
- }
- #region Win32 API Stuff
- // Define the Win32 API methods we are going to use
- [DllImport("user32.dll")]
- private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
- [DllImport("user32.dll")]
- private static extern bool InsertMenu(IntPtr hMenu, int wPosition, int wFlags, int wIDNewItem, string lpNewItem);
- /// Define our Constants we will use
- public const int WM_SYSCOMMAND = 0x112;
- public const int MF_SEPARATOR = 0x800;
- public const int MF_BYPOSITION = 0x400;
- public const int MF_STRING = 0x0;
- public const int _EditLayoutID = 1000;
- public const int _ResetLayoutID = 1001;
- public IntPtr Handle => new WindowInteropHelper(this).Handle;
- private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- {
- // Check if a System Command has been executed
- if (msg == WM_SYSCOMMAND)
- // Execute the appropriate code for the System Menu item that was clicked
- switch (wParam.ToInt32())
- {
- case _EditLayoutID:
- Editor.EditLayout();
- handled = true;
- break;
- case _ResetLayoutID:
- if (MessageBox.Show(
- "WARNING: This will delete any customisations you have made!\n\nAre you sure you wish to reset this layout?",
- "Confirm Layout Reset", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
- Editor.ResetLayout();
- handled = true;
- break;
- }
- return IntPtr.Zero;
- }
- private void ConfigureSystemMenu(object sender, RoutedEventArgs e)
- {
- /// Get the Handle for the Forms System Menu
- var systemMenuHandle = GetSystemMenu(Handle, false);
- /// Create our new System Menu items just before the Close menu item
- InsertMenu(systemMenuHandle, 5, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator
- InsertMenu(systemMenuHandle, 6, MF_BYPOSITION, _EditLayoutID, "Edit Layout");
- InsertMenu(systemMenuHandle, 7, MF_BYPOSITION, _ResetLayoutID, "Reset Layout");
- // Attach our WndProc handler to this Window
- var source = HwndSource.FromHwnd(Handle);
- source.AddHook(WndProc);
- }
- #endregion
- //private void Wiki_Click(object sender, RoutedEventArgs e)
- //{
- // System.Diagnostics.Process.Start("https://prs-software.com.au/wiki/index.php/" + CurrentPanelSlug());
- //}
- //private string CurrentPanelSlug()
- //{
- // if ((Items != null) && Items.Any())
- // return Items.First().GetType().EntityName().Split('.').Last();
- // return "";
- //}
- }
- }
|