Page Index Toggle Pages: [1] 2  Send TopicPrint
Hot Topic (More than 10 Replies) Combine with InkCanvas (Read 16204 times)
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Combine with InkCanvas
Nov 4th, 2011 at 7:32am
Print Post  
We need to implement hand-writing pen on the diagram, just like InkCanvas from WPF. Any idea?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #1 - Nov 4th, 2011 at 7:50am
Print Post  
Do you need hand-writing support inside the nodes, or anywhere in the diagram?
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #2 - Nov 4th, 2011 at 7:56am
Print Post  
In the diagram.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #3 - Nov 4th, 2011 at 8:13am
Print Post  
One approach you might try is to add a DiagramNodeAdapter(new InkCanvas()) to the diagram, make its Bounds as big as Diagram.Bounds, and keep it at the bottom of Z order. Another option could be inserting a Grid or Canvas inside the ScrollViewer, showing overlapping InkCanvas and Diagram inside the Grid/Canvas, and setting diagram.BackBrush to Transparent. I think the Transparent area of the diagram will pass input events to the InkCanvas behind, but I'm not sure how well scrolling will work in the latter scenario.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #4 - Nov 4th, 2011 at 8:26am
Print Post  
Thanks, I'll try it
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #5 - Nov 22nd, 2011 at 2:59am
Print Post  
Stoyo wrote on Nov 4th, 2011 at 8:13am:
One approach you might try is to add a DiagramNodeAdapter(new InkCanvas()) to the diagram, make its Bounds as big as Diagram.Bounds, and keep it at the bottom of Z order. Another option could be inserting a Grid or Canvas inside the ScrollViewer, showing overlapping InkCanvas and Diagram inside the Grid/Canvas, and setting diagram.BackBrush to Transparent. I think the Transparent area of the diagram will pass input events to the InkCanvas behind, but I'm not sure how well scrolling will work in the latter scenario.

I hope that helps,
Stoyan


I have tried both two advices. The second one is close to my requirement. But we need to place the ink at top of diagram, and it seems that InkCanvas cann't pass the input events to the diagram when adding an object.

Another way is that: Is it possible to add a object include a polyline when mouse moving?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #6 - Nov 22nd, 2011 at 8:36am
Print Post  
If the InkCanvas should be at the top, you will have to set its Is-HitTestVisible property to false to allow mouse input to get to the diagram. E.g. you could add an edit-ink toggle button to your UI that sets the InkCanvas.Is-HitTestVisible value to its negative.

It might be possible to draw polylines in the diagram if you create a custom DiagramLink or DiagramNode derived class and override its Start/Update/Complete-Create methods. If you derive from DiagramLink, you could add each additional point to the link's ControlPoints collection. If you derive from DiagramNode, you could collect the points in a List<Point> field and render them from the Draw override.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #7 - Nov 23rd, 2011 at 5:46pm
Print Post  
Re your private message, you can use this as a start:

Code
Select All
class FreeLine : DiagramNode
{
	public FreeLine()
	{
		points = new List<Point>();
	}

	protected override void UpdateCreate(Point current)
	{
		base.UpdateCreate(current);
		points.Add(current);
	}

	public override void Draw(DrawingContext graphics, RenderOptions options)
	{
		var pen = new Pen(Brushes.Black, 1);
		for (int i = 0; i < points.Count - 1; ++i)
		{
			var p1 = points[i] - new Vector(Bounds.X, Bounds.Y);
			var p2 = points[i + 1] - new Vector(Bounds.X, Bounds.Y);
			graphics.DrawLine(pen, p1, p2);
		}
	}

	private List<Point> points;
}

diagram.Behavior = Behavior.Custom;
diagram.CustomNodeType = typeof(FreeLine); 



Some additions you might implement are updating Bounds from CompleteCreate, and perhaps scaling the drawing from the UpdateModify method (or otherwise disabling resize).

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #8 - Nov 30th, 2011 at 10:48am
Print Post  
Thanks, your code works fine. But there is serious delay when I am drawing a long line. I fixed it with following code
Code
Select All
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Ink;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;

using MindFusion;
using MindFusion.Diagramming.Wpf;
using MindFusion.Diagramming.Wpf.Commands;
using MindFusion.Diagramming.Wpf.Layout;
using MindFusion.Layout;


namespace FCDemo
{
    class FreeLine : DiagramNode
    {
        private Stroke stroke;
        private StylusPointCollection points;
        public FreeLine( )
        {
            points = new StylusPointCollection( );
        }

        protected override void StartCreate( Point org )
        {
            base.StartCreate( org );
            var p = org - new Vector( Bounds.X , Bounds.Y );
            points.Add( new StylusPoint( p.X , p.Y ) );
            stroke = new Stroke( points );
        }

        protected override void UpdateCreate( System.Windows.Point current )
        {
            base.UpdateCreate( current );
            var p = current - new Vector( Bounds.X , Bounds.Y );
            stroke.StylusPoints.Add( new StylusPoint( p.X , p.Y ) );
        }

