Пример #1
0
        public override bool Equals(object o)
        {
            bool result = false;

            if (o is ZoomboxView)
            {
                ZoomboxView other = (ZoomboxView)o;
                if (ViewKind == other.ViewKind)
                {
                    switch (ViewKind)
                    {
                    case ZoomboxViewKind.Absolute:
                        result = (DoubleHelper.AreVirtuallyEqual(_scaleWidth, other._scaleWidth)) &&
                                 (DoubleHelper.AreVirtuallyEqual(Position, other.Position));
                        break;

                    case ZoomboxViewKind.Region:
                        result = DoubleHelper.AreVirtuallyEqual(Region, other.Region);
                        break;

                    default:
                        result = true;
                        break;
                    }
                }
            }
            return(result);
        }
Пример #2
0
        public override object ConvertTo(
            ITypeDescriptorContext typeDescriptorContext,
            CultureInfo cultureInfo,
            object value,
            Type destinationType)
        {
            object      result = null;
            ZoomboxView view   = value as ZoomboxView;

            if (view != null)
            {
                if (destinationType == typeof(string))
                {
                    result = "Empty";
                    switch (view.ViewKind)
                    {
                    case ZoomboxViewKind.Absolute:
                        if (PointHelper.IsEmpty(view.Position))
                        {
                            if (!DoubleHelper.IsNaN(view.Scale))
                            {
                                result = view.Scale.ToString();
                            }
                        }
                        else if (DoubleHelper.IsNaN(view.Scale))
                        {
                            result = view.Position.X.ToString() + "," + view.Position.Y.ToString();
                        }
                        else
                        {
                            result = view.Scale.ToString() + ","
                                     + view.Position.X.ToString() + ","
                                     + view.Position.Y.ToString();
                        }
                        break;

                    case ZoomboxViewKind.Center:
                        result = "Center";
                        break;

                    case ZoomboxViewKind.Fill:
                        result = "Fill";
                        break;

                    case ZoomboxViewKind.Fit:
                        result = "Fit";
                        break;

                    case ZoomboxViewKind.Region:
                        result = view.Region.X.ToString() + ","
                                 + view.Region.Y.ToString() + ","
                                 + view.Region.Width.ToString() + ","
                                 + view.Region.Height.ToString();
                        break;
                    }
                }
            }
            return(result ?? base.ConvertTo(typeDescriptorContext, cultureInfo, value, destinationType));
        }
Пример #3
0
        public override object ConvertFrom(
            ITypeDescriptorContext typeDescriptorContext,
            CultureInfo cultureInfo,
            object value)
        {
            ZoomboxView result = null;

            if (value is double)
            {
                result = new ZoomboxView((double)value);
            }
            else if (value is Point)
            {
                result = new ZoomboxView((Point)value);
            }
            else if (value is Rect)
            {
                result = new ZoomboxView((Rect)value);
            }
            else if (value is string)
            {
                if (string.IsNullOrEmpty((value as string).Trim()))
                {
                    result = ZoomboxView.Empty;
                }
                else
                {
                    switch ((value as string).Trim().ToLower())
                    {
                    case "center":
                        result = ZoomboxView.Center;
                        break;

                    case "empty":
                        result = ZoomboxView.Empty;
                        break;

                    case "fill":
                        result = ZoomboxView.Fill;
                        break;

                    case "fit":
                        result = ZoomboxView.Fit;
                        break;

                    default:
                        // parse double values; respect the following separators: ' ', ';', or ','
                        List <double> values = new List <double>();
                        foreach (
                            string token in
                            (value as string).Split(new[] { ' ', ';', ',' }, StringSplitOptions.RemoveEmptyEntries)
                            )
                        {
                            double d;
                            if (double.TryParse(token, out d))
                            {
                                values.Add(d);
                            }
                            if (values.Count >= 4)
                            {
                                // disregard additional values
                                break;
                            }
                        }

                        switch (values.Count)
                        {
                        case 1:         // scale
                            result = new ZoomboxView(values[0]);
                            break;

                        case 2:         // x, y
                            result = new ZoomboxView(values[0], values[1]);
                            break;

                        case 3:         // scale, x, y
                            result = new ZoomboxView(values[0], values[1], values[2]);
                            break;

                        case 4:         // x, y, width, height
                            result = new ZoomboxView(values[0], values[1], values[2], values[3]);
                            break;
                        }
                        break;
                    }
                }
            }
            return(result ?? base.ConvertFrom(typeDescriptorContext, cultureInfo, value));
        }
