Exemplo n.º 1
0
        public override bool Equals(object o)
        {
            bool result = false;

            if (o is ZoomboxView)
            {
                ZoomboxView other = (ZoomboxView)o;
                if (this.ViewKind == other.ViewKind)
                {
                    switch (this.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);
        }
Exemplo n.º 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 == null ? base.ConvertTo(typeDescriptorContext, cultureInfo, value, destinationType) : result);
        }
Exemplo n.º 3
0
 private void SetCurrentView( ZoomboxView value )
 {
   this.SetValue( Zoombox.CurrentViewPropertyKey, value );
 }
Exemplo n.º 4
0
    private void UpdateView( ZoomboxView view, bool allowAnimation, bool allowStackAddition, int stackIndex )
    {
      if( _contentPresenter == null || _content == null || !this.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 ) )
      {
        this.ZoomTo( view.Scale, allowStackAddition );
        return;
      }

      // disallow reentrancy
      if( !this.IsUpdatingView )
      {
        this.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 ) - this.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( this.ContentRect.TopLeft, this ),
                    _content.TranslatePoint( this.ContentRect.BottomRight, this ) );

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

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

            case ZoomboxViewKind.Fit:
              region = this.ContentRect;
              break;

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

          if( view.ViewKind != ZoomboxViewKind.Empty )
          {
            if( !region.IsEmpty )
            {   // ZOOMING TO A REGION
              this.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 == true )
            {
              Rect boundsRect = new Rect( new Size( this.ContentRect.Width * newRelativeScale, this.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( this.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( this.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( this.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( this.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;

            var initialContentSize = ( _content is Viewbox ) ? ( ( Viewbox )_content ).Child.DesiredSize : _content.DesiredSize;
            var scaledContentSize = new Size( initialContentSize.Width * newRelativeScale, initialContentSize.Height * newRelativeScale );

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

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

              DoubleAnimation daTranslateY = new DoubleAnimation( currentY, newRelativePosition.Y, AnimationDuration );
              daTranslateY.AccelerationRatio = this.AnimationAccelerationRatio;
              daTranslateY.DecelerationRatio = this.AnimationDecelerationRatio;
              daTranslateY.CurrentTimeInvalidated += new EventHandler( this.UpdateViewport );
              daTranslateY.CurrentStateInvalidated += new EventHandler( this.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 );

              if( this.IsUsingScrollBars )
              {
                //Vertical scrollBar animations
                DoubleAnimation verticalMaxAnimation = new DoubleAnimation();
                verticalMaxAnimation.From = _verticalScrollBar.Maximum;
                verticalMaxAnimation.To = scaledContentSize.Height - _verticalScrollBar.ViewportSize;
                verticalMaxAnimation.Duration = AnimationDuration;
                _verticalScrollBar.BeginAnimation( ScrollBar.MaximumProperty, verticalMaxAnimation );

                DoubleAnimation verticalValueAnimation = new DoubleAnimation();
                verticalValueAnimation.From = _verticalScrollBar.Value;
                verticalValueAnimation.To = -newRelativePosition.Y;
                verticalValueAnimation.Duration = AnimationDuration;
                verticalValueAnimation.Completed += this.VerticalValueAnimation_Completed;
                _verticalScrollBar.BeginAnimation( ScrollBar.ValueProperty, verticalValueAnimation );

                //Horizontal scrollBar animations
                DoubleAnimation horizontalMaxAnimation = new DoubleAnimation();
                horizontalMaxAnimation.From = _horizontalScrollBar.Maximum;
                horizontalMaxAnimation.To = scaledContentSize.Width - _horizontalScrollBar.ViewportSize;
                horizontalMaxAnimation.Duration = AnimationDuration;
                _horizontalScrollBar.BeginAnimation( ScrollBar.MaximumProperty, horizontalMaxAnimation );

                DoubleAnimation horizontalValueAnimation = new DoubleAnimation();
                horizontalValueAnimation.From = _horizontalScrollBar.Value;
                horizontalValueAnimation.To = -newRelativePosition.X;
                horizontalValueAnimation.Duration = AnimationDuration;
                horizontalValueAnimation.Completed += this.HorizontalValueAnimation_Completed;
                _horizontalScrollBar.BeginAnimation( ScrollBar.ValueProperty, horizontalValueAnimation );
              }
            }
            else if( this.IsUsingScrollBars )
            {
              //Vertical scrollBar
              _verticalScrollBar.Maximum = scaledContentSize.Height - _verticalScrollBar.ViewportSize;
              _verticalScrollBar.Value = -newRelativePosition.Y;
              //Horizontal scrollBar
              _horizontalScrollBar.Maximum = scaledContentSize.Width - _horizontalScrollBar.ViewportSize;
              _horizontalScrollBar.Value = -newRelativePosition.X;
            }

            // 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
            this.Scale = newRelativeScale;
            _basePosition = newRelativePosition + this.ContentOffset * newRelativeScale;
            this.UpdateViewport();
          }

          // add the current view to the view stack
          if( this.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( this.ViewStack.Count > 1
              && Math.Abs( DateTime.Now.Ticks - _lastStackAddition.Ticks ) < TimeSpan.FromMilliseconds( 300 ).Ticks )
            {
              this.ViewStack.RemoveAt( this.ViewStack.Count - 1 );
              _lastStackAddition = DateTime.Now - TimeSpan.FromMilliseconds( 300 );
            }

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

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

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

          // set the new view parameters
          // NOTE: this is the only place where the CurrentView member should be set
          this.SetCurrentView( view );
        }
        finally
        {
          this.IsUpdatingView = false;
        }
      }
    }
Exemplo n.º 5
0
 private void UpdateView( ZoomboxView view, bool allowAnimation, bool allowStackAddition )
 {
   this.UpdateView( view, allowAnimation, allowStackAddition, -1 );
 }
Exemplo n.º 6
0
    private void ContentPresenterFirstArranged( object sender, EventArgs e )
    {
      // remove the handler
      _contentPresenter.LayoutUpdated -= new EventHandler( this.ContentPresenterFirstArranged );

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

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

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

            // if a ViewStackIndex has been set, apply the scale and position values, iff different than the default values
            if( this.ViewStackIndex >= 0 )
            {
              isInitialViewSet = true;
              if( !DoubleHelper.IsNaN( scale ) || !PointHelper.IsEmpty( position ) )
              {
                this.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( this.EffectiveViewStackMode == ZoomboxViewStackMode.Auto )
            {
              this.ViewStack.PushView( initialView );
              this.ViewStackIndex = 0;
            }
            else
            {
              this.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 : this.Scale, position );
          this.UpdateView( initialView, false, false );
        }
      }
      finally
      {
        IsAnimated = oldAnimated;
      }
    }
Exemplo n.º 7
0
 public void ZoomTo( ZoomboxView view )
 {
   this.UpdateView( view, true, true );
 }
Exemplo n.º 8
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 char[] { ' ', ';', ',' }, 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 == null ? base.ConvertFrom( typeDescriptorContext, cultureInfo, value ) : result );
    }
Exemplo n.º 9
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 char[] { ' ', ';', ',' }, 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 == null ? base.ConvertFrom(typeDescriptorContext, cultureInfo, value) : result);
        }