diff --git a/Signal Generator/AddSignalWindow.xaml.cs b/Signal Generator/AddSignalWindow.xaml.cs index b6a0b20..8f1bfd2 100644 --- a/Signal Generator/AddSignalWindow.xaml.cs +++ b/Signal Generator/AddSignalWindow.xaml.cs @@ -22,6 +22,7 @@ namespace Signal_Generator { ObservableCollection signalProps = new ObservableCollection(); ObservableCollection typesOfSignal = new ObservableCollection(); + public AddSignalWindow() { InitializeComponent(); diff --git a/Signal Generator/DrawTask.cs b/Signal Generator/DrawTask.cs index d0e5ffd..58da12f 100644 --- a/Signal Generator/DrawTask.cs +++ b/Signal Generator/DrawTask.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; @@ -12,31 +13,47 @@ using System.Windows.Shapes; namespace Signal_Generator { - public class DrawTask : Task + public class DrawTask : Task, INotifyPropertyChanged { - Canvas currentCanvas; + Canvas canvas; System.Timers.Timer taskTimer; Stopwatch stopwatch = new Stopwatch(); - MultiSignal currentMultiSignal; - public DStatus dStatus; - public enum DStatus + MultiSignal multiSignal; + + private State _state; + public State state + { + get { return _state; } + set + { + _state = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("state")); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + public enum State { Created, Running, Paused, Finished, Canceled } public DrawTask(Action a) : base(a) { } - public void buildTask(MultiSignal s, Canvas c) + public void buildTask(Canvas c) { - currentCanvas = c; - currentMultiSignal = s; - dStatus = DStatus.Running; - drawSignalAtCanvas(); + canvas = c; + multiSignal = MultiSignal.getInstance(); + state = State.Running; + stopwatch.Start(); taskTimer = new System.Timers.Timer(2000); taskTimer.Elapsed += updateTextForms; taskTimer.Enabled = true; + + drawSignalAtCanvas(); } + private void updateTextForms(object sender, ElapsedEventArgs e) { @@ -46,24 +63,24 @@ namespace Signal_Generator private void drawSignalAtCanvas() { double lastX = 0, lastY = 0; - double w = currentCanvas.ActualWidth; + double w = canvas.ActualWidth; for (int i = 0; i != (int)w; i++) { - double y = currentMultiSignal.currentAmplitude(i / 5.0); + double y = multiSignal.currentAmplitude(i / 5.0); drawLine(lastX, lastY, i, y); lastX = i; lastY = y; Thread.Sleep(10); - switch (dStatus) + switch (state) { - case DStatus.Paused: - while (dStatus == DStatus.Paused) + case State.Paused: + while (state == State.Paused) Thread.Sleep(10); break; - case DStatus.Canceled: return; + case State.Canceled: return; } } - dStatus = DStatus.Finished; + state = State.Finished; } private void drawLine(double x1, double y1, double x2, double y2) @@ -76,14 +93,14 @@ namespace Signal_Generator l.Y1 = remap(y1); l.X2 = x2; l.Y2 = remap(y2); - currentCanvas.Children.Add(l); + canvas.Children.Add(l); }; - currentCanvas.Dispatcher.Invoke(a); + canvas.Dispatcher.Invoke(a); } private double remap(double x, double oldMin = -100.0, double oldMax = 100.0, double newMin = 100.0, double newMax = 0.0) { - newMin = currentCanvas.ActualHeight; + newMin = canvas.ActualHeight; return newMin + (x - oldMin) * (newMax - newMin) / (oldMax - oldMin); } } diff --git a/Signal Generator/MainWindow.xaml.cs b/Signal Generator/MainWindow.xaml.cs index 28975a7..f9eeeec 100644 --- a/Signal Generator/MainWindow.xaml.cs +++ b/Signal Generator/MainWindow.xaml.cs @@ -56,16 +56,15 @@ namespace Signal_Generator addSignalWindow_Instance.Close(); } - private void startProcedure_Button_Click(object sender, RoutedEventArgs e) { IsEnabled = false; - MultiSignal ms = new MultiSignal(); + MultiSignal ms = MultiSignal.getInstance(); foreach (IAnalogSignal item in signalCollection) { ms.add(item); } - taskWindow_Instance = new TaskWindow(ms); + taskWindow_Instance = new TaskWindow(); taskWindow_Instance.Show(); taskWindow_Instance.Closed += enableMainWindow; } diff --git a/Signal Generator/ProcedureModel.cs b/Signal Generator/ProcedureModel.cs new file mode 100644 index 0000000..99a6e49 --- /dev/null +++ b/Signal Generator/ProcedureModel.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Signal_Generator +{ + public class ProcedureModel : ICommand + { + public DrawTask currentTask; + Canvas targetCanvas; + + public ProcedureModel() + { + } + + public event EventHandler CanExecuteChanged; + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + + private void RaiseCanExecuteChanged(object o, PropertyChangedEventArgs e) + { + Action a = () => + { + RaiseCanExecuteChanged(); + }; + targetCanvas.Dispatcher.Invoke(a); + } + + public bool CanExecute(object parameter) + { + if (parameter == null) return false; + var parameters = parameter as object[]; + var btn = parameters[0] as Button; + var ms = MultiSignal.getInstance(); + + if ((ms == null) && (ms.count() == 0)) + return false; + switch (btn.Name) + { + case "start_Button": + btn.Content = updateStartButtonContent(); + return true; + default: + btn.Content = updatePauseButtonContent().Item2; + if (!updatePauseButtonContent().Item1) + return false; + return true; + } + } + + private string updateStartButtonContent() + { + if (currentTask == null) return "Запустить"; + switch (currentTask.state) + { + case DrawTask.State.Created: + return "Запустить"; + case DrawTask.State.Running: + return "Завершить"; + case DrawTask.State.Paused: + goto case DrawTask.State.Running; + default: + goto case DrawTask.State.Created; + } + } + + private Tuple updatePauseButtonContent() + { + if (currentTask == null) return new Tuple(false, "Пауза"); + switch (currentTask.state) + { + case DrawTask.State.Created: + return new Tuple(false, "Пауза"); + case DrawTask.State.Running: + return new Tuple(true, "Пауза"); + case DrawTask.State.Paused: + return new Tuple(true, "Возобновить"); + default: + goto case DrawTask.State.Created; + } + } + + public void Execute(object parameter) + { + var parameters = parameter as object[]; + var btn = parameters[0] as Button; + targetCanvas = parameters[1] as Canvas; + + switch (btn.Name) + { + case "start_Button": + startOrCancelTask(); + break; + case "pause_Button": + pauseOrResumeTask(); + break; + } + + } + + private void startOrCancelTask () + { + targetCanvas.Children.Clear(); + if (currentTask != null) + switch (currentTask.state) + { + case DrawTask.State.Paused: + goto case DrawTask.State.Running; + case DrawTask.State.Running: + currentTask.state = DrawTask.State.Canceled; + return; + } + Action newAction = () => + { + currentTask.PropertyChanged += RaiseCanExecuteChanged; + currentTask.buildTask(targetCanvas); + }; + currentTask = new DrawTask(newAction); + currentTask.Start(); + } + + private void pauseOrResumeTask() + { + switch (currentTask.state) + { + case DrawTask.State.Paused: + currentTask.state = DrawTask.State.Running; + break; + case DrawTask.State.Running: + currentTask.state = DrawTask.State.Paused; + break; + } + } + } +} diff --git a/Signal Generator/Signal Generator.csproj b/Signal Generator/Signal Generator.csproj index f43c494..c9bac2e 100644 --- a/Signal Generator/Signal Generator.csproj +++ b/Signal Generator/Signal Generator.csproj @@ -59,11 +59,13 @@ AddSignalWindow.xaml + + TaskWindow.xaml diff --git a/Signal Generator/Signal/MultiSignal.cs b/Signal Generator/Signal/MultiSignal.cs index 03c826b..2e954b8 100644 --- a/Signal Generator/Signal/MultiSignal.cs +++ b/Signal Generator/Signal/MultiSignal.cs @@ -9,13 +9,21 @@ namespace Signal_Generator { public class MultiSignal : IAnalogSignal { + private static MultiSignal instance; private List signals { get; set; } - public MultiSignal() + private MultiSignal() { signals = new List(); } + public static MultiSignal getInstance() + { + if (instance == null) + instance = new MultiSignal(); + return instance; + } + internal void add(IAnalogSignal signal) { signals.Add(signal); @@ -26,6 +34,11 @@ namespace Signal_Generator signals.Remove(signal); } + internal int count() + { + return signals.Count(); + } + public double currentAmplitude(double t) { double summaryAmplitude = 0; @@ -39,13 +52,9 @@ namespace Signal_Generator // Неиспользуемые поля и методы public string typeToString => throw new NotImplementedException(); - string IAnalogSignal.paramsToString => throw new NotImplementedException(); - string IAnalogSignal.typeToString => throw new NotImplementedException(); - Collection IAnalogSignal.paramsCollection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - double IAnalogSignal.currentAmplitude(double t) { throw new NotImplementedException(); diff --git a/Signal Generator/TaskViewConverter.cs b/Signal Generator/TaskViewConverter.cs new file mode 100644 index 0000000..cf92fdf --- /dev/null +++ b/Signal Generator/TaskViewConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Data; + +namespace Signal_Generator +{ + class ArrayConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + return values.Clone(); + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Signal Generator/TaskWindow.xaml b/Signal Generator/TaskWindow.xaml index 20cbddd..4db8b83 100644 --- a/Signal Generator/TaskWindow.xaml +++ b/Signal Generator/TaskWindow.xaml @@ -1,4 +1,5 @@  - + + + + + + @@ -27,8 +33,22 @@ Текущий сигнал: diff --git a/Signal Generator/TaskWindow.xaml.cs b/Signal Generator/TaskWindow.xaml.cs index c62a7bd..24ae5f5 100644 --- a/Signal Generator/TaskWindow.xaml.cs +++ b/Signal Generator/TaskWindow.xaml.cs @@ -23,47 +23,15 @@ namespace Signal_Generator public partial class TaskWindow : Window { - MultiSignal currentMultiSignal; - DrawTask currentTask; - - public TaskWindow(MultiSignal s) + public TaskWindow() { InitializeComponent(); - currentMultiSignal = s; - } - - private void start_Button_Click(object sender, RoutedEventArgs e) - { - signalGraph_Canvas.Children.Clear(); - if (currentTask != null) - switch (currentTask.dStatus) - { - case DrawTask.DStatus.Paused: - goto case DrawTask.DStatus.Running; - case DrawTask.DStatus.Running: - currentTask.dStatus = DrawTask.DStatus.Canceled; - break; - } - Action newAction = () => - { - currentTask.buildTask(currentMultiSignal, signalGraph_Canvas); - }; - currentTask = new DrawTask(newAction); - currentTask.Start(); } - private void pause_Button_Click(object sender, RoutedEventArgs e) + private void Grid_Loaded(object sender, RoutedEventArgs e) { - switch (currentTask.dStatus) { - case DrawTask.DStatus.Paused: - currentTask.dStatus = DrawTask.DStatus.Running; - pause_Button.Content = "Приостановить"; - break; - case DrawTask.DStatus.Running: - currentTask.dStatus = DrawTask.DStatus.Paused; - pause_Button.Content = "Возобновить"; - break; - } + // принудительное обновление + ((ProcedureModel)Resources["ProcedureModel"]).RaiseCanExecuteChanged(); } } }