Пример #4
0
        public override object ConvertFrom(
            ITypeDescriptorContext typeDescriptorContext,
            CultureInfo cultureInfo,
            object value)
        {
            ZoomboxView result = null;
            if (value is double)
            {
                result = new ZoomboxView((double)value);
            }
            else if (value is Point)
            {
                result = new ZoomboxView((Point)value);
            }
            else if (value is Rect)
            {
                result = new ZoomboxView((Rect)value);
            }
            else if (value is string)
            {
                if (string.IsNullOrEmpty((value as string).Trim()))
                {
                    result = ZoomboxView.Empty;
                }
                else
                {
                    switch ((value as string).Trim().ToLower())
                    {
                        case "center":
                            result = ZoomboxView.Center;
                            break;

                        case "empty":
                            result = ZoomboxView.Empty;
                            break;

                        case "fill":
                            result = ZoomboxView.Fill;
                            break;

                        case "fit":
                            result = ZoomboxView.Fit;
                            break;

                        default:
                            // parse double values; respect the following separators: ' ', ';', or ','
                            List<double> values = new List<double>();
                            foreach (
                                string token in
                                    (value as string).Split(new[] { ' ', ';', ',' }, StringSplitOptions.RemoveEmptyEntries)
                                )
                            {
                                double d;
                                if (double.TryParse(token, out d))
                                {
                                    values.Add(d);
                                }
                                if (values.Count >= 4)
                                {
                                    // disregard additional values
                                    break;
                                }
                            }

                            switch (values.Count)
                            {
                                case 1: // scale
                                    result = new ZoomboxView(values[0]);
                                    break;

                                case 2: // x, y
                                    result = new ZoomboxView(values[0], values[1]);
                                    break;

                                case 3: // scale, x, y
                                    result = new ZoomboxView(values[0], values[1], values[2]);
                                    break;

                                case 4: // x, y, width, height
                                    result = new ZoomboxView(values[0], values[1], values[2], values[3]);
                                    break;
                            }
                            break;
                    }
                }
            }
            return (result ?? base.ConvertFrom(typeDescriptorContext, cultureInfo, value));
        }
Пример #5
0
 public void ZoomTo(ZoomboxView view)
 {
     UpdateView(view, true, true);
 }
