I am building a custom polyline tool, all I want is to add points and have a preview of the line that is going to be added (check the GIF to see what I am trying to achieve).
Here is the tool:
public
class
PolylineShapeTool : ToolBase, IMouseListener
{
private
LineSegment _currentLineSegment;
private
PathFigure _currentPathFigure;
private
PathSegmentCollection _currentPathSegmentCollection;
private
RadDiagramShape _currentShape;
public
PolylineShapeTool()
:
base
(
"PolylineShapeTool"
)
{
}
private
RadDiagram Diagram
{
get
{
return
Graph
as
RadDiagram; }
}
public
bool
MouseDown(PointerArgs e)
{
return
false
;
}
public
bool
MouseDoubleClick(PointerArgs e)
{
return
false
;
}
public
bool
MouseMove(PointerArgs e)
{
if
(IsActive && _currentShape !=
null
)
{
if
(_currentLineSegment !=
null
)
{
var rect = CalculateRectFromBasePoint(e.TransformedPoint);
_currentLineSegment.Point = e.TransformedPoint;
_currentShape.Width = rect.Width;
_currentShape.Height = rect.Height;
}
return
true
;
}
return
false
;
}
public
bool
MouseUp(PointerArgs e)
{
if
(IsActive)
{
_currentLineSegment =
new
LineSegment { Point = e.TransformedPoint };
if
(_currentPathSegmentCollection ==
null
)
{
_currentPathSegmentCollection =
new
PathSegmentCollection();
_currentPathFigure =
new
PathFigure
{
StartPoint = e.TransformedPoint,
Segments = _currentPathSegmentCollection,
IsFilled =
false
,
IsClosed =
false
};
var pathGeometry =
new
PathGeometry { Figures =
new
PathFigureCollection { _currentPathFigure } };
_currentShape =
new
RadDiagramShape { Geometry = pathGeometry};
Diagram.AddShape(_currentShape);
}
_currentPathSegmentCollection.Add(_currentLineSegment);
_currentPathFigure.Segments = _currentPathSegmentCollection;
return
true
;
}
return
false
;
}
protected
override
void
OnDeactivated()
{
base
.OnDeactivated();
_currentShape =
null
;
_currentLineSegment =
null
;
_currentPathFigure =
null
;
_currentPathSegmentCollection =
null
;
}
private
Rect CalculateRectFromBasePoint(Point transformedPoint)
{
var width = Math.Abs(_currentShape.X - transformedPoint.X);
var height = Math.Abs(_currentShape.Y - transformedPoint.Y);
var x = Math.Min(_currentShape.X, transformedPoint.X);
var y = Math.Min(_currentShape.Y, transformedPoint.Y);
return
new
Rect(x, y, width, height);
}
}
The problem is that it isn't working as expected, despite setting the StartPoint of the PathFigure, the first line starts at (0,0).
What do I have to change in this or how could I create such tool?
Why I don't use the Path tool? Because I don't need Bezier curves and there's no preview for the current line.
13 Answers, 1 is accepted
Currently I am trying to find a better and an easier approach to achieve your requirement. I am researching if you can use any other tools for this purpose. I will write back if I find something.
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Thank you Pavel!
I managed to achieve your requirement by creating a fully customized tool. The approach that I used follows these steps:
- Subscribe to the MouseDown, MouseMove and KeyDown events
- On MouseDown I create a RadDiagramConnection and on MouseMove I update the EndPoint property of the connection
- The KeyDown event serves to complete the shape that you have created (use Enter Key)
- When the custom tool is Deactivated I remove the connection and create a RadDiagramShape with the same Geometry and Position
I believe this achieves your requirement. One behavior that is not addressed in the attached project is that the created shape is only 1 pixel in width. This means that you need to click directly on the shape in order to select it or mode it around. There is no login in the RadDigram to select shapes that are in some radius around the click position. You can overcome this behavior by creating custom HitTestService. In that servie you will be able to check if there are any shapes near the click position and return them.
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
I will create my own HitTestSv for the selection. Yet I would like to know whats the use of the Telerik.Windows.Diagrams.Core.DiagramConstants.SelectionHitTestRadius property?
Thank you very much for your support Pavel!!
That property is respected only for the RadDiagramConnections. By design the connections are 1px in width which makes their selection hard. This is why we created that constat. But in the current implementation of the default HitTestService we do not respect the shapes of the diagram. By design the shapes are not 1px in width and this is why we filter the results and take the items that implement the IConnection interface.
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
I have found some flaws in our approach to create a polyline tool that I am not being able to find a way to fix it.
Situation 1: When you create a straight line, it moves the second point a few pixels to the right.
Situation 2: Anything that you draw will slightly move from its original position.
I've attached a GIF where you'll be able to easily comprehend what are the situations I'm talking about.
I already checked the final points before the shape is added to the diagram and everything seems fine. This doesn't happen to the original PathTool.
Thankss
We were able to address the reported issues regarding the custom tool.
First let me try to explain why this was happening. The reason behind the issues was that I did not respect the actual size of the generated geometry. Since you will need to create shapes that are 1 pixel in width or height you need to set the minimum allowed size of the shapes to be 1 pixel.
This can be done by setting the MinHeight and MinWidth properties of the shapes to 1. Furthermore you need to set two of the constants of the RadDiagram to 1. These are the MinimumShapeSize and MinimumAdornerSize. These constants will allow you to resize the shapes to 1 pixel.
This is implemented in the attached project. Please take a look at it and let me know if you need any further assistance.
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
I've tested your attached project and I also changed the constants and shape style in my own project. The behavior kept the same, it moves after I finish to build the line.
I've added a GIF where I reproduce the situation directly from this last project you've attached.
In the attached project I also updated the implementation of the PolylineShapeTool class. Have you tried the new implementation?
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
There are two different situations:
Creating a straight line: Click once to set the first point, move down and press Enter to finish.
Creating a random polyline:
Click in some points and press Enter. The whole shape moves 1px from the position it's supposed to be created.
The behavior that is reproduced when you try to draw a straight line was addressed by my previous project. The reason behind it was that I did not consider the size of the shape. This is why you actually set the MinHeight and MinWidth properties along with the DiagramConstants.
The reason behind the second issue is the fact that the geometry of the RadDiagramShape is always drawn in the bounds of the visual object. However the geometry of the RadDiagramConnection does not respect such bounds. This is why you need to compensate the position and the size of the newly created RadDiagramShape with the strokethickness of the RadDiagramConnection.
Check the attached project for more details.
Regards,
Pavel R. Pavlov
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
It works very well!
Thank you so much for your attention and support!!!!!