终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

992 lines
33 KiB

  1. using BeDesignerSCADA.Adorners;
  2. using BeDesignerSCADA.Speical;
  3. using BPASmartClient.Compiler;
  4. using BPASmartClient.SCADAControl;
  5. using Microsoft.Toolkit.Mvvm.Input;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using System.Windows;
  15. using System.Windows.Controls;
  16. using System.Windows.Controls.Primitives;
  17. using System.Windows.Documents;
  18. using System.Windows.Input;
  19. using System.Windows.Markup;
  20. using System.Windows.Media;
  21. using System.Windows.Shapes;
  22. using System.Xml;
  23. namespace BeDesignerSCADA.Controls
  24. {
  25. public class CanvasPanel : Canvas
  26. {
  27. public CanvasPanel()
  28. {
  29. UseLayoutRounding = true;
  30. Drop += CanvasPanel_Drop;
  31. CopySelectItemsCommand = new RelayCommand(CopySelectItems);
  32. PasteSelectItemsCommand = new RelayCommand(PasteSelectItems);
  33. DeleteSelectItemsCommand = new RelayCommand(DeleteSelectItems);
  34. SetTopLayerCommand = new RelayCommand(SetTopLayer);
  35. SetBottomLayerCommand = new RelayCommand(SetBottomLayer);
  36. SelectedItems = new ObservableCollection<FrameworkElement>();
  37. ContextMenu=Application.Current.Resources["CanvasRightMenu"] as ContextMenu;
  38. KeyDown += CanvasPanel_KeyDown;
  39. }
  40. #region 添加控件
  41. private void CanvasPanel_Drop(object sender, DragEventArgs e)
  42. {
  43. Type type = e.Data.GetData("System.RuntimeType") as Type;
  44. var t = type.GetCustomAttributes(typeof(ControlTypeAttribute), false);
  45. if (t.Length > 0)
  46. {
  47. Console.WriteLine((t as ControlTypeAttribute[])[0].Group);
  48. }
  49. try
  50. {
  51. var control = Activator.CreateInstance(type) as FrameworkElement;
  52. control.Name = GetControlName(type);
  53. Children.Add(control);
  54. var xPos = e.GetPosition(this).X;
  55. var yPos = e.GetPosition(this).Y;
  56. if (xPos % GridPxiel != 0)
  57. xPos = (GridPxiel - xPos % GridPxiel) + xPos;
  58. if (yPos % GridPxiel != 0)
  59. yPos = (GridPxiel - yPos % GridPxiel) + yPos;
  60. SetLeft(control, xPos);
  61. SetTop(control, yPos);
  62. SelectedItems = new ObservableCollection<FrameworkElement>() { control };
  63. SelectedItem = control;
  64. }
  65. catch (Exception)
  66. {
  67. }
  68. }
  69. string GetControlName(Type ctrlType)
  70. {
  71. var children = Children.GetEnumerator();
  72. children.Reset();
  73. List<string> names = new List<string>();
  74. while (children.MoveNext())
  75. {
  76. if (children.Current.GetType().Name == ctrlType.Name)
  77. {
  78. names.Add((children.Current as FrameworkElement).Name);
  79. }
  80. }
  81. var nameIndex = names.Count;
  82. while (names.Contains($"{ctrlType.Name.ToLower().Replace("the", string.Empty)}{nameIndex}"))
  83. {
  84. nameIndex++;
  85. }
  86. return $"{ctrlType.Name.ToLower().Replace("the", string.Empty)}{nameIndex}";
  87. }
  88. #endregion
  89. #region 初始化
  90. protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
  91. {
  92. if (visualAdded is Border || visualRemoved is Border)
  93. {
  94. return;
  95. }
  96. if (visualAdded is FrameworkElement ctrl)
  97. {
  98. ctrl.PreviewMouseLeftButtonDown += Ctrl_MouseLeftButtonDown;
  99. }
  100. if (visualRemoved is FrameworkElement ctr)
  101. {
  102. ctr.PreviewMouseLeftButtonDown -= Ctrl_MouseLeftButtonDown;
  103. }
  104. base.OnVisualChildrenChanged(visualAdded, visualRemoved);
  105. }
  106. #endregion
  107. #region 单击选中项处理
  108. /// <summary>
  109. /// 单击了控件时:不调用框选的刷新方式
  110. /// </summary>
  111. bool isClickedControl = false;
  112. /// <summary>
  113. /// 左键按下
  114. /// </summary>
  115. /// <param name="sender"></param>
  116. /// <param name="e"></param>
  117. private void Ctrl_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
  118. {
  119. if (sender is FrameworkElement ctl)
  120. {
  121. var cp = GetParentObject<CanvasPanel>(ctl);
  122. if (Keyboard.Modifiers == ModifierKeys.Control)
  123. {
  124. cp.SelectedItems.Add(ctl);
  125. }
  126. else
  127. {
  128. cp.SelectedItems = new ObservableCollection<FrameworkElement>() { ctl };
  129. }
  130. isClickedControl = true;
  131. RefreshSelection();
  132. }
  133. }
  134. /// <summary>
  135. /// 获取属性
  136. /// </summary>
  137. /// <typeparam name="T"></typeparam>
  138. /// <param name="obj"></param>
  139. /// <returns></returns>
  140. public static T GetParentObject<T>(DependencyObject obj) where T : FrameworkElement
  141. {
  142. DependencyObject parent = VisualTreeHelper.GetParent(obj);
  143. while (parent != null)
  144. {
  145. if (parent is T)
  146. {
  147. return (T)parent;
  148. }
  149. parent = VisualTreeHelper.GetParent(parent);
  150. }
  151. return null;
  152. }
  153. #endregion
  154. #region 右键菜单
  155. #endregion
  156. #region 绘制选择框
  157. Border selectionBorder = new Border()
  158. {
  159. Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#557F7F7F")),
  160. BorderThickness = new Thickness(1),
  161. BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF303030")),
  162. };
  163. protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
  164. {
  165. base.OnMouseLeftButtonDown(e);
  166. selectionStart = e.GetPosition(this);
  167. if (!this.Children.Contains(selectionBorder))
  168. {
  169. this.Children.Add(selectionBorder);
  170. this.CaptureMouse();
  171. }
  172. }
  173. Point selectionStart = default;
  174. protected override void OnMouseMove(MouseEventArgs e)
  175. {
  176. if (isClickedControl)
  177. {
  178. return;
  179. }
  180. base.OnMouseMove(e);
  181. if (e.LeftButton == MouseButtonState.Pressed)
  182. {
  183. var nowPoint = e.GetPosition(this);
  184. var offsetX = nowPoint.X - selectionStart.X;
  185. var offsetY = nowPoint.Y - selectionStart.Y;
  186. Clear();
  187. selectionBorder.Width = Math.Abs(offsetX);
  188. selectionBorder.Height = Math.Abs(offsetY);
  189. // 分四种情况绘制
  190. if (offsetX >= 0 && offsetY >= 0)// 右下
  191. {
  192. SetLeft(selectionBorder, selectionStart.X);
  193. SetTop(selectionBorder, selectionStart.Y);
  194. }
  195. else if (offsetX > 0 && offsetY < 0)// 右上
  196. {
  197. SetLeft(selectionBorder, selectionStart.X);
  198. SetBottom(selectionBorder, ActualHeight - selectionStart.Y);
  199. }
  200. else if (offsetX < 0 && offsetY > 0)// 左下
  201. {
  202. SetRight(selectionBorder, ActualWidth - selectionStart.X);
  203. SetTop(selectionBorder, selectionStart.Y);
  204. }
  205. else if (offsetX < 0 && offsetY < 0)// 左上
  206. {
  207. SetRight(selectionBorder, ActualWidth - selectionStart.X);
  208. SetBottom(selectionBorder, ActualHeight - selectionStart.Y);
  209. }
  210. }
  211. }
  212. protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
  213. {
  214. base.OnMouseLeftButtonUp(e);
  215. if (double.IsNaN(GetLeft(selectionBorder)))
  216. {
  217. SetLeft(selectionBorder, ActualWidth - GetRight(selectionBorder) - selectionBorder.ActualWidth);
  218. }
  219. if (double.IsNaN(GetTop(selectionBorder)))
  220. {
  221. SetTop(selectionBorder, ActualHeight - GetBottom(selectionBorder) - selectionBorder.ActualHeight);
  222. }
  223. FrameSelection(GetLeft(selectionBorder), GetTop(selectionBorder), selectionBorder.Width, selectionBorder.Height);
  224. selectionBorder.Width = 0;
  225. selectionBorder.Height = 0;
  226. this.Children.Remove(selectionBorder);
  227. this.ReleaseMouseCapture();
  228. }
  229. private void Clear()
  230. {
  231. SetLeft(selectionBorder, double.NaN);
  232. SetRight(selectionBorder, double.NaN);
  233. SetTop(selectionBorder, double.NaN);
  234. SetBottom(selectionBorder, double.NaN);
  235. }
  236. #endregion
  237. #region 选中属性
  238. public FrameworkElement SelectedItem
  239. {
  240. get { return (FrameworkElement)GetValue(SelectedItemProperty); }
  241. set { SetValue(SelectedItemProperty, value); }
  242. }
  243. public static readonly DependencyProperty SelectedItemProperty =
  244. DependencyProperty.Register("SelectedItem", typeof(FrameworkElement), typeof(CanvasPanel), new PropertyMetadata(null, OnSelectedItemChanged));
  245. private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as CanvasPanel)?.RefreshSelection1();
  246. public void RefreshSelection1()
  247. {
  248. }
  249. #endregion
  250. #region 框选
  251. public ObservableCollection<FrameworkElement> SelectedItems
  252. {
  253. get { return (ObservableCollection<FrameworkElement>)GetValue(SelectedItemsProperty); }
  254. set { SetValue(SelectedItemsProperty, value); }
  255. }
  256. public static readonly DependencyProperty SelectedItemsProperty =
  257. DependencyProperty.Register("SelectedItems", typeof(ObservableCollection<FrameworkElement>), typeof(CanvasPanel), new PropertyMetadata(null, OnSelectedItemsChanged));
  258. private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as CanvasPanel)?.RefreshSelection();
  259. public void RefreshSelection()
  260. {
  261. foreach (var item in Children)
  262. {
  263. if (!(item is IExecutable))
  264. continue;
  265. var ele = item as FrameworkElement;
  266. if (ele == null) continue;
  267. var layer = AdornerLayer.GetAdornerLayer(ele);
  268. var arr = layer.GetAdorners(ele);//获取该控件上所有装饰器,返回一个数组
  269. if (arr != null)
  270. {
  271. for (int i = arr.Length - 1; i >= 0; i--)
  272. {
  273. layer.Remove(arr[i]);
  274. }
  275. }
  276. }
  277. if (SelectedItems != null)
  278. {
  279. foreach (var item in SelectedItems)
  280. {
  281. var layer = AdornerLayer.GetAdornerLayer(item);
  282. layer.Add(new SelectionAdorner(item));
  283. SelectedItem = item;
  284. }
  285. }
  286. }
  287. /// <summary>
  288. /// 移除所有选择装饰器
  289. /// </summary>
  290. public void ClearSelection()
  291. {
  292. foreach (var item in Children)
  293. {
  294. if (!(item is IExecutable))
  295. continue;
  296. var ele = item as FrameworkElement;
  297. if (ele == null) continue;
  298. var layer = AdornerLayer.GetAdornerLayer(ele);
  299. var arr = layer.GetAdorners(ele);//获取该控件上所有装饰器,返回一个数组
  300. if (arr != null)
  301. {
  302. for (int i = arr.Length - 1; i >= 0; i--)
  303. {
  304. layer.Remove(arr[i]);
  305. }
  306. }
  307. }
  308. }
  309. /// <summary>
  310. /// 计算框选项
  311. /// </summary>
  312. private void FrameSelection(double x, double y, double width, double height)
  313. {
  314. if (width > 0 || height > 0)
  315. {
  316. isClickedControl = false;
  317. }
  318. if (isClickedControl)
  319. {
  320. isClickedControl = false;
  321. SelectedItems = new ObservableCollection<FrameworkElement>();
  322. return;
  323. }
  324. SelectedItems = new ObservableCollection<FrameworkElement>();
  325. foreach (var item in Children)
  326. {
  327. if (item is FrameworkElement ctrl && !(ctrl is Border))
  328. {
  329. // 框左上角
  330. var left = GetLeft(ctrl);
  331. var top = GetTop(ctrl);
  332. if (left >= x && left <= x + width && top >= y && top <= y + height)
  333. {
  334. if (!SelectedItems.Contains(ctrl))
  335. SelectedItems.Add(ctrl);
  336. }
  337. // 框右下角
  338. var right = left + ctrl.ActualWidth;
  339. var bottom = top + ctrl.ActualHeight;
  340. if (right >= x && right <= x + width && bottom >= y && bottom <= y + height)
  341. {
  342. if (!SelectedItems.Contains(ctrl))
  343. SelectedItems.Add(ctrl);
  344. }
  345. // 框右上角
  346. if (right >= x && right <= x + width && top >= y && top <= y + height)
  347. {
  348. if (!SelectedItems.Contains(ctrl))
  349. SelectedItems.Add(ctrl);
  350. }
  351. // 框左下角
  352. if (left >= x && left <= x + width && bottom >= y && bottom <= y + height)
  353. {
  354. if (!SelectedItems.Contains(ctrl))
  355. SelectedItems.Add(ctrl);
  356. }
  357. }
  358. }
  359. RefreshSelection();
  360. }
  361. #endregion
  362. #region 外部调用
  363. public List<FrameworkElement> GetAllExecChildren()
  364. {
  365. List<FrameworkElement> result = new List<FrameworkElement>();
  366. foreach (var ctrl in Children)
  367. {
  368. if (ctrl is IExecutable exec)
  369. {
  370. result.Add(ctrl as FrameworkElement);
  371. }
  372. }
  373. return result;
  374. }
  375. /// <summary>
  376. /// 对齐像素单位
  377. /// </summary>
  378. public int GridPxiel
  379. {
  380. get { return (int)GetValue(GridPxielProperty); }
  381. set { SetValue(GridPxielProperty, value); }
  382. }
  383. public static readonly DependencyProperty GridPxielProperty =
  384. DependencyProperty.Register("GridPxiel", typeof(int), typeof(CanvasPanel), new PropertyMetadata(4));
  385. public void MoveControls(double offsetX, double offsetY)
  386. {
  387. ClearAlignLine();
  388. // 获取可对齐的点
  389. List<Point> points = new List<Point>();
  390. foreach (FrameworkElement ctrl in Children)
  391. {
  392. if (!SelectedItems.Contains(ctrl))
  393. {
  394. // 左上的点
  395. Point item = new Point(GetLeft(ctrl), GetTop(ctrl));
  396. points.Add(item);
  397. // 左下的点
  398. Point itemlb = new Point(GetLeft(ctrl), GetTop(ctrl) + ctrl.ActualHeight);
  399. points.Add(itemlb);
  400. // 右下的点
  401. Point itemrb = new Point(GetLeft(ctrl) + ctrl.ActualWidth, GetTop(ctrl) + ctrl.ActualHeight);
  402. points.Add(itemrb);
  403. // 右上的点
  404. Point itemrt = new Point(GetLeft(ctrl) + ctrl.ActualWidth, GetTop(ctrl));
  405. points.Add(itemrt);
  406. }
  407. }
  408. // 控件移动
  409. foreach (var item in SelectedItems)
  410. {
  411. var moveX = GetLeft(item) + offsetX;
  412. moveX = (moveX < 0) ? 0 : moveX;
  413. var moveY = GetTop(item) + offsetY;
  414. moveY = moveY < 0 ? 0 : moveY;
  415. if (moveX % GridPxiel != 0)
  416. moveX = (GridPxiel - moveX % GridPxiel) + moveX;
  417. if (moveY % GridPxiel != 0)
  418. moveY = (GridPxiel - moveY % GridPxiel) + moveY;
  419. SetLeft(item, moveX);
  420. SetTop(item, moveY);
  421. }
  422. // 计算是否显示对齐线
  423. var targetItemTop = SelectedItems?.Min(x => GetTop(x));
  424. var targetItem = SelectedItems.FirstOrDefault(x => GetTop(x) == targetItemTop);
  425. var lefAlign = points.FirstOrDefault(x => Math.Abs(x.X - GetLeft(targetItem)) == 0);
  426. if (lefAlign != default)
  427. {
  428. //SetLeft(targetItem, lefAlign.X);
  429. var layer = AdornerLayer.GetAdornerLayer(this);
  430. layer.Add(new SelectionAlignLine(this, lefAlign, new Point(GetLeft(targetItem), GetTop(targetItem))));
  431. }
  432. var topAlign = points.FirstOrDefault(x => Math.Abs(x.Y - GetTop(targetItem)) == 0);
  433. if (topAlign != default)
  434. {
  435. //SetTop(targetItem, topAlign.Y);
  436. var layer = AdornerLayer.GetAdornerLayer(this);
  437. layer.Add(new SelectionAlignLine(this, topAlign, new Point(GetLeft(targetItem), GetTop(targetItem))));
  438. }
  439. int px = 20;
  440. // 网格对齐
  441. if (UseAutoAlignment)
  442. {
  443. foreach (var item in SelectedItems)
  444. {
  445. var left = GetLeft(item);
  446. if (left % px <= 1)
  447. {
  448. SetLeft(item, (int)left / px * px);
  449. }
  450. var top = GetTop(item);
  451. if (top % px <= 1)
  452. {
  453. SetTop(item, (int)top / px * px);
  454. }
  455. }
  456. }
  457. }
  458. /// <summary>
  459. /// 清除绘制的对齐线
  460. /// </summary>
  461. public void ClearAlignLine()
  462. {
  463. var arr = AdornerLayer.GetAdornerLayer(this).GetAdorners(this);
  464. if (arr != null)
  465. {
  466. for (int i = arr.Length - 1; i >= 0; i--)
  467. {
  468. AdornerLayer.GetAdornerLayer(this).Remove(arr[i]);
  469. }
  470. }
  471. }
  472. public void ZoomControls(int offsetX, int offsetY)
  473. {
  474. foreach (var item in SelectedItems)
  475. {
  476. if (item.ActualHeight + offsetY > 10)
  477. {
  478. item.Height += offsetY;
  479. }
  480. if (item.ActualWidth + offsetX > 10)
  481. {
  482. item.Width += offsetX;
  483. }
  484. }
  485. }
  486. /// <summary>
  487. /// 调整控件大小:鼠标在控件中的不同位置,调整控件大小
  488. /// </summary>
  489. public void ReCtrlSize(Point lastPoint,Point currentPoint, MousePos mousePos)
  490. {
  491. foreach (var control in SelectedItems)
  492. {
  493. //计算偏移量
  494. double x = currentPoint.X - lastPoint.X;
  495. double y = currentPoint.Y - lastPoint.Y;
  496. switch (mousePos)
  497. {
  498. case MousePos.None:
  499. break;
  500. case MousePos.Top://上,调整
  501. if (control.Height - y > control.MinHeight)
  502. {
  503. SetTop(control, GetTop(control) + y);
  504. //control.Top += y;
  505. control.Height -= y;
  506. }
  507. break;
  508. case MousePos.Right:
  509. if (control.Width + x > control.MinWidth)
  510. {
  511. control.Width += x;
  512. }
  513. break;
  514. case MousePos.Bottom:
  515. if (control.Height + y > control.MinHeight)
  516. {
  517. control.Height += y;
  518. }
  519. break;
  520. case MousePos.Left:
  521. if (control.Width - x > control.MinWidth)
  522. {
  523. SetLeft(control, GetLeft(control) + x);//control.Left += x;
  524. control.Width -= x;
  525. }
  526. break;
  527. case MousePos.LeftTop://左上
  528. if (control.Width - x > control.MinWidth)
  529. {
  530. SetLeft(control, GetLeft(control) + x);//control.Left += x;
  531. control.Width -= x;
  532. }
  533. if (control.Height - y > control.MinHeight)
  534. {
  535. SetTop(control, GetTop(control) + y);//control.Top += y;
  536. control.Height -= y;
  537. }
  538. break;
  539. case MousePos.LeftBottom:
  540. if (control.Width - x > control.MinWidth)
  541. {
  542. SetLeft(control, GetLeft(control) + x);//control.Left += x;
  543. control.Width -= x;
  544. }
  545. if (control.Height + y > control.MinHeight)
  546. {
  547. control.Height += y;
  548. }
  549. break;
  550. case MousePos.RightTop:
  551. if (control.Width + x > MinWidth)
  552. {
  553. control.Width += x;
  554. }
  555. if (control.Height - y > MinHeight)
  556. {
  557. SetTop(control, GetTop(control) + y);//control.Top += y;
  558. control.Height -= y;
  559. }
  560. break;
  561. case MousePos.RightBottom:
  562. if (control.Width + x > MinWidth)
  563. {
  564. control.Width += x;
  565. }
  566. if (control.Height + y > MinHeight)
  567. {
  568. control.Height += y;
  569. }
  570. break;
  571. default:
  572. break;
  573. }
  574. }
  575. }
  576. #endregion
  577. #region 对齐操作
  578. /// <summary>
  579. /// 是否使用网格对齐 10px
  580. /// </summary>
  581. public bool UseAutoAlignment
  582. {
  583. get { return (bool)GetValue(UseAutoAlignmentProperty); }
  584. set { SetValue(UseAutoAlignmentProperty, value); }
  585. }
  586. public static readonly DependencyProperty UseAutoAlignmentProperty =
  587. DependencyProperty.Register("UseAutoAlignment", typeof(bool), typeof(CanvasPanel), new PropertyMetadata(false));
  588. public void AlignLeft()
  589. {
  590. if (SelectedItems == null || SelectedItems.Count == 0)
  591. return;
  592. var leftMin = SelectedItems.Min(x => Canvas.GetLeft(x));
  593. foreach (var item in SelectedItems)
  594. {
  595. SetLeft(item, leftMin);
  596. }
  597. }
  598. public void AlignRight()
  599. {
  600. if (SelectedItems == null || SelectedItems.Count == 0)
  601. return;
  602. var rightMax = SelectedItems.Max(x => GetLeft(x) + x.ActualWidth);
  603. foreach (var item in SelectedItems)
  604. {
  605. var targetLeft = rightMax - item.ActualWidth;
  606. SetLeft(item, targetLeft);
  607. }
  608. }
  609. public void AlignCenter()
  610. {
  611. if (SelectedItems == null || SelectedItems.Count == 0)
  612. return;
  613. var leftmin = SelectedItems.Min(x => GetLeft(x));
  614. var rightmax = SelectedItems.Max(x => GetLeft(x) + x.ActualWidth);
  615. var center = (rightmax - leftmin) / 2 + leftmin;
  616. foreach (var item in SelectedItems)
  617. {
  618. var target = center - (item.ActualWidth / 2);
  619. SetLeft(item, target);
  620. }
  621. }
  622. public void AlignTop()
  623. {
  624. if (SelectedItems == null || SelectedItems.Count == 0)
  625. return;
  626. var topMin = SelectedItems.Min(x => GetTop(x));
  627. foreach (var item in SelectedItems)
  628. {
  629. SetTop(item, topMin);
  630. }
  631. }
  632. public void AlignBottom()
  633. {
  634. if (SelectedItems == null || SelectedItems.Count == 0)
  635. return;
  636. var botMax = SelectedItems.Max(x => GetTop(x) + x.ActualHeight);
  637. foreach (var item in SelectedItems)
  638. {
  639. var targetLeft = botMax - item.ActualHeight;
  640. SetTop(item, targetLeft);
  641. }
  642. }
  643. public void VertialLayout()
  644. {
  645. if (SelectedItems == null || SelectedItems.Count < 3)
  646. return;
  647. var topCtl = SelectedItems.Min(x => GetTop(x) + x.ActualHeight);
  648. var botCtrl = SelectedItems.Max(x => GetTop(x));
  649. var emptyHeight = botCtrl - topCtl;
  650. var orderCtrl = SelectedItems.OrderBy(x => GetTop(x)).ToList();
  651. orderCtrl.RemoveAt(0);
  652. orderCtrl.RemoveAt(orderCtrl.Count - 1);
  653. var useSpace = orderCtrl.Sum(x => x.ActualHeight);
  654. var ableSpaceAvg = (emptyHeight - useSpace) / (SelectedItems.Count - 1);
  655. double nowPostion = topCtl;
  656. foreach (var item in orderCtrl)
  657. {
  658. SetTop(item, nowPostion + ableSpaceAvg);
  659. nowPostion += item.ActualHeight + ableSpaceAvg;
  660. }
  661. }
  662. public void HorizontalLayout()
  663. {
  664. if (SelectedItems == null || SelectedItems.Count < 3)
  665. return;
  666. var leftCtl = SelectedItems.Min(x => GetLeft(x) + x.ActualWidth);
  667. var rightCtrl = SelectedItems.Max(x => GetLeft(x));
  668. var emptyHeight = rightCtrl - leftCtl;
  669. var orderCtrl = SelectedItems.OrderBy(x => GetLeft(x)).ToList();
  670. orderCtrl.RemoveAt(0);
  671. orderCtrl.RemoveAt(orderCtrl.Count - 1);
  672. var useSpace = orderCtrl.Sum(x => x.ActualWidth);
  673. var ableSpaceAvg = (emptyHeight - useSpace) / (SelectedItems.Count - 1);
  674. double nowPostion = leftCtl;
  675. foreach (var item in orderCtrl)
  676. {
  677. SetLeft(item, nowPostion + ableSpaceAvg);
  678. nowPostion += item.ActualWidth + ableSpaceAvg;
  679. }
  680. }
  681. #endregion
  682. #region 按键操作
  683. public RelayCommand CopySelectItemsCommand { get; set; }
  684. public RelayCommand PasteSelectItemsCommand { get; set; }
  685. public RelayCommand DeleteSelectItemsCommand { get; set; }
  686. public RelayCommand SetTopLayerCommand { get; set; }
  687. public RelayCommand SetBottomLayerCommand { get; set; }
  688. List<FrameworkElement> copyTemp = new List<FrameworkElement>();
  689. private void CanvasPanel_KeyDown(object sender, KeyEventArgs e)
  690. {
  691. if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)
  692. {
  693. CopySelectItems();
  694. }
  695. else if (e.Key == Key.V && Keyboard.Modifiers == ModifierKeys.Control)
  696. {
  697. PasteSelectItems();
  698. }
  699. else if (e.Key == Key.Delete)
  700. {
  701. DeleteSelectItems();
  702. }
  703. else if (e.Key == Key.Up)
  704. {
  705. var offset = -1;
  706. foreach (var item in SelectedItems)
  707. {
  708. SetTop(item, (GetTop(item) + offset) < 0 ? 0 : GetTop(item) + offset);
  709. }
  710. e.Handled = true;
  711. }
  712. else if (e.Key == Key.Down)
  713. {
  714. var offset = 1;
  715. foreach (var item in SelectedItems)
  716. {
  717. SetTop(item, (GetTop(item) + offset) < 0 ? 0 : GetTop(item) + offset);
  718. }
  719. e.Handled = true;
  720. }
  721. else if (e.Key == Key.Left)
  722. {
  723. var offset = -1;
  724. foreach (var item in SelectedItems)
  725. {
  726. SetLeft(item, (GetLeft(item) + offset) < 0 ? 0 : GetLeft(item) + offset);
  727. }
  728. e.Handled = true;
  729. }
  730. else if (e.Key == Key.Right)
  731. {
  732. var offset = 1;
  733. foreach (var item in SelectedItems)
  734. {
  735. SetLeft(item, (GetLeft(item) + offset) < 0 ? 0 : GetLeft(item) + offset);
  736. }
  737. e.Handled = true;
  738. }
  739. }
  740. /// <summary>
  741. /// 复制
  742. /// </summary>
  743. public void CopySelectItems()
  744. {
  745. copyTemp.Clear();
  746. foreach (var item in SelectedItems)
  747. {
  748. copyTemp.Add(item);
  749. }
  750. }
  751. /// <summary>
  752. /// 粘贴
  753. /// </summary>
  754. public void PasteSelectItems()
  755. {
  756. SelectedItems.Clear();
  757. foreach (var item in copyTemp)
  758. {
  759. var xml = XamlWriter.Save(item);
  760. var element = XamlReader.Parse(xml) as FrameworkElement;
  761. element.Name += "_1";
  762. SetLeft(element, GetLeft(element) + 10);
  763. SetTop(element, GetTop(element) + 10);
  764. Children.Add(element);
  765. SelectedItems.Add(element);
  766. }
  767. // 将复制的内容替换 以便处理连续复制
  768. copyTemp.Clear();
  769. foreach (var item in SelectedItems)
  770. {
  771. copyTemp.Add(item);
  772. }
  773. RefreshSelection();
  774. }
  775. /// <summary>
  776. /// 置于顶层
  777. /// </summary>
  778. public void SetTopLayer()
  779. {
  780. if (SelectedItems.Count == 0)
  781. return;
  782. foreach (var item in SelectedItems)
  783. {
  784. Children.Remove(item);
  785. }
  786. foreach (var item in SelectedItems)
  787. {
  788. Children.Add(item);
  789. }
  790. }
  791. /// <summary>
  792. /// 置于底层
  793. /// </summary>
  794. public void SetBottomLayer()
  795. {
  796. if (SelectedItems.Count == 0)
  797. return;
  798. foreach (var item in SelectedItems)
  799. {
  800. Children.Remove(item);
  801. }
  802. foreach (var item in SelectedItems)
  803. {
  804. Children.Insert(0, item);
  805. }
  806. }
  807. /// <summary>
  808. /// 删除
  809. /// </summary>
  810. public void DeleteSelectItems()
  811. {
  812. foreach (var item in SelectedItems)
  813. {
  814. Children.Remove(item);
  815. }
  816. SelectedItems.Clear();
  817. RefreshSelection();
  818. }
  819. #endregion
  820. #region 运行Xaml 保存 读取
  821. public List<FrameworkElement> Generator()
  822. {
  823. List<FrameworkElement> elements = new List<FrameworkElement>();
  824. foreach (var item in Children)
  825. {
  826. // 排除非自定义的控件们
  827. if (!(item is IExecutable))
  828. continue;
  829. var xml = XamlWriter.Save(item);
  830. var ele = XamlReader.Parse(xml) as FrameworkElement;
  831. elements.Add(ele);
  832. }
  833. return elements;
  834. }
  835. /// <summary>
  836. /// 保存数据到文本
  837. /// </summary>
  838. public string Save()
  839. {
  840. StringBuilder sb = new StringBuilder();
  841. foreach (var item in Children)
  842. {
  843. var xml = XamlWriter.Save(item);
  844. sb.Append(xml + "\r\n");
  845. }
  846. return sb.ToString();
  847. }
  848. /// <summary>
  849. /// 读取文件
  850. /// </summary>
  851. public void Load(string path)
  852. {
  853. Children.Clear();
  854. FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  855. using (StreamReader sr = new StreamReader(fs, System.Text.Encoding.Unicode))
  856. {
  857. while (sr.Peek() > -1)
  858. {
  859. string str = sr.ReadLine();
  860. //if (!str.Contains("NewConveyorBelt"))
  861. {
  862. try
  863. {
  864. var ele = XamlReader.Parse(str) as FrameworkElement;
  865. Children.Add(ele);
  866. }
  867. catch (Exception ex)
  868. {
  869. }
  870. }
  871. }
  872. }
  873. SelectedItems?.Clear();
  874. }
  875. #endregion
  876. }
  877. }