Skip to content

Commit 7e7a19f

Browse files
committed
Wip custom theming
1 parent ff0221d commit 7e7a19f

14 files changed

Lines changed: 285 additions & 130 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Riok.Mapperly.Abstractions;
2+
using YMouseButtonControl.Core.ViewModels.Models;
3+
using YMouseButtonControl.DataAccess.Models;
4+
5+
namespace YMouseButtonControl.Core.Mappings;
6+
7+
[Mapper]
8+
public static partial class ThemeMapper
9+
{
10+
public static partial ThemeVm Map(Theme? theme);
11+
12+
public static partial Theme Map(ThemeVm? vm);
13+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Data;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Dapper;
7+
using YMouseButtonControl.Core.Mappings;
8+
using YMouseButtonControl.Core.ViewModels.Models;
9+
using YMouseButtonControl.DataAccess.Context;
10+
using YMouseButtonControl.DataAccess.Models;
11+
using YMouseButtonControl.DataAccess.Queries;
12+
13+
namespace YMouseButtonControl.Core.Repositories;
14+
15+
public class ThemeRepository(YMouseButtonControlDbContext ctx, ThemeQueries queries)
16+
: IRepository<Theme, ThemeVm>
17+
{
18+
private const string TblName = "Themes";
19+
20+
public int Add(ThemeVm vm)
21+
{
22+
using var conn = ctx.CreateConnection();
23+
return conn.Query<int>(queries.Add(), ThemeMapper.Map(vm)).Single();
24+
}
25+
26+
public Task<int> AddAsync(ThemeVm vm)
27+
{
28+
throw new NotImplementedException();
29+
}
30+
31+
public int Delete(ThemeVm vm)
32+
{
33+
using var conn = ctx.CreateConnection();
34+
return conn.Execute(queries.DeleteById(TblName), new { ThemeMapper.Map(vm).Id });
35+
}
36+
37+
public Task<int> DeleteAsync(ThemeVm vm)
38+
{
39+
throw new NotImplementedException();
40+
}
41+
42+
public IEnumerable<ThemeVm> GetAll()
43+
{
44+
using var conn = ctx.CreateConnection();
45+
return conn.Query<Theme>(queries.GetAll(TblName)).Select(ThemeMapper.Map);
46+
}
47+
48+
public Task<IEnumerable<ThemeVm>> GetAllAsync()
49+
{
50+
throw new NotImplementedException();
51+
}
52+
53+
public ThemeVm? GetById(int id)
54+
{
55+
using var conn = ctx.CreateConnection();
56+
return ThemeMapper.Map(
57+
conn.QueryFirstOrDefault<Theme>(queries.GetById(TblName), new { Id = id })
58+
);
59+
}
60+
61+
public Task<ThemeVm?> GetByIdAsync(int id)
62+
{
63+
throw new NotImplementedException();
64+
}
65+
66+
public ThemeVm? GetByName(string name)
67+
{
68+
using var conn = ctx.CreateConnection();
69+
return ThemeMapper.Map(
70+
conn.QuerySingleOrDefault<Theme>(queries.GetByName(TblName), new { Name = name })
71+
);
72+
}
73+
74+
public int Update(ThemeVm vm)
75+
{
76+
using var conn = ctx.CreateConnection();
77+
return conn.Execute(queries.Update(), ThemeMapper.Map(vm));
78+
}
79+
80+
public Task<int> UpdateAsync(ThemeVm vm)
81+
{
82+
throw new NotImplementedException();
83+
}
84+
}
Lines changed: 100 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,146 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using Avalonia;
35
using Avalonia.Media;
46
using Avalonia.Styling;
57
using ReactiveUI;
8+
using YMouseButtonControl.Core.Repositories;
69
using YMouseButtonControl.Core.Services.Settings;
710
using YMouseButtonControl.Core.ViewModels.Models;
8-
using YMouseButtonControl.DataAccess.Models;
911

1012
namespace YMouseButtonControl.Core.Services.Theme;
1113

1214
public interface IThemeService
1315
{
14-
IBrush HighlightLight { get; set; }
15-
IBrush HighlightDark { get; set; }
16-
IBrush BackgroundDark { get; set; }
17-
IBrush BackgroundLight { get; set; }
18-
IBrush CurBackground { get; set; }
19-
IBrush CurHighlight { get; set; }
16+
public IBrush Background { get; }
17+
public IBrush Highlight { get; }
2018
ThemeVariant ThemeVariant { get; }
19+
List<ThemeVm> Themes { get; }
2120
}
2221

2322
public class ThemeService : ReactiveObject, IThemeService
2423
{
24+
private readonly IRepository<DataAccess.Models.Theme, ThemeVm> _themeRepo;
2525
private readonly SettingIntVm _themeSetting;
26-
private IBrush _highlightLight = Brushes.Yellow;
27-
private IBrush _highlightDark = Brush.Parse("#3700b3");
28-
private IBrush _backgroundDark = Brushes.Black;
29-
private IBrush _backgroundLight = Brushes.White;
30-
private IBrush _curBackground;
31-
private IBrush _curHighlight;
32-
private ThemeVariant _themeVariant;
33-
34-
public ThemeService(ISettingsService settingsService)
26+
private readonly ThemeVm _themeVm;
27+
private IBrush _background;
28+
private IBrush _highlight;
29+
private readonly ThemeVariant _themeVariant;
30+
31+
public ThemeService(
32+
IRepository<DataAccess.Models.Theme, ThemeVm> themeRepo,
33+
ISettingsService settingsService
34+
)
3535
{
36+
_themeRepo = themeRepo;
3637
_themeSetting =
3738
settingsService.GetSetting("Theme") as SettingIntVm
3839
?? throw new Exception("Error retrieving theme setting");
39-
_curBackground = GetCurrentThemeBackground();
40-
_curHighlight = GetCurrentThemeHighlight();
40+
_themeVm =
41+
_themeRepo.GetById(_themeSetting.IntValue)
42+
?? throw new Exception($"Error retrieving theme with id: {_themeSetting.IntValue}");
4143
_themeVariant = GetThemeVariant();
44+
_background = GetBackground();
45+
_highlight = GetHighlight();
4246
}
4347

44-
public IBrush HighlightLight
45-
{
46-
get => _highlightLight;
47-
set => this.RaiseAndSetIfChanged(ref _highlightLight, value);
48-
}
49-
50-
public IBrush HighlightDark
51-
{
52-
get => _highlightDark;
53-
set => this.RaiseAndSetIfChanged(ref _highlightDark, value);
54-
}
48+
public List<ThemeVm> Themes => [.. _themeRepo.GetAll().OrderBy(x => x.Id)];
5549

56-
public IBrush BackgroundDark
57-
{
58-
get => _backgroundDark;
59-
set => this.RaiseAndSetIfChanged(ref _backgroundDark, value);
60-
}
61-
62-
public IBrush BackgroundLight
63-
{
64-
get => _backgroundLight;
65-
set => this.RaiseAndSetIfChanged(ref _backgroundLight, value);
66-
}
50+
public ThemeVariant ThemeVariant => _themeVariant;
6751

68-
public IBrush CurBackground
52+
public IBrush Background
6953
{
70-
get => _curBackground;
71-
set => this.RaiseAndSetIfChanged(ref _curBackground, value);
54+
get => _background;
55+
set => this.RaiseAndSetIfChanged(ref _background, value);
7256
}
7357

74-
public IBrush CurHighlight
58+
public IBrush Highlight
7559
{
76-
get => _curHighlight;
77-
set => this.RaiseAndSetIfChanged(ref _curHighlight, value);
60+
get => _highlight;
61+
set => this.RaiseAndSetIfChanged(ref _highlight, value);
7862
}
7963

80-
public ThemeVariant ThemeVariant => _themeVariant;
81-
82-
private ThemeVariant GetThemeVariant()
64+
private IBrush GetBackground()
8365
{
84-
var theme = (ThemeEnum)_themeSetting.IntValue;
85-
return theme switch
66+
// Background is of the form #aarrggbb
67+
if (_themeVm.Background.StartsWith('#'))
8668
{
87-
ThemeEnum.Default => ThemeVariant.Default,
88-
ThemeEnum.Light => ThemeVariant.Light,
89-
ThemeEnum.Dark => ThemeVariant.Dark,
90-
_ => throw new ArgumentOutOfRangeException($"Invalid theme {theme}"),
91-
};
69+
return Brush.Parse(_themeVm.Background);
70+
}
71+
72+
// Background is an avalonia resource like SystemAltHighColor
73+
if (
74+
Application.Current!.TryGetResource(
75+
_themeVm.Background,
76+
Application.Current.ActualThemeVariant,
77+
out var backgroundBrush
78+
)
79+
)
80+
{
81+
if (backgroundBrush is null)
82+
{
83+
throw new Exception("Error retrieving background brush");
84+
}
85+
var bbStr = backgroundBrush.ToString();
86+
if (string.IsNullOrWhiteSpace(bbStr))
87+
{
88+
throw new Exception("Error retrieving background brush");
89+
}
90+
var brush = Brush.Parse(bbStr);
91+
return brush;
92+
}
93+
94+
// Background may be a color like White, Black, etc.
95+
return Brush.Parse(_themeVm.Background);
9296
}
9397

94-
private IBrush GetCurrentThemeBackground()
98+
private IBrush GetHighlight()
9599
{
96-
var theme = (ThemeEnum)_themeSetting.IntValue;
97-
98-
return theme switch
100+
// Highlight is of the form #aarrggbb
101+
if (_themeVm.Highlight.StartsWith('#'))
99102
{
100-
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Light =>
101-
_backgroundLight,
102-
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Dark =>
103-
_backgroundDark,
104-
ThemeEnum.Light => _backgroundLight,
105-
ThemeEnum.Dark => _backgroundDark,
106-
_ => throw new ArgumentOutOfRangeException($"Unknown theme {theme}"),
107-
};
103+
return Brush.Parse(_themeVm.Highlight);
104+
}
105+
106+
// Highlight is an avalonia resource like SystemAltHighColor
107+
if (
108+
Application.Current!.TryGetResource(
109+
_themeVm.Highlight,
110+
Application.Current.ActualThemeVariant,
111+
out var highlightBrush
112+
)
113+
)
114+
{
115+
if (highlightBrush is null)
116+
{
117+
throw new Exception("Error retrieving highlight brush");
118+
}
119+
var bbStr = highlightBrush.ToString();
120+
if (string.IsNullOrWhiteSpace(bbStr))
121+
{
122+
throw new Exception("Error retrieving highlight brush");
123+
}
124+
var brush = Brush.Parse(bbStr);
125+
return brush;
126+
}
127+
128+
// Highlight may be a color like White, Black, etc.
129+
return Brush.Parse(_themeVm.Highlight);
108130
}
109131