Пример #6
0
        private void UpdateView(ZoomboxView view, bool allowAnimation, bool allowStackAddition, int stackIndex)
        {
            if (_contentPresenter == null || _content == null || !HasArrangedContentPresenter)
                return;

            // if an absolute view is being used and only a Scale value has been specified,
            // use the ZoomTo() function to perform a relative zoom
            if (view.ViewKind == ZoomboxViewKind.Absolute && PointHelper.IsEmpty(view.Position))
            {
                ZoomTo(view.Scale, allowStackAddition);
                return;
            }

            // disallow reentrancy
            if (!IsUpdatingView)
            {
                IsUpdatingView = true;
                try
                {
                    // determine the new scale and position
                    double newRelativeScale = _viewboxFactor;
                    Point newRelativePosition = new Point();
                    Rect region = Rect.Empty;
                    switch (view.ViewKind)
                    {
                        case ZoomboxViewKind.Empty:
                            break;

                        case ZoomboxViewKind.Absolute:
                            newRelativeScale = DoubleHelper.IsNaN(view.Scale) ? _relativeScale : view.Scale;
                            newRelativePosition = PointHelper.IsEmpty(view.Position)
                                ? _relativePosition
                                : new Point(view.Position.X, view.Position.Y) - ContentOffset * newRelativeScale;
                            break;

                        case ZoomboxViewKind.Region:
                            region = view.Region;
                            break;

                        case ZoomboxViewKind.Center:
                            {
                                // get the current ContentRect in the coordinate space of the Zoombox control
                                Rect currentContentRect =
                                    new Rect(
                                        _content.TranslatePoint(ContentRect.TopLeft, this),
                                        _content.TranslatePoint(ContentRect.BottomRight, this));

                                // inflate (or deflate) the rect by the appropriate amounts in the x & y directions
                                region = Rect.Inflate(currentContentRect,
                                    (RenderSize.Width / _viewboxFactor - currentContentRect.Width) / 2,
                                    (RenderSize.Height / _viewboxFactor - currentContentRect.Height) / 2);

                                // now translate the centered rect back to the coordinate space of the content
                                region = new Rect(TranslatePoint(region.TopLeft, _content),
                                    TranslatePoint(region.BottomRight, _content));
                            }
                            break;

                        case ZoomboxViewKind.Fit:
                            region = ContentRect;
                            break;

                        case ZoomboxViewKind.Fill:
                            region = CalculateFillRect();
                            break;
                    }

                    if (view.ViewKind != ZoomboxViewKind.Empty)
                    {
                        if (!region.IsEmpty)
                        {
                            // ZOOMING TO A REGION
                            CalculatePositionAndScale(region, ref newRelativePosition, ref newRelativeScale);
                        }
                        else if (view != ZoomboxView.Empty)
                        {
                            // USING ABSOLUTE POSITION AND SCALE VALUES

                            // ensure that the scale value falls within the valid range
                            if (newRelativeScale > MaxScale)
                            {
                                newRelativeScale = MaxScale;
                            }
                            else if (newRelativeScale < MinScale)
                            {
                                newRelativeScale = MinScale;
                            }
                        }

                        double currentScale = _relativeScale;
                        double currentX = _relativePosition.X;
                        double currentY = _relativePosition.Y;

                        ScaleTransform st = null;
                        TranslateTransform tt = null;
                        TransformGroup tg = null;

                        if (_contentPresenter.RenderTransform != Transform.Identity)
                        {
                            tg = _contentPresenter.RenderTransform as TransformGroup;
                            st = tg.Children[0] as ScaleTransform;
                            tt = tg.Children[1] as TranslateTransform;
                            currentScale = st.ScaleX;
                            currentX = tt.X;
                            currentY = tt.Y;
                        }

                        if (KeepContentInBounds)
                        {
                            Rect boundsRect =
                                new Rect(new Size(ContentRect.Width * newRelativeScale,
                                    ContentRect.Height * newRelativeScale));

                            // Calc viewport rect (should be inside bounds content rect)
                            Point viewportPosition = new Point(-newRelativePosition.X, -newRelativePosition.Y);
                            Rect viewportRect = new Rect(viewportPosition, _contentPresenter.RenderSize);

                            if (DoubleHelper.AreVirtuallyEqual(_relativeScale, newRelativeScale))
                            // we are positioning the content, not scaling
                            {
                                // Handle the width and height seperately since the content extent
                                // could be contained only partially in the viewport.  Also if the viewport is only
                                // partially contained within the content extent.

                                //
                                // Content extent width is greater than the viewport's width (Zoomed in).  Make sure we restrict
                                // the viewport X inside the content.
                                //
                                if (IsGreaterThanOrClose(boundsRect.Width, viewportRect.Width))
                                {
                                    if (boundsRect.Right < viewportRect.Right)
                                    {
                                        newRelativePosition.X = -(boundsRect.Width - viewportRect.Width);
                                    }

                                    if (boundsRect.Left > viewportRect.Left)
                                    {
                                        newRelativePosition.X = 0;
                                    }
                                }
                                //
                                // Viewport width is greater than the content extent's width (Zoomed out).  Make sure we restrict
                                // the content X inside the viewport.
                                //
                                else if (IsGreaterThanOrClose(viewportRect.Width, boundsRect.Width))
                                {
                                    if (viewportRect.Right < boundsRect.Right)
                                    {
                                        newRelativePosition.X = viewportRect.Width - boundsRect.Width;
                                    }

                                    if (viewportRect.Left > boundsRect.Left)
                                    {
                                        newRelativePosition.X = 0;
                                    }
                                }

                                //
                                // Content extent height is greater than the viewport's height (Zoomed in).  Make sure we restrict
                                // the viewport Y inside the content.
                                //
                                if (IsGreaterThanOrClose(boundsRect.Height, viewportRect.Height))
                                {
                                    if (boundsRect.Bottom < viewportRect.Bottom)
                                    {
                                        newRelativePosition.Y = -(boundsRect.Height - viewportRect.Height);
                                    }

                                    if (boundsRect.Top > viewportRect.Top)
                                    {
                                        newRelativePosition.Y = 0;
                                    }
                                }
                                //
                                // Viewport height is greater than the content extent's height (Zoomed out).  Make sure we restrict
                                // the content Y inside the viewport.
                                //
                                else if (IsGreaterThanOrClose(viewportRect.Height, boundsRect.Height))
                                {
                                    if (viewportRect.Bottom < boundsRect.Bottom)
                                    {
                                        newRelativePosition.Y = viewportRect.Height - boundsRect.Height;
                                    }

                                    if (viewportRect.Top > boundsRect.Top)
                                    {
                                        newRelativePosition.Y = 0;
                                    }
                                }
                            }
                        }

                        st = new ScaleTransform(newRelativeScale / _viewboxFactor, newRelativeScale / _viewboxFactor);
                        tt = new TranslateTransform(newRelativePosition.X, newRelativePosition.Y);
                        tg = new TransformGroup();
                        tg.Children.Add(st);
                        tg.Children.Add(tt);

                        _contentPresenter.RenderTransform = tg;

                        if (allowAnimation && IsAnimated)
                        {
                            DoubleAnimation daScale = new DoubleAnimation(currentScale, newRelativeScale / _viewboxFactor,
                                AnimationDuration);
                            daScale.AccelerationRatio = AnimationAccelerationRatio;
                            daScale.DecelerationRatio = AnimationDecelerationRatio;

                            DoubleAnimation daTranslateX = new DoubleAnimation(currentX, newRelativePosition.X,
                                AnimationDuration);
                            daTranslateX.AccelerationRatio = AnimationAccelerationRatio;
                            daTranslateX.DecelerationRatio = AnimationDecelerationRatio;

                            DoubleAnimation daTranslateY = new DoubleAnimation(currentY, newRelativePosition.Y,
                                AnimationDuration);
                            daTranslateY.AccelerationRatio = AnimationAccelerationRatio;
                            daTranslateY.DecelerationRatio = AnimationDecelerationRatio;
                            daTranslateY.CurrentTimeInvalidated += UpdateViewport;
                            daTranslateY.CurrentStateInvalidated += ZoomAnimationCompleted;

                            // raise animation beginning event before beginning the animations
                            RaiseEvent(new RoutedEventArgs(AnimationBeginningEvent, this));

                            st.BeginAnimation(ScaleTransform.ScaleXProperty, daScale);
                            st.BeginAnimation(ScaleTransform.ScaleYProperty, daScale);
                            tt.BeginAnimation(TranslateTransform.XProperty, daTranslateX);
                            tt.BeginAnimation(TranslateTransform.YProperty, daTranslateY);
                        }

                        // maintain the relative scale and position for dragging and animating purposes
                        _relativePosition = newRelativePosition;
                        _relativeScale = newRelativeScale;

                        // update the Scale and Position properties to keep them in sync with the current view
                        Scale = newRelativeScale;
                        _basePosition = newRelativePosition + ContentOffset * newRelativeScale;
                        UpdateViewport();
                    }

                    // add the current view to the view stack
                    if (EffectiveViewStackMode == ZoomboxViewStackMode.Auto && allowStackAddition)
                    {
                        // if the last view was pushed on the stack within the last 300 milliseconds, discard it
                        // since proximally close views are probably the result of a mouse wheel scroll
                        if (ViewStack.Count > 1
                            &&
                            Math.Abs(DateTime.Now.Ticks - _lastStackAddition.Ticks) <
                            TimeSpan.FromMilliseconds(300).Ticks)
                        {
                            ViewStack.RemoveAt(ViewStack.Count - 1);
                            _lastStackAddition = DateTime.Now - TimeSpan.FromMilliseconds(300);
                        }

                        // if the current view is the same as the last view, do nothing
                        if (ViewStack.Count > 0 && view == ViewStack.SelectedView)
                        {
                            // do nothing
                        }
                        else
                        {
                            // otherwise, push the current view on stack
                            ViewStack.PushView(view);
                            ViewStackIndex++;
                            stackIndex = ViewStackIndex;

                            // update the timestamp for the last stack addition
                            _lastStackAddition = DateTime.Now;
                        }
                    }

                    // update the stack indices used by CurrentViewChanged event
                    _lastViewIndex = CurrentViewIndex;
                    SetCurrentViewIndex(stackIndex);

                    // set the new view parameters
                    // NOTE: this is the only place where the CurrentView member should be set
                    SetCurrentView(view);
                }
                finally
                {
                    IsUpdatingView = false;
                }
            }
        }
