Page Index Toggle Pages: 1 Send TopicPrint
Hot Topic (More than 10 Replies) ScrollViewer destroys NodeDeleting events? (Read 11427 times)
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
ScrollViewer destroys NodeDeleting events?
Dec 12th, 2011 at 2:25pm
Print Post  
Belatedly, i added ScrollViewer to allow panning and autoscrolling etc but....

..suddenly, the NodeDeleting events do not fire.

All the other Mindfusion events are there like clicking, doubleclicking, etc, only deleting is silent.

If i remove the xaml <ScrollViewer> Tags, the events are back there again.

One COULD easily write own event handler that checks for delete key and deletes selection nodes, but it "seems" unappropriate & one worries what else got broke in the back..

Any ideas?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #1 - Dec 12th, 2011 at 2:38pm
Print Post  
By default ScrollViewer captures the keyboard focus and does not pass keyboard events to the diagram. Set <ScrollViewer ... Focusable="False" ... > to prevent that.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #2 - Dec 12th, 2011 at 3:22pm
Print Post  
Thank you, that worked Smiley

Do we know how to detect the actual size of client visible area of the diagram within the ScrollViewer?

Bounds returns the rect of the background area, all of it...
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #3 - Dec 12th, 2011 at 4:05pm
Print Post  
Hi,

If you need to know the size in WPF points, check the scrollviewer's ActualWidth and ActualHeight properties. There's also the Diagram.Viewport property you could use - it returns the viewport rectangle in MeasureUnit units, and it also considers the current scroll position and zoom level.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #4 - Dec 14th, 2011 at 4:51pm
Print Post  
Uh i was so happy with:

