Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions WindowsEdgeLight/Commands/RelayCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Windows.Input;

namespace WindowsEdgeLight.Commands;

/// <summary>
/// A command whose sole purpose is to relay its functionality to other objects by invoking delegates.
/// </summary>
public class RelayCommand : ICommand
{
private readonly Action<object?> _execute;
private readonly Func<object?, bool>? _canExecute;

/// <summary>
/// Initializes a new instance of the RelayCommand class.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic (optional).</param>
public RelayCommand(Action<object?> execute, Func<object?, bool>? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}

/// <summary>
/// Determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command.</param>
/// <returns>True if the command can execute; otherwise, false.</returns>
public bool CanExecute(object? parameter)
{
return _canExecute?.Invoke(parameter) ?? true;
}

/// <summary>
/// Executes the command.
/// </summary>
/// <param name="parameter">Data used by the command.</param>
public void Execute(object? parameter)
{
_execute(parameter);
}

/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler? CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}

/// <summary>
/// Raises the CanExecuteChanged event.
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
24 changes: 15 additions & 9 deletions WindowsEdgeLight/ControlWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
using System.Windows;
using WindowsEdgeLight.ViewModels;

namespace WindowsEdgeLight;

public partial class ControlWindow : Window
{
private readonly MainWindow mainWindow;
private readonly MainViewModel viewModel;

public ControlWindow(MainWindow main)
{
InitializeComponent();
mainWindow = main;
viewModel = (MainViewModel)main.DataContext;

// Set DataContext for binding
DataContext = viewModel;

// Disable switch monitor button if only one monitor
UpdateMonitorButtonState();
}

private void UpdateMonitorButtonState()
{
SwitchMonitorButton.IsEnabled = mainWindow.HasMultipleMonitors() && !mainWindow.IsShowingOnAllMonitors();
SwitchMonitorButton.IsEnabled = mainWindow.HasMultipleMonitors() && !viewModel.ShowOnAllMonitors;
AllMonitorsButton.IsEnabled = mainWindow.HasMultipleMonitors();
}

Expand All @@ -28,42 +34,42 @@ public void UpdateAllMonitorsButtonState()

private void BrightnessDown_Click(object sender, RoutedEventArgs e)
{
mainWindow.DecreaseBrightness();
viewModel.DecreaseBrightnessCommand.Execute(null);
}

private void BrightnessUp_Click(object sender, RoutedEventArgs e)
{
mainWindow.IncreaseBrightness();
viewModel.IncreaseBrightnessCommand.Execute(null);
}

private void ColorCooler_Click(object sender, RoutedEventArgs e)
{
mainWindow.DecreaseColorTemperature();
viewModel.DecreaseColorTemperatureCommand.Execute(null);
}

private void ColorWarmer_Click(object sender, RoutedEventArgs e)
{
mainWindow.IncreaseColorTemperature();
viewModel.IncreaseColorTemperatureCommand.Execute(null);
}

private void Toggle_Click(object sender, RoutedEventArgs e)
{
mainWindow.HandleToggle();
viewModel.ToggleLightCommand.Execute(null);
}

private void SwitchMonitor_Click(object sender, RoutedEventArgs e)
{
mainWindow.MoveToNextMonitor();
viewModel.MoveToNextMonitorCommand.Execute(null);
UpdateMonitorButtonState();
}

private void AllMonitors_Click(object sender, RoutedEventArgs e)
{
mainWindow.ToggleAllMonitors();
viewModel.ToggleAllMonitorsCommand.Execute(null);
}

private void Close_Click(object sender, RoutedEventArgs e)
{
System.Windows.Application.Current.Shutdown();
viewModel.ExitCommand.Execute(null);
}
}
30 changes: 30 additions & 0 deletions WindowsEdgeLight/Converters/BooleanToVisibilityConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace WindowsEdgeLight.Converters;

/// <summary>
/// Converts a boolean value to a Visibility value.
/// True = Visible, False = Collapsed
/// </summary>
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolValue)
{
return boolValue ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility visibility)
{
return visibility == Visibility.Visible;
}
return false;
}
}
15 changes: 11 additions & 4 deletions WindowsEdgeLight/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowsEdgeLight"
xmlns:converters="clr-namespace:WindowsEdgeLight.Converters"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Windows Edge Light"
Width="800"
Expand All @@ -18,6 +19,10 @@
WindowStyle="None"
mc:Ignorable="d">

<Window.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>

<Window.TaskbarItemInfo>
<TaskbarItemInfo Description="Windows Edge Light - Right-click for options" />
</Window.TaskbarItemInfo>
Expand All @@ -28,13 +33,15 @@
x:Name="EdgeLightBorder"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="None">
Stretch="None"
Opacity="{Binding CurrentOpacity}"
Visibility="{Binding IsLightVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
<Path.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0.0" Color="#FFFFFF" />
<GradientStop Offset="0.3" Color="#F0F0F0" />
<GradientStop Offset="0.5" Color="#FFFFFF" />
<GradientStop Offset="0.7" Color="#F0F0F0" />
<GradientStop Offset="0.3" Color="{Binding EdgeColor}" />
<GradientStop Offset="0.5" Color="{Binding EdgeColor}" />
<GradientStop Offset="0.7" Color="{Binding EdgeColor}" />
<GradientStop Offset="1.0" Color="#FFFFFF" />
</LinearGradientBrush>
</Path.Fill>
Expand Down
Loading