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); }
/// <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); }
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; } }
/// <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); } }
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)); }
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)); }
/// <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); }
private static void OnMajorTickStepPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.ResetAndArrangeTicks(); } }
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); } }
private static void OnIndicatorsZIndexPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.UpdateIndicatorContainerZIndex((int)args.NewValue); } }
/// <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); }
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)); }
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; }
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); } } }
/// <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); } }