Code
Select All
                       Rect size = new Rect(0, 0, v.ViewportWidth+v.HorizontalOffset, v.ViewportHeight+v.VerticalOffset);

                        if (!size.Contains(MousePosition)) //within itself
                        {  



as it detected even the pan-shifted inside of a viewport, UNTIL i understood that one can have also a floating window above, and then one needs discern the "topmost" property to be able to say if the hit is correct.

Diagram.Viewport does not have the Topmost property?

Is there a simple way to find out which diagram is topmost? (we use Avalon Dock)

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #5 - Dec 14th, 2011 at 5:55pm
Print Post  
Could you explain the problem in more details? If you need to transform mouse position relative to some other control to the diagram's logical coordinate system, you could do something like this:

var diagramPoint = control.TransformToVisual(diagram.DocumentPlane).Transform(mousePos);
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #6 - Dec 14th, 2011 at 6:05pm
Print Post  
well i can have multiple document avalon dock setup, and lets say 5 mindfusion diagrams. Some of them are floating (as not docked) and i need to detect which is the topmost when i e.g. drag onto it.

So was hoping for a cheap solution like (diagram.topmost == true) or via viewport property, in order to determine the topmost hit one.

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #7 - Dec 14th, 2011 at 6:59pm
Print Post  
Perhaps try this to access that property:
((FloatingDockablePane) (diagram.Parent)).FloatingWindow.Topmost

I'm not sure if that code is for the same dock control, but I found it here by googling for "avalon window topmost":
http://codesomnia.de/2011/caliburn-micro-feat-avalondock-i-conductor-and-view/
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #8 - Dec 15th, 2011 at 10:51am
Print Post  
Argh Roll Eyes

It just crossed my mind that "topmost" does not help: one can have several floating diagrams around...

Best would be if there was a way to detect the uppermost hit diagram when the handler:

protected override void OnDrop(DragEventArgs e)

hits. Then one could ignore other bubbling drop events after the uppermost hit one has been done.

===

I also tried to discern what is hit per drop by using the

HitTestResult hit = VisualTreeHelper.HitTest((Visual)e.Source, MousePosition)

[not sure here if e.Source is a good origin]

but the HitTestResult is of mindfusion type A.UM ? Though it corresponds to the diagram background size 1500x1500 that we gave in xaml, i have no way of casting it to some actual diagram type in order to determine whats hit?

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #9 - Dec 15th, 2011 at 1:33pm
Print Post  
You shouldn't have to care which diagram is the 'uppermost hit' if you attach a Drop event handler to each diagram. Only the one directly under the mouse will handle the event then. I verified that with the following modification of the 'Multiple Views' sample project:

Code
Select All
private void myAdd_Click(object sender, RoutedEventArgs e)
{
	var diagram = new Diagram();
	diagram.DragOver += Diagram_DragOver;
	diagram.Drop += Diagram_Drop;
	diagram.AllowDrop = true;

	MindFusion.UI.Wpf.Window window = new MindFusion.UI.Wpf.Window();
	window.Width = 200;
	window.Height = 200;
	window.Content = diagram;
	window.Show(windowHost);
}

void Diagram_Drop(object sender, DragEventArgs e)
{
	var diagram = (Diagram)sender;

	e.Effects = DragDropEffects.Copy;
	e.Handled = true;

	var point = e.GetPosition(diagram.DocumentPlane);
	diagram.Factory.CreateShapeNode(point, new Size(50, 50))
		.Text = (string)e.Data.GetData(typeof(string));
}

void Diagram_DragOver(object sender, DragEventArgs e)
{
	e.Effects = DragDropEffects.Copy;
	e.Handled = true;
} 



Now if you open several windows, rearrange them to overlap and drag some text to them, only the one under the mouse will get a new node created.

If you prefer to attach a handler to a single object and use VisualTreeHelper to find diagrams, the following seems to work:

Code
Select All
public MainWindow()
{
	InitializeComponent();
	AllowDrop = true;

	DragOver += new DragEventHandler(MainWindow_DragOver);
	Drop += new DragEventHandler(MainWindow_Drop);
}

void MainWindow_Drop(object sender, DragEventArgs e)
{
	var gridLayer = e.OriginalSource as UIElement;
	if (gridLayer != null && VisualTreeHelper.GetParent(gridLayer) is Diagram)
	{
		var diagram = (Diagram)VisualTreeHelper.GetParent(gridLayer);
		e.Effects = DragDropEffects.Copy;
		e.Handled = true;

		var point = e.GetPosition(diagram.DocumentPlane);
		diagram.Factory.CreateShapeNode(point, new Size(50, 50))
			.Text = (string)e.Data.GetData(typeof(string));
	}
}

void MainWindow_DragOver(object sender, DragEventArgs e)
{
	e.Effects = DragDropEffects.Copy;
	e.Handled = true;
} 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #10 - Dec 15th, 2011 at 3:18pm
Print Post  
Ah thank you, Stoyan Smiley

"You shouldn't have to care which diagram is the 'uppermost hit' if you attach a Drop event handler to each diagram."

I do that already, but use OnDrop from windows and not from Mindfusion, so maybe it behaves differently: will have to consider rewriting it a bit.

The original reason to use windows OnDrop was to try simulate nice graphical draging of nodes from diagram to next diagram (the way nodes are dragged within the same diagram), but it didn't succeed in full.

Is there a Mindfusion way to attach a node to cursor while you drag over the diagram boundaries to next diagram or you always show only .NET drag cursors?

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #11 - Dec 15th, 2011 at 6:32pm
Print Post  
You can override the system cursors by handling the GiveFeedback event. E.g. you could set as a cursor some icon representing a node. If you want to draw a real node being dragged between windows, you will have to use a temporary canvas or diagram that overlays the whole app and hosts a single node, and change the position of that node from the GiveFeedback handler.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #12 - Dec 16th, 2011 at 11:24am
Print Post  
Good ideas, thank you  Smiley
  
Back to top
 
IP Logged
 
ulthien
Junior Member
**
Offline


I love YaBB 1G - SP1!

Posts: 91
Location: Munich
Joined: Nov 29th, 2011
Re: ScrollViewer destroys NodeDeleting events?
Reply #13 - Apr 17th, 2012 at 8:53am
Print Post  
Stoyo wrote on Dec 15th, 2011 at 6:32pm:
If you want to draw a real node being dragged between windows, you will have to use a temporary canvas or diagram that overlays the whole app and hosts a single node, and change the position of that node from the GiveFeedback handler.

I hope that helps,
Stoyan


Hello Stoyan,

would you have an example (XAML?) for these two approaches for overlays to draw temporary dragged nodes? When using multi-diag app (i.e. we use Avalon Dock) one would have to overlay the whole screen as some of the mindfusion diagrams' views can be floating around.

This would really be a nice-to-have as then the graphical metaphor is the same everywhere: not only is the dragging visually supported within the same diagram, but when dragging to/fro different diagrams, too.

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: ScrollViewer destroys NodeDeleting events?
Reply #14 - Apr 17th, 2012 at 12:29pm
Print Post  
Hi,

You can find an example below. It opens a new window that covers the whole screen to enable drawing the node everywhere. The drag operation is started by holding down shift while pressing the mouse button. It doesn't actually use the Windows drag/drop events, since MouseMove is enough when we cover the whole screen. VisualTreeHelper.HitTest might not work with the dock control you are using if it creates system windows via the Win32 API. In such case you will have to use the dock control's API for hit testing.

Another option might be to create a small window - just as big as the node - and move the window around while the mouse moves. This might be necessary if you have to support drag between two instances of the application, since VisualTreeHelper won't work then, and you will  have to use OLE drag/drop instead of MouseMove anyway.

The code below is from a modification of the MultiViews sample project, where you must also add these changes:

In MainWindow.xaml, add the following attribute to windowHost:
PreviewMouseDown="OnPreviewMouseDown"

In MainWindow.xaml.cs, replace the window.Content = view assignment with:
window.Content = new Diagram();

I hope that helps,
Stoyan

Code
Select All
private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
	if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
	{
		VisualTreeHelper.HitTest((Visual)sender, null, StartDrag,
			new PointHitTestParameters(e.GetPosition((IInputElement)sender)));
		e.Handled = true;
	}
}

