Add Primary Channel (select using Ctrl+Click on a selected channel) functionality, tie Global PTT and tones to Primary Channel rather than every selected channel

pull/1/head
Steven Jennison 11 months ago
parent 145da26184
commit d2bfd46a39

@ -9,6 +9,7 @@
*
* Copyright (C) 2025 Caleb, K4PHP
* Copyright (C) 2025 Bryan Biedenkapp, N2PLL
* Copyright (C) 2025 Steven Jennison, KD8RHO
*
*/
@ -29,6 +30,8 @@ namespace dvmconsole.Controls
/// </summary>
public partial class ChannelBox : UserControl, INotifyPropertyChanged
{
public readonly static Border BORDER_DEFAULT;
public readonly static Border BORDER_GREEN;
public readonly static LinearGradientBrush GRAY_GRADIENT;
public readonly static LinearGradientBrush DARK_GRAY_GRADIENT; // Delected/Disconnected Color
public readonly static LinearGradientBrush BLUE_GRADIENT; // Selected Channel Color
@ -265,6 +268,17 @@ namespace dvmconsole.Controls
}
}
private bool isPrimary = false;
public bool IsPrimary
{
get => isPrimary;
set
{
isPrimary = value;
UpdateBackground();
}
}
/// <summary>
/// Current volume for this channel.
/// </summary>
@ -364,6 +378,19 @@ namespace dvmconsole.Controls
ORANGE_GRADIENT.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#F0FFAF00"), 0.485));
ORANGE_GRADIENT.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#F0C68700"), 0.517));
BORDER_DEFAULT = new Border
{
BorderBrush = new SolidColorBrush(Colors.LightGray),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8)
};
BORDER_GREEN = new Border
{
BorderBrush = new SolidColorBrush(Colors.Green),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8)
};
}
/// <summary>
@ -510,6 +537,13 @@ namespace dvmconsole.Controls
}
ControlBorder.Background = IsSelected ? BLUE_GRADIENT : DARK_GRAY_GRADIENT;
if (IsSelected)
if (IsPrimary)
ControlBorder.BorderBrush = BORDER_GREEN.BorderBrush;
else
ControlBorder.BorderBrush = BORDER_DEFAULT.BorderBrush;
else
ControlBorder.BorderBrush = BORDER_DEFAULT.BorderBrush;
}
/// <summary>
@ -530,6 +564,28 @@ namespace dvmconsole.Controls
/// <param name="e"></param>
private void ChannelBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (IsSelected)
{
// Check if either CTRL key is down, if so toggle PRIMARY state instead of deselecting
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
// If current channel is PRIMARY, clear it, otherwise set current to primary
if (selectedChannelsManager.PrimaryChannel == this)
{
selectedChannelsManager.ClearPrimaryChannel();
IsPrimary = false;
}
else
{
selectedChannelsManager.SetPrimaryChannel(this);
IsPrimary = true;
}
// Shortcut return, do not run the rest of this method
return;
}
}
IsSelected = !IsSelected;
ControlBorder.Background = IsSelected ? BLUE_GRADIENT : DARK_GRAY_GRADIENT;
@ -544,7 +600,7 @@ namespace dvmconsole.Controls
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PttButton_Click(object sender, RoutedEventArgs e)
public void PttButton_Click(object sender, RoutedEventArgs e)
{
if (!IsSelected)
return;

@ -168,10 +168,23 @@ namespace dvmconsole
btnGlobalPtt.MouseRightButtonDown += btnGlobalPtt_MouseRightButtonDown;
selectedChannelsManager.SelectedChannelsChanged += SelectedChannelsChanged;
selectedChannelsManager.PrimaryChannelChanged += PrimaryChannelChanged;
SizeChanged += MainWindow_SizeChanged;
Loaded += MainWindow_Loaded;
}
private void PrimaryChannelChanged()
{
var primaryChannel = selectedChannelsManager.PrimaryChannel;
foreach (UIElement element in channelsCanvas.Children)
{
if (element is ChannelBox box)
{
box.IsPrimary = box == primaryChannel;
}
}
}
/// <summary>
/// Helper to enable menu controls for Commands submenu.
/// </summary>
@ -631,10 +644,14 @@ namespace dvmconsole
{
try
{
foreach (ChannelBox channel in selectedChannelsManager.GetSelectedChannels())
var channel = selectedChannelsManager.PrimaryChannel;
if (channel == null)
{
return;
}
if (channel.SystemName == PLAYBACKSYS || channel.ChannelName == PLAYBACKCHNAME || channel.DstId == PLAYBACKTG)
continue;
return;
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
if (system == null)
@ -642,7 +659,7 @@ namespace dvmconsole
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_SYSTEM} {channel.SystemName}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
return;
}
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
@ -651,7 +668,7 @@ namespace dvmconsole
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_CODEPLUG_CHANNEL}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
return;
}
PeerSystem fne = fneSystemManager.GetFneSystem(system.Name);
@ -660,7 +677,7 @@ namespace dvmconsole
Log.WriteLine($"{channel.ChannelName} has a {ERR_INVALID_FNE_REF}. {ERR_INVALID_CODEPLUG}. {ERR_SKIPPING_AUDIO}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
return;
}
//
@ -745,7 +762,6 @@ namespace dvmconsole
});
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Failed to process alert tone: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
@ -1917,61 +1933,12 @@ namespace dvmconsole
{
if (globalPttState)
await Task.Delay(500);
foreach (ChannelBox channel in selectedChannelsManager.GetSelectedChannels())
{
if (channel.SystemName == PLAYBACKSYS || channel.ChannelName == PLAYBACKCHNAME || channel.DstId == PLAYBACKTG)
continue;
Codeplug.System system = Codeplug.GetSystemForChannel(channel.ChannelName);
if (system == null)
{
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_SYSTEM} {channel.SystemName}. {ERR_INVALID_CODEPLUG}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
}
Codeplug.Channel cpgChannel = Codeplug.GetChannelByName(channel.ChannelName);
if (cpgChannel == null)
{
Log.WriteLine($"{channel.ChannelName} refers to an {INVALID_CODEPLUG_CHANNEL}. {ERR_INVALID_CODEPLUG}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
}
PeerSystem fne = fneSystemManager.GetFneSystem(system.Name);
if (fne == null)
{
Log.WriteLine($"{channel.ChannelName} has a {ERR_INVALID_FNE_REF}. {ERR_INVALID_CODEPLUG}.");
channel.IsSelected = false;
selectedChannelsManager.RemoveSelectedChannel(channel);
continue;
}
channel.TxStreamId = fne.NewStreamId();
if (globalPttState)
ChannelBox channel = selectedChannelsManager.PrimaryChannel;
if (channel == null)
{
Dispatcher.Invoke(() =>
{
btnGlobalPtt.Background = ChannelBox.RED_GRADIENT;
channel.PttState = true;
});
fne.SendP25TDU(uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), true);
}
else
{
Dispatcher.Invoke(() =>
{
btnGlobalPtt.Background = ChannelBox.GRAY_GRADIENT;
channel.PttState = false;
});
fne.SendP25TDU(uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), false);
}
return;
}
channel.PttButton_Click(sender,e);
}
/// <summary>

