/// <summary> /// Sets scroll and zoom to center the given rectangle in the client area with a given scale</summary> /// <param name="adapter">Adapter managing transform</param> /// <param name="scale">Scale</param> /// <param name="itemBounds">Rectangle to frame, in client coordinates</param> /// <param name="clientBounds">Client area</param> public static void ZoomAboutCenter(this ITransformAdapter adapter, Point scale, Rect itemBounds, Rect clientBounds) { if (adapter == null || !adapter.Transform.HasInverse || itemBounds.IsEmpty) { return; } Rect worldBounds = MathUtil.InverseTransform(adapter.Transform, itemBounds); if (adapter.UniformScale) { scale.X = scale.Y = Math.Min(scale.X, scale.Y); } scale = adapter.ConstrainScale(scale); // calculate translation needed to put bounds center at center of view Point worldBoundsCenter = new Point( worldBounds.X + worldBounds.Width / 2, worldBounds.Y + worldBounds.Height / 2); Point translation = new Point( clientBounds.Width / 2 - worldBoundsCenter.X * scale.X, clientBounds.Height / 2 - worldBoundsCenter.Y * scale.Y); adapter.SetTransform(scale.X, scale.Y, translation.X, translation.Y); }
/// <summary> /// Sets scroll and zoom so that the largest axis of the given rectangle almost /// fills the client area</summary> /// <param name="adapter">Adapter managing transform</param> /// <param name="itemBounds">Rectangle to frame, in client coordinates</param> /// <param name="clientBounds">Client area</param> public static void Frame(this ITransformAdapter adapter, Rect itemBounds, Rect clientBounds) { if (adapter == null || itemBounds.IsEmpty || !adapter.Transform.HasInverse) { return; } Rect worldBounds = MathUtil.InverseTransform(adapter.Transform, itemBounds); // calculate scale so bounding rectangle (in world coordinates) fills client // rectangle with some margin around the edges const double MarginScale = 0.86; Point scale = new Point( Math.Abs(clientBounds.Width / worldBounds.Width) * MarginScale, Math.Abs(clientBounds.Height / worldBounds.Height) * MarginScale); if (adapter.UniformScale) { scale.X = scale.Y = Math.Min(scale.X, scale.Y); } scale = adapter.ConstrainScale(scale); // calculate translation needed to put bounds center at center of view Point worldBoundsCenter = new Point( worldBounds.X + worldBounds.Width / 2, worldBounds.Y + worldBounds.Height / 2); Point translation = new Point( (clientBounds.Width / 2 - worldBoundsCenter.X * scale.X), (clientBounds.Height / 2 - worldBoundsCenter.Y * scale.Y)); adapter.SetTransform(scale.X, scale.Y, translation.X, translation.Y); }
/// <summary> /// Sets scroll and zoom so that the largest axis of the given rectangle almost /// fills the client area</summary> /// <param name="adapter">Adapter managing transform</param> /// <param name="bounds">Rectangle to frame, in Windows client coordinates</param> public static void Frame(this ITransformAdapter adapter, RectangleF bounds) { if (bounds.IsEmpty) { return; } RectangleF worldBounds = GdiUtil.InverseTransform(adapter.Transform, bounds); // calculate scale so bounding rectangle (in world coordinates) fills client // rectangle with some margin around the edges RectangleF clientRect = adapter.AdaptedControl.ClientRectangle; const float MarginScale = 0.86f; PointF scale = new PointF( Math.Abs(clientRect.Width / worldBounds.Width) * MarginScale, Math.Abs(clientRect.Height / worldBounds.Height) * MarginScale); if (adapter.UniformScale) { scale.X = scale.Y = Math.Min(scale.X, scale.Y); } scale = adapter.ConstrainScale(scale); // calculate translation needed to put bounds center at center of view PointF worldBoundsCenter = new PointF( worldBounds.X + worldBounds.Width / 2, worldBounds.Y + worldBounds.Height / 2); PointF translation = new PointF( clientRect.Width / 2 - worldBoundsCenter.X * scale.X, clientRect.Height / 2 - worldBoundsCenter.Y * scale.Y); adapter.SetTransform( scale.X, scale.Y, translation.X, translation.Y); }