-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathMainWindow.axaml.cs
201 lines (182 loc) · 6.45 KB
/
MainWindow.axaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// <copyright file="MainWindow.axaml.cs" company="Devexperts LLC">
// Copyright © 2024 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// </copyright>
using System;
using System.Collections.Generic;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;
using DxFeed.Graal.Net;
using DxFeed.Graal.Net.Api;
using DxFeed.Graal.Net.Events;
using DxFeed.Graal.Net.Events.Candles;
using DxFeed.Graal.Net.Models;
using DxFeed.Graal.Net.Utils;
namespace CandleChartSample;
/// <summary>
/// The MainWindow class represents the main window of the CandleChartSample application.
/// This window is responsible for setting up the candle chart model, handling user input,
/// and updating the UI with candle data.
/// </summary>
public partial class MainWindow : Window
{
private readonly CandleList _candles = new();
private readonly TimeSeriesTxModel<Candle>.Builder _modelBuilder = new();
private TimeSeriesTxModel<Candle>? _model;
private string _symbol = string.Empty;
/// <summary>
/// Initializes a new instance of the MainWindow class.
/// Sets up the market feed address, initializes components, plot, and model builder,
/// and configures initial user input handling.
/// </summary>
public MainWindow()
{
InitializeComponent();
InitializePlot();
InitializeModelBuilder();
HandleTextChanged(SymbolTextBox);
}
/// <summary>
/// Initializes the plot for displaying candle data.
/// Configures axes and sets the initial time range for data.
/// </summary>
private void InitializePlot()
{
AvaPlot.Plot.Axes.DateTimeTicksBottom();
var candlePlot = AvaPlot.Plot.Add.Candlestick(_candles);
candlePlot.Axes.YAxis = AvaPlot.Plot.Axes.Right;
candlePlot.Axes.YAxis.Label.Text = "Price";
FromTimeTextBox.Text = DateTimeOffset.Now.AddMonths(-6).ToString("yyyyMMdd", CultureInfo.InvariantCulture);
}
/// <summary>
/// Initializes the model builder for creating a time series model of candles.
/// Configures the feed and listener for receiving candle events.
/// </summary>
private void InitializeModelBuilder() =>
_modelBuilder
.WithFeed(DXFeed.GetInstance())
.WithSnapshotProcessing(true)
.WithListener(OnCandleEventsReceived);
/// <summary>
/// Disposes the current time series model when the window is closed.
/// </summary>
/// <param name="e">Event arguments.</param>
protected override void OnClosed(EventArgs e) =>
_model?.Dispose();
/// <summary>
/// Handles the receipt of candle events.
/// Updates the candle list and refreshes the plot UI.
/// </summary>
/// <param name="source">The source of the indexed event.</param>
/// <param name="events">The collection of candle events.</param>
/// <param name="isSnapshot">Indicates if the events are part of a snapshot.</param>
private void OnCandleEventsReceived(IndexedEventSource source, IEnumerable<Candle> events, bool isSnapshot)
{
_candles.Update(events, isSnapshot);
Dispatcher.UIThread.Invoke(() =>
{
if (isSnapshot)
{
AvaPlot.Plot.Axes.AutoScale();
}
AvaPlot.Refresh();
});
}
/// <summary>
/// Handles the KeyDown event for the TextBox controls.
/// Updates the model when the Enter key is pressed.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event arguments.</param>
private void OnKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
HandleTextChanged(sender as TextBox);
}
}
/// <summary>
/// Handles the LostFocus event for the TextBox controls.
/// Updates the model when the focus is lost.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event arguments.</param>
private void OnLostFocus(object? sender, RoutedEventArgs e) =>
HandleTextChanged(sender as TextBox);
/// <summary>
/// Handles the text changed event for the TextBox controls.
/// Determines which TextBox triggered the event and calls the appropriate handler.
/// </summary>
/// <param name="textBox">The TextBox that triggered the event.</param>
private void HandleTextChanged(TextBox? textBox)
{
if (textBox == null)
{
return;
}
switch (textBox.Name)
{
case nameof(SymbolTextBox):
OnSymbolTextChanged();
break;
case nameof(FromTimeTextBox):
OnFromTimeTextChanged();
break;
}
}
/// <summary>
/// Updates the model when the symbol text changes.
/// Disposes the old model and creates a new one with the updated symbol.
/// </summary>
private void OnSymbolTextChanged()
{
if (_symbol.Equals(GetSymbol(), StringComparison.Ordinal))
{
return;
}
_symbol = GetSymbol();
_model?.Dispose();
_model = _modelBuilder
.WithSymbol(CandleSymbol.ValueOf(_symbol))
.WithFromTime(GetFromTime())
.Build();
}
/// <summary>
/// Updates the model's from time when the from-time text changes.
/// </summary>
private void OnFromTimeTextChanged()
{
if (_model == null)
{
OnSymbolTextChanged();
}
_model?.SetFromTime(GetFromTime());
}
/// <summary>
/// Gets the current symbol from the SymbolTextBox.
/// </summary>
/// <returns>The current symbol.</returns>
private string GetSymbol() =>
SymbolTextBox.Text ?? string.Empty;
/// <summary>
/// Gets the from-time in Unix time milliseconds from the FromTimeTextBox.
/// </summary>
/// <returns>The from-time in Unix time milliseconds.</returns>
private long GetFromTime()
{
try
{
return string.IsNullOrWhiteSpace(FromTimeTextBox.Text)
? 0
: TimeFormat.Default.Parse(FromTimeTextBox.Text).ToUnixTimeMilliseconds();
}
catch (Exception)
{
return 0;
}
}
}