├── .gitignore
├── LICENSE
├── Preview
├── gradient.png
├── multi.PNG
├── schema.png
├── single.png
└── stack.png
├── README.md
├── RealTimeGraphX.UWP.Demo
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ └── Wide310x150Logo.scale-200.png
├── Converters
│ ├── DataPointToStringConverter.cs
│ └── TimeSpanToStringConverter.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── MainPageVM.cs
├── NamedBrush.cs
├── NamedColor.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── RealTimeGraphX.UWP.Demo.csproj
├── Themes
│ └── Generic.xaml
└── UwpGraphControl.cs
├── RealTimeGraphX.UWP
├── ExtensionMethods.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── RealTimeGraphX.UWP.rd.xml
├── RealTimeGraphX.UWP.csproj
├── RealTimeGraphX.UWP.nuspec
├── Themes
│ └── Generic.xaml
├── UwpBindingElement.cs
├── UwpDataTriggerAction.cs
├── UwpDataTriggerElement.cs
├── UwpGraphAxisControl.cs
├── UwpGraphAxisPanel.cs
├── UwpGraphAxisTickData.cs
├── UwpGraphComponentBase.cs
├── UwpGraphController.cs
├── UwpGraphDataSeries.cs
├── UwpGraphGridLines.cs
├── UwpGraphSurface.cs
└── icon.png
├── RealTimeGraphX.WPF.Demo
├── App.config
├── App.xaml
├── App.xaml.cs
├── Converters
│ └── ObjectEqualityConverter.cs
├── ListGraphItemVM.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MainWindowVM.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RealTimeGraphX.WPF.Demo.csproj
├── Themes
│ └── Generic.xaml
└── WpfGraphControl.cs
├── RealTimeGraphX.WPF
├── ExtensionMethods.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RealTimeGraphX.WPF.csproj
├── RealTimeGraphX.WPF.nuspec
├── Themes
│ └── Generic.xaml
├── WpfGraphAxisControl.cs
├── WpfGraphAxisPanel.cs
├── WpfGraphAxisTickData.cs
├── WpfGraphComponentBase.cs
├── WpfGraphController.cs
├── WpfGraphDataSeries.cs
├── WpfGraphGridLines.cs
├── WpfGraphSurface.cs
└── icon.png
├── RealTimeGraphX.sln
├── RealTimeGraphX
├── DataPoints
│ ├── DateTimeDataPoint.cs
│ ├── DoubleDataPoint.cs
│ ├── FloatDataPoint.cs
│ ├── Int32DataPoint.cs
│ └── TimeSpanDataPoint.cs
├── EventArguments
│ └── RangeChangedEventArgs.cs
├── GraphCommand.cs
├── GraphController.cs
├── GraphDataPoint.cs
├── GraphDataPointHelper.cs
├── GraphDataPointTypeConverter.cs
├── GraphDataQueue.cs
├── GraphObject.cs
├── GraphRange.cs
├── GraphRangeAutoYFallBackMode.cs
├── GraphRenderer.cs
├── GraphTransform.cs
├── IGraphComponent.cs
├── IGraphController.cs
├── IGraphDataPoint.cs
├── IGraphDataSeries.cs
├── IGraphRenderer.cs
├── IGraphSurface.cs
├── RealTimeGraphX.csproj
└── Renderers
│ └── ScrollingLineRenderer.cs
└── visuals
└── icon.png
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *.log
81 | *.vspscc
82 | *.vssscc
83 | .builds
84 | *.pidb
85 | *.svclog
86 | *.scc
87 |
88 | # Chutzpah Test files
89 | _Chutzpah*
90 |
91 | # Visual C++ cache files
92 | ipch/
93 | *.aps
94 | *.ncb
95 | *.opendb
96 | *.opensdf
97 | *.sdf
98 | *.cachefile
99 | *.VC.db
100 | *.VC.VC.opendb
101 |
102 | # Visual Studio profiler
103 | *.psess
104 | *.vsp
105 | *.vspx
106 | *.sap
107 |
108 | # Visual Studio Trace Files
109 | *.e2e
110 |
111 | # TFS 2012 Local Workspace
112 | $tf/
113 |
114 | # Guidance Automation Toolkit
115 | *.gpState
116 |
117 | # ReSharper is a .NET coding add-in
118 | _ReSharper*/
119 | *.[Rr]e[Ss]harper
120 | *.DotSettings.user
121 |
122 | # JustCode is a .NET coding add-in
123 | .JustCode
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # The packages folder can be ignored because of Package Restore
183 | **/[Pp]ackages/*
184 | # except build/, which is used as an MSBuild target.
185 | !**/[Pp]ackages/build/
186 | # Uncomment if necessary however generally it will be regenerated when needed
187 | #!**/[Pp]ackages/repositories.config
188 | # NuGet v3's project.json files produces more ignorable files
189 | *.nuget.props
190 | *.nuget.targets
191 |
192 | # Microsoft Azure Build Output
193 | csx/
194 | *.build.csdef
195 |
196 | # Microsoft Azure Emulator
197 | ecf/
198 | rcf/
199 |
200 | # Windows Store app package directories and files
201 | AppPackages/
202 | BundleArtifacts/
203 | Package.StoreAssociation.xml
204 | _pkginfo.txt
205 | *.appx
206 |
207 | # Visual Studio cache files
208 | # files ending in .cache can be ignored
209 | *.[Cc]ache
210 | # but keep track of directories ending in .cache
211 | !*.[Cc]ache/
212 |
213 | # Others
214 | ClientBin/
215 | ~$*
216 | *~
217 | *.dbmdl
218 | *.dbproj.schemaview
219 | *.jfm
220 | *.pfx
221 | *.publishsettings
222 | orleans.codegen.cs
223 |
224 | # Including strong name files can present a security risk
225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
226 | #*.snk
227 |
228 | # Since there are multiple workflows, uncomment next line to ignore bower_components
229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
230 | #bower_components/
231 |
232 | # RIA/Silverlight projects
233 | Generated_Code/
234 |
235 | # Backup & report files from converting an old project file
236 | # to a newer Visual Studio version. Backup files are not needed,
237 | # because we have git ;-)
238 | _UpgradeReport_Files/
239 | Backup*/
240 | UpgradeLog*.XML
241 | UpgradeLog*.htm
242 | ServiceFabricBackup/
243 | *.rptproj.bak
244 |
245 | # SQL Server files
246 | *.mdf
247 | *.ldf
248 | *.ndf
249 |
250 | # Business Intelligence projects
251 | *.rdl.data
252 | *.bim.layout
253 | *.bim_*.settings
254 | *.rptproj.rsuser
255 |
256 | # Microsoft Fakes
257 | FakesAssemblies/
258 |
259 | # GhostDoc plugin setting file
260 | *.GhostDoc.xml
261 |
262 | # Node.js Tools for Visual Studio
263 | .ntvs_analysis.dat
264 | node_modules/
265 |
266 | # Visual Studio 6 build log
267 | *.plg
268 |
269 | # Visual Studio 6 workspace options file
270 | *.opt
271 |
272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
273 | *.vbw
274 |
275 | # Visual Studio LightSwitch build output
276 | **/*.HTMLClient/GeneratedArtifacts
277 | **/*.DesktopClient/GeneratedArtifacts
278 | **/*.DesktopClient/ModelManifest.xml
279 | **/*.Server/GeneratedArtifacts
280 | **/*.Server/ModelManifest.xml
281 | _Pvt_Extensions
282 |
283 | # Paket dependency manager
284 | .paket/paket.exe
285 | paket-files/
286 |
287 | # FAKE - F# Make
288 | .fake/
289 |
290 | # JetBrains Rider
291 | .idea/
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/**
303 | # !tools/packages.config
304 |
305 | # Tabs Studio
306 | *.tss
307 |
308 | # Telerik's JustMock configuration file
309 | *.jmconfig
310 |
311 | # BizTalk build output
312 | *.btp.cs
313 | *.btm.cs
314 | *.odx.cs
315 | *.xsd.cs
316 |
317 | # OpenCover UI analysis results
318 | OpenCover/
319 |
320 | # Azure Stream Analytics local run output
321 | ASALocalRun/
322 |
323 | # MSBuild Binary and Structured Log
324 | *.binlog
325 |
326 | # NVidia Nsight GPU debugger configuration file
327 | *.nvuser
328 |
329 | # MFractors (Xamarin productivity tool) working folder
330 | .mfractor/
331 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Roy Ben Shabat
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Preview/gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/Preview/gradient.png
--------------------------------------------------------------------------------
/Preview/multi.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/Preview/multi.PNG
--------------------------------------------------------------------------------
/Preview/schema.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/Preview/schema.png
--------------------------------------------------------------------------------
/Preview/single.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/Preview/single.png
--------------------------------------------------------------------------------
/Preview/stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/Preview/stack.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RealTimeGraphX
2 |
3 | [](https://sirilix.visualstudio.com/RealTimeGraphX/_build/latest?definitionId=5&branchName=master)  [](https://www.nuget.org/packages/RealTimeGraphX/) [](https://www.nuget.org/packages/RealTimeGraphX.WPF/)
4 |
5 | RealTimeGraphX is a data type agnostic, high performance plotting library for WPF and UWP.
6 |
7 | The library core components are built using .Net Standard which makes it portable to a range of platforms.
8 |
9 | Typical use case is, scientific measurements applications which requires real-time display with large data volumes.
10 |
11 | RealTimeGraphX has a number of built-in data point types (axis) like Double, Float, Int32 ,TimeSpan and DateTime, but you can easily implement any kind of custom data type by inheriting and implementing the mathematical logic for that type.
12 |
13 | ### Features:
14 | - **High performance**
15 | - **Thread safe**
16 | - **MVVM support**
17 | - **Any type of data point**
18 | - **Zooming and panning**
19 |
20 |
21 |
22 |
23 |
24 | The solution contains demo projects for WPF and UWP.
25 |
26 | **Single Series**
27 |
28 | 
29 |
30 | **Multi Series**
31 |
32 | 
33 |
34 | **Gradient Fill**
35 |
36 | 
37 |
38 |
39 |
40 |
41 |
42 | The follwing diagrams demonstrates the connections between graph components and how they are implemented on each platform.
43 |
44 | **Model**
45 |
46 | 
47 |
48 | The graph controller binds to a renderer and a surface. Data points are pushed to the controller, the controller uses the renderer in orderer to prepare and arrange the points for visual display. Finally, the controller directs the renderer to draw the points on the specific surface.
49 |
50 |
51 | **WPF Stack Implementation**
52 |
53 | 
54 |
55 | Each platform (WPF/UWP etc.) should implement it's own *IGraphDataSeries* and *IGraphSurface*.
56 |
57 |
58 |
59 |
60 |
61 | Example
62 |
63 | ##### Model.cs
64 |
65 | ```csharp
66 |
67 | public class ViewModel
68 | {
69 | //Graph controller with timespan as X axis and double as Y.
70 | public WpfGraphController Controller { get; set; }
71 |
72 | public ViewModel()
73 | {
74 | Controller = new WpfGraphController();
75 | Controller.Renderer = new ScrollingLineRenderer();
76 | Controller.DataSeriesCollection.Add(new WpfGraphDataSeries()
77 | {
78 | Name = "Series Name",
79 | Stroke = Colors.Red,
80 | });
81 |
82 | //We will attach the surface using WPF binding...
83 | //Controller.Surface = null;
84 | }
85 |
86 | private void Start()
87 | {
88 | Stopwatch watch = new Stopwatch();
89 | watch.Start();
90 |
91 | Thread thread = new Thread(() =>
92 | {
93 | while (true)
94 | {
95 | //Get the current elapsed time and mouse position.
96 | var y = System.Windows.Forms.Cursor.Position.Y;
97 | var x = watch.Elapsed;
98 |
99 | //Push the x,y to the controller.
100 | Controller.PushData(x, y);
101 |
102 | Thread.Sleep(30);
103 | }
104 | });
105 | thread.Start();
106 | }
107 | }
108 |
109 | ```
110 |
111 | ##### View.xaml
112 |
113 | ```xaml
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | ```
135 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.ViewManagement;
11 | using Windows.UI.Xaml;
12 | using Windows.UI.Xaml.Controls;
13 | using Windows.UI.Xaml.Controls.Primitives;
14 | using Windows.UI.Xaml.Data;
15 | using Windows.UI.Xaml.Input;
16 | using Windows.UI.Xaml.Media;
17 | using Windows.UI.Xaml.Navigation;
18 |
19 | namespace RealTimeGraphX.UWP.Demo
20 | {
21 | ///
22 | /// Provides application-specific behavior to supplement the default Application class.
23 | ///
24 | sealed partial class App : Application
25 | {
26 | ///
27 | /// Initializes the singleton application object. This is the first line of authored code
28 | /// executed, and as such is the logical equivalent of main() or WinMain().
29 | ///
30 | public App()
31 | {
32 | this.InitializeComponent();
33 |
34 | ApplicationView.PreferredLaunchViewSize = new Size(1168, 577);
35 | ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
36 |
37 | this.Suspending += OnSuspending;
38 | }
39 |
40 | ///
41 | /// Invoked when the application is launched normally by the end user. Other entry points
42 | /// will be used such as when the application is launched to open a specific file.
43 | ///
44 | /// Details about the launch request and process.
45 | protected override void OnLaunched(LaunchActivatedEventArgs e)
46 | {
47 | Frame rootFrame = Window.Current.Content as Frame;
48 |
49 | // Do not repeat app initialization when the Window already has content,
50 | // just ensure that the window is active
51 | if (rootFrame == null)
52 | {
53 | // Create a Frame to act as the navigation context and navigate to the first page
54 | rootFrame = new Frame();
55 |
56 | rootFrame.NavigationFailed += OnNavigationFailed;
57 |
58 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
59 | {
60 | //TODO: Load state from previously suspended application
61 | }
62 |
63 | // Place the frame in the current Window
64 | Window.Current.Content = rootFrame;
65 | }
66 |
67 | if (e.PrelaunchActivated == false)
68 | {
69 | if (rootFrame.Content == null)
70 | {
71 | // When the navigation stack isn't restored navigate to the first page,
72 | // configuring the new page by passing required information as a navigation
73 | // parameter
74 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
75 | }
76 | // Ensure the current window is active
77 | Window.Current.Activate();
78 | }
79 | }
80 |
81 | ///
82 | /// Invoked when Navigation to a certain page fails
83 | ///
84 | /// The Frame which failed navigation
85 | /// Details about the navigation failure
86 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
87 | {
88 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
89 | }
90 |
91 | ///
92 | /// Invoked when application execution is being suspended. Application state is saved
93 | /// without knowing whether the application will be terminated or resumed with the contents
94 | /// of memory still intact.
95 | ///
96 | /// The source of the suspend request.
97 | /// Details about the suspend request.
98 | private void OnSuspending(object sender, SuspendingEventArgs e)
99 | {
100 | var deferral = e.SuspendingOperation.GetDeferral();
101 | //TODO: Save application state and stop any background activity
102 | deferral.Complete();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP.Demo/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Converters/DataPointToStringConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Data;
9 |
10 | namespace RealTimeGraphX.UWP.Demo.Converters
11 | {
12 | public class DataPointToStringConverter : DependencyObject, IValueConverter
13 | {
14 | public object Convert(object value, Type targetType, object parameter, string language)
15 | {
16 | return value.ToString();
17 | }
18 |
19 | public object ConvertBack(object value, Type targetType, object parameter, string language)
20 | {
21 | var asm = Assembly.Load("RealTimeGraphX");
22 | var type = asm.GetType("RealTimeGraphX.DataPoints." + parameter.ToString());
23 | var instance = Activator.CreateInstance(type) as IGraphDataPoint;
24 | return instance.Parse(value.ToString());
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Converters/TimeSpanToStringConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml.Data;
7 |
8 | namespace RealTimeGraphX.UWP.Demo.Converters
9 | {
10 | public class TimeSpanToStringConverter : IValueConverter
11 | {
12 | public object Convert(object value, Type targetType, object parameter, string language)
13 | {
14 | return value.ToString();
15 | }
16 |
17 | public object ConvertBack(object value, Type targetType, object parameter, string language)
18 | {
19 | return TimeSpan.Parse(value.ToString());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graphics.Canvas;
2 | using Microsoft.Graphics.Canvas.Brushes;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Runtime.InteropServices.WindowsRuntime;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using Windows.Foundation;
12 | using Windows.Foundation.Collections;
13 | using Windows.UI;
14 | using Windows.UI.ViewManagement;
15 | using Windows.UI.Xaml;
16 | using Windows.UI.Xaml.Controls;
17 | using Windows.UI.Xaml.Controls.Primitives;
18 | using Windows.UI.Xaml.Data;
19 | using Windows.UI.Xaml.Input;
20 | using Windows.UI.Xaml.Media;
21 | using Windows.UI.Xaml.Navigation;
22 |
23 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
24 |
25 | namespace RealTimeGraphX.UWP.Demo
26 | {
27 | ///
28 | /// An empty page that can be used on its own or navigated to within a Frame.
29 | ///
30 | public sealed partial class MainPage : Page
31 | {
32 | public MainPage()
33 | {
34 |
35 |
36 | this.InitializeComponent();
37 |
38 | DataContext = new MainPageVM();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/MainPageVM.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.DataPoints;
2 | using RealTimeGraphX.Renderers;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Windows.ApplicationModel.Core;
11 | using Windows.UI;
12 | using Windows.UI.Xaml.Media;
13 |
14 | namespace RealTimeGraphX.UWP.Demo
15 | {
16 | public class MainPageVM : GraphObject
17 | {
18 | public UwpGraphController Controller { get; set; }
19 |
20 | public UwpGraphController MultiController { get; set; }
21 |
22 | public MainPageVM()
23 | {
24 | Controller = new UwpGraphController();
25 | Controller.Range.MinimumY = 0;
26 | Controller.Range.MaximumY = 1080;
27 | Controller.Range.MaximumX = TimeSpan.FromSeconds(10);
28 | Controller.Range.AutoY = true;
29 |
30 | Controller.DataSeriesCollection.Add(new UwpGraphDataSeries()
31 | {
32 | Name = "Series",
33 | Stroke = Colors.DodgerBlue,
34 | });
35 |
36 | MultiController = new UwpGraphController();
37 | MultiController.Range.MinimumY = 0;
38 | MultiController.Range.MaximumY = 1080;
39 | MultiController.Range.MaximumX = TimeSpan.FromSeconds(10);
40 | MultiController.Range.AutoY = true;
41 |
42 | MultiController.DataSeriesCollection.Add(new UwpGraphDataSeries()
43 | {
44 | Name = "Series 1",
45 | Stroke = Colors.Red,
46 | });
47 |
48 | MultiController.DataSeriesCollection.Add(new UwpGraphDataSeries()
49 | {
50 | Name = "Series 2",
51 | Stroke = Colors.Green,
52 | });
53 |
54 | MultiController.DataSeriesCollection.Add(new UwpGraphDataSeries()
55 | {
56 | Name = "Series 3",
57 | Stroke = Colors.Blue,
58 | });
59 |
60 | MultiController.DataSeriesCollection.Add(new UwpGraphDataSeries()
61 | {
62 | Name = "Series 4",
63 | Stroke = Colors.Yellow,
64 | });
65 |
66 | MultiController.DataSeriesCollection.Add(new UwpGraphDataSeries()
67 | {
68 | Name = "Series 5",
69 | Stroke = Colors.Gray,
70 | });
71 |
72 | Stopwatch watch = new Stopwatch();
73 | watch.Start();
74 |
75 | Task.Factory.StartNew(async () =>
76 | {
77 | while (true)
78 | {
79 | double y = 0;
80 |
81 | await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
82 | {
83 | y = Windows.UI.Core.CoreWindow.GetForCurrentThread().PointerPosition.Y;
84 | });
85 |
86 | List yy = new List()
87 | {
88 | y,
89 | y + 20,
90 | y + 40,
91 | y + 60,
92 | y + 80,
93 | };
94 |
95 | var x = watch.Elapsed;
96 |
97 | List xx = new List()
98 | {
99 | x,
100 | x,
101 | x,
102 | x,
103 | x
104 | };
105 |
106 | Controller.PushData(x, y);
107 | MultiController.PushData(xx, yy);
108 |
109 | Thread.Sleep(30);
110 | }
111 | });
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/NamedBrush.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Media;
8 |
9 | namespace RealTimeGraphX.UWP.Demo
10 | {
11 | public class NamedBrush : DependencyObject
12 | {
13 | public Brush Brush
14 | {
15 | get { return (Brush)GetValue(BrushProperty); }
16 | set { SetValue(BrushProperty, value); }
17 | }
18 | public static readonly DependencyProperty BrushProperty =
19 | DependencyProperty.Register("Brush", typeof(Brush), typeof(NamedBrush), new PropertyMetadata(null));
20 |
21 | public String Name
22 | {
23 | get
24 | {
25 | if (Brush is SolidColorBrush)
26 | {
27 | return (Brush as SolidColorBrush).Color.ToString();
28 | }
29 | else
30 | {
31 | return "Gradient";
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/NamedColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI;
7 | using Windows.UI.Xaml;
8 |
9 | namespace RealTimeGraphX.UWP.Demo
10 | {
11 | public class NamedColor : DependencyObject
12 | {
13 | public Color Color
14 | {
15 | get { return (Color)GetValue(ColorProperty); }
16 | set { SetValue(ColorProperty, value); }
17 | }
18 | public static readonly DependencyProperty ColorProperty =
19 | DependencyProperty.Register("Color", typeof(Color), typeof(NamedColor), new PropertyMetadata(null));
20 |
21 | public String Name
22 | {
23 | get { return Color.ToString(); }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | RealTimeGraphX.UWP.Demo
7 | Roy
8 | Assets\StoreLogo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RealTimeGraphX.UWP.Demo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RealTimeGraphX.UWP.Demo")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
53 |
54 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP.Demo/UwpGraphControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices.WindowsRuntime;
5 | using Windows.UI.Xaml;
6 | using Windows.UI.Xaml.Controls;
7 | using Windows.UI.Xaml.Data;
8 | using Windows.UI.Xaml.Documents;
9 | using Windows.UI.Xaml.Input;
10 | using Windows.UI.Xaml.Media;
11 |
12 | namespace RealTimeGraphX.UWP.Demo
13 | {
14 | public sealed class UwpGraphControl : Control
15 | {
16 | ///
17 | /// Gets or sets the graph controller.
18 | ///
19 | public IGraphController Controller
20 | {
21 | get { return (IGraphController)GetValue(ControllerProperty); }
22 | set { SetValue(ControllerProperty, value); }
23 | }
24 | public static readonly DependencyProperty ControllerProperty =
25 | DependencyProperty.Register("Controller", typeof(IGraphController), typeof(UwpGraphControl), new PropertyMetadata(null));
26 |
27 | ///
28 | /// Gets or sets a value indicating whether to display a tool tip with the current cursor value.
29 | ///
30 | public bool DisplayToolTip
31 | {
32 | get { return (bool)GetValue(DisplayToolTipProperty); }
33 | set { SetValue(DisplayToolTipProperty, value); }
34 | }
35 | public static readonly DependencyProperty DisplayToolTipProperty =
36 | DependencyProperty.Register("DisplayToolTip", typeof(bool), typeof(UwpGraphControl), new PropertyMetadata(false));
37 |
38 | public UwpGraphControl()
39 | {
40 | this.DefaultStyleKey = typeof(UwpGraphControl);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graphics.Canvas;
2 | using Microsoft.Graphics.Canvas.Geometry;
3 | using RealTimeGraphX;
4 | using RealTimeGraphX.UWP;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Numerics;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using Windows.UI;
12 | using Windows.UI.Xaml.Media;
13 |
14 | ///
15 | /// Contains a collection of extension methods.
16 | ///
17 | internal static class ExtensionMethods
18 | {
19 | ///
20 | /// Draws a polyline.
21 | ///
22 | /// The session.
23 | /// The points.
24 | /// The color.
25 | /// The stroke thickness.
26 | public static void DrawPolyline(this CanvasDrawingSession session, List points, Color color, float strokeThickness)
27 | {
28 | CanvasPathBuilder pathBuilder = new CanvasPathBuilder(session);
29 |
30 | pathBuilder.BeginFigure(points[0].X, points[0].Y);
31 |
32 | for (int i = 1; i < points.Count; i++)
33 | {
34 | pathBuilder.AddLine(points[i].X, points[i].Y);
35 | }
36 |
37 | pathBuilder.EndFigure(CanvasFigureLoop.Open);
38 |
39 | session.DrawGeometry(CanvasGeometry.CreatePath(pathBuilder), color, strokeThickness);
40 | }
41 |
42 | ///
43 | /// Fills a polygon.
44 | ///
45 | /// The session.
46 | /// The surface.
47 | /// The series.
48 | /// The points.
49 | /// The brush.
50 | public static void FillPolygon(this CanvasDrawingSession session, UwpGraphSurface surface, UwpGraphDataSeries series, List points, Brush brush)
51 | {
52 | var size = surface.GetSize();
53 | var geometry = CanvasGeometry.CreatePolygon(session, points.ToArray());
54 | var v = series.GetCanvasBrush(session, size.Width, size.Height);
55 | session.FillGeometry(geometry, v);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RealTimeGraphX.UWP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RealTimeGraphX.UWP")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/Properties/RealTimeGraphX.UWP.rd.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/RealTimeGraphX.UWP.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RealTimeGraphX.UWP
5 | 1.0.0
6 | RealTimeGraphX is a data type agnostic, high performance plotting library for WPF and UWP.
7 | RealTimeGraphX.WPF
8 | Roy Ben Shabat
9 | false
10 | MIT
11 | https://github.com/royben/RealTimeGraphX
12 | icon.png
13 | Chart Graph Plotting RealTime WPF UWP
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpDataTriggerAction.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xaml.Interactivity;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Shapes;
10 |
11 | namespace RealTimeGraphX.UWP
12 | {
13 | ///
14 | /// Represents a data trigger action.
15 | ///
16 | ///
17 | ///
18 | internal class UwpDataTriggerAction : DependencyObject, IAction
19 | {
20 | ///
21 | /// Gets or sets the target object.
22 | ///
23 | public FrameworkElement TargetObject
24 | {
25 | get { return (FrameworkElement)GetValue(TargetObjectProperty); }
26 | set { SetValue(TargetObjectProperty, value); }
27 | }
28 | public static readonly DependencyProperty TargetObjectProperty =
29 | DependencyProperty.Register("TargetObject", typeof(FrameworkElement), typeof(UwpDataTriggerAction), new PropertyMetadata(null));
30 |
31 | ///
32 | /// Gets or sets the name of the property.
33 | ///
34 | public String PropertyName
35 | {
36 | get { return (String)GetValue(PropertyNameProperty); }
37 | set { SetValue(PropertyNameProperty, value); }
38 | }
39 | public static readonly DependencyProperty PropertyNameProperty =
40 | DependencyProperty.Register("PropertyName", typeof(String), typeof(UwpDataTriggerAction), new PropertyMetadata(null));
41 |
42 | ///
43 | /// Gets or sets the value.
44 | ///
45 | public Object Value
46 | {
47 | get { return (Object)GetValue(ValueProperty); }
48 | set { SetValue(ValueProperty, value); }
49 | }
50 | public static readonly DependencyProperty ValueProperty =
51 | DependencyProperty.Register("Value", typeof(Object), typeof(UwpDataTriggerAction), new PropertyMetadata(null));
52 |
53 | ///
54 | /// Executes the action.
55 | ///
56 | /// The that is passed to the action by the behavior. Generally this is or a target object.
57 | /// The value of this parameter is determined by the caller.
58 | ///
59 | /// Returns the result of the action.
60 | ///
61 | ///
62 | /// An example of parameter usage is EventTriggerBehavior, which passes the EventArgs as a parameter to its actions.
63 | ///
64 | public object Execute(object sender, object parameter)
65 | {
66 | List props = new List();
67 | List fields = new List();
68 |
69 | Type type = TargetObject.GetType();
70 |
71 | while (type != null)
72 | {
73 | props.AddRange(type.GetTypeInfo().DeclaredProperties);
74 | fields.AddRange(type.GetTypeInfo().DeclaredFields);
75 | type = type.BaseType;
76 |
77 | var prop = props.SingleOrDefault(x => x.Name == PropertyName + "Property");
78 |
79 | if (prop != null)
80 | {
81 | var propValue = props.SingleOrDefault(x => x.Name == PropertyName);
82 | var _element_dp = prop.GetValue(TargetObject) as DependencyProperty;
83 | TargetObject.SetValue(_element_dp, Convert.ChangeType(Value, propValue.PropertyType));
84 | return null;
85 | }
86 | else
87 | {
88 | var field = fields.SingleOrDefault(x => x.Name == PropertyName + "Property");
89 |
90 | if (field != null)
91 | {
92 | var propValue = props.SingleOrDefault(x => x.Name == PropertyName);
93 |
94 | var _element_dp = field.GetValue(TargetObject) as DependencyProperty;
95 | TargetObject.SetValue(_element_dp, Convert.ChangeType(Value, propValue.PropertyType));
96 | return null;
97 | }
98 | }
99 | }
100 |
101 | return null;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpDataTriggerElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xaml.Interactions.Core;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Media;
11 |
12 | namespace RealTimeGraphX.UWP
13 | {
14 | ///
15 | /// Represents an invisible element which can be used to reevaluate a data trigger behavior binding inside a style.
16 | ///
17 | ///
18 | internal class UwpDataTriggerElement : Control
19 | {
20 | private FrameworkElement _parent;
21 | private DataTriggerBehavior _dataTrigger;
22 |
23 | #region Properties
24 |
25 | ///
26 | /// Gets or sets the name of the data trigger behavior element.
27 | ///
28 | public String ElementName
29 | {
30 | get { return (String)GetValue(ElementNameProperty); }
31 | set { SetValue(ElementNameProperty, value); }
32 | }
33 | public static readonly DependencyProperty ElementNameProperty =
34 | DependencyProperty.Register("ElementName", typeof(String), typeof(UwpDataTriggerElement), new PropertyMetadata(null));
35 |
36 | ///
37 | /// Gets or sets the data context path that will cause the evaluation when changed.
38 | ///
39 | public String DataContextPath
40 | {
41 | get { return (String)GetValue(DataContextPathProperty); }
42 | set { SetValue(DataContextPathProperty, value); }
43 | }
44 | public static readonly DependencyProperty DataContextPathProperty =
45 | DependencyProperty.Register("DataContextPath", typeof(String), typeof(UwpDataTriggerElement), new PropertyMetadata(null, (d, e) => (d as UwpDataTriggerElement).OnBindingChanged()));
46 |
47 | #endregion
48 |
49 | #region Constructors
50 |
51 | ///
52 | /// Initializes a new instance of the class.
53 | ///
54 | public UwpDataTriggerElement()
55 | {
56 | Loaded += DataTriggerElement_Loaded;
57 | }
58 |
59 | #endregion
60 |
61 | #region Event Handlers
62 |
63 | ///
64 | /// Handles the Loaded event of the DataTriggerElement control.
65 | ///
66 | /// The source of the event.
67 | /// The instance containing the event data.
68 | private void DataTriggerElement_Loaded(object sender, RoutedEventArgs e)
69 | {
70 | _parent = VisualTreeHelper.GetParent(this) as FrameworkElement;
71 | _dataTrigger = (_parent as FrameworkElement).FindName(ElementName) as DataTriggerBehavior;
72 | OnBindingChanged();
73 | }
74 |
75 | #endregion
76 |
77 | #region Virtual Methods
78 |
79 | ///
80 | /// Called when the has changed.
81 | ///
82 | /// The sender.
83 | /// The dependency property.
84 | protected virtual void OnDataContextPropertyChanged(DependencyObject sender, DependencyProperty dp)
85 | {
86 | var value = (DataContext as DependencyObject).GetValue(dp);
87 |
88 | if (value.ToString() == _dataTrigger.Value.ToString())
89 | {
90 | UpdateBinding();
91 | }
92 | }
93 |
94 | #endregion
95 |
96 | #region Private Methods
97 |
98 | ///
99 | /// Reevaluates the binding.
100 | ///
101 | private void OnBindingChanged()
102 | {
103 | if (DataContext != null)
104 | {
105 | var dataContextPropInfo = DataContext.GetType().GetField(DataContextPath + "Property", BindingFlags.Static | BindingFlags.Public);
106 |
107 | if (dataContextPropInfo != null)
108 | {
109 | var _datacontext_dp = dataContextPropInfo.GetValue(DataContext) as DependencyProperty;
110 |
111 | (DataContext as DependencyObject).RegisterPropertyChangedCallback(_datacontext_dp, OnDataContextPropertyChanged);
112 |
113 | if ((DataContext as DependencyObject).GetValue(_datacontext_dp).ToString() == _dataTrigger.Value.ToString())
114 | {
115 | UpdateBinding();
116 | }
117 | }
118 | }
119 | }
120 |
121 | ///
122 | /// Updates the binding.
123 | ///
124 | private void UpdateBinding()
125 | {
126 | foreach (var action in _dataTrigger.Actions.OfType())
127 | {
128 | action.Execute(_dataTrigger, _dataTrigger.Value);
129 | }
130 | }
131 |
132 | #endregion
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphAxisControl.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.EventArguments;
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.Collections.ObjectModel;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 |
13 | namespace RealTimeGraphX.UWP
14 | {
15 | ///
16 | /// Represents a horizontal/vertical graph axis control.
17 | ///
18 | ///
19 | public class UwpGraphAxisControl : UwpGraphComponentBase
20 | {
21 | private ItemsControl _items_control;
22 |
23 | ///
24 | /// Gets or sets the control orientation.
25 | ///
26 | public Orientation Orientation
27 | {
28 | get { return (Orientation)GetValue(OrientationProperty); }
29 | set { SetValue(OrientationProperty, value); }
30 | }
31 | public static readonly DependencyProperty OrientationProperty =
32 | DependencyProperty.Register("Orientation", typeof(Orientation), typeof(UwpGraphAxisControl), new PropertyMetadata(Orientation.Vertical));
33 |
34 | ///
35 | /// Gets or sets the tick item template.
36 | ///
37 | public DataTemplate ItemTemplate
38 | {
39 | get { return (DataTemplate)GetValue(ItemTemplateProperty); }
40 | set { SetValue(ItemTemplateProperty, value); }
41 | }
42 | public static readonly DependencyProperty ItemTemplateProperty =
43 | DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(UwpGraphAxisControl), new PropertyMetadata(null));
44 |
45 | ///
46 | /// Gets or sets the tick items.
47 | ///
48 | internal ObservableCollection Items
49 | {
50 | get { return (ObservableCollection)GetValue(ItemsProperty); }
51 | set { SetValue(ItemsProperty, value); }
52 | }
53 | public static readonly DependencyProperty ItemsProperty =
54 | DependencyProperty.Register("Items", typeof(ObservableCollection), typeof(UwpGraphAxisControl), new PropertyMetadata(null));
55 |
56 | ///
57 | /// Gets or sets the number of ticks to display on the control.
58 | ///
59 | public int Ticks
60 | {
61 | get { return (int)GetValue(TicksProperty); }
62 | set { SetValue(TicksProperty, value); }
63 | }
64 | public static readonly DependencyProperty TicksProperty =
65 | DependencyProperty.Register("Ticks", typeof(int), typeof(UwpGraphAxisControl), new PropertyMetadata(9, (d, e) => (d as UwpGraphAxisControl).OnTicksChanged()));
66 |
67 | ///
68 | /// Gets or sets the string format which is used to format the ticks value.
69 | ///
70 | public String StringFormat
71 | {
72 | get { return (String)GetValue(StringFormatProperty); }
73 | set { SetValue(StringFormatProperty, value); }
74 | }
75 | public static readonly DependencyProperty StringFormatProperty =
76 | DependencyProperty.Register("StringFormat", typeof(String), typeof(UwpGraphAxisControl), new PropertyMetadata(null));
77 |
78 | ///
79 | /// Initializes a new instance of the class.
80 | ///
81 | public UwpGraphAxisControl()
82 | {
83 | this.DefaultStyleKey = typeof(UwpGraphAxisControl);
84 | }
85 |
86 | ///
87 | /// Invoked whenever application code or internal processes (such as a rebuilding layout pass) call ApplyTemplate. In simplest terms, this means the method is called just before a UI element displays in your app. Override this method to influence the default post-template logic of a class.
88 | ///
89 | protected override void OnApplyTemplate()
90 | {
91 | base.OnApplyTemplate();
92 |
93 | _items_control = GetTemplateChild("PART_ItemsControl") as ItemsControl;
94 | OnTicksChanged();
95 | }
96 |
97 | ///
98 | /// Called when the property has changed.
99 | ///
100 | protected virtual void OnTicksChanged()
101 | {
102 | Items = new ObservableCollection(Enumerable.Range(0, Ticks).Select(x => new UwpGraphAxisTickData()));
103 |
104 | if (Controller != null)
105 | {
106 | Controller.RequestVirtualRangeChange();
107 | }
108 | }
109 |
110 | ///
111 | /// Called when the controller has changed.
112 | ///
113 | /// The old controller.
114 | /// The new controller.
115 | protected override void OnControllerChanged(IGraphController oldController, IGraphController newController)
116 | {
117 | base.OnControllerChanged(oldController, newController);
118 |
119 | if (newController != null)
120 | {
121 | newController.RequestVirtualRangeChange();
122 | }
123 | }
124 |
125 | ///
126 | /// Handles the event.
127 | ///
128 | /// The source of the event.
129 | /// The event arguments.
130 | protected override void OnVirtualRangeChanged(object sender, RangeChangedEventArgs e)
131 | {
132 | base.OnVirtualRangeChanged(sender, e);
133 |
134 | InvokeUI(() =>
135 | {
136 | if (Orientation == Orientation.Vertical)
137 | {
138 | if (Items != null)
139 | {
140 | var steps = e.MinimumY.CreateRange(e.MinimumY, e.MaximumY, Ticks).Reverse().ToList();
141 |
142 | for (int i = 0; i < steps.Count; i++)
143 | {
144 | var tick_data = Items[i];
145 | tick_data.Data = steps[i];
146 | tick_data.DisplayText = tick_data.Data.ToString(StringFormat);
147 | tick_data.IsFirst = i == 0;
148 | tick_data.IsLast = i == steps.Count - 1;
149 | tick_data.IsEven = i % 2 == 0;
150 | }
151 | }
152 | }
153 | else
154 | {
155 | if (Items != null)
156 | {
157 | var steps = e.MinimumX.CreateRange(e.MinimumX, e.MaximumX, Ticks).ToList();
158 |
159 | for (int i = 0; i < steps.Count; i++)
160 | {
161 | var tick_data = Items[i];
162 | tick_data.Data = steps[i];
163 | tick_data.DisplayText = tick_data.Data.ToString(StringFormat);
164 | tick_data.IsFirst = i == 0;
165 | tick_data.IsLast = i == steps.Count - 1;
166 | tick_data.IsEven = i % 2 == 0;
167 | }
168 | }
169 | }
170 | });
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphAxisPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using Windows.Foundation;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Media;
11 |
12 | namespace RealTimeGraphX.UWP
13 | {
14 | ///
15 | /// Represents a panel that will align its children in an axis labels like arrangement.
16 | ///
17 | ///
18 | public class UwpGraphAxisPanel : Grid
19 | {
20 | private List _measured_childs;
21 |
22 | ///
23 | /// Gets or sets the panel orientation.
24 | ///
25 | public Orientation Orientation
26 | {
27 | get { return (Orientation)GetValue(OrientationProperty); }
28 | set { SetValue(OrientationProperty, value); }
29 | }
30 | public static readonly DependencyProperty OrientationProperty =
31 | DependencyProperty.Register("Orientation", typeof(Orientation), typeof(UwpGraphAxisPanel), new PropertyMetadata(Orientation.Vertical));
32 |
33 | ///
34 | /// Initializes a new instance of the class.
35 | ///
36 | public UwpGraphAxisPanel()
37 | {
38 | _measured_childs = new List();
39 | Loaded += VerticalAxisPanel_Loaded;
40 | }
41 |
42 | ///
43 | /// Handles the Loaded event of the VerticalAxisGrid control.
44 | ///
45 | /// The source of the event.
46 | /// The instance containing the event data.
47 | private void VerticalAxisPanel_Loaded(object sender, RoutedEventArgs e)
48 | {
49 | UpdatePanel();
50 | }
51 |
52 | ///
53 | /// Provides the behavior for the "Measure" pass of the layout cycle. Classes can override this method to define their own "Measure" pass behavior.
54 | ///
55 | /// The available size that this object can give to child objects. Infinity can be specified as a value to indicate that the object will size to whatever content is available.
56 | ///
57 | /// The size that this object determines it needs during layout, based on its calculations of the allocated sizes for child objects or based on other considerations such as a fixed container size.
58 | ///
59 | protected override Size MeasureOverride(Size availableSize)
60 | {
61 | UpdatePanel();
62 | return base.MeasureOverride(availableSize);
63 | }
64 |
65 | ///
66 | /// Updates the panel.
67 | ///
68 | private void UpdatePanel()
69 | {
70 | if (!Children.Any(x => !_measured_childs.Contains(x))) return;
71 |
72 | RowDefinitions.Clear();
73 | ColumnDefinitions.Clear();
74 |
75 |
76 | if (Orientation == Orientation.Vertical)
77 | {
78 | for (int i = 0; i < Children.Count; i++)
79 | {
80 | FrameworkElement element = Children[i] as FrameworkElement;
81 |
82 | _measured_childs.Add(element);
83 |
84 | if (i < Children.Count - 1)
85 | {
86 | RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
87 | Grid.SetRow(element, i);
88 |
89 | //if (element.DataContext is GraphAxisTickData)
90 | //{
91 | // (element.DataContext as GraphAxisTickData).Row = i;
92 | //}
93 |
94 | element.VerticalAlignment = VerticalAlignment.Top;
95 |
96 | element.SizeChanged += (_, __) =>
97 | {
98 | element.Margin = new Thickness(0, (element.ActualHeight / 2) * -1, 0, 0);
99 | };
100 | }
101 | else
102 | {
103 | Grid.SetRow(element, i);
104 |
105 | //if (element.DataContext is GraphAxisTickData)
106 | //{
107 | // (element.DataContext as GraphAxisTickData).Row = i;
108 | //}
109 |
110 | element.VerticalAlignment = VerticalAlignment.Bottom;
111 |
112 | element.SizeChanged += (_, __) =>
113 | {
114 | element.Margin = new Thickness(0, 0, 0, (element.ActualHeight / 2) * -1);
115 | };
116 | }
117 | }
118 | }
119 | else
120 | {
121 | for (int i = 0; i < Children.Count; i++)
122 | {
123 | FrameworkElement element = Children[i] as FrameworkElement;
124 |
125 | _measured_childs.Add(element);
126 |
127 | if (i < Children.Count - 1)
128 | {
129 | ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
130 | Grid.SetColumn(element, i);
131 | element.HorizontalAlignment = HorizontalAlignment.Left;
132 |
133 | //if (element.DataContext is GraphAxisTickData)
134 | //{
135 | // (element.DataContext as GraphAxisTickData).Column = i;
136 | //}
137 |
138 | element.SizeChanged += (_, __) =>
139 | {
140 | element.Margin = new Thickness((element.ActualWidth / 2) * -1, 0, 0, 0);
141 | };
142 | }
143 | else
144 | {
145 | Grid.SetColumn(element, i);
146 | element.HorizontalAlignment = HorizontalAlignment.Right;
147 |
148 | //if (element.DataContext is GraphAxisTickData)
149 | //{
150 | // (element.DataContext as GraphAxisTickData).Column = i;
151 | //}
152 |
153 | element.SizeChanged += (_, __) =>
154 | {
155 | element.Margin = new Thickness(0, 0, (element.ActualWidth / 2) * -1, 0);
156 | };
157 | }
158 | }
159 | }
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphAxisTickData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Controls;
8 |
9 | namespace RealTimeGraphX.UWP
10 | {
11 | ///
12 | /// Represents a graph axis data point tick value wrapper.
13 | ///
14 | public class UwpGraphAxisTickData : DependencyObject
15 | {
16 | ///
17 | /// Gets or sets a value indicating whether this tick is the first tick.
18 | ///
19 | public bool IsFirst
20 | {
21 | get { return (bool)GetValue(IsFirstProperty); }
22 | set { SetValue(IsFirstProperty, value); }
23 | }
24 | public static readonly DependencyProperty IsFirstProperty =
25 | DependencyProperty.Register("IsFirst", typeof(bool), typeof(UwpGraphAxisTickData), new PropertyMetadata(false));
26 |
27 | ///
28 | /// Gets or sets a value indicating whether this tick is the last tick.
29 | ///
30 | public bool IsLast
31 | {
32 | get { return (bool)GetValue(IsLastProperty); }
33 | set { SetValue(IsLastProperty, value); }
34 | }
35 | public static readonly DependencyProperty IsLastProperty =
36 | DependencyProperty.Register("IsLast", typeof(bool), typeof(UwpGraphAxisTickData), new PropertyMetadata(false));
37 |
38 | ///
39 | /// Gets or sets a value indicating whether this tick is not the first or last.
40 | ///
41 | public bool IsCenter
42 | {
43 | get { return !IsFirst && !IsLast; }
44 | }
45 |
46 | ///
47 | /// Gets or sets a value indicating whether this tick index is even.
48 | ///
49 | public bool IsEven
50 | {
51 | get { return (bool)GetValue(IsEvenProperty); }
52 | set { SetValue(IsEvenProperty, value); }
53 | }
54 | public static readonly DependencyProperty IsEvenProperty =
55 | DependencyProperty.Register("IsEven", typeof(bool), typeof(UwpGraphAxisTickData), new PropertyMetadata(false));
56 |
57 | ///
58 | /// Gets a value indicating whether this tick index is odd.
59 | ///
60 | public bool IsOdd
61 | {
62 | get { return !IsEven; }
63 | }
64 |
65 | ///
66 | /// Gets or sets the actual graph data point.
67 | ///
68 | public IGraphDataPoint Data
69 | {
70 | get { return (IGraphDataPoint)GetValue(DataProperty); }
71 | set { SetValue(DataProperty, value); }
72 | }
73 | public static readonly DependencyProperty DataProperty =
74 | DependencyProperty.Register("Data", typeof(IGraphDataPoint), typeof(UwpGraphAxisTickData), new PropertyMetadata(null));
75 |
76 | ///
77 | /// Gets or sets the display text.
78 | ///
79 | public String DisplayText
80 | {
81 | get { return (String)GetValue(DisplayTextProperty); }
82 | set { SetValue(DisplayTextProperty, value); }
83 | }
84 | public static readonly DependencyProperty DisplayTextProperty =
85 | DependencyProperty.Register("DisplayText", typeof(String), typeof(UwpGraphAxisTickData), new PropertyMetadata(null));
86 |
87 | ///
88 | /// Gets the data point value.
89 | ///
90 | public object Value
91 | {
92 | get
93 | {
94 | return Data != null ? Data.GetValue() : null;
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphComponentBase.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.EventArguments;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.UI.Xaml;
8 | using Windows.UI.Xaml.Controls;
9 |
10 | namespace RealTimeGraphX.UWP
11 | {
12 | ///
13 | /// Represents a graph component base class.
14 | ///
15 | ///
16 | public class UwpGraphComponentBase : Control
17 | {
18 | ///
19 | /// Gets or sets the graph controller.
20 | ///
21 | public IGraphController Controller
22 | {
23 | get { return (IGraphController)GetValue(ControllerProperty); }
24 | set { SetValue(ControllerProperty, value); }
25 | }
26 | public static readonly DependencyProperty ControllerProperty =
27 | DependencyProperty.Register("Controller", typeof(IGraphController), typeof(UwpGraphComponentBase), new PropertyMetadata(null,(d,e) => (d as UwpGraphComponentBase).OnControllerChanged(e.OldValue as IGraphController, e.NewValue as IGraphController)));
28 |
29 |
30 | ///
31 | /// Called when the controller has changed.
32 | ///
33 | /// The old controller.
34 | /// The new controller.
35 | protected virtual void OnControllerChanged(IGraphController oldController, IGraphController newController)
36 | {
37 | if (oldController != null)
38 | {
39 | oldController.VirtualRangeChanged -= OnVirtualRangeChanged;
40 | }
41 |
42 | if (newController != null)
43 | {
44 | newController.VirtualRangeChanged += OnVirtualRangeChanged;
45 | }
46 | }
47 |
48 | ///
49 | /// Handles the event.
50 | ///
51 | /// The source of the event.
52 | /// The event arguments.
53 | protected virtual void OnVirtualRangeChanged(object sender, RangeChangedEventArgs e)
54 | {
55 | //Optional
56 | }
57 |
58 | ///
59 | /// Invokes the specified method on the component dispatcher.
60 | ///
61 | /// The action.
62 | protected async void InvokeUI(Action action)
63 | {
64 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { action(); });
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.UI;
7 | using Windows.UI.Xaml.Media;
8 |
9 | namespace RealTimeGraphX.UWP
10 | {
11 | ///
12 | /// Represents a UWP graph controller .
13 | ///
14 | /// The type of the x data point.
15 | /// The type of the y data point.
16 | ///
17 | public class UwpGraphController : GraphController
18 | where TXDataPoint : GraphDataPoint
19 | where TYDataPoint : GraphDataPoint
20 | {
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphDataSeries.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graphics.Canvas;
2 | using Microsoft.Graphics.Canvas.Brushes;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Windows.UI;
9 | using Windows.UI.Xaml;
10 | using Windows.UI.Xaml.Media;
11 |
12 | namespace RealTimeGraphX.UWP
13 | {
14 | ///
15 | /// Represents a UWP data series .
16 | ///
17 | ///
18 | ///
19 | public class UwpGraphDataSeries : GraphObject, IGraphDataSeries
20 | {
21 | private class Stop
22 | {
23 | public float Offset { get; set; }
24 | public Color Color { get; set; }
25 | }
26 | private Stop[] _stopCollection;
27 |
28 |
29 |
30 | private String _name;
31 | ///
32 | /// Gets or sets the series name.
33 | ///
34 | public String Name
35 | {
36 | get { return _name; }
37 | set { _name = value; RaisePropertyChangedAuto(); }
38 | }
39 |
40 | private float _strokeThickness;
41 | ///
42 | /// Gets or sets the stroke thickness.
43 | ///
44 | public float StrokeThickness
45 | {
46 | get
47 | {
48 | return _strokeThickness;
49 | }
50 | set
51 | {
52 | _strokeThickness = value;
53 | RaisePropertyChangedAuto();
54 | }
55 | }
56 |
57 | private bool _isVisible;
58 | ///
59 | /// Gets or sets a value indicating whether this series should be visible.
60 | ///
61 | public bool IsVisible
62 | {
63 | get { return _isVisible; }
64 | set { _isVisible = value; RaisePropertyChangedAuto(); }
65 | }
66 |
67 | private Color _stroke;
68 | ///
69 | /// Gets or sets the series stroke color.
70 | ///
71 | public Color Stroke
72 | {
73 | get { return _stroke; }
74 | set
75 | {
76 | _stroke = value;
77 | RaisePropertyChangedAuto();
78 | }
79 | }
80 |
81 | private Brush _fill;
82 | ///
83 | /// Gets or sets the series fill brush.
84 | ///
85 | public Brush Fill
86 | {
87 | get { return _fill; }
88 | set
89 | {
90 | _fill = value;
91 |
92 | if (_fill != null)
93 | {
94 | if (_fill is SolidColorBrush)
95 | {
96 | _stopCollection = new Stop[] { new Stop() { Color = (_fill as SolidColorBrush).Color, Offset = 0 } };
97 | }
98 | else if (_fill is LinearGradientBrush)
99 | {
100 | _stopCollection = (_fill as LinearGradientBrush).GradientStops.Select(x => new Stop() { Color = x.Color, Offset = (float)x.Offset }).ToArray();
101 | }
102 | }
103 |
104 | RaisePropertyChangedAuto();
105 | }
106 | }
107 |
108 | ///
109 | /// Gets or sets a value indicating whether to fill the series.
110 | ///
111 | public bool UseFill
112 | {
113 | get { return Fill != null; }
114 | }
115 |
116 | private Object _currentValue;
117 | ///
118 | /// Gets the current value.
119 | ///
120 | public Object CurrentValue
121 | {
122 | get { return _currentValue; }
123 | set
124 | {
125 | _currentValue = value;
126 | }
127 | }
128 |
129 | ///
130 | /// Initializes a new instance of the class.
131 | ///
132 | public UwpGraphDataSeries()
133 | {
134 | StrokeThickness = 1;
135 | IsVisible = true;
136 | Stroke = Colors.DodgerBlue;
137 | }
138 |
139 | ///
140 | /// Gets the canvas brush.
141 | ///
142 | /// The creator.
143 | /// The width.
144 | /// The height.
145 | ///
146 | internal ICanvasBrush GetCanvasBrush(ICanvasResourceCreator creator, double width, double height)
147 | {
148 | if (_stopCollection.Length == 1)
149 | {
150 | return new CanvasSolidColorBrush(creator, _stopCollection[0].Color);
151 | }
152 | else
153 | {
154 | return new CanvasLinearGradientBrush(creator, _stopCollection.Select(x => new CanvasGradientStop() { Color = x.Color, Position = (float)(x.Offset) }).ToArray()) { StartPoint = new System.Numerics.Vector2(0, 0), EndPoint = new System.Numerics.Vector2((float)width, (float)height) };
155 | }
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/UwpGraphGridLines.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using Windows.UI.Xaml;
8 |
9 | namespace RealTimeGraphX.UWP
10 | {
11 | ///
12 | /// Represents a graph grid lines component.
13 | ///
14 | ///
15 | public class UwpGraphGridLines : UwpGraphComponentBase
16 | {
17 | ///
18 | /// Gets or sets the number of grid rows.
19 | ///
20 | public int Rows
21 | {
22 | get { return (int)GetValue(RowsProperty); }
23 | set { SetValue(RowsProperty, value); }
24 | }
25 | public static readonly DependencyProperty RowsProperty =
26 | DependencyProperty.Register("Rows", typeof(int), typeof(UwpGraphGridLines), new PropertyMetadata(8, (d, e) => (d as UwpGraphGridLines).UpdateGridLines()));
27 |
28 | ///
29 | /// Gets or sets the number of grid columns.
30 | ///
31 | public int Columns
32 | {
33 | get { return (int)GetValue(ColumnsProperty); }
34 | set { SetValue(ColumnsProperty, value); }
35 | }
36 | public static readonly DependencyProperty ColumnsProperty =
37 | DependencyProperty.Register("Columns", typeof(int), typeof(UwpGraphGridLines), new PropertyMetadata(8, (d, e) => (d as UwpGraphGridLines).UpdateGridLines()));
38 |
39 | ///
40 | /// Gets or sets the vertical items.
41 | ///
42 | internal IEnumerable VerticalItems
43 | {
44 | get { return (IEnumerable)GetValue(VerticalItemsProperty); }
45 | set { SetValue(VerticalItemsProperty, value); }
46 | }
47 | public static readonly DependencyProperty VerticalItemsProperty =
48 | DependencyProperty.Register("VerticalItems", typeof(IEnumerable), typeof(UwpGraphGridLines), new PropertyMetadata(null));
49 |
50 | ///
51 | /// Gets or sets the horizontal items.
52 | ///
53 | internal IEnumerable HorizontalItems
54 | {
55 | get { return (IEnumerable)GetValue(HorizontalItemsProperty); }
56 | set { SetValue(HorizontalItemsProperty, value); }
57 | }
58 | public static readonly DependencyProperty HorizontalItemsProperty =
59 | DependencyProperty.Register("HorizontalItems", typeof(IEnumerable), typeof(UwpGraphGridLines), new PropertyMetadata(null));
60 |
61 | ///
62 | /// Initializes a new instance of the class.
63 | ///
64 | public UwpGraphGridLines()
65 | {
66 | this.DefaultStyleKey = typeof(UwpGraphGridLines);
67 | Loaded += GridLines_Loaded;
68 | }
69 |
70 | ///
71 | /// Handles the Loaded event of the GridLines control.
72 | ///
73 | /// The source of the event.
74 | /// The instance containing the event data.
75 | private void GridLines_Loaded(object sender, RoutedEventArgs e)
76 | {
77 | UpdateGridLines();
78 | }
79 |
80 | ///
81 | /// Updates the grid lines.
82 | ///
83 | private void UpdateGridLines()
84 | {
85 | VerticalItems = Enumerable.Range(0, Rows).ToList();
86 | HorizontalItems = Enumerable.Range(0, Columns).ToList();
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/RealTimeGraphX.UWP/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.UWP/icon.png
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace RealTimeGraphX.WPF.Demo
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Converters/ObjectEqualityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Data;
8 |
9 | namespace RealTimeGraphX.WPF.Demo.Converters
10 | {
11 | public class ObjectEqualityConverter : IMultiValueConverter
12 | {
13 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
14 | {
15 | return values[0] == values[1];
16 | }
17 |
18 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
19 | {
20 | throw new NotImplementedException();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/ListGraphItemVM.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.DataPoints;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Media;
8 |
9 | namespace RealTimeGraphX.WPF.Demo
10 | {
11 | public class ListGraphItemVM
12 | {
13 | public WpfGraphController Controller { get; set; }
14 |
15 | public String Name { get; set; }
16 |
17 | public String StringFormat { get; set; }
18 |
19 | public Color Color
20 | {
21 | get { return Controller.DataSeriesCollection[0].Stroke; }
22 | set { Controller.DataSeriesCollection[0].Stroke = value; }
23 | }
24 |
25 | public ListGraphItemVM()
26 | {
27 | Controller = new WpfGraphController();
28 | Controller.Range.MinimumY = 0;
29 | Controller.Range.MaximumY = 1080;
30 | Controller.Range.MaximumX = TimeSpan.FromSeconds(10);
31 | Controller.Range.AutoY = true;
32 | Controller.Range.AutoYFallbackMode = GraphRangeAutoYFallBackMode.MinMax;
33 |
34 | Controller.DataSeriesCollection.Add(new WpfGraphDataSeries()
35 | {
36 | Name = "Series",
37 | Stroke = Colors.DodgerBlue,
38 | });
39 |
40 | StringFormat = "0.0";
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace RealTimeGraphX.WPF.Demo
17 | {
18 | ///
19 | /// Interaction logic for MainWindow.xaml
20 | ///
21 | public partial class MainWindow : Window
22 | {
23 | public MainWindow()
24 | {
25 | InitializeComponent();
26 | DataContext = new MainWindowVM();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/MainWindowVM.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.DataPoints;
2 | using RealTimeGraphX.Renderers;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Media;
12 |
13 | namespace RealTimeGraphX.WPF.Demo
14 | {
15 | public class MainWindowVM
16 | {
17 | private Random r = new Random();
18 |
19 | public WpfGraphController Controller { get; set; }
20 |
21 | public WpfGraphController MultiController { get; set; }
22 |
23 | public List ListItems { get; set; }
24 |
25 | public List ListItems2 { get; set; }
26 |
27 | public MainWindowVM()
28 | {
29 | Controller = new WpfGraphController();
30 | Controller.Range.MinimumY = 0;
31 | Controller.Range.MaximumY = 1080;
32 | Controller.Range.MaximumX = TimeSpan.FromSeconds(10);
33 | Controller.Range.AutoY = true;
34 | Controller.Range.AutoYFallbackMode = GraphRangeAutoYFallBackMode.MinMax;
35 |
36 | Controller.DataSeriesCollection.Add(new WpfGraphDataSeries()
37 | {
38 | Name = "Series",
39 | Stroke = Colors.DodgerBlue,
40 | });
41 |
42 | MultiController = new WpfGraphController();
43 | MultiController.Range.MinimumY = 0;
44 | MultiController.Range.MaximumY = 1080;
45 | MultiController.Range.MaximumX = TimeSpan.FromSeconds(10);
46 | MultiController.Range.AutoY = true;
47 |
48 | MultiController.DataSeriesCollection.Add(new WpfGraphDataSeries()
49 | {
50 | Name = "Series 1",
51 | Stroke = Colors.Red,
52 | });
53 |
54 | MultiController.DataSeriesCollection.Add(new WpfGraphDataSeries()
55 | {
56 | Name = "Series 2",
57 | Stroke = Colors.Green,
58 | });
59 |
60 | MultiController.DataSeriesCollection.Add(new WpfGraphDataSeries()
61 | {
62 | Name = "Series 3",
63 | Stroke = Colors.Blue,
64 | });
65 |
66 | MultiController.DataSeriesCollection.Add(new WpfGraphDataSeries()
67 | {
68 | Name = "Series 4",
69 | Stroke = Colors.Yellow,
70 | });
71 |
72 | MultiController.DataSeriesCollection.Add(new WpfGraphDataSeries()
73 | {
74 | Name = "Series 5",
75 | Stroke = Colors.Gray,
76 | });
77 |
78 | ListItems = new List();
79 |
80 | for (int i = 1; i < 6; i++)
81 | {
82 | var item = new ListGraphItemVM();
83 | item.Name = $"Item {i}";
84 | item.StringFormat = $"F{i}";
85 | item.Color = GetRandomColor();
86 | ListItems.Add(item);
87 | }
88 |
89 | ListItems2 = new List();
90 |
91 | for (int i = 1; i < 6; i++)
92 | {
93 | var item = new ListGraphItemVM();
94 | item.Name = $"Item {i}";
95 | item.StringFormat = $"F{i}";
96 | item.Color = GetRandomColor();
97 | ListItems2.Add(item);
98 | }
99 |
100 | Application.Current.MainWindow.ContentRendered += (_, __) => Start();
101 | }
102 |
103 | private void Start()
104 | {
105 | Task.Factory.StartNew(() =>
106 | {
107 | Stopwatch watch = new Stopwatch();
108 | watch.Start();
109 |
110 | while (true)
111 | {
112 | var y = System.Windows.Forms.Cursor.Position.Y;
113 |
114 | List yy = new List()
115 | {
116 | y,
117 | y + 20,
118 | y + 40,
119 | y + 60,
120 | y + 80,
121 | };
122 |
123 | var x = watch.Elapsed;
124 |
125 | List xx = new List()
126 | {
127 | x,
128 | x,
129 | x,
130 | x,
131 | x
132 | };
133 |
134 | Controller.PushData(x, y);
135 | MultiController.PushData(xx, yy);
136 |
137 | for (int i = 0; i < ListItems.Count; i++)
138 | {
139 | ListItems[i].Controller.PushData(x, y + r.Next(0, 50 * (i + 1)));
140 | ListItems2[i].Controller.PushData(x, y + r.Next(0, 50 * (i + 1)));
141 | }
142 |
143 | Thread.Sleep(30);
144 | }
145 | }, TaskCreationOptions.LongRunning);
146 | }
147 |
148 | private Color GetRandomColor()
149 | {
150 | return Color.FromRgb((byte)r.Next(50, 255), (byte)r.Next(50, 255), (byte)r.Next(50, 255));
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("RealTimeGraphX.WPF.Demo")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("RealTimeGraphX.WPF.Demo")]
15 | [assembly: AssemblyCopyright("Copyright © 2018")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RealTimeGraphX.WPF.Demo.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RealTimeGraphX.WPF.Demo.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RealTimeGraphX.WPF.Demo.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/RealTimeGraphX.WPF.Demo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B822CBD9-1113-4668-85C9-22AA9C24CE60}
8 | WinExe
9 | RealTimeGraphX.WPF.Demo
10 | RealTimeGraphX.WPF.Demo
11 | v4.6.1
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 4.0
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | MSBuild:Compile
57 | Designer
58 |
59 |
60 |
61 |
62 |
63 | MSBuild:Compile
64 | Designer
65 |
66 |
67 | App.xaml
68 | Code
69 |
70 |
71 | MainWindow.xaml
72 | Code
73 |
74 |
75 | MSBuild:Compile
76 | Designer
77 |
78 |
79 |
80 |
81 |
82 | Code
83 |
84 |
85 | True
86 | True
87 | Resources.resx
88 |
89 |
90 | True
91 | Settings.settings
92 | True
93 |
94 |
95 | ResXFileCodeGenerator
96 | Resources.Designer.cs
97 |
98 |
99 | SettingsSingleFileGenerator
100 | Settings.Designer.cs
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | {6b9774f7-960d-438e-ad81-c6b9be328d50}
109 | RealTimeGraphX.WPF
110 |
111 |
112 | {61f001e1-6e17-4ca6-8f3a-8a11d7166815}
113 | RealTimeGraphX
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
55 |
56 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF.Demo/WpfGraphControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace RealTimeGraphX.WPF.Demo
17 | {
18 | public class WpfGraphControl : Control
19 | {
20 | ///
21 | /// Gets or sets the graph controller.
22 | ///
23 | public IGraphController Controller
24 | {
25 | get { return (IGraphController)GetValue(ControllerProperty); }
26 | set { SetValue(ControllerProperty, value); }
27 | }
28 | public static readonly DependencyProperty ControllerProperty =
29 | DependencyProperty.Register("Controller", typeof(IGraphController), typeof(WpfGraphControl), new PropertyMetadata(null));
30 |
31 | ///
32 | /// Gets or sets a value indicating whether to display a tool tip with the current cursor value.
33 | ///
34 | public bool DisplayToolTip
35 | {
36 | get { return (bool)GetValue(DisplayToolTipProperty); }
37 | set { SetValue(DisplayToolTipProperty, value); }
38 | }
39 | public static readonly DependencyProperty DisplayToolTipProperty =
40 | DependencyProperty.Register("DisplayToolTip", typeof(bool), typeof(WpfGraphControl), new PropertyMetadata(false));
41 |
42 | ///
43 | /// Gets or sets the string format for the X Axis.
44 | ///
45 | public String StringFormatX
46 | {
47 | get { return (String)GetValue(StringFormatXProperty); }
48 | set { SetValue(StringFormatXProperty, value); }
49 | }
50 | public static readonly DependencyProperty StringFormatXProperty =
51 | DependencyProperty.Register("StringFormatX", typeof(String), typeof(WpfGraphControl), new PropertyMetadata("0.0"));
52 |
53 | ///
54 | /// Gets or sets the string format for the Y Axis.
55 | ///
56 | public String StringFormatY
57 | {
58 | get { return (String)GetValue(StringFormatYProperty); }
59 | set { SetValue(StringFormatYProperty, value); }
60 | }
61 | public static readonly DependencyProperty StringFormatYProperty =
62 | DependencyProperty.Register("StringFormatY", typeof(String), typeof(WpfGraphControl), new PropertyMetadata("hh\\:mm\\:ss"));
63 |
64 |
65 | ///
66 | /// Initializes the class.
67 | ///
68 | static WpfGraphControl()
69 | {
70 | DefaultStyleKeyProperty.OverrideMetadata(typeof(WpfGraphControl), new FrameworkPropertyMetadata(typeof(WpfGraphControl)));
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/ExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace RealTimeGraphX.WPF
11 | {
12 | ///
13 | /// Contains a collection of extension methods.
14 | ///
15 | internal static class ExtensionMethods
16 | {
17 | ///
18 | /// Converts this WPF color to a GDI color.
19 | ///
20 | /// The color.
21 | ///
22 | internal static Color ToGdiColor(this System.Windows.Media.Color color)
23 | {
24 | return Color.FromArgb(color.A, color.R, color.G, color.B);
25 | }
26 |
27 | ///
28 | /// Converts this WPF brush to a GDI brush.
29 | ///
30 | /// The brush.
31 | ///
32 | internal static Brush ToGdiBrush(this System.Windows.Media.Brush brush)
33 | {
34 | if (brush.GetType() == typeof(System.Windows.Media.SolidColorBrush))
35 | {
36 | return new SolidBrush((brush as System.Windows.Media.SolidColorBrush).Color.ToGdiColor());
37 | }
38 | else if (brush.GetType() == typeof(System.Windows.Media.LinearGradientBrush))
39 | {
40 | System.Windows.Media.LinearGradientBrush b = brush as System.Windows.Media.LinearGradientBrush;
41 |
42 | double angle = Math.Atan2(b.EndPoint.Y - b.StartPoint.Y, b.EndPoint.X - b.StartPoint.X) * 180 / Math.PI;
43 |
44 | LinearGradientBrush gradient = new LinearGradientBrush(new Rectangle(0, 0, 200, 100), Color.Black, Color.Black, (float)angle);
45 |
46 | ColorBlend blend = new ColorBlend();
47 |
48 | List colors = new List();
49 | List offsets = new List();
50 |
51 | foreach (var stop in b.GradientStops)
52 | {
53 | colors.Add(stop.Color.ToGdiColor());
54 | offsets.Add((float)stop.Offset);
55 | }
56 |
57 | blend.Colors = colors.ToArray();
58 | blend.Positions = offsets.ToArray();
59 |
60 | gradient.InterpolationColors = blend;
61 |
62 | return gradient;
63 | }
64 | else
65 | {
66 | return new LinearGradientBrush(new PointF(0, 0), new Point(200, 100), Color.Black, Color.Black);
67 | }
68 | }
69 |
70 | ///
71 | /// Determines whether this dependency object is running in design mode.
72 | ///
73 | /// The object.
74 | internal static bool IsInDesignMode(this System.Windows.DependencyObject obj)
75 | {
76 | return (DesignerProperties.GetIsInDesignMode(obj));
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("RealTimeGraphX.WPF")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("RealTimeGraphX.WPF")]
15 | [assembly: AssemblyCopyright("Copyright © 2018")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly:ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RealTimeGraphX.WPF.Properties {
12 |
13 |
14 | ///
15 | /// A strongly-typed resource class, for looking up localized strings, etc.
16 | ///
17 | // This class was auto-generated by the StronglyTypedResourceBuilder
18 | // class via a tool like ResGen or Visual Studio.
19 | // To add or remove a member, edit your .ResX file then rerun ResGen
20 | // with the /str option, or rebuild your VS project.
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Resources {
25 |
26 | private static global::System.Resources.ResourceManager resourceMan;
27 |
28 | private static global::System.Globalization.CultureInfo resourceCulture;
29 |
30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
31 | internal Resources() {
32 | }
33 |
34 | ///
35 | /// Returns the cached ResourceManager instance used by this class.
36 | ///
37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
38 | internal static global::System.Resources.ResourceManager ResourceManager {
39 | get {
40 | if ((resourceMan == null)) {
41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RealTimeGraphX.WPF.Properties.Resources", typeof(Resources).Assembly);
42 | resourceMan = temp;
43 | }
44 | return resourceMan;
45 | }
46 | }
47 |
48 | ///
49 | /// Overrides the current thread's CurrentUICulture property for all
50 | /// resource lookups using this strongly typed resource class.
51 | ///
52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
53 | internal static global::System.Globalization.CultureInfo Culture {
54 | get {
55 | return resourceCulture;
56 | }
57 | set {
58 | resourceCulture = value;
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace RealTimeGraphX.WPF.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/RealTimeGraphX.WPF.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6B9774F7-960D-438E-AD81-C6B9BE328D50}
8 | library
9 | RealTimeGraphX.WPF
10 | RealTimeGraphX.WPF
11 | v4.6.1
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | bin\Release\RealTimeGraphX.WPF.xml
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 4.0
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | MSBuild:Compile
54 | Designer
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | Code
66 |
67 |
68 |
69 |
70 | Code
71 |
72 |
73 | True
74 | True
75 | Resources.resx
76 |
77 |
78 | True
79 | Settings.settings
80 | True
81 |
82 |
83 | ResXFileCodeGenerator
84 | Resources.Designer.cs
85 |
86 |
87 | SettingsSingleFileGenerator
88 | Settings.Designer.cs
89 |
90 |
91 |
92 |
93 |
94 | {61f001e1-6e17-4ca6-8f3a-8a11d7166815}
95 | RealTimeGraphX
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/RealTimeGraphX.WPF.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RealTimeGraphX.WPF
5 | 1.0.0
6 | RealTimeGraphX is a data type agnostic, high performance plotting library for WPF and UWP.
7 | RealTimeGraphX.WPF
8 | Roy Ben Shabat
9 | false
10 | MIT
11 | https://github.com/royben/RealTimeGraphX
12 | icon.png
13 | Chart Graph Plotting RealTime WPF UWP
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphAxisPanel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 |
9 | namespace RealTimeGraphX.WPF
10 | {
11 | ///
12 | /// Represents a panel that will align its children in an axis labels like arrangement.
13 | ///
14 | ///
15 | public class WpfGraphAxisPanel : Grid
16 | {
17 | ///
18 | /// Gets or sets the panel orientation.
19 | ///
20 | public Orientation Orientation
21 | {
22 | get { return (Orientation)GetValue(OrientationProperty); }
23 | set { SetValue(OrientationProperty, value); }
24 | }
25 | public static readonly DependencyProperty OrientationProperty =
26 | DependencyProperty.Register("Orientation", typeof(Orientation), typeof(WpfGraphAxisPanel), new PropertyMetadata(Orientation.Vertical));
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | public WpfGraphAxisPanel()
32 | {
33 | Loaded += VerticalAxisPanel_Loaded;
34 | }
35 |
36 | ///
37 | /// Handles the Loaded event of the VerticalAxisGrid control.
38 | ///
39 | /// The source of the event.
40 | /// The instance containing the event data.
41 | private void VerticalAxisPanel_Loaded(object sender, RoutedEventArgs e)
42 | {
43 | UpdatePanel();
44 | }
45 |
46 | ///
47 | /// Updates the panel.
48 | ///
49 | public void UpdatePanel()
50 | {
51 | RowDefinitions.Clear();
52 | ColumnDefinitions.Clear();
53 |
54 |
55 | if (Orientation == Orientation.Vertical)
56 | {
57 | for (int i = 0; i < InternalChildren.Count; i++)
58 | {
59 | FrameworkElement element = InternalChildren[i] as FrameworkElement;
60 |
61 | if (i < InternalChildren.Count - 1)
62 | {
63 | RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
64 | Grid.SetRow(element, i);
65 | element.VerticalAlignment = VerticalAlignment.Top;
66 |
67 | element.SizeChanged += (_, __) =>
68 | {
69 | element.Margin = new Thickness(0, (element.ActualHeight / 2) * -1, 0, 0);
70 | };
71 | }
72 | else
73 | {
74 | Grid.SetRow(element, i);
75 | element.VerticalAlignment = VerticalAlignment.Bottom;
76 |
77 | element.SizeChanged += (_, __) =>
78 | {
79 | element.Margin = new Thickness(0, 0, 0, (element.ActualHeight / 2) * -1);
80 | };
81 | }
82 | }
83 | }
84 | else
85 | {
86 | for (int i = 0; i < InternalChildren.Count; i++)
87 | {
88 | FrameworkElement element = InternalChildren[i] as FrameworkElement;
89 |
90 | if (i < InternalChildren.Count - 1)
91 | {
92 | ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
93 | Grid.SetColumn(element, i);
94 | element.HorizontalAlignment = HorizontalAlignment.Left;
95 |
96 | element.SizeChanged += (_, __) =>
97 | {
98 | element.Margin = new Thickness((element.ActualWidth / 2) * -1, 0, 0, 0);
99 | };
100 | }
101 | else
102 | {
103 | Grid.SetColumn(element, i);
104 | element.HorizontalAlignment = HorizontalAlignment.Right;
105 |
106 | element.SizeChanged += (_, __) =>
107 | {
108 | element.Margin = new Thickness(0, 0, (element.ActualWidth / 2) * -1, 0);
109 | };
110 | }
111 | }
112 | }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphAxisTickData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace RealTimeGraphX.WPF
10 | {
11 | ///
12 | /// Represents a graph axis data point tick value wrapper.
13 | ///
14 | public class WpfGraphAxisTickData : DependencyObject
15 | {
16 | ///
17 | /// Gets or sets a value indicating whether this tick is the first tick.
18 | ///
19 | public bool IsFirst
20 | {
21 | get { return (bool)GetValue(IsFirstProperty); }
22 | set { SetValue(IsFirstProperty, value); }
23 | }
24 | public static readonly DependencyProperty IsFirstProperty =
25 | DependencyProperty.Register("IsFirst", typeof(bool), typeof(WpfGraphAxisTickData), new PropertyMetadata(false));
26 |
27 | ///
28 | /// Gets or sets a value indicating whether this tick is the last tick.
29 | ///
30 | public bool IsLast
31 | {
32 | get { return (bool)GetValue(IsLastProperty); }
33 | set { SetValue(IsLastProperty, value); }
34 | }
35 | public static readonly DependencyProperty IsLastProperty =
36 | DependencyProperty.Register("IsLast", typeof(bool), typeof(WpfGraphAxisTickData), new PropertyMetadata(false));
37 |
38 | ///
39 | /// Gets or sets a value indicating whether this tick is not the first or last.
40 | ///
41 | public bool IsCenter
42 | {
43 | get { return !IsFirst && !IsLast; }
44 | }
45 |
46 | ///
47 | /// Gets or sets a value indicating whether this tick index is even.
48 | ///
49 | public bool IsEven
50 | {
51 | get { return (bool)GetValue(IsEvenProperty); }
52 | set { SetValue(IsEvenProperty, value); }
53 | }
54 | public static readonly DependencyProperty IsEvenProperty =
55 | DependencyProperty.Register("IsEven", typeof(bool), typeof(WpfGraphAxisTickData), new PropertyMetadata(false));
56 |
57 | ///
58 | /// Gets a value indicating whether this tick index is odd.
59 | ///
60 | public bool IsOdd
61 | {
62 | get { return !IsEven; }
63 | }
64 |
65 | ///
66 | /// Gets or sets the actual graph data point.
67 | ///
68 | public IGraphDataPoint Data
69 | {
70 | get { return (IGraphDataPoint)GetValue(DataProperty); }
71 | set { SetValue(DataProperty, value); }
72 | }
73 | public static readonly DependencyProperty DataProperty =
74 | DependencyProperty.Register("Data", typeof(IGraphDataPoint), typeof(WpfGraphAxisTickData), new PropertyMetadata(null));
75 |
76 | ///
77 | /// Gets or sets the display text.
78 | ///
79 | public String DisplayText
80 | {
81 | get { return (String)GetValue(DisplayTextProperty); }
82 | set { SetValue(DisplayTextProperty, value); }
83 | }
84 | public static readonly DependencyProperty DisplayTextProperty =
85 | DependencyProperty.Register("DisplayText", typeof(String), typeof(WpfGraphAxisTickData), new PropertyMetadata(null));
86 |
87 | ///
88 | /// Gets the Data Point value.
89 | ///
90 | public object Value
91 | {
92 | get
93 | {
94 | return Data != null ? Data.GetValue() : null;
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphComponentBase.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.EventArguments;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 |
10 | namespace RealTimeGraphX.WPF
11 | {
12 | ///
13 | /// Represents a graph component base class.
14 | ///
15 | ///
16 | public abstract class WpfGraphComponentBase : Control
17 | {
18 | ///
19 | /// Gets or sets the graph controller.
20 | ///
21 | public IGraphController Controller
22 | {
23 | get { return (IGraphController)GetValue(ControllerProperty); }
24 | set { SetValue(ControllerProperty, value); }
25 | }
26 | public static readonly DependencyProperty ControllerProperty =
27 | DependencyProperty.Register("Controller", typeof(IGraphController), typeof(WpfGraphComponentBase), new PropertyMetadata(null, (d, e) => (d as WpfGraphComponentBase).OnControllerChanged(e.OldValue as IGraphController, e.NewValue as IGraphController)));
28 |
29 | ///
30 | /// Called when the controller has changed.
31 | ///
32 | /// The old controller.
33 | /// The new controller.
34 | protected virtual void OnControllerChanged(IGraphController oldController, IGraphController newController)
35 | {
36 | if (oldController != null)
37 | {
38 | oldController.VirtualRangeChanged -= OnVirtualRangeChanged;
39 | }
40 |
41 | if (newController != null)
42 | {
43 | newController.VirtualRangeChanged += OnVirtualRangeChanged;
44 | }
45 | }
46 |
47 | ///
48 | /// Handles the event.
49 | ///
50 | /// The source of the event.
51 | /// The event arguments.
52 | protected virtual void OnVirtualRangeChanged(object sender, RangeChangedEventArgs e)
53 | {
54 | //Optional
55 | }
56 |
57 | ///
58 | /// Invokes the specified method on the component dispatcher.
59 | ///
60 | /// The action.
61 | protected void InvokeUI(Action action)
62 | {
63 | Dispatcher.BeginInvoke(action);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Media;
7 |
8 | namespace RealTimeGraphX.WPF
9 | {
10 | ///
11 | /// Represents a WPF graph controller .
12 | ///
13 | /// The type of the x data point.
14 | /// The type of the y data point.
15 | ///
16 | public class WpfGraphController : GraphController
17 | where TXDataPoint : GraphDataPoint
18 | where TYDataPoint : GraphDataPoint
19 | {
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphDataSeries.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Media;
7 |
8 | namespace RealTimeGraphX.WPF
9 | {
10 | ///
11 | /// Represents a WPF data series .
12 | ///
13 | ///
14 | ///
15 | public class WpfGraphDataSeries : GraphObject, IGraphDataSeries
16 | {
17 | #region Internal Properties
18 |
19 | ///
20 | /// Gets the GDI stroke color.
21 | ///
22 | internal System.Drawing.Color GdiStroke { get; private set; }
23 |
24 | ///
25 | /// Gets the GDI fill brush.
26 | ///
27 | internal System.Drawing.Brush GdiFill { get; private set; }
28 |
29 | ///
30 | /// Gets or sets the GDI pen.
31 | ///
32 | internal System.Drawing.Pen GdiPen { get; set; }
33 |
34 | #endregion
35 |
36 | private String _name;
37 | ///
38 | /// Gets or sets the series name.
39 | ///
40 | public String Name
41 | {
42 | get { return _name; }
43 | set { _name = value; RaisePropertyChangedAuto(); }
44 | }
45 |
46 | private float _strokeThickness;
47 | ///
48 | /// Gets or sets the stroke thickness.
49 | ///
50 | public float StrokeThickness
51 | {
52 | get
53 | {
54 | return _strokeThickness;
55 | }
56 | set
57 | {
58 | _strokeThickness = value;
59 | GdiPen = new System.Drawing.Pen(GdiStroke, _strokeThickness);
60 | RaisePropertyChangedAuto();
61 | }
62 | }
63 |
64 | private bool _isVisible;
65 | ///
66 | /// Gets or sets a value indicating whether this series should be visible.
67 | ///
68 | public bool IsVisible
69 | {
70 | get { return _isVisible; }
71 | set { _isVisible = value; RaisePropertyChangedAuto(); }
72 | }
73 |
74 | private Color _stroke;
75 | ///
76 | /// Gets or sets the series stroke color.
77 | ///
78 | public Color Stroke
79 | {
80 | get { return _stroke; }
81 | set
82 | {
83 | _stroke = value;
84 | RaisePropertyChangedAuto();
85 |
86 | if (_stroke != null)
87 | {
88 | GdiStroke = _stroke.ToGdiColor();
89 | GdiPen = new System.Drawing.Pen(GdiStroke, StrokeThickness);
90 | }
91 | else
92 | {
93 | GdiStroke = System.Drawing.Color.Transparent;
94 | }
95 | }
96 | }
97 |
98 | private Brush _fill;
99 | ///
100 | /// Gets or sets the series fill brush.
101 | ///
102 | public Brush Fill
103 | {
104 | get { return _fill; }
105 | set
106 | {
107 | _fill = value;
108 | RaisePropertyChangedAuto();
109 |
110 | if (_fill != null)
111 | {
112 | GdiFill = _fill.ToGdiBrush();
113 | }
114 | else
115 | {
116 | GdiFill = null;
117 | }
118 | }
119 | }
120 |
121 | ///
122 | /// Initializes a new instance of the class.
123 | ///
124 | public WpfGraphDataSeries()
125 | {
126 | StrokeThickness = 1;
127 | IsVisible = true;
128 | Stroke = Colors.DodgerBlue;
129 | }
130 |
131 | ///
132 | /// Gets or sets a value indicating whether to fill the series.
133 | ///
134 | public bool UseFill
135 | {
136 | get { return Fill != null; }
137 | }
138 |
139 | private object _currentValue;
140 | ///
141 | /// Gets the current value.
142 | ///
143 | public object CurrentValue
144 | {
145 | get { return _currentValue; }
146 | set { _currentValue = value; RaisePropertyChangedAuto(); }
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/WpfGraphGridLines.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Windows;
4 |
5 | namespace RealTimeGraphX.WPF
6 | {
7 | ///
8 | /// Represents a graph grid lines component.
9 | ///
10 | ///
11 | public class WpfGraphGridLines : WpfGraphComponentBase
12 | {
13 | ///
14 | /// Gets or sets the number of grid rows.
15 | ///
16 | public int Rows
17 | {
18 | get { return (int)GetValue(RowsProperty); }
19 | set { SetValue(RowsProperty, value); }
20 | }
21 | public static readonly DependencyProperty RowsProperty =
22 | DependencyProperty.Register("Rows", typeof(int), typeof(WpfGraphGridLines), new PropertyMetadata(8, (d, e) => (d as WpfGraphGridLines).UpdateGridLines()));
23 |
24 | ///
25 | /// Gets or sets the number of grid columns.
26 | ///
27 | public int Columns
28 | {
29 | get { return (int)GetValue(ColumnsProperty); }
30 | set { SetValue(ColumnsProperty, value); }
31 | }
32 | public static readonly DependencyProperty ColumnsProperty =
33 | DependencyProperty.Register("Columns", typeof(int), typeof(WpfGraphGridLines), new PropertyMetadata(8, (d, e) => (d as WpfGraphGridLines).UpdateGridLines()));
34 |
35 | ///
36 | /// Gets or sets the vertical items.
37 | ///
38 | internal IEnumerable VerticalItems
39 | {
40 | get { return (IEnumerable)GetValue(VerticalItemsProperty); }
41 | set { SetValue(VerticalItemsProperty, value); }
42 | }
43 | internal static readonly DependencyProperty VerticalItemsProperty =
44 | DependencyProperty.Register("VerticalItems", typeof(IEnumerable), typeof(WpfGraphGridLines), new PropertyMetadata(null));
45 |
46 | ///
47 | /// Gets or sets the horizontal items.
48 | ///
49 | internal IEnumerable HorizontalItems
50 | {
51 | get { return (IEnumerable)GetValue(HorizontalItemsProperty); }
52 | set { SetValue(HorizontalItemsProperty, value); }
53 | }
54 | internal static readonly DependencyProperty HorizontalItemsProperty =
55 | DependencyProperty.Register("HorizontalItems", typeof(IEnumerable), typeof(WpfGraphGridLines), new PropertyMetadata(null));
56 |
57 | ///
58 | /// Initializes the class.
59 | ///
60 | static WpfGraphGridLines()
61 | {
62 | DefaultStyleKeyProperty.OverrideMetadata(typeof(WpfGraphGridLines), new FrameworkPropertyMetadata(typeof(WpfGraphGridLines)));
63 | }
64 |
65 | ///
66 | /// Initializes a new instance of the class.
67 | ///
68 | public WpfGraphGridLines()
69 | {
70 | Loaded += GridLines_Loaded;
71 | }
72 |
73 | ///
74 | /// Handles the Loaded event of the GridLines control.
75 | ///
76 | /// The source of the event.
77 | /// The instance containing the event data.
78 | private void GridLines_Loaded(object sender, RoutedEventArgs e)
79 | {
80 | UpdateGridLines();
81 | }
82 |
83 | ///
84 | /// Updates the grid lines.
85 | ///
86 | private void UpdateGridLines()
87 | {
88 | VerticalItems = Enumerable.Range(0, Rows).ToList();
89 | HorizontalItems = Enumerable.Range(0, Columns).ToList();
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/RealTimeGraphX.WPF/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/RealTimeGraphX.WPF/icon.png
--------------------------------------------------------------------------------
/RealTimeGraphX/DataPoints/DoubleDataPoint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RealTimeGraphX.DataPoints
8 | {
9 | ///
10 | /// Represents a graph value data point.
11 | ///
12 | ///
13 | public class DoubleDataPoint : GraphDataPoint
14 | {
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | public DoubleDataPoint() : base()
19 | {
20 |
21 | }
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | /// The value.
27 | public DoubleDataPoint(double value) : base(value)
28 | {
29 |
30 | }
31 |
32 | ///
33 | /// Performs an implicit conversion from to .
34 | ///
35 | /// The value.
36 | ///
37 | /// The result of the conversion.
38 | ///
39 | public static implicit operator DoubleDataPoint(double value)
40 | {
41 | return new DoubleDataPoint(value);
42 | }
43 |
44 | ///
45 | /// Implements the operator -.
46 | ///
47 | /// a.
48 | /// The b.
49 | ///
50 | /// The result of the operator.
51 | ///
52 | public static DoubleDataPoint operator -(DoubleDataPoint a, DoubleDataPoint b)
53 | {
54 | return new DoubleDataPoint(a.Value - b.Value);
55 | }
56 |
57 | ///
58 | /// Implements the operator +.
59 | ///
60 | /// a.
61 | /// The b.
62 | ///
63 | /// The result of the operator.
64 | ///
65 | public static DoubleDataPoint operator +(DoubleDataPoint a, DoubleDataPoint b)
66 | {
67 | return new DoubleDataPoint(a.Value + b.Value);
68 | }
69 |
70 | ///
71 | /// Sums the value of this instance with another instance value and returns the result.
72 | ///
73 | /// The other instance.
74 | ///
75 | public override IGraphDataPoint Add(IGraphDataPoint other)
76 | {
77 | return new DoubleDataPoint(this.Value + (other as DoubleDataPoint).Value);
78 | }
79 |
80 | ///
81 | /// Subtract the value of another instance from this instance and returns the result.
82 | ///
83 | /// The other instance.
84 | ///
85 | public override IGraphDataPoint Subtract(IGraphDataPoint other)
86 | {
87 | return new DoubleDataPoint(this.Value - (other as DoubleDataPoint).Value);
88 | }
89 |
90 | ///
91 | /// Multiplies the value of this instance with another instance value and returns the result.
92 | ///
93 | /// The other instance.
94 | ///
95 | public override IGraphDataPoint Multiply(IGraphDataPoint other)
96 | {
97 | return new DoubleDataPoint(this.Value * (other as DoubleDataPoint).Value);
98 | }
99 |
100 | ///
101 | /// Divides the value of this instance with another instance value and returns the result.
102 | ///
103 | /// The other instance.
104 | ///
105 | public override IGraphDataPoint Divide(IGraphDataPoint other)
106 | {
107 | return new DoubleDataPoint(this.Value / (other as DoubleDataPoint).Value);
108 | }
109 |
110 | ///
111 | /// Returns the percentage value of this instance between the specified minimum and maximum values.
112 | ///
113 | /// The minimum.
114 | /// The maximum.
115 | ///
116 | public override double ComputeRelativePosition(IGraphDataPoint min, IGraphDataPoint max)
117 | {
118 | DoubleDataPoint dMin = min as DoubleDataPoint;
119 | DoubleDataPoint dMax = max as DoubleDataPoint;
120 |
121 | var result = ((Value - dMin) * 100) / (dMax - dMin);
122 |
123 | return double.IsNaN(result) || double.IsInfinity(result) ? dMin.Value : result;
124 | }
125 |
126 | ///
127 | /// Returns the absolute value of the specified percentage value between the specified minimum and maximum values.
128 | ///
129 | /// The minimum.
130 | /// The maximum.
131 | /// The percentage.
132 | ///
133 | public override IGraphDataPoint ComputeAbsolutePosition(IGraphDataPoint min, IGraphDataPoint max, double percentage)
134 | {
135 | double minimum = (double)min.GetValue();
136 | double maximum = (double)max.GetValue();
137 |
138 | return new DoubleDataPoint(minimum + (maximum - minimum) * percentage);
139 | }
140 |
141 | ///
142 | /// Creates a range of values from the specified minimum and maximum.
143 | ///
144 | /// The minimum.
145 | /// The maximum.
146 | /// The count.
147 | ///
148 | public override IEnumerable CreateRange(IGraphDataPoint min, IGraphDataPoint max, int count)
149 | {
150 | double minimum = (double)min.GetValue();
151 | double maximum = (double)max.GetValue();
152 |
153 | return Enumerable.Range(0, count).
154 | Select(i => minimum + (maximum - minimum) * ((double)i / (count - 1))).
155 | Select(x => new DoubleDataPoint(x));
156 | }
157 |
158 | ///
159 | /// Returns a formated string of this data point.
160 | ///
161 | /// The format.
162 | ///
163 | public override string ToString(string format)
164 | {
165 | return Value.ToString(format);
166 | }
167 |
168 | ///
169 | /// Parses the specified value and returns a new instance of data point.
170 | ///
171 | /// The value.
172 | ///
173 | public override IGraphDataPoint Parse(string value)
174 | {
175 | return new DoubleDataPoint(double.Parse(value));
176 | }
177 |
178 | ///
179 | /// Return the default margins for this data point type.
180 | /// and .
181 | ///
182 | ///
183 | protected override DoubleDataPoint OnGetDefaultMargins()
184 | {
185 | return new DoubleDataPoint(0.5);
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/RealTimeGraphX/EventArguments/RangeChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RealTimeGraphX.EventArguments
8 | {
9 | ///
10 | /// Represents a graph range change event arguments.
11 | ///
12 | ///
13 | public class RangeChangedEventArgs : EventArgs
14 | {
15 | ///
16 | /// Gets or sets the minimum x value.
17 | ///
18 | public GraphDataPoint MinimumX { get; set; }
19 |
20 | ///
21 | /// Gets or sets the maximum x value.
22 | ///
23 | public GraphDataPoint MaximumX { get; set; }
24 |
25 | ///
26 | /// Gets or sets the minimum y value.
27 | ///
28 | public GraphDataPoint MinimumY { get; set; }
29 |
30 | ///
31 | /// Gets or sets the maximum y value.
32 | ///
33 | public GraphDataPoint MaximumY { get; set; }
34 |
35 | ///
36 | /// Initializes a new instance of the class.
37 | ///
38 | public RangeChangedEventArgs()
39 | {
40 |
41 | }
42 |
43 | ///
44 | /// Initializes a new instance of the class.
45 | ///
46 | /// The minimum x value.
47 | /// The maximum x value.
48 | /// The minimum y value.
49 | /// The maximum y value.
50 | public RangeChangedEventArgs(GraphDataPoint minimumX, GraphDataPoint maximumX,GraphDataPoint minimumY,GraphDataPoint maximumY) : this()
51 | {
52 | MinimumX = minimumX;
53 | MaximumX = maximumX;
54 | MinimumY = minimumY;
55 | MaximumY = maximumY;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows.Input;
5 |
6 | namespace RealTimeGraphX
7 | {
8 | ///
9 | /// Represents a graph relay command.
10 | ///
11 | ///
12 | public class GraphCommand : ICommand
13 | {
14 | private Action _action;
15 | private Func _canExecute;
16 |
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | /// The action.
21 | /// The can execute.
22 | public GraphCommand(Action action, Func canExecute)
23 | {
24 | _action = action;
25 | _canExecute = canExecute;
26 | }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The action.
32 | public GraphCommand(Action action) : this(action, null)
33 | {
34 |
35 | }
36 |
37 | ///
38 | /// Defines the method that determines whether the command can execute in its current state.
39 | ///
40 | /// Data used by the command. If the command does not require data to be passed, this object can be set to null.
41 | ///
42 | /// true if this command can be executed; otherwise, false.
43 | ///
44 | public bool CanExecute(object parameter)
45 | {
46 | if (_canExecute != null)
47 | {
48 | return _canExecute();
49 | }
50 |
51 | return true;
52 | }
53 |
54 | ///
55 | /// Defines the method to be called when the command is invoked.
56 | ///
57 | /// Data used by the command. If the command does not require data to be passed, this object can be set to null.
58 | public void Execute(object parameter)
59 | {
60 | _action();
61 | }
62 |
63 | ///
64 | /// Raises the can execute changed event.
65 | ///
66 | public void RaiseCanExecuteChanged()
67 | {
68 | CanExecuteChanged?.Invoke(this, new EventArgs());
69 | }
70 |
71 | ///
72 | /// Occurs when changes occur that affect whether or not the command should execute.
73 | ///
74 | ///
75 | public event EventHandler CanExecuteChanged;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphDataPointHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RealTimeGraphX
8 | {
9 | ///
10 | /// Represents an helper class.
11 | ///
12 | public static class GraphDataPointHelper
13 | {
14 | ///
15 | /// Returns the absolute value of the specified percentage value between the specified minimum and maximum values.
16 | ///
17 | /// The minimum.
18 | /// The maximum.
19 | /// The percentage.
20 | ///
21 | public static T ComputeAbsolutePosition(T min, T max, double percentage) where T : class, IGraphDataPoint
22 | {
23 | return (Activator.CreateInstance(min.GetType()) as T).ComputeAbsolutePosition(min, max, percentage) as T;
24 | }
25 |
26 | ///
27 | /// Creates a range of values from the specified minimum and maximum.
28 | ///
29 | /// The minimum.
30 | /// The maximum.
31 | /// The count.
32 | ///
33 | public static IEnumerable CreateRange(IGraphDataPoint min, IGraphDataPoint max, int count) where T : class, IGraphDataPoint
34 | {
35 | return (Activator.CreateInstance(min.GetType()) as T).CreateRange(min, max, count) as IEnumerable;
36 | }
37 |
38 | ///
39 | /// Initializes a new instance of the specified type.
40 | ///
41 | ///
42 | ///
43 | public static T Init() where T : class, IGraphDataPoint
44 | {
45 | return Activator.CreateInstance(typeof(T)) as T;
46 | }
47 |
48 | ///
49 | /// Gets the default margins for the specified IGraphDataPoint.
50 | ///
51 | ///
52 | ///
53 | public static T GetDefaultMargins() where T : class, IGraphDataPoint
54 | {
55 | return Init().GetDefaultMargins() as T;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphDataPointTypeConverter.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.DataPoints;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Globalization;
6 | using System.Text;
7 |
8 | namespace RealTimeGraphX
9 | {
10 | ///
11 | /// Represents the type converter.
12 | ///
13 | public class GraphDataPointTypeConverter : TypeConverter
14 | {
15 | private IGraphDataPoint _instance;
16 |
17 | ///
18 | /// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
19 | ///
20 | /// An that provides a format context.
21 | /// A that represents the type you want to convert from.
22 | ///
23 | /// true if this converter can perform the conversion; otherwise, false.
24 | ///
25 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
26 | {
27 | return sourceType == typeof(String);
28 | }
29 |
30 | ///
31 | /// Converts the given object to the type of this converter, using the specified context and culture information.
32 | ///
33 | /// An that provides a format context.
34 | /// The to use as the current culture.
35 | /// The to convert.
36 | ///
37 | /// An that represents the converted value.
38 | ///
39 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
40 | {
41 | if (value != null && _instance != null)
42 | {
43 | try
44 | {
45 | return _instance.Parse(value.ToString());
46 | }
47 | catch {}
48 | }
49 |
50 | return _instance;
51 | }
52 |
53 | ///
54 | /// Returns whether this converter can convert the object to the specified type, using the specified context.
55 | ///
56 | /// An that provides a format context.
57 | /// A that represents the type you want to convert to.
58 | ///
59 | /// true if this converter can perform the conversion; otherwise, false.
60 | ///
61 | public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
62 | {
63 | return destinationType == typeof(String);
64 | }
65 |
66 | ///
67 | /// Converts the given value object to the specified type, using the specified context and culture information.
68 | ///
69 | /// An that provides a format context.
70 | /// A . If null is passed, the current culture is assumed.
71 | /// The to convert.
72 | /// The to convert the value parameter to.
73 | ///
74 | /// An that represents the converted value.
75 | ///
76 | public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
77 | {
78 | _instance = value as IGraphDataPoint;
79 | return value != null ? value.ToString() : null;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphDataQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace RealTimeGraphX
10 | {
11 | ///
12 | /// Represents a blocking concurrent queue for graph data consumption.
13 | ///
14 | ///
15 | ///
16 | public class GraphDataQueue : BlockingCollection
17 | {
18 | ///
19 | /// Initializes a new instance of the GraphDataQueue, Use Add and TryAdd for Enqueue and TryEnqueue and Take and TryTake for Dequeue and TryDequeue functionality
20 | ///
21 | public GraphDataQueue()
22 | : base(new ConcurrentQueue())
23 | {
24 | }
25 |
26 | ///
27 | /// Initializes a new instance of the GraphDataQueue, Use Add and TryAdd for Enqueue and TryEnqueue and Take and TryTake for Dequeue and TryDequeue functionality
28 | ///
29 | ///
30 | public GraphDataQueue(int maxSize)
31 | : base(new ConcurrentQueue(), maxSize)
32 | {
33 | }
34 |
35 | ///
36 | /// Enqueues the specified item.
37 | ///
38 | /// The item.
39 | public void BlockEnqueue(T item)
40 | {
41 | Add(item);
42 | }
43 |
44 | ///
45 | /// Blocks until an item is available for dequeuing.
46 | ///
47 | ///
48 | public T BlockDequeue()
49 | {
50 | return Take();
51 | }
52 |
53 | ///
54 | /// Blocks until an item is available for dequeuing.
55 | ///
56 | /// The cancellation token.
57 | ///
58 | public T BlockDequeue(CancellationToken cancellationToken)
59 | {
60 | return Take(cancellationToken);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Runtime.CompilerServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 |
10 | namespace RealTimeGraphX
11 | {
12 | ///
13 | /// Represents an supported graph object.
14 | ///
15 | ///
16 | public abstract class GraphObject : INotifyPropertyChanged
17 | {
18 | ///
19 | /// Occurs when a property value changes.
20 | ///
21 | [field: NonSerialized]
22 | public event PropertyChangedEventHandler PropertyChanged;
23 |
24 | ///
25 | /// Raises the property changed event.
26 | ///
27 | /// Name of the property.
28 | protected virtual void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
29 | {
30 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
31 | }
32 |
33 | ///
34 | /// Raises the property changed event.
35 | ///
36 | /// Name of the property.
37 | protected virtual void RaisePropertyChanged(String propName)
38 | {
39 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphRange.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RealTimeGraphX
8 | {
9 | ///
10 | /// Represents a graph x/y data points boundaries.
11 | ///
12 | public interface IGraphRange : IGraphComponent
13 | {
14 | ///
15 | /// Gets or sets the maximum x value.
16 | ///
17 | GraphDataPoint MaximumX { get; set; }
18 |
19 | ///
20 | /// Gets or sets the minimum x value.
21 | ///
22 | GraphDataPoint MinimumY { get; set; }
23 |
24 | ///
25 | /// Gets or sets the maximum y value.
26 | ///
27 | GraphDataPoint MaximumY { get; set; }
28 |
29 | ///
30 | /// Gets or sets a value indicating whether to automatically adjust the graph and according to the current effective data points.
31 | ///
32 | bool AutoY { get; set; }
33 |
34 | ///
35 | /// Gets or sets the fallback mode for when AutoY is set to true and all Y values are equal so to retain a perspective.
36 | ///
37 | GraphRangeAutoYFallBackMode AutoYFallbackMode { get; set; }
38 |
39 | ///
40 | /// Gets or sets the AutoY fallback margins when is set to Margins.
41 | ///
42 | GraphDataPoint AutoYFallBackMargins { get; set; }
43 | }
44 |
45 | ///
46 | /// Represents a graph X/Y range boundaries.
47 | ///
48 | /// Type of x-axis data point.
49 | /// Type of y-axis data point.
50 | ///
51 | public class GraphRange : GraphObject, IGraphRange where XDataPoint : GraphDataPoint where YDataPoint : GraphDataPoint
52 | {
53 | private XDataPoint _maximumX;
54 | ///
55 | /// Gets or sets the maximum x value.
56 | ///
57 | public XDataPoint MaximumX
58 | {
59 | get { return _maximumX; }
60 | set { _maximumX = value; RaisePropertyChangedAuto(); }
61 | }
62 |
63 | private YDataPoint _minimumY;
64 | ///
65 | /// Gets or sets the minimum x value.
66 | ///
67 | public YDataPoint MinimumY
68 | {
69 | get { return _minimumY; }
70 | set { _minimumY = value; RaisePropertyChangedAuto(); }
71 | }
72 |
73 | private YDataPoint _maximumY;
74 | ///
75 | /// Gets or sets the maximum y value.
76 | ///
77 | public YDataPoint MaximumY
78 | {
79 | get { return _maximumY; }
80 | set { _maximumY = value; RaisePropertyChangedAuto(); }
81 | }
82 |
83 | private bool _autoY;
84 | ///
85 | /// Gets or sets a value indicating whether to automatically adjust the graph and according to the current visible data points.
86 | ///
87 | public bool AutoY
88 | {
89 | get { return _autoY; }
90 | set { _autoY = value; RaisePropertyChangedAuto(); }
91 | }
92 |
93 | private GraphRangeAutoYFallBackMode _autoYFallbackMode;
94 | ///
95 | /// Gets or sets the fallback mode for when AutoY is set to true and all Y values are equal so to retain a perspective.
96 | ///
97 | public GraphRangeAutoYFallBackMode AutoYFallbackMode
98 | {
99 | get { return _autoYFallbackMode; }
100 | set { _autoYFallbackMode = value; RaisePropertyChangedAuto(); }
101 | }
102 |
103 | private YDataPoint _autoYFallbackMargins;
104 | ///
105 | /// Gets or sets the margins for when is set to .
106 | ///
107 | public YDataPoint AutoYFallbackMargins
108 | {
109 | get { return _autoYFallbackMargins; }
110 | set { _autoYFallbackMargins = value; RaisePropertyChangedAuto(); }
111 | }
112 |
113 | ///
114 | /// Initializes a new instance of the class.
115 | ///
116 | public GraphRange()
117 | {
118 | MinimumY = GraphDataPointHelper.Init();
119 | MaximumX = GraphDataPointHelper.Init();
120 | MaximumY = GraphDataPointHelper.Init();
121 | AutoYFallbackMode = GraphRangeAutoYFallBackMode.Margins;
122 | AutoYFallbackMargins = GraphDataPointHelper.GetDefaultMargins();
123 | }
124 |
125 | ///
126 | /// Gets or sets the maximum x value.
127 | ///
128 | GraphDataPoint IGraphRange.MaximumX
129 | {
130 | get
131 | {
132 | return MaximumX;
133 | }
134 | set
135 | {
136 | MaximumX = (XDataPoint)value;
137 | }
138 | }
139 |
140 | ///
141 | /// Gets or sets the minimum x value.
142 | ///
143 | GraphDataPoint IGraphRange.MinimumY
144 | {
145 | get
146 | {
147 | return MinimumY;
148 | }
149 | set
150 | {
151 | MinimumY = (YDataPoint)value;
152 | }
153 | }
154 |
155 | ///
156 | /// Gets or sets the maximum y value.
157 | ///
158 | GraphDataPoint IGraphRange.MaximumY
159 | {
160 | get
161 | {
162 | return MaximumY;
163 | }
164 | set
165 | {
166 | MaximumY = (YDataPoint)value;
167 | }
168 | }
169 |
170 | ///
171 | /// Gets or sets the fallback mode for when AutoY is set to true and all Y values are equal so to retain a perspective.
172 | ///
173 | GraphDataPoint IGraphRange.AutoYFallBackMargins
174 | {
175 | get
176 | {
177 | return AutoYFallbackMargins;
178 | }
179 | set
180 | {
181 | AutoYFallbackMargins = (YDataPoint)value;
182 | }
183 | }
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphRangeAutoYFallBackMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace RealTimeGraphX
6 | {
7 | ///
8 | /// Represents an AutoY fall-back mode for then all Y values are equal.
9 | ///
10 | public enum GraphRangeAutoYFallBackMode
11 | {
12 | ///
13 | /// Create fake min/max margins of 0.5 from the Y value.
14 | ///
15 | Margins,
16 | ///
17 | /// Fallback to and .
18 | ///
19 | MinMax,
20 | ///
21 | /// Do nothing when all Y values are equal.
22 | ///
23 | None,
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Drawing;
4 |
5 | namespace RealTimeGraphX
6 | {
7 | ///
8 | /// Represents an base class.
9 | ///
10 | /// The type of the data series.
11 | ///
12 | ///
13 | public abstract class GraphRenderer : GraphObject, IGraphRenderer where TDataSeries : IGraphDataSeries
14 | {
15 | ///
16 | /// Converts the specified relative x position to a graph surface absolute position.
17 | ///
18 | /// The target surface.
19 | /// The relative x position.
20 | ///
21 | protected virtual float ConvertXValueToRendererValue(IGraphSurface surface, double x)
22 | {
23 | return (float)(x * surface.GetSize().Width / 100);
24 | }
25 |
26 | ///
27 | /// Converts the specified relative y position to a graph surface absolute position.
28 | ///
29 | /// The surface.
30 | /// The relative y position.
31 | ///
32 | protected virtual float ConvertYValueToRendererValue(IGraphSurface surface, double y)
33 | {
34 | return (float)(surface.GetSize().Height - (y * surface.GetSize().Height / 100));
35 | }
36 |
37 | ///
38 | /// Arranges the series of data points and returns a series of drawing points.
39 | ///
40 | /// The target graph surface.
41 | /// The instance of the current rendered data series.
42 | /// Instance of graph range.
43 | /// Collection of x coordinates.
44 | /// Collection of y coordinates.
45 | /// The minimum x coordinates value.
46 | /// The maximum x coordinates value.
47 | /// The minimum y coordinates value.
48 | /// The maximum y coordinates value.
49 | ///
50 | public abstract IEnumerable Render(IGraphSurface surface, TDataSeries series, IGraphRange range, List xx, List yy, GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY);
51 |
52 | ///
53 | /// Draws the specified data series points on the target surface.
54 | ///
55 | /// The target graph surface.
56 | /// The instance of the current rendered data series.
57 | /// The collection of the current data series drawing points.
58 | /// The index of the current data series within the collection of data series.
59 | /// The length of the data series collection.
60 | public abstract void Draw(IGraphSurface surface, TDataSeries series, IEnumerable points, int index, int count);
61 |
62 | ///
63 | /// Gets a closed polygon version of the specified drawing points.
64 | ///
65 | /// The target surface.
66 | /// The drawing points.
67 | ///
68 | protected virtual IEnumerable GetFillPoints(IGraphSurface surface, IEnumerable points)
69 | {
70 | List closed = points.ToList();
71 | closed.Add(new PointF(points.Last().X, surface.GetSize().Width));
72 | closed.Add(new PointF(0, surface.GetSize().Height));
73 | return closed.ToArray();
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/RealTimeGraphX/GraphTransform.cs:
--------------------------------------------------------------------------------
1 | namespace RealTimeGraphX
2 | {
3 | ///
4 | /// Represents a graph transformation.
5 | ///
6 | public class GraphTransform
7 | {
8 | ///
9 | /// Gets or sets the horizontal scale factor.
10 | ///
11 | public float ScaleX { get; set; }
12 |
13 | ///
14 | /// Gets or sets the vertical scale factor.
15 | ///
16 | public float ScaleY { get; set; }
17 |
18 | ///
19 | /// Gets or sets the horizontal translate transformation.
20 | ///
21 | public float TranslateX { get; set; }
22 |
23 | ///
24 | /// Gets or sets the vertical translate transformation.
25 | ///
26 | public float TranslateY { get; set; }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | public GraphTransform()
32 | {
33 | ScaleX = 1;
34 | ScaleY = 1;
35 | TranslateX = 0;
36 | TranslateY = 0;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/RealTimeGraphX/IGraphComponent.cs:
--------------------------------------------------------------------------------
1 | namespace RealTimeGraphX
2 | {
3 | ///
4 | /// Represents a RealTimeGraphX component.
5 | ///
6 | public interface IGraphComponent
7 | {
8 |
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/RealTimeGraphX/IGraphDataPoint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 |
5 | namespace RealTimeGraphX
6 | {
7 | ///
8 | /// Represents a graph X or Y data point that can be pushed to a Graph Controller .
9 | ///
10 | ///
11 | [TypeConverter(typeof(GraphDataPointTypeConverter))]
12 | public interface IGraphDataPoint : IComparable
13 | {
14 | ///
15 | /// Sums the value of this instance with another instance value and returns the result.
16 | ///
17 | /// The other instance.
18 | ///
19 | IGraphDataPoint Add(IGraphDataPoint other);
20 |
21 | ///
22 | /// Subtract the value of another instance from this instance and returns the result.
23 | ///
24 | /// The other instance.
25 | ///
26 | IGraphDataPoint Subtract(IGraphDataPoint other);
27 |
28 | ///
29 | /// Multiplies the value of this instance with another instance value and returns the result.
30 | ///
31 | /// The other instance.
32 | ///
33 | IGraphDataPoint Multiply(IGraphDataPoint other);
34 |
35 | ///
36 | /// Divides the value of this instance with another instance value and returns the result.
37 | ///
38 | /// The other instance.
39 | ///
40 | IGraphDataPoint Divide(IGraphDataPoint other);
41 |
42 | ///
43 | /// Creates a range of values from the specified minimum and maximum.
44 | ///
45 | /// The minimum.
46 | /// The maximum.
47 | /// The count.
48 | ///
49 | IEnumerable CreateRange(IGraphDataPoint min, IGraphDataPoint max, int count);
50 |
51 | ///
52 | /// Returns the percentage value of this instance between the specified minimum and maximum values.
53 | ///
54 | /// The minimum.
55 | /// The maximum.
56 | ///
57 | double ComputeRelativePosition(IGraphDataPoint min, IGraphDataPoint max);
58 |
59 | ///
60 | /// Returns the absolute value of the specified percentage value between the specified minimum and maximum values.
61 | ///
62 | /// The minimum.
63 | /// The maximum.
64 | /// The percentage.
65 | ///
66 | IGraphDataPoint ComputeAbsolutePosition(IGraphDataPoint min, IGraphDataPoint max, double percentage);
67 |
68 | ///
69 | /// Gets the encapsulated value.
70 | ///
71 | ///
72 | object GetValue();
73 |
74 | ///
75 | /// Sets the encapsulated value.
76 | ///
77 | /// The value.
78 | void SetValue(object value);
79 |
80 | ///
81 | /// Returns a formated string of this data point.
82 | ///
83 | /// The format.
84 | ///
85 | String ToString(String format);
86 |
87 | ///
88 | /// Parses the specified value.
89 | ///
90 | /// The value.
91 | ///
92 | IGraphDataPoint Parse(String value);
93 |
94 | ///
95 | /// Gets the default margins for this data point type.
96 | /// and .
97 | ///
98 | ///
99 | IGraphDataPoint GetDefaultMargins();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/RealTimeGraphX/IGraphDataSeries.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RealTimeGraphX
4 | {
5 | ///
6 | /// Represents a graph data series.
7 | ///
8 | ///
9 | public interface IGraphDataSeries : IGraphComponent
10 | {
11 | ///
12 | /// Gets or sets the series name.
13 | ///
14 | String Name { get; set; }
15 |
16 | ///
17 | /// Gets or sets the stroke thickness.
18 | ///
19 | float StrokeThickness { get; set; }
20 |
21 | ///
22 | /// Gets or sets a value indicating whether to fill the series.
23 | ///
24 | bool UseFill { get; }
25 |
26 | ///
27 | /// Gets or sets a value indicating whether this series should be visible.
28 | ///
29 | bool IsVisible { get; set; }
30 |
31 | ///
32 | /// Gets the current value.
33 | ///
34 | Object CurrentValue { get; set; }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/RealTimeGraphX/IGraphRenderer.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.EventArguments;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Text;
6 |
7 | namespace RealTimeGraphX
8 | {
9 | ///
10 | /// Represents a graph renderer capable of receiving a series of data points from a controller and transforming them to drawing points.
11 | ///
12 | /// The type of the data series.
13 | ///
14 | public interface IGraphRenderer : IGraphComponent where TDataSeries : IGraphDataSeries
15 | {
16 | ///
17 | /// Arranges the series of data points and returns a series of drawing points.
18 | ///
19 | /// The target graph surface.
20 | /// The instance of the current rendered data series.
21 | /// Instance of graph range.
22 | /// Collection of x coordinates.
23 | /// Collection of y coordinates.
24 | /// The minimum x coordinates value.
25 | /// The maximum x coordinates value.
26 | /// The minimum y coordinates value.
27 | /// The maximum y coordinates value.
28 | ///
29 | IEnumerable Render(IGraphSurface surface, TDataSeries series, IGraphRange range, List xx, List yy, GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY);
30 |
31 | ///
32 | /// Draws the specified data series points on the target surface.
33 | ///
34 | /// The target graph surface.
35 | /// The instance of the current rendered data series.
36 | /// The collection of the current data series drawing points.
37 | /// The index of the current data series within the collection of data series.
38 | /// The length of the data series collection.
39 | void Draw(IGraphSurface surface, TDataSeries series, IEnumerable points, int index, int count);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/RealTimeGraphX/IGraphSurface.cs:
--------------------------------------------------------------------------------
1 | using RealTimeGraphX.EventArguments;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Text;
6 |
7 | namespace RealTimeGraphX
8 | {
9 | ///
10 | /// Represents a graph drawing surface capable of drawing a series of points submitted by a graph renderer.
11 | ///
12 | public interface IGraphSurface : IGraphComponent
13 | {
14 | ///
15 | /// Occurs when the surface size has changed.
16 | ///
17 | event EventHandler SurfaceSizeChanged;
18 |
19 | ///
20 | /// Occurs when the surface zoom rectangle has changed.
21 | ///
22 | event EventHandler ZoomRectChanged;
23 |
24 | ///
25 | /// Returns the actual size of the surface.
26 | ///
27 | ///
28 | SizeF GetSize();
29 |
30 | ///
31 | /// Returns the current bounds of the zooming rectangle.
32 | ///
33 | ///
34 | RectangleF GetZoomRect();
35 | }
36 |
37 | ///
38 | /// Represents a graph drawing surface capable of drawing a series of points submitted by a graph renderer.
39 | ///
40 | /// The type of the data series.
41 | ///
42 | public interface IGraphSurface : IGraphSurface where TDataSeries : IGraphDataSeries
43 | {
44 | ///
45 | /// Called before drawing has started.
46 | ///
47 | void BeginDraw();
48 |
49 | ///
50 | /// Draws the stroke of the specified data series points.
51 | ///
52 | /// The data series.
53 | /// The points.
54 | void DrawSeries(TDataSeries dataSeries, IEnumerable points);
55 |
56 | ///
57 | /// Fills the specified data series points.
58 | ///
59 | /// The data series.
60 | /// The points.
61 | void FillSeries(TDataSeries dataSeries, IEnumerable points);
62 |
63 | ///
64 | /// Applies transformation on the current pass.
65 | ///
66 | /// The transform.
67 | void SetTransform(GraphTransform transform);
68 |
69 | ///
70 | /// Called when drawing has completed.
71 | ///
72 | void EndDraw();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/RealTimeGraphX/RealTimeGraphX.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | false
6 | 1.0.0
7 | RealTimeGraphX is a data type agnostic, high performance plotting library for WPF and UWP.
8 | LICENSE
9 | https://github.com/royben/RealTimeGraphX
10 | icon.png
11 | https://github.com/royben/RealTimeGraphX
12 | Chart;Graph;Plotting;RealTime;WPF;UWP
13 | Roy Ben Shabat
14 | Roy Ben Shabat
15 | Release
16 |
17 |
18 |
19 | C:\DATA\Development\RealTimeGraphX\RealTimeGraphX\bin\Debug\RealTimeGraphX.xml
20 |
21 |
22 |
23 | C:\DATA\Development\RealTimeGraphX\RealTimeGraphX\bin\Release\RealTimeGraphX.xml
24 |
25 |
26 |
27 |
28 | True
29 |
30 |
31 |
32 | True
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/RealTimeGraphX/Renderers/ScrollingLineRenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 |
6 | namespace RealTimeGraphX.Renderers
7 | {
8 | ///
9 | /// Represents a scrolling style .
10 | ///
11 | /// The type of the data series.
12 | ///
13 | public class ScrollingLineRenderer : GraphRenderer where TDataSeries : IGraphDataSeries
14 | {
15 | ///
16 | /// Arranges the series of data points and returns a series of drawing points.
17 | ///
18 | /// The target graph surface.
19 | /// The instance of the current rendered data series.
20 | /// Instance of graph range.
21 | /// Collection of x coordinates.
22 | /// Collection of y coordinates.
23 | /// The minimum x coordinates value.
24 | /// The maximum x coordinates value.
25 | /// The minimum y coordinates value.
26 | /// The maximum y coordinates value.
27 | ///
28 | public override IEnumerable Render(IGraphSurface surface, TDataSeries series, IGraphRange range, List xx, List yy, GraphDataPoint minimumX, GraphDataPoint maximumX, GraphDataPoint minimumY, GraphDataPoint maximumY)
29 | {
30 | var dxList = xx.Select(x => x.ComputeRelativePosition(minimumX, maximumX)).ToList();
31 | var dyList = yy.Select(x => x.ComputeRelativePosition(minimumY, maximumY)).ToList();
32 |
33 | if (maximumX - minimumX > range.MaximumX)
34 | {
35 | var offset = ((maximumX - minimumX) - range.MaximumX) + minimumX;
36 |
37 | for (int i = 0; i < xx.Count; i++)
38 | {
39 | if (xx[i] < offset)
40 | {
41 | xx.RemoveAt(i);
42 | yy.RemoveAt(i);
43 | i--;
44 | }
45 | else
46 | {
47 | break;
48 | }
49 | }
50 | }
51 |
52 | List points = new List();
53 |
54 | for (int i = 0; i < dxList.Count; i++)
55 | {
56 | float image_x = ConvertXValueToRendererValue(surface,dxList[i]);
57 | float image_y = (float)Math.Min(ConvertYValueToRendererValue(surface, dyList[i]), surface.GetSize().Height - 2);
58 |
59 | PointF point = new PointF(image_x, image_y);
60 | points.Add(point);
61 | }
62 |
63 | return points;
64 | }
65 |
66 | ///
67 | /// Draws the specified data series points on the target surface.
68 | ///
69 | /// The target graph surface.
70 | /// The instance of the current rendered data series.
71 | /// The collection of the current data series drawing points.
72 | /// The index of the current data series within the collection of data series.
73 | /// The length of the data series collection.
74 | public override void Draw(IGraphSurface surface, TDataSeries series, IEnumerable points, int index, int count)
75 | {
76 | if (series.UseFill)
77 | {
78 | surface?.FillSeries(series, GetFillPoints(surface, points));
79 | }
80 |
81 | surface?.DrawSeries(series, points);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/visuals/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/royben/RealTimeGraphX/d35b95d65ee118450c4dbafd61b90c14a9067bd0/visuals/icon.png
--------------------------------------------------------------------------------