private void ArrangeMarker(Size desiredSize, double newValue)
        {
            if (this.Owner == null)
            {
                return;
            }

            double radius = Math.Min(desiredSize.Width, desiredSize.Height) / 2;

            switch (this.Owner.OwnerGauge.GaugeType)
            {
            case GaugeType.Linear:
                double distance = RadGauge.MapLogicalToPhysicalValue(newValue - this.minValue, this.isHorizontal ? desiredSize.Width : desiredSize.Height, this.MinMaxValueDifference);
                this.ArrangeLinearly(distance, this.CreateStartPoint(desiredSize), this.CreateDirection());
                break;

            case GaugeType.Radial:
                double angleInDegrees = RadGauge.MapLogicalToPhysicalValue(newValue - this.Owner.OwnerGauge.MinValue, this.maxAngle - this.minAngle, this.MinMaxValueDifference);
                double currentAngle   = this.minAngle + angleInDegrees;

                if (this.IsRotated)
                {
                    this.visualElementRotation.Angle = this.initialRotationAngle + currentAngle;
                }
                else
                {
                    this.visualElementRotation.Angle = this.initialRotationAngle;
                }

                double angleInRadians = RadialGaugePanel.ConvertDegreesToRadians(currentAngle);
                Point  center         = new Point((desiredSize.Width / 2) - (this.visualElement.DesiredSize.Width / 2), (desiredSize.Height / 2) - (this.visualElement.DesiredSize.Height / 2));
                this.ArrangeRadially(angleInRadians, center, radius);
                break;
            }
        }
        private Point ArrangeRectangle(double value, Size finalSize)
        {
            Point result = new Point();

            double finalValue = Math.Abs(value - this.StartValue);
            double extent     = RadGauge.MapLogicalToPhysicalValue(finalValue, this.isHorizontal ? finalSize.Width : finalSize.Height, this.MinMaxValueDifference);

            bool   flip      = this.Value < this.StartValue;
            double barLength = extent;

            if (this.isHorizontal)
            {
                this.bar.Width  = barLength;
                this.bar.Height = this.Thickness;

                result.X = flip ? this.barLocation - extent : this.barLocation;
                result.Y = ((finalSize.Height / 2) - (this.bar.Height / 2)) + RadLinearGauge.GetIndicatorOffset(this);
            }
            else
            {
                this.bar.Height = barLength;
                this.bar.Width  = this.Thickness;

                result.X = ((finalSize.Width / 2) - (this.bar.Width / 2)) + RadLinearGauge.GetIndicatorOffset(this);
                result.Y = flip ? this.barLocation : this.barLocation - extent;
            }

            return(result);
        }
示例#3
0
        /// <summary>
        /// Called in the measure layout pass to determine the desired size.
        /// </summary>
        /// <param name="availableSize">The available size that was given by the layout system.</param>
        /// <returns>Returns the desired size of the indicator.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            if (this.MeasureCallback != null)
            {
                this.MeasureCallback();
            }

            if (this.ownerPanel == null)
            {
                this.ownerPanel = ElementTreeHelper.FindVisualAncestor <GaugePanel>(this);
            }

            Size result = RadGauge.NormalizeSize(availableSize);

            if (result.Width == 0 || result.Height == 0)
            {
                result = this.ownerPanel.LastMeasureSize;
            }

            this.Update(result);

            this.LastMeasureSize = result;

            return(result);
        }
示例#4
0
        private static void OnValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            double newVal = (double)args.NewValue;

            RadGauge.ValidateValue(newVal);

            GaugeIndicator indicator = sender as GaugeIndicator;

            if (!indicator.IsTemplateApplied || indicator.Owner == null || indicator.IsInternalPropertyChange)
            {
                indicator.ActualValue = newVal;
                return;
            }

            indicator.ClampValueToRange(ValueProperty);

            if (indicator.isAnimationRunning)
            {
                indicator.isAnimationRunning = false;
                indicator.storyboard.Seek(new TimeSpan(0));
            }

            double value = indicator.Value;

            if (indicator.IsAnimated)
            {
                double from = (double)args.OldValue;
                StartValueAnimation(from, newVal, indicator);
            }
            else
            {
                indicator.ActualValue = value;
            }
        }