Пример #7
0
 private void UpdateView(ZoomboxView view, bool allowAnimation, bool allowStackAddition)
 {
     UpdateView(view, allowAnimation, allowStackAddition, -1);
 }
Пример #8
0
 private void SetCurrentView(ZoomboxView value)
 {
     this.SetValue(Zoombox.CurrentViewPropertyKey, value);
 }
Пример #9
0
        private void ContentPresenterFirstArranged(object sender, EventArgs e)
        {
            // remove the handler
            _contentPresenter.LayoutUpdated -= ContentPresenterFirstArranged;

            // it's now safe to update the view
            HasArrangedContentPresenter = true;
            InvalidateVisual();

            // temporarily disable animations
            bool oldAnimated = IsAnimated;
            IsAnimated = false;
            try
            {
                // set the initial view
                double scale = Scale;
                Point position = Position;

                // if there are items in the ViewStack and a ViewStackIndex is set, use it
                if (EffectiveViewStackMode != ZoomboxViewStackMode.Disabled)
                {
                    bool isInitialViewSet = false;
                    if (ViewStack.Count > 0)
                    {
                        if (ViewStackIndex >= 0)
                        {
                            if (ViewStackIndex > ViewStack.Count - 1)
                            {
                                ViewStackIndex = ViewStack.Count - 1;
                            }
                            else
                            {
                                UpdateView(ViewStack[ViewStackIndex], false, false, ViewStackIndex);
                            }
                        }
                        else if (EffectiveViewStackMode != ZoomboxViewStackMode.Auto)
                        {
                            // if this is not an auto-stack, then ensure the index is set to a valid value
                            if (ViewStackIndex < 0)
                            {
                                ViewStackIndex = 0;
                            }
                        }

                        // if a ViewStackIndex has been set, apply the scale and position values, iff different than the default values
                        if (ViewStackIndex >= 0)
                        {
                            isInitialViewSet = true;
                            if (!DoubleHelper.IsNaN(scale) || !PointHelper.IsEmpty(position))
                            {
                                UpdateView(new ZoomboxView(scale, position), false, false);
                            }
                        }
                    }

                    if (!isInitialViewSet)
                    {
                        // set initial view according to the scale and position values and push it on the stack, as necessary
                        ZoomboxView initialView = new ZoomboxView(DoubleHelper.IsNaN(Scale) ? 1.0 : Scale,
                            PointHelper.IsEmpty(position) ? new Point() : position);

                        if (EffectiveViewStackMode == ZoomboxViewStackMode.Auto)
                        {
                            ViewStack.PushView(initialView);
                            ViewStackIndex = 0;
                        }
                        else
                        {
                            UpdateView(initialView, false, false);
                        }
                    }
                }
                else
                {
                    // just set initial view according to the scale and position values
                    ZoomboxView initialView = new ZoomboxView(DoubleHelper.IsNaN(Scale) ? 1.0 : Scale, position);
                    UpdateView(initialView, false, false);
                }
            }
            finally
            {
                IsAnimated = oldAnimated;
            }
        }