@ -8,6 +8,7 @@
* @license AGPLv3 License (https://opensource.org/licenses/AGPL-3.0)
*
* Copyright (C) 2024 Caleb, K4PHP
* Copyright (C) 2025 Steven Jennison, KD8RHO
*
*/
@ -20,8 +21,11 @@ namespace dvmconsole
/// </summary>
public class SelectedChannelsManager
{
private ChannelBox primaryChannel;
private readonly HashSet<ChannelBox> selectedChannels;
public ChannelBox PrimaryChannel => primaryChannel;
public IReadOnlyCollection<ChannelBox> GetSelectedChannels() => selectedChannels;
/*
@ -33,6 +37,10 @@ namespace dvmconsole
/// </summary>
public event Action SelectedChannelsChanged;
/// <summary>
/// Triggered when primary channel is changed
/// </summary>
public event Action PrimaryChannelChanged;
/*
** Methods
*/
@ -54,7 +62,7 @@ namespace dvmconsole
if (selectedChannels.Add(channel))
{
channel.IsSelected = true;
SelectedChannelsChanged.Invoke();
SelectedChannelsChanged?.Invoke();
}
}
@ -66,8 +74,13 @@ namespace dvmconsole
{
if (selectedChannels.Remove(channel))
{
if (primaryChannel == channel)
{
ClearPrimaryChannel();
}
channel.IsPrimary = false;
channel.IsSelected = false;
SelectedChannelsChanged.Invoke();
SelectedChannelsChanged?.Invoke();
}
}
@ -80,7 +93,27 @@ namespace dvmconsole
channel.IsSelected = false;
selectedChannels.Clear();
SelectedChannelsChanged.Invoke();
SelectedChannelsChanged?.Invoke();
}
/// <summary>
/// Sets primary channel to the passed ChannelBox
/// </summary>
/// <param name="channel"></param>
public void SetPrimaryChannel(ChannelBox channel)
{
Log.WriteLine($"Setting primary channel to {channel.ChannelName}");
primaryChannel = channel;
PrimaryChannelChanged?.Invoke();
}
/// <summary>
/// Clears the primary channel selection, setting it to null
/// </summary>
public void ClearPrimaryChannel()
{
primaryChannel = null;
PrimaryChannelChanged?.Invoke();
}
} // public class SelectedChannelsManager
} // namespace dvmconsole

Loading…
Cancel
Save

Powered by TurnKey Linux.