/// <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) { return; } Rect worldBounds = MathUtil.InverseTransform(adapter.Transform, itemBounds); if (adapter.UniformScale) { scale.X = scale.Y = Math.Min(scale.X, scale.Y); } scale = TransformAdapters.ConstrainScale(adapter, 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 = TransformAdapters.ConstrainScale(adapter, 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> /// If the given rectangle isn't visible, sets scroll and scale so that the largest axis /// of the rectangle almost fills the client area</summary> /// <param name="adapter">Adapter managing transform</param> /// <param name="itemBounds">Rectangle to ensure visible</param> /// <param name="clientBounds">Client area</param> public static void EnsureVisible(this ITransformAdapter adapter, Rect itemBounds, Rect clientBounds) { // check rectangle is already in the visible rect if (clientBounds.Contains(itemBounds)) { // already visible return; } TransformAdapters.Frame(adapter, itemBounds, clientBounds); }