/// <summary>
        /// Removes any white space.  The canvas may be panned and zoomed in to do this.
        /// </summary>
        /// <param name="aCamera">The camera whose view will be adjusted.</param>
        protected virtual void FillViewWhiteSpace(PCamera aCamera)
        {
            RectangleF rootBounds = aCamera.Root.FullBounds;
            RectangleF viewBounds = aCamera.ViewBounds;

            if (!PUtil.RectangleContainsRectangle(rootBounds, aCamera.ViewBounds)) {
            //if (!rootBounds.Contains(aCamera.ViewBounds)) {
                aCamera.AnimateViewToPanToBounds(rootBounds, 0);
                aCamera.AnimateViewToPanToBounds(focusNode.GlobalFullBounds, 0);

                // center content.
                float dx = 0;
                float dy = 0;
                viewBounds = aCamera.ViewBounds;

                if (viewBounds.Width > rootBounds.Width) {   // then center along x axis.
                    float rootBoundsMinX = Math.Min(rootBounds.X, rootBounds.Right);
                    float viewBoundsMinX = Math.Min(viewBounds.X, viewBounds.Right);
                    float boundsCenterX = rootBoundsMinX + (rootBounds.Width / 2);
                    float viewBoundsCenterX = viewBoundsMinX + (viewBounds.Width / 2);
                    dx = viewBoundsCenterX - boundsCenterX;
                }

                if (viewBounds.Height > rootBounds.Height) { // then center along y axis.
                    float rootBoundsMinY = Math.Min(rootBounds.Y, rootBounds.Right);
                    float viewBoundsMinY = Math.Min(viewBounds.Y, viewBounds.Right);
                    float boundsCenterY = rootBoundsMinY + (rootBounds.Height / 2);
                    float viewBoundsCenterY = viewBoundsMinY + (viewBounds.Height / 2);
                    dy = viewBoundsCenterY - boundsCenterY;
                }
                aCamera.TranslateViewBy(dx, dy);
            }
        }
        /// <summary>
        /// Animates the camera's view to keep the focus node on the screen and at 100
        /// percent scale with minimal view movement.
        /// </summary>
        /// <param name="aCamera">The camera whose view will be animated.</param>
        /// <param name="aFocusNode">The focus node to animate to.</param>
        /// <param name="duration">The length of the animation.</param>
        /// <returns>
        /// The activity that animates the camera's view to the focus node.
        /// </returns>
        public virtual PActivity DirectCameraViewToFocus(PCamera aCamera, PNode aFocusNode, int duration)
        {
            PMatrix originalViewMatrix = aCamera.ViewMatrix;

            // Scale the canvas to include
            SizeF s = new SizeF(1, 0);
            s = focusNode.GlobalToLocal(s);

            float scaleFactor = s.Width / aCamera.ViewScale;
            PointF scalePoint = PUtil.CenterOfRectangle(focusNode.GlobalFullBounds);
            if (scaleFactor != 1) {
                aCamera.ScaleViewBy(scaleFactor, scalePoint.X, scalePoint.Y);
            }

            // Pan the canvas to include the view bounds with minimal canvas
            // movement.
            aCamera.AnimateViewToPanToBounds(focusNode.GlobalFullBounds, 0);

            // Get rid of any white space. The canvas may be panned and
            // zoomed in to do this. But make sure not stay constrained by max
            // magnification.
            //FillViewWhiteSpace(aCamera);

            PMatrix resultingMatrix = aCamera.ViewMatrix;
            aCamera.ViewMatrix = originalViewMatrix;

            // Animate the canvas so that it ends up with the given
            // view transform.
            return AnimateCameraViewMatrixTo(aCamera, resultingMatrix, duration);
        }