        protected override void CompleteCreate( Point end )
        {
            base.CompleteCreate( end );
            var p = end - new Vector( Bounds.X , Bounds.Y );
            stroke.StylusPoints.Add( new StylusPoint( p.X , p.Y ) );
        }

        public override void Draw( System.Windows.Media.DrawingContext graphics , MindFusion.Diagramming.Wpf.RenderOptions options )
        {
            if ( stroke!=null )
                stroke.Draw( graphics );
        }
    }
}
 



Now, there are two other problems:
1. I cann't draw the line from right to left and down to up.
2.how to update the bounds of the node?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #9 - Nov 30th, 2011 at 11:38am
Print Post  
You can update Bounds like this:

Code
Select All
private Rect union;

protected override void StartCreate(Point org)
{
	base.StartCreate(org);
	union = new Rect(org, org);
	...
}

protected override void UpdateCreate(Point current)
{
	base.UpdateCreate(current);

	union.Union(current);
	SetBounds(union, false, false);
	...
} 



I suppose you cannot draw from right to left because of the conversion to local coordinates relative to Bounds at each update - the local points become invalid because Boudns changes later. Instead, you could keep the points in absolute coordinates (do not subtract the vector in overridden methods) but transform them when drawing:

Code
Select All
graphics.PushTransform(new TranslateTransform(- Bounds.X, - Bounds.Y));
// draw absolute points
// ...
graphics.Pop(); 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #10 - Nov 30th, 2011 at 12:06pm
Print Post  
Grin Great!!!

But I cann't move the node after create it. The line didn't moved with the "Handle". Any problem in following code?

Code
Select All
graphics.PushTransform( new TranslateTransform( -Bounds.X , -Bounds.Y ) );
		if ( stroke!=null )
		    stroke.Draw( graphics );
		graphics.Pop( );
 

  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #11 - Nov 30th, 2011 at 12:24pm
Print Post  
Apparently the Stroke object adds its own transform, so you should offset by its own bounds instead the node's one. Here's the final version of the class, seems to work fine:

Code
Select All
class FreeLine : DiagramNode
{
	private Stroke stroke;
	private StylusPointCollection points;
	private Rect union;

	public FreeLine()
	{
		points = new StylusPointCollection();
	}

	protected override void StartCreate(Point org)
	{
		base.StartCreate(org);
		union = new Rect(org, org);
		points.Add(new StylusPoint(org.X, org.Y));
		stroke = new Stroke(points);
	}

	protected override void UpdateCreate(Point current)
	{
		base.UpdateCreate(current);
		union.Union(current);
		SetBounds(union, false, false);
		stroke.StylusPoints.Add(new StylusPoint(current.X, current.Y));
	}

	public override void Draw(DrawingContext graphics, MindFusion.Diagramming.Wpf.RenderOptions options)
	{
		if (stroke == null)
			return;

		var strokeBounds = stroke.GetBounds();
		graphics.PushTransform(new TranslateTransform(
			- strokeBounds.X, - strokeBounds.Y));

		stroke.Draw(graphics);

		graphics.Pop();
	}
} 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #12 - Nov 30th, 2011 at 12:36pm
Print Post  
Thanks for your help.
« Last Edit: Nov 30th, 2011 at 1:55pm by qomo-peter »  
Back to top
 
IP Logged
 
qomo-peter
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 16
Joined: Nov 4th, 2011
Re: Combine with InkCanvas
Reply #13 - Jun 13th, 2012 at 4:01am
Print Post  
Hi Stoyo,
There is serious delay when drawing a long free line on the diagram. I found a solution, but I have no idea how to integrate with wpf diagram. Please check the attachment and give me your advice. The solution use "DynamicRenderer" to avoid delay. Thanks very much.
  

NoDelay.zip (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Combine with InkCanvas
Reply #14 - Jun 13th, 2012 at 7:50am
Print Post  
Hi,

I don't think the DynamicRenderer in your example does anything useful. It is returned as a first visual child of the custom panel, and then the Stroke objects are added directly to the panel too, becoming siblings of the DynamicRenderer rather than its children. The DynamicRenderer would matter if you add the strokes to its ContainerVisual instead to the panel:

Code
Select All
protected override void OnMouseUp(MouseButtonEventArgs e)
{
    down = false;
    if (pen != null)
    {
        pen.Draw();
        //_col.Add(pen);
        (_col[0] as ContainerVisual).Children.Add(pen);
    }
} 



In either case, I can't see any difference in speed between the FreeLine rendering in my test app and the CustomPen from this sample project. Both just call Stroke.Draw(dc) anyway, so the problem shouldn't be related to rendering speed. Perhaps you should run a profiler to see what takes most time while drawing the lines. E.g. there might be delay if you handle some validation events, such as NodeCreating, and running longer operations in the handler methods.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: [1] 2 
Send TopicPrint