mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-04 00:35:46 +08:00
790 lines
30 KiB
C#
790 lines
30 KiB
C#
//copyright(c) 2016 Alberto Rodriguez
|
|
|
|
//Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
//of this software and associated documentation files (the "Software"), to deal
|
|
//in the Software without restriction, including without limitation the rights
|
|
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
//copies of the Software, and to permit persons to whom the Software is
|
|
//furnished to do so, subject to the following conditions:
|
|
|
|
//The above copyright notice and this permission notice shall be included in all
|
|
//copies or substantial portions of the Software.
|
|
|
|
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
//SOFTWARE.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Windows.Input;
|
|
using Windows.Foundation;
|
|
using Windows.UI;
|
|
using Windows.UI.Text;
|
|
using Windows.UI.Xaml;
|
|
using Windows.UI.Xaml.Controls;
|
|
using Windows.UI.Xaml.Data;
|
|
using Windows.UI.Xaml.Media;
|
|
using Windows.UI.Xaml.Shapes;
|
|
using LiveCharts.Charts;
|
|
using LiveCharts.Definitions.Charts;
|
|
using LiveCharts.Dtos;
|
|
using LiveCharts.Events;
|
|
using LiveCharts.Uwp.Components;
|
|
|
|
namespace LiveCharts.Uwp
|
|
{
|
|
/// <summary>
|
|
/// An Axis of a chart
|
|
/// </summary>
|
|
public class Axis : FrameworkElement, IAxisView
|
|
{
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of Axis class
|
|
/// </summary>
|
|
public Axis()
|
|
{
|
|
TitleBlock = BindATextBlock();
|
|
|
|
this.SetIfNotSet(SeparatorProperty, new Separator());
|
|
this.SetIfNotSet(SectionsProperty, new SectionsCollection());
|
|
|
|
TitleBlock.SetBinding(TextBlock.TextProperty,
|
|
new Binding {Path = new PropertyPath("Title"), Source = this});
|
|
}
|
|
#endregion
|
|
|
|
#region Events
|
|
/// <summary>
|
|
/// Occurs when an axis range changes by an user action (zooming or panning)
|
|
/// </summary>
|
|
public event RangeChangedHandler RangeChanged;
|
|
|
|
/// <summary>
|
|
/// The range changed command property
|
|
/// </summary>
|
|
public static readonly DependencyProperty RangeChangedCommandProperty = DependencyProperty.Register(
|
|
"RangeChangedCommand", typeof(ICommand), typeof(Axis), new PropertyMetadata(default(ICommand)));
|
|
/// <summary>
|
|
/// Gets or sets the command to execute when an axis range changes by an user action (zooming or panning)
|
|
/// </summary>
|
|
/// <value>
|
|
/// The range changed command.
|
|
/// </value>
|
|
public ICommand RangeChangedCommand
|
|
{
|
|
get { return (ICommand)GetValue(RangeChangedCommandProperty); }
|
|
set { SetValue(RangeChangedCommandProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs before an axis range changes by an user action (zooming or panning)
|
|
/// </summary>
|
|
public event PreviewRangeChangedHandler PreviewRangeChanged;
|
|
|
|
/// <summary>
|
|
/// The preview range changed command property
|
|
/// </summary>
|
|
public static readonly DependencyProperty PreviewRangeChangedCommandProperty = DependencyProperty.Register(
|
|
"PreviewRangeChangedCommand", typeof(ICommand), typeof(Axis), new PropertyMetadata(default(ICommand)));
|
|
/// <summary>
|
|
/// Gets or sets the command to execute before an axis range changes by an user action (zooming or panning)
|
|
/// </summary>
|
|
/// <value>
|
|
/// The preview range changed command.
|
|
/// </value>
|
|
public ICommand PreviewRangeChangedCommand
|
|
{
|
|
get { return (ICommand)GetValue(PreviewRangeChangedCommandProperty); }
|
|
set { SetValue(PreviewRangeChangedCommandProperty, value); }
|
|
}
|
|
#endregion
|
|
|
|
#region properties
|
|
|
|
private TextBlock TitleBlock { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets the Model of the axis, the model is used a DTO to communicate with the core of the library.
|
|
/// </summary>
|
|
public AxisCore Model { get; set; }
|
|
/// <summary>
|
|
/// Gets previous Max Value
|
|
/// </summary>
|
|
public double PreviousMaxValue { get; internal set; }
|
|
/// <summary>
|
|
/// Gets previous Min Value
|
|
/// </summary>
|
|
public double PreviousMinValue { get; internal set; }
|
|
#endregion
|
|
|
|
#region Dependency Properties
|
|
|
|
/// <summary>
|
|
/// The labels property
|
|
/// </summary>
|
|
public static readonly DependencyProperty LabelsProperty = DependencyProperty.Register(
|
|
"Labels", typeof (IList<string>), typeof (Axis),
|
|
new PropertyMetadata(default(IList<string>), UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets axis labels, labels property stores the array to map for each index and value, for example if axis value is 0 then label will be labels[0], when value 1 then labels[1], value 2 then labels[2], ..., value n labels[n], use this property instead of a formatter when there is no conversion between value and label for example names, if you are plotting sales vs salesman name.
|
|
/// </summary>
|
|
//[TypeConverter(typeof(StringCollectionConverter))]
|
|
public IList<string> Labels
|
|
{
|
|
get { return (IList<string>) GetValue(LabelsProperty); }
|
|
set { SetValue(LabelsProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The sections property
|
|
/// </summary>
|
|
public static readonly DependencyProperty SectionsProperty = DependencyProperty.Register(
|
|
"Sections", typeof (SectionsCollection), typeof (Axis), new PropertyMetadata(default(SectionsCollection)));
|
|
/// <summary>
|
|
/// Gets or sets the axis sectionsCollection, a section is useful to highlight ranges or values in a chart.
|
|
/// </summary>
|
|
public SectionsCollection Sections
|
|
{
|
|
get { return (SectionsCollection) GetValue(SectionsProperty); }
|
|
set { SetValue(SectionsProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The label formatter property
|
|
/// </summary>
|
|
public static readonly DependencyProperty LabelFormatterProperty = DependencyProperty.Register(
|
|
"LabelFormatter", typeof (Func<double, string>), typeof (Axis),
|
|
new PropertyMetadata(default(Func<double, string>), UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets the function to convert a value to label, for example when you need to display your chart as currency ($1.00) or as degrees (10°), if Labels property is not null then formatter is ignored, and label will be pulled from Labels prop.
|
|
/// </summary>
|
|
public Func<double, string> LabelFormatter
|
|
{
|
|
get { return (Func<double, string>) GetValue(LabelFormatterProperty); }
|
|
set { SetValue(LabelFormatterProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The separator property
|
|
/// </summary>
|
|
public static readonly DependencyProperty SeparatorProperty = DependencyProperty.Register(
|
|
"Separator", typeof (Separator), typeof (Axis),
|
|
new PropertyMetadata(default(Separator), UpdateChart()));
|
|
/// <summary>
|
|
/// Get or sets configuration for parallel lines to axis.
|
|
/// </summary>
|
|
public Separator Separator
|
|
{
|
|
get { return (Separator) GetValue(SeparatorProperty); }
|
|
set { SetValue(SeparatorProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The show labels property
|
|
/// </summary>
|
|
public static readonly DependencyProperty ShowLabelsProperty = DependencyProperty.Register(
|
|
"ShowLabels", typeof (bool), typeof (Axis),
|
|
new PropertyMetadata(true, LabelsVisibilityChanged));
|
|
|
|
/// <summary>
|
|
/// Gets or sets if labels are shown in the axis.
|
|
/// </summary>
|
|
public bool ShowLabels
|
|
{
|
|
get { return (bool) GetValue(ShowLabelsProperty); }
|
|
set { SetValue(ShowLabelsProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The maximum value property
|
|
/// </summary>
|
|
public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register(
|
|
"MaxValue", typeof (double), typeof (Axis),
|
|
new PropertyMetadata(double.NaN, UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets axis max value, set it to double.NaN to make this property Auto, default value is double.NaN
|
|
/// </summary>
|
|
public double MaxValue
|
|
{
|
|
get { return (double) GetValue(MaxValueProperty); }
|
|
set { SetValue(MaxValueProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The minimum value property
|
|
/// </summary>
|
|
public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register(
|
|
"MinValue", typeof (double), typeof (Axis),
|
|
new PropertyMetadata(double.NaN, UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets axis min value, set it to double.NaN to make this property Auto, default value is double.NaN
|
|
/// </summary>
|
|
public double MinValue
|
|
{
|
|
get { return (double)GetValue(MinValueProperty); }
|
|
set { SetValue(MinValueProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the actual minimum value.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The actual minimum value.
|
|
/// </value>
|
|
public double ActualMinValue => Model.BotLimit;
|
|
|
|
/// <summary>
|
|
/// Gets the actual maximum value.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The actual maximum value.
|
|
/// </value>
|
|
public double ActualMaxValue => Model.TopLimit;
|
|
|
|
/// <summary>
|
|
/// The minimum range property
|
|
/// </summary>
|
|
public static readonly DependencyProperty MinRangeProperty = DependencyProperty.Register(
|
|
"MinRange", typeof(double), typeof(Axis), new PropertyMetadata(double.MinValue));
|
|
/// <summary>
|
|
/// Gets or sets the min range this axis can display, useful to limit user zooming.
|
|
/// </summary>
|
|
public double MinRange
|
|
{
|
|
get { return (double) GetValue(MinRangeProperty); }
|
|
set { SetValue(MinRangeProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The maximum range property
|
|
/// </summary>
|
|
public static readonly DependencyProperty MaxRangeProperty = DependencyProperty.Register(
|
|
"MaxRange", typeof(double), typeof(Axis), new PropertyMetadata(double.MaxValue));
|
|
/// <summary>
|
|
/// Gets or sets the max range this axis can display, useful to limit user zooming.
|
|
/// </summary>
|
|
public double MaxRange
|
|
{
|
|
get { return (double) GetValue(MaxRangeProperty); }
|
|
set { SetValue(MaxRangeProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The title property
|
|
/// </summary>
|
|
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
|
|
"Title", typeof(string), typeof(Axis),
|
|
new PropertyMetadata(null, UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets axis title, the title will be displayed only if this property is not null, default is null.
|
|
/// </summary>
|
|
public string Title
|
|
{
|
|
get { return (string)GetValue(TitleProperty); }
|
|
set { SetValue(TitleProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The position property
|
|
/// </summary>
|
|
public static readonly DependencyProperty PositionProperty = DependencyProperty.Register(
|
|
"Position", typeof (AxisPosition), typeof (Axis),
|
|
new PropertyMetadata(default(AxisPosition), UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets the axis position, default is Axis.Position.LeftBottom, when the axis is at Y and Position is LeftBottom, then axis will be placed at left, RightTop position will place it at Right, when the axis is at X and position LeftBottom, the axis will be placed at bottom, if position is RightTop then it will be placed at top.
|
|
/// </summary>
|
|
public AxisPosition Position
|
|
{
|
|
get { return (AxisPosition) GetValue(PositionProperty); }
|
|
set { SetValue(PositionProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The is merged property
|
|
/// </summary>
|
|
public static readonly DependencyProperty IsMergedProperty = DependencyProperty.Register(
|
|
"IsMerged", typeof (bool), typeof (Axis),
|
|
new PropertyMetadata(default(bool), UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets if the axis labels should me placed inside the chart, this is useful to save some space.
|
|
/// </summary>
|
|
public bool IsMerged
|
|
{
|
|
get { return (bool) GetValue(IsMergedProperty); }
|
|
set { SetValue(IsMergedProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The bar unit property
|
|
/// </summary>
|
|
public static readonly DependencyProperty BarUnitProperty = DependencyProperty.Register(
|
|
"BarUnit", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN));
|
|
/// <summary>
|
|
/// Gets or sets the bar's series unit width (rows and columns), this property specifies the value in the chart that any bar should take as width.
|
|
/// </summary>
|
|
[Obsolete("This property was renamed, please use Unit property instead.")]
|
|
public double BarUnit
|
|
{
|
|
get { return (double) GetValue(BarUnitProperty); }
|
|
set { SetValue(BarUnitProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The unit property
|
|
/// </summary>
|
|
public static readonly DependencyProperty UnitProperty = DependencyProperty.Register(
|
|
"Unit", typeof(double), typeof(Axis), new PropertyMetadata(double.NaN));
|
|
/// <summary>
|
|
/// Gets or sets the axis unit, setting this property to your actual scale unit (seconds, minutes or any other scale) helps you to fix possible visual issues.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The unit.
|
|
/// </value>
|
|
public double Unit
|
|
{
|
|
get { return (double)GetValue(UnitProperty); }
|
|
set { SetValue(UnitProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The disable animations property
|
|
/// </summary>
|
|
public static readonly DependencyProperty DisableAnimationsProperty = DependencyProperty.Register(
|
|
"DisableAnimations", typeof (bool), typeof (Axis), new PropertyMetadata(default(bool), UpdateChart(true)));
|
|
/// <summary>
|
|
/// Gets or sets if the axis is animated.
|
|
/// </summary>
|
|
public bool DisableAnimations
|
|
{
|
|
get { return (bool) GetValue(DisableAnimationsProperty); }
|
|
set { SetValue(DisableAnimationsProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font family property
|
|
/// </summary>
|
|
public static readonly DependencyProperty FontFamilyProperty =
|
|
DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(Axis),
|
|
new PropertyMetadata(new FontFamily("Calibri")));
|
|
|
|
/// <summary>
|
|
/// Gets or sets labels font family, font to use for any label in this axis
|
|
/// </summary>
|
|
public FontFamily FontFamily
|
|
{
|
|
get { return (FontFamily)GetValue(FontFamilyProperty); }
|
|
set { SetValue(FontFamilyProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font size property
|
|
/// </summary>
|
|
public static readonly DependencyProperty FontSizeProperty =
|
|
DependencyProperty.Register("FontSize", typeof(double), typeof(Axis), new PropertyMetadata(11.0));
|
|
/// <summary>
|
|
/// Gets or sets labels font size
|
|
/// </summary>
|
|
public double FontSize
|
|
{
|
|
get { return (double)GetValue(FontSizeProperty); }
|
|
set { SetValue(FontSizeProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font weight property
|
|
/// </summary>
|
|
public static readonly DependencyProperty FontWeightProperty =
|
|
DependencyProperty.Register("FontWeight", typeof(FontWeight), typeof(Axis),
|
|
new PropertyMetadata(FontWeights.Normal));
|
|
/// <summary>
|
|
/// Gets or sets labels font weight
|
|
/// </summary>
|
|
public FontWeight FontWeight
|
|
{
|
|
get { return (FontWeight)GetValue(FontWeightProperty); }
|
|
set { SetValue(FontWeightProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font style property
|
|
/// </summary>
|
|
public static readonly DependencyProperty FontStyleProperty =
|
|
DependencyProperty.Register("FontStyle", typeof(FontStyle), typeof(Axis),
|
|
new PropertyMetadata(FontStyle.Normal));
|
|
|
|
/// <summary>
|
|
/// Gets or sets labels font style
|
|
/// </summary>
|
|
public FontStyle FontStyle
|
|
{
|
|
get { return (FontStyle)GetValue(FontStyleProperty); }
|
|
set { SetValue(FontStyleProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font stretch property
|
|
/// </summary>
|
|
public static readonly DependencyProperty FontStretchProperty =
|
|
DependencyProperty.Register("FontStretch", typeof(FontStretch), typeof(Axis),
|
|
new PropertyMetadata(FontStretch.Normal));
|
|
|
|
/// <summary>
|
|
/// Gets or sets labels font stretch
|
|
/// </summary>
|
|
public FontStretch FontStretch
|
|
{
|
|
get { return (FontStretch)GetValue(FontStretchProperty); }
|
|
set { SetValue(FontStretchProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The foreground property
|
|
/// </summary>
|
|
public static readonly DependencyProperty ForegroundProperty =
|
|
DependencyProperty.Register("Foreground", typeof(Brush), typeof(Axis), new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 170, 170, 170))));
|
|
|
|
/// <summary>
|
|
/// Gets or sets labels text color.
|
|
/// </summary>
|
|
public Brush Foreground
|
|
{
|
|
get { return (Brush)GetValue(ForegroundProperty); }
|
|
set { SetValue(ForegroundProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The labels rotation property
|
|
/// </summary>
|
|
public static readonly DependencyProperty LabelsRotationProperty = DependencyProperty.Register(
|
|
"LabelsRotation", typeof (double), typeof (Axis), new PropertyMetadata(default(double), UpdateChart()));
|
|
/// <summary>
|
|
/// Gets or sets the labels rotation in the axis, the angle starts as a horizontal line, you can use any angle in degrees, even negatives.
|
|
/// </summary>
|
|
public double LabelsRotation
|
|
{
|
|
get { return (double) GetValue(LabelsRotationProperty); }
|
|
set { SetValue(LabelsRotationProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The is enabled property
|
|
/// </summary>
|
|
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(
|
|
"IsEnabled", typeof(bool), typeof(Axis), new PropertyMetadata(default(bool)));
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this instance is enabled.
|
|
/// </summary>
|
|
/// <value>
|
|
/// <c>true</c> if this instance is enabled; otherwise, <c>false</c>.
|
|
/// </value>
|
|
public bool IsEnabled
|
|
{
|
|
get { return (bool) GetValue(IsEnabledProperty); }
|
|
set { SetValue(IsEnabledProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The axis orientation property
|
|
/// </summary>
|
|
public static readonly DependencyProperty AxisOrientationProperty = DependencyProperty.Register(
|
|
"AxisOrientation", typeof(AxisOrientation), typeof(Axis), new PropertyMetadata(default(AxisOrientation)));
|
|
/// <summary>
|
|
/// Gets or sets the element orientation ind the axis
|
|
/// </summary>
|
|
public AxisOrientation AxisOrientation
|
|
{
|
|
get { return (AxisOrientation)GetValue(AxisOrientationProperty); }
|
|
internal set { SetValue(AxisOrientationProperty, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
/// <summary>
|
|
/// Cleans this instance.
|
|
/// </summary>
|
|
public void Clean()
|
|
{
|
|
if (Model == null) return;
|
|
Model.ClearSeparators();
|
|
Model.Chart.View.RemoveFromView(TitleBlock);
|
|
Sections.Clear();
|
|
TitleBlock = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the range.
|
|
/// </summary>
|
|
/// <param name="min">The minimum.</param>
|
|
/// <param name="max">The maximum.</param>
|
|
public void SetRange(double min, double max)
|
|
{
|
|
var bMax = double.IsNaN(MaxValue) ? Model.TopLimit : MaxValue;
|
|
var bMin = double.IsNaN(MinValue) ? Model.BotLimit : MinValue;
|
|
|
|
var nMax = double.IsNaN(MaxValue) ? Model.TopLimit : MaxValue;
|
|
var nMin = double.IsNaN(MinValue) ? Model.BotLimit : MinValue;
|
|
|
|
var e = new RangeChangedEventArgs
|
|
{
|
|
Range = nMax - nMin,
|
|
RightLimitChange = bMax - nMax,
|
|
LeftLimitChange = bMin - nMin,
|
|
Axis = this
|
|
};
|
|
|
|
var pe = new PreviewRangeChangedEventArgs(e)
|
|
{
|
|
PreviewMaxValue = max,
|
|
PreviewMinValue = min
|
|
};
|
|
OnPreviewRangeChanged(pe);
|
|
|
|
if (pe.Cancel) return;
|
|
|
|
MaxValue = max;
|
|
MinValue = min;
|
|
|
|
Model.Chart.Updater.Run();
|
|
|
|
OnRangeChanged(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the separator.
|
|
/// </summary>
|
|
/// <param name="model">The model.</param>
|
|
/// <param name="chart">The chart.</param>
|
|
public void RenderSeparator(SeparatorElementCore model, ChartCore chart)
|
|
{
|
|
AxisSeparatorElement ase;
|
|
|
|
if (model.View == null)
|
|
{
|
|
ase = new AxisSeparatorElement(model)
|
|
{
|
|
Line = BindALine(),
|
|
TextBlock = BindATextBlock()
|
|
};
|
|
|
|
model.View = ase;
|
|
chart.View.AddToView(ase.Line);
|
|
chart.View.AddToView(ase.TextBlock);
|
|
Canvas.SetZIndex(ase.Line, -1);
|
|
}
|
|
else
|
|
{
|
|
ase = (AxisSeparatorElement) model.View;
|
|
}
|
|
|
|
ase.Line.Visibility = !Separator.IsEnabled ? Visibility.Collapsed : Visibility.Visible;
|
|
ase.TextBlock.Visibility = !ShowLabels ? Visibility.Collapsed : Visibility.Visible;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the title.
|
|
/// </summary>
|
|
/// <param name="chart">The chart.</param>
|
|
/// <param name="rotationAngle">The rotation angle.</param>
|
|
/// <returns></returns>
|
|
public CoreSize UpdateTitle(ChartCore chart, double rotationAngle = 0)
|
|
{
|
|
if (TitleBlock.Parent == null)
|
|
{
|
|
if (Math.Abs(rotationAngle) > 1)
|
|
TitleBlock.RenderTransform = new RotateTransform {Angle = rotationAngle};
|
|
|
|
chart.View.AddToView(TitleBlock);
|
|
}
|
|
|
|
TitleBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
|
|
|
return string.IsNullOrWhiteSpace(Title)
|
|
? new CoreSize()
|
|
: new CoreSize(TitleBlock.DesiredSize.Width, TitleBlock.DesiredSize.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the title top.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
public void SetTitleTop(double value)
|
|
{
|
|
Canvas.SetTop(TitleBlock, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the title left.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
public void SetTitleLeft(double value)
|
|
{
|
|
Canvas.SetLeft(TitleBlock, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the title left.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public double GetTitleLeft()
|
|
{
|
|
return Canvas.GetLeft(TitleBlock);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the tile top.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public double GetTileTop()
|
|
{
|
|
return Canvas.GetTop(TitleBlock);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the size of the label.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public CoreSize GetLabelSize()
|
|
{
|
|
return new CoreSize(TitleBlock.DesiredSize.Width, TitleBlock.DesiredSize.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ases the core element.
|
|
/// </summary>
|
|
/// <param name="chart">The chart.</param>
|
|
/// <param name="source">The source.</param>
|
|
/// <returns></returns>
|
|
public virtual AxisCore AsCoreElement(ChartCore chart, AxisOrientation source)
|
|
{
|
|
if (Model == null) Model = new AxisCore(this);
|
|
|
|
Model.ShowLabels = ShowLabels;
|
|
Model.Chart = chart;
|
|
Model.IsMerged = IsMerged;
|
|
Model.Labels = Labels;
|
|
Model.LabelFormatter = LabelFormatter;
|
|
Model.MaxValue = MaxValue;
|
|
Model.MinValue = MinValue;
|
|
Model.Title = Title;
|
|
Model.Position = Position;
|
|
Model.Separator = Separator.AsCoreElement(Model, source);
|
|
Model.DisableAnimations = DisableAnimations;
|
|
Model.Sections = Sections.Select(x => x.AsCoreElement(Model, source)).ToList();
|
|
|
|
return Model;
|
|
}
|
|
|
|
#endregion
|
|
|
|
internal TextBlock BindATextBlock()
|
|
{
|
|
var tb = new TextBlock();
|
|
|
|
tb.SetBinding(TextBlock.FontFamilyProperty,
|
|
new Binding { Path = new PropertyPath("FontFamily"), Source = this });
|
|
tb.SetBinding(TextBlock.FontSizeProperty,
|
|
new Binding { Path = new PropertyPath("FontSize"), Source = this });
|
|
tb.SetBinding(TextBlock.FontStretchProperty,
|
|
new Binding { Path = new PropertyPath("FontStretch"), Source = this });
|
|
tb.SetBinding(TextBlock.FontStyleProperty,
|
|
new Binding { Path = new PropertyPath("FontStyle"), Source = this });
|
|
tb.SetBinding(TextBlock.FontWeightProperty,
|
|
new Binding { Path = new PropertyPath("FontWeight"), Source = this });
|
|
tb.SetBinding(TextBlock.ForegroundProperty,
|
|
new Binding { Path = new PropertyPath("Foreground"), Source = this });
|
|
|
|
return tb;
|
|
}
|
|
|
|
internal Line BindALine()
|
|
{
|
|
var l = new Line();
|
|
|
|
var s = Separator as Separator;
|
|
if (s == null) return l;
|
|
|
|
l.SetBinding(Shape.StrokeProperty,
|
|
new Binding {Path = new PropertyPath("Stroke"), Source = s});
|
|
try
|
|
{
|
|
l.SetBinding(Shape.StrokeDashArrayProperty,
|
|
new Binding { Path = new PropertyPath("StrokeDashArray"), Source = s });
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// temporarily ignore it
|
|
}
|
|
|
|
l.SetBinding(Shape.StrokeThicknessProperty,
|
|
new Binding {Path = new PropertyPath("StrokeThickness"), Source = s});
|
|
l.SetBinding(VisibilityProperty,
|
|
new Binding {Path = new PropertyPath("Visibility"), Source = s});
|
|
|
|
return l;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the chart.
|
|
/// </summary>
|
|
/// <param name="animate">if set to <c>true</c> [animate].</param>
|
|
/// <param name="updateNow">if set to <c>true</c> [update now].</param>
|
|
/// <returns></returns>
|
|
protected static PropertyChangedCallback UpdateChart(bool animate = false, bool updateNow = false)
|
|
{
|
|
return (o, args) =>
|
|
{
|
|
var wpfAxis = o as Axis;
|
|
if (wpfAxis == null) return;
|
|
|
|
wpfAxis.Model?.Chart.Updater.Run(animate, updateNow);
|
|
};
|
|
}
|
|
|
|
private static void LabelsVisibilityChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
|
|
{
|
|
var axis = (Axis) dependencyObject;
|
|
if (axis.Model == null) return;
|
|
|
|
foreach (var separator in axis.Model.CurrentSeparators)
|
|
{
|
|
var s = (AxisSeparatorElement) separator.View;
|
|
s.TextBlock.Visibility = axis.ShowLabels
|
|
? Visibility.Visible
|
|
: Visibility.Collapsed;
|
|
}
|
|
|
|
UpdateChart()(dependencyObject, dependencyPropertyChangedEventArgs);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="E:RangeChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="RangeChangedEventArgs"/> instance containing the event data.</param>
|
|
protected void OnRangeChanged(RangeChangedEventArgs e)
|
|
{
|
|
RangeChanged?.Invoke(e);
|
|
if (RangeChangedCommand != null && RangeChangedCommand.CanExecute(e))
|
|
RangeChangedCommand.Execute(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="E:PreviewRangeChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="PreviewRangeChangedEventArgs"/> instance containing the event data.</param>
|
|
protected void OnPreviewRangeChanged(PreviewRangeChangedEventArgs e)
|
|
{
|
|
PreviewRangeChanged?.Invoke(e);
|
|
if (PreviewRangeChangedCommand != null && PreviewRangeChangedCommand.CanExecute(e))
|
|
PreviewRangeChangedCommand.Execute(e);
|
|
}
|
|
}
|
|
} |