using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Microsoft.Win32; using Syncfusion.UI.Xaml.Diagram; namespace PRSDesktop { /// /// Interaction logic for OrganizationalChart.xaml /// public partial class OrgChartPanel : UserControl, IPanel { private OrgChartSettings _settings; private readonly OrgChartDataModel model = new(); public OrgChartPanel() { InitializeComponent(); if (Security.IsAllowed()) Layout.Items.Add("Employees"); if (Security.IsAllowed()) Layout.Items.Add("Positions"); if (Security.IsAllowed()) Layout.Items.Add("Job Roles"); Layout.Visibility = Layout.Items.Count > 1 ? Visibility.Visible : Visibility.Collapsed; LayoutLabel.Visibility = Layout.Visibility; } public event DataModelUpdateEvent OnUpdateDataModel; public bool IsReady { get; set; } private void SaveSettings() { //_settings.Zoom = Zoom.Value; _settings.Appearance = (OrgChartAppearance)Appearance.SelectedIndex; _settings.Layout = Equals(Layout.SelectedValue, "Employees") ? OrgChartLayout.Employee : Equals(Layout.SelectedValue, "Positions") ? OrgChartLayout.Position : OrgChartLayout.Role; Task.Run( () => { new UserConfiguration().Save(_settings); } ); } #region IPanel Support public void CreateToolbarButtons(IPanelHost host) { } public Dictionary Selected() { return new Dictionary(); } public void Heartbeat(TimeSpan time) { } public void Setup() { _settings = new UserConfiguration().Load(); Appearance.SelectedIndex = (int)_settings.Appearance; model.Appearance = _settings.Appearance; var layout = _settings.Layout == OrgChartLayout.Employee ? "Employees" : _settings.Layout == OrgChartLayout.Position ? "Positions" : "Job Roles"; Layout.SelectedValue = Layout.Items.Contains(layout) ? layout : Layout.Items[0]; model.Layout = _settings.Layout; //Zoom.Value = _settings.Zoom; diagram.DataContext = model; (diagram.Info as IGraphInfo).ItemAdded += ApplyItemTemplate; model.Active = true; } public void Shutdown() { } public string SectionName => "Organisational Chart"; public DataModel DataModel(Selection selection) { return new BaseDataModel(null); } public void Refresh() { model.Refresh(); var graphinfo = diagram.Info as IGraphInfo; graphinfo.Commands.FitToPage.Execute(null); } private void ApplyItemTemplate(object sender, ItemAddedEventArgs args) { var node = args.Item as NodeViewModel; if (node == null) return; node.ContentTemplate = TemplateGenerator.CreateDataTemplate(() => { var image = new Border { BorderBrush = new SolidColorBrush(Colors.Gray), BorderThickness = new Thickness(0.75), CornerRadius = new CornerRadius(25.0), Width = 50, Height = 50, Margin = new Thickness(0, 0, 5, 0) }; image.SetBinding(TagProperty, new Binding("ID")); image.SetBinding(Border.BackgroundProperty, new Binding("Image")); image.SetBinding(VisibilityProperty, new Binding("ImageVisible")); image.SetValue(Grid.ColumnProperty, 0); image.SetValue(Grid.RowProperty, 0); image.SetValue(Grid.RowSpanProperty, 2); image.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center); var position = new Label(); position.FontWeight = FontWeights.DemiBold; position.HorizontalContentAlignment = HorizontalAlignment.Center; //description.Background = new SolidColorBrush(Colors.Blue); position.VerticalContentAlignment = VerticalAlignment.Top; position.SetBinding(TagProperty, new Binding("ID")); position.SetBinding(ContentProperty, "Position"); position.SetValue(Grid.ColumnProperty, 1); position.SetValue(Grid.RowProperty, 0); var name = new Label(); //name.Background = new SolidColorBrush(Colors.Green); name.HorizontalContentAlignment = HorizontalAlignment.Center; name.VerticalContentAlignment = VerticalAlignment.Center; name.SetBinding(TagProperty, new Binding("ID")); name.SetBinding(ContentProperty, "Name"); name.Background = new SolidColorBrush(Colors.Transparent); var nameborder = new Border { BorderBrush = new SolidColorBrush(Colors.Transparent), BorderThickness = new Thickness(0.75), CornerRadius = new CornerRadius(5.0), Padding = new Thickness(0) }; nameborder.SetValue(Grid.ColumnProperty, 1); nameborder.SetValue(Grid.RowProperty, 1); nameborder.SetBinding(TagProperty, new Binding("ID")); nameborder.SetBinding(Border.BackgroundProperty, "WarningColor"); nameborder.Child = name; var layout = new Grid(); layout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(25, GridUnitType.Pixel) }); layout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) }); layout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); layout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); layout.Children.Add(image); layout.Children.Add(position); layout.Children.Add(nameborder); var border = new Border { MinWidth = 150, BorderBrush = new SolidColorBrush(Colors.Gray), BorderThickness = new Thickness(0.75), CornerRadius = new CornerRadius(5.0), Padding = new Thickness(5), Child = layout }; border.MouseDown += Border_MouseDown; border.SetBinding(TagProperty, "ID"); border.SetBinding(Border.BackgroundProperty, "Color"); return border; }); } #endregion #region Menu Actions private void AddExistingItemClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as System.Tuple; entry.Item2.ParentID = entry.Item1.ID; entry.Item2.Visible = true; UpdateItems(new[] { entry.Item2 }); } private void CreateNewItemClick(object sender, RoutedEventArgs e) { var menu = sender as MenuItem; var parent = menu.Tag as OrgChartEntry; var entry = new OrgChartEntry { ParentID = parent != null ? parent.ID : Guid.Empty }; EditItem(entry); } private void EditItemClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as OrgChartEntry; EditItem(entry); } private void RemoveItemClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as OrgChartEntry; var updates = model.Data.Where(x => x.ParentID == entry.ID).ToList(); foreach (var child in updates) child.ParentID = entry.ParentID; entry.ParentID = Guid.Empty; entry.Visible = false; updates.Add(entry); UpdateItems(updates); } private void ChanegColorClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as OrgChartEntry; var color = ImageUtils.StringToColor(entry.Color); if (ColorEdit.Execute("Change Color", ref color)) { entry.Color = ImageUtils.ColorToString(color); UpdateItems(new[] { entry }); } } private void StartNewTreeClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as OrgChartEntry; entry.ParentID = Guid.Empty; UpdateItems(new[] { entry }); } private void MoveToClick(object sender, RoutedEventArgs e) { var entry = (sender as MenuItem).Tag as System.Tuple; entry.Item1.ParentID = entry.Item2.ID; UpdateItems(new[] { entry.Item1 }); } private void EditItem(OrgChartEntry entry) { if (_settings.Layout == OrgChartLayout.Employee) { var employee = entry.ID == Guid.Empty ? new Employee() : new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault(); if (employee != null) { if (employee.ID == Guid.Empty) employee.OrgChart.ReportsTo.ID = entry.ID; var bOK = new EmployeeGrid().EditItems(new[] { employee }); if (bOK) model.Refresh(); } else { MessageBox.Show("Unable to Locate Employee!"); } } else if (_settings.Layout == OrgChartLayout.Position) { var position = entry.ID == Guid.Empty ? new EmployeePosition() : new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault(); if (position != null) { if (position.ID == Guid.Empty) position.OrgChart.ReportsTo.ID = entry.ID; var bOK = new DynamicDataGrid().EditItems(new[] { position }); if (bOK) model.Refresh(); } else { MessageBox.Show("Unable to Locate Position!"); } } else if (_settings.Layout == OrgChartLayout.Role) { var role = entry.ID == Guid.Empty ? new Role() : new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault(); if (role != null) { if (role.ID == Guid.Empty) role.OrgChart.ReportsTo.ID = entry.ID; var bOK = new DynamicDataGrid().EditItems(new[] { role }); if (bOK) model.Refresh(); } else { MessageBox.Show("Unable to Locate Role!"); } } } private void UpdateItems(IEnumerable entries) { if (_settings.Layout == OrgChartLayout.Employee) { var updates = new List(); foreach (var entry in entries) { var update = new Employee(); update.ID = entry.ID; update.OrgChart.ReportsTo.ID = entry.ParentID; update.OrgChart.Color = entry.Color; update.OrgChart.Visible = entry.Visible; updates.Add(update); } using (new WaitCursor()) { new Client().Save(updates, "Updated from Org Chart"); //model.Refresh(); } } else if (_settings.Layout == OrgChartLayout.Position) { var updates = new List(); foreach (var entry in entries) { var update = new EmployeePosition(); update.ID = entry.ID; update.OrgChart.ReportsTo.ID = entry.ParentID; update.OrgChart.Color = entry.Color; update.OrgChart.Visible = entry.Visible; updates.Add(update); } using (new WaitCursor()) { new Client().Save(updates, "Updated from Org Chart"); //model.Refresh(); } } else if (_settings.Layout == OrgChartLayout.Role) { var updates = new List(); foreach (var entry in entries) { var update = new Role(); update.ID = entry.ID; update.OrgChart.ReportsTo.ID = entry.ParentID; update.OrgChart.Color = entry.Color; update.OrgChart.Visible = entry.Visible; updates.Add(update); } using (new WaitCursor()) { new Client().Save(updates, "Updated from Org Chart"); //model.Refresh(); } } diagram.Visibility = Visibility.Collapsed; model.Refresh(); diagram.Visibility = Visibility.Visible; } #endregion #region Menu Setup private void LoadNewItemsMenu(ItemsControl menu) { menu.Items.Clear(); var parent = menu.Tag as OrgChartEntry; foreach (var entry in model.Data.Where(x => x.Visible == false)) { var item = new MenuItem { Header = _settings.Layout == OrgChartLayout.Employee ? entry.Name : entry.Position }; item.Click += AddExistingItemClick; item.Tag = new System.Tuple(parent, entry); menu.Items.Add(item); } } private void LoadMoveToOptions(OrgChartEntry current, MenuItem moveto) { foreach (var entry in model.Data.OrderBy(x => x.Name)) if (!model.Data.IsChildOf(entry, current)) { var item = new MenuItem { Header = _settings.Layout == OrgChartLayout.Employee ? entry.Name : entry.Position }; item.Tag = new System.Tuple(current, entry); item.Click += MoveToClick; moveto.Items.Add(item); } if (moveto.Items.Count > 0 && current.ParentID != Guid.Empty) moveto.Items.Add(new Separator()); if (current.ParentID != Guid.Empty) { var noone = new MenuItem { Header = "Start New Tree" }; noone.Click += StartNewTreeClick; noone.Tag = current; moveto.Items.Add(noone); } } private void Diagram_MouseDown(object sender, MouseButtonEventArgs e) { if (e.RightButton == MouseButtonState.Pressed && Security.IsAllowed()) { var menu = new ContextMenu(); var additem = new MenuItem { Header = "Add Existing" }; LoadNewItemsMenu(additem); additem.IsEnabled = additem.Items.Count > 0; menu.Items.Add(additem); menu.Items.Add(new Separator()); var createitem = new MenuItem { Header = "Create New" }; createitem.Click += CreateNewItemClick; menu.Items.Add(createitem); menu.IsOpen = true; } } private void Border_MouseDown(object sender, MouseButtonEventArgs e) { if (e.RightButton == MouseButtonState.Pressed && Security.IsAllowed()) { var id = (Guid)(sender as Border).Tag; var current = model.Data.FirstOrDefault(x => x.ID == id); if (current == null) return; e.Handled = true; if (e.ClickCount == 2) { EditItem(current); } else { var menu = new ContextMenu(); var moveto = new MenuItem { Header = "Move To.." }; menu.Items.Add(moveto); LoadMoveToOptions(current, moveto); var changecolor = new MenuItem { Header = "Change Color" }; changecolor.Click += ChanegColorClick; changecolor.Tag = current; menu.Items.Add(changecolor); var edititem = new MenuItem { Header = "Edit Properties" }; edititem.Click += EditItemClick; edititem.Tag = current; menu.Items.Add(edititem); menu.Items.Add(new Separator()); var additem = new MenuItem { Header = "Add Existing" }; menu.Items.Add(additem); LoadNewItemsMenu(additem); additem.IsEnabled = additem.Items.Count > 0; var newitem = new MenuItem { Header = "Create New" }; newitem.Click += CreateNewItemClick; menu.Items.Add(newitem); menu.Items.Add(new Separator()); var removeitem = new MenuItem { Header = "Remove" }; removeitem.Click += RemoveItemClick; removeitem.Tag = current; menu.Items.Add(removeitem); menu.IsOpen = true; } } } #endregion #region Toolbar Actions private void Zoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (diagram == null) return; //if (model.Active) // SaveSettings(); var graphinfo = diagram.Info as IGraphInfo; graphinfo.Commands.Zoom.Execute(new ZoomPositionParameter { ZoomCommand = ZoomCommand.Zoom, ZoomTo = e.NewValue / 100 }); } private void PrintButton_Click(object sender, RoutedEventArgs e) { if (diagram == null) return; diagram.PrintingService.ShowDialog = true; diagram.PrintingService.Print(); } private void ExportButton_Click(object sender, RoutedEventArgs e) { if (diagram == null) return; var dlg = new SaveFileDialog(); dlg.Filter = "PNG Files (*.png)|*.png|PDF Files (*.pdf)|*.pdf"; dlg.FilterIndex = 0; dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); dlg.FileName = Path.Combine(dlg.InitialDirectory, "Organizational Chart.png"); if (dlg.ShowDialog() == true) { var tempfile = Path.GetTempFileName(); var finalfile = Path.ChangeExtension(dlg.FileName, dlg.FilterIndex > 1 ? "pdf" : "png"); diagram.ExportSettings = new ExportSettings { IsSaveToXps = dlg.FilterIndex > 1, FileName = dlg.FilterIndex > 1 ? tempfile : finalfile, ExportMode = ExportMode.Content }; diagram.Export(); if (dlg.FilterIndex > 1) { MessageBox.Show("PDF Functions broken .in .NET6"); return; // XPSToPdfConverter converter = new XPSToPdfConverter(); // PdfDocument pdfDocument = converter.Convert(tempfile); // pdfDocument.Save(finalfile); // pdfDocument.Close(true); // System.IO.File.Delete(tempfile); } Process.Start(finalfile); } } private void Appearance_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (model.Active) SaveSettings(); model.Appearance = (OrgChartAppearance)Appearance.SelectedIndex; } private void Layout_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (model.Active) SaveSettings(); model.Layout = _settings != null ? _settings.Layout : OrgChartLayout.Employee; } #endregion } }