8
Source/Examples/WPF/ExampleBrowser/App.xaml
Normal file
8
Source/Examples/WPF/ExampleBrowser/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Application x:Class="ExampleBrowser.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
24
Source/Examples/WPF/ExampleBrowser/App.xaml.cs
Normal file
24
Source/Examples/WPF/ExampleBrowser/App.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="App.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for App.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
17
Source/Examples/WPF/ExampleBrowser/ExampleBrowser.WPF.csproj
Normal file
17
Source/Examples/WPF/ExampleBrowser/ExampleBrowser.WPF.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net462;net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||
<UseWPF>true</UseWPF>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\OxyPlot.SkiaSharp.Wpf\OxyPlot.SkiaSharp.Wpf.csproj" />
|
||||
<ProjectReference Include="..\..\..\OxyPlot.Wpf\OxyPlot.Wpf.csproj" />
|
||||
<ProjectReference Include="..\..\..\OxyPlot\OxyPlot.csproj" />
|
||||
<ProjectReference Include="..\..\ExampleLibrary\ExampleLibrary.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="..\..\..\..\Icons\OxyPlot_64.png" Link="OxyPlot_64.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
133
Source/Examples/WPF/ExampleBrowser/MainWindow.xaml
Normal file
133
Source/Examples/WPF/ExampleBrowser/MainWindow.xaml
Normal file
@@ -0,0 +1,133 @@
|
||||
<Window x:Class="ExampleBrowser.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxyWpf="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
xmlns:oxySkia="clr-namespace:OxyPlot.SkiaSharp.Wpf;assembly=OxyPlot.SkiaSharp.Wpf"
|
||||
xmlns:local="clr-namespace:ExampleBrowser"
|
||||
Title="OxyPlot.WPF Example Browser"
|
||||
Height="720" Width="1280" Icon="OxyPlot_64.png">
|
||||
<Window.DataContext>
|
||||
<local:MainWindowViewModel />
|
||||
</Window.DataContext>
|
||||
<Window.Resources>
|
||||
<SolidColorBrush x:Key="HotItemBackground" Color="#e6f3f7"/>
|
||||
<SolidColorBrush x:Key="SelectedItemBorder" Color="#6dbdd1"/>
|
||||
<SolidColorBrush x:Key="SelectedItemBackground" Color="#cbe6ef"/>
|
||||
<SolidColorBrush x:Key="NormalItemBackground" Color="White"/>
|
||||
|
||||
<DrawingBrush x:Key="CheckerBoard" TileMode="Tile" ViewboxUnits="Absolute" Viewbox="0,0,2,2" Viewport="0,0,10,10" ViewportUnits="Absolute">
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<GeometryDrawing Brush="White">
|
||||
<GeometryDrawing.Geometry>
|
||||
<RectangleGeometry Rect="0,0,2,2" />
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="LightGray">
|
||||
<GeometryDrawing.Geometry>
|
||||
<GeometryGroup>
|
||||
<RectangleGeometry Rect="0,0,1,1" />
|
||||
<RectangleGeometry Rect="1,1,1,1" />
|
||||
</GeometryGroup>
|
||||
</GeometryDrawing.Geometry>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
|
||||
<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="Background" Value="{StaticResource NormalItemBackground}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}">
|
||||
<Grid>
|
||||
<Rectangle Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}"
|
||||
StrokeThickness="{TemplateBinding BorderThickness}" RadiusX="3" RadiusY="3" SnapsToDevicePixels="True"/>
|
||||
<ContentPresenter Margin="8,5" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
<Condition Property="IsSelected" Value="False"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" Value="{StaticResource HotItemBackground}" />
|
||||
</MultiTrigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource SelectedItemBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource SelectedItemBorder}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Background="#20000000">
|
||||
<ListBox ItemsSource="{Binding ExamplesView}" ItemContainerStyle="{DynamicResource ListboxItemStyle}"
|
||||
SelectedItem="{Binding SelectedExample}" BorderThickness="0,0,0,1">
|
||||
<ListBox.GroupStyle>
|
||||
<GroupStyle>
|
||||
<GroupStyle.ContainerStyle>
|
||||
<Style TargetType="{x:Type GroupItem}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Expander IsExpanded="False" ExpandDirection="Down">
|
||||
<Expander.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock FontWeight="Bold" Text="{Binding Name}" Padding="0 0 8 0"/>
|
||||
<TextBlock Text="{Binding ItemCount, StringFormat='({0})'}"/>
|
||||
</StackPanel>
|
||||
</Expander.Header>
|
||||
<ItemsPresenter />
|
||||
</Expander>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</GroupStyle.ContainerStyle>
|
||||
</GroupStyle>
|
||||
</ListBox.GroupStyle>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1">
|
||||
<TabControl TabStripPlacement="Bottom">
|
||||
<TabControl.Resources>
|
||||
<Style TargetType="{x:Type TextBox}" x:Key="CodeTextBox">
|
||||
<Setter Property="AcceptsReturn" Value="True"></Setter>
|
||||
<Setter Property="FontFamily" Value="Consolas"></Setter>
|
||||
<Setter Property="BorderThickness" Value="0"></Setter>
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"></Setter>
|
||||
</Style>
|
||||
</TabControl.Resources>
|
||||
<TabItem Header="Plot">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<local:NotNullVisibilityConverter x:Key="NotNullVisibilityConverter" />
|
||||
</Grid.Resources>
|
||||
<oxySkia:PlotView Model="{Binding SkiaModel}" Controller="{Binding SelectedExample.PlotController}" Visibility="{Binding SkiaModel, Converter={StaticResource NotNullVisibilityConverter}}" />
|
||||
<oxyWpf:PlotView Model="{Binding CanvasModel}" Controller="{Binding SelectedExample.PlotController}" Visibility="{Binding CanvasModel, Converter={StaticResource NotNullVisibilityConverter}}" />
|
||||
<local:XamlPlotView Model="{Binding CanvasXamlModel}" Controller="{Binding SelectedExample.PlotController}" Visibility="{Binding CanvasXamlModel, Converter={StaticResource NotNullVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Code">
|
||||
<TextBox Text="{Binding Code, Mode=OneWay}" Style="{StaticResource CodeTextBox}" />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock Text="Renderer:" VerticalAlignment="Center" />
|
||||
<ComboBox SelectedItem="{Binding Renderer}" ItemsSource="{Binding Renderers}" Margin="3,0,0,0" Width="80" />
|
||||
<CheckBox IsChecked="{Binding Transposed}" Content="Transposed" VerticalAlignment="Center" Margin="10,0,5,0" IsEnabled="{Binding CanTranspose}" />
|
||||
<CheckBox IsChecked="{Binding Reversed}" Content="Reversed" VerticalAlignment="Center" Margin="10,0,5,0" IsEnabled="{Binding CanReverse}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
34
Source/Examples/WPF/ExampleBrowser/MainWindow.xaml.cs
Normal file
34
Source/Examples/WPF/ExampleBrowser/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
using Microsoft.Win32;
|
||||
using System.Windows;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindow" /> class.
|
||||
/// </summary>
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
SystemEvents.DisplaySettingsChanged += this.SystemEvents_DisplaySettingsChanged;
|
||||
}
|
||||
|
||||
private void SystemEvents_DisplaySettingsChanged(object sender, System.EventArgs e)
|
||||
{
|
||||
(this.DataContext as MainWindowViewModel)?.ActiveModel?.PlotView?.InvalidatePlot(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
165
Source/Examples/WPF/ExampleBrowser/MainWindowViewModel.cs
Normal file
165
Source/Examples/WPF/ExampleBrowser/MainWindowViewModel.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindowViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
using ExampleLibrary;
|
||||
using OxyPlot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
public class MainWindowViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private bool _CanTranspose;
|
||||
private bool _CanReverse;
|
||||
private string _Code;
|
||||
private Renderer _Renderer;
|
||||
private PlotModel _PlotModel;
|
||||
private bool _Transposed;
|
||||
private bool _Reversed;
|
||||
private IEnumerable<ExampleInfo> examples;
|
||||
private ExampleInfo selectedExample;
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
this.Examples = ExampleLibrary.Examples.GetList();
|
||||
this.ExamplesView = CollectionViewSource.GetDefaultView(this.Examples.OrderBy(e => e.Category));
|
||||
this.ExamplesView.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public PlotModel ActiveModel => this.CanvasModel ?? this.SkiaModel;
|
||||
|
||||
public bool CanTranspose
|
||||
{
|
||||
get => this._CanTranspose;
|
||||
private set
|
||||
{
|
||||
this._CanTranspose = value;
|
||||
this.RaisePropertyChanged(nameof(this.CanTranspose));
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanReverse
|
||||
{
|
||||
get => this._CanReverse;
|
||||
private set
|
||||
{
|
||||
this._CanReverse = value;
|
||||
this.RaisePropertyChanged(nameof(this.CanReverse));
|
||||
}
|
||||
}
|
||||
|
||||
public PlotModel CanvasModel => this.Renderer == Renderer.Canvas ? this._PlotModel : null;
|
||||
|
||||
public string Code
|
||||
{
|
||||
get => this._Code;
|
||||
set
|
||||
{
|
||||
this._Code = value;
|
||||
this.RaisePropertyChanged(nameof(this.Code));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ExampleInfo> Examples
|
||||
{
|
||||
get => this.examples;
|
||||
set
|
||||
{
|
||||
this.examples = value;
|
||||
this.RaisePropertyChanged(nameof(this.Examples));
|
||||
}
|
||||
}
|
||||
|
||||
public ICollectionView ExamplesView { get; set; }
|
||||
|
||||
public Renderer Renderer
|
||||
{
|
||||
get => this._Renderer;
|
||||
set
|
||||
{
|
||||
this._Renderer = value;
|
||||
this.CoerceRenderer();
|
||||
this.RaisePropertyChanged(nameof(this.Renderer));
|
||||
}
|
||||
}
|
||||
|
||||
private void CoerceRenderer()
|
||||
{
|
||||
((IPlotModel)this._PlotModel)?.AttachPlotView(null);
|
||||
this.RaisePropertyChanged(nameof(this.SkiaModel));
|
||||
this.RaisePropertyChanged(nameof(this.CanvasXamlModel));
|
||||
this.RaisePropertyChanged(nameof(this.CanvasModel));
|
||||
}
|
||||
|
||||
public IEnumerable<Renderer> Renderers => Enum.GetValues(typeof(Renderer)).Cast<Renderer>();
|
||||
|
||||
public ExampleInfo SelectedExample
|
||||
{
|
||||
get => this.selectedExample;
|
||||
set
|
||||
{
|
||||
this.selectedExample = value;
|
||||
this.CoerceSelectedExample();
|
||||
this.RaisePropertyChanged(nameof(this.SelectedExample));
|
||||
}
|
||||
}
|
||||
|
||||
public PlotModel SkiaModel => this.Renderer == Renderer.SkiaSharp ? this._PlotModel : null;
|
||||
|
||||
public PlotModel CanvasXamlModel => this.Renderer == Renderer.Canvas_XAML ? this._PlotModel : null;
|
||||
|
||||
public bool Transposed
|
||||
{
|
||||
get => this._Transposed;
|
||||
set
|
||||
{
|
||||
this._Transposed = value;
|
||||
this.UpdatePlotModel();
|
||||
this.RaisePropertyChanged(nameof(this.Transposed));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Reversed
|
||||
{
|
||||
get => this._Reversed;
|
||||
set
|
||||
{
|
||||
this._Reversed = value;
|
||||
this.UpdatePlotModel();
|
||||
this.RaisePropertyChanged(nameof(this.Reversed));
|
||||
}
|
||||
}
|
||||
|
||||
protected void RaisePropertyChanged(string property)
|
||||
{
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
|
||||
}
|
||||
|
||||
private void CoerceSelectedExample()
|
||||
{
|
||||
this.CanTranspose = this.SelectedExample?.IsTransposable == true;
|
||||
this.CanReverse = this.SelectedExample?.IsReversible == true;
|
||||
this.UpdatePlotModel();
|
||||
}
|
||||
|
||||
private void UpdatePlotModel()
|
||||
{
|
||||
var flags = ExampleInfo.PrepareFlags(
|
||||
this.CanTranspose && this.Transposed,
|
||||
this.CanReverse && this.Reversed);
|
||||
|
||||
this._PlotModel = this.SelectedExample?.GetModel(flags);
|
||||
this.Code = this.SelectedExample?.GetCode(flags);
|
||||
this.CoerceRenderer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="NotNullVisibilityConverter.cs" company="OxyPlot">
|
||||
// Copyright (c) 2020 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
public sealed class NotNullVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value == null
|
||||
? Visibility.Collapsed
|
||||
: Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AssemblyInfo.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
|
||||
15
Source/Examples/WPF/ExampleBrowser/Renderer.cs
Normal file
15
Source/Examples/WPF/ExampleBrowser/Renderer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="Renderer.cs" company="OxyPlot">
|
||||
// Copyright (c) 2020 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
public enum Renderer
|
||||
{
|
||||
Canvas,
|
||||
Canvas_XAML,
|
||||
SkiaSharp
|
||||
}
|
||||
}
|
||||
22
Source/Examples/WPF/ExampleBrowser/XamlPlotView.cs
Normal file
22
Source/Examples/WPF/ExampleBrowser/XamlPlotView.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="XamlPlotView.cs" company="OxyPlot">
|
||||
// Copyright (c) 2020 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleBrowser
|
||||
{
|
||||
using OxyPlot;
|
||||
using OxyPlot.Wpf;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a PlotView which uses the XamlRenderContext for rendering.
|
||||
/// </summary>
|
||||
public class XamlPlotView : PlotView
|
||||
{
|
||||
protected override IRenderContext CreateRenderContext()
|
||||
{
|
||||
return new XamlRenderContext(this.Canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Source/Examples/WPF/ExampleBrowser/app.manifest
Normal file
12
Source/Examples/WPF/ExampleBrowser/app.manifest
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="foo"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
</assembly>
|
||||
8
Source/Examples/WPF/SimpleDemo/App.xaml
Normal file
8
Source/Examples/WPF/SimpleDemo/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Application x:Class="SimpleDemo.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
25
Source/Examples/WPF/SimpleDemo/App.xaml.cs
Normal file
25
Source/Examples/WPF/SimpleDemo/App.xaml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="App.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for App.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
namespace SimpleDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
59
Source/Examples/WPF/SimpleDemo/MainViewModel.cs
Normal file
59
Source/Examples/WPF/SimpleDemo/MainViewModel.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Represents the view-model for the main window.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace SimpleDemo
|
||||
{
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the view-model for the main window.
|
||||
/// </summary>
|
||||
public class MainViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainViewModel" /> class.
|
||||
/// </summary>
|
||||
public MainViewModel()
|
||||
{
|
||||
// Create the plot model
|
||||
var tmp = new PlotModel { Title = "Simple example", Subtitle = "using OxyPlot" };
|
||||
|
||||
// Create two line series (markers are hidden by default)
|
||||
var series1 = new LineSeries { Title = "Series 1", MarkerType = MarkerType.Circle };
|
||||
series1.Points.Add(new DataPoint(0, 0));
|
||||
series1.Points.Add(new DataPoint(10, 18));
|
||||
series1.Points.Add(new DataPoint(20, 12));
|
||||
series1.Points.Add(new DataPoint(30, 8));
|
||||
series1.Points.Add(new DataPoint(40, 15));
|
||||
|
||||
var series2 = new LineSeries { Title = "Series 2", MarkerType = MarkerType.Square };
|
||||
series2.Points.Add(new DataPoint(0, 4));
|
||||
series2.Points.Add(new DataPoint(10, 12));
|
||||
series2.Points.Add(new DataPoint(20, 16));
|
||||
series2.Points.Add(new DataPoint(30, 25));
|
||||
series2.Points.Add(new DataPoint(40, 5));
|
||||
|
||||
|
||||
// Add the series to the plot model
|
||||
tmp.Series.Add(series1);
|
||||
tmp.Series.Add(series2);
|
||||
|
||||
// Axes are created automatically if they are not defined
|
||||
|
||||
// Set the Model property, the INotifyPropertyChanged event will make the WPF Plot control update its content
|
||||
this.Model = tmp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot model.
|
||||
/// </summary>
|
||||
public PlotModel Model { get; private set; }
|
||||
}
|
||||
}
|
||||
14
Source/Examples/WPF/SimpleDemo/MainWindow.xaml
Normal file
14
Source/Examples/WPF/SimpleDemo/MainWindow.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<Window x:Class="SimpleDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
xmlns:simpleDemo="clr-namespace:SimpleDemo"
|
||||
Title="OxyPlot SimpleDemo" Height="480" Width="640">
|
||||
<Window.DataContext>
|
||||
<simpleDemo:MainViewModel />
|
||||
</Window.DataContext>
|
||||
<Grid>
|
||||
<!-- The OxyPlot control is binding to a PlotModel in the MainViewModel -->
|
||||
<oxy:PlotView Model="{Binding Model}" />
|
||||
</Grid>
|
||||
</Window>
|
||||
25
Source/Examples/WPF/SimpleDemo/MainWindow.xaml.cs
Normal file
25
Source/Examples/WPF/SimpleDemo/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace SimpleDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindow" /> class.
|
||||
/// </summary>
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AssemblyInfo.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
|
||||
11
Source/Examples/WPF/SimpleDemo/SimpleDemo.csproj
Normal file
11
Source/Examples/WPF/SimpleDemo/SimpleDemo.csproj
Normal file
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-windows</TargetFrameworks>
|
||||
<UseWPF>true</UseWPF>
|
||||
<OutputType>WinExe</OutputType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\OxyPlot.Wpf\OxyPlot.Wpf.csproj" />
|
||||
<ProjectReference Include="..\..\..\OxyPlot\OxyPlot.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
3
Source/Examples/WPF/SimpleDemo/app.config
Normal file
3
Source/Examples/WPF/SimpleDemo/app.config
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
|
||||
8
Source/Examples/WPF/WpfExamples/App.xaml
Normal file
8
Source/Examples/WPF/WpfExamples/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Application x:Class="WpfExamples.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
25
Source/Examples/WPF/WpfExamples/App.xaml.cs
Normal file
25
Source/Examples/WPF/WpfExamples/App.xaml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="App.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for App.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
namespace WpfExamples
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
24
Source/Examples/WPF/WpfExamples/BitmapTools.cs
Normal file
24
Source/Examples/WPF/WpfExamples/BitmapTools.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="BitmapTools.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WpfExamples
|
||||
{
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
public static class BitmapTools
|
||||
{
|
||||
public static Bitmap Resize(Bitmap bitmap, int newWidth, int newHeight)
|
||||
{
|
||||
var resizedBitmap = new Bitmap(newWidth, newHeight);
|
||||
var g = Graphics.FromImage(resizedBitmap);
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
g.DrawImage(bitmap, 0, 0, newWidth, newHeight);
|
||||
g.Dispose();
|
||||
return resizedBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Source/Examples/WPF/WpfExamples/DelegateCommand.cs
Normal file
104
Source/Examples/WPF/WpfExamples/DelegateCommand.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="DelegateCommand.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Represents a delegate command.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WpfExamples
|
||||
{
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a delegate command.
|
||||
/// </summary>
|
||||
public class DelegateCommand : ICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// The can execute.
|
||||
/// </summary>
|
||||
private readonly Func<bool> canExecute;
|
||||
|
||||
/// <summary>
|
||||
/// The execute.
|
||||
/// </summary>
|
||||
private readonly Action execute;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DelegateCommand" /> class.
|
||||
/// </summary>
|
||||
/// <param name="execute">The execute.</param>
|
||||
public DelegateCommand(Action execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DelegateCommand" /> class.
|
||||
/// </summary>
|
||||
/// <param name="execute">The execute.</param>
|
||||
/// <param name="canExecute">The can execute.</param>
|
||||
public DelegateCommand(Action execute, Func<bool> canExecute)
|
||||
{
|
||||
if (execute == null)
|
||||
{
|
||||
throw new ArgumentNullException("execute");
|
||||
}
|
||||
|
||||
this.execute = execute;
|
||||
this.canExecute = canExecute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when changes occur that affect whether or not the command should execute.
|
||||
/// </summary>
|
||||
public event EventHandler CanExecuteChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
if (this.canExecute != null)
|
||||
{
|
||||
CommandManager.RequerySuggested += value;
|
||||
}
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
if (this.canExecute != null)
|
||||
{
|
||||
CommandManager.RequerySuggested -= value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the method that determines whether the command can execute in its current state.
|
||||
/// </summary>
|
||||
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <c>null</c>.</param>
|
||||
/// <returns><c>true</c> if this command can be executed; otherwise, <c>false</c>.</returns>
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return this.canExecute == null ? true : this.canExecute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the method to be called when the command is invoked.
|
||||
/// </summary>
|
||||
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <c>null</c>.</param>
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
this.execute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the can execute changed.
|
||||
/// </summary>
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CommandManager.InvalidateRequerySuggested();
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Source/Examples/WPF/WpfExamples/Example.cs
Normal file
56
Source/Examples/WPF/WpfExamples/Example.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="Example.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WpfExamples
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
public class Example
|
||||
{
|
||||
public Example(Type mainWindowType, string title = null, string description = null)
|
||||
{
|
||||
this.MainWindowType = mainWindowType;
|
||||
this.Title = title ?? mainWindowType.Namespace;
|
||||
this.Description = description;
|
||||
try
|
||||
{
|
||||
this.Thumbnail = new BitmapImage(new Uri("pack://application:,,,/Images/" + this.ThumbnailFileName));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
public string Title { get; private set; }
|
||||
public string Description { get; set; }
|
||||
private Type MainWindowType { get; set; }
|
||||
|
||||
public ImageSource Thumbnail { get; set; }
|
||||
|
||||
public string ThumbnailFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.MainWindowType.Namespace + ".png";
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Title;
|
||||
}
|
||||
|
||||
public Window Create()
|
||||
{
|
||||
return Activator.CreateInstance(this.MainWindowType) as Window;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Source/Examples/WPF/WpfExamples/ExampleAttribute.cs
Normal file
28
Source/Examples/WPF/WpfExamples/ExampleAttribute.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ExampleAttribute.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WpfExamples
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ExampleAttribute : Attribute
|
||||
{
|
||||
public ExampleAttribute(string description)
|
||||
: this(null, description)
|
||||
{
|
||||
}
|
||||
|
||||
public ExampleAttribute(string title, string description)
|
||||
{
|
||||
this.Title = title;
|
||||
this.Description = description;
|
||||
}
|
||||
|
||||
public string Title { get; private set; }
|
||||
|
||||
public string Description { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Window x:Class="AlignedAxesDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
Title="AlignedAxesDemo" Height="480" Width="640">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label>The plot margins are undefined, and the vertical axes should be adjusted to have the same width.</Label>
|
||||
<oxy:PlotView Grid.Row="1" Model="{Binding Model0}"/>
|
||||
<oxy:PlotView Grid.Row="2" Model="{Binding Model1}"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,55 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AlignedAxesDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Aligning plot margins from desired axis widths.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindow"/> class.
|
||||
/// </summary>
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Model0 = CreatePlotModel(0, 10);
|
||||
this.Model1 = CreatePlotModel(0, 1e8);
|
||||
|
||||
// TODO: align the vertical axis size without setting PlotMargins
|
||||
this.Model0.PlotMargins = this.Model1.PlotMargins = new OxyThickness(70, 40, 20, 20);
|
||||
|
||||
this.DataContext = this;
|
||||
}
|
||||
|
||||
public PlotModel Model0 { get; private set; }
|
||||
|
||||
public PlotModel Model1 { get; private set; }
|
||||
|
||||
private static PlotModel CreatePlotModel(double min, double max)
|
||||
{
|
||||
var model = new PlotModel();
|
||||
var verticalAxis = new LinearAxis { Position = AxisPosition.Left, Minimum = min, Maximum = max };
|
||||
model.Axes.Add(verticalAxis);
|
||||
model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
|
||||
model.Series.Add(new FunctionSeries(x => Math.Sin(x * Math.PI * 4) * Math.Sin(x * Math.PI * 4) * Math.Sqrt(x) * max, 0, 1, 1000));
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<UserControl x:Class="AnimationsDemo.AnimationSettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<Label Content="Total duration (ms)" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<TextBox Text="{Binding AnimationDuration}" Margin="6,4,6,4" Height="25" Width="50" VerticalContentAlignment="Center" />
|
||||
|
||||
<Label Content="Frame duration (ms)" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<TextBox Text="{Binding AnimationFrameDuration}" Margin="6,4,6,4" Height="25" Width="50" VerticalContentAlignment="Center" />
|
||||
|
||||
<Label Content="Delay (ms)" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<TextBox Text="{Binding AnimationDelay}" Margin="6,4,6,4" Height="25" Width="50" VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<Label Content="Easing function" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<ComboBox ItemsSource="{Binding EasingFunctions}" SelectedItem="{Binding SelectedEasingFunction}"
|
||||
DisplayMemberPath="Name" Margin="6,4,6,4" Height="25" Width="100" VerticalContentAlignment="Center"
|
||||
IsEnabled="{Binding SupportsEasingFunction}"/>
|
||||
|
||||
<Label Content="Horizontal %" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<TextBox Text="{Binding HorizontalPercentage}" Margin="6,4,6,4" Height="25" Width="50" VerticalContentAlignment="Center" />
|
||||
|
||||
<Label Content="Vertical %" VerticalAlignment="Center" Margin="6,4,6,4" />
|
||||
<TextBox Text="{Binding VerticalPercentage}" Margin="6,4,6,4" Height="25" Width="50" VerticalContentAlignment="Center" />
|
||||
|
||||
<Button Content="Animate" Click="OnAnimateClick" Width="75" Margin="6,4,6,4" Height="25" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,27 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="LinearBarView.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System.Windows;
|
||||
|
||||
public partial class AnimationSettingsControl
|
||||
{
|
||||
public AnimationSettingsControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnAnimateClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = this.DataContext as IAnimationViewModel;
|
||||
if (vm != null)
|
||||
{
|
||||
await vm.AnimateAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="BackEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
public class BackEase : IEasingFunction
|
||||
{
|
||||
public BackEase()
|
||||
{
|
||||
this.Amplitude = 1d;
|
||||
}
|
||||
|
||||
public double Amplitude { get; set; }
|
||||
|
||||
public double Ease(double value)
|
||||
{
|
||||
var num = Math.Max(0.0, this.Amplitude);
|
||||
return Math.Pow(value, 3.0) - value * num * Math.Sin(Math.PI * value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="BounceEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
public class BounceEase : IEasingFunction
|
||||
{
|
||||
public BounceEase()
|
||||
{
|
||||
this.Bounces = 3;
|
||||
this.Bounciness = 2d;
|
||||
}
|
||||
|
||||
public int Bounces { get; set; }
|
||||
|
||||
public double Bounciness { get; set; }
|
||||
|
||||
public double Ease(double value)
|
||||
{
|
||||
double y1 = Math.Max(0.0, (double)this.Bounces);
|
||||
double num1 = this.Bounciness;
|
||||
if (num1 < 1.0 || num1 == 1d)
|
||||
num1 = 1001.0 / 1000.0;
|
||||
double num2 = Math.Pow(num1, y1);
|
||||
double num3 = 1.0 - num1;
|
||||
double num4 = (1.0 - num2) / num3 + num2 * 0.5;
|
||||
double y2 = Math.Floor(Math.Log(-(value * num4) * (1.0 - num1) + 1.0, num1));
|
||||
double y3 = y2 + 1.0;
|
||||
double num5 = (1.0 - Math.Pow(num1, y2)) / (num3 * num4);
|
||||
double num6 = (1.0 - Math.Pow(num1, y3)) / (num3 * num4);
|
||||
double num7 = (num5 + num6) * 0.5;
|
||||
double num8 = value - num7;
|
||||
double num9 = num7 - num5;
|
||||
double num10 = -Math.Pow(1.0 / num1, y1 - y2);
|
||||
double num11 = num9;
|
||||
double num12 = num11 * num11;
|
||||
return num10 / num12 * (num8 - num9) * (num8 + num9);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="CircleEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
using AnimationsDemo;
|
||||
|
||||
public class CircleEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
value = Math.Max(0.0, Math.Min(1.0, value));
|
||||
|
||||
var num1 = 1.0;
|
||||
var num2 = 1.0;
|
||||
var num3 = value;
|
||||
var num4 = num3 * num3;
|
||||
var num5 = Math.Sqrt(num2 - num4);
|
||||
|
||||
return num1 - num5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public interface IEasingFunction
|
||||
{
|
||||
double Ease(double value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="BackEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public class NoEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
return 1d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="PowerEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
public class PowerEase : IEasingFunction
|
||||
{
|
||||
public PowerEase()
|
||||
{
|
||||
this.Power = 2d;
|
||||
}
|
||||
|
||||
public double Power { get; set; }
|
||||
|
||||
public double Ease(double value)
|
||||
{
|
||||
double y = Math.Max(0.0, this.Power);
|
||||
return Math.Pow(value, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="QuadraticEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public class QuadraticEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
double num = value;
|
||||
return num * num;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="QuadraticEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public class QuarticEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
double num = value;
|
||||
return num * num * value * value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="QuinticEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public class QuinticEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
double num = value;
|
||||
return num * num * value * value * value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="SineEase.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
public class SineEase : IEasingFunction
|
||||
{
|
||||
public double Ease(double value)
|
||||
{
|
||||
return 1.0 - Math.Sin(Math.PI / 2.0 * (1.0 - value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using OxyPlot.Series;
|
||||
|
||||
public static partial class AnimationExtensions
|
||||
{
|
||||
private static readonly IEasingFunction DefaultEasingFunction = new NoEase();
|
||||
|
||||
static AnimationExtensions()
|
||||
{
|
||||
DefaultAnimationDelay = 0;
|
||||
DefaultAnimationDuration = 750;
|
||||
DefaultAnimationFrameDuration = 10;
|
||||
}
|
||||
|
||||
public static int DefaultAnimationDelay { get; set; }
|
||||
|
||||
public static int DefaultAnimationDuration { get; set; }
|
||||
|
||||
public static int DefaultAnimationFrameDuration { get; set; }
|
||||
|
||||
private static List<double> CalculateEaseValues(double range, int count, IEasingFunction easingFunction, double baseValue = 0d)
|
||||
{
|
||||
var items = new List<double>();
|
||||
|
||||
var easePhase = 1d / count;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var valueToEase = easePhase * i;
|
||||
var easeValue = easingFunction.Ease(valueToEase);
|
||||
|
||||
items.Add(baseValue + (easeValue * range));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private static void InsertDelayAnimationFrame(this List<AnimationFrame> animationFrames, TimeSpan delay)
|
||||
{
|
||||
if (animationFrames.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (delay <= TimeSpan.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var animationFrame = new AnimationFrame
|
||||
{
|
||||
Duration = delay
|
||||
};
|
||||
|
||||
animationFrames.Insert(1, animationFrame);
|
||||
}
|
||||
|
||||
private static List<IAnimatablePoint> GetAnimatablePoints(this DataPointSeries series)
|
||||
{
|
||||
var points = new List<IAnimatablePoint>();
|
||||
|
||||
var itemsSource = series.ItemsSource;
|
||||
if (itemsSource != null)
|
||||
{
|
||||
points.AddRange(from x in itemsSource.Cast<object>()
|
||||
where x is IAnimatablePoint
|
||||
select (IAnimatablePoint)x);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public static partial class AnimationExtensions
|
||||
{
|
||||
public static AnimationFrame GetFinalAnimationFrame(DataPointSeries series)
|
||||
{
|
||||
var animationFrame = new AnimationFrame
|
||||
{
|
||||
Duration = TimeSpan.Zero
|
||||
};
|
||||
|
||||
var points = series.GetAnimatablePoints();
|
||||
foreach (var point in points)
|
||||
{
|
||||
animationFrame.AnimationPoints.Add(new AnimationPoint
|
||||
{
|
||||
X = point.FinalX,
|
||||
Y = point.FinalY
|
||||
});
|
||||
}
|
||||
|
||||
return animationFrame;
|
||||
}
|
||||
|
||||
public static async Task AnimateSeriesAsync(
|
||||
this PlotModel plotModel,
|
||||
DataPointSeries series,
|
||||
List<AnimationFrame> animationFrames)
|
||||
{
|
||||
if (animationFrames.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var finalAnimationFrame = GetFinalAnimationFrame(series);
|
||||
animationFrames.Add(finalAnimationFrame);
|
||||
|
||||
var xAxis = plotModel.DefaultXAxis;
|
||||
var oldXAxisMinimum = xAxis.Minimum;
|
||||
var oldXAxisMaximum = xAxis.Maximum;
|
||||
|
||||
xAxis.Minimum = xAxis.ActualMinimum;
|
||||
xAxis.Maximum = xAxis.ActualMaximum;
|
||||
|
||||
var yAxis = plotModel.DefaultYAxis;
|
||||
var oldYAxisMinimum = yAxis.Minimum;
|
||||
var oldYAxisMaximum = yAxis.Maximum;
|
||||
|
||||
yAxis.Minimum = yAxis.ActualMinimum;
|
||||
yAxis.Maximum = yAxis.ActualMaximum;
|
||||
|
||||
var previousDataFieldX = series.DataFieldX;
|
||||
var previousDataFieldY = series.DataFieldY;
|
||||
|
||||
// Always fix up the data fields (we are using IAnimatablePoint from now on)
|
||||
series.DataFieldX = "X";
|
||||
series.DataFieldY = "Y";
|
||||
|
||||
var points = series.GetAnimatablePoints();
|
||||
|
||||
foreach (var animationFrame in animationFrames)
|
||||
{
|
||||
// TODO: consider implementing the IsVisible feature
|
||||
|
||||
var animationPoints = animationFrame.AnimationPoints;
|
||||
if (animationPoints.Count > 0)
|
||||
{
|
||||
for (var j = 0; j < points.Count; j++)
|
||||
{
|
||||
var animatablePoint = points[j];
|
||||
if (animatablePoint != null)
|
||||
{
|
||||
if (j < animationPoints.Count)
|
||||
{
|
||||
var animationPoint = animationPoints[j];
|
||||
|
||||
animatablePoint.X = animationPoint.X;
|
||||
animatablePoint.Y = animationPoint.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plotModel.InvalidatePlot(true);
|
||||
|
||||
await Task.Delay(animationFrame.Duration);
|
||||
}
|
||||
|
||||
xAxis.Minimum = oldXAxisMinimum;
|
||||
xAxis.Maximum = oldXAxisMaximum;
|
||||
|
||||
yAxis.Minimum = oldYAxisMinimum;
|
||||
yAxis.Maximum = oldYAxisMaximum;
|
||||
|
||||
series.DataFieldX = previousDataFieldX;
|
||||
series.DataFieldY = previousDataFieldY;
|
||||
|
||||
plotModel.InvalidatePlot(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public static partial class AnimationExtensions
|
||||
{
|
||||
public static async Task AnimateSeriesAsync(
|
||||
this PlotModel plotModel,
|
||||
LinearBarSeries series,
|
||||
AnimationSettings settings)
|
||||
{
|
||||
var points = series.GetAnimatablePoints();
|
||||
if (points.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var duration = settings.Duration;
|
||||
if (duration == default(TimeSpan))
|
||||
{
|
||||
duration = TimeSpan.FromMilliseconds(DefaultAnimationDuration);
|
||||
}
|
||||
|
||||
var easingFunction = settings.EasingFunction;
|
||||
if (easingFunction == null)
|
||||
{
|
||||
easingFunction = DefaultEasingFunction;
|
||||
}
|
||||
|
||||
var animationFrameDurationInMs = (int)settings.FrameDuration.TotalMilliseconds;
|
||||
var minimumValue = settings.MinimumValue;
|
||||
|
||||
var animationFrames = new List<AnimationFrame>();
|
||||
|
||||
// Animation assumptions:
|
||||
//
|
||||
// - Total duration: 300ms (in this example)
|
||||
// - At least animate each horizontal value separately
|
||||
// - First animate from left => right (70 % of the time)
|
||||
// - Second animate from center => end (30 % of the time)
|
||||
//
|
||||
// | ^
|
||||
// | |
|
||||
// | ___ |
|
||||
// | | | | 30 % of time
|
||||
// | ___ | | | 90 ms
|
||||
// | | | | | |
|
||||
// | | | ___ | | |
|
||||
// | | | | | | | |
|
||||
// |___|_|___|_|___|_|_____________________________ ^
|
||||
//
|
||||
// <---------------- 70 % of time ---------------->
|
||||
// (210 ms)
|
||||
|
||||
var horizontalDuration = duration.TotalMilliseconds / 100 * settings.HorizontalPercentage;
|
||||
var verticalDuration = duration.TotalMilliseconds / 100 * settings.VerticalPercentage;
|
||||
|
||||
var animationFrameCount = (int)(duration.TotalMilliseconds / animationFrameDurationInMs);
|
||||
var animationFrameDuration = TimeSpan.FromMilliseconds(animationFrameDurationInMs);
|
||||
|
||||
if (!minimumValue.HasValue)
|
||||
{
|
||||
minimumValue = 0d;
|
||||
|
||||
var defaultYAxis = plotModel.DefaultYAxis;
|
||||
if (defaultYAxis != null)
|
||||
{
|
||||
if (defaultYAxis.Minimum > 0d)
|
||||
{
|
||||
minimumValue = defaultYAxis.Minimum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var minX = (from point in points orderby point.X select point.X).Min();
|
||||
var maxX = (from point in points orderby point.X select point.X).Max();
|
||||
var deltaX = maxX - minX;
|
||||
|
||||
for (var i = 0; i < animationFrameCount; i++)
|
||||
{
|
||||
var animationFrame = new AnimationFrame
|
||||
{
|
||||
Duration = animationFrameDuration
|
||||
};
|
||||
|
||||
var currentTime = animationFrameDurationInMs * i;
|
||||
var percentage = i * 100d / animationFrameCount;
|
||||
|
||||
var horizontalPercentage = currentTime * 100d / horizontalDuration;
|
||||
if (horizontalPercentage > 100d)
|
||||
{
|
||||
horizontalPercentage = 100d;
|
||||
}
|
||||
|
||||
var currentDeltaX = deltaX / 100d * horizontalPercentage;
|
||||
var currentX = minX + currentDeltaX;
|
||||
|
||||
// Get the last visible point. It should not be based on the index (can be really different), but on the X position
|
||||
// since we want to draw a smooth animation
|
||||
var lastVisibleHorizontalPoint = 0;
|
||||
for (int j = 0; j < points.Count; j++)
|
||||
{
|
||||
var x = points[j].FinalX;
|
||||
if (x > currentX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lastVisibleHorizontalPoint = j;
|
||||
}
|
||||
|
||||
for (var j = 0; j < points.Count; j++)
|
||||
{
|
||||
var point = points[j];
|
||||
|
||||
var isVisible = false;
|
||||
var x = point.FinalX;
|
||||
var y = 0d;
|
||||
|
||||
if (j <= lastVisibleHorizontalPoint)
|
||||
{
|
||||
isVisible = true;
|
||||
y = point.FinalY;
|
||||
|
||||
// We know how long an y animation takes. We only have to calculate if this start time of this x animation
|
||||
// is longer than verticalDuration ago
|
||||
var localDeltaX = point.FinalX - minX;
|
||||
var localPercentageX = localDeltaX * 100d / deltaX;
|
||||
var startTime = horizontalDuration / 100 * localPercentageX;
|
||||
var endTime = startTime + verticalDuration;
|
||||
|
||||
if (endTime > currentTime)
|
||||
{
|
||||
var timeDeltaTotal = endTime - startTime;
|
||||
var timeDeltaCurrent = currentTime - startTime;
|
||||
var subPercentage = timeDeltaCurrent * 100d / timeDeltaTotal;
|
||||
|
||||
// This bar is part of the current animation, calculate the Y relative to 30 % of the time based on the current index
|
||||
// Calculate the % that offset is based on totalTimeDelta
|
||||
|
||||
// Calculate point to animate from
|
||||
var maxY = point.FinalY;
|
||||
var minY = minimumValue.Value;
|
||||
var deltaY = maxY - minY;
|
||||
|
||||
// We need to ease against percentage (between 0 and 1)
|
||||
var ease = easingFunction.Ease(subPercentage / 100);
|
||||
var currentDeltaY = deltaY * ease;
|
||||
|
||||
y = minY + currentDeltaY;
|
||||
}
|
||||
}
|
||||
|
||||
animationFrame.AnimationPoints.Add(new AnimationPoint
|
||||
{
|
||||
IsVisible = isVisible,
|
||||
X = x,
|
||||
Y = y
|
||||
});
|
||||
}
|
||||
|
||||
animationFrames.Add(animationFrame);
|
||||
}
|
||||
|
||||
animationFrames.InsertDelayAnimationFrame(settings.Delay);
|
||||
|
||||
await plotModel.AnimateSeriesAsync(series, animationFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationExtensions.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public static partial class AnimationExtensions
|
||||
{
|
||||
public static async Task AnimateSeriesAsync(
|
||||
this PlotModel plotModel,
|
||||
LineSeries series,
|
||||
AnimationSettings settings)
|
||||
{
|
||||
var points = series.GetAnimatablePoints();
|
||||
if (points.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var duration = settings.Duration;
|
||||
if (duration == default(TimeSpan))
|
||||
{
|
||||
duration = TimeSpan.FromMilliseconds(DefaultAnimationDuration);
|
||||
}
|
||||
|
||||
var easingFunction = settings.EasingFunction;
|
||||
if (easingFunction == null)
|
||||
{
|
||||
easingFunction = DefaultEasingFunction;
|
||||
}
|
||||
|
||||
var animationFrameDurationInMs = (int)settings.FrameDuration.TotalMilliseconds;
|
||||
var minimumValue = settings.MinimumValue;
|
||||
|
||||
var animationFrames = new List<AnimationFrame>();
|
||||
|
||||
var horizontalDuration = duration.TotalMilliseconds / 100 * settings.HorizontalPercentage;
|
||||
var verticalDuration = duration.TotalMilliseconds / 100 * settings.VerticalPercentage;
|
||||
|
||||
var animationFrameCount = (int)(duration.TotalMilliseconds / animationFrameDurationInMs);
|
||||
var animationFrameDuration = TimeSpan.FromMilliseconds(animationFrameDurationInMs);
|
||||
|
||||
if (!minimumValue.HasValue)
|
||||
{
|
||||
minimumValue = 0d;
|
||||
|
||||
var defaultYAxis = plotModel.DefaultYAxis;
|
||||
if (defaultYAxis != null)
|
||||
{
|
||||
if (defaultYAxis.Minimum > 0d)
|
||||
{
|
||||
minimumValue = defaultYAxis.Minimum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var minX = (from point in points orderby point.X select point.X).Min();
|
||||
var maxX = (from point in points orderby point.X select point.X).Max();
|
||||
var deltaX = maxX - minX;
|
||||
|
||||
for (var i = 0; i < animationFrameCount; i++)
|
||||
{
|
||||
var animationFrame = new AnimationFrame
|
||||
{
|
||||
Duration = animationFrameDuration
|
||||
};
|
||||
|
||||
var currentTime = animationFrameDurationInMs * i;
|
||||
var percentage = i * 100d / animationFrameCount;
|
||||
|
||||
var horizontalPercentage = currentTime * 100d / horizontalDuration;
|
||||
if (horizontalPercentage > 100d)
|
||||
{
|
||||
horizontalPercentage = 100d;
|
||||
}
|
||||
|
||||
var currentDeltaX = deltaX / 100d * horizontalPercentage;
|
||||
var currentX = minX + currentDeltaX;
|
||||
|
||||
// Get the last visible point. It should not be based on the index (can be really different), but on the X position
|
||||
// since we want to draw a smooth animation
|
||||
var lastVisibleHorizontalPoint = 0;
|
||||
for (int j = 0; j < points.Count; j++)
|
||||
{
|
||||
if (points[j].FinalX > currentX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lastVisibleHorizontalPoint = j;
|
||||
}
|
||||
|
||||
for (var j = 0; j < points.Count; j++)
|
||||
{
|
||||
var point = points[j];
|
||||
|
||||
var isVisible = true;
|
||||
var y = point.FinalY;
|
||||
var x = point.FinalX;
|
||||
|
||||
var nextPointIndex = lastVisibleHorizontalPoint + 1;
|
||||
|
||||
if (j > nextPointIndex)
|
||||
{
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
if (j >= nextPointIndex)
|
||||
{
|
||||
// Calculate the position the y line is in currently (based on x1 and x2)
|
||||
var previousPoint = points[lastVisibleHorizontalPoint];
|
||||
var nextPoint = points[nextPointIndex];
|
||||
|
||||
var previousX = previousPoint.FinalX;
|
||||
var nextX = nextPoint.FinalX;
|
||||
|
||||
var totalDeltaX = nextX - previousX;
|
||||
var subDeltaX = currentX - previousX;
|
||||
|
||||
var subPercentage = (subDeltaX * 100) / totalDeltaX;
|
||||
|
||||
var previousY = previousPoint.FinalY;
|
||||
var nextY = nextPoint.FinalY;
|
||||
var totalDeltaY = nextY - previousY;
|
||||
|
||||
var subDeltaY = totalDeltaY / 100 * subPercentage;
|
||||
|
||||
y = previousY + subDeltaY;
|
||||
x = currentX;
|
||||
}
|
||||
|
||||
// Calculate possible ease functions
|
||||
if (j < nextPointIndex)
|
||||
{
|
||||
// We know how long an y animation takes. We only have to calculate if this start time of this x animation
|
||||
// is longer than verticalDuration ago
|
||||
var localDeltaX = point.FinalX - minX;
|
||||
var localPercentageX = localDeltaX * 100d / deltaX;
|
||||
var startTime = horizontalDuration / 100 * localPercentageX;
|
||||
var endTime = startTime + verticalDuration;
|
||||
if (endTime > currentTime)
|
||||
{
|
||||
var timeDeltaTotal = endTime - startTime;
|
||||
var timeDeltaCurrent = currentTime - startTime;
|
||||
var easePercentage = timeDeltaCurrent * 100d / timeDeltaTotal;
|
||||
|
||||
// This bar is part of the current animation, calculate the Y relative to 30 % of the time based on the current index
|
||||
// Calculate the % that offset is based on totalTimeDelta
|
||||
|
||||
// Calculate point to animate from
|
||||
var maxY = point.FinalY;
|
||||
var minY = minimumValue.Value;
|
||||
var deltaY = maxY - minY;
|
||||
|
||||
// We need to ease against percentage (between 0 and 1)
|
||||
var ease = easingFunction.Ease(easePercentage / 100);
|
||||
var currentDeltaY = deltaY * ease;
|
||||
|
||||
y = minY + currentDeltaY;
|
||||
}
|
||||
}
|
||||
|
||||
animationFrame.AnimationPoints.Add(new AnimationPoint
|
||||
{
|
||||
X = x,
|
||||
Y = y,
|
||||
IsVisible = isVisible
|
||||
});
|
||||
}
|
||||
|
||||
animationFrames.Add(animationFrame);
|
||||
}
|
||||
|
||||
animationFrames.InsertDelayAnimationFrame(settings.Delay);
|
||||
|
||||
await plotModel.AnimateSeriesAsync(series, animationFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<Window x:Class="AnimationsDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:AnimationsDemo="clr-namespace:AnimationsDemo"
|
||||
Title="AnimationsDemo" Height="480" Width="740">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TabControl x:Name="tabControl" Grid.Row="0">
|
||||
<TabItem Header="Linear Bar Series">
|
||||
<AnimationsDemo:LinearBarView />
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Line Series">
|
||||
<AnimationsDemo:LineSeriesView />
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Area Series">
|
||||
<AnimationsDemo:AreaSeriesView />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
<AnimationsDemo:AnimationSettingsControl Grid.Row="1" DataContext="{Binding ElementName=tabControl, Path=SelectedItem.Content.DataContext}" />
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,27 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System.Windows;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example(null, "Animations using extension methods on series.")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationFrame.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class AnimationFrame
|
||||
{
|
||||
private static readonly TimeSpan DefaultDuration = TimeSpan.FromMilliseconds(15);
|
||||
|
||||
public AnimationFrame()
|
||||
{
|
||||
AnimationPoints = new List<AnimationPoint>();
|
||||
Duration = DefaultDuration;
|
||||
}
|
||||
|
||||
public TimeSpan Duration { get; set; }
|
||||
|
||||
public List<AnimationPoint> AnimationPoints { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationPoint.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
[DebuggerDisplay("{X} / {Y} (IsVisible = {IsVisible})")]
|
||||
public class AnimationPoint
|
||||
{
|
||||
public AnimationPoint()
|
||||
{
|
||||
this.IsVisible = true;
|
||||
}
|
||||
|
||||
public double X { get; set; }
|
||||
|
||||
public double Y { get; set; }
|
||||
|
||||
public bool IsVisible { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AnimationFrame.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
|
||||
public class AnimationSettings
|
||||
{
|
||||
public AnimationSettings()
|
||||
{
|
||||
this.HorizontalPercentage = 70;
|
||||
this.VerticalPercentage = 30;
|
||||
|
||||
this.Delay = TimeSpan.FromMilliseconds(AnimationExtensions.DefaultAnimationDelay);
|
||||
this.Duration = TimeSpan.FromMilliseconds(AnimationExtensions.DefaultAnimationDuration);
|
||||
this.FrameDuration = TimeSpan.FromMilliseconds(AnimationExtensions.DefaultAnimationFrameDuration);
|
||||
}
|
||||
|
||||
public double? MinimumValue { get; set; }
|
||||
|
||||
public double HorizontalPercentage { get; set; }
|
||||
|
||||
public double VerticalPercentage { get; set; }
|
||||
|
||||
public TimeSpan Delay { get; set; }
|
||||
|
||||
public TimeSpan Duration { get; set; }
|
||||
|
||||
public TimeSpan FrameDuration { get; set; }
|
||||
|
||||
public IEasingFunction EasingFunction { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="IAnimatablePoint.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public interface IAnimatablePoint
|
||||
{
|
||||
double FinalX { get; set; }
|
||||
|
||||
double FinalY { get; set; }
|
||||
|
||||
double X { get; set; }
|
||||
|
||||
double Y { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="Pnl.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using OxyPlot.Axes;
|
||||
|
||||
[DebuggerDisplay("X: {X} => {FinalX} | Y: {Y} => {FinalY}")]
|
||||
public class Pnl : IAnimatablePoint
|
||||
{
|
||||
public double FinalX { get; set; }
|
||||
public double FinalY { get; set; }
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
|
||||
public DateTime Time
|
||||
{
|
||||
get { return DateTimeAxis.ToDateTime(this.X); }
|
||||
set
|
||||
{
|
||||
var finalX = DateTimeAxis.ToDouble(value);
|
||||
|
||||
this.FinalX = finalX;
|
||||
this.X = finalX;
|
||||
}
|
||||
}
|
||||
|
||||
public double Value
|
||||
{
|
||||
get { return this.Y;}
|
||||
set
|
||||
{
|
||||
this.FinalY = value;
|
||||
this.Y = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0:HH:mm} {1:0.0}", this.Time, this.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
|
||||
public abstract class AnimationViewModelBase : IAnimationViewModel
|
||||
{
|
||||
protected AnimationViewModelBase()
|
||||
{
|
||||
this.EasingFunctions = (from type in typeof(CircleEase).Assembly.GetTypes()
|
||||
where type.GetInterfaces().Any(x => x == typeof(IEasingFunction)) && !type.IsAbstract
|
||||
orderby type.Name
|
||||
select type).ToList();
|
||||
this.SelectedEasingFunction = this.EasingFunctions.FirstOrDefault();
|
||||
|
||||
if (!this.SupportsEasingFunction)
|
||||
{
|
||||
this.SelectedEasingFunction = typeof(NoEase);
|
||||
}
|
||||
|
||||
this.AnimationDuration = 1000;
|
||||
this.AnimationFrameDuration = AnimationExtensions.DefaultAnimationFrameDuration;
|
||||
this.HorizontalPercentage = 70;
|
||||
this.VerticalPercentage = 30;
|
||||
|
||||
this.PlotModel = new PlotModel();
|
||||
}
|
||||
|
||||
public abstract bool SupportsEasingFunction { get; }
|
||||
|
||||
public PlotModel PlotModel { get; private set; }
|
||||
|
||||
public List<Type> EasingFunctions { get; private set; }
|
||||
|
||||
public Type SelectedEasingFunction { get; set; }
|
||||
|
||||
public double HorizontalPercentage { get; set; }
|
||||
|
||||
public double VerticalPercentage { get; set; }
|
||||
|
||||
public int AnimationDelay { get; set; }
|
||||
|
||||
public int AnimationDuration { get; set; }
|
||||
|
||||
public int AnimationFrameDuration { get; set; }
|
||||
|
||||
public Task AnimateAsync()
|
||||
{
|
||||
var easingFunction = (IEasingFunction)Activator.CreateInstance(this.SelectedEasingFunction);
|
||||
|
||||
var animationSettings = new AnimationSettings
|
||||
{
|
||||
EasingFunction = easingFunction,
|
||||
Duration = TimeSpan.FromMilliseconds(this.AnimationDuration),
|
||||
FrameDuration = TimeSpan.FromMilliseconds(this.AnimationFrameDuration),
|
||||
Delay = TimeSpan.FromMilliseconds(this.AnimationDelay),
|
||||
HorizontalPercentage = this.HorizontalPercentage,
|
||||
VerticalPercentage = this.VerticalPercentage
|
||||
};
|
||||
|
||||
return this.AnimateAsync(animationSettings);
|
||||
}
|
||||
|
||||
public abstract Task AnimateAsync(AnimationSettings animationSettings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AreaSeriesViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public class AreaSeriesViewModel : AnimationViewModelBase
|
||||
{
|
||||
public AreaSeriesViewModel()
|
||||
{
|
||||
var pnls = new List<Pnl>();
|
||||
|
||||
var random = new Random(31);
|
||||
var dateTime = DateTime.Today.Add(TimeSpan.FromHours(9));
|
||||
for (var pointIndex = 0; pointIndex < 50; pointIndex++)
|
||||
{
|
||||
pnls.Add(new Pnl
|
||||
{
|
||||
Time = dateTime,
|
||||
Value = -200 + random.Next(1000),
|
||||
});
|
||||
dateTime = dateTime.AddMinutes(1);
|
||||
}
|
||||
|
||||
var minimum = pnls.Min(x => x.Value);
|
||||
var maximum = pnls.Max(x => x.Value);
|
||||
|
||||
var plotModel = this.PlotModel;
|
||||
plotModel.Title = "Area Series Animation Demo";
|
||||
|
||||
var series = new AreaSeries
|
||||
{
|
||||
Title = "P & L",
|
||||
ItemsSource = pnls,
|
||||
DataFieldX = "Time",
|
||||
DataFieldY = "Value",
|
||||
Color = OxyColor.Parse("#4CAF50"),
|
||||
Fill = OxyColor.Parse("#454CAF50"),
|
||||
MarkerSize = 3,
|
||||
MarkerFill = OxyColor.Parse("#FFFFFFFF"),
|
||||
MarkerStroke = OxyColor.Parse("#4CAF50"),
|
||||
MarkerStrokeThickness = 1.5,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 1,
|
||||
};
|
||||
plotModel.Series.Add(series);
|
||||
|
||||
var annotation = new LineAnnotation
|
||||
{
|
||||
Type = LineAnnotationType.Horizontal,
|
||||
Y = 0
|
||||
};
|
||||
plotModel.Annotations.Add(annotation);
|
||||
|
||||
var dateTimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
IntervalType = DateTimeIntervalType.Hours,
|
||||
IntervalLength = 50
|
||||
};
|
||||
plotModel.Axes.Add(dateTimeAxis);
|
||||
|
||||
var margin = (maximum - minimum) * 0.05;
|
||||
|
||||
var valueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
Minimum = minimum - margin,
|
||||
Maximum = maximum + margin,
|
||||
};
|
||||
plotModel.Axes.Add(valueAxis);
|
||||
}
|
||||
|
||||
public override bool SupportsEasingFunction { get { return true; } }
|
||||
|
||||
public override async Task AnimateAsync(AnimationSettings animationSettings)
|
||||
{
|
||||
var plotModel = this.PlotModel;
|
||||
var series = plotModel.Series.First() as AreaSeries;
|
||||
if (series != null)
|
||||
{
|
||||
await plotModel.AnimateSeriesAsync(series, animationSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="IAnimationViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface IAnimationViewModel
|
||||
{
|
||||
bool SupportsEasingFunction { get; }
|
||||
|
||||
Task AnimateAsync();
|
||||
Task AnimateAsync(AnimationSettings animationSettings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="LineSeriesViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public class LineSeriesViewModel : AnimationViewModelBase
|
||||
{
|
||||
public LineSeriesViewModel()
|
||||
{
|
||||
var pnls = new List<Pnl>();
|
||||
|
||||
var random = new Random(31);
|
||||
var dateTime = DateTime.Today.Add(TimeSpan.FromHours(9));
|
||||
for (var pointIndex = 0; pointIndex < 50; pointIndex++)
|
||||
{
|
||||
pnls.Add(new Pnl
|
||||
{
|
||||
Time = dateTime,
|
||||
Value = -200 + random.Next(1000),
|
||||
});
|
||||
dateTime = dateTime.AddMinutes(1);
|
||||
}
|
||||
|
||||
var minimum = pnls.Min(x => x.Value);
|
||||
var maximum = pnls.Max(x => x.Value);
|
||||
|
||||
var plotModel = this.PlotModel;
|
||||
plotModel.Title = "Line Series Animation Demo";
|
||||
|
||||
var series = new LineSeries
|
||||
{
|
||||
Title = "P & L",
|
||||
ItemsSource = pnls,
|
||||
DataFieldX = "Time",
|
||||
DataFieldY = "Value",
|
||||
Color = OxyColor.Parse("#4CAF50"),
|
||||
MarkerSize = 3,
|
||||
MarkerFill = OxyColor.Parse("#FFFFFFFF"),
|
||||
MarkerStroke = OxyColor.Parse("#4CAF50"),
|
||||
MarkerStrokeThickness = 1.5,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 1,
|
||||
};
|
||||
plotModel.Series.Add(series);
|
||||
|
||||
var annotation = new LineAnnotation
|
||||
{
|
||||
Type = LineAnnotationType.Horizontal,
|
||||
Y = 0
|
||||
};
|
||||
plotModel.Annotations.Add(annotation);
|
||||
|
||||
var dateTimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
IntervalType = DateTimeIntervalType.Hours,
|
||||
IntervalLength = 50
|
||||
};
|
||||
plotModel.Axes.Add(dateTimeAxis);
|
||||
|
||||
var margin = (maximum - minimum) * 0.05;
|
||||
|
||||
var valueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
Minimum = minimum - margin,
|
||||
Maximum = maximum + margin,
|
||||
};
|
||||
plotModel.Axes.Add(valueAxis);
|
||||
}
|
||||
|
||||
public override bool SupportsEasingFunction { get { return true; } }
|
||||
|
||||
public override async Task AnimateAsync(AnimationSettings animationSettings)
|
||||
{
|
||||
var plotModel = this.PlotModel;
|
||||
var series = plotModel.Series.First() as LineSeries;
|
||||
if (series != null)
|
||||
{
|
||||
await plotModel.AnimateSeriesAsync(series, animationSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
public class LinearBarViewModel : AnimationViewModelBase
|
||||
{
|
||||
public LinearBarViewModel()
|
||||
{
|
||||
var pnls = new List<Pnl>();
|
||||
|
||||
var random = new Random(31);
|
||||
var dateTime = DateTime.Today.Add(TimeSpan.FromHours(9));
|
||||
for (var pointIndex = 0; pointIndex < 50; pointIndex++)
|
||||
{
|
||||
pnls.Add(new Pnl
|
||||
{
|
||||
Time = dateTime,
|
||||
Value = -200 + random.Next(1000),
|
||||
});
|
||||
dateTime = dateTime.AddMinutes(1);
|
||||
}
|
||||
|
||||
var minimum = pnls.Min(x => x.Value);
|
||||
var maximum = pnls.Max(x => x.Value);
|
||||
|
||||
var plotModel = this.PlotModel;
|
||||
plotModel.Title = "Linear Bar Series Animation Demo";
|
||||
|
||||
var series = new LinearBarSeries
|
||||
{
|
||||
Title = "P & L",
|
||||
ItemsSource = pnls,
|
||||
DataFieldX = "Time",
|
||||
DataFieldY = "Value",
|
||||
FillColor = OxyColor.Parse("#454CAF50"),
|
||||
StrokeColor = OxyColor.Parse("#4CAF50"),
|
||||
StrokeThickness = 1,
|
||||
BarWidth = 5
|
||||
};
|
||||
plotModel.Series.Add(series);
|
||||
|
||||
var annotation = new LineAnnotation
|
||||
{
|
||||
Type = LineAnnotationType.Horizontal,
|
||||
Y = 0
|
||||
};
|
||||
plotModel.Annotations.Add(annotation);
|
||||
|
||||
var dateTimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
IntervalType = DateTimeIntervalType.Hours,
|
||||
IntervalLength = 50
|
||||
};
|
||||
plotModel.Axes.Add(dateTimeAxis);
|
||||
|
||||
var margin = (maximum - minimum) * 0.05;
|
||||
|
||||
var valueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
Minimum = minimum - margin,
|
||||
Maximum = maximum + margin,
|
||||
};
|
||||
plotModel.Axes.Add(valueAxis);
|
||||
}
|
||||
|
||||
public override bool SupportsEasingFunction { get { return true; } }
|
||||
|
||||
public override async Task AnimateAsync(AnimationSettings animationSettings)
|
||||
{
|
||||
var plotModel = this.PlotModel;
|
||||
var series = plotModel.Series.First() as LinearBarSeries;
|
||||
if (series != null)
|
||||
{
|
||||
await plotModel.AnimateSeriesAsync(series, animationSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="AnimationsDemo.AreaSeriesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
|
||||
|
||||
<Grid>
|
||||
<oxy:PlotView Model="{Binding PlotModel}" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="AreaSeriesView.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public partial class AreaSeriesView
|
||||
{
|
||||
public AreaSeriesView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = new AreaSeriesViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="AnimationsDemo.LineSeriesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
|
||||
|
||||
<Grid>
|
||||
<oxy:PlotView Model="{Binding PlotModel}" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="LineSeriesView.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public partial class LineSeriesView
|
||||
{
|
||||
public LineSeriesView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = new LineSeriesViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="AnimationsDemo.LinearBarView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
|
||||
|
||||
<Grid>
|
||||
<oxy:PlotView Model="{Binding PlotModel}" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="LinearBarView.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace AnimationsDemo
|
||||
{
|
||||
public partial class LinearBarView
|
||||
{
|
||||
public LinearBarView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = new LinearBarViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Window x:Class="ContextMenuDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" Title="ContextMenuDemo" Height="480" Width="640">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Reset" Command="{Binding ResetCommand}"></MenuItem>
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</Window>
|
||||
@@ -0,0 +1,51 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ContextMenuDemo
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
using DelegateCommand = PropertyTools.Wpf.DelegateCommand;
|
||||
using ICommand = System.Windows.Input.ICommand;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Integrate with a ContextMenu")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
var model = new PlotModel { Title = "ContextMenu" };
|
||||
model.Series.Add(new FunctionSeries(Math.Sin, 0, 10, 200));
|
||||
this.Model = model;
|
||||
|
||||
this.ResetCommand = new DelegateCommand(() =>
|
||||
{
|
||||
this.Model.ResetAllAxes();
|
||||
this.Model.InvalidatePlot(false);
|
||||
});
|
||||
|
||||
this.DataContext = this;
|
||||
}
|
||||
|
||||
public ICommand ResetCommand { get; set; }
|
||||
|
||||
public PlotModel Model { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// The main view model.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ContourDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
/// <summary>
|
||||
/// The main view model.
|
||||
/// </summary>
|
||||
public class MainViewModel : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// The selected example.
|
||||
/// </summary>
|
||||
private Example selectedExample;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainViewModel" /> class.
|
||||
/// </summary>
|
||||
public MainViewModel()
|
||||
{
|
||||
this.Examples = new List<Example>();
|
||||
this.AddExamples();
|
||||
this.SelectedExample = this.Examples[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the examples.
|
||||
/// </summary>
|
||||
/// <value>The examples.</value>
|
||||
public List<Example> Examples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the plot model.
|
||||
/// </summary>
|
||||
/// <value>The plot model.</value>
|
||||
public PlotModel PlotModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected example.
|
||||
/// </summary>
|
||||
/// <value>The selected example.</value>
|
||||
public Example SelectedExample
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.selectedExample;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.selectedExample = value;
|
||||
this.RaisePropertyChanged("SelectedExample");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the property changed event.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
protected void RaisePropertyChanged(string property)
|
||||
{
|
||||
PropertyChangedEventHandler handler = this.PropertyChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new PropertyChangedEventArgs(property));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the examples.
|
||||
/// </summary>
|
||||
private void AddExamples()
|
||||
{
|
||||
Func<double, double, double> peaks =
|
||||
(x, y) =>
|
||||
3 * (1 - x) * (1 - x) * Math.Exp(-(x * x) - (y + 1) * (y + 1))
|
||||
- 10 * (x / 5 - x * x * x - y * y * y * y * y) * Math.Exp(-x * x - y * y)
|
||||
- 1.0 / 3 * Math.Exp(-(x + 1) * (x + 1) - y * y);
|
||||
|
||||
this.Examples.Add(new Example("peaks", -3, 3, 0.05, -3, 3, 0.05, -6, 10, 1, peaks));
|
||||
Func<double, double> square = x => x * x;
|
||||
this.Examples.Add(
|
||||
new Example(
|
||||
"Conrec example 1",
|
||||
-1.5,
|
||||
1.5,
|
||||
0.1,
|
||||
-1.5,
|
||||
1.5,
|
||||
0.1,
|
||||
0,
|
||||
2.25,
|
||||
0.25,
|
||||
(x, y) =>
|
||||
1.0
|
||||
/ (square(x * x + (y - 0.842) * (y + 0.842)) + square(x * (y - 0.842) + x * (y - 0.842)))));
|
||||
|
||||
// todo: something wrong here?
|
||||
double c = 0;
|
||||
this.Examples.Add(
|
||||
new Example(
|
||||
"Conrec example 2",
|
||||
-2 * Math.PI,
|
||||
2 * Math.PI,
|
||||
0.25,
|
||||
-2 * Math.PI,
|
||||
2 * Math.PI,
|
||||
0.25,
|
||||
-1,
|
||||
1,
|
||||
0.02,
|
||||
(x, y) =>
|
||||
Math.Sin(Math.Sqrt(x * x + y * y)) + y != 0 ? 1.0 / Math.Sqrt((x - c) * (x - c) + y * y) : 0));
|
||||
|
||||
this.Examples.Add(
|
||||
new Example(
|
||||
"sin(x)*cos(y)",
|
||||
-Math.PI,
|
||||
Math.PI,
|
||||
0.1,
|
||||
-Math.PI,
|
||||
Math.PI,
|
||||
0.1,
|
||||
-1,
|
||||
1,
|
||||
0.1,
|
||||
(x, y) => Math.Sin(x) * Math.Cos(y)));
|
||||
|
||||
this.Examples.Add(new Example("x*y", -1, 1, 0.1, -1, 1, 0.1, -1, 1, 0.1, (x, y) => x * y));
|
||||
this.Examples.Add(new Example("x^{2}+y^{2}", -1, 1, 0.1, -1, 1, 0.1, -1, 1, 0.1, (x, y) => x * x + y * y));
|
||||
this.Examples.Add(
|
||||
new Example(
|
||||
"atan2(y,x)",
|
||||
-1,
|
||||
1,
|
||||
0.1,
|
||||
-1,
|
||||
1,
|
||||
0.1,
|
||||
-180,
|
||||
180,
|
||||
10,
|
||||
(x, y) => Math.Atan2(y, x) * 180 / Math.PI,
|
||||
"0°"));
|
||||
|
||||
this.Examples.Add(new Example("y/x", -1, 1, 0.1, -1, 1, 0.1, -1, 1, 0.1, (x, y) => y / x, "0%"));
|
||||
|
||||
// http://en.wikipedia.org/wiki/Sinc_function
|
||||
this.Examples.Add(
|
||||
new Example(
|
||||
"sinc(r+0.1)",
|
||||
-8,
|
||||
8,
|
||||
0.2,
|
||||
-8,
|
||||
8,
|
||||
0.2,
|
||||
-0.2,
|
||||
1,
|
||||
0.1,
|
||||
(x, y) =>
|
||||
{
|
||||
double r = Math.Sqrt(x * x + y * y);
|
||||
return Math.Sin(r + 0.1) / (r + 0.1);
|
||||
},
|
||||
"0.0"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an example.
|
||||
/// </summary>
|
||||
public class Example
|
||||
{
|
||||
/// <summary>
|
||||
/// The d.
|
||||
/// </summary>
|
||||
private readonly double[,] D;
|
||||
|
||||
/// <summary>
|
||||
/// The x.
|
||||
/// </summary>
|
||||
private readonly double[] X;
|
||||
|
||||
/// <summary>
|
||||
/// The y.
|
||||
/// </summary>
|
||||
private readonly double[] Y;
|
||||
|
||||
/// <summary>
|
||||
/// The z.
|
||||
/// </summary>
|
||||
private readonly double[] Z;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Example" /> class.
|
||||
/// </summary>
|
||||
/// <param name="title">The title.</param>
|
||||
/// <param name="minx">The minx.</param>
|
||||
/// <param name="maxx">The maxx.</param>
|
||||
/// <param name="dx">The dx.</param>
|
||||
/// <param name="miny">The miny.</param>
|
||||
/// <param name="maxy">The maxy.</param>
|
||||
/// <param name="dy">The dy.</param>
|
||||
/// <param name="minz">The minz.</param>
|
||||
/// <param name="maxz">The maxz.</param>
|
||||
/// <param name="dz">The dz.</param>
|
||||
/// <param name="f">The f.</param>
|
||||
/// <param name="formatString">The format string.</param>
|
||||
public Example(
|
||||
string title,
|
||||
double minx,
|
||||
double maxx,
|
||||
double dx,
|
||||
double miny,
|
||||
double maxy,
|
||||
double dy,
|
||||
double minz,
|
||||
double maxz,
|
||||
double dz,
|
||||
Func<double, double, double> f,
|
||||
string formatString = null)
|
||||
{
|
||||
this.Title = title;
|
||||
this.X = ArrayBuilder.CreateVector(minx, maxx, dx);
|
||||
this.Y = ArrayBuilder.CreateVector(miny, maxy, dy);
|
||||
this.Z = ArrayBuilder.CreateVector(minz, maxz, dz);
|
||||
this.D = ArrayBuilder.Evaluate(f, this.X, this.Y);
|
||||
this.FormatString = formatString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
public string FormatString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot model.
|
||||
/// </summary>
|
||||
/// <value>The plot model.</value>
|
||||
public PlotModel PlotModel
|
||||
{
|
||||
get
|
||||
{
|
||||
var m = new PlotModel { Title = this.Title };
|
||||
var cs = new ContourSeries
|
||||
{
|
||||
ColumnCoordinates = this.X,
|
||||
RowCoordinates = this.Y,
|
||||
Data = this.D,
|
||||
ContourLevels = this.Z,
|
||||
LabelFormatString = this.FormatString
|
||||
};
|
||||
cs.CalculateContours();
|
||||
m.Series.Add(cs);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Title;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Window x:Class="ContourDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" Title="ContourDemo" Height="480" Width="640">
|
||||
<DockPanel>
|
||||
<Menu DockPanel.Dock="Top">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="E_xit" Click="FileExit"/>
|
||||
</MenuItem>
|
||||
<MenuItem x:Name="ExamplesMenu" Header="Examples" ItemsSource="{Binding Examples}">
|
||||
<MenuItem.ItemContainerStyle>
|
||||
<Style TargetType="MenuItem">
|
||||
<EventSetter Event="Click" Handler="ExampleClick"/>
|
||||
</Style>
|
||||
</MenuItem.ItemContainerStyle>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<oxy:PlotView Model="{Binding SelectedExample.PlotModel}"/>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,51 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ContourDemo
|
||||
{
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Plotting with contour series.")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private MainViewModel vm = new MainViewModel();
|
||||
|
||||
private MenuItem checkedItem;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this.vm;
|
||||
}
|
||||
|
||||
private void FileExit(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void ExampleClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var mi = (MenuItem)sender;
|
||||
if (this.checkedItem != null)
|
||||
{
|
||||
this.checkedItem.IsChecked = false;
|
||||
}
|
||||
|
||||
mi.IsChecked = true;
|
||||
this.checkedItem = mi;
|
||||
this.vm.SelectedExample = mi.DataContext as MainViewModel.Example;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="CustomPlotController.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Represents the plot controller for the main window.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ControllerDemo
|
||||
{
|
||||
using OxyPlot;
|
||||
|
||||
public class CustomPlotController : PlotController
|
||||
{
|
||||
public CustomPlotController()
|
||||
{
|
||||
this.UnbindAll();
|
||||
this.BindKeyDown(OxyKey.Left, PlotCommands.PanRight);
|
||||
this.BindKeyDown(OxyKey.Right, PlotCommands.PanLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Represents the view-model for the main window.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ControllerDemo
|
||||
{
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the view-model for the main window.
|
||||
/// </summary>
|
||||
public class MainViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainViewModel" /> class.
|
||||
/// </summary>
|
||||
public MainViewModel()
|
||||
{
|
||||
// Set the Model property, the INotifyPropertyChanged event will make the WPF Plot control update its content
|
||||
this.Model = CreatePlotModel("Custom PlotController", "Supports left/right keys only");
|
||||
this.Controller = new CustomPlotController();
|
||||
|
||||
this.Model1 = CreatePlotModel("Default controller", null);
|
||||
this.Model2 = CreatePlotModel("Default controller", "UnbindAll()");
|
||||
}
|
||||
|
||||
private static PlotModel CreatePlotModel(string title, string subtitle)
|
||||
{
|
||||
// Create the plot model
|
||||
var tmp = new PlotModel { Title = title, Subtitle = subtitle };
|
||||
|
||||
tmp.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
|
||||
tmp.Axes.Add(new LinearAxis { Position = AxisPosition.Left });
|
||||
|
||||
// Create two line series (markers are hidden by default)
|
||||
var series1 = new LineSeries { Title = "Series 1", MarkerType = MarkerType.Circle };
|
||||
series1.Points.Add(new DataPoint(0, 0));
|
||||
series1.Points.Add(new DataPoint(10, 18));
|
||||
series1.Points.Add(new DataPoint(20, 12));
|
||||
series1.Points.Add(new DataPoint(30, 8));
|
||||
series1.Points.Add(new DataPoint(40, 15));
|
||||
|
||||
var series2 = new LineSeries { Title = "Series 2", MarkerType = MarkerType.Square };
|
||||
series2.Points.Add(new DataPoint(0, 4));
|
||||
series2.Points.Add(new DataPoint(10, 12));
|
||||
series2.Points.Add(new DataPoint(20, 16));
|
||||
series2.Points.Add(new DataPoint(30, 25));
|
||||
series2.Points.Add(new DataPoint(40, 5));
|
||||
|
||||
// Add the series to the plot model
|
||||
tmp.Series.Add(series1);
|
||||
tmp.Series.Add(series2);
|
||||
|
||||
// Axes are created automatically if they are not defined
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot model.
|
||||
/// </summary>
|
||||
public PlotModel Model { get; private set; }
|
||||
public PlotModel Model1 { get; private set; }
|
||||
public PlotModel Model2 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot controller.
|
||||
/// </summary>
|
||||
public IPlotController Controller { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Window x:Class="ControllerDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
xmlns:local="clr-namespace:ControllerDemo"
|
||||
Title="OxyPlot Controller Demo" Height="480" Width="640">
|
||||
<Window.DataContext>
|
||||
<local:MainViewModel />
|
||||
</Window.DataContext>
|
||||
<TabControl>
|
||||
<TabItem Header="Custom controller">
|
||||
<!-- The OxyPlot control is binding to a PlotModel and a PlotController in the MainViewModel -->
|
||||
<oxy:PlotView Model="{Binding Model}"
|
||||
Controller="{Binding Controller}" />
|
||||
</TabItem>
|
||||
<TabItem Header="Default controllers">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<oxy:PlotView Model="{Binding Model1}" />
|
||||
<oxy:PlotView Grid.Column="1" x:Name="plotView2" Model="{Binding Model2}" />
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Window>
|
||||
@@ -0,0 +1,29 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ControllerDemo
|
||||
{
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Shows how to define a Controller.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindow" /> class.
|
||||
/// </summary>
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.plotView2.ActualController.UnbindAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Window x:Class="CoupledAxesDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
Title="CoupledAxesDemo" Height="480" Width="640">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<oxy:PlotView Model="{Binding Model1}"/>
|
||||
<oxy:PlotView Model="{Binding Model2}" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,73 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace CoupledAxesDemo
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Shows how to keep two axes in sync.")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this;
|
||||
|
||||
this.Model1 = new PlotModel { Title = "Model 1" };
|
||||
this.Model2 = new PlotModel { Title = "Model 2" };
|
||||
var axis1 = new LinearAxis { Position = AxisPosition.Bottom };
|
||||
var axis2 = new LinearAxis { Position = AxisPosition.Bottom };
|
||||
this.Model1.Axes.Add(axis1);
|
||||
this.Model2.Axes.Add(axis2);
|
||||
this.Model1.Series.Add(new FunctionSeries(Math.Sin, 0, 10, 1000));
|
||||
this.Model2.Series.Add(new FunctionSeries(x => Math.Sin(x) / x, 0, 10, 1000));
|
||||
|
||||
bool isInternalChange = false;
|
||||
axis1.AxisChanged += (s, e) =>
|
||||
{
|
||||
if (isInternalChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
isInternalChange = true;
|
||||
axis2.Zoom(axis1.ActualMinimum, axis1.ActualMaximum);
|
||||
this.Model2.InvalidatePlot(false);
|
||||
isInternalChange = false;
|
||||
};
|
||||
|
||||
axis2.AxisChanged += (s, e) =>
|
||||
{
|
||||
if (isInternalChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
isInternalChange = true;
|
||||
axis1.Zoom(axis2.ActualMinimum, axis2.ActualMaximum);
|
||||
this.Model1.InvalidatePlot(false);
|
||||
isInternalChange = false;
|
||||
};
|
||||
}
|
||||
|
||||
public PlotModel Model1 { get; set; }
|
||||
|
||||
public PlotModel Model2 { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="CsvDocument.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// A class for comma-separated value files
|
||||
// http://en.wikipedia.org/wiki/Comma-separated_values
|
||||
// Default is "USA/UK CSV" where the separator is ',' and decimal separator is '.'.
|
||||
// Todo: Support quoted values...
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace CsvDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// A class for comma-separated value files
|
||||
/// http://en.wikipedia.org/wiki/Comma-separated_values
|
||||
/// Default is "USA/UK CSV" where the separator is ',' and decimal separator is '.'.
|
||||
/// Todo: Support quoted values...
|
||||
/// </summary>
|
||||
public class CsvDocument
|
||||
{
|
||||
public string[] Headers { get; private set; }
|
||||
public Collection<string[]> Items { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified file name.
|
||||
/// </summary>
|
||||
/// <param name="fileName">Name of the file.</param>
|
||||
/// <param name="separator">The separator (auto-detect if not specified).</param>
|
||||
public void Load(string fileName, char separator = '\0')
|
||||
{
|
||||
using (var r = new StreamReader(fileName))
|
||||
{
|
||||
var header = r.ReadLine();
|
||||
|
||||
if (separator == '\0')
|
||||
{
|
||||
// Auto detect
|
||||
int commaCount = Count(header, ',');
|
||||
int semicolonCount = Count(header, ';');
|
||||
separator = commaCount > semicolonCount ? ',' : ';';
|
||||
}
|
||||
|
||||
Headers = header.Split(separator);
|
||||
Items = new Collection<string[]>();
|
||||
|
||||
while (!r.EndOfStream)
|
||||
{
|
||||
var line = r.ReadLine();
|
||||
if (line == null || line.StartsWith("%") || line.StartsWith("//"))
|
||||
continue;
|
||||
Items.Add(line.Split(separator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int Count(string s, char c)
|
||||
{
|
||||
return s.Count(ch => ch == c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
Year,Annual mean,5-year mean
|
||||
// GlobalLand+OceanSurfaceTemperatureAnomaly (Base:1951-1980)
|
||||
1882,-.22,-.24
|
||||
1883,-.24,-.25
|
||||
1884,-.30,-.26
|
||||
1885,-.30,-.29
|
||||
1886,-.25,-.29
|
||||
1887,-.35,-.26
|
||||
1888,-.26,-.28
|
||||
1889,-.15,-.28
|
||||
1890,-.37,-.28
|
||||
1891,-.28,-.29
|
||||
1892,-.32,-.32
|
||||
1893,-.32,-.30
|
||||
1894,-.33,-.28
|
||||
1895,-.27,-.24
|
||||
1896,-.17,-.23
|
||||
1897,-.13,-.20
|
||||
1898,-.25,-.16
|
||||
1899,-.17,-.16
|
||||
1900,-.10,-.19
|
||||
1901,-.16,-.20
|
||||
1902,-.27,-.23
|
||||
1903,-.31,-.26
|
||||
1904,-.34,-.27
|
||||
1905,-.25,-.30
|
||||
1906,-.20,-.30
|
||||
1907,-.39,-.30
|
||||
1908,-.34,-.32
|
||||
1909,-.35,-.35
|
||||
1910,-.33,-.34
|
||||
1911,-.34,-.34
|
||||
1912,-.34,-.29
|
||||
1913,-.31,-.25
|
||||
1914,-.15,-.24
|
||||
1915,-.09,-.25
|
||||
1916,-.30,-.25
|
||||
1917,-.40,-.26
|
||||
1918,-.32,-.28
|
||||
1919,-.20,-.25
|
||||
1920,-.19,-.22
|
||||
1921,-.13,-.19
|
||||
1922,-.24,-.20
|
||||
1923,-.21,-.19
|
||||
1924,-.21,-.17
|
||||
1925,-.16,-.14
|
||||
1926,-.01,-.13
|
||||
1927,-.13,-.13
|
||||
1928,-.11,-.11
|
||||
1929,-.25,-.11
|
||||
1930,-.07,-.10
|
||||
1931,-.01,-.11
|
||||
1932,-.06,-.07
|
||||
1933,-.17,-.08
|
||||
1934,-.05,-.08
|
||||
1935,-.10,-.06
|
||||
1936,-.03,.00
|
||||
1937,.08,.02
|
||||
1938,.12,.05
|
||||
1939,.03,.08
|
||||
1940,.05,.07
|
||||
1941,.11,.06
|
||||
1942,.04,.10
|
||||
1943,.10,.10
|
||||
1944,.20,.07
|
||||
1945,.07,.07
|
||||
1946,-.04,.04
|
||||
1947,.01,-.01
|
||||
1948,-.04,-.06
|
||||
1949,-.06,-.05
|
||||
1950,-.15,-.05
|
||||
1951,-.04,-.02
|
||||
1952,.03,-.03
|
||||
1953,.11,-.02
|
||||
1954,-.10,-.05
|
||||
1955,-.10,-.04
|
||||
1956,-.17,-.04
|
||||
1957,.08,-.01
|
||||
1958,.08,.01
|
||||
1959,.06,.06
|
||||
1960,-.01,.05
|
||||
1961,.08,.05
|
||||
1962,.04,.00
|
||||
1963,.08,-.02
|
||||
1964,-.21,-.05
|
||||
1965,-.11,-.06
|
||||
1966,-.03,-.08
|
||||
1967,.00,-.02
|
||||
1968,-.04,.01
|
||||
1969,.08,-.01
|
||||
1970,.03,-.01
|
||||
1971,-.10,.03
|
||||
1972,.00,.00
|
||||
1973,.14,-.02
|
||||
1974,-.08,-.03
|
||||
1975,-.05,.00
|
||||
1976,-.16,-.03
|
||||
1977,.13,.00
|
||||
1978,.02,.05
|
||||
1979,.09,.13
|
||||
1980,.18,.12
|
||||
1981,.26,.17
|
||||
1982,.05,.17
|
||||
1983,.26,.14
|
||||
1984,.09,.12
|
||||
1985,.05,.16
|
||||
1986,.13,.17
|
||||
1987,.27,.19
|
||||
1988,.31,.26
|
||||
1989,.20,.30
|
||||
1990,.38,.27
|
||||
1991,.35,.24
|
||||
1992,.12,.25
|
||||
1993,.14,.25
|
||||
1994,.24,.24
|
||||
1995,.38,.29
|
||||
1996,.30,.38
|
||||
1997,.40,.39
|
||||
1998,.57,.38
|
||||
1999,.33,.42
|
||||
2000,.33,.45
|
||||
2001,.48,.45
|
||||
2002,.56,.48
|
||||
2003,.55,.54
|
||||
2004,.48,.55
|
||||
2005,.62,.55
|
||||
2006,.55,.53
|
||||
2007,.57,*
|
||||
2008,.44,*
|
||||
//----------------------------------
|
||||
|
@@ -0,0 +1,366 @@
|
||||
DayOfYear,75 percentile,50 percentile,25 percentile
|
||||
1,49.193,21.127,8.777
|
||||
2,46.47,20.869,8.581
|
||||
3,45.977,20.094,8.5
|
||||
4,45.953,19.617,8.532
|
||||
5,46.357,19.744,8.606
|
||||
6,47.448,19.651,8.568
|
||||
7,48.23,19.299,8.571
|
||||
8,48.529,18.909,8.59
|
||||
9,49.567,18.897,8.675
|
||||
10,52.336,19.129,8.699
|
||||
11,53.17,19.522,8.77
|
||||
12,54.645,19.872,8.79
|
||||
13,54.698,19.9,8.795
|
||||
14,53.519,19.814,8.854
|
||||
15,52.733,19.796,8.948
|
||||
16,51.173,20.138,9.105
|
||||
17,49.453,20.507,9.255
|
||||
18,46.759,20.748,9.42
|
||||
19,44.397,20.544,9.577
|
||||
20,40.57,20.177,9.754
|
||||
21,38.575,19.801,9.898
|
||||
22,35.808,19.475,10.038
|
||||
23,33.824,19.217,10.072
|
||||
24,32.495,18.875,9.966
|
||||
25,30.669,18.179,9.761
|
||||
26,29.326,17.06,9.525
|
||||
27,28.345,16.105,9.297
|
||||
28,27.846,15.378,9.071
|
||||
29,27.584,14.954,8.794
|
||||
30,27.512,14.52,8.494
|
||||
31,27.603,14.066,8.213
|
||||
32,29.068,13.747,7.984
|
||||
33,31.829,13.44,7.79
|
||||
34,34.463,13.281,7.617
|
||||
35,36.26,13.312,7.527
|
||||
36,37.525,13.348,7.455
|
||||
37,38.225,13.407,7.388
|
||||
38,38.569,13.478,7.296
|
||||
39,38.889,13.404,7.217
|
||||
40,38.975,13.403,7.173
|
||||
41,38.962,13.346,7.145
|
||||
42,37.669,13.271,7.083
|
||||
43,35.134,13.215,7.117
|
||||
44,32.634,13.133,7.157
|
||||
45,30.845,12.963,7.127
|
||||
46,29.479,12.881,7.058
|
||||
47,28.51,12.787,6.921
|
||||
48,28.01,12.661,6.783
|
||||
49,27.669,12.587,6.66
|
||||
50,27.229,12.587,6.532
|
||||
51,26.696,12.653,6.462
|
||||
52,26.756,12.716,6.392
|
||||
53,26.679,12.759,6.215
|
||||
54,26.687,12.73,6.132
|
||||
55,26.785,12.653,6.105
|
||||
56,26.946,12.598,6.125
|
||||
57,27.291,12.532,6.222
|
||||
58,27.375,12.603,6.387
|
||||
59,27.273,12.637,6.556
|
||||
60,27.185,12.581,6.736
|
||||
61,27.019,12.507,6.888
|
||||
62,26.326,12.464,7.053
|
||||
63,26.17,12.48,7.264
|
||||
64,26.625,12.508,7.422
|
||||
65,26.749,12.763,7.647
|
||||
66,26.841,12.953,7.847
|
||||
67,26.897,13.162,8.032
|
||||
68,27.037,13.206,8.222
|
||||
69,27.434,13.282,8.367
|
||||
70,27.752,13.433,8.503
|
||||
71,28.006,13.554,8.624
|
||||
72,28.318,13.677,8.754
|
||||
73,28.576,13.694,8.83
|
||||
74,28.35,13.7,8.872
|
||||
75,28.842,13.465,8.82
|
||||
76,29.285,13.397,8.774
|
||||
77,30.394,13.268,8.7
|
||||
78,31.192,13.154,8.587
|
||||
79,31.438,13.147,8.507
|
||||
80,31.562,13.253,8.432
|
||||
81,31.714,13.564,8.391
|
||||
82,31.73,13.716,8.367
|
||||
83,32.106,13.959,8.363
|
||||
84,32.665,14.147,8.397
|
||||
85,32.852,14.415,8.48
|
||||
86,33.016,14.544,8.596
|
||||
87,33.056,14.714,8.68
|
||||
88,32.932,14.977,8.783
|
||||
89,33.223,15.212,8.894
|
||||
90,33.825,15.34,9.061
|
||||
91,34.711,15.254,9.252
|
||||
92,35.589,15.303,9.463
|
||||
93,35.39,15.437,9.654
|
||||
94,35,15.695,9.851
|
||||
95,34.656,16.038,10.04
|
||||
96,34.817,16.403,10.327
|
||||
97,35.036,16.831,10.658
|
||||
98,36,17.253,11.081
|
||||
99,36.718,17.827,11.445
|
||||
100,37.432,18.644,11.75
|
||||
101,37.946,19.718,12.112
|
||||
102,39.376,20.802,12.48
|
||||
103,41.372,21.973,13.181
|
||||
104,43.008,23.509,13.951
|
||||
105,45.043,24.792,14.736
|
||||
106,47.379,25.897,15.342
|
||||
107,49.299,27.08,15.958
|
||||
108,50.707,28.79,16.48
|
||||
109,52.318,30.232,17.184
|
||||
110,55.13,31.786,17.957
|
||||
111,58.003,32.804,18.739
|
||||
112,60.907,34.23,19.621
|
||||
113,64.674,36.111,20.225
|
||||
114,68.404,37.424,20.586
|
||||
115,71.771,39.136,20.964
|
||||
116,74.626,40.178,21.829
|
||||
117,77.831,41.552,22.809
|
||||
118,81.643,43.802,23.755
|
||||
119,86.104,47.505,24.691
|
||||
120,89.915,50.671,26.154
|
||||
121,94.757,54.61,27.913
|
||||
122,98.215,58.149,29.779
|
||||
123,101.479,61.48,33.217
|
||||
124,105.083,65.993,37.634
|
||||
125,107.978,70.787,42.251
|
||||
126,112.088,75.851,45.953
|
||||
127,119.428,80.009,49.321
|
||||
128,125.771,83.123,52.868
|
||||
129,130.095,85.603,56.467
|
||||
130,133.998,89.331,60.039
|
||||
131,139.083,92.704,64.18
|
||||
132,143.678,98.341,67.011
|
||||
133,147.795,102.776,68.344
|
||||
134,150.878,106.5,69.96
|
||||
135,156.997,109.751,72.063
|
||||
136,162.641,113.178,73.664
|
||||
137,165.596,117.007,75.62
|
||||
138,168.151,120.836,77.339
|
||||
139,172.718,123.137,80.121
|
||||
140,176.231,124.718,82.69
|
||||
141,178.121,126.692,84.56
|
||||
142,183.312,126.519,88.937
|
||||
143,186.238,128.312,92.33
|
||||
144,189.062,131.288,93.458
|
||||
145,191.432,132.109,94.485
|
||||
146,192.528,131.947,96.669
|
||||
147,192.066,132.277,98.263
|
||||
148,191.135,131.868,99.427
|
||||
149,191.284,133.477,99.427
|
||||
150,191.852,135.335,99.109
|
||||
151,192.484,135.73,98.676
|
||||
152,191.964,136.158,97.838
|
||||
153,194.231,136.666,98.531
|
||||
154,197.098,136.991,100.614
|
||||
155,197.889,139.87,102.729
|
||||
156,197.52,143.804,104.777
|
||||
157,199.251,146.414,105.825
|
||||
158,201.474,148.735,107.062
|
||||
159,202.064,149.693,107.607
|
||||
160,201.938,148.492,107.946
|
||||
161,201.635,147.894,107.678
|
||||
162,199.866,147.618,105.333
|
||||
163,194.997,145.941,102.291
|
||||
164,189.773,141.09,99.417
|
||||
165,184.611,135.605,95.759
|
||||
166,182.78,131.006,92.721
|
||||
167,180.056,127.459,90.276
|
||||
168,177.459,124.499,87.705
|
||||
169,174.869,121.753,85.265
|
||||
170,170.972,120.383,82.665
|
||||
171,166.876,118.078,80.992
|
||||
172,163.159,114.606,80.94
|
||||
173,162.172,111.47,81.102
|
||||
174,160.582,111.31,80.849
|
||||
175,160.642,110.768,80.513
|
||||
176,158.259,109.167,78.764
|
||||
177,154.502,107.728,77.52
|
||||
178,152.924,105.909,76.985
|
||||
179,150.08,103.11,76.471
|
||||
180,148.698,100.639,76.531
|
||||
181,146.599,99.12,76.444
|
||||
182,145.26,98.254,75.395
|
||||
183,142.886,98.438,74.134
|
||||
184,141.733,96.765,72.803
|
||||
185,139.368,95.237,71.534
|
||||
186,137.482,94.305,70.69
|
||||
187,136.83,93.008,69.986
|
||||
188,134.039,92.116,69.199
|
||||
189,132.275,92.343,68.788
|
||||
190,130.743,92.631,68.052
|
||||
191,129.116,93.225,66.872
|
||||
192,126.396,93.229,65.852
|
||||
193,124.305,91.615,63.955
|
||||
194,122.119,90.711,62.514
|
||||
195,118.93,89.67,61.3
|
||||
196,115.911,88.349,59.614
|
||||
197,112.139,86.481,58.36
|
||||
198,109.512,85.673,56.945
|
||||
199,107.619,83.724,55.44
|
||||
200,106.274,81.378,53.462
|
||||
201,105.839,78.855,52.425
|
||||
202,105.693,77.058,51.443
|
||||
203,105.068,76.135,50.985
|
||||
204,104.686,74.365,49.859
|
||||
205,103.936,73.04,48.714
|
||||
206,103.194,71.953,48.183
|
||||
207,102.506,71.705,47.528
|
||||
208,101.53,70.56,46.947
|
||||
209,100.51,70.316,46.683
|
||||
210,100.126,70.27,47.049
|
||||
211,99.129,70.111,46.563
|
||||
212,98.029,69.669,46.439
|
||||
213,97.43,68.759,45.898
|
||||
214,96.212,69.047,45.739
|
||||
215,96.354,68.999,45.31
|
||||
216,96.157,68.429,44.877
|
||||
217,95.723,66.994,44.454
|
||||
218,95.388,65.05,43.462
|
||||
219,94.61,62.902,42.337
|
||||
220,92.45,61.18,40.878
|
||||
221,90.313,59.959,39.366
|
||||
222,88.812,58.549,37.988
|
||||
223,88.358,57.512,37.065
|
||||
224,89.491,55.81,35.993
|
||||
225,89.089,54.649,34.961
|
||||
226,88.699,53.436,34.107
|
||||
227,89.218,52.222,33.158
|
||||
228,88.901,51.26,32.626
|
||||
229,88.013,51.19,31.977
|
||||
230,88.315,50.8,31.526
|
||||
231,87.98,49.519,31.062
|
||||
232,86.743,48.69,30.146
|
||||
233,84.979,47.237,29.417
|
||||
234,81.895,45.545,28.713
|
||||
235,79.447,44.75,28.017
|
||||
236,78.416,44.153,27.103
|
||||
237,77.39,44.515,26.522
|
||||
238.0416667,77.173,45.441,26.027
|
||||
239,76.503,45.582,25.314
|
||||
240,75.401,45.681,25.232
|
||||
241,76.363,46.124,25.173
|
||||
242,78.687,46.126,25.176
|
||||
243,80.048,47.234,25.611
|
||||
244,81.396,49.053,25.77
|
||||
245,84.578,49.62,26.318
|
||||
246,86.131,50.906,27.086
|
||||
247,89.214,52.457,27.197
|
||||
248,93.029,53.698,27.59
|
||||
249,97.28,54.171,28.505
|
||||
250,100.011,54.171,28.644
|
||||
251,101.553,54.203,28.599
|
||||
252,101.288,54.303,28.388
|
||||
253,102.147,53.832,27.68
|
||||
254,103.53,53.615,27.087
|
||||
255,105.64,53.832,26.14
|
||||
256,107.098,53.416,25.222
|
||||
257,109.116,51.939,24.709
|
||||
258,112.68,52.349,23.983
|
||||
259,115.509,53.601,23.092
|
||||
260,120.616,54.7,22.908
|
||||
261,123.169,58.081,23.099
|
||||
262,128.822,62.178,23.772
|
||||
263,132.976,64.461,24.575
|
||||
264,138.354,65.973,25.47
|
||||
265,140.369,68.088,25.885
|
||||
266,142.521,70.353,26.017
|
||||
267,138.586,71.895,26.294
|
||||
268,132.316,70.603,27.506
|
||||
269,129.669,68.695,28.423
|
||||
270,126.784,67.772,28.573
|
||||
271,125.359,64.869,28.186
|
||||
272,123.408,62.712,27.436
|
||||
273,121.061,61.421,26.559
|
||||
274,116.681,59.279,26.187
|
||||
275.0416667,115.366,58.607,26.636
|
||||
276,114.583,58.147,27.468
|
||||
277,117.407,58.63,28.187
|
||||
278,119.265,60.983,27.885
|
||||
279,119.124,63.361,27.801
|
||||
280,119.449,64.703,27.661
|
||||
281,118.991,66.86,28.093
|
||||
282,115.618,67.154,28.328
|
||||
283,112.482,67.123,28.517
|
||||
284,109.191,67.156,28.046
|
||||
285,104.218,65.69,27.233
|
||||
286,100.496,63.232,26.819
|
||||
287,96.72,60.236,26.154
|
||||
288,94.952,56.19,25.315
|
||||
289,91.762,53.531,24.307
|
||||
290,87.324,51.338,23.379
|
||||
291,85.99,48.048,22.143
|
||||
292,86.5,44.703,21.405
|
||||
293,86.704,42.61,21.244
|
||||
294,89.365,41.504,21.152
|
||||
295,91.439,39.632,21.193
|
||||
296,92.438,40.934,20.599
|
||||
297,94.275,43.341,20.127
|
||||
298,95.601,45.221,19.643
|
||||
299,96.71,45.933,19.41
|
||||
300.0416667,98.883,46.438,19.234
|
||||
301,101.442,47.49,19.227
|
||||
302,103.494,48.641,19.067
|
||||
303,104.085,49.45,18.856
|
||||
304,104.609,50.671,18.704
|
||||
305,106.297,52.571,18.678
|
||||
306,107.735,51.398,18.681
|
||||
307,105.827,48.694,18.605
|
||||
308,102.559,46.163,18.753
|
||||
309,99.539,44.092,18.861
|
||||
310,97.159,42.238,19.26
|
||||
311,93.706,40.227,19.461
|
||||
312,89.754,38.83,19.53
|
||||
313,87.614,37.25,19.247
|
||||
314,83.186,35.468,19.139
|
||||
315,78.874,33.057,18.641
|
||||
316,74.862,31.157,17.985
|
||||
317,71.934,29.892,17.319
|
||||
318,69.052,28.989,16.574
|
||||
319,66.94,27.857,15.757
|
||||
320,63.718,26.878,14.879
|
||||
321,59.431,25.661,14.236
|
||||
322,56.662,24.598,13.812
|
||||
323,56.402,24.211,13.487
|
||||
324,57.857,24.291,13.084
|
||||
325,59.647,23.748,13.043
|
||||
326,60.291,24.014,13.094
|
||||
327,61.47,25.002,13.222
|
||||
328,64.589,25.813,13.399
|
||||
329,67.277,26.711,13.553
|
||||
330,69.793,27.37,13.564
|
||||
331,71.701,27.857,13.498
|
||||
332,71.751,28.393,13.592
|
||||
333,70.524,28.961,13.611
|
||||
334,69.164,28.674,13.624
|
||||
335,65.541,28.633,13.366
|
||||
336,63.893,27.814,13.114
|
||||
337,65.048,26.589,12.993
|
||||
338,64.092,25.736,12.732
|
||||
339,62.418,25.328,12.624
|
||||
340,61.277,25.924,12.596
|
||||
341,60.331,26.29,12.484
|
||||
342,59.47,26.487,12.309
|
||||
343,58.32,25.883,12.148
|
||||
344,57.138,25.887,12.078
|
||||
345,58.127,25.927,12.057
|
||||
346,58.14,25.97,11.958
|
||||
347,55.474,26.256,11.713
|
||||
348,53.294,26.207,11.629
|
||||
349,52.155,25.583,11.406
|
||||
350,50.378,24.222,11.315
|
||||
351,49.456,23.445,11.208
|
||||
352,48.808,22.573,10.804
|
||||
353,48.646,22.211,10.471
|
||||
354,47.987,21.408,10.104
|
||||
355,47.638,21.036,9.783
|
||||
356,49.308,20.74,9.597
|
||||
357,50.824,20.305,9.586
|
||||
358,51.266,20.68,9.507
|
||||
359,52.067,21.064,9.445
|
||||
360,52.68,21.267,9.243
|
||||
361,53.962,21.318,9.173
|
||||
362,54.629,21.618,9.125
|
||||
363,55.772,21.603,9.016
|
||||
364,55.282,21.691,8.869
|
||||
365,53.222,21.437,8.807
|
||||
|
@@ -0,0 +1,31 @@
|
||||
Year,Population
|
||||
-10000,1.000
|
||||
-9000,3.000
|
||||
-8000,5.000
|
||||
-7000,7.000
|
||||
-6000,10.000
|
||||
-5000,15.000
|
||||
-4000,20.000
|
||||
-3000,25.000
|
||||
-2000,35.000
|
||||
-1000,50.000
|
||||
-500,100.000
|
||||
1,200.000
|
||||
1000,310.000
|
||||
1750,791.000
|
||||
1800,978.000
|
||||
1850,1262.000
|
||||
1900,1650.000
|
||||
1950,2518.629
|
||||
1955,2755.823
|
||||
1960,2981.659
|
||||
1965,3334.874
|
||||
1970,3692.492
|
||||
1975,4068.109
|
||||
1980,4434.682
|
||||
1985,4830.979
|
||||
1990,5263.593
|
||||
1995,5674.380
|
||||
2000,6070.581
|
||||
2005,6453.628
|
||||
2008,6706.993
|
||||
|
@@ -0,0 +1,89 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace CsvDemo
|
||||
{
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
using OxyPlot.Legends;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
public class MainViewModel : Observable
|
||||
{
|
||||
private PlotModel model;
|
||||
|
||||
public PlotModel Model
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.model;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (this.model != value)
|
||||
{
|
||||
this.SetValue(ref this.model, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Open(string file)
|
||||
{
|
||||
var doc = new CsvDocument();
|
||||
doc.Load(file);
|
||||
var tmp = new PlotModel
|
||||
{
|
||||
Title = Path.GetFileNameWithoutExtension(file),
|
||||
PlotMargins = new OxyThickness(50, 0, 0, 40)
|
||||
};
|
||||
|
||||
var l = new Legend
|
||||
{
|
||||
LegendPosition = LegendPosition.RightTop,
|
||||
LegendPlacement = LegendPlacement.Outside
|
||||
};
|
||||
|
||||
tmp.Legends.Add(l);
|
||||
|
||||
for (int i = 1; i < doc.Headers.Length; i++)
|
||||
{
|
||||
var ls = new LineSeries { Title = doc.Headers[i] };
|
||||
foreach (var item in doc.Items)
|
||||
{
|
||||
double x = this.ParseDouble(item[0]);
|
||||
double y = this.ParseDouble(item[i]);
|
||||
ls.Points.Add(new DataPoint(x, y));
|
||||
}
|
||||
|
||||
tmp.Series.Add(ls);
|
||||
}
|
||||
|
||||
tmp.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = doc.Headers[0] });
|
||||
this.Model = tmp;
|
||||
}
|
||||
|
||||
private double ParseDouble(string s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return double.NaN;
|
||||
}
|
||||
s = s.Replace(',', '.');
|
||||
double result;
|
||||
if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return double.NaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<Window x:Class="CsvDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
Title="CsvDemo" Height="480" Width="640"
|
||||
AllowDrop="True" Drop="Window_Drop">
|
||||
<DockPanel>
|
||||
<Menu DockPanel.Dock="Top">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Open csv..." Click="OpenCsv_Click"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Save plot..." Click="SavePlot_Click"/>
|
||||
<!--<MenuItem Header="Save report..." Click="SaveReport_Click"/>-->
|
||||
<Separator/>
|
||||
<MenuItem Header="Exit" Click="Exit_Click"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Edit">
|
||||
<MenuItem Header="Copy svg" Click="CopySvg_Click"/>
|
||||
<MenuItem Header="Copy bitmap" Click="CopyBitmap_Click"/>
|
||||
<MenuItem Header="Copy xaml" Click="CopyXaml_Click"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Help">
|
||||
<MenuItem Header="Website" Click="HelpWeb_Click"/>
|
||||
<MenuItem Header="About" Click="HelpAbout_Click"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Grid>
|
||||
<oxy:PlotView
|
||||
x:Name="plot1"
|
||||
Model="{Binding Model}"
|
||||
Background="White"/>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,149 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace CsvDemo
|
||||
{
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Wpf;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Plotting data from CSV files.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
private readonly MainViewModel vm = new MainViewModel();
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this.vm;
|
||||
// vm.Open("Examples\CsvDemo\Data\GlobalTemperatureAnomaly.csv");
|
||||
// vm.Open("Examples\CsvDemo\Data\WorldPopulation.csv");
|
||||
this.vm.Open(@"Examples\CsvDemo\Data\RiverFlow.csv");
|
||||
}
|
||||
|
||||
private void Window_Drop(object sender, DragEventArgs e)
|
||||
{
|
||||
var data = e.Data as DataObject;
|
||||
if (data != null && data.ContainsFileDropList())
|
||||
{
|
||||
foreach (var file in data.GetFileDropList())
|
||||
{
|
||||
this.vm.Open(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Exit_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void OpenCsv_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new OpenFileDialog();
|
||||
dlg.Filter = ".csv files|*.csv";
|
||||
dlg.DefaultExt = ".csv";
|
||||
if (dlg.ShowDialog(this).Value)
|
||||
{
|
||||
this.vm.Open(dlg.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
private void SavePlot_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new SaveFileDialog
|
||||
{
|
||||
Filter = ".svg files|*.svg|.png files|*.png|.pdf files|*.pdf|.xaml files|*.xaml",
|
||||
DefaultExt = ".svg"
|
||||
};
|
||||
if (dlg.ShowDialog(this).Value)
|
||||
{
|
||||
var ext = Path.GetExtension(dlg.FileName).ToLower();
|
||||
switch (ext)
|
||||
{
|
||||
case ".png":
|
||||
plot1.SaveBitmap(dlg.FileName, 0, 0);
|
||||
break;
|
||||
case ".svg":
|
||||
var rc = new CanvasRenderContext(new Canvas());
|
||||
var svg = OxyPlot.SvgExporter.ExportToString(this.vm.Model, plot1.ActualWidth, plot1.ActualHeight, false, rc);
|
||||
File.WriteAllText(dlg.FileName, svg);
|
||||
break;
|
||||
case ".pdf":
|
||||
using (var s = File.Create(dlg.FileName))
|
||||
{
|
||||
PdfExporter.Export(vm.Model, s, plot1.ActualWidth, plot1.ActualHeight);
|
||||
}
|
||||
|
||||
break;
|
||||
case ".xaml":
|
||||
plot1.SaveXaml(dlg.FileName);
|
||||
break;
|
||||
}
|
||||
|
||||
this.OpenContainingFolder(dlg.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenContainingFolder(string fileName)
|
||||
{
|
||||
// var folder = Path.GetDirectoryName(fileName);
|
||||
var psi = new ProcessStartInfo("Explorer.exe", "/select," + fileName);
|
||||
Process.Start(psi);
|
||||
}
|
||||
|
||||
//private void SaveReport_Click(object sender, RoutedEventArgs e)
|
||||
//{
|
||||
// var dlg = new SaveFileDialog { Filter = ".html files|*.html", DefaultExt = ".html" };
|
||||
// if (dlg.ShowDialog(this).Value)
|
||||
// {
|
||||
// this.vm.SaveReport(dlg.FileName);
|
||||
// this.OpenContainingFolder(dlg.FileName);
|
||||
// }
|
||||
//}
|
||||
|
||||
private void CopySvg_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var rc = new CanvasRenderContext(null);
|
||||
var svg = OxyPlot.SvgExporter.ExportToString(this.vm.Model, plot1.ActualWidth, plot1.ActualHeight, true, rc);
|
||||
Clipboard.SetText(svg);
|
||||
}
|
||||
|
||||
private void CopyBitmap_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clipboard.SetImage(plot1.ToBitmap());
|
||||
}
|
||||
|
||||
private void CopyXaml_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clipboard.SetText(plot1.ToXaml());
|
||||
}
|
||||
|
||||
private void HelpAbout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show("by OxyPlot");
|
||||
}
|
||||
|
||||
private void HelpWeb_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Process.Start("http://oxyplot.org");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<Window x:Class="CustomTrackerDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" xmlns:oxyshared="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf.Shared"
|
||||
Title="CustomTrackerDemo" Height="480" Width="640">
|
||||
<Window.Resources>
|
||||
<oxyshared:OxyColorConverter x:Key="OxyColorConverter" />
|
||||
</Window.Resources>
|
||||
<TabControl Margin="4">
|
||||
<TabItem Header="Custom background brush">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" LineExtents="{Binding PlotModel.PlotArea}">
|
||||
<oxyshared:TrackerControl.Background>
|
||||
<LinearGradientBrush EndPoint="0,1">
|
||||
<GradientStop Color="#f0e0e0ff" />
|
||||
<GradientStop Offset="1" Color="#f0ffffff" />
|
||||
</LinearGradientBrush>
|
||||
</oxyshared:TrackerControl.Background>
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<TextBlock Text="{Binding}" Margin="7" />
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="Border by series color">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" LineExtents="{Binding PlotModel.PlotArea}" BorderBrush="{Binding Series.ActualColor, Converter={StaticResource OxyColorConverter}}" BorderThickness="3">
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<TextBlock Text="{Binding}" Margin="7" />
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="No tracker">
|
||||
<oxy:PlotView Model="{Binding Model}" DefaultTrackerTemplate="{x:Null}" />
|
||||
</TabItem>
|
||||
<TabItem Header="Rounded box">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" ShowPointer="False" CornerRadius="8" BorderEdgeMode="Unspecified" LineExtents="{Binding PlotModel.PlotArea}">
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<TextBlock Text="{Binding}" Margin="7" />
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="No vertical line">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" VerticalLineVisibility="Collapsed" LineExtents="{Binding PlotModel.PlotArea}">
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<TextBlock Text="{Binding}" Margin="7" />
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="Border">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<Canvas>
|
||||
<Border CornerRadius="0 6 6 6" BorderBrush="Black" BorderThickness="1" Background="White" Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}" Padding="5" Margin="0">
|
||||
<TextBlock Text="{Binding}" />
|
||||
</Border>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="TextBlock">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<Canvas>
|
||||
<TextBlock Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}" Padding="5" Margin="10" Background="#a0ffffff" Text="{Binding}" />
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="Circle">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<Canvas>
|
||||
<Grid Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}">
|
||||
<Ellipse Fill="Black" Width="12" Height="12" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<Ellipse.RenderTransform>
|
||||
<TranslateTransform X="-6" Y="-6" />
|
||||
</Ellipse.RenderTransform>
|
||||
</Ellipse>
|
||||
<TextBlock Text="{Binding DataPoint.Y, StringFormat='{}{0:0.00}'}" Margin="6 6 0 0" />
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="UniformPanel">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" LineExtents="{Binding PlotModel.PlotArea}">
|
||||
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<UniformGrid Columns="2" Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}" Margin="6">
|
||||
<TextBlock Text="X:" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding DataPoint.X, StringFormat='{}{0:0.000}'}" />
|
||||
<TextBlock Text="Y:" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding DataPoint.Y, StringFormat='{}{0:0.000}'}" />
|
||||
<TextBlock Text="Dataset:" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding Series.Title}" />
|
||||
</UniformGrid>
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="Different trackers">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.TrackerDefinitions>
|
||||
<oxyshared:TrackerDefinition TrackerKey="Tracker1">
|
||||
<oxyshared:TrackerDefinition.TrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<Canvas>
|
||||
<TextBlock Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}" Padding="5" Margin="10" Background="LightBlue" Text="{Binding}" />
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</oxyshared:TrackerDefinition.TrackerTemplate>
|
||||
</oxyshared:TrackerDefinition>
|
||||
<oxyshared:TrackerDefinition TrackerKey="Tracker2">
|
||||
<oxyshared:TrackerDefinition.TrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<Canvas>
|
||||
<TextBlock Canvas.Left="{Binding Position.X}" Canvas.Top="{Binding Position.Y}" Padding="5" Margin="10" Background="LightGreen" Text="{Binding}" />
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</oxyshared:TrackerDefinition.TrackerTemplate>
|
||||
</oxyshared:TrackerDefinition>
|
||||
</oxy:PlotView.TrackerDefinitions>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
<TabItem Header="Bind to Item">
|
||||
<oxy:PlotView Model="{Binding Model}">
|
||||
<oxy:PlotView.DefaultTrackerTemplate>
|
||||
<ControlTemplate>
|
||||
<oxyshared:TrackerControl Position="{Binding Position}" LineExtents="{Binding LineExtents}">
|
||||
<oxyshared:TrackerControl.Content>
|
||||
<!-- We can bind to the items from the ItemsSource -->
|
||||
<TextBlock Text="{Binding Item, StringFormat='Item={0}'}" Margin="8"/>
|
||||
</oxyshared:TrackerControl.Content>
|
||||
</oxyshared:TrackerControl>
|
||||
</ControlTemplate>
|
||||
</oxy:PlotView.DefaultTrackerTemplate>
|
||||
</oxy:PlotView>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Window>
|
||||
@@ -0,0 +1,43 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace CustomTrackerDemo
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Demonstrates a custom tracker.")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = this;
|
||||
}
|
||||
|
||||
public PlotModel Model
|
||||
{
|
||||
get
|
||||
{
|
||||
var model = new PlotModel();
|
||||
model.Series.Add(new LineSeries { Title = "Series 1", TrackerKey = "Tracker1", ItemsSource = new List<DataPoint> { new DataPoint(0, 0), new DataPoint(10, 20), new DataPoint(20, 18) } });
|
||||
model.Series.Add(new LineSeries { Title = "Series 2", TrackerKey = "Tracker2", ItemsSource = new List<DataPoint> { new DataPoint(0, 10), new DataPoint(10, 10), new DataPoint(20, 16) } });
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Window x:Class="DataTemplateDemo.PlotViewDataTemplateWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
Title="PlotView in DataTemplate"
|
||||
Height="480"
|
||||
Width="640">
|
||||
|
||||
<TabControl ItemsSource="{Binding Models}">
|
||||
<TabControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding PlotModel.Title}"/>
|
||||
</DataTemplate>
|
||||
</TabControl.ItemTemplate>
|
||||
<TabControl.ContentTemplate>
|
||||
<DataTemplate>
|
||||
<oxy:PlotView Model="{Binding PlotModel}" Controller="{Binding PlotController}" />
|
||||
</DataTemplate>
|
||||
</TabControl.ContentTemplate>
|
||||
</TabControl>
|
||||
</Window>
|
||||
@@ -0,0 +1,68 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="PlotViewDataTemplateWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for PlotViewDataTemplateWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace DataTemplateDemo
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for PlotViewDataTemplateWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Demonstrates a PlotView in a DataTemplate.")]
|
||||
public partial class PlotViewDataTemplateWindow : Window
|
||||
{
|
||||
public PlotViewDataTemplateWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Models = CreateModels().ToArray();
|
||||
this.DataContext = this;
|
||||
}
|
||||
|
||||
public IList<Model> Models { get; private set; }
|
||||
|
||||
private static Random r = new Random(13);
|
||||
|
||||
private static IEnumerable<Model> CreateModels()
|
||||
{
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var pm = new PlotModel { Title = string.Format("Plot {0}", i + 1) };
|
||||
|
||||
var series = new LineSeries();
|
||||
for (var j = 0; j < 10; j++)
|
||||
{
|
||||
series.Points.Add(new DataPoint(j, r.NextDouble()));
|
||||
}
|
||||
|
||||
pm.Series.Add(series);
|
||||
|
||||
var pc = new PlotController();
|
||||
pc.UnbindAll();
|
||||
pc.BindKeyDown(OxyKey.Left, PlotCommands.PanRight);
|
||||
pc.BindKeyDown(OxyKey.Right, PlotCommands.PanLeft);
|
||||
|
||||
yield return new Model { PlotModel = pm, PlotController = pc };
|
||||
}
|
||||
}
|
||||
|
||||
public class Model
|
||||
{
|
||||
public PlotModel PlotModel { get; set; }
|
||||
public IPlotController PlotController { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Window x:Class="HistogramDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
Title="HistogramDemo" Height="480" Width="640">
|
||||
<DockPanel Margin="10">
|
||||
<StackPanel DockPanel.Dock="Bottom" Width="300">
|
||||
<TextBlock Name="instructions" Text="Use the mouse to 'drag' a line across the image below ..." FontSize="10" Foreground="#333333" Margin="5" TextWrapping="Wrap"/>
|
||||
<Grid Name="grid" MouseLeftButtonUp="Grid_MouseLeftButtonUp" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
|
||||
<Image Width="300" Height="200" x:Name="image" Source="/Examples/HistogramDemo/hare.jpg"/>
|
||||
<Line Stroke="Black" StrokeThickness="3" x:Name="line"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<Grid>
|
||||
<oxy:PlotView x:Name="chart"/>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,148 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace HistogramDemo
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Plots a histogram of RGB components.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
private readonly LineSeries blueLine;
|
||||
private readonly LineSeries greenLine;
|
||||
private readonly LineSeries redLine;
|
||||
|
||||
private bool leftButtonDown;
|
||||
private int[] pixelData;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
this.LoadPixelData();
|
||||
|
||||
var throttledEvent = new ThrottledMouseMoveEvent(image);
|
||||
throttledEvent.ThrottledMouseMove += this.ThrottledEvent_ThrottledMouseMove;
|
||||
var pm = new PlotModel { Title = "RGB histogram" };
|
||||
this.redLine = new LineSeries { Color = OxyColors.Red };
|
||||
this.greenLine = new LineSeries { Color = OxyColors.Green };
|
||||
this.blueLine = new LineSeries { Color = OxyColors.Blue };
|
||||
this.redLine.InterpolationAlgorithm = InterpolationAlgorithms.CanonicalSpline;
|
||||
this.greenLine.InterpolationAlgorithm = InterpolationAlgorithms.CanonicalSpline;
|
||||
this.blueLine.InterpolationAlgorithm = InterpolationAlgorithms.CanonicalSpline;
|
||||
pm.Series.Add(this.redLine);
|
||||
pm.Series.Add(this.greenLine);
|
||||
pm.Series.Add(this.blueLine);
|
||||
pm.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Minimum = 0, Maximum = 1, MajorStep = 0.2, MinorStep = 0.05, Title = "Frequency" });
|
||||
pm.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = 0, Maximum = 100, Title = "Lightness" });
|
||||
chart.Model = pm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the image data once it is loaded
|
||||
/// </summary>
|
||||
private void LoadPixelData()
|
||||
{
|
||||
var bitmapImage = new BitmapImage(new Uri("pack://application:,,,/Examples/HistogramDemo/hare.jpg"));
|
||||
|
||||
int stride = ((bitmapImage.PixelWidth * bitmapImage.Format.BitsPerPixel) + 7) / 8;
|
||||
var pixelByteArray = new byte[bitmapImage.PixelHeight * stride];
|
||||
bitmapImage.CopyPixels(pixelByteArray, stride, 0);
|
||||
this.pixelData = new int[pixelByteArray.Length / 4];
|
||||
Buffer.BlockCopy(pixelByteArray, 0, this.pixelData, 0, pixelByteArray.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles mouse move to draw the line and intensity histograms
|
||||
/// </summary>
|
||||
private void ThrottledEvent_ThrottledMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!this.leftButtonDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
line.X2 = e.GetPosition(grid).X;
|
||||
line.Y2 = e.GetPosition(grid).Y;
|
||||
|
||||
// compute distance between the points
|
||||
double distance = Math.Sqrt((line.X1 - line.X2) * (line.X1 - line.X2) + (line.Y1 - line.Y2) * (line.Y1 - line.Y2));
|
||||
|
||||
this.redLine.Points.Clear();
|
||||
this.greenLine.Points.Clear();
|
||||
this.blueLine.Points.Clear();
|
||||
|
||||
int b = 16;
|
||||
var histoR = new int[256 / b];
|
||||
var histoG = new int[256 / b];
|
||||
var histoB = new int[256 / b];
|
||||
|
||||
// build the charts
|
||||
int n = 0;
|
||||
for (double pt = 0; pt < distance; pt++)
|
||||
{
|
||||
double xPos = line.X1 + (line.X2 - line.X1) * pt / distance;
|
||||
double yPos = line.Y1 + (line.Y2 - line.Y1) * pt / distance;
|
||||
|
||||
var xIndex = (int)xPos;
|
||||
var yIndex = (int)yPos;
|
||||
|
||||
int pixel = this.pixelData[xIndex + (yIndex * 300)];
|
||||
|
||||
// the RGB values are 'packed' into an int, here we unpack them
|
||||
var blue = (byte)(pixel & 0xFF);
|
||||
pixel >>= 8;
|
||||
var green = (byte)(pixel & 0xFF);
|
||||
pixel >>= 8;
|
||||
var red = (byte)(pixel & 0xFF);
|
||||
|
||||
histoR[red / b]++;
|
||||
histoG[green / b]++;
|
||||
histoB[blue / b]++;
|
||||
n++;
|
||||
}
|
||||
|
||||
double xScale = 100.0 / histoR.Length;
|
||||
for (int i = 0; i < histoR.Length; i++)
|
||||
{
|
||||
double x = i * xScale;
|
||||
this.redLine.Points.Add(new DataPoint(x, (double)histoR[i] / n));
|
||||
this.greenLine.Points.Add(new DataPoint(x, (double)histoG[i] / n));
|
||||
this.blueLine.Points.Add(new DataPoint(x, (double)histoB[i] / n));
|
||||
}
|
||||
|
||||
chart.InvalidatePlot();
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
instructions.Visibility = Visibility.Collapsed;
|
||||
this.leftButtonDown = true;
|
||||
line.X1 = line.X2 = e.GetPosition(grid).X;
|
||||
line.Y1 = line.Y2 = e.GetPosition(grid).Y;
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.leftButtonDown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ThrottledMouseEvent.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Creates a 'throttled' MouseMove event which ensures that the UI
|
||||
// rendering is not starved.
|
||||
// see: http://www.scottlogic.co.uk/blog/colin/2010/06/throttling-silverlight-mouse-events-to-keep-the-ui-responsive/
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace HistogramDemo
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a 'throttled' MouseMove event which ensures that the UI
|
||||
/// rendering is not starved.
|
||||
/// see: http://www.scottlogic.co.uk/blog/colin/2010/06/throttling-silverlight-mouse-events-to-keep-the-ui-responsive/
|
||||
/// </summary>
|
||||
public class ThrottledMouseMoveEvent
|
||||
{
|
||||
private bool awaitingRender;
|
||||
|
||||
private readonly UIElement element;
|
||||
|
||||
public ThrottledMouseMoveEvent(UIElement element)
|
||||
{
|
||||
this.element = element;
|
||||
element.MouseMove += this.ElementMouseMove;
|
||||
}
|
||||
|
||||
public event MouseEventHandler ThrottledMouseMove;
|
||||
|
||||
private void ElementMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!this.awaitingRender)
|
||||
{
|
||||
// if we are not awaiting a render as a result of a previously handled event
|
||||
// raise a ThrottledMouseMove event, and add a Rendering handler so that
|
||||
// we can determine when this event has been acted upon.
|
||||
this.OnThrottledMouseMove(e);
|
||||
this.awaitingRender = true;
|
||||
CompositionTarget.Rendering += this.CompositionTargetRendering;
|
||||
}
|
||||
}
|
||||
|
||||
private void CompositionTargetRendering(object sender, EventArgs e)
|
||||
{
|
||||
this.awaitingRender = false;
|
||||
CompositionTarget.Rendering -= this.CompositionTargetRendering;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the ThrottledMouseMove event
|
||||
/// </summary>
|
||||
protected void OnThrottledMouseMove(MouseEventArgs args)
|
||||
{
|
||||
if (this.ThrottledMouseMove != null)
|
||||
{
|
||||
this.ThrottledMouseMove(this.element, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Source/Examples/WPF/WpfExamples/Examples/HistogramDemo/hare.jpg
Normal file
BIN
Source/Examples/WPF/WpfExamples/Examples/HistogramDemo/hare.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@@ -0,0 +1,33 @@
|
||||
<Window x:Class="InterpolationDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
Title="PerformanceDemo" Height="480" Width="640">
|
||||
|
||||
<ItemsControl ItemsSource="{Binding PlotModels}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
|
||||
<ItemsControl.Template>
|
||||
<ControlTemplate>
|
||||
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
|
||||
Padding="{TemplateBinding Control.Padding}"
|
||||
BorderBrush="{TemplateBinding Border.BorderBrush}"
|
||||
Background="{TemplateBinding Panel.Background}"
|
||||
SnapsToDevicePixels="True">
|
||||
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
|
||||
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</ItemsControl.Template>
|
||||
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel IsVirtualizing="True" IsItemsHost="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<oxy:PlotView Model="{Binding}" Height="200" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Window>
|
||||
@@ -0,0 +1,125 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace InterpolationDemo
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
using WpfExamples;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Shows different types of interpolation including a custom one.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
private readonly Random r = new Random(13);
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
List<DataPoint> points = this.GeneratePoints(50);
|
||||
|
||||
this.PlotModels = new List<PlotModel>
|
||||
{
|
||||
this.GenerateRandomPlotModel(points, "None", null),
|
||||
this.GenerateRandomPlotModel(points, "Canonical aka Cardinal",
|
||||
new Entry("0.5 (default)", InterpolationAlgorithms.CanonicalSpline),
|
||||
new Entry("0.1", new CanonicalSpline(0.1)),
|
||||
new Entry("1.0", new CanonicalSpline(1.0))),
|
||||
this.GenerateRandomPlotModel(points, "Catmull–Rom",
|
||||
new Entry("Standard", InterpolationAlgorithms.CatmullRomSpline),
|
||||
new Entry("Uniform", InterpolationAlgorithms.UniformCatmullRomSpline),
|
||||
new Entry("Chordal", InterpolationAlgorithms.ChordalCatmullRomSpline))
|
||||
};
|
||||
|
||||
this.DataContext = this;
|
||||
}
|
||||
|
||||
private class Entry
|
||||
{
|
||||
public Entry(string title, IInterpolationAlgorithm algorithm)
|
||||
{
|
||||
this.Title = title;
|
||||
this.Algorithm = algorithm;
|
||||
}
|
||||
|
||||
public string Title { get; }
|
||||
|
||||
public IInterpolationAlgorithm Algorithm { get; }
|
||||
}
|
||||
|
||||
private List<DataPoint> GeneratePoints(int numberOfPoints)
|
||||
{
|
||||
var result = new List<DataPoint>(numberOfPoints);
|
||||
for (int i = 0; i < numberOfPoints; i++)
|
||||
{
|
||||
if (i < 5)
|
||||
{
|
||||
result.Add(new DataPoint(i, 0.0));
|
||||
}
|
||||
else if (i < 10)
|
||||
{
|
||||
result.Add(new DataPoint(i, 1.0));
|
||||
}
|
||||
else if (i < 12)
|
||||
{
|
||||
result.Add(new DataPoint(i, 0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new DataPoint(i, this.r.NextDouble()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<PlotModel> PlotModels { get; set; }
|
||||
|
||||
private PlotModel GenerateRandomPlotModel(List<DataPoint> points, string title, params Entry[] entries)
|
||||
{
|
||||
var plotModel = new PlotModel
|
||||
{
|
||||
Title = title,
|
||||
TitleToolTip = title
|
||||
};
|
||||
|
||||
if (entries == null)
|
||||
{
|
||||
var lineSeries = new LineSeries();
|
||||
lineSeries.Points.AddRange(points);
|
||||
plotModel.Series.Add(lineSeries);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
foreach (var entry in entries.Reverse())
|
||||
{
|
||||
var lineSeries = new LineSeries
|
||||
{
|
||||
Title = entry.Title,
|
||||
InterpolationAlgorithm = entry.Algorithm,
|
||||
StrokeThickness = 1.0
|
||||
};
|
||||
lineSeries.Points.AddRange(points);
|
||||
plotModel.Series.Add(lineSeries);
|
||||
}
|
||||
}
|
||||
|
||||
return plotModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainViewModel.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace LegendsDemo
|
||||
{
|
||||
using System;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
using OxyPlot.Legends;
|
||||
|
||||
using PropertyTools.DataAnnotations;
|
||||
using WpfExamples;
|
||||
|
||||
using HorizontalAlignment = OxyPlot.HorizontalAlignment;
|
||||
|
||||
public class MainViewModel : Observable
|
||||
{
|
||||
private HorizontalAlignment legendItemAlignment = HorizontalAlignment.Left;
|
||||
private LegendItemOrder legendItemOrder;
|
||||
private LegendOrientation legendOrientation;
|
||||
private LegendPlacement legendPlacement;
|
||||
private LegendPosition legendPosition;
|
||||
private LegendSymbolPlacement legendSymbolPlacement;
|
||||
private PlotModel model;
|
||||
private int numberOfSeries = 20;
|
||||
private double maxHeight = double.NaN;
|
||||
private double maxWidth = double.NaN;
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
|
||||
[DisplayName("Position"), Category("Legend properties")]
|
||||
public LegendPosition LegendPosition
|
||||
{
|
||||
get { return this.legendPosition; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendPosition, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("Placement")]
|
||||
public LegendPlacement LegendPlacement
|
||||
{
|
||||
get { return this.legendPlacement; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendPlacement, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("Orientation")]
|
||||
public LegendOrientation LegendOrientation
|
||||
{
|
||||
get { return this.legendOrientation; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendOrientation, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("ItemOrder")]
|
||||
public LegendItemOrder LegendItemOrder
|
||||
{
|
||||
get { return this.legendItemOrder; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendItemOrder, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("ItemAlignment")]
|
||||
public HorizontalAlignment LegendItemAlignment
|
||||
{
|
||||
get { return this.legendItemAlignment; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendItemAlignment, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("SymbolPlacement")]
|
||||
public LegendSymbolPlacement LegendSymbolPlacement
|
||||
{
|
||||
get { return this.legendSymbolPlacement; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.legendSymbolPlacement, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("MaxWidth"), Optional]
|
||||
public double LegendMaxWidth
|
||||
{
|
||||
get { return this.maxWidth; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.maxWidth, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("MaxHeight"), Optional]
|
||||
public double LegendMaxHeight
|
||||
{
|
||||
get { return this.maxHeight; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.maxHeight, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("Curves"), Slidable(1, 32)]
|
||||
public int NumberOfSeries
|
||||
{
|
||||
get { return this.numberOfSeries; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.numberOfSeries, value);
|
||||
this.PropertiesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public PlotModel Model
|
||||
{
|
||||
get { return this.model; }
|
||||
set
|
||||
{
|
||||
this.SetValue(ref this.model, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void PropertiesChanged()
|
||||
{
|
||||
this.Model = this.CreateModel(this.NumberOfSeries);
|
||||
}
|
||||
|
||||
private PlotModel CreateModel(int n)
|
||||
{
|
||||
var newModel = new PlotModel
|
||||
{
|
||||
Title = "LineSeries"
|
||||
};
|
||||
|
||||
var l = new Legend
|
||||
{
|
||||
LegendBorder = OxyColors.Black,
|
||||
LegendBackground = OxyColor.FromAColor(200, OxyColors.White),
|
||||
LegendPosition = this.LegendPosition,
|
||||
LegendPlacement = this.LegendPlacement,
|
||||
LegendOrientation = this.LegendOrientation,
|
||||
LegendItemOrder = this.LegendItemOrder,
|
||||
LegendItemAlignment = this.LegendItemAlignment,
|
||||
LegendSymbolPlacement = this.LegendSymbolPlacement,
|
||||
LegendMaxWidth = this.LegendMaxWidth,
|
||||
LegendMaxHeight = this.LegendMaxHeight
|
||||
};
|
||||
|
||||
newModel.Legends.Add(l);
|
||||
|
||||
for (int i = 1; i <= n; i++)
|
||||
{
|
||||
var s = new LineSeries { Title = "Series " + i };
|
||||
newModel.Series.Add(s);
|
||||
for (double x = 0; x < 2 * Math.PI; x += 0.1)
|
||||
s.Points.Add(new DataPoint(x, Math.Sin(x * i) / i + i));
|
||||
}
|
||||
return newModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Window x:Class="LegendsDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" xmlns:pt="clr-namespace:PropertyTools.Wpf;assembly=PropertyTools.Wpf"
|
||||
Title="LegendsDemo" Height="720" Width="1280">
|
||||
<DockPanel>
|
||||
<pt:PropertyGrid SelectedObject="{Binding}" DockPanel.Dock="Left" Width="300" TabVisibility="Collapsed" Margin="8"/>
|
||||
<Grid>
|
||||
<oxy:PlotView Model="{Binding Model}" Background="White"/>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,29 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace LegendsDemo
|
||||
{
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example("Demonstrates legend box capabilities.")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MainWindow"/> class.
|
||||
/// </summary>
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContext = new MainViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<Window x:Class="MathBlockDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf"
|
||||
Title="MathBlock demo" Height="480" Width="720">
|
||||
<Window.Resources>
|
||||
<Style TargetType="{x:Type oxy:MathBlock}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type oxy:MathBlock}">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Canvas x:Name="PART_Canvas"></Canvas>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<GroupBox Header="MathBlock" Margin="8" Padding="8">
|
||||
<StackPanel>
|
||||
<oxy:MathBlock FontSize="40" Foreground="DarkRed" Background="Lavender" FontStyle="Italic" FontWeight="ExtraBold" HorizontalAlignment="Left" Padding="40 0 0 0" ToolTip="HorizontalAlignment=Left">E=mc^{2}</oxy:MathBlock>
|
||||
<oxy:MathBlock FontSize="64" FontFamily="Times New Roman" Background="LemonChiffon" HorizontalAlignment="Right" ToolTip="HorizontalAlignment=Right">x^{2}_{i}</oxy:MathBlock>
|
||||
<oxy:MathBlock FontSize="36" FontWeight="Bold" Background="LightGreen" HorizontalAlignment="Center" ToolTip="HorizontalAlignment=Center">H_{2}O</oxy:MathBlock>
|
||||
<oxy:MathBlock FontSize="12" Background="CornflowerBlue" ToolTip="Default HorizontalAlignment (Stretch)">ABC</oxy:MathBlock>
|
||||
<oxy:MathBlock HorizontalContentAlignment="Center" Background="LightYellow" ToolTip="HorizontalContentAlignment=Center, HorizontalAlignment=Stretch">x_{0}^{2n}</oxy:MathBlock>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<TextBlock Text="The contents of MathBlock and TextBlock should be aligned: "/>
|
||||
<oxy:MathBlock Content="x^{2}_{i}"/>
|
||||
<TextBlock Text=", "/>
|
||||
<oxy:MathBlock Content="H_{2}O"/>
|
||||
<TextBlock Text=", "/>
|
||||
<oxy:MathBlock Content="5^{th}"/>
|
||||
<TextBlock Text="."/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</Window>
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace MathBlockDemo
|
||||
{
|
||||
using WpfExamples;
|
||||
|
||||
[Example(null, "MathBlock control")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MathBlock.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Provides a control for displaying simple math.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OxyPlot.Wpf
|
||||
{
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a control for displaying simple math.
|
||||
/// </summary>
|
||||
[TemplatePart(Name = PartCanvas, Type = typeof(Canvas))]
|
||||
public class MathBlock : ContentControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The canvas template part.
|
||||
/// </summary>
|
||||
private const string PartCanvas = "PART_Canvas";
|
||||
|
||||
/// <summary>
|
||||
/// The canvas
|
||||
/// </summary>
|
||||
private Canvas canvas;
|
||||
|
||||
/// <summary>
|
||||
/// The render context
|
||||
/// </summary>
|
||||
private IRenderContext renderContext;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes static members of the <see cref="MathBlock" /> class.
|
||||
/// </summary>
|
||||
static MathBlock()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(
|
||||
typeof(MathBlock),
|
||||
new FrameworkPropertyMetadata(typeof(MathBlock)));
|
||||
ContentProperty.OverrideMetadata(
|
||||
typeof(MathBlock),
|
||||
new FrameworkPropertyMetadata(typeof(MathBlock), (s, e) => ((MathBlock)s).ContentChanged()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles changes in the Content property.
|
||||
/// </summary>
|
||||
private void ContentChanged()
|
||||
{
|
||||
this.UpdateContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to measure a control.
|
||||
/// </summary>
|
||||
/// <param name="constraint">The maximum size that the method can return.</param>
|
||||
/// <returns>The size of the control, up to the maximum specified by <paramref name="constraint" />.</returns>
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
if (this.Content == null)
|
||||
{
|
||||
return base.MeasureOverride(constraint);
|
||||
}
|
||||
|
||||
var text = this.Content.ToString();
|
||||
|
||||
double fontWeight = this.FontWeight.ToOpenTypeWeight();
|
||||
string fontFamily = null;
|
||||
if (this.FontFamily != null)
|
||||
{
|
||||
fontFamily = this.FontFamily.Source;
|
||||
}
|
||||
|
||||
var size = this.renderContext.MeasureMathText(text, fontFamily, this.FontSize, fontWeight);
|
||||
return new Size(size.Width + this.Padding.Left + this.Padding.Right, size.Height + this.Padding.Top + this.Padding.Bottom);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate" />.
|
||||
/// </summary>
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
this.canvas = this.GetTemplateChild(PartCanvas) as Canvas;
|
||||
this.renderContext = new CanvasRenderContext(this.canvas);
|
||||
this.SizeChanged += this.HandleSizeChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles changes in control size.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="SizeChangedEventArgs" /> instance containing the event data.</param>
|
||||
private void HandleSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
this.UpdateContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the content.
|
||||
/// </summary>
|
||||
private void UpdateContent()
|
||||
{
|
||||
if (this.canvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.canvas.Children.Clear();
|
||||
if (this.Content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var text = this.Content.ToString();
|
||||
var horizontalAlignment = this.HorizontalContentAlignment.ToHorizontalAlignment();
|
||||
var verticalAlignment = this.VerticalContentAlignment.ToVerticalAlignment();
|
||||
double fontWeight = this.FontWeight.ToOpenTypeWeight();
|
||||
double x = this.Padding.Left;
|
||||
switch (horizontalAlignment)
|
||||
{
|
||||
case OxyPlot.HorizontalAlignment.Right:
|
||||
x = this.ActualWidth - this.Padding.Right;
|
||||
break;
|
||||
case OxyPlot.HorizontalAlignment.Center:
|
||||
x = this.Padding.Left + ((this.ActualWidth - this.Padding.Left - this.Padding.Right) * 0.5);
|
||||
break;
|
||||
}
|
||||
|
||||
double y = this.Padding.Top;
|
||||
switch (verticalAlignment)
|
||||
{
|
||||
case OxyPlot.VerticalAlignment.Bottom:
|
||||
y = this.ActualHeight - this.Padding.Bottom;
|
||||
break;
|
||||
case OxyPlot.VerticalAlignment.Middle:
|
||||
y = this.Padding.Top + ((this.ActualWidth - this.Padding.Bottom - this.Padding.Top) * 0.5);
|
||||
break;
|
||||
}
|
||||
|
||||
var p = new ScreenPoint(x, y);
|
||||
string fontFamily = null;
|
||||
if (this.FontFamily != null)
|
||||
{
|
||||
fontFamily = this.FontFamily.Source;
|
||||
}
|
||||
|
||||
this.renderContext.DrawMathText(
|
||||
p,
|
||||
text,
|
||||
this.Foreground.ToOxyColor(),
|
||||
fontFamily,
|
||||
this.FontSize,
|
||||
fontWeight,
|
||||
0,
|
||||
horizontalAlignment,
|
||||
verticalAlignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Window x:Class="MemoryTest.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MemoryTest="clr-namespace:MemoryTest"
|
||||
Title="MemoryTest" Height="350" Width="240">
|
||||
<Window.Resources>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Margin" Value="8"/>
|
||||
<EventSetter Event="Click" Handler="OpenWindow_Click"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<StackPanel>
|
||||
<Button Content="Test 1" Tag="{x:Type MemoryTest:Window1}"/>
|
||||
<Button Content="Test 2" Tag="{x:Type MemoryTest:Window2}"/>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,36 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="MainWindow.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for MainWindow.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace MemoryTest
|
||||
{
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using WpfExamples;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[Example(null, "Memory test")]
|
||||
public partial class MainWindow
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void OpenWindow_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var type = ((Button)sender).Tag as Type;
|
||||
var win = Activator.CreateInstance(type) as Window;
|
||||
win.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<Window x:Class="MemoryTest.Window1"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" Title="Window1" Height="300" Width="300">
|
||||
<Grid>
|
||||
<oxy:PlotView Model="{Binding Model}"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,43 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="Window1.xaml.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Interaction logic for Window1.xaml
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace MemoryTest
|
||||
{
|
||||
using OxyPlot;
|
||||
using OxyPlot.Series;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for Window1.xaml
|
||||
/// </summary>
|
||||
public partial class Window1 : Window
|
||||
{
|
||||
public PlotModel Model { get; set; }
|
||||
|
||||
public Window1()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
Model = new PlotModel { Title = "Test 1" };
|
||||
Model.Series.Add(new FunctionSeries(Math.Cos, 0, 10, 0.01));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Window x:Class="MemoryTest.Window2"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" Title="Window2" Height="480" Width="640">
|
||||
<Grid>
|
||||
<ScrollViewer>
|
||||
<ItemsControl ItemsSource="{Binding Plots}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<oxy:PlotView Model="{Binding}" Height="300"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Window>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user