// Terminate transformation in a clean way, "freeing" animated properties private void EndMatrixAnimation() { IsMatrixAnimationInProgress = false; MainMatrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, null); // Final tasks MainMatrixTransform.Matrix = rescaleMatrix; }
// Adjust scale and origin to see the whole puzzle internal void RescaleAndCenter(bool isWithAnimation) { if (viewModel.Layout == null) { return; } BoundingRectangle r = viewModel.Layout.Bounds; // Add some extra margin and always represent a 20x20 grid at minimum r = new BoundingRectangle(Math.Min(-11, r.Min.Row - 3), Math.Max(11, r.Max.Row + 4), Math.Min(-11, r.Min.Column - 3), Math.Max(11, r.Max.Column + 4)); // Reverse-transform corners into WordCanvas coordinates Point p1Grid = new Point(r.Min.Column * UnitSize, r.Min.Row * UnitSize); Point p2Grid = new Point(r.Max.Column * UnitSize, r.Max.Row * UnitSize); rescaleMatrix = MainMatrixTransform.Matrix; // Set rotation to zero // Get angle from transformation matrix double θ = Math.Atan2(rescaleMatrix.M21, rescaleMatrix.M11); // Just to use a variable named θ rescaleMatrix.Rotate(θ / Math.PI * 180); // It would certainly kill Microsoft to indicate on Rotate page or Intellisense tooltip that angle is in degrees... // First adjust scale Point p1Screen = rescaleMatrix.Transform(p1Grid); Point p2Screen = rescaleMatrix.Transform(p2Grid); double rescaleFactorX = ClippingCanvas.ActualWidth / (p2Screen.X - p1Screen.X); double rescaleFactorY = ClippingCanvas.ActualHeight / (p2Screen.Y - p1Screen.Y); double rescaleFactor = Math.Min(rescaleFactorX, rescaleFactorY); rescaleMatrix.Scale(rescaleFactor, rescaleFactor); // Then adjust location and center p1Screen = rescaleMatrix.Transform(p1Grid); p2Screen = rescaleMatrix.Transform(p2Grid); double offX1 = -p1Screen.X; double offX2 = ClippingCanvas.ActualWidth - p2Screen.X; double offY1 = -p1Screen.Y; double offY2 = ClippingCanvas.ActualHeight - p2Screen.Y; rescaleMatrix.Translate((offX1 + offX2) / 2, (offY1 + offY2) / 2); if (isWithAnimation) { // Use an animation for a smooth transformation MatrixAnimation ma = new MatrixAnimation { From = MainMatrixTransform.Matrix, To = rescaleMatrix, Duration = new Duration(TimeSpan.FromSeconds(0.35)) }; ma.Completed += MatrixAnimationCompleted; IsMatrixAnimationInProgress = true; MainMatrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, ma); } else { EndMatrixAnimation(); } }