Browse Source

Новая логика управления процедурой. Теперь главная модель реализует интерфейс ICommand.

master
Никита 6 years ago
parent
commit
2f821a3844
  1. 1
      Signal Generator/AddSignalWindow.xaml.cs
  2. 57
      Signal Generator/DrawTask.cs
  3. 5
      Signal Generator/MainWindow.xaml.cs
  4. 145
      Signal Generator/ProcedureModel.cs
  5. 2
      Signal Generator/Signal Generator.csproj
  6. 19
      Signal Generator/Signal/MultiSignal.cs
  7. 24
      Signal Generator/TaskViewConverter.cs
  8. 26
      Signal Generator/TaskWindow.xaml
  9. 40
      Signal Generator/TaskWindow.xaml.cs

1
Signal Generator/AddSignalWindow.xaml.cs

@ -22,6 +22,7 @@ namespace Signal_Generator
{ {
ObservableCollection<Parameter> signalProps = new ObservableCollection<Parameter>(); ObservableCollection<Parameter> signalProps = new ObservableCollection<Parameter>();
ObservableCollection<IAnalogSignal> typesOfSignal = new ObservableCollection<IAnalogSignal>(); ObservableCollection<IAnalogSignal> typesOfSignal = new ObservableCollection<IAnalogSignal>();
public AddSignalWindow() public AddSignalWindow()
{ {
InitializeComponent(); InitializeComponent();

57
Signal Generator/DrawTask.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -12,31 +13,47 @@ using System.Windows.Shapes;
namespace Signal_Generator namespace Signal_Generator
{ {
public class DrawTask : Task public class DrawTask : Task, INotifyPropertyChanged
{ {
Canvas currentCanvas; Canvas canvas;
System.Timers.Timer taskTimer; System.Timers.Timer taskTimer;
Stopwatch stopwatch = new Stopwatch(); Stopwatch stopwatch = new Stopwatch();
MultiSignal currentMultiSignal; MultiSignal multiSignal;
public DStatus dStatus;
public enum DStatus 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 Created, Running, Paused, Finished, Canceled
} }
public DrawTask(Action a) : base(a) { } public DrawTask(Action a) : base(a) { }
public void buildTask(MultiSignal s, Canvas c) public void buildTask(Canvas c)
{ {
currentCanvas = c; canvas = c;
currentMultiSignal = s; multiSignal = MultiSignal.getInstance();
dStatus = DStatus.Running; state = State.Running;
drawSignalAtCanvas();
stopwatch.Start(); stopwatch.Start();
taskTimer = new System.Timers.Timer(2000); taskTimer = new System.Timers.Timer(2000);
taskTimer.Elapsed += updateTextForms; taskTimer.Elapsed += updateTextForms;
taskTimer.Enabled = true; taskTimer.Enabled = true;
drawSignalAtCanvas();
} }
private void updateTextForms(object sender, ElapsedEventArgs e) private void updateTextForms(object sender, ElapsedEventArgs e)
{ {
@ -46,24 +63,24 @@ namespace Signal_Generator
private void drawSignalAtCanvas() private void drawSignalAtCanvas()
{ {
double lastX = 0, lastY = 0; double lastX = 0, lastY = 0;
double w = currentCanvas.ActualWidth; double w = canvas.ActualWidth;
for (int i = 0; i != (int)w; i++) 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); drawLine(lastX, lastY, i, y);
lastX = i; lastX = i;
lastY = y; lastY = y;
Thread.Sleep(10); Thread.Sleep(10);
switch (dStatus) switch (state)
{ {
case DStatus.Paused: case State.Paused:
while (dStatus == DStatus.Paused) while (state == State.Paused)
Thread.Sleep(10); Thread.Sleep(10);
break; 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) private void drawLine(double x1, double y1, double x2, double y2)
@ -76,14 +93,14 @@ namespace Signal_Generator
l.Y1 = remap(y1); l.Y1 = remap(y1);
l.X2 = x2; l.X2 = x2;
l.Y2 = remap(y2); 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) 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); return newMin + (x - oldMin) * (newMax - newMin) / (oldMax - oldMin);
} }
} }

5
Signal Generator/MainWindow.xaml.cs

@ -56,16 +56,15 @@ namespace Signal_Generator
addSignalWindow_Instance.Close(); addSignalWindow_Instance.Close();
} }
private void startProcedure_Button_Click(object sender, RoutedEventArgs e) private void startProcedure_Button_Click(object sender, RoutedEventArgs e)
{ {
IsEnabled = false; IsEnabled = false;
MultiSignal ms = new MultiSignal(); MultiSignal ms = MultiSignal.getInstance();
foreach (IAnalogSignal item in signalCollection) foreach (IAnalogSignal item in signalCollection)
{ {
ms.add(item); ms.add(item);
} }
taskWindow_Instance = new TaskWindow(ms); taskWindow_Instance = new TaskWindow();
taskWindow_Instance.Show(); taskWindow_Instance.Show();
taskWindow_Instance.Closed += enableMainWindow; taskWindow_Instance.Closed += enableMainWindow;
} }

145
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<bool, string> updatePauseButtonContent()
{
if (currentTask == null) return new Tuple<bool, string>(false, "Пауза");
switch (currentTask.state)
{
case DrawTask.State.Created:
return new Tuple<bool, string>(false, "Пауза");
case DrawTask.State.Running:
return new Tuple<bool, string>(true, "Пауза");
case DrawTask.State.Paused:
return new Tuple<bool, string>(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;
}
}
}
}

2
Signal Generator/Signal Generator.csproj

@ -59,11 +59,13 @@
<DependentUpon>AddSignalWindow.xaml</DependentUpon> <DependentUpon>AddSignalWindow.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="DrawTask.cs" /> <Compile Include="DrawTask.cs" />
<Compile Include="ProcedureModel.cs" />
<Compile Include="Signal\Base\AnalogSignalMethods.cs" /> <Compile Include="Signal\Base\AnalogSignalMethods.cs" />
<Compile Include="Signal\FmSignal.cs" /> <Compile Include="Signal\FmSignal.cs" />
<Compile Include="Settings.cs" /> <Compile Include="Settings.cs" />
<Compile Include="Signal\Base\Parameter.cs" /> <Compile Include="Signal\Base\Parameter.cs" />
<Compile Include="Signal\SinusoidalSignal.cs" /> <Compile Include="Signal\SinusoidalSignal.cs" />
<Compile Include="TaskViewConverter.cs" />
<Compile Include="TaskWindow.xaml.cs"> <Compile Include="TaskWindow.xaml.cs">
<DependentUpon>TaskWindow.xaml</DependentUpon> <DependentUpon>TaskWindow.xaml</DependentUpon>
</Compile> </Compile>

19
Signal Generator/Signal/MultiSignal.cs

@ -9,13 +9,21 @@ namespace Signal_Generator
{ {
public class MultiSignal : IAnalogSignal public class MultiSignal : IAnalogSignal
{ {
private static MultiSignal instance;
private List<IAnalogSignal> signals { get; set; } private List<IAnalogSignal> signals { get; set; }
public MultiSignal() private MultiSignal()
{ {
signals = new List<IAnalogSignal>(); signals = new List<IAnalogSignal>();
} }
public static MultiSignal getInstance()
{
if (instance == null)
instance = new MultiSignal();
return instance;
}
internal void add(IAnalogSignal signal) internal void add(IAnalogSignal signal)
{ {
signals.Add(signal); signals.Add(signal);
@ -26,6 +34,11 @@ namespace Signal_Generator
signals.Remove(signal); signals.Remove(signal);
} }
internal int count()
{
return signals.Count();
}
public double currentAmplitude(double t) public double currentAmplitude(double t)
{ {
double summaryAmplitude = 0; double summaryAmplitude = 0;
@ -39,13 +52,9 @@ namespace Signal_Generator
// Неиспользуемые поля и методы // Неиспользуемые поля и методы
public string typeToString => throw new NotImplementedException(); public string typeToString => throw new NotImplementedException();
string IAnalogSignal.paramsToString => throw new NotImplementedException(); string IAnalogSignal.paramsToString => throw new NotImplementedException();
string IAnalogSignal.typeToString => throw new NotImplementedException(); string IAnalogSignal.typeToString => throw new NotImplementedException();
Collection<Parameter> IAnalogSignal.paramsCollection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } Collection<Parameter> IAnalogSignal.paramsCollection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
double IAnalogSignal.currentAmplitude(double t) double IAnalogSignal.currentAmplitude(double t)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

24
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();
}
}
}

26
Signal Generator/TaskWindow.xaml

@ -1,4 +1,5 @@
<Window x:Class="Signal_Generator.TaskWindow" <Window x:Class="Signal_Generator.TaskWindow"
x:Name="TaskWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@ -7,7 +8,12 @@
mc:Ignorable="d" mc:Ignorable="d"
Title="Моделирование работы группы сигналов" Height="250" Width="500" Title="Моделирование работы группы сигналов" Height="250" Width="500"
ResizeMode="NoResize"> ResizeMode="NoResize">
<Grid Margin="10"> <Window.Resources>
<local:ProcedureModel x:Key="ProcedureModel"/>
<local:ArrayConverter x:Key="ArrayConverter"/>
</Window.Resources>
<Grid Margin="10" Loaded="Grid_Loaded">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
@ -27,8 +33,22 @@
<TextBlock x:Name="currentAmplitude_TextBlock" Margin="0,0,5,5" Grid.Row="2" Grid.Column="1">Текущий сигнал:</TextBlock> <TextBlock x:Name="currentAmplitude_TextBlock" Margin="0,0,5,5" Grid.Row="2" Grid.Column="1">Текущий сигнал:</TextBlock>
<TextBox x:Name="currentAmplitude_TextBox" Margin="0,0,0,5" Grid.Row="2" Grid.Column="2"/> <TextBox x:Name="currentAmplitude_TextBox" Margin="0,0,0,5" Grid.Row="2" Grid.Column="2"/>
<Button x:Name="start_Button" Width="120" Content="Запустить" Margin="5,0" Grid.Row="3" Grid.Column="0" <Button x:Name="start_Button" Width="120" Content="Запустить" Margin="5,0" Grid.Row="3" Grid.Column="0"
Grid.ColumnSpan="2" Click="start_Button_Click"/> Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource ArrayConverter}">
<Binding ElementName="start_Button"/>
<Binding ElementName="signalGraph_Canvas"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
<Button x:Name="pause_Button" Width="120" Content="Приостановить" Margin="5,0" Grid.Row="3" Grid.Column="2" <Button x:Name="pause_Button" Width="120" Content="Приостановить" Margin="5,0" Grid.Row="3" Grid.Column="2"
Grid.ColumnSpan="2" Click="pause_Button_Click"/> Grid.ColumnSpan="2" Command="{StaticResource ProcedureModel}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource ArrayConverter}">
<Binding ElementName="pause_Button"/>
<Binding ElementName="signalGraph_Canvas"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</Grid> </Grid>
</Window> </Window>

40
Signal Generator/TaskWindow.xaml.cs

@ -23,47 +23,15 @@ namespace Signal_Generator
public partial class TaskWindow : Window public partial class TaskWindow : Window
{ {
MultiSignal currentMultiSignal; public TaskWindow()
DrawTask currentTask;
public TaskWindow(MultiSignal s)
{ {
InitializeComponent(); 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: ((ProcedureModel)Resources["ProcedureModel"]).RaiseCanExecuteChanged();
currentTask.dStatus = DrawTask.DStatus.Running;
pause_Button.Content = "Приостановить";
break;
case DrawTask.DStatus.Running:
currentTask.dStatus = DrawTask.DStatus.Paused;
pause_Button.Content = "Возобновить";
break;
}
} }
} }
} }

Loading…
Cancel
Save