This is a migrated thread and some comments may be shown as answers.

How to restrict RadDiagramThumbnail's ViewportRect position

5 Answers 113 Views
Diagram
This is a migrated thread and some comments may be shown as answers.
Jaeho
Top achievements
Rank 1
Jaeho asked on 29 Mar 2020, 10:20 AM

Hi,

I am trying specify RadDiagram Canvas size and I have two questions below.

Question 1)

When I set Width and Height of RadDiagram to large numbers,

ViewportRect.location of RadDiagramThumbnail is different.

Is this correct behavior and why is this happening?

 

Question 2)

With With and Height set, I am able to restrict the movement(or scroll?) of canvas to (0,0) and (width,height).

Below is the code I wrote to restrict the pan movement.

Now, I want to the same thing when I click and move mouse on RadDiagramThumbnail's ViewportRect.

How can I do this?

Thanks in advance.

Jaeho

 

 

MainWindow.xaml

   <Grid x:Name="LyoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <telerik:RadDiagram x:Name="xDiagram" 
            Width="5760"
            Height="3240"
            MouseMove="diagram_MouseMove"
            PreviewMouseDown="diagram_MouseDown"
            PreviewMouseUp="diagram_MouseUp"
            PreviewPan="Diagram_OnPreviewPan"
                            >
            <telerik:RadDiagramShape x:Name="Shape1" 
                                 Content="Shape1" 
                                 Geometry="{telerik:FlowChartShape ShapeType=Database1Shape}" 
                                 Position="100,80" />
            <telerik:RadDiagramShape x:Name="Shape2" 
                                 Content="Shape2" 
                                 Position="200,180" />
            <telerik:RadDiagramConnection Source="{Binding ElementName=Shape1}" Target="{Binding ElementName=Shape2}" />
        </telerik:RadDiagram>
        <telerik:RadDiagramThumbnail x:Name="xThumbnail" 
                             Grid.Row="1" 
                             Diagram="{Binding ElementName=xDiagram}">
            <telerik:RadDiagramThumbnail.ViewportStyle>
                <Style TargetType="Rectangle">
                    <Setter Property="Stroke" Value="Blue" />
                </Style>
            </telerik:RadDiagramThumbnail.ViewportStyle>
        </telerik:RadDiagramThumbnail>
    </Grid>''

 

 

