mirror of
https://github.com/JasonYANG170/logicanalyzer.git
synced 2024-11-23 12:06:27 +00:00
Allow to choose channel colors
This commit is contained in:
parent
4e575109a9
commit
b59577ec04
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using Avalonia.Media;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -30,6 +31,7 @@ namespace LogicAnalyzer.Classes
|
||||||
public string TextualChannelNumber { get { return $"Channel {ChannelNumber + 1}"; } }
|
public string TextualChannelNumber { get { return $"Channel {ChannelNumber + 1}"; } }
|
||||||
public int ChannelNumber { get; set; }
|
public int ChannelNumber { get; set; }
|
||||||
public string ChannelName { get; set; } = "";
|
public string ChannelName { get; set; } = "";
|
||||||
|
public Color? ChannelColor { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OldCaptureSettings
|
public class OldCaptureSettings
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace LogicAnalyzer.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event EventHandler<ChannelEventArgs> ChannelClick;
|
||||||
|
|
||||||
private void CreateControls()
|
private void CreateControls()
|
||||||
{
|
{
|
||||||
ChannelGrid.Children.Clear();
|
ChannelGrid.Children.Clear();
|
||||||
|
@ -67,7 +69,10 @@ namespace LogicAnalyzer.Controls
|
||||||
|
|
||||||
newChannelLabel.Text = channels[buc].TextualChannelNumber;
|
newChannelLabel.Text = channels[buc].TextualChannelNumber;
|
||||||
|
|
||||||
newChannelLabel.Foreground = GraphicObjectsCache.GetBrush(AnalyzerColors.FgChannelColors[buc % 24]);
|
newChannelLabel.Foreground = GraphicObjectsCache.GetBrush(channels[buc].ChannelColor ?? AnalyzerColors.FgChannelColors[buc % 24]);
|
||||||
|
|
||||||
|
newChannelLabel.Tag = channels[buc];
|
||||||
|
newChannelLabel.PointerPressed += NewChannelLabel_PointerPressed;
|
||||||
|
|
||||||
newChannelGrid.Children.Add(newChannelLabel);
|
newChannelGrid.Children.Add(newChannelLabel);
|
||||||
|
|
||||||
|
@ -100,6 +105,24 @@ namespace LogicAnalyzer.Controls
|
||||||
ChannelGrid.EndBatchUpdate();
|
ChannelGrid.EndBatchUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void NewChannelLabel_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
var label = sender as TextBlock;
|
||||||
|
|
||||||
|
if (label == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var channel = label.Tag as CaptureChannel;
|
||||||
|
|
||||||
|
if(channel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ChannelClick == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChannelClick(sender , new ChannelEventArgs { Channel = channel });
|
||||||
|
}
|
||||||
|
|
||||||
void NewChannelTextbox_TextChanged(AvaloniaPropertyChangedEventArgs e)
|
void NewChannelTextbox_TextChanged(AvaloniaPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((e.Sender as TextBox).Tag as CaptureChannel).ChannelName = e.NewValue?.ToString();
|
((e.Sender as TextBox).Tag as CaptureChannel).ChannelName = e.NewValue?.ToString();
|
||||||
|
@ -111,6 +134,11 @@ namespace LogicAnalyzer.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ChannelEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public required CaptureChannel Channel { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class RegionEventArgs : EventArgs
|
public class RegionEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public SampleRegion? Region { get; set; }
|
public SampleRegion? Region { get; set; }
|
||||||
|
|
|
@ -21,25 +21,27 @@ namespace LogicAnalyzer.Controls
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSamples(UInt128[] Samples, int ChannelCount)
|
public void UpdateSamples(CaptureChannel[] Channels, UInt128[] Samples)
|
||||||
{
|
{
|
||||||
if (ChannelCount > 24)
|
int channelCount = Channels.Length;
|
||||||
ChannelCount = 24;
|
|
||||||
|
if (channelCount > 24)
|
||||||
|
channelCount = 24;
|
||||||
|
|
||||||
int width = Math.Max(Math.Min(Samples.Length, 4096), 1024);
|
int width = Math.Max(Math.Min(Samples.Length, 4096), 1024);
|
||||||
|
|
||||||
float cHeight = 144 / (float)ChannelCount;
|
float cHeight = 144 / (float)channelCount;
|
||||||
float sWidth = (float)width / (float)Samples.Length;
|
float sWidth = (float)width / (float)Samples.Length;
|
||||||
float high = cHeight / 6;
|
float high = cHeight / 6;
|
||||||
float low = cHeight - high;
|
float low = cHeight - high;
|
||||||
|
|
||||||
using SKBitmap skb = new SKBitmap(width, 144);
|
using SKBitmap skb = new SKBitmap(width, 144);
|
||||||
|
|
||||||
SKPaint[] colors = new SKPaint[ChannelCount];
|
SKPaint[] colors = new SKPaint[channelCount];
|
||||||
|
|
||||||
for (int buc = 0; buc < ChannelCount; buc++)
|
for (int buc = 0; buc < channelCount; buc++)
|
||||||
{
|
{
|
||||||
var avColor = AnalyzerColors.FgChannelColors[buc];
|
var avColor = Channels[buc].ChannelColor ?? AnalyzerColors.FgChannelColors[buc];
|
||||||
|
|
||||||
colors[buc] = new SKPaint
|
colors[buc] = new SKPaint
|
||||||
{
|
{
|
||||||
|
@ -56,7 +58,7 @@ namespace LogicAnalyzer.Controls
|
||||||
UInt128 sample = Samples[x];
|
UInt128 sample = Samples[x];
|
||||||
UInt128 prevSample = Samples[x == 0 ? x : x - 1];
|
UInt128 prevSample = Samples[x == 0 ? x : x - 1];
|
||||||
|
|
||||||
for (int chan = 0; chan < ChannelCount; chan++)
|
for (int chan = 0; chan < channelCount; chan++)
|
||||||
{
|
{
|
||||||
UInt128 curVal = sample & ((UInt128)1 << chan);
|
UInt128 curVal = sample & ((UInt128)1 << chan);
|
||||||
UInt128 prevVal = prevSample & ((UInt128)1 << chan);
|
UInt128 prevVal = prevSample & ((UInt128)1 << chan);
|
||||||
|
|
|
@ -18,7 +18,9 @@ namespace LogicAnalyzer.Controls
|
||||||
public int PreSamples { get; set; }
|
public int PreSamples { get; set; }
|
||||||
public int[]? Bursts { get; set; }
|
public int[]? Bursts { get; set; }
|
||||||
public UInt128[] Samples { get; set; }
|
public UInt128[] Samples { get; set; }
|
||||||
public int ChannelCount { get; set; }
|
|
||||||
|
public CaptureChannel[]? Channels { get; set; }
|
||||||
|
//public int ChannelCount { get; set; }
|
||||||
public int SamplesInScreen { get; set; }
|
public int SamplesInScreen { get; set; }
|
||||||
public int FirstSample { get; set; }
|
public int FirstSample { get; set; }
|
||||||
public int? UserMarker { get; set; }
|
public int? UserMarker { get; set; }
|
||||||
|
@ -91,6 +93,9 @@ namespace LogicAnalyzer.Controls
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
int ChannelCount = Channels?.Length ?? 0;
|
||||||
|
|
||||||
int minSize = ChannelCount * MIN_CHANNEL_HEIGHT;
|
int minSize = ChannelCount * MIN_CHANNEL_HEIGHT;
|
||||||
|
|
||||||
if (Parent.Bounds.Height > minSize && this.Height != double.NaN)
|
if (Parent.Bounds.Height > minSize && this.Height != double.NaN)
|
||||||
|
@ -173,12 +178,12 @@ namespace LogicAnalyzer.Controls
|
||||||
else
|
else
|
||||||
lineY = (chan + 1) * channelHeight - margin;
|
lineY = (chan + 1) * channelHeight - margin;
|
||||||
|
|
||||||
context.DrawLine(GraphicObjectsCache.GetPen(AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX + sampleWidth, lineY));
|
context.DrawLine(GraphicObjectsCache.GetPen(Channels?[chan].ChannelColor ?? AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX + sampleWidth, lineY));
|
||||||
|
|
||||||
if (curVal != prevVal && buc != 0)
|
if (curVal != prevVal && buc != 0)
|
||||||
{
|
{
|
||||||
lineY = chan * channelHeight + margin;
|
lineY = chan * channelHeight + margin;
|
||||||
context.DrawLine(GraphicObjectsCache.GetPen(AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX, lineY + channelHeight - margin * 2));
|
context.DrawLine(GraphicObjectsCache.GetPen(Channels?[chan].ChannelColor ?? AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX, lineY + channelHeight - margin * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Shared.PlatformSupport;
|
using Avalonia.Shared.PlatformSupport;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using AvaloniaColorPicker;
|
||||||
using AvaloniaEdit.Utils;
|
using AvaloniaEdit.Utils;
|
||||||
using LogicAnalyzer.Classes;
|
using LogicAnalyzer.Classes;
|
||||||
using LogicAnalyzer.Controls;
|
using LogicAnalyzer.Controls;
|
||||||
|
@ -24,6 +25,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -70,6 +72,8 @@ namespace LogicAnalyzer
|
||||||
sampleMarker.SamplesInserted += SampleMarker_SamplesInserted;
|
sampleMarker.SamplesInserted += SampleMarker_SamplesInserted;
|
||||||
sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted;
|
sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted;
|
||||||
|
|
||||||
|
channelViewer.ChannelClick += ChannelViewer_ChannelClick;
|
||||||
|
|
||||||
tkInScreen.PropertyChanged += tkInScreen_ValueChanged;
|
tkInScreen.PropertyChanged += tkInScreen_ValueChanged;
|
||||||
scrSamplePos.Scroll += scrSamplePos_ValueChanged;
|
scrSamplePos.Scroll += scrSamplePos_ValueChanged;
|
||||||
scrSamplePos.PointerEnter += ScrSamplePos_PointerEnter;
|
scrSamplePos.PointerEnter += ScrSamplePos_PointerEnter;
|
||||||
|
@ -96,6 +100,26 @@ namespace LogicAnalyzer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void ChannelViewer_ChannelClick(object? sender, ChannelEventArgs e)
|
||||||
|
{
|
||||||
|
var picker = new ColorPickerWindow();
|
||||||
|
|
||||||
|
if (e.Channel.ChannelColor != null)
|
||||||
|
picker.Color = e.Channel.ChannelColor.Value;
|
||||||
|
else
|
||||||
|
picker.Color = AnalyzerColors.FgChannelColors[e.Channel.ChannelNumber];
|
||||||
|
|
||||||
|
var color = await picker.ShowDialog(this);
|
||||||
|
|
||||||
|
if (color == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
e.Channel.ChannelColor = color;
|
||||||
|
(sender as TextBlock).Foreground = GraphicObjectsCache.GetBrush(color.Value);
|
||||||
|
samplePreviewer.UpdateSamples(channelViewer.Channels, sampleViewer.Samples);
|
||||||
|
sampleViewer.InvalidateVisual();
|
||||||
|
}
|
||||||
|
|
||||||
private async void MnuAbout_Click(object? sender, RoutedEventArgs e)
|
private async void MnuAbout_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var aboutDialog = new AboutDialog();
|
var aboutDialog = new AboutDialog();
|
||||||
|
@ -283,7 +307,7 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.Samples = samples;
|
sampleViewer.Samples = samples;
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount);
|
samplePreviewer.UpdateSamples(channelViewer.Channels, samples);
|
||||||
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +376,7 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.Samples = samples;
|
sampleViewer.Samples = samples;
|
||||||
sampleViewer.PreSamples = settings.PreTriggerSamples;
|
sampleViewer.PreSamples = settings.PreTriggerSamples;
|
||||||
sampleViewer.ChannelCount = settings.CaptureChannels.Length;
|
sampleViewer.Channels = settings.CaptureChannels;
|
||||||
sampleViewer.SamplesInScreen = Math.Min(100, samples.Length / 10);
|
sampleViewer.SamplesInScreen = Math.Min(100, samples.Length / 10);
|
||||||
sampleViewer.FirstSample = Math.Max(settings.PreTriggerSamples - 10, 0);
|
sampleViewer.FirstSample = Math.Max(settings.PreTriggerSamples - 10, 0);
|
||||||
sampleViewer.ClearRegions();
|
sampleViewer.ClearRegions();
|
||||||
|
@ -360,8 +384,10 @@ namespace LogicAnalyzer
|
||||||
|
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
|
||||||
|
channelViewer.Channels = settings.CaptureChannels;
|
||||||
|
|
||||||
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
||||||
samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount);
|
samplePreviewer.UpdateSamples(channelViewer.Channels, samples);
|
||||||
|
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
|
@ -372,8 +398,6 @@ namespace LogicAnalyzer
|
||||||
scrSamplePos.Value = sampleViewer.FirstSample;
|
scrSamplePos.Value = sampleViewer.FirstSample;
|
||||||
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
||||||
|
|
||||||
channelViewer.Channels = settings.CaptureChannels;
|
|
||||||
|
|
||||||
mnuSave.IsEnabled = true;
|
mnuSave.IsEnabled = true;
|
||||||
mnuProtocols.IsEnabled = true;
|
mnuProtocols.IsEnabled = true;
|
||||||
mnuExport.IsEnabled = true;
|
mnuExport.IsEnabled = true;
|
||||||
|
@ -587,7 +611,7 @@ namespace LogicAnalyzer
|
||||||
|
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
|
||||||
samplePreviewer.UpdateSamples(finalSamples, sampleViewer.ChannelCount);
|
samplePreviewer.UpdateSamples(channelViewer.Channels, finalSamples);
|
||||||
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
||||||
|
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
|
@ -630,7 +654,7 @@ namespace LogicAnalyzer
|
||||||
|
|
||||||
List<byte[]> samples = new List<byte[]>();
|
List<byte[]> samples = new List<byte[]>();
|
||||||
|
|
||||||
for (int buc = 0; buc < sampleViewer.ChannelCount; buc++)
|
for (int buc = 0; buc < (sampleViewer.Channels?.Length ?? 0); buc++)
|
||||||
samples.Add(ExtractSamples(buc, sampleViewer.Samples, e.FirstSample, e.SampleCount));
|
samples.Add(ExtractSamples(buc, sampleViewer.Samples, e.FirstSample, e.SampleCount));
|
||||||
|
|
||||||
var names = channelViewer.Channels.Select(c => c.ChannelName).ToArray();
|
var names = channelViewer.Channels.Select(c => c.ChannelName).ToArray();
|
||||||
|
@ -729,7 +753,7 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.Samples = e.Samples;
|
sampleViewer.Samples = e.Samples;
|
||||||
sampleViewer.PreSamples = e.PreSamples;
|
sampleViewer.PreSamples = e.PreSamples;
|
||||||
sampleViewer.ChannelCount = e.ChannelCount;
|
sampleViewer.Channels = settings.CaptureChannels;
|
||||||
|
|
||||||
if(!preserveSamples)
|
if(!preserveSamples)
|
||||||
sampleViewer.SamplesInScreen = Math.Min(100, e.Samples.Length / 10);
|
sampleViewer.SamplesInScreen = Math.Min(100, e.Samples.Length / 10);
|
||||||
|
@ -756,15 +780,15 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.ClearAnalyzedChannels();
|
sampleViewer.ClearAnalyzedChannels();
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
|
||||||
samplePreviewer.UpdateSamples(e.Samples, sampleViewer.ChannelCount);
|
channelViewer.Channels = settings.CaptureChannels;
|
||||||
|
|
||||||
|
samplePreviewer.UpdateSamples(channelViewer.Channels, e.Samples);
|
||||||
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
||||||
|
|
||||||
scrSamplePos.Maximum = e.Samples.Length - 1;
|
scrSamplePos.Maximum = e.Samples.Length - 1;
|
||||||
scrSamplePos.Value = sampleViewer.FirstSample;
|
scrSamplePos.Value = sampleViewer.FirstSample;
|
||||||
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
||||||
|
|
||||||
channelViewer.Channels = settings.CaptureChannels;
|
|
||||||
|
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
sampleMarker.ClearRegions();
|
sampleMarker.ClearRegions();
|
||||||
|
@ -1296,7 +1320,7 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.Samples = ex.Samples;
|
sampleViewer.Samples = ex.Samples;
|
||||||
sampleViewer.PreSamples = ex.Settings.PreTriggerSamples;
|
sampleViewer.PreSamples = ex.Settings.PreTriggerSamples;
|
||||||
sampleViewer.ChannelCount = ex.Settings.CaptureChannels.Length;
|
sampleViewer.Channels = ex.Settings.CaptureChannels;
|
||||||
sampleViewer.SamplesInScreen = Math.Min(100, ex.Samples.Length / 10);
|
sampleViewer.SamplesInScreen = Math.Min(100, ex.Samples.Length / 10);
|
||||||
sampleViewer.FirstSample = Math.Max(ex.Settings.PreTriggerSamples - 10, 0);
|
sampleViewer.FirstSample = Math.Max(ex.Settings.PreTriggerSamples - 10, 0);
|
||||||
sampleViewer.ClearRegions();
|
sampleViewer.ClearRegions();
|
||||||
|
@ -1307,7 +1331,9 @@ namespace LogicAnalyzer
|
||||||
|
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
|
||||||
samplePreviewer.UpdateSamples(ex.Samples, sampleViewer.ChannelCount);
|
channelViewer.Channels = ex.Settings.CaptureChannels;
|
||||||
|
|
||||||
|
samplePreviewer.UpdateSamples(channelViewer.Channels, ex.Samples);
|
||||||
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
samplePreviewer.ViewPosition = sampleViewer.FirstSample;
|
||||||
|
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
|
@ -1322,7 +1348,7 @@ namespace LogicAnalyzer
|
||||||
scrSamplePos.Value = sampleViewer.FirstSample;
|
scrSamplePos.Value = sampleViewer.FirstSample;
|
||||||
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
tkInScreen.Value = sampleViewer.SamplesInScreen;
|
||||||
|
|
||||||
channelViewer.Channels = ex.Settings.CaptureChannels;
|
|
||||||
|
|
||||||
mnuSave.IsEnabled = true;
|
mnuSave.IsEnabled = true;
|
||||||
mnuProtocols.IsEnabled = true;
|
mnuProtocols.IsEnabled = true;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user