/// <summary> /// 当鼠标移动到图形上的时候,画Handle /// </summary> /// <param name="cursorPosition">鼠标坐标的位置</param> /// <returns>返回鼠标移动到的图形</returns> private VisualGraphics DrawHandleWhenMouseOverVisual <ExcludedVisual>(Point cursorPosition) where ExcludedVisual : VisualGraphics { if (this.previouseHoveredVisual != null) { this.previouseHoveredVisual.IsDrawHandle = false; this.previouseHoveredVisual.Render(); this.previouseHoveredVisual = null; } VisualGraphics visualHit = this.HitTestFirstVisual <ExcludedVisual>(cursorPosition); if (visualHit == null) { //if (this.previouseHoveredVisual != null) //{ // this.previouseHoveredVisual.IsDrawHandle = false; // this.previouseHoveredVisual.Render(); // this.previouseHoveredVisual = null; //} } else { this.previouseHoveredVisual = visualHit; this.previouseHoveredVisual.IsDrawHandle = true; this.previouseHoveredVisual.Render(); } return(visualHit); }
private void ProcessSelectedVisualCursor(VisualGraphics selectedVisual, Point cursorPosition) { if (selectedVisual == null) { this.Cursor = Cursors.Arrow; return; } for (int i = 0; i < selectedVisual.ConnectionHandles; i++) { Rect boundary = selectedVisual.GetConnectorBounds(i); if (boundary.Contains(cursorPosition)) { this.Cursor = Cursors.Cross; return; } } for (int i = 0; i < selectedVisual.ResizeHandles; i++) { Rect boundary = selectedVisual.GetResizeHandleBounds(i); if (boundary.Contains(cursorPosition)) { this.Cursor = Cursors.Hand; return; } } this.Cursor = Cursors.Arrow; }
public VisualGraphics DrawVisual(GraphicsBase graphics) { VisualGraphics visual = VisualFactory.Create(graphics); this.VisualList.Add(visual); this.AddVisualChild(visual); // 该函数只会把DrawableVisual和DrawableVisualLayer关联起来,在渲染的时候并不会真正渲染。关联的目的是为了做命中测试(HitTest)。 visual.Render(); return(visual); }
/// <summary> /// 检测第一个被鼠标命中的元素 /// </summary> /// <typeparam name="TExcluded">要排除在外的鼠标命中的元素的类型</typeparam> /// <param name="hitTestPos">鼠标坐标位置</param> /// <returns>第一个被鼠标命中的元素</returns> private VisualGraphics HitTestFirstVisual <TExcluded>(Point hitTestPos) where TExcluded : VisualGraphics { VisualTreeHelper.HitTest(this, null, this.HitTestResultCallback <TExcluded>, new PointHitTestParameters(hitTestPos)); if (this.visualHits.Count == 0) { return(null); } // 被点击到的元素 VisualGraphics visualHit = this.visualHits[0] as VisualGraphics; this.visualHits.Clear(); return(visualHit); }
/// <summary> /// 保存图形里输入的文本 /// </summary> private void StopVisualInputState(VisualGraphics visual) { if (this.visualState != Visuals.VisualState.InputState) { return; } if (visual == null) { return; } visual.Graphics.TextProperties.Text = this.TextBoxEditor.Text; visual.Render(); // 刷新文本信息 this.TextBoxEditor.Text = null; this.TextBoxEditor.Visibility = Visibility.Collapsed; }
/// <summary> /// 让一个图形进入编辑状态 /// </summary> /// <param name="visual"></param> private void StartVisualInputState(VisualGraphics visual) { if (visual == null) { logger.WarnFormat("要编辑的图形为空"); return; } Rect bounds = visual.GetTextBounds(); this.TextBoxEditor.Width = bounds.Width; this.TextBoxEditor.Height = bounds.Height; Canvas.SetLeft(this.TextBoxEditor, bounds.TopLeft.X); Canvas.SetTop(this.TextBoxEditor, bounds.TopLeft.Y); this.TextBoxEditor.Text = visual.Graphics.TextProperties.Text; this.TextBoxEditor.Visibility = Visibility.Visible; this.TextBoxEditor.Focus(); }
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); Point cursorPosition = e.GetPosition(this); switch (this.visualState) { case Visuals.VisualState.Translate: { this.visualState = Visuals.VisualState.Idle; this.translateVisual = null; this.associatedPolylines = null; break; } case Visuals.VisualState.Idle: { break; } case Visuals.VisualState.Connecting: { this.visualState = Visuals.VisualState.Idle; this.firstVisual = null; this.secondVisual = null; break; } case Visuals.VisualState.Resizing: { this.visualState = Visuals.VisualState.Idle; break; } case Visuals.VisualState.InputState: { break; } default: throw new NotImplementedException(); } }
/// <summary> /// 当前选中的Visual改变的时候被调用 /// 保证previouseSelected和selectedVisual都不为空 /// </summary> /// <param name="previouseSelected"></param> /// <param name="selectedVisual"></param> private void ProcessSelectedVisualChanged(VisualGraphics previouseSelected, VisualGraphics selectedVisual) { if (previouseSelected == selectedVisual) { return; } if (previouseSelected != null) { if (previouseSelected != selectedVisual) { previouseSelected.IsSelected = false; previouseSelected.Render(); selectedVisual.IsSelected = true; selectedVisual.Render(); } } else { selectedVisual.IsSelected = true; selectedVisual.Render(); } }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); Point cursorPosition = e.GetPosition(this); switch (this.visualState) { case Visuals.VisualState.Idle: { VisualGraphics visualHit = this.DrawHandleWhenMouseOverVisual <VisualPolyline>(cursorPosition); // 处理鼠标状态 this.ProcessSelectedVisualCursor(visualHit, cursorPosition); break; } case Visuals.VisualState.Translate: { double x = cursorPosition.X - this.previousPosition.X; double y = cursorPosition.Y - this.previousPosition.Y; this.translateVisual.Translate(x, y); foreach (GraphicsPolyline polyline in this.associatedPolylines) { List <Point> pointList = null; if (this.translateVisual.ID == polyline.AssociatedGraphics1) { // 移动的图形是第一个图形 Point firstConnector = this.translateVisual.GetConnectorPoint(polyline.Graphics1Handle); ConnectionLocations firstConnectorLocation = this.translateVisual.GetConnectorLocation(polyline.Graphics1Handle); Point secondConnector = polyline.PointList.LastOrDefault(); if (string.IsNullOrEmpty(polyline.AssociatedGraphics2)) { // 连接点的另一端不在图形上 pointList = GraphicsUtility.MakeConnectionPath(firstConnector, firstConnectorLocation, secondConnector); } else { // 连接点的另一端在图形上 VisualGraphics secondVisual = this.VisualList.FirstOrDefault(v => v.ID == polyline.AssociatedGraphics2); ConnectionLocations secondConnectorLocation = secondVisual.Graphics.GetConnectorLocation(polyline.Graphics2Handle); pointList = GraphicsUtility.MakeConnectionPath(firstConnector, firstConnectorLocation, secondConnector, secondConnectorLocation); } } else if (this.translateVisual.ID == polyline.AssociatedGraphics2) { // 移动的图形是第二个图形 Point secondConnector = this.translateVisual.GetConnectorPoint(polyline.Graphics2Handle); ConnectionLocations secondConnectorLocation = this.translateVisual.GetConnectorLocation(polyline.Graphics2Handle); Point firstConnector = polyline.PointList.FirstOrDefault(); if (string.IsNullOrEmpty(polyline.AssociatedGraphics1)) { // 连接点的另一端不在图形上 // 规定必须在图形上,不允许只有第二个点在图形上,而第一个点不在。但是允许第一个点在图形上,第二个点不在 pointList = GraphicsUtility.MakeConnectionPath(secondConnector, secondConnectorLocation, firstConnector); pointList.Reverse(); } else { // 连接点的另一端在图形上 VisualGraphics firstVisual = this.VisualList.FirstOrDefault(v => v.ID == polyline.AssociatedGraphics1); ConnectionLocations firstConnectorLocation = firstVisual.Graphics.GetConnectorLocation(polyline.Graphics1Handle); pointList = GraphicsUtility.MakeConnectionPath(firstConnector, firstConnectorLocation, secondConnector, secondConnectorLocation); } } else { throw new NotImplementedException(); } VisualPolyline visualPolyline = this.VisualList.OfType <VisualPolyline>().FirstOrDefault(v => v.ID == polyline.ID); visualPolyline.Update(pointList); } this.previousPosition = cursorPosition; break; } case Visuals.VisualState.Connecting: { GraphicsPolyline graphicsPolyline = this.polyline.Graphics as GraphicsPolyline; Point secondConnector = cursorPosition; // 检测鼠标是否在某个图形上面 VisualGraphics visualHit = this.DrawHandleWhenMouseOverVisual <VisualPolyline>(cursorPosition); if (visualHit == null || visualHit == this.firstVisual) { this.secondVisual = null; graphicsPolyline.AssociatedGraphics2 = null; // 更新连接线 List <Point> points = GraphicsUtility.MakeConnectionPath(this.firstConnector, this.firstConnectorLocation, secondConnector); this.polyline.Update(points); } else { // 如果当前鼠标下的元素和选中的是不同一个元素,那么就表示有连接的元素了 // 运行到此处说明两个图形被连接起来了 this.secondVisual = visualHit; // 运行到这里说明折线的另一端已经在图形的连接点范围内了 int handle; Point handlePoint; ConnectionLocations secondConnectorLocation; if (this.secondVisual.Graphics.GetNearestConnectorHandle(cursorPosition, out handle, out handlePoint, out secondConnectorLocation)) { secondConnector = handlePoint; graphicsPolyline.AssociatedGraphics2 = this.secondVisual.ID; graphicsPolyline.Graphics2Handle = handle; // 更新连接线 List <Point> points = GraphicsUtility.MakeConnectionPath(this.firstConnector, this.firstConnectorLocation, secondConnector, secondConnectorLocation); this.polyline.Update(points); } else { // 鼠标已经在第二个图形上了,但是没有放在连接点附近 List <Point> points = GraphicsUtility.MakeConnectionPath(this.firstConnector, this.firstConnectorLocation, secondConnector); this.polyline.Update(points); } } break; } case Visuals.VisualState.Resizing: { this.selectedVisual.Resize(this.resizeLocation, this.resizeCenter, cursorPosition); break; } case Visuals.VisualState.InputState: { break; } default: throw new NotImplementedException(); } }
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); this.previouseSelectedVisual = this.selectedVisual; Point cursorPosition = e.GetPosition(this); VisualGraphics visualHit = this.HitTestFirstVisual <ExcludedNullVisual>(cursorPosition); if (visualHit == null) { if (this.selectedVisual != null) { this.selectedVisual.IsSelected = false; this.selectedVisual.IsDrawHandle = false; this.selectedVisual.Render(); this.selectedVisual = null; } // 停止编辑状态 this.StopVisualInputState(this.previouseSelectedVisual); TextBoxEditor.Visibility = Visibility.Collapsed; // 重置到空闲状态 this.visualState = Visuals.VisualState.Idle; return; } this.ProcessSelectedVisualChanged(this.selectedVisual, visualHit); this.selectedVisual = visualHit; this.previousPosition = cursorPosition; if (e.ClickCount == 2) { // 双击图形,那么进入编辑状态 this.visualState = Visuals.VisualState.InputState; this.StartVisualInputState(this.selectedVisual); } else { this.StopVisualInputState(this.previouseSelectedVisual); #region 判断是否点击了连接点 for (int i = 0; i < visualHit.ConnectionHandles; i++) { Rect bounds = visualHit.GetConnectorBounds(i); if (bounds.Contains(cursorPosition)) { Point center = bounds.GetCenter(); ConnectionLocations location = visualHit.GetConnectorLocation(i); this.visualState = Visuals.VisualState.Connecting; GraphicsPolyline graphics = new GraphicsPolyline() { AssociatedGraphics1 = visualHit.ID, Graphics1Handle = i }; this.polyline = this.DrawVisual(graphics) as VisualPolyline; this.firstConnector = center; this.firstConnectorLocation = location; this.firstVisual = visualHit; return; } } #endregion #region 判断是否点击了Reisze点 for (int i = 0; i < visualHit.ResizeHandles; i++) { Rect bounds = visualHit.GetResizeHandleBounds(i); if (bounds.Contains(cursorPosition)) { this.resizeCenter = bounds.GetCenter(); this.resizeLocation = visualHit.Graphics.GetResizeLocation(this.resizeCenter); this.visualState = Visuals.VisualState.Resizing; return; } } #endregion #region 是平移状态 // 获取当前被移动的图形所有的连接点信息 this.associatedPolylines = this.GetAssociatedPolylines(visualHit.Graphics); Console.WriteLine("关联的折线有{0}个", this.associatedPolylines.Count); this.translateVisual = visualHit; this.visualState = Visuals.VisualState.Translate; #endregion } }