示例#5
0
        /// <summary>
        /// Defines the arrange logic for the ticks.
        /// </summary>
        /// <param name="finalSize">The size in which the ticks can be arranged.</param>
        internal override void ArrangeTicksOverride(Size finalSize)
        {
            int tickCount = this.TickCount;

            if (tickCount == 0 || this.OwnerGauge.TickStep == 0)
            {
                return;
            }

            var gauge = this.OwnerGauge as RadRadialGauge;

            double tickRadiusScale = gauge.TickRadiusScale;
            double minValue        = this.OwnerGauge.MinValue;
            double maxValue        = this.OwnerGauge.MaxValue;
            double tickStep        = this.OwnerGauge.TickStep;
            double minAngle        = gauge.MinAngle;
            double maxAngle        = gauge.MaxAngle;

            int tickCounter = 0;

            for (double tickValue = 0; tickCounter < tickCount; tickValue += tickStep, tickCounter++)
            {
                double angle = RadGauge.MapLogicalToPhysicalValue(tickValue, maxAngle - minAngle, maxValue - minValue);
                this.ArrangeTick(this.GetTick(tickCounter), finalSize, angle, tickRadiusScale);
            }
        }
示例#6
0
        private void ArrangeLabel(ContentPresenter label, double value, double offset)
        {
            double halfLabelHeight = label.DesiredSize.Height / 2;
            double halfLabelWidth  = label.DesiredSize.Width / 2;

            bool flipLayout = this.OwnerGauge.MaxValue < this.OwnerGauge.MinValue;

            double minMaxDiff = Math.Abs(this.OwnerGauge.MaxValue - this.OwnerGauge.MinValue);
            double valueDiff  = flipLayout ? value - this.OwnerGauge.MaxValue : value - this.OwnerGauge.MinValue;

            double tmp  = this.isHorizontal ? halfLabelWidth : halfLabelHeight;
            double half = flipLayout ? -tmp : tmp;
            double distanceFromLayoutRectEdge = RadGauge.MapLogicalToPhysicalValue(valueDiff, this.availableExtent, minMaxDiff) - half;

            if (flipLayout)
            {
                distanceFromLayoutRectEdge = this.availableExtent - distanceFromLayoutRectEdge;
            }

            double left = 0;
            double top  = 0;

            if (this.isHorizontal)
            {
                left = distanceFromLayoutRectEdge;
                top  = (this.halfAvailableHeight - halfLabelHeight) + offset;
            }
            else
            {
                left = (this.halfAvailableWidth - halfLabelWidth) + offset;
                top  = this.availableExtent - distanceFromLayoutRectEdge - label.DesiredSize.Height;
            }

            label.Arrange(new Rect(new Point(left, top), label.DesiredSize));
        }
示例#7
0
        private void ArrangeTick(ContentPresenter tick, double value)
        {
            double halfTickHeight = tick.DesiredSize.Height / 2;
            double halfTickWidth  = tick.DesiredSize.Width / 2;

            double minMaxDiff = Math.Abs(this.OwnerGauge.MaxValue - this.OwnerGauge.MinValue);
            double distance   = RadGauge.MapLogicalToPhysicalValue(value, this.availableExtent, minMaxDiff);

            if (this.OwnerGauge.MaxValue < this.OwnerGauge.MinValue)
            {
                distance = this.availableExtent - distance;
            }

            double left = 0;
            double top  = 0;

            if (this.isHorizontal)
            {
                tick.RenderTransform = null;
                left = distance - halfTickWidth;
                top  = this.halfAvailableHeight - halfTickHeight;
            }
            else
            {
                tick.RenderTransform       = this.verticalTickTransform;
                tick.RenderTransformOrigin = new Point(0.5, 0.5);
                left = this.halfAvailableWidth - halfTickWidth;
                top  = this.availableExtent - distance - halfTickHeight;
            }

            tick.Arrange(new Rect(new Point(left, top), tick.DesiredSize));
        }