110-
private IBrush GetCurrentThemeHighlight()
132+
private ThemeVariant GetThemeVariant()
111133
{
112-
var theme = (ThemeEnum)_themeSetting.IntValue;
113-
114-
return theme switch
134+
return _themeSetting.IntValue switch
115135
{
116-
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Light =>
117-
_highlightLight,
118-
ThemeEnum.Default when Application.Current?.ActualThemeVariant == ThemeVariant.Dark =>
119-
_highlightDark,
120-
ThemeEnum.Light => _highlightLight,
121-
ThemeEnum.Dark => _highlightDark,
122-
_ => throw new Exception($"Unknown theme {theme}"),
136+
1 => Application.Current!.ActualThemeVariant == ThemeVariant.Light
137+
? ThemeVariant.Light
138+
: ThemeVariant.Dark,
139+
2 => ThemeVariant.Light,
140+
3 => ThemeVariant.Dark,
141+
_ => throw new ArgumentOutOfRangeException(
142+
$"Invalid theme id: {_themeSetting.IntValue}"
143+
),
123144
};
124145
}
125146
}

YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public MouseComboViewModel(
4444
IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
4545
)
4646
{
47-
_backgroundColor = themeService.CurBackground;
47+
_backgroundColor = themeService.Background;
4848
switch (mouseButton)
4949
{
5050
case MouseButton.Mb1:
@@ -56,14 +56,14 @@ IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
5656
{
5757
if (next.Button == (YMouseButton)(mouseButton + 1))
5858
{
59-
BackgroundColor = themeService.CurHighlight;
59+
BackgroundColor = themeService.Highlight;
6060
}
6161
});
6262
_mbUpDisposable = mouseListener.OnMouseReleasedChanged.Subscribe(next =>
6363
{
6464
if (next.Button == (YMouseButton)(mouseButton + 1))
6565
{
66-
BackgroundColor = themeService.CurBackground;
66+
BackgroundColor = themeService.Background;
6767
}
6868
});
6969
break;
@@ -73,7 +73,7 @@ IShowSimulatedKeystrokesDialogService showSimulatedKeystrokesDialogService
7373
case MouseButton.Mwr:
7474
_wheelTimer.Elapsed += delegate
7575
{
76-
BackgroundColor = themeService.CurBackground;
76+
BackgroundColor = themeService.Background;
7777
};
7878
_mWheelDisposable = mouseListener.OnMouseWheelChanged.Subscribe(next =>
7979
{
@@ -149,7 +149,7 @@ await ShowSimulatedKeystrokesDialogService.ShowSimulatedKeystrokesDialog(
149149

150150
void MouseWheelDoHighlight()
151151
{
152-
BackgroundColor = themeService.CurHighlight;
152+
BackgroundColor = themeService.Highlight;
153153
if (!_wheelTimer.Enabled)
154154
{
155155
_wheelTimer.Start();

0 commit comments

Comments
 (0)