MainWindow.xaml.cs

        private bool isPanning = false;
        private Point oldPosition;

        private void Diagram_OnPreviewPan(object sender, PositionChangedRoutedEventArgs e)
        {
            e.Handled = true;
            this.isPanning = true;

        }

        private void diagram_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.oldPosition = e.GetPosition(this);
        }

        private void diagram_MouseUp(object sender, MouseEventArgs e)
        {
            this.isPanning = false;
        }

        private void diagram_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.LeftButton == MouseButtonState.Pressed) || (e.RightButton == MouseButtonState.Pressed))
            {
                var position = e.GetPosition(this);

                if (this.isPanning && (e.RightButton == MouseButtonState.Pressed || Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                {
                    RadDiagram diagram = sender as RadDiagram;
                    double xOffset = position.X - oldPosition.X;
                    double yOffset = position.Y - oldPosition.Y;
                    if (yOffset < 0)
                    {
                        int visibleHeight = (int)(diagram.DesiredSize.Height / diagram.Zoom);
                        double pos = diagram.Viewport.Top + visibleHeight;
                        if (pos - yOffset > diagram.ActualHeight)
                        {
                            yOffset += (int)((pos - yOffset) - diagram.ActualHeight);
                        }
                    }
                    else if (yOffset > 0)
                    {
                        if (diagram.Viewport.Top - yOffset < 0)
                        {
                            //e.Handled = true;
                            yOffset += (int)diagram.Viewport.Top - yOffset;
                        }
                    }

                    if (xOffset < 0)
                    {
                        int visibleWidth = (int)(diagram.DesiredSize.Width / diagram.Zoom);
                        double pos = diagram.Viewport.Left + visibleWidth;
                        if (pos - xOffset > diagram.ActualWidth)
                        {
                            //e.Handled = true;
                            xOffset += (int)((pos - xOffset) - diagram.ActualWidth);
                        }
                    }
                    else if (xOffset > 0)
                    {

                        if (diagram.Viewport.Left - xOffset < 0)
                        {
                            //e.Handled = true;
                            xOffset += (int)diagram.Viewport.Left - xOffset;
                        }
                    }

                    if (Math.Abs(xOffset) != 0 || Math.Abs(yOffset) != 0)
                    {
                        diagram.Position = new Point(diagram.Position.X + xOffset, diagram.Position.Y + yOffset);
                    }

                    oldPosition = new Point(oldPosition.X + xOffset, oldPosition.Y + yOffset);
                }
            }
        }

 

5 Answers, 1 is accepted

Sort by
0
Vladimir Stoyanov
Telerik team
answered on 01 Apr 2020, 02:55 PM

Hello Jaehoo,

Thank you for the provided code snippets. 

Based on the provided information I am uncertain whether the current approach is the best one. May I ask you to elaborate a bit on what you are trying to achieve ultimately? This will hopefully allow me to better understand the scenario and further assist you.

On a side note, you can check out the following thread: Custom Diagram Size (Not viewport), where a similar scenario was discussed. 

I am looking forward to your reply.

Regards,
Vladimir Stoyanov
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Jaeho
Top achievements
Rank 1
answered on 02 Apr 2020, 04:09 AM

Dear Vladimir,

Thanks for your feedback.

With more time spent on studying diagram's viewport and RadDiagramThumbnail's viewportrect,

I agree with you that my previous approach was not a good one.

What I want to do is to be able to limit the scrolling of diagram to the rectangle which includes all shapes.

And the scrolling area should be decided dynamically as shapes are added, deleted or moved to other locations.

Currently, diagram allows infinite scrolling of diagram.

I see that RadDiagramThumbnail is limiting the drag of viewportrect.

And this is what I want to do on diagram canvas.

 

Hope this gives you better understanding.

 

Thanks.

0
Vladimir Stoyanov
Telerik team
answered on 06 Apr 2020, 01:12 PM

Hello Jaeho,

Thank you for the additional information. 

I am attaching a sample project demonstrating a possible approach for limiting the panning within the bounds of the existing shapes. It involves adding a handler for the ViewportChanged event, which will also be fired when the viewport is changed through the RadDiagramThumbnail. 

Note, that I have not tested the suggested approach extensively, however I do hope that it will serve as a good starting point for achieving the desired behavior. Of course, feel free to modify it or extend it in order to suit your exact scenario. 

Regards,
Vladimir Stoyanov
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Jaeho
Top achievements
Rank 1
answered on 08 Apr 2020, 11:53 AM

Hello Vladimir,

Thanks for your feedback and the sample project.

Unfortunately, I wasn't able to solve my problem.

Let me rephrase question.

I see that RadDiagramThumbnail has a rectangle where I can drag around the diagram's viewport.

And there seems to be a limited draggable area where I cannot drag beyond.

Is it possible to get the draggable area of RadDiagramThumbnail so I can apply same draggable area to diagram?

Thanks and regards,

Jaeho

0
Vladimir Stoyanov
Telerik team
answered on 13 Apr 2020, 08:49 AM

Hello Jaeho,

There isn't a straightforward approach to applying the same restrictions in the RadDiagram. Here is the essential logic of the RadDiagramThumbnail, which is executed on mouse move when the rectangle is dragged:

protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (this.isLeftButtonDown)
            {
                var currentMousePosition = e.GetPosition(this);
                double offsetX = currentMousePosition.X - this.dragStartPoint.X;
                double offsetY = currentMousePosition.Y - this.dragStartPoint.Y;
                if (this.isDragging)
                {
                    var viewportSize = this.ViewportRect.ToSize();
                    var halfViewportWidth = viewportSize.Width / 2;
                    var halfViewportHeight = viewportSize.Height / 2;
                    Point possiblePosition = new Point(this.positionOnDragStart.X + offsetX, this.positionOnDragStart.Y + offsetY);
                    double positionX = Math.Max(-halfViewportWidth, Math.Min(possiblePosition.X, this.mainCanvas.ActualWidth - halfViewportWidth));
                    double positionY = Math.Max(-halfViewportHeight, Math.Min(possiblePosition.Y, this.mainCanvas.ActualHeight - halfViewportHeight));
                    this.ViewportRect = new Rect(new Point(positionX, positionY), viewportSize);

                    this.SetDiagramPosition();
                }
                else if (Math.Abs(offsetX) > 2 || Math.Abs(offsetY) > 2)
                {
                    this.isDragging = true;
                    this.CaptureMouse();
                }
            }
        }
private void SetDiagramPosition()
        {
            Point newPosition = this.CalculateDiagramPoint(this.ViewportRect.TopLeft());
            if (this.Diagram != null)
            {
                this.Diagram.BringIntoView(newPosition, this.Zoom, DiagramAnimations.GetIsPanAnimationEnabled(this.Diagram));
            }
        }

        private Point CalculateDiagramPoint(Point thumbnailPoint)
        {
            if (this.mainCanvas == null || this.Diagram == null)
                return new Point();

            double offsetX = (thumbnailPoint.X * (this.imageRectangle.Width / this.mainCanvas.ActualWidth)) + this.imageRectangle.X;
            double offsetY = (thumbnailPoint.Y * (this.imageRectangle.Height / this.mainCanvas.ActualHeight)) + this.imageRectangle.Y;

            return new Point(offsetX, offsetY);
        }

You can observe that the X and Y positions are limited in the OnMouseMove event and later the BringIntoView method of the RadDiagram is used.

I hope you find this helpful.

Regards,
Vladimir Stoyanov
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
Diagram
Asked by
Jaeho
Top achievements
Rank 1
Answers by
Vladimir Stoyanov
Telerik team
Jaeho
Top achievements
Rank 1
Share this question
or