示例#8
0
        /// <summary>
        /// Calculates and angle in degrees based on a value, a value range, an angle range and a sweep direction.
        /// </summary>
        /// <param name="context">A context that contains the value to be converted to an angle.</param>
        /// <returns>Returns an angle in radians that corresponds to the provided value in the context.</returns>
        internal static double CalculateAngle(CalculateAngleContext context)
        {
            double angleDeg = RadGauge.MapLogicalToPhysicalValue(context.value - context.startValue, context.gaugePhysicalLength, context.gaugeLogicalLength);

            var angle = RadialGaugePanel.ConvertDegreesToRadians(angleDeg);

            return(RadialGaugePanel.ConvertDegreesToRadians(context.minAngle) + angle);
        }
示例#9
0
        private static void OnMajorTickStepPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            RadGauge gauge = sender as RadGauge;

            if (gauge.panel != null)
            {
                gauge.panel.ResetAndArrangeTicks();
            }
        }
示例#10
0
        private static void OnLabelTemplatePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            RadGauge gauge = sender as RadGauge;

            if (gauge.panel != null)
            {
                gauge.panel.UpdateTickTemplates(args.NewValue as DataTemplate, TickType.Label);
            }
        }
示例#11
0
        private static void OnIndicatorsZIndexPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            RadGauge gauge = sender as RadGauge;

            if (gauge.panel != null)
            {
                gauge.panel.UpdateIndicatorContainerZIndex((int)args.NewValue);
            }
        }
示例#12
0
        /// <summary>
        /// Called in the measure layout pass to determine the desired size.
        /// </summary>
        /// <param name="availableSize">The available size that was given by the layout system.</param>
        /// <returns>Returns the desired size of the panel.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            if (this.ownerGauge == null)
            {
                Debug.Assert(false, "Must have an owner gauge reference at this point.");
                return(base.MeasureOverride(availableSize));
            }

            Size desired = RadGauge.NormalizeSize(availableSize);

            if (this.arrangeSize.Width > 0 || this.arrangeSize.Height > 0)
            {
                this.measureSize = this.arrangeSize;
            }
            else
            {
                this.measureSize = desired;
            }

            if (this.ticks.Count == 0)
            {
                this.CreateTicks();
            }

            if (this.labels.Count == 0)
            {
                this.CreateLabels();
            }

            foreach (GaugeIndicator indicator in this.indicatorContainer.Children)
            {
                indicator.Owner = this;
                if (indicator.LastMeasureSize == this.measureSize || indicator.DesiredSize == this.measureSize)
                {
                    indicator.InvalidateMeasure();
                }
                indicator.Measure(this.measureSize);
            }
            this.indicatorContainer.Measure(this.measureSize);

            foreach (ContentPresenter tick in this.ticks)
            {
                tick.Measure(this.measureSize);
            }

            foreach (ContentPresenter label in this.labels)
            {
                label.Measure(this.measureSize);
            }

            this.isMeasurePassed = true;

            return(desired);
        }
