Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramApp/ViewModels/DiagramsViewModel.cs
2023-01-24 16:20:39 +08:00

679 lines
26 KiB
C#

using AIStudio.Wpf.DiagramHelper.Commands;
using AIStudio.Wpf.Flowchart;
using AIStudio.Wpf.DiagramHelper.Extensions.ViewModels;
using AIStudio.Wpf.DiagramHelper.Helpers;
using AIStudio.Wpf.DiagramApp.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using AIStudio.Wpf.DiagramDesigner;
using ZXing;
using AIStudio.Wpf.DiagramDesigner.Helpers;
namespace AIStudio.Wpf.DiagramApp.ViewModels
{
public partial class DiagramsViewModel : BindableBase
{
protected IDiagramServiceProvider _service { get { return DiagramServicesProvider.Instance.Provider; } }
public DiagramsViewModel(string title, string status, DiagramType diagramType)
{
Title = title;
Status = status;
DiagramType = diagramType;
DiagramViewModels = new ObservableCollection<IDiagramViewModel>()
{
new DiagramViewModel(){Name= "页-1", DiagramType = diagramType},
};
DiagramViewModel = DiagramViewModels.FirstOrDefault();
Init();
}
public DiagramsViewModel(string filename)
{
FileName = filename;
var diagramDocument = OpenFile(filename);
OpenFile(diagramDocument);
}
public DiagramsViewModel(string filename, DiagramDocument diagramDocument)
{
FileName = filename;
OpenFile(diagramDocument);
}
protected virtual void InitDiagramViewModel()
{
}
protected virtual void Init()
{
InitDiagramViewModel();
}
public string FileName { get; set; }
#region
private string _title;
public string Title
{
get
{
return _title;
}
set
{
SetProperty(ref _title, value);
}
}
private string _status;
public string Status
{
get
{
return _status;
}
set
{
SetProperty(ref _status, value);
}
}
private bool _showGrid;
public bool ShowGrid
{
get
{
return _showGrid;
}
set
{
if (SetProperty(ref _showGrid, value))
{
foreach (var item in DiagramViewModels)
{
item.ShowGrid = _showGrid;
}
}
}
}
public DiagramType DiagramType { get; set; }
private double OffsetX = 10;
private double OffsetY = 10;
private ObservableCollection<IDiagramViewModel> _diagramViewModels;
public ObservableCollection<IDiagramViewModel> DiagramViewModels
{
get
{
return _diagramViewModels;
}
set
{
SetProperty(ref _diagramViewModels, value);
}
}
private IDiagramViewModel _diagramViewModel;
public IDiagramViewModel DiagramViewModel
{
get
{
return _diagramViewModel;
}
set
{
if (_diagramViewModel != value)
{
if (_diagramViewModel != null)
{
_diagramViewModel.PropertyChanged -= DiagramViewModel_PropertyChanged;
_diagramViewModel.OutAddVerify -= AddVerify;
}
SetProperty(ref _diagramViewModel, value);
if (_diagramViewModel != null)
{
_diagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
_diagramViewModel.OutAddVerify += AddVerify;
}
}
}
}
#endregion
#region
private void DiagramViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsSelected")
{
_service.SelectedItem = DiagramViewModel.SelectedItems?.FirstOrDefault();
}
var property = sender.GetType().GetProperty(e.PropertyName);
var attr = property.GetCustomAttributes(typeof(BrowsableAttribute), true);
if (attr != null && attr.Length != 0 && (attr[0] as BrowsableAttribute).Browsable == false)
{
return;
}
Status = "*";
}
#endregion
protected virtual bool AddVerify(SelectableDesignerItemViewModelBase arg)
{
return true;
}
public static DiagramDocument OpenFile(string filename)
{
try
{
DiagramDocument diagramDocument = null;
if (filename.ToLower().EndsWith(".xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(DiagramDocument));
FileInfo fileInfo = new FileInfo(filename);
using (TextReader reader = fileInfo.OpenText())
{
diagramDocument = (DiagramDocument)serializer.Deserialize(reader);
}
}
else
{
diagramDocument = JsonConvert.DeserializeObject<DiagramDocument>(File.ReadAllText(filename));
}
return diagramDocument;
}
catch (System.IO.FileNotFoundException fnfe)
{
throw new FileNotFoundException("The system document could not be found ", fnfe);
}
catch (System.IO.DirectoryNotFoundException dnfe)
{
throw new DirectoryNotFoundException("A required directory was nt found", dnfe);
}
catch (System.IO.IOException ioe)
{
throw new IOException("A file system error occurred", ioe);
}
catch (System.UnauthorizedAccessException uae)
{
throw new UnauthorizedAccessException("The requested file system access wasnot granted", uae);
}
catch (System.Security.SecurityException se)
{
throw new System.Security.SecurityException("The security policy prevents access to a file system resource", se);
}
catch (System.Exception e)
{
throw new System.Exception(
string.Format("The database format vc invalid \r\n Exception:{0} \r\n InnerException:{1}", e.Message, e.InnerException.Message));
}
}
protected virtual void OpenFile(DiagramDocument diagramDocument)
{
Title = diagramDocument.Title;
DiagramType = diagramDocument.DiagramType;
List<DiagramViewModel> viewModels = new List<DiagramViewModel>();
foreach (var diagramItem in diagramDocument.DiagramItems)
{
var viewModel = new DiagramViewModel();
viewModel.Name = diagramItem.Name;
viewModel.DiagramType = diagramItem.DiagramType;
viewModel.ShowGrid = diagramItem.ShowGrid;
viewModel.GridCellSize = diagramItem.GridCellSize;
viewModel.CellHorizontalAlignment = diagramItem.CellHorizontalAlignment;
viewModel.CellVerticalAlignment = diagramItem.CellVerticalAlignment;
viewModel.PageSizeOrientation = diagramItem.PageSizeOrientation;
viewModel.PageSize = diagramItem.PageSize;
viewModel.PageSizeType = diagramItem.PageSizeType;
viewModel.GridMargin = diagramItem.GridMargin;
viewModel.GridColor = diagramItem.GridColor;
foreach (DesignerItemBase diagramItemData in diagramItem.AllDesignerItems)
{
Type type = TypeHelper.GetType(diagramItemData.ItemTypeName);
DesignerItemViewModelBase itemBase = (DesignerItemViewModelBase)Activator.CreateInstance(type, viewModel, diagramItemData);
viewModel.Items.Add(itemBase);
}
foreach (var connection in diagramItem.Connections)
{
connection.SourceType = System.Type.GetType(connection.SourceTypeName);
connection.SinkType = System.Type.GetType(connection.SinkTypeName);
DesignerItemViewModelBase sourceItem = GetConnectorDataItem(viewModel, connection.SourceId, connection.SourceType);
ConnectorOrientation sourceConnectorOrientation = connection.SourceOrientation;
FullyCreatedConnectorInfo sourceConnectorInfo = GetFullConnectorInfo(connection.Id, sourceItem, sourceConnectorOrientation, connection.SourceXRatio, connection.SourceYRatio, connection.SourceInnerPoint);
DesignerItemViewModelBase sinkItem = GetConnectorDataItem(viewModel, connection.SinkId, connection.SinkType);
ConnectorOrientation sinkConnectorOrientation = connection.SinkOrientation;
FullyCreatedConnectorInfo sinkConnectorInfo = GetFullConnectorInfo(connection.Id, sinkItem, sinkConnectorOrientation, connection.SinkXRatio, connection.SinkYRatio, connection.SinkInnerPoint);
ConnectorViewModel connectionVM = new ConnectorViewModel(viewModel, sourceConnectorInfo, sinkConnectorInfo, connection);
viewModel.Items.Add(connectionVM);
}
viewModels.Add(viewModel);
}
DiagramViewModels = new ObservableCollection<IDiagramViewModel>(viewModels);
DiagramViewModel = DiagramViewModels.FirstOrDefault();
}
public bool SaveFile(bool isSaveAs = false)
{
string filter = "Files (*.xml)|*.xml|Files (*.json)|*.json|All Files (*.*)|*.*";
if (string.IsNullOrEmpty(FileName) || isSaveAs == true)
{
Microsoft.Win32.SaveFileDialog saveFile = new Microsoft.Win32.SaveFileDialog();
saveFile.Filter = filter;
if (saveFile.ShowDialog() == true)
{
FileName = saveFile.FileName;
Title = Path.GetFileNameWithoutExtension(FileName);
}
else
{
return false;
}
}
var para = Path.GetExtension(FileName);
DiagramDocument diagramDocument = new DiagramDocument();
diagramDocument.DiagramItems = new List<DiagramItem>();
diagramDocument.Title = Title;
diagramDocument.DiagramType = DiagramType;
foreach (var viewModel in DiagramViewModels)
{
DiagramItem diagramItem = new DiagramItem();
diagramItem.Name = viewModel.Name;
diagramItem.DiagramType = viewModel.DiagramType;
diagramItem.ShowGrid = viewModel.ShowGrid;
diagramItem.GridCellSize = viewModel.GridCellSize;
diagramItem.CellHorizontalAlignment = viewModel.CellHorizontalAlignment;
diagramItem.CellVerticalAlignment = viewModel.CellVerticalAlignment;
diagramItem.PageSizeOrientation = viewModel.PageSizeOrientation;
diagramItem.PageSize = viewModel.PageSize;
diagramItem.PageSizeType = viewModel.PageSizeType;
diagramItem.GridMargin = viewModel.GridMargin;
diagramItem.GridColor = viewModel.GridColor;
diagramItem.AddItems(DiagramViewModel.Items);
foreach (var connectionVM in DiagramViewModel.Items.OfType<ConnectorViewModel>())
{
if (!connectionVM.IsFullConnection)
continue;
ConnectionItem connection = new ConnectionItem(connectionVM);
diagramItem.ConnectionIds.Add(connectionVM.Id);
diagramItem.Connections.Add(connection);
}
diagramDocument.DiagramItems.Add(diagramItem);
}
if (para == ".xml")
{
FileInfo file = new FileInfo(FileName);
diagramDocument.Save(file);
}
else
{
File.WriteAllText(FileName, JsonConvert.SerializeObject(diagramDocument));
}
Status = "";
return true;
}
private DesignerItemViewModelBase GetConnectorDataItem(IDiagramViewModel diagramViewModel, Guid conectorDataItemId, Type connectorDataItemType)
{
DesignerItemViewModelBase dataItem = diagramViewModel.Items.OfType<DesignerItemViewModelBase>().Single(x => x.Id == conectorDataItemId);
return dataItem;
}
private FullyCreatedConnectorInfo GetFullConnectorInfo(Guid connectorId, DesignerItemViewModelBase dataItem, ConnectorOrientation connectorOrientation, double xRatio, double yRatio, bool isInnerPoint)
{
if (isInnerPoint)
{
return dataItem.Connectors.Where(p => p.XRatio == xRatio && p.YRatio == yRatio).FirstOrDefault();
}
else
{
switch (connectorOrientation)
{
case ConnectorOrientation.Top:
return dataItem.TopConnector;
case ConnectorOrientation.Left:
return dataItem.LeftConnector;
case ConnectorOrientation.Right:
return dataItem.RightConnector;
case ConnectorOrientation.Bottom:
return dataItem.BottomConnector;
default:
throw new InvalidOperationException(
string.Format("Found invalid persisted Connector Orientation for Connector Id: {0}", connectorId));
}
}
}
private ConnectorViewModel GetSourceItem(FullyCreatedConnectorInfo sinkConnector)
{
foreach (var connector in DiagramViewModel.Items.OfType<ConnectorViewModel>())
{
if (connector.SinkConnectorInfo == sinkConnector)
{
return connector;
}
}
return null;
}
private bool ItemsToDeleteHasConnector(List<SelectableDesignerItemViewModelBase> itemsToRemove, ConnectorInfoBase connector)
{
if (connector is FullyCreatedConnectorInfo fully)
{
return itemsToRemove.Contains(fully.DataItem);
}
return false;
}
#region
public void SetPropertyValue(SelectableDesignerItemViewModelBase selectable, string propertyName)
{
foreach (var item in DiagramViewModel.SelectedItems)
{
if (item != selectable)
{
CopyHelper.CopyPropertyValue(selectable, item, propertyName);
}
}
}
public void SetFont(IFontViewModel fontViewModel, string propertyName)
{
foreach (var item in DiagramViewModel.SelectedItems)
{
if (item.FontViewModel != fontViewModel)
{
CopyHelper.CopyPropertyValue(fontViewModel, item.FontViewModel, propertyName);
}
}
}
public void SetColor(IColorViewModel colorViewModel, string propertyName)
{
foreach (var item in DiagramViewModel.SelectedItems)
{
if (item.ColorViewModel != colorViewModel)
{
CopyHelper.CopyPropertyValue(colorViewModel, item.ColorViewModel, propertyName);
}
}
}
public void SetQuickItem(IQuickThemeViewModel quickThemeViewModel, string propertyName)
{
if (propertyName == nameof(QuickTheme) && quickThemeViewModel.QuickTheme != null)
{
foreach (var item in DiagramViewModel.SelectedItems)
{
SetFont(quickThemeViewModel.QuickTheme.FontViewModel, "FontColor");
SetColor(quickThemeViewModel.QuickTheme.ColorViewModel, "FillColor");
SetColor(quickThemeViewModel.QuickTheme.ColorViewModel, "LineColor");
SetColor(quickThemeViewModel.QuickTheme.ColorViewModel, "LineWidth");
}
quickThemeViewModel.QuickTheme = null;
}
}
public void LockAction(LockObject lockObject, string propertyName)
{
foreach (var item in DiagramViewModel.SelectedItems)
{
item.LockObjectViewModel.SetValue(lockObject);
}
}
public virtual void AddPageExecuted(object para)
{
int index = 0;
if (para is DiagramViewModel oldpage)
{
index = DiagramViewModels.IndexOf(oldpage) + 1;
}
else
{
index = DiagramViewModels.Count;
}
var page = new DiagramViewModel() { Name = NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-"), DiagramType = DiagramType };
DiagramViewModels.Insert(index, page);
DiagramViewModel = page;
InitDiagramViewModel();
}
public void AddCopyPageExecuted(object para)
{
if (DiagramViewModel != null)
{
var viewModel = DiagramViewModel;
DiagramItem diagramItem = new DiagramItem();
diagramItem.Name = viewModel.Name;
diagramItem.DiagramType = viewModel.DiagramType;
diagramItem.ShowGrid = viewModel.ShowGrid;
diagramItem.GridCellSize = viewModel.GridCellSize;
diagramItem.CellHorizontalAlignment = viewModel.CellHorizontalAlignment;
diagramItem.CellVerticalAlignment = viewModel.CellVerticalAlignment;
diagramItem.PageSizeOrientation = viewModel.PageSizeOrientation;
diagramItem.PageSize = viewModel.PageSize;
diagramItem.PageSizeType = viewModel.PageSizeType;
diagramItem.GridMargin = viewModel.GridMargin;
diagramItem.GridColor = viewModel.GridColor;
diagramItem.AddItems(DiagramViewModel.Items);
foreach (var connectionVM in DiagramViewModel.Items.OfType<ConnectorViewModel>())
{
if (connectionVM.IsFullConnection == false) continue;
FullyCreatedConnectorInfo sinkConnector = connectionVM.SinkConnectorInfoFully;
ConnectionItem connection = new ConnectionItem(connectionVM);
diagramItem.ConnectionIds.Add(connectionVM.Id);
diagramItem.Connections.Add(connection);
}
viewModel = new DiagramViewModel();
viewModel.Name = NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-");
viewModel.DiagramType = diagramItem.DiagramType;
viewModel.ShowGrid = diagramItem.ShowGrid;
viewModel.GridCellSize = diagramItem.GridCellSize;
viewModel.CellHorizontalAlignment = diagramItem.CellHorizontalAlignment;
viewModel.CellVerticalAlignment = diagramItem.CellVerticalAlignment;
viewModel.PageSizeOrientation = diagramItem.PageSizeOrientation;
viewModel.PageSize = diagramItem.PageSize;
viewModel.PageSizeType = diagramItem.PageSizeType;
viewModel.GridMargin = diagramItem.GridMargin;
viewModel.GridColor = diagramItem.GridColor;
foreach (DesignerItemBase diagramItemData in diagramItem.AllDesignerItems)
{
Type type = TypeHelper.GetType(diagramItemData.ItemTypeName);
DesignerItemViewModelBase itemBase = (DesignerItemViewModelBase)Activator.CreateInstance(type, viewModel, diagramItemData);
viewModel.Items.Add(itemBase);
}
foreach (var connection in diagramItem.Connections)
{
connection.SourceType = System.Type.GetType(connection.SourceTypeName);
connection.SinkType = System.Type.GetType(connection.SinkTypeName);
DesignerItemViewModelBase sourceItem = GetConnectorDataItem(viewModel, connection.SourceId, connection.SourceType);
ConnectorOrientation sourceConnectorOrientation = connection.SourceOrientation;
FullyCreatedConnectorInfo sourceConnectorInfo = GetFullConnectorInfo(connection.Id, sourceItem, sourceConnectorOrientation, connection.SourceXRatio, connection.SourceYRatio, connection.SourceInnerPoint);
DesignerItemViewModelBase sinkItem = GetConnectorDataItem(viewModel, connection.SinkId, connection.SinkType);
ConnectorOrientation sinkConnectorOrientation = connection.SinkOrientation;
FullyCreatedConnectorInfo sinkConnectorInfo = GetFullConnectorInfo(connection.Id, sinkItem, sinkConnectorOrientation, connection.SinkXRatio, connection.SinkYRatio, connection.SinkInnerPoint);
ConnectorViewModel connectionVM = new ConnectorViewModel(viewModel, sourceConnectorInfo, sinkConnectorInfo, connection);
viewModel.Items.Add(connectionVM);
}
DiagramViewModels.Add(viewModel);
DiagramViewModel = viewModel;
InitDiagramViewModel();
}
}
public void DeletePageExecuted(object para)
{
if (para is DiagramViewModel oldpage)
{
int index = DiagramViewModels.IndexOf(oldpage) - 1;
DiagramViewModels.Remove(oldpage);
if (index > 0)
{
DiagramViewModel = DiagramViewModels[index];
}
else
{
DiagramViewModel = DiagramViewModels.FirstOrDefault();
}
}
}
public void RenamePageExecuted(object para)
{
if (para is DiagramViewModel oldpage)
{
oldpage.IsEditName = true;
}
}
public void EndRenamePageExecuted(object para)
{
if (para is DiagramViewModel oldpage)
{
oldpage.IsEditName = false;
}
}
public void AddImageExecuted(object para)
{
ImageItemViewModel itemBase = new ImageItemViewModel();
DiagramViewModel.DirectAddItemCommand.Execute(itemBase);
if (itemBase.Root != null)
{
_service.DrawModeViewModel.CursorMode = CursorMode.Move;
}
}
public void EditImageExecuted(object para)
{
ImageItemViewModel itemBase = para as ImageItemViewModel;
if (itemBase != null)
{
itemBase.EditData();
}
}
public void ResizeImageExecuted(object para)
{
ImageItemViewModel itemBase = para as ImageItemViewModel;
if (itemBase != null)
{
itemBase.StartResize();
}
}
public void ResetImageExecuted(object para)
{
ImageItemViewModel itemBase = para as ImageItemViewModel;
if (itemBase != null)
{
itemBase.Reset();
}
}
public void AddVideoExecuted(object para)
{
VideoItemViewModel itemBase = new VideoItemViewModel();
DiagramViewModel.DirectAddItemCommand.Execute(itemBase);
if (itemBase.Root != null)
{
_service.DrawModeViewModel.CursorMode = CursorMode.Move;
}
}
public void AddOutLineTextExecuted(object para)
{
OutLineTextDesignerItemViewModel itemBase = new OutLineTextDesignerItemViewModel();
DiagramViewModel.DirectAddItemCommand.Execute(itemBase);
if (itemBase.Root != null)
{
_service.DrawModeViewModel.CursorMode = CursorMode.Move;
}
}
public void AddBarcodeExecuted(object para)
{
BarcodeDesignerItemViewModel itemBase = new BarcodeDesignerItemViewModel() { Format = (BarcodeFormat)Enum.Parse(typeof(BarcodeFormat), para.ToString()), Text="AIStudio.Wpf.DiagramApp" };
DiagramViewModel.DirectAddItemCommand.Execute(itemBase);
if (itemBase.Root != null)
{
_service.DrawModeViewModel.CursorMode = CursorMode.Move;
}
}
#endregion
private Size MeasureString(OutLineTextDesignerItemViewModel itemBase)
{
var formattedText = new FormattedText(
itemBase.Text,
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface(new FontFamily(itemBase.FontViewModel.FontFamily), itemBase.FontViewModel.FontStyle, itemBase.FontViewModel.FontWeight, itemBase.FontViewModel.FontStretch),
itemBase.FontViewModel.FontSize,
Brushes.Black);
return new Size(formattedText.Width, formattedText.Height);
}
public virtual void Dispose()
{
}
}
}