using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Reactive.Linq; using System.Windows; using System.Windows.Input; using System.Windows.Media; using AIStudio.Wpf.DiagramDesigner.Geometrys; using AIStudio.Wpf.DiagramDesigner.Helpers; using AIStudio.Wpf.DiagramDesigner.Models; using Newtonsoft.Json; namespace AIStudio.Wpf.DiagramDesigner { public class DiagramViewModel : BindableBase, IDiagramViewModel { #region 属性 public ObservableCollection Items { get; set; } = new ObservableCollection(); public List SelectedItems { get { return Items.Where(x => x.IsSelected).ToList(); } } public SelectableDesignerItemViewModelBase SelectedItem { get { return SelectedItems.FirstOrDefault(); } } private SelectionService selectionService; public SelectionService SelectionService { get { if (selectionService == null) selectionService = new SelectionService(this); return selectionService; } } private bool _isReadOnly; public bool IsReadOnly { get { return _isReadOnly; } set { SetProperty(ref _isReadOnly, value); } } public bool IsLoading { get; set; } public IDrawModeViewModel DrawModeViewModel { get; set; } public IColorViewModel ColorViewModel { get; set; } public IFontViewModel FontViewModel { get; set; } public IShapeViewModel ShapeViewModel { get; set; } private PageSizeType _pageSizeType = PageSizeType.A4; public PageSizeType PageSizeType { get { return _pageSizeType; } set { SetProperty(ref _pageSizeType, value); RaisePropertyChanged(nameof(PageSize)); } } private Size _pageSize = new Size(1000, 600); public Size PageSize { get { if (PageSizeOrientation == PageSizeOrientation.Vertical) { return GetPageSize(); } else { return new Size(GetPageSize().Height, GetPageSize().Width); } } set { if (SetProperty(ref _pageSize, value)) { RaisePropertyChanged(nameof(PhysicalPageSize)); } } } public Size PhysicalPageSize { get { return new Size(ScreenHelper.WidthToMm(PageSize.Width), ScreenHelper.WidthToMm(PageSize.Height)); } set { PageSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height)); } } public Size GetPageSize() { Size size = _pageSize; switch (PageSizeType) { case PageSizeType.A3: size = new Size(297, 420); break; case PageSizeType.A4: size = new Size(210, 297); break; case PageSizeType.A5: size = new Size(148, 210); break; case PageSizeType.B4: size = new Size(257, 364); break; case PageSizeType.B5: size = new Size(176, 250); break; case PageSizeType.DLEnvelope: size = new Size(110, 220); break; case PageSizeType.C5Envelope: size = new Size(162, 229); break; case PageSizeType.Quarto: size = new Size(215, 275); break; case PageSizeType.C6Quarto: size = new Size(114, 162); break; case PageSizeType.B5Quarto: size = new Size(176, 250); break; case PageSizeType.ItalyQuarto: size = new Size(110, 230); break; case PageSizeType.A4small: size = new Size(210, 297); break; case PageSizeType.GermanStdFanfold: size = new Size(215.9, 304.8); break; case PageSizeType.GermanLegalFanfold: size = new Size(203.2, 330.2); break; case PageSizeType.PRC16K: size = new Size(146, 215); break; case PageSizeType.PRC32K: size = new Size(97, 151); break; case PageSizeType.Letter: size = new Size(215.9, 279.4); break; case PageSizeType.Folio: size = new Size(215.9, 330.2); break; case PageSizeType.Legal: size = new Size(215.9, 355.6); break; case PageSizeType.Executive: size = new Size(184.15, 266.7); break; case PageSizeType.Statement: size = new Size(139.7, 215.9); break; case PageSizeType.Envelope: size = new Size(104.77, 241.3); break; case PageSizeType.MonarchEnvelope: size = new Size(98.425, 190.5); break; case PageSizeType.Tabloid: size = new Size(279.4, 431.8); break; case PageSizeType.LetterSmall: size = new Size(215.9, 279.4); break; case PageSizeType.CSheet: size = new Size(431.8, 558.8); break; case PageSizeType.DSheet: size = new Size(558.8, 863.6); break; case PageSizeType.ESheet: size = new Size(863.6, 1117.6); break; } return new Size(ScreenHelper.MmToWidth(size.Width), ScreenHelper.MmToWidth(size.Height)); } private PageSizeOrientation _pageSizeOrientation; public PageSizeOrientation PageSizeOrientation { get { return _pageSizeOrientation; } set { SetProperty(ref _pageSizeOrientation, value); RaisePropertyChanged(nameof(PageSize)); } } private PageUnit _pageUnit = PageUnit.cm; [Browsable(false)] public PageUnit PageUnit { get { return _pageUnit; } set { if (value != PageUnit.cm && value != PageUnit.inch) { return; } SetProperty(ref _pageUnit, value); } } private Size _gridCellSize = new Size(100, 100); public Size GridCellSize { get { return _gridCellSize; } set { SetProperty(ref _gridCellSize, value); } } public double GridCellWidth { get { return _gridCellSize.Width; } set { _gridCellSize.Width = value; RaisePropertyChanged(nameof(PhysicalGridCellWidth)); RaisePropertyChanged(nameof(GridCellSize)); } } public double GridCellHeight { get { return _gridCellSize.Height; } set { _gridCellSize.Height = value; RaisePropertyChanged(nameof(PhysicalGridCellHeight)); RaisePropertyChanged(nameof(GridCellSize)); } } public Size PhysicalGridCellSize { get { return new Size(ScreenHelper.WidthToMm(GridCellSize.Width), ScreenHelper.WidthToMm(GridCellSize.Height)); } set { GridCellSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height)); } } public double PhysicalGridCellWidth { get { return ScreenHelper.WidthToMm(GridCellWidth); } set { GridCellWidth = ScreenHelper.MmToWidth(value); } } public double PhysicalGridCellHeight { get { return ScreenHelper.WidthToMm(GridCellHeight); } set { GridCellHeight = ScreenHelper.MmToWidth(value); } } private Color _pageBackground = Colors.White; public Color PageBackground { get { return _pageBackground; } set { SetProperty(ref _pageBackground, value); } } private bool _showGrid = true; public bool ShowGrid { get { return _showGrid; } set { SetProperty(ref _showGrid, value); } } private Color _gridColor = Colors.LightGray; public Color GridColor { get { return _gridColor; } set { SetProperty(ref _gridColor, value); } } private Size _gridMargin = new Size(28, 28); public Size GridMarginSize { get { return _gridMargin; } set { SetProperty(ref _gridMargin, value); } } public double GridMarginWidth { get { return _gridMargin.Width; } set { _gridMargin.Width = value; RaisePropertyChanged(nameof(GridMarginSize)); } } public double GridMarginHeight { get { return _gridMargin.Height; } set { _gridMargin.Height = value; RaisePropertyChanged(nameof(GridMarginSize)); } } public Size PhysicalGridMarginSize { get { return new Size(ScreenHelper.WidthToMm(GridMarginSize.Width), ScreenHelper.WidthToMm(GridMarginSize.Height)); } set { GridMarginSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height)); } } public double PhysicalGridMarginWidth { get { return ScreenHelper.WidthToMm(GridMarginWidth); } set { GridMarginWidth = ScreenHelper.MmToWidth(value); } } public double PhysicalGridMarginHeight { get { return ScreenHelper.WidthToMm(GridMarginHeight); } set { GridMarginHeight = ScreenHelper.MmToWidth(value); } } private double _zoomValue = 1; [Browsable(false)] public double ZoomValue { get { return _zoomValue; } set { SetProperty(ref _zoomValue, value); } } private double _maximumZoomValue = 100; [Browsable(false)] public double MaximumZoomValue { get { return _maximumZoomValue; } set { SetProperty(ref _maximumZoomValue, value); } } private double _minimumZoomValue = 0.01; [Browsable(false)] public double MinimumZoomValue { get { return _minimumZoomValue; } set { SetProperty(ref _minimumZoomValue, value); } } private bool _defaultZoomBox; public bool DefaultZoomBox { get { return _defaultZoomBox; } set { SetProperty(ref _defaultZoomBox, value); } } private double _delayZoomValue = 1; [Browsable(false)] public double DelayZoomValue { get { return _delayZoomValue; } set { SetProperty(ref _delayZoomValue, value); } } private FitViewModel _fitViewModel; public FitViewModel FitViewModel { get { return _fitViewModel; } set { SetProperty(ref _fitViewModel, value); } } private string _name; [Browsable(false)] public string Name { get { return _name; } set { SetProperty(ref _name, value); } } private DiagramType _diagramType; [Browsable(false)] public DiagramType DiagramType { get { return _diagramType; } set { SetProperty(ref _diagramType, value); } } private CellHorizontalAlignment _cellHorizontalAlignment; [Browsable(false)] public CellHorizontalAlignment CellHorizontalAlignment { get { return _cellHorizontalAlignment; } set { SetProperty(ref _cellHorizontalAlignment, value); } } private CellVerticalAlignment _cellVerticalAlignment; [Browsable(false)] public CellVerticalAlignment CellVerticalAlignment { get { return _cellVerticalAlignment; } set { SetProperty(ref _cellVerticalAlignment, value); } } private bool _isEditName; [Browsable(false)] public bool IsEditName { get { return _isEditName; } set { SetProperty(ref _isEditName, value); } } private System.Windows.Point _currentPoint; [Browsable(false)] public System.Windows.Point CurrentPoint { get { return _currentPoint; } set { SetProperty(ref _currentPoint, value); } } private Color _currentColor; [Browsable(false)] public Color CurrentColor { get { return _currentColor; } set { SetProperty(ref _currentColor, value); } } private string _searchText; public string SearchText { get { return _searchText; } set { SetProperty(ref _searchText, value); } } private string _searchInfo; public string SearchInfo { get { return _searchText; } set { SetProperty(ref _searchInfo, value); } } protected ObservableCollection menuOptions; public IEnumerable MenuOptions { get { return menuOptions; } } public bool ShowMenuOptions { get { if (MenuOptions == null || MenuOptions.Count() == 0) return false; else return true; } } public DiagramOption DiagramOption { get; set; } = new DiagramOption(); public bool AllowDrop { get; set; } = true; protected DoCommandManager DoCommandManager = new DoCommandManager(); public event DiagramEventHandler Event; private double OffsetX = 10; private double OffsetY = 10; #endregion #region 命令 private ICommand _createNewDiagramCommand; public ICommand CreateNewDiagramCommand { get { return this._createNewDiagramCommand ?? (this._createNewDiagramCommand = new SimpleCommand(ExecuteEnable, ExecuteCreateNewDiagramCommand)); } } private ICommand _directAddItemCommand; public ICommand DirectAddItemCommand { get { return this._directAddItemCommand ?? (this._directAddItemCommand = new SimpleCommand(ExecuteEnable, ExecuteDirectAddItemCommand)); } } private ICommand _addItemCommand; public ICommand AddItemCommand { get { return this._addItemCommand ?? (this._addItemCommand = new SimpleCommand(ExecuteEnable, ExecuteAddItemCommand)); } } private ICommand _directRemoveItemCommand; public ICommand DirectRemoveItemCommand { get { return this._directRemoveItemCommand ?? (this._directRemoveItemCommand = new SimpleCommand(ExecuteEnable, ExecuteDirectRemoveItemCommand)); } } private ICommand _removeItemCommand; public ICommand RemoveItemCommand { get { return this._removeItemCommand ?? (this._removeItemCommand = new SimpleCommand(ExecuteEnable, ExecuteRemoveItemCommand)); } } private ICommand _clearSelectedItemsCommand; public ICommand ClearSelectedItemsCommand { get { return this._clearSelectedItemsCommand ?? (this._clearSelectedItemsCommand = new SimpleCommand(ExecuteEnable, ExecuteClearSelectedItemsCommand)); } } private ICommand _alignTopCommand; public ICommand AlignTopCommand { get { return this._alignTopCommand ?? (this._alignTopCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignTopCommand)); } } private ICommand _alignVerticalCentersCommand; public ICommand AlignVerticalCentersCommand { get { return this._alignVerticalCentersCommand ?? (this._alignVerticalCentersCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignVerticalCentersCommand)); } } private ICommand _alignBottomCommand; public ICommand AlignBottomCommand { get { return this._alignBottomCommand ?? (this._alignBottomCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignBottomCommand)); } } private ICommand _alignLeftCommand; public ICommand AlignLeftCommand { get { return this._alignLeftCommand ?? (this._alignLeftCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignLeftCommand)); } } private ICommand _alignHorizontalCentersCommand; public ICommand AlignHorizontalCentersCommand { get { return this._alignHorizontalCentersCommand ?? (this._alignHorizontalCentersCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignHorizontalCentersCommand)); } } private ICommand _alignRightCommand; public ICommand AlignRightCommand { get { return this._alignRightCommand ?? (this._alignRightCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignRightCommand)); } } private ICommand _bringForwardCommand; public ICommand BringForwardCommand { get { return this._bringForwardCommand ?? (this._bringForwardCommand = new SimpleCommand(ExecuteEnable, ExecuteBringForwardCommand)); } } private ICommand _bringToFrontCommand; public ICommand BringToFrontCommand { get { return this._bringToFrontCommand ?? (this._bringToFrontCommand = new SimpleCommand(ExecuteEnable, ExecuteBringToFrontCommand)); } } private ICommand _sendBackwardCommand; public ICommand SendBackwardCommand { get { return this._sendBackwardCommand ?? (this._sendBackwardCommand = new SimpleCommand(ExecuteEnable, ExecuteSendBackwardCommand)); } } private ICommand _sendToBackCommand; public ICommand SendToBackCommand { get { return this._sendToBackCommand ?? (this._sendToBackCommand = new SimpleCommand(ExecuteEnable, ExecuteSendToBackCommand)); } } private ICommand _distributeHorizontalCommand; public ICommand DistributeHorizontalCommand { get { return this._distributeHorizontalCommand ?? (this._distributeHorizontalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeHorizontalCommand)); } } private ICommand _distributeVerticalCommand; public ICommand DistributeVerticalCommand { get { return this._distributeVerticalCommand ?? (this._distributeVerticalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeVerticalCommand)); } } private ICommand _selectAllCommand; public ICommand SelectAllCommand { get { return this._selectAllCommand ?? (this._selectAllCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectAllCommand)); } } private ICommand _selectInverseCommand; public ICommand SelectInverseCommand { get { return this._selectInverseCommand ?? (this._selectInverseCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectInverseCommand)); } } private ICommand _selectItemCommand; public ICommand SelectItemCommand { get { return this._selectItemCommand ?? (this._selectItemCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectItemCommand)); } } private ICommand _copyCommand; public ICommand CopyCommand { get { return this._copyCommand ?? (this._copyCommand = new SimpleCommand(ExecuteEnable, ExecuteCopyCommand)); } } private ICommand _pasteCommand; public ICommand PasteCommand { get { return this._pasteCommand ?? (this._pasteCommand = new SimpleCommand(ExecuteEnable, ExecutePasteCommand)); } } private ICommand _cutCommand; public ICommand CutCommand { get { return this._cutCommand ?? (this._cutCommand = new SimpleCommand(ExecuteEnable, ExecuteCutCommand)); } } private ICommand _deleteCommand; public virtual ICommand DeleteCommand { get { return this._deleteCommand ?? (this._deleteCommand = new SimpleCommand(ExecuteEnable, ExecuteDeleteCommand)); } } private ICommand _leftMoveCommand; public ICommand LeftMoveCommand { get { return this._leftMoveCommand ?? (this._leftMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteLeftMoveCommand)); } } private ICommand _rightMoveCommand; public ICommand RightMoveCommand { get { return this._rightMoveCommand ?? (this._rightMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteRightMoveCommand)); } } private ICommand _upMoveCommand; public ICommand UpMoveCommand { get { return this._upMoveCommand ?? (this._upMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteUpMoveCommand)); } } private ICommand _downMoveCommand; public ICommand DownMoveCommand { get { return this._downMoveCommand ?? (this._downMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteDownMoveCommand)); } } private ICommand _centerMoveCommand; public ICommand CenterMoveCommand { get { return this._centerMoveCommand ?? (this._centerMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteCenterMoveCommand)); } } private ICommand _sameSizeCommand; public ICommand SameSizeCommand { get { return this._sameSizeCommand ?? (this._sameSizeCommand = new SimpleCommand(ExecuteEnable, ExecuteSameSizeCommand)); } } private ICommand _sameWidthCommand; public ICommand SameWidthCommand { get { return this._sameWidthCommand ?? (this._sameWidthCommand = new SimpleCommand(ExecuteEnable, ExecuteSameWidthCommand)); } } private ICommand _sameHeightCommand; public ICommand SameHeightCommand { get { return this._sameHeightCommand ?? (this._sameHeightCommand = new SimpleCommand(ExecuteEnable, ExecuteSameHeightCommand)); } } private ICommand _sameAngleCommand; public ICommand SameAngleCommand { get { return this._sameAngleCommand ?? (this._sameAngleCommand = new SimpleCommand(ExecuteEnable, ExecuteSameAngleCommand)); } } private ICommand _fitAutoCommand; public ICommand FitAutoCommand { get { return this._fitAutoCommand ?? (this._fitAutoCommand = new SimpleCommand(ExecuteEnable, ExecuteFitAutoCommand)); } } private ICommand _fitWidthCommand; public ICommand FitWidthCommand { get { return this._fitWidthCommand ?? (this._fitWidthCommand = new SimpleCommand(ExecuteEnable, ExecuteFitWidthCommand)); } } private ICommand _fitHeightCommand; public ICommand FitHeightCommand { get { return this._fitHeightCommand ?? (this._fitHeightCommand = new SimpleCommand(ExecuteEnable, ExecuteFitHeightCommand)); } } private ICommand _groupCommand; public ICommand GroupCommand { get { return this._groupCommand ?? (this._groupCommand = new SimpleCommand(ExecuteEnable, ExecuteGroupCommand)); } } private ICommand _ungroupCommand; public ICommand UngroupCommand { get { return this._ungroupCommand ?? (this._ungroupCommand = new SimpleCommand(ExecuteEnable, ExecuteUngroupCommand)); } } private ICommand _lockCommand; public ICommand LockCommand { get { return this._lockCommand ?? (this._lockCommand = new SimpleCommand(ExecuteEnable, ExecuteLockCommand)); } } private ICommand _unlockCommand; public ICommand UnlockCommand { get { return this._unlockCommand ?? (this._unlockCommand = new SimpleCommand(ExecuteEnable, ExecuteUnlockCommand)); } } private ICommand _editCommand; public ICommand EditCommand { get { return this._editCommand ?? (this._editCommand = new SimpleCommand(ExecuteEnable, ExecuteEditCommand)); } } private ICommand _undoCommand; public ICommand UndoCommand { get { return this._undoCommand ?? (this._undoCommand = new SimpleCommand(Undo_Enabled, this.ExecutedUndoCommand)); } } private ICommand _redoCommand; public ICommand RedoCommand { get { return this._redoCommand ?? (this._redoCommand = new SimpleCommand(Redo_Enabled, this.ExecutedRedoCommand)); } } private ICommand _resetLayoutCommand; public ICommand ResetLayoutCommand { get { return this._resetLayoutCommand ?? (this._resetLayoutCommand = new SimpleCommand(ExecuteEnable, this.ExecutedResetLayoutCommand)); } } private ICommand _searchDownCommand; public ICommand SearchDownCommand { get { return this._searchDownCommand ?? (this._searchDownCommand = new SimpleCommand(ExecuteEnable, this.ExecutedSearchDownCommand)); } } private ICommand _searchUpCommand; public ICommand SearchUpCommand { get { return this._searchUpCommand ?? (this._searchUpCommand = new SimpleCommand(ExecuteEnable, this.ExecutedSearchUpCommand)); } } #endregion #region ctor和初始化 public DiagramViewModel() { Mediator.Instance.Register(this); Items.CollectionChanged += Items_CollectionChanged; var zoomValueChangedSubscription = WhenPropertyChanged.Where(o => o.ToString() == nameof(ZoomValue)).Throttle(TimeSpan.FromMilliseconds(100)).Subscribe(OnZoomValueChanged);//Sample } public DiagramViewModel(DiagramItem diagramItem) : this() { DiagramType = diagramItem.DiagramType; ShowGrid = diagramItem.ShowGrid; PhysicalGridCellSize = diagramItem.PhysicalGridCellSize; CellHorizontalAlignment = diagramItem.CellHorizontalAlignment; CellVerticalAlignment = diagramItem.CellVerticalAlignment; PageSizeOrientation = diagramItem.PageSizeOrientation; PhysicalPageSize = diagramItem.PhysicalPageSize; PageSizeType = diagramItem.PageSizeType; PhysicalGridMarginSize = diagramItem.PhysicalGridMarginSize; GridColor = diagramItem.GridColor; AllowDrop = diagramItem.AllowDrop; Init(); BuildMenuOptions(); } public virtual void Init() { DoCommandManager.Init(); } protected virtual void ExecutedResetLayoutCommand(object obj) { } #endregion #region 命令使能 public virtual bool ExecuteEnable(object para) { return IsReadOnly == false; } #endregion #region 菜单 private void BuildMenuOptions() { menuOptions = new ObservableCollection(); CinchMenuItem menuItem = new CinchMenuItem(); menuItem.Text = "居中"; menuItem.Command = CenterMoveCommand; menuItem.CommandParameter = this; menuOptions.Add(menuItem); } #endregion #region UnDo ReDo private void Do(object sender, string propertyName, object newvalue) { sender.SetPropertyValue(propertyName, newvalue); } private void UnDo(object sender, string propertyName, object oldvalue) { sender.SetPropertyValue(propertyName, oldvalue); } private void ExecutedUndoCommand(object para) { Undo(para); } private bool Undo(object para) { var first = SelectedItems.OfType().FirstOrDefault(); if (first != null && first.IsEditing == true) { return false; } DoCommandManager.UnDo(); return true; } private void ExecutedRedoCommand(object para) { Redo(para); } private bool Redo(object para) { var first = SelectedItems.OfType().FirstOrDefault(); if (first != null && first.IsEditing == true) { return false; } DoCommandManager.ReDo(); return true; } private bool Undo_Enabled(object para) { return DoCommandManager.CanUnDo; } private bool Redo_Enabled(object para) { return DoCommandManager.CanReDo; } #endregion #region 属性改变 private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.OldItems != null) { foreach (var item in e.OldItems.OfType()) { item.PropertyChanged -= Item_PropertyChanged; item.Dispose(); } } if (e.NewItems != null) { foreach (var item in e.NewItems.OfType()) { item.PropertyChanged += Item_PropertyChanged; } } RaisePropertyChanged("Items"); } private void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { RaisePropertyChanged(sender, e.PropertyName); if (e.PropertyName == "IsSelected") { RaisePropertyChanged(nameof(SelectedItem)); } //连续改变,需要特殊处理,不单独触发属性改变ReDo if (sender is DesignerItemViewModelBase designer) { if (designer.BeginDo) return; } var selectable = sender as SelectableViewModelBase; if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs) { var property = sender.GetType().GetProperty(e.PropertyName); var attr = property.GetCustomAttributes(typeof(CanDoAttribute), true); if (attr != null && attr.Length != 0) { //加入ReDo DoCommandManager.DoNewCommand(sender.ToString() + e.PropertyName, () => Do(sender, e.PropertyName, valuePropertyChangedEventArgs.NewValue), () => UnDo(sender, e.PropertyName, valuePropertyChangedEventArgs.OldValue), null, false); Event?.Invoke(sender, new DiagramEventArgs(valuePropertyChangedEventArgs.PropertyName, valuePropertyChangedEventArgs.NewValue, valuePropertyChangedEventArgs.OldValue, selectable?.Id)); } } } //提供给标尺计算,延迟100ms,等布局改变再计算。 private void OnZoomValueChanged(string obj) { DelayZoomValue = ZoomValue; } #endregion [MediatorMessageSink("DoneDrawingMessage")] public void OnDoneDrawingMessage(bool dummy) { foreach (var item in Items.OfType()) { item.ShowConnectors = false; } } #region 新增,删除 protected virtual void ExecuteCreateNewDiagramCommand(object parameter) { this.Items.Clear(); } private void ExecuteDirectAddItemCommand(object parameter) { if (parameter is SelectableDesignerItemViewModelBase ite) { if (AddVerify(ite) != true) return; ClearSelectedItems(); Add(ite); } else if (parameter is IEnumerable items) { if (items.Select(p => AddVerify(p)).Any() != true) return; ClearSelectedItems(); foreach (var item in items) { Add(item); } } } private void ExecuteAddItemCommand(object parameter) { if (parameter is SelectableDesignerItemViewModelBase ite) { if (AddVerify(ite) != true) return; DoCommandManager.DoNewCommand(this.ToString(), () => { ClearSelectedItems(); Add(ite); }, () => { Items.Remove(ite); }); } else if (parameter is IEnumerable items) { if (items.Select(p => AddVerify(p)).Any() != true) return; DoCommandManager.DoNewCommand(this.ToString(), () => { ClearSelectedItems(); foreach (var item in items) { Add(item); } }, () => { foreach (var item in items) { Items.Remove(item); } }); } } public bool AddVerify(SelectableDesignerItemViewModelBase item) { if (item.InitData() == false) return false; return true; } private void Add(SelectableDesignerItemViewModelBase item) { item.Root = this; item.ZIndex = Items.Any() ? Items.Max(p => p.ZIndex) + 1 : 0; if (item.Id == Guid.Empty) { item.Id = Guid.NewGuid(); } var logical = item as LogicalGateItemViewModelBase; if (logical != null && logical.LogicalType > 0) { logical.OrderNumber = Items.OfType().Count(p => (int)p.LogicalType > 0) + 1; } var designerItemViewModelBase = item as DesignerItemViewModelBase; if (designerItemViewModelBase != null) { designerItemViewModelBase.SetCellAlignment(); } Items.Add(item); item.IsSelected = true; } private void ExecuteDirectRemoveItemCommand(object parameter) { if (parameter is SelectableDesignerItemViewModelBase ite) { ite.IsSelected = false; Items.Remove(ite); } else if (parameter is IEnumerable items) { foreach (var item in items) { item.IsSelected = false; Items.Remove(item); } } } private void ExecuteRemoveItemCommand(object parameter) { if (parameter is SelectableDesignerItemViewModelBase ite) { DoCommandManager.DoNewCommand(this.ToString(), () => { ite.IsSelected = false; Items.Remove(ite); }, () => { Items.Add(ite); }); } else if (parameter is IEnumerable items) { DoCommandManager.DoNewCommand(this.ToString(), () => { foreach (var item in items) { item.IsSelected = false; Items.Remove(item); } }, () => { foreach (var item in items) { Items.Add(item); } }); } } private void ExecuteClearSelectedItemsCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems) { item.IsSelected = false; } } public void ClearSelectedItems() { foreach (var item in this.Items.ToList()) { item.IsSelected = false; } } private void ExecuteSelectAllCommand(object parameter) { foreach (var item in Items) { item.IsSelected = true; } } private void ExecuteSelectInverseCommand(object parameter) { foreach (var item in SelectedItems) { item.IsSelected = false; } foreach (var item in Items.Except(SelectedItems)) { item.IsSelected = true; } } public void ExecuteSelectItemCommand(object parameter) { if (parameter is ISelectable selectable) { foreach (var item in this.Items.ToList()) { if (object.Equals(selectable, item)) { item.IsSelected = true; } else { item.IsSelected = false; } } } } #endregion #region 复制,粘贴 private void ExecuteCopyCommand(object parameter) { Copy(parameter); } private bool Copy(object parameter) { List selectedDesignerItems; List selectedConnections; if (parameter is IEnumerable para) { selectedDesignerItems = para.OfType().ToList(); selectedConnections = para.OfType().ToList(); } else { if (SelectedItems.Count == 0) { return false; } var first = SelectedItems.OfType().FirstOrDefault(); if (first != null && first.IsEditing == true) { return false; } selectedDesignerItems = SelectedItems.OfType().ToList(); selectedConnections = SelectedItems.OfType().ToList(); } foreach (ConnectionViewModel connection in Items.OfType()) { if (!selectedConnections.Contains(connection)) { DesignerItemViewModelBase sourceItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SourceConnectorInfo.DataItem.Id); DesignerItemViewModelBase sinkItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SinkConnectorInfoFully?.DataItem?.Id); if (sourceItem != null && sinkItem != null && BelongToSameGroup(sourceItem, sinkItem)) { selectedConnections.Add(connection); } } } string json = new SerializableObject { DesignerItems = selectedDesignerItems.Select(p => p.ToSerializableItem(".json")).Where(p => p != null).ToList(), Connections = selectedConnections.Select(p => p.ToSerializableItem(".json")).Where(p => p != null).ToList(), }.ToJson(); OffsetX = 10; OffsetY = 10; System.Windows.Clipboard.Clear(); System.Windows.Clipboard.SetData(System.Windows.DataFormats.Serializable, json); return true; } private void ExecutePasteCommand(object parameter) { Paste(parameter); } protected virtual bool Paste(object parameter) { if (System.Windows.Clipboard.ContainsData(System.Windows.DataFormats.Serializable)) { string clipboardData = System.Windows.Clipboard.GetData(System.Windows.DataFormats.Serializable) as String; if (string.IsNullOrEmpty(clipboardData)) return false; try { List items = new List(); SerializableObject copyitem = JsonConvert.DeserializeObject(clipboardData); Dictionary mappingOldToNewIDs = new Dictionary(); foreach (var diagramItemData in copyitem.DesignerItems) { DesignerItemViewModelBase newItem = null; Type type = TypeHelper.GetType(diagramItemData.ModelTypeName); DesignerItemViewModelBase itemBase = Activator.CreateInstance(type, this, diagramItemData, ".json") as DesignerItemViewModelBase; Guid newID = Guid.NewGuid(); mappingOldToNewIDs.Add(itemBase.Id, newID); itemBase.Id = newID; itemBase.Left += OffsetX; itemBase.Top += OffsetY; newItem = itemBase; if (newItem != null) { items.Add(newItem); } } OffsetX += 10; OffsetY += 10; List connectors = new List(); foreach (var connection in copyitem.Connections) { var connectionItem = JsonConvert.DeserializeObject(connection.SerializableString); Guid newID = Guid.NewGuid(); mappingOldToNewIDs.Add(connectionItem.Id, newID); connectionItem.SourceId = mappingOldToNewIDs[connectionItem.SourceId]; connectionItem.SinkId = mappingOldToNewIDs[connectionItem.SinkId]; connectionItem.SourceType = System.Type.GetType(connectionItem.SourceTypeName); connectionItem.SinkType = System.Type.GetType(connectionItem.SinkTypeName); DesignerItemViewModelBase sourceItem = DiagramViewModelHelper.GetConnectorDataItem(items, connectionItem.SourceId, connectionItem.SourceType); ConnectorOrientation sourceConnectorOrientation = connectionItem.SourceOrientation; FullyCreatedConnectorInfo sourceConnectorInfo = sourceItem.GetFullConnectorInfo(connectionItem.Id, sourceConnectorOrientation, connectionItem.SourceXRatio, connectionItem.SourceYRatio, connectionItem.SourceInnerPoint, connectionItem.SourceIsPortless); DesignerItemViewModelBase sinkItem = DiagramViewModelHelper.GetConnectorDataItem(items, connectionItem.SinkId, connectionItem.SinkType); ConnectorOrientation sinkConnectorOrientation = connectionItem.SinkOrientation; FullyCreatedConnectorInfo sinkConnectorInfo = sinkItem.GetFullConnectorInfo(connectionItem.Id, sinkConnectorOrientation, connectionItem.SinkXRatio, connectionItem.SinkYRatio, connectionItem.SinkInnerPoint, connectionItem.SinkIsPortless); ConnectionViewModel connectionVM = new ConnectionViewModel(this, sourceConnectorInfo, sinkConnectorInfo, connectionItem); connectors.Add(connectionVM); } //修复父级的引用 foreach (var item in items) { if (item.ParentId != Guid.Empty) { if (mappingOldToNewIDs.ContainsKey(item.ParentId)) item.ParentId = mappingOldToNewIDs[item.ParentId]; } } items.AddRange(connectors); DirectAddItemCommand.Execute(items); FixOtherInfo(items); } catch (Exception e) { System.Windows.MessageBox.Show(e.StackTrace, e.Message, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } return true; } else { return false; } } protected virtual void FixOtherInfo(List items) { } private bool ItemsToDeleteHasConnector(List itemsToRemove, ConnectorInfoBase connector) { if (connector is FullyCreatedConnectorInfo fully) { return itemsToRemove.Contains(fully.DataItem); } return false; } private void ExecuteCutCommand(object parameter) { Cut(parameter); } private bool Cut(object parameter) { if (Paste(null) == false) return false; OffsetX = 0; OffsetY = 0; if (Delete(null) == false) return false; return true; } protected void ExecuteDeleteCommand(object parameter) { Delete(parameter); } protected virtual bool Delete(object parameter) { List itemsToRemove; if (parameter is IEnumerable para) { itemsToRemove = para.OfType().ToList(); } else { if (SelectedItems.Count == 0) { return false; } var first = SelectedItems.OfType().FirstOrDefault(); if (first != null && first.IsEditing == true) { return false; } itemsToRemove = SelectedItems.OfType().ToList(); } List connectionsToAlsoRemove = new List(); foreach (var connector in Items.OfType()) { if (ItemsToDeleteHasConnector(itemsToRemove, connector.SourceConnectorInfo)) { connectionsToAlsoRemove.Add(connector); } if (ItemsToDeleteHasConnector(itemsToRemove, connector.SinkConnectorInfo)) { connectionsToAlsoRemove.Add(connector); } } itemsToRemove.AddRange(connectionsToAlsoRemove); RemoveItemCommand.Execute(itemsToRemove); return true; } #endregion #region 布局 private void ExecuteAlignTopCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double top = selectedItems.OrderBy(p => p.Top).Select(p => p.Top).FirstOrDefault(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Top, nameof(item.Top), guid.ToString()); item.Top = top; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Top = item.GetOldValue(nameof(item.Top), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Top), guid.ToString()); } }); } } private void ExecuteAlignVerticalCentersCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double mid = selectedItems.Select(p => p.Top + p.ItemHeight / 2).Average(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Top, nameof(item.Top), guid.ToString()); item.Top = mid - item.ItemHeight / 2; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Top = item.GetOldValue(nameof(item.Top), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Top), guid.ToString()); } }); } } private void ExecuteAlignBottomCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double top = selectedItems.OrderBy(p => p.Top + p.ItemHeight).Select(p => p.Top + p.ItemHeight).LastOrDefault(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Top, nameof(item.Top), guid.ToString()); item.Top = top - item.ItemHeight; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Top = item.GetOldValue(nameof(item.Top), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Top), guid.ToString()); } }); } } private void ExecuteAlignLeftCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double left = selectedItems.OrderBy(p => p.Left).Select(p => p.Left).FirstOrDefault(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Left, nameof(item.Left), guid.ToString()); item.Left = left; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Left = item.GetOldValue(nameof(item.Left), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Left), guid.ToString()); } }); } } private void ExecuteAlignHorizontalCentersCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double mid = selectedItems.Select(p => p.Left + p.ItemWidth / 2).Average(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Left, nameof(item.Left), guid.ToString()); item.Left = mid - item.ItemWidth / 2; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Left = item.GetOldValue(nameof(item.Left), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Left), guid.ToString()); } }); } } private void ExecuteAlignRightCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double right = selectedItems.OrderBy(p => p.Left + p.ItemWidth).Select(p => p.Left + p.ItemWidth).LastOrDefault(); foreach (DesignerItemViewModelBase item in selectedItems) { item.SetOldValue(item.Left, nameof(item.Left), guid.ToString()); item.Left = right - item.ItemWidth; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.Left = item.GetOldValue(nameof(item.Left), guid.ToString()); } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { item.ClearOldValue(nameof(item.Left), guid.ToString()); } }); } } private void ExecuteBringForwardCommand(object parameter) { List ordered; if (parameter is IEnumerable para) { ordered = para.OrderByDescending(p => p.ZIndex).ToList(); } else { ordered = SelectedItems.OrderByDescending(p => p.ZIndex).ToList(); } List changeditems = new List(); var guid = Guid.NewGuid(); DoCommandManager.DoNewCommand(this.ToString(), () => { int count = this.Items.Count; for (int i = 0; i < ordered.Count; i++) { var item = ordered[i]; int currentIndex = item.ZIndex; int newIndex = Math.Min(count - 1 - i, currentIndex + 1); if (currentIndex != newIndex) { item.SetOldValue(item.ZIndex, nameof(item.ZIndex), guid.ToString()); item.ZIndex = newIndex; changeditems.Add(item); IEnumerable it = this.Items.Where(p => p.ZIndex == newIndex); foreach (var elm in it) { if (elm != item) { elm.SetOldValue(elm.ZIndex, nameof(elm.ZIndex), guid.ToString()); elm.ZIndex = currentIndex; changeditems.Add(elm); break; } } } } }, () => { foreach (var item in changeditems) { item.ZIndex = item.GetOldValue(nameof(item.ZIndex), guid.ToString()); } }, () => { foreach (var item in changeditems) { item.ClearOldValue(nameof(item.ZIndex), guid.ToString()); } }); } private void ExecuteBringToFrontCommand(object parameter) { List selectionSorted; if (parameter is IEnumerable para) { selectionSorted = para.OrderByDescending(p => p.ZIndex).ToList(); } else { selectionSorted = SelectedItems.OrderByDescending(p => p.ZIndex).ToList(); } List childrenSorted = Items.OrderByDescending(p => p.ZIndex).ToList(); List changeditems = new List(); var guid = Guid.NewGuid(); DoCommandManager.DoNewCommand(this.ToString(), () => { int i = childrenSorted.Count - 1; int j = childrenSorted.Count - selectionSorted.Count - 1; foreach (SelectableDesignerItemViewModelBase item in childrenSorted) { item.SetOldValue(item.ZIndex, nameof(item.ZIndex), guid.ToString()); if (selectionSorted.Contains(item)) { item.ZIndex = i--; } else { item.ZIndex = j--; } changeditems.Add(item); } }, () => { foreach (var item in changeditems) { item.ZIndex = item.GetOldValue(nameof(item.ZIndex), guid.ToString()); } }, () => { foreach (var item in changeditems) { item.ClearOldValue(nameof(item.ZIndex), guid.ToString()); } }); } private void ExecuteSendBackwardCommand(object parameter) { List ordered; if (parameter is IEnumerable para) { ordered = para.OrderBy(p => p.ZIndex).ToList(); } else { ordered = SelectedItems.OrderBy(p => p.ZIndex).ToList(); } int count = this.Items.Count; List changeditems = new List(); var guid = Guid.NewGuid(); DoCommandManager.DoNewCommand(this.ToString(), () => { for (int i = 0; i < ordered.Count; i++) { var item = ordered[i]; int currentIndex = item.ZIndex; int newIndex = Math.Max(i, currentIndex - 1); if (currentIndex != newIndex) { item.SetOldValue(item.ZIndex, nameof(item.ZIndex), guid.ToString()); item.ZIndex = newIndex; changeditems.Add(item); IEnumerable it = this.Items.Where(p => p.ZIndex == newIndex); foreach (var elm in it) { if (elm != ordered[i]) { elm.SetOldValue(elm.ZIndex, nameof(elm.ZIndex), guid.ToString()); elm.ZIndex = currentIndex; changeditems.Add(elm); break; } } } } }, () => { foreach (var item in changeditems) { item.ZIndex = item.GetOldValue(nameof(item.ZIndex), guid.ToString()); } }, () => { foreach (var item in changeditems) { item.ClearOldValue(nameof(item.ZIndex), guid.ToString()); } }); } private void ExecuteSendToBackCommand(object parameter) { List selectionSorted; if (parameter is IEnumerable para) { selectionSorted = para.OrderByDescending(p => p.ZIndex).ToList(); } else { selectionSorted = SelectedItems.OrderByDescending(p => p.ZIndex).ToList(); } List childrenSorted = Items.OrderByDescending(p => p.ZIndex).ToList(); List changeditems = new List(); var guid = Guid.NewGuid(); DoCommandManager.DoNewCommand(this.ToString(), () => { int i = childrenSorted.Count - 1; int j = selectionSorted.Count - 1; foreach (SelectableDesignerItemViewModelBase item in childrenSorted) { item.SetOldValue(item.ZIndex, nameof(item.ZIndex), guid.ToString()); if (selectionSorted.Contains(item)) { item.ZIndex = j--; } else { item.ZIndex = i--; } changeditems.Add(item); } }, () => { foreach (var item in changeditems) { item.ZIndex = item.GetOldValue(nameof(item.ZIndex), guid.ToString()); } }, () => { foreach (var item in changeditems) { item.ClearOldValue(nameof(item.ZIndex), guid.ToString()); } }); } private void ExecuteDistributeHorizontalCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para.Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Left); } else { selectedItems = this.SelectedItems.OfType().Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Left); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double left = Double.MaxValue; double right = Double.MinValue; double sumWidth = 0; foreach (DesignerItemViewModelBase item in selectedItems) { left = Math.Min(left, item.Left); right = Math.Max(right, item.Left + item.ItemWidth); sumWidth += item.ItemWidth; } double distance = Math.Max(0, (right - left - sumWidth) / (selectedItems.Count() - 1)); double offset = selectedItems.First().Left; foreach (DesignerItemViewModelBase item in selectedItems) { double delta = offset - item.Left; foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.SetOldValue(di.Left, nameof(di.Left), guid.ToString()); di.Left += delta; } offset = offset + item.ItemWidth + distance; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.Left = di.GetOldValue(nameof(di.Left), guid.ToString()); } } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.ClearOldValue(nameof(di.Left), guid.ToString()); } } }); } } private void ExecuteDistributeVerticalCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para.Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Top); } else { selectedItems = this.SelectedItems.OfType().Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Top); } var guid = Guid.NewGuid(); if (selectedItems.Count() > 1) { DoCommandManager.DoNewCommand(this.ToString(), () => { double top = Double.MaxValue; double bottom = Double.MinValue; double sumHeight = 0; foreach (DesignerItemViewModelBase item in selectedItems) { top = Math.Min(top, item.Top); bottom = Math.Max(bottom, item.Top + item.ItemHeight); sumHeight += item.ItemHeight; } double distance = Math.Max(0, (bottom - top - sumHeight) / (selectedItems.Count() - 1)); double offset = selectedItems.First().Top; foreach (DesignerItemViewModelBase item in selectedItems) { double delta = offset - item.Top; foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.SetOldValue(di.Top, nameof(di.Top), guid.ToString()); di.Top += +delta; } offset = offset + item.ItemHeight + distance; } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.Top = di.GetOldValue(nameof(di.Top), guid.ToString()); } } }, () => { foreach (DesignerItemViewModelBase item in selectedItems) { foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item)) { di.ClearOldValue(nameof(di.Top), guid.ToString()); } } }); } } #endregion #region 移动 private void ExecuteLeftMoveCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems.OfType()) { item.Left -= 0.5; } } private void ExecuteRightMoveCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems.OfType()) { item.Left += 0.5; } } private void ExecuteUpMoveCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems.OfType()) { item.Top -= 0.5; } } private void ExecuteDownMoveCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems.OfType()) { item.Top += 0.5; } } protected virtual void ExecuteCenterMoveCommand(object parameter) { IEnumerable selectedItems; if (parameter is IEnumerable para) { selectedItems = para; } else { selectedItems = this.SelectedItems.OfType(); } foreach (var item in selectedItems.OfType()) { item.Left = (PageSize.Width - item.ItemWidth) / 2; item.Top = (PageSize.Height - item.ItemHeight) / 2; } FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(selectedItems) }; } public void UpdateZIndex() { List ordered = Items.OrderBy(p => p.ZIndex).ToList(); for (int i = 0; i < ordered.Count; i++) { ordered[i].ZIndex = i; } } #endregion #region 大小 private void ExecuteSameSizeCommand(object parameter) { if (parameter is DesignerItemViewModelBase designerItem) { foreach (var item in SelectedItems.OfType()) { item.ItemWidth = designerItem.ItemWidth; item.ItemHeight = designerItem.ItemHeight; } } } private void ExecuteSameWidthCommand(object parameter) { if (parameter is DesignerItemViewModelBase designerItem) { foreach (var item in SelectedItems.OfType()) { item.ItemWidth = designerItem.ItemWidth; } } } private void ExecuteSameHeightCommand(object parameter) { if (parameter is DesignerItemViewModelBase designerItem) { foreach (var item in SelectedItems.OfType()) { item.ItemHeight = designerItem.ItemHeight; } } } private void ExecuteSameAngleCommand(object parameter) { if (parameter is DesignerItemViewModelBase designerItem) { foreach (var item in SelectedItems.OfType()) { item.Angle = designerItem.Angle; } } } #endregion #region 适应大小 private void ExecuteFitAutoCommand(object parameter) { FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType()), FitMode = FitMode.FitAuto }; } private void ExecuteFitWidthCommand(object parameter) { FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType()), FitMode = FitMode.FitWidth }; } private void ExecuteFitHeightCommand(object parameter) { FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType()), FitMode = FitMode.FitHeight }; } #endregion #region 分组 private void ExecuteGroupCommand(object parameter) { List items; GroupDesignerItemViewModel groupItem = null; if (parameter is IEnumerable para) { if (para.FirstOrDefault() is GroupDesignerItemViewModel groupDesignerItemViewModel && groupDesignerItemViewModel.Custom) { groupDesignerItemViewModel.Custom = false; groupItem = groupDesignerItemViewModel; items = para.Skip(1).ToList(); } else { items = para.ToList(); } } else { items = SelectedItems?.OfType().Where(p => p.ParentId == Guid.Empty).ToList(); } var groups = items.OfType().Where(p => p.IsGroup && p.ParentId == Guid.Empty).ToList(); //解除分组 if (groupItem == null && groups.Count > 0) { ExecuteUngroupCommand(groups); return; } RectangleBase rect = DiagramViewModelHelper.GetBoundingRectangle(items); if (groupItem == null) { groupItem = new GroupDesignerItemViewModel(); } DirectAddItemCommand.Execute(groupItem); foreach (DesignerItemViewModelBase item in items) item.ParentId = groupItem.Id; groupItem.Resize(); ClearSelectedItemsCommand.Execute(null); //groupItem.IsSelected = true; SelectionService.AddToSelection(groupItem); } private void ExecuteUngroupCommand(object parameter) { List groups; if (parameter is IEnumerable para) { groups = para.ToList(); } else { groups = SelectedItems?.OfType().Where(p => p.IsGroup && p.ParentId == Guid.Empty).ToList(); } foreach (DesignerItemViewModelBase groupRoot in groups) { var children = SelectedItems.OfType().Where(p => p.ParentId == groupRoot.Id); foreach (DesignerItemViewModelBase child in children) child.ParentId = Guid.Empty; RemoveItemCommand.Execute(groupRoot); UpdateZIndex(); } } public bool BelongToSameGroup(IGroupable item1, IGroupable item2) { IGroupable root1 = SelectionService.GetGroupRoot(item1); IGroupable root2 = SelectionService.GetGroupRoot(item2); return (root1.Id == root2.Id); } #endregion #region 快捷键操作 public bool ExecuteShortcut(KeyEventArgs e) { if (DiagramOption.ShortcutOption.SelectAll(e)) { SelectAllCommand.Execute(null); return true; } else if (DiagramOption.ShortcutOption.Copy(e)) { return Copy(null); } else if (DiagramOption.ShortcutOption.Paste(e)) { return Paste(null); } else if (DiagramOption.ShortcutOption.Cut(e)) { return Cut(null); } else if (DiagramOption.ShortcutOption.Undo(e)) { return Undo(null); } else if (DiagramOption.ShortcutOption.Redo(e)) { return Redo(null); } else if (DiagramOption.ShortcutOption.Delete(e)) { return Delete(null); } else if (DiagramOption.ShortcutOption.LeftMove(e)) { LeftMoveCommand.Execute(null); return true; } else if (DiagramOption.ShortcutOption.RightMove(e)) { RightMoveCommand.Execute(null); return true; } else if (DiagramOption.ShortcutOption.UpMove(e)) { UpMoveCommand.Execute(null); return true; } else if (DiagramOption.ShortcutOption.DownMove(e)) { DownMoveCommand.Execute(null); return true; } else if (DiagramOption.ShortcutOption.Group(e)) { GroupCommand.Execute(null); return true; } return false; } #endregion #region 锁定与解锁,待完善 private void ExecuteLockCommand(object parameter) { } private void ExecuteUnlockCommand(object parameter) { } #endregion #region 搜索与编辑 protected virtual void ExecuteEditCommand(object parameter) { if (parameter is SelectableDesignerItemViewModelBase designerItem) { designerItem.ShowText = true; } else { if (SelectedItem != null) SelectedItem.ShowText = true; } } private void ExecutedSearchUpCommand(object obj) { if (obj != null) { var selecteddesign = SelectedItem as DesignerItemViewModelBase; var searchitems = Items.OfType().Where(p => p.Text?.Contains(obj.ToString()) == true).ToList(); if (searchitems.Count > 0) { int selectindex = 0; if (selecteddesign != null) { int index = searchitems.IndexOf(selecteddesign); if (index == -1) { selectindex = 0; } else if (index - 1 >= 0) { selectindex = index - 1; } else { selectindex = searchitems.Count - 1; } } SelectItemCommand.Execute(searchitems[selectindex]); SearchInfo = $"第{selectindex + 1}条,共{searchitems.Count}条"; FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(SelectedItem as DesignerItemViewModelBase) }; } else { SearchInfo = "第0条,共0条"; } } else { SearchInfo = null; } } private void ExecutedSearchDownCommand(object obj) { if (obj != null) { var selecteddesign = SelectedItem as DesignerItemViewModelBase; var searchitems = Items.OfType().Where(p => p.Text?.Contains(obj.ToString()) == true).ToList(); if (searchitems.Count > 0) { int selectindex = 0; if (selecteddesign != null) { int index = searchitems.IndexOf(selecteddesign); if (index == -1) { selectindex = 0; } else if (index + 1 < searchitems.Count) { selectindex = index + 1; } else { selectindex = 0; } } SelectItemCommand.Execute(searchitems[selectindex]); SearchInfo = $"第{selectindex + 1}条,共{searchitems.Count}条"; FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(SelectedItem as DesignerItemViewModelBase) }; } else { SearchInfo = "第0条,共0条"; } } else { SearchInfo = null; } } #endregion } }