示例#13
0
        private static void OnMaxValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            double newVal = (double)args.NewValue;

            ValidateValue(newVal);

            RadGauge gauge = sender as RadGauge;

            if (gauge.panel != null)
            {
                gauge.panel.UpdateOnMinMaxValueChange();
            }
        }
        /// <summary>
        /// This method is called whenever the segments
        /// need to recreate their visual representation.
        /// </summary>
        /// <param name="availableSize">The available size which the visual parts can occupy.</param>
        internal override void ResetSegments(Size availableSize)
        {
            this.SegmentInfos.Clear();

            this.extent = this.isHorizontal ? availableSize.Width : availableSize.Height;

            double logicalRange  = this.MinMaxValueDifference;
            double physicalStart = RadGauge.MapLogicalToPhysicalValue(this.StartValue - this.minValue, this.extent, logicalRange);

            double indicatorExtent = RadGauge.MapLogicalToPhysicalValue(this.ActualValue - this.minValue, this.extent, logicalRange) - physicalStart;
            double startPosition   = this.isHorizontal ? physicalStart : (this.extent - physicalStart);

            double halfAvailableWidth  = availableSize.Width / 2;
            double halfAvailableHeight = availableSize.Height / 2;
            double offset = RadLinearGauge.GetIndicatorOffset(this);

            foreach (BarIndicatorSegment segment in this.Segments)
            {
                if (segment.Path == null)
                {
                    Debug.Assert(false, "Missing segment path.");
                    continue;
                }
                double lengthRatio = segment.Length / this.TotalSegmentLength;
                double lineLength  = indicatorExtent * lengthRatio;

                SegmentInfo info = new SegmentInfo();
                info.Start = startPosition;
                info.End   = startPosition + (this.isHorizontal ? lineLength : -lineLength);
                this.SegmentInfos.Add(info);

                LineSegment line = new LineSegment();
                line.Point = this.isHorizontal ? new Point(info.End, halfAvailableHeight + offset) : new Point(halfAvailableWidth + offset, info.End);

                info.PathSegment = line;

                PathFigure figure = new PathFigure();
                figure.StartPoint = this.isHorizontal ? new Point(info.Start, halfAvailableHeight + offset) : new Point(halfAvailableWidth + offset, info.Start);
                figure.Segments.Add(line);

                PathGeometry geom = new PathGeometry();
                geom.Figures.Add(figure);

                Path path = segment.Path;
                path.Stroke          = segment.Stroke;
                path.StrokeThickness = segment.Thickness;
                path.Data            = geom;

                startPosition = info.End;
            }
        }
        private void UpdateAngle(double value)
        {
            if (this.Owner == null || this.Owner.OwnerGauge == null)
            {
                return;
            }

            var gauge    = this.Owner.OwnerGauge as RadRadialGauge;
            var minAngle = gauge.MinAngle;
            var maxAngle = gauge.MaxAngle;

            double angle = RadGauge.MapLogicalToPhysicalValue(value, maxAngle - minAngle, this.MinMaxValueDifference);

            this.needleRotation.Angle = minAngle + angle;
        }
        private void UpdateBarLocation(double startValue)
        {
            double minValue = Math.Min(this.Owner.OwnerGauge.MinValue, this.Owner.OwnerGauge.MaxValue);
            double extent   = RadGauge.MapLogicalToPhysicalValue(startValue - minValue, this.isHorizontal ? this.Owner.LastMeasureSize.Width : this.Owner.LastMeasureSize.Height, this.MinMaxValueDifference);

            if (this.isHorizontal)
            {
                this.barLocation = extent;
            }
            else
            {
                this.barLocation = this.Owner.LastMeasureSize.Height - extent;
            }

            this.SetLocation(this.ArrangeRectangle(this.ActualValue, this.Owner.LastMeasureSize));
        }
示例#17
0
        private void UpdateAngleRestrictions()
        {
            var gauge = this.Owner.OwnerGauge as RadRadialGauge;

            var gaugeMinAngle = gauge.MinAngle;
            var gaugeMaxAngle = gauge.MaxAngle;

            var physicalLength = gaugeMaxAngle - gaugeMinAngle;
            var logicalLength  = Math.Abs(this.Owner.OwnerGauge.MaxValue - this.Owner.OwnerGauge.MinValue);

            var logicalStartValue = this.StartValue - this.Owner.OwnerGauge.MinValue;
            var startValueAngle   = RadGauge.MapLogicalToPhysicalValue(logicalStartValue, physicalLength, logicalLength);
            var actualValueAngle  = RadGauge.MapLogicalToPhysicalValue(this.ActualValue - this.Owner.OwnerGauge.MinValue, physicalLength, logicalLength);

            this.minAngle = gaugeMinAngle + startValueAngle;
            this.maxAngle = gaugeMinAngle + actualValueAngle;
        }
        private void PrepareReset(Size availableSize)
        {
            this.radiusScale = RadRadialGauge.GetIndicatorRadiusScale(this);
            this.center      = new Point(availableSize.Width / 2, availableSize.Height / 2);
            this.radius      = Math.Min(availableSize.Width, availableSize.Height) / 2;

            var gauge          = this.Owner.OwnerGauge as RadRadialGauge;
            var gaugeMinAngle  = gauge.MinAngle;
            var gaugeMaxAngle  = gauge.MaxAngle;
            var physicalLength = gaugeMaxAngle - gaugeMinAngle;
            var logicalLength  = Math.Abs(this.Owner.OwnerGauge.MaxValue - this.Owner.OwnerGauge.MinValue);

            var logicalStartValue = this.StartValue - this.Owner.OwnerGauge.MinValue;
            var startValueAngle   = RadGauge.MapLogicalToPhysicalValue(logicalStartValue, physicalLength, logicalLength);
            var actualValueAngle  = RadGauge.MapLogicalToPhysicalValue(this.ActualValue - this.Owner.OwnerGauge.MinValue, physicalLength, logicalLength);

            this.minAngle = gaugeMinAngle + startValueAngle;
            this.maxAngle = gaugeMinAngle + actualValueAngle;
        }
