Skip to content

Commit

Permalink
Merge pull request #28 from FaithBeam/custom-theme
Browse files Browse the repository at this point in the history
Move Theme Values into Db
  • Loading branch information
FaithBeam authored Oct 19, 2024
2 parents ff0221d + 2883ded commit 46b84ea
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 131 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This is an attempt at a cross-platform clone of X-Mouse-Button-Control.

![Image of YMouseButtonControl](https://github.com/user-attachments/assets/b85448e5-3f94-498b-b1f9-f442aad753e5)
![YMouseButtonControl 0 22 0](https://github.com/user-attachments/assets/a42266b8-dead-4dfd-b894-2deba1e9aa7e)

## Usage

Expand Down
13 changes: 13 additions & 0 deletions YMouseButtonControl.Core/Mappings/ThemeMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Riok.Mapperly.Abstractions;
using YMouseButtonControl.Core.ViewModels.Models;
using YMouseButtonControl.DataAccess.Models;

namespace YMouseButtonControl.Core.Mappings;

[Mapper]
public static partial class ThemeMapper
{
public static partial ThemeVm Map(Theme? theme);

public static partial Theme Map(ThemeVm? vm);
}
84 changes: 84 additions & 0 deletions YMouseButtonControl.Core/Repositories/ThemeRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using YMouseButtonControl.Core.Mappings;
using YMouseButtonControl.Core.ViewModels.Models;
using YMouseButtonControl.DataAccess.Context;
using YMouseButtonControl.DataAccess.Models;
using YMouseButtonControl.DataAccess.Queries;

namespace YMouseButtonControl.Core.Repositories;

public class ThemeRepository(YMouseButtonControlDbContext ctx, ThemeQueries queries)
: IRepository<Theme, ThemeVm>
{
private const string TblName = "Themes";

public int Add(ThemeVm vm)
{
using var conn = ctx.CreateConnection();
return conn.Query<int>(queries.Add(), ThemeMapper.Map(vm)).Single();
}

public Task<int> AddAsync(ThemeVm vm)
{
throw new NotImplementedException();
}

public int Delete(ThemeVm vm)
{
using var conn = ctx.CreateConnection();
return conn.Execute(queries.DeleteById(TblName), new { ThemeMapper.Map(vm).Id });
}

public Task<int> DeleteAsync(ThemeVm vm)
{
throw new NotImplementedException();
}

public IEnumerable<ThemeVm> GetAll()
{
using var conn = ctx.CreateConnection();
return conn.Query<Theme>(queries.GetAll(TblName)).Select(ThemeMapper.Map);
}

public Task<IEnumerable<ThemeVm>> GetAllAsync()
{
throw new NotImplementedException();
}

public ThemeVm? GetById(int id)
{
using var conn = ctx.CreateConnection();
return ThemeMapper.Map(
conn.QueryFirstOrDefault<Theme>(queries.GetById(TblName), new { Id = id })
);
}

public Task<ThemeVm?> GetByIdAsync(int id)
{
throw new NotImplementedException();
}

public ThemeVm? GetByName(string name)
{
using var conn = ctx.CreateConnection();
return ThemeMapper.Map(
conn.QuerySingleOrDefault<Theme>(queries.GetByName(TblName), new { Name = name })
);
}

public int Update(ThemeVm vm)
{
using var conn = ctx.CreateConnection();
return conn.Execute(queries.Update(), ThemeMapper.Map(vm));
}

public Task<int> UpdateAsync(ThemeVm vm)
{
throw new NotImplementedException();
}
}
179 changes: 100 additions & 79 deletions YMouseButtonControl.Core/Services/Theme/ThemeService.cs
Original file line number Diff line number Diff line change
@@ -1,125 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
using Avalonia.Media;
using Avalonia.Styling;
using ReactiveUI;
using YMouseButtonControl.Core.Repositories;
using YMouseButtonControl.Core.Services.Settings;
using YMouseButtonControl.Core.ViewModels.Models;
using YMouseButtonControl.DataAccess.Models;

namespace YMouseButtonControl.Core.Services.Theme;

public interface IThemeService
{
IBrush HighlightLight { get; set; }
IBrush HighlightDark { get; set; }
IBrush BackgroundDark { get; set; }
IBrush BackgroundLight { get; set; }
IBrush CurBackground { get; set; }
IBrush CurHighlight { get; set; }
public IBrush Background { get; }
public IBrush Highlight { get; }
ThemeVariant ThemeVariant { get; }
List<ThemeVm> Themes { get; }
}

public class ThemeService : ReactiveObject, IThemeService
{
private readonly IRepository<DataAccess.Models.Theme, ThemeVm> _themeRepo;
private readonly SettingIntVm _themeSetting;
private IBrush _highlightLight = Brushes.Yellow;
private IBrush _highlightDark = Brush.Parse("#3700b3");
private IBrush _backgroundDark = Brushes.Black;
private IBrush _backgroundLight = Brushes.White;
private IBrush _curBackground;
private IBrush _curHighlight;
private ThemeVariant _themeVariant;

public ThemeService(ISettingsService settingsService)
private readonly ThemeVm _themeVm;
private IBrush _background;
private IBrush _highlight;
private readonly ThemeVariant _themeVariant;

public ThemeService(
IRepository<DataAccess.Models.Theme, ThemeVm> themeRepo,
ISettingsService settingsService
)
{
_themeRepo = themeRepo;
_themeSetting =
settingsService.GetSetting("Theme") as SettingIntVm
?? throw new Exception("Error retrieving theme setting");
_curBackground = GetCurrentThemeBackground();
_curHighlight = GetCurrentThemeHighlight();
_themeVm =
_themeRepo.GetById(_themeSetting.IntValue)
?? throw new Exception($"Error retrieving theme with id: {_themeSetting.IntValue}");
_themeVariant = GetThemeVariant();
_background = GetBackground();
_highlight = GetHighlight();
}

public IBrush HighlightLight
{
get => _highlightLight;
set => this.RaiseAndSetIfChanged(ref _highlightLight, value);
}

public IBrush HighlightDark
{
get => _highlightDark;
set => this.RaiseAndSetIfChanged(ref _highlightDark, value);
}
public List<ThemeVm> Themes => [.. _themeRepo.GetAll().OrderBy(x => x.Id)];

public IBrush BackgroundDark
{
get => _backgroundDark;
set => this.RaiseAndSetIfChanged(ref _backgroundDark, value);
}

public IBrush BackgroundLight
{
get => _backgroundLight;
set => this.RaiseAndSetIfChanged(ref _backgroundLight, value);
}
public ThemeVariant ThemeVariant => _themeVariant;

public IBrush CurBackground
public IBrush Background
{
get => _curBackground;
set => this.RaiseAndSetIfChanged(ref _curBackground, value);
get => _background;
set => this.RaiseAndSetIfChanged(ref _background, value);
}

public IBrush CurHighlight
public IBrush Highlight
{
get => _curHighlight;
set => this.RaiseAndSetIfChanged(ref _curHighlight, value);
get => _highlight;
set => this.RaiseAndSetIfChanged(ref _highlight, value);
}

public ThemeVariant ThemeVariant => _themeVariant;

private ThemeVariant GetThemeVariant()
private IBrush GetBackground()
{
var theme = (ThemeEnum)_themeSetting.IntValue;
return theme switch
// Background is of the form #aarrggbb
if (_themeVm.Background.StartsWith('#'))
{
ThemeEnum.Default => ThemeVariant.Default,
ThemeEnum.Light => ThemeVariant.Light,
ThemeEnum.Dark => ThemeVariant.Dark,
_ => throw new ArgumentOutOfRangeException($"Invalid theme {theme}"),
};
return Brush.Parse(_themeVm.Background);
}

// Background is an avalonia resource like SystemAltHighColor
if (
Application.Current!.TryGetResource(
_themeVm.Background,
Application.Current.ActualThemeVariant,
out var backgroundBrush
)
)
{
if (backgroundBrush is null)
{
throw new Exception("Error retrieving background brush");
}
var bbStr = backgroundBrush.ToString();
if (string.IsNullOrWhiteSpace(bbStr))
{
throw new Exception("Error retrieving background brush");
}
var brush = Brush.Parse(bbStr);
return brush;
}

// Background may be a color like White, Black, etc.
return Brush.Parse(_themeVm.Background);
}

private IBrush GetCurrentThemeBackground()
private IBrush GetHighlight()
{
var theme = (ThemeEnum)_themeSetting.IntValue;

return theme switch
// Highlight is of the form #aarrggbb
if (_themeVm.Highlight.StartsWith('#'))
{
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Light =>
_backgroundLight,
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Dark =>
_backgroundDark,
ThemeEnum.Light => _backgroundLight,
ThemeEnum.Dark => _backgroundDark,
_ => throw new ArgumentOutOfRangeException($"Unknown theme {theme}"),
};
return Brush.Parse(_themeVm.Highlight);
}

// Highlight is an avalonia resource like SystemAltHighColor
if (
Application.Current!.TryGetResource(
_themeVm.Highlight,
Application.Current.ActualThemeVariant,
out var highlightBrush
)
)
{
if (highlightBrush is null)
{
throw new Exception("Error retrieving highlight brush");
}
var bbStr = highlightBrush.ToString();
if (string.IsNullOrWhiteSpace(bbStr))
{
throw new Exception("Error retrieving highlight brush");
}
var brush = Brush.Parse(bbStr);
return brush;
}

// Highlight may be a color like White, Black, etc.
return Brush.Parse(_themeVm.Highlight);
}

private IBrush GetCurrentThemeHighlight()
private ThemeVariant GetThemeVariant()
{
var theme = (ThemeEnum)_themeSetting.IntValue;

return theme switch
return _themeSetting.IntValue switch
{
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Light =>
_highlightLight,
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Dark =>
_highlightDark,
ThemeEnum.Light => _highlightLight,
ThemeEnum.Dark => _highlightDark,
_ => throw new Exception($"Unknown theme {theme}"),
1 => Application.Current!.ActualThemeVariant == ThemeVariant.Light
? ThemeVariant.Light
: ThemeVariant.Dark,
2 => ThemeVariant.Light,
3 => ThemeVariant.Dark,
_ => throw new ArgumentOutOfRangeException(
$"Invalid theme id: {_themeSetting.IntValue}"
),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public MouseComboViewModel(
IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
)
{
_backgroundColor = themeService.CurBackground;
_backgroundColor = themeService.Background;
switch (mouseButton)
{
case MouseButton.Mb1:
Expand All @@ -56,14 +56,14 @@ IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
{
if (next.Button == (YMouseButton)(mouseButton + 1))
{
BackgroundColor = themeService.CurHighlight;
BackgroundColor = themeService.Highlight;
}
});
_mbUpDisposable = mouseListener.OnMouseReleasedChanged.Subscribe(next =>
{
if (next.Button == (YMouseButton)(mouseButton + 1))
{
BackgroundColor = themeService.CurBackground;
BackgroundColor = themeService.Background;
}
});
break;
Expand All @@ -73,7 +73,7 @@ IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
case MouseButton.Mwr:
_wheelTimer.Elapsed += delegate
{
BackgroundColor = themeService.CurBackground;
BackgroundColor = themeService.Background;
};
_mWheelDisposable = mouseListener.OnMouseWheelChanged.Subscribe(next =>
{
Expand Down Expand Up @@ -149,7 +149,7 @@ await ShowSimulatedKeystrokesDialogService.ShowSimulatedKeystrokesDialog(

void MouseWheelDoHighlight()
{
BackgroundColor = themeService.CurHighlight;
BackgroundColor = themeService.Highlight;
if (!_wheelTimer.Enabled)
{
_wheelTimer.Start();
Expand Down
Loading

0 comments on commit 46b84ea

Please sign in to comment.