protected override Vector2 DoMeasure(float width, MeasureMode widthMode, float height, MeasureMode heightMode)
        {
            GraphView     graphView = GetFirstAncestorOfType <GraphView>();
            VisualElement viewport  = graphView.contentViewContainer;

            contentRectInViewportSpace = Rect.zero;

            // Compute the bounding box of the content of the scope in viewport space (because nodes are not parented by the scope that contains them)
            foreach (GraphElement subElement in containedElements)
            {
                if (subElement.panel != panel)
                {
                    continue;
                }
                if (subElement.parent == null)
                {
                    continue;
                }

                Rect boundingRect = subElement.GetPosition();

                if (Scope.IsValidRect(boundingRect))
                {
                    boundingRect = subElement.parent.ChangeCoordinatesTo(viewport, boundingRect);

                    // Use the first element with a valid geometry as reference to compute the bounding box of contained elements
                    if (!Scope.IsValidRect(contentRectInViewportSpace))
                    {
                        contentRectInViewportSpace = boundingRect;
                    }
                    else
                    {
                        contentRectInViewportSpace = RectUtils.Encompass(contentRectInViewportSpace, boundingRect);
                    }
                }
            }

            return(new Vector2(contentRectInViewportSpace.width, contentRectInViewportSpace.height));
        }
        void CalculateRects(VisualElement container)
        {
            if (graphView == null)
            {
                // Nothing to do in this case.
                return;
            }

            m_ContentRect      = graphView.CalculateRectToFitAll(container);
            m_ContentRectLocal = m_ContentRect;

            // Retrieve viewport rectangle as if zoom and pan were inactive
            Matrix4x4 containerInvTransform   = container.WorldTransformInverse();
            Vector4   containerInvTranslation = containerInvTransform.GetColumn(3);
            var       containerInvScale       = new Vector2(containerInvTransform.m00, containerInvTransform.m11);

            m_ViewportRect = graphView.GetRect();

            // Bring back viewport coordinates to (0,0), scale 1:1
            m_ViewportRect.x += containerInvTranslation.x;
            m_ViewportRect.y += containerInvTranslation.y;

            var graphViewWB = graphView.worldBound;

            m_ViewportRect.x      += graphViewWB.x * containerInvScale.x;
            m_ViewportRect.y      += graphViewWB.y * containerInvScale.y;
            m_ViewportRect.width  *= containerInvScale.x;
            m_ViewportRect.height *= containerInvScale.y;

            // Update label with new value
            var containerZoomFactor = container.worldTransform.m00;

            SetZoomFactorText(String.Format(CultureInfo.InvariantCulture.NumberFormat, "{0:F2}", containerZoomFactor) + "x");

            // Adjust rects for MiniMap
            float effectiveWidth  = layout.width - 1;
            float effectiveHeight = layout.height - 1;

            // Encompass viewport rectangle (as if zoom and pan were inactive)
            var totalRect     = RectUtils.Encompass(m_ContentRect, m_ViewportRect);
            var minimapFactor = effectiveWidth / totalRect.width;

            // Transform each rect to MiniMap coordinates
            ChangeToMiniMapCoords(ref totalRect, minimapFactor, Vector3.zero);

            var minimapTranslation = new Vector3(-totalRect.x, titleBarOffset - totalRect.y);

            ChangeToMiniMapCoords(ref m_ViewportRect, minimapFactor, minimapTranslation);
            ChangeToMiniMapCoords(ref m_ContentRect, minimapFactor, minimapTranslation);

            // Diminish and center everything to fit vertically
            if (totalRect.height > (effectiveHeight - titleBarOffset))
            {
                float totalRectFactor  = (effectiveHeight - titleBarOffset) / totalRect.height;
                float totalRectOffsetX = (effectiveWidth - (totalRect.width * totalRectFactor)) / 2.0f;
                float totalRectOffsetY = titleBarOffset - ((totalRect.y + minimapTranslation.y) * totalRectFactor);

                m_ContentRect.width  *= totalRectFactor;
                m_ContentRect.height *= totalRectFactor;
                m_ContentRect.x      *= totalRectFactor;
                m_ContentRect.y      *= totalRectFactor;
                m_ContentRect.x      += totalRectOffsetX;
                m_ContentRect.y      += totalRectOffsetY;

                m_ViewportRect.width  *= totalRectFactor;
                m_ViewportRect.height *= totalRectFactor;
                m_ViewportRect.x      *= totalRectFactor;
                m_ViewportRect.y      *= totalRectFactor;
                m_ViewportRect.x      += totalRectOffsetX;
                m_ViewportRect.y      += totalRectOffsetY;
            }
        }