private HitTestResultBehavior StartDrag(HitTestResult result)
{
	var node = result.VisualHit as DiagramNode;
	if (node != null)
	{
		overlay = new Window();
		overlay.AllowsTransparency = true;
		overlay.WindowStyle = WindowStyle.None;
		overlay.Background = Brushes.Transparent;
		overlay.ShowInTaskbar = false;
		overlay.Left = 0;
		overlay.Top = 0;
		overlay.Width = 2000;
		overlay.Height = 2000;
		overlay.Show();
		overlay.Topmost = true;

		var diagram = new Diagram();
		diagram.BackBrush = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
		diagram.Bounds = new Rect(0, 0, 2000, 2000);
		diagram.CaptureMouse();
		diagram.Focus();
		diagram.PreviewMouseMove += OnOverlayMouseMove;
		diagram.PreviewMouseUp += OnOverlayMouseUp;
		overlay.Content = diagram;

		var clone = (DiagramNode)node.Clone(false);
		diagram.Nodes.Add(clone);

		overlay.UpdateLayout();
		var pos = Mouse.GetPosition(diagram.DocumentPlane);
		clone.Move(
			pos.X - clone.Bounds.Width / 2,
			pos.Y - clone.Bounds.Height / 2);

		return HitTestResultBehavior.Stop;
	}

	return HitTestResultBehavior.Continue;
}

private void OnOverlayMouseMove(object sender, MouseEventArgs e)
{
	var diagram = (Diagram)sender;
	var pos = e.GetPosition(diagram.DocumentPlane);

	var clone = diagram.Nodes[0];
	clone.Move(
			pos.X - clone.Bounds.Width / 2,
			pos.Y - clone.Bounds.Height / 2);
}

private void OnOverlayMouseUp(object sender, MouseButtonEventArgs e)
{
	overlay.Close();

	windowHost.CaptureMouse();
	var mousePos = Mouse.GetPosition(windowHost);
	windowHost.ReleaseMouseCapture();
	VisualTreeHelper.HitTest(
		windowHost, null, EndDrag,
		new PointHitTestParameters(mousePos));
}

private HitTestResultBehavior EndDrag(HitTestResult result)
{
	// result.VisualHit is diagram.DocumentPlane
	var diagram = VisualTreeHelper.GetParent(result.VisualHit) as Diagram;
	if (diagram != null)
	{
		var overlayDiagram = (Diagram)overlay.Content;
		var clone = (DiagramNode)overlayDiagram.Nodes[0].Clone(false);
		diagram.Nodes.Add(clone);

		var pos = Mouse.GetPosition(diagram.DocumentPlane);
		clone.Move(
			pos.X - clone.Bounds.Width / 2,
			pos.Y - clone.Bounds.Height / 2);

		return HitTestResultBehavior.Stop;
	}

	return HitTestResultBehavior.Continue;
}

Window overlay;
 

  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint