123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Reflection;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using Comal.Classes;
- using InABox.Configuration;
- using InABox.Core;
- using InABox.DynamicGrid;
- using InABox.WPF;
- using InABox.WPF.Themes;
- using Microsoft.Xaml.Behaviors.Core;
- using Syncfusion.Windows.Tools.Controls;
- namespace PRSDesktop
- {
- public class DashboardFavourite : BaseObject
- {
- [TextBoxEditor]
- [EditorSequence(1)]
- public string Name { get; set; }
- [CheckBoxEditor]
- [EditorSequence(2)]
- public bool IsGlobal { get; set; }
- [NullEditor]
- public string Layout { get; set; }
- }
- // public class DynamicItemsListGrid<T> : DynamicGrid<T>
- // where T : BaseObject, new()
- // {
- // public List<T> Items { get; set; }
- //
- // public DynamicItemsListGrid() : this(new()) { }
- //
- // public DynamicItemsListGrid(List<T> items) : base()
- // {
- // Items = items;
- // }
- //
- // protected override void DeleteItems(params CoreRow[] rows)
- // {
- // foreach (var row in rows.OrderByDescending(x => x.Index))
- // {
- // Items.RemoveAt(row.Index);
- // }
- // }
- //
- // protected override T LoadItem(CoreRow row)
- // {
- // return Items[row.Index];
- // }
- //
- // protected override void Reload(Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sort, Action<CoreTable?, Exception?> action)
- // {
- // var result = new CoreTable();
- // result.LoadColumns(typeof(T));
- // result.LoadRows(Items);
- // action.Invoke(result, null);
- // }
- //
- // public override void SaveItem(T item)
- // {
- // if (!Items.Contains(item))
- // {
- // Items.Add(item);
- // }
- // }
- // }
- public class GlobalUtilityDashboardSettings : IGlobalConfigurationSettings
- {
- public List<DashboardFavourite> Favourites { get; set; }
- public GlobalUtilityDashboardSettings()
- {
- Favourites = new();
- }
- }
- public class UtilityDashboardSettings : IUserConfigurationSettings
- {
- public UtilityDashboardSettings()
- {
- Dashboards = new Dictionary<string, string>();
- Favourites = new();
- }
- public Dictionary<string, string> Dashboards { get; set; }
- public List<DashboardFavourite> Favourites { get; set; }
- public int Selected { get; set; }
- public bool AutoHide { get; set; }
- }
- /// <summary>
- /// Interaction logic for UtilityDashboard.xaml
- /// </summary>
- public partial class UtilityDashboard : UserControl, IBasePanel
- {
-
- private readonly Dictionary<string, DynamicFormDesignGrid> _dashboards = new();
- private readonly Dictionary<DynamicFormDesignGrid, List<ICorePanel>> _panels = new();
- private class WidgetDashboardElement
- {
- public Type DashboardElement { get; set; }
- public Type Widget { get; set; }
-
- public Type Group { get; set; }
- public Type Properties { get; set; }
- public string GroupCaption { get; set; }
- public string WidgetCaption { get; set; }
- public Type[] SecurityTokens { get; set; }
- public WidgetDashboardElement(Type dashboardElement, Type widget, Type group, Type properties, Type[] securityTokens)
- {
- DashboardElement = dashboardElement;
- Widget = widget;
- Group = group;
- Properties = properties;
- SecurityTokens = securityTokens;
- GroupCaption = UtilityDashboard.GetCaption(group);
- WidgetCaption = UtilityDashboard.GetCaption(widget);
- }
- }
- private static List<WidgetDashboardElement>? _dashboardElements;
- private string? CurrentDashboardName => DashboardsTab.SelectedTab?.Header?.ToString();
- private DynamicFormDesignGrid? CurrentDashboard => CurrentDashboardName != null ? _dashboards.GetValueOrDefault(CurrentDashboardName) : null;
-
- private UtilityDashboardSettings _settings = new();
- public UtilityDashboard()
- {
- InitializeComponent();
- }
- public void CreateToolbarButtons(IPanelHost host)
- {
- }
- private void SaveSettings()
- {
- new UserConfiguration<UtilityDashboardSettings>().Save(_settings);
- }
- #region Panel Functions & Properties
- public event DataModelUpdateEvent? OnUpdateDataModel;
- public bool IsReady { get; set; }
- public string SectionName => "Utility Dashboard";
- public DataModel DataModel(Selection selection)
- {
- return new EmptyDataModel();
- }
- public void Setup()
- {
- _settings = new UserConfiguration<UtilityDashboardSettings>().Load();
- if (_settings.Dashboards.Count == 0) _settings.Dashboards["New Dashboard"] = CreateForm("").SaveLayout();
- foreach (var key in _settings.Dashboards.Keys)
- CreateTab(key);
- if (_settings.Selected >= -1 && _settings.Selected < DashboardsTab.Items.Count)
- DashboardsTab.SelectedIndex = _settings.Selected;
- //DashboardsTab.FullScreenMode = _settings.AutoHide ? FullScreenMode.ControlMode : FullScreenMode.None;
- }
- public Dictionary<string, object[]> Selected()
- {
- return new Dictionary<string, object[]>();
- }
- public void Heartbeat(TimeSpan time)
- {
- }
- public void Refresh()
- {
- if(CurrentDashboardName is string name)
- {
- RefreshDashboard(name);
- }
- }
- public void Shutdown(CancelEventArgs? cancel)
- {
- foreach (var (name, grid) in _dashboards)
- {
- ShutdownDashboard(name, grid);
- }
- _panels.Clear();
- }
- #endregion
- #region Favourites
- private IEnumerable<DashboardFavourite> GetFavourites()
- {
- foreach(var favourite in _settings.Favourites)
- {
- yield return favourite;
- }
- var global = new GlobalConfiguration<GlobalUtilityDashboardSettings>().Load(false).Favourites;
- foreach (var favourite in global)
- {
- yield return favourite;
- }
- }
- private void ManageFavourites_Click()
- {
- var favourites = GetFavourites().ToList();
- var grid = new DynamicItemsListGrid<DashboardFavourite>() { Items = favourites };
- grid.Reconfigure(options =>
- {
- options.AddRange(DynamicGridOption.DeleteRows, DynamicGridOption.EditRows, DynamicGridOption.MultiSelect);
- });
- grid.OnCustomiseEditor += FavouritesGrid_OnCustomiseEditor;
- DynamicGridUtils.CreateGridWindow("Manage Favourites", grid).ShowDialog();
- _settings.Favourites = favourites.Where(x => !x.IsGlobal).ToList();
- SaveSettings();
- if (Security.IsAllowed<CanSetGlobalDashboardFavourites>())
- {
- var config = new GlobalConfiguration<GlobalUtilityDashboardSettings>();
- var global = config.Load();
- global.Favourites = favourites.Where(x => x.IsGlobal).ToList();
- config.Save(global);
- }
- }
- private void FavouritesGrid_OnCustomiseEditor(IDynamicEditorForm sender, DashboardFavourite[]? items, DynamicGridColumn column, BaseEditor editor)
- {
- if(column.ColumnName == "IsGlobal")
- {
- editor.Editable = Security.IsAllowed<CanSetGlobalDashboardFavourites>() ? Editable.Enabled : Editable.Disabled;
- }
- }
- private void SaveAsFavourite_Click(string dashboardName)
- {
- _settings.Favourites.Add(new DashboardFavourite
- {
- Name = dashboardName,
- Layout = _dashboards.GetValueOrDefault(dashboardName)?.Form.SaveLayout() ?? _settings.Dashboards[dashboardName]
- });
- SaveSettings();
- }
- private void LoadFavourite_Click(DashboardFavourite favourite)
- {
- var name = CreateNewTabName(favourite.Name);
- _settings.Dashboards[name] = favourite.Layout;
- SaveSettings();
- var tab = CreateTab(name);
- DashboardsTab.SelectedItem = tab;
- }
- #endregion
- #region Tabs
- private void Tab_OnContextMenuOpening(object sender, DynamicTabItemContextMenuEventArgs args)
- {
- var name = (DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString();
- if (string.IsNullOrEmpty(name))
- return;
- DynamicFormDesignGrid grid = _dashboards[name];
- var menu = args.Menu;
- menu.AddSeparatorIfNeeded();
- var isDesigning = grid.Mode != FormMode.Preview;
- menu.Items.Add(new MenuItem()
- {
- Header = isDesigning ? "Close Design Mode" : "Design Mode",
- Command = new ActionCommand(() =>
- {
- if (grid.Mode == FormMode.Designing)
- {
- grid.Mode = FormMode.Preview;
- SaveCurrentDashboard();
- DashboardsTab.ChangedCommand.Execute(null);
- }
- else
- {
- ShutdownDashboard();
- grid.Mode = FormMode.Designing;
- }
- }),
- Icon = new Image() { Source = (isDesigning ? PRSDesktop.Resources.delete : PRSDesktop.Resources.pencil).AsBitmapImage(24, 24) }
- });
- var index = 0;
- var favourites = GetFavourites().ToList();
- if (favourites.Any())
- {
- foreach (var favourite in favourites)
- {
- menu.AddItem(favourite.Name, null, favourite, LoadFavourite_Click, index: index++);
- }
- menu.AddSeparatorIfNeeded(index: index++);
- menu.AddItem("Manage Favourites", null, ManageFavourites_Click, index: index++);
- }
- menu.AddItem("Save as Favourite", null, name, SaveAsFavourite_Click, index: index++);
- menu.AddSeparator(index: index++);
- }
- private void Tab_OnCloseTab(object sender, DynamicTabControlEventArgs args)
- {
- var name = args.TabItem.Header?.ToString();
- if (name is null)
- return;
- _dashboards.Remove(name);
- _settings.Dashboards.Remove(name);
- if (!_settings.Dashboards.Any())
- {
- var tab = new DynamicTabItem();
- InitializeNewDashboardTab(tab);
- DashboardsTab.Items.Add(tab);
- }
- else
- {
- DashboardsTab.ChangedCommand.Execute(null);
- }
- }
- private void Tab_OnTabRenamed(object sender, DynamicTabItemRenamedEventArgs args)
- {
- var oldSettings = _settings.Dashboards[args.OldName];
- _settings.Dashboards.Remove(args.OldName);
- args.NewName = CreateNewTabName(args.NewName);
- if (_dashboards.TryGetValue(args.OldName, out var dashboard))
- {
- _dashboards.Remove(args.OldName);
- _dashboards[args.NewName] = dashboard;
- _settings.Dashboards[args.NewName] = dashboard.Form.SaveLayout();
- }
- else
- {
- _settings.Dashboards[args.NewName] = oldSettings;
- }
- }
- /// <summary>
- /// Setup events on a new tab.
- /// </summary>
- /// <param name="tab"></param>
- private void InitializeTab(DynamicTabItem tab)
- {
- tab.CanClose = true;
- tab.OnCloseTab += Tab_OnCloseTab;
- tab.CanRename = true;
- tab.OnTabRenamed += Tab_OnTabRenamed;
- tab.OnContextMenuOpening += Tab_OnContextMenuOpening;
- }
- private string CreateNewTabName(string name)
- {
- var newName = name;
- int i = 1;
- while (TabNameExists(newName))
- {
- newName = $"{name} ({i})";
- ++i;
- }
- return newName;
- }
- private bool TabNameExists(string name)
- {
- return _settings.Dashboards.ContainsKey(name);
- }
- /// <summary>
- /// Creates a new tab with a given header and adds it to <see cref="DashboardsTab"/>.
- /// </summary>
- /// <param name="header"></param>
- /// <returns></returns>
- private DynamicTabItem CreateTab(string header)
- {
- var tab = new DynamicTabItem() { Header = header };
- InitializeTab(tab);
- DashboardsTab.Items.Add(tab);
- return tab;
- }
- /// <summary>
- /// Creates a new dashboard for a tab, and then initializes the tab.
- /// </summary>
- /// <param name="tab"></param>
- private void InitializeNewDashboardTab(DynamicTabItem tab)
- {
- var name = CreateNewTabName("New Dashboard");
- _settings.Dashboards[name] = CreateForm("").SaveLayout();
- DashboardsTab.ChangedCommand.Execute(null);
- SaveSettings();
- tab.Header = name;
- InitializeTab(tab);
- }
- private void DashboardsTab_OnOnCreateTab(object sender, DynamicTabControlEventArgs args)
- {
- InitializeNewDashboardTab(args.TabItem);
- }
- private void DashboardsTab_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (e.OriginalSource != DashboardsTab)
- return;
- if (e.AddedItems.Count == 0)
- return;
- ShutdownDashboard();
- if (e.AddedItems[0] is DynamicTabItem tab)
- {
- var name = (tab.Header as string)!;
- if (tab!.Content == null)
- tab.Content = CreateDashboard(name, _settings.Dashboards[name]);
- else
- {
- RefreshDashboard(name);
- }
- if (IsReady)
- {
- _settings.Selected = tab.TabIndex;
- DashboardsTab.ChangedCommand.Execute(null);
- }
- }
- }
- private void DashboardsTab_OnOnTabsChanged(object sender, EventArgs args)
- {
- SaveSettings();
- }
- #endregion
- #region Dashboard & Design
- private void SaveDashboard(string name, DynamicFormDesignGrid grid)
- {
- _settings.Dashboards[name] = grid.Form.SaveLayout();
- if (IsReady)
- SaveSettings();
- }
- private void SaveCurrentDashboard()
- {
- var name = CurrentDashboardName;
- if (name == null) return;
- var grid = CurrentDashboard;
- if (grid == null) return;
- SaveDashboard(name, grid);
- }
- private void ShutdownDashboard(string name, DynamicFormDesignGrid grid)
- {
- SaveDashboard(name, grid);
- var cancel = new CancelEventArgs();
- foreach (var panel in _panels[grid])
- {
- panel.Shutdown(cancel);
- if (cancel.Cancel)
- {
- return;
- }
- }
- _panels[grid].Clear();
- }
- private void ShutdownDashboard()
- {
- var name = CurrentDashboardName;
- if (name == null) return;
- var grid = CurrentDashboard;
- if (grid == null) return;
- ShutdownDashboard(name, grid);
- }
- private void RefreshDashboard(string name)
- {
- if (!_dashboards.ContainsKey(name))
- return;
- var grid = _dashboards[name];
- if (_panels.ContainsKey(grid))
- {
- foreach (var panel in _panels[grid])
- panel.Refresh();
- }
- }
- private FrameworkElement CreateElement<TWidget, TGroup, TProperties>(DynamicFormDesignGrid grid, DFLayoutElement<TProperties> element)
- where TWidget : FrameworkElement, IDashboardWidget<TGroup, TProperties>, new()
- where TGroup : DashboardWidgetGroup
- where TProperties : IConfigurationSettings, IDashboardProperties, new()
- {
- if (!_panels.ContainsKey(grid))
- _panels[grid] = new List<ICorePanel>();
- var dashboardName = GetDashboardElements()
- .Where(x => x.DashboardElement == element.GetType())
- .FirstOrDefault()?.WidgetCaption ?? "Unknown Dashboard";
- var container = DashboardContainer.Create<TWidget, TGroup, TProperties>(element, dashboardName);
- _panels[grid].Add(container.Panel);
- return container;
- }
- private FrameworkElement OnCreateElement(object sender, DynamicFormCreateElementArgs e)
- {
- var widgetType = GetVisibleDashboardElements().Where(x => x.DashboardElement == e.Element.GetType()).FirstOrDefault();
- if(widgetType == null)
- {
- var border = new Border
- {
- BorderBrush = new SolidColorBrush(Colors.Gray),
- BorderThickness = new Thickness(0.0),
- Margin = new Thickness(0.0),
- Background = ThemeManager.WorkspaceBackgroundBrush //new SolidColorBrush(Colors.Silver);
- };
- return border;
- }
- var method = typeof(UtilityDashboard)
- .GetMethod(nameof(CreateElement), BindingFlags.Instance | BindingFlags.NonPublic)!
- .MakeGenericMethod(widgetType.Widget, widgetType.Group, widgetType.Properties);
- return (method.Invoke(this, new object[] { sender, e.Element }) as FrameworkElement)!;
- }
-
- private static string GetCaption(Type groupType)
- {
- var caption = groupType.GetCustomAttribute<Caption>();
- if(caption != null)
- {
- return caption.Text;
- }
- return CoreUtils.Neatify(groupType.Name);
- }
- private static List<WidgetDashboardElement> GetDashboardElements()
- {
- if (_dashboardElements == null)
- {
- _dashboardElements = new();
- var types = CoreUtils.TypeList(
- new [] { Assembly.GetExecutingAssembly() },
- x => x.IsClass
- && !x.IsAbstract
- && !x.IsGenericType
- && x.GetInterfaces().Contains(typeof(IDashboardElement)));
- foreach (var type in types)
- {
- var dashboardElementDef = type.GetSuperclassDefinition(typeof(DashboardElement<,,>));
- if (dashboardElementDef != null)
- {
- var dashboard = dashboardElementDef.GenericTypeArguments[0];
- var group = dashboardElementDef.GenericTypeArguments[1];
- var properties = dashboardElementDef.GenericTypeArguments[2];
- var requires = dashboard.GetInterfaces(typeof(IRequiresSecurity<>)).Select(x => x.GenericTypeArguments[0]);
- _dashboardElements.Add(new(type, dashboard, group, properties, requires.ToArray()));
- }
- }
- }
- return _dashboardElements;
- }
- private static IEnumerable<WidgetDashboardElement> GetVisibleDashboardElements()
- {
- return GetDashboardElements().Where(x =>
- {
- foreach (var require in x.SecurityTokens)
- {
- if (!Security.IsAllowed(require))
- return false;
- }
- return true;
- });
- }
- private Border CreateDashboard(string name, string layout)
- {
- var form = CreateForm(layout);
- var grid = new DynamicFormDesignGrid();
- foreach(var widget in GetVisibleDashboardElements())
- {
- grid.AddElement(widget.DashboardElement, widget.WidgetCaption, widget.GroupCaption, true);
- }
- grid.ShowBorders = false;
- grid.OnCreateElement += OnCreateElement;
- grid.OnAfterDesign += OnAfterDesign;
- grid.OnAfterRender += OnAfterRender;
- grid.Mode = FormMode.Preview;
- var border = new Border
- {
- BorderBrush = new SolidColorBrush(Colors.Silver),
- BorderThickness = new Thickness(0.75),
- Child = grid // scroll;
- };
- _dashboards[name] = grid;
- _panels[grid] = new List<ICorePanel>();
- grid.Form = form;
- grid.Initialize();
- return border;
- }
- private void OnAfterRender(DynamicFormDesignGrid sender)
- {
- if (!sender.IsDesigning)
- {
- if (_panels.TryGetValue(sender, out var panels))
- {
- foreach (var panel in panels)
- panel.Refresh();
- }
- }
- }
- private static DFLayout CreateForm(string layout)
- {
- var form = new DFLayout();
- if (string.IsNullOrWhiteSpace(layout))
- {
- form.ColumnWidths.Add("*");
- form.ColumnWidths.Add("*");
- form.ColumnWidths.Add("*");
- form.RowHeights.Add("*");
- form.RowHeights.Add("*");
- form.RowHeights.Add("*");
- }
- else
- {
- form.LoadLayout(layout);
- }
- return form;
- }
-
- private void OnAfterDesign(object sender)
- {
- SaveCurrentDashboard();
- if(CurrentDashboardName is string name) // Null-check
- {
- RefreshDashboard(name);
- }
- }
- #endregion
- }
- }
|