示例#19
0
        private static void OnMaxValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            double newVal = (double)args.NewValue;

            ValidateValue(newVal);

            RadGauge gauge = sender as RadGauge;

            if (gauge.panel != null)
            {
                gauge.panel.UpdateOnMinMaxValueChange();
            }

            if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
            {
                var peer = FrameworkElementAutomationPeer.FromElement(gauge) as RadGaugeAutomationPeer;
                if (peer != null)
                {
                    peer.RaiseMinimumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue);
                }
            }
        }
        /// <summary>
        /// This method is called so that a segmented indicator can synchronize
        /// its visual state with its current value.
        /// </summary>
        /// <param name="value">The value to synchronize with.</param>
        internal override void SyncWithValue(double value)
        {
            double currentPosition = RadGauge.MapLogicalToPhysicalValue(value - this.minValue, this.extent, this.MinMaxValueDifference);

            if (!this.isHorizontal)
            {
                currentPosition = this.extent - currentPosition;
            }

            foreach (SegmentInfo info in this.SegmentInfos)
            {
                LineSegment line         = (LineSegment)info.PathSegment;
                Point       currentPoint = line.Point;
                double      start        = info.Start;
                double      end          = info.End;

                if (!this.isHorizontal)
                {
                    double tmp = start;
                    start = end;
                    end   = tmp;
                }

                if (start <= currentPosition && end >= currentPosition)
                {
                    line.Point = this.isHorizontal ? new Point(currentPosition, currentPoint.Y) : new Point(currentPoint.X, currentPosition);
                }
                else if (end <= currentPosition)
                {
                    line.Point = this.isHorizontal ? new Point(info.End, currentPoint.Y) : new Point(currentPoint.X, info.Start);
                }
                else if (start >= currentPosition)
                {
                    line.Point = this.isHorizontal ? new Point(info.Start, currentPoint.Y) : new Point(currentPoint.X, info.End);
                }
            }
        }
示例#21
0
        /// <summary>
        /// Defines the arrange logic for the labels.
        /// </summary>
        /// <param name="finalSize">The size in which the labels can be arranged.</param>
        internal override void ArrangeLabelsOverride(Size finalSize)
        {
            if (this.LabelCount == 0 || this.OwnerGauge.LabelStep == 0)
            {
                return;
            }

            var gauge = this.OwnerGauge as RadRadialGauge;

            double labelRadiusScale = gauge.LabelRadiusScale;
            double minValue         = this.OwnerGauge.MinValue;
            double maxValue         = this.OwnerGauge.MaxValue;
            double labelStep        = this.OwnerGauge.LabelStep;
            double minAngle         = gauge.MinAngle;
            double maxAngle         = gauge.MaxAngle;

            int j = 0;

            for (double i = minValue; i <= maxValue; i += labelStep, j++)
            {
                double angle = RadGauge.MapLogicalToPhysicalValue(i - minValue, maxAngle - minAngle, maxValue - minValue);
                this.ArrangeLabel(this.GetLabel(j), finalSize, angle, labelRadiusScale);
            }
        }