Skip to content

Commit a318f9a

Browse files
committed
New: Review score game fields #273
1 parent 81693b8 commit a318f9a

File tree

16 files changed

+540
-35
lines changed

16 files changed

+540
-35
lines changed

source/Playnite/GameHandler.cs

+18
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,24 @@ public static Game GetMultiGameEditObject(IEnumerable<IGame> games)
229229
dummyGame.CompletionStatus = firstCompletionStatus;
230230
}
231231

232+
var firstUserScore = firstGame.UserScore;
233+
if (games.All(a => a.UserScore == firstUserScore) == true)
234+
{
235+
dummyGame.UserScore = firstUserScore;
236+
}
237+
238+
var firstCriticScore = firstGame.CriticScore;
239+
if (games.All(a => a.CriticScore == firstCriticScore) == true)
240+
{
241+
dummyGame.CriticScore = firstCriticScore;
242+
}
243+
244+
var firstCommunityScore = firstGame.CommunityScore;
245+
if (games.All(a => a.CommunityScore == firstCommunityScore) == true)
246+
{
247+
dummyGame.CommunityScore = firstCommunityScore;
248+
}
249+
232250
return dummyGame;
233251
}
234252
}

source/Playnite/Models/Game.cs

+45
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,51 @@ public CompletionStatus CompletionStatus
630630
}
631631
}
632632

633+
private int? userScore = null;
634+
public int? UserScore
635+
{
636+
get
637+
{
638+
return userScore;
639+
}
640+
641+
set
642+
{
643+
userScore = value;
644+
OnPropertyChanged("UserScore");
645+
}
646+
}
647+
648+
private int? criticScore = null;
649+
public int? CriticScore
650+
{
651+
get
652+
{
653+
return criticScore;
654+
}
655+
656+
set
657+
{
658+
criticScore = value;
659+
OnPropertyChanged("CriticScore");
660+
}
661+
}
662+
663+
private int? communityScore = null;
664+
public int? CommunityScore
665+
{
666+
get
667+
{
668+
return communityScore;
669+
}
670+
671+
set
672+
{
673+
communityScore = value;
674+
OnPropertyChanged("CommunityScore");
675+
}
676+
}
677+
633678
public event PropertyChangedEventHandler PropertyChanged;
634679

635680
public Game()

source/Playnite/Models/IGame.cs

+15
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,21 @@ string Source
246246
get; set;
247247
}
248248

249+
int? UserScore
250+
{
251+
get; set;
252+
}
253+
254+
int? CriticScore
255+
{
256+
get; set;
257+
}
258+
259+
int? CommunityScore
260+
{
261+
get; set;
262+
}
263+
249264
CompletionStatus CompletionStatus
250265
{
251266
get; set;

source/Playnite/Settings/Settings.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,10 @@ public FilterSettings FilterSettings
408408
{ "AgeRating", false },
409409
{ "Region", false },
410410
{ "Source", false },
411-
{ "CompletionStatus", false }
411+
{ "CompletionStatus", false },
412+
{ "UserScore", false },
413+
{ "CriticScore", false },
414+
{ "CommunityScore", false }
412415
};
413416

414417
public ObservableConcurrentDictionary<string, bool> GridViewHeaders

source/Playnite/Settings/ViewProperties.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public enum SortOrder
3434
AgeRating,
3535
Region,
3636
Source,
37-
CompletionStatus
37+
CompletionStatus,
38+
UserScore,
39+
CriticScore,
40+
CommunityScore
3841
}
3942

4043
public enum SortOrderDirection

source/PlayniteUI/Controls/GamesGridView.xaml

+65
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
IsCheckable="True" IsChecked="{Binding GridViewHeaders[Added]}" />
152152
<MenuItem Header="{DynamicResource ModifiedLabel}"
153153
IsCheckable="True" IsChecked="{Binding GridViewHeaders[Modified]}" />
154+
<MenuItem Header="{DynamicResource UserScore}"
155+
IsCheckable="True" IsChecked="{Binding GridViewHeaders[UserScore]}" />
156+
<MenuItem Header="{DynamicResource CriticScore}"
157+
IsCheckable="True" IsChecked="{Binding GridViewHeaders[CriticScore]}" />
158+
<MenuItem Header="{DynamicResource CommunityScore}"
159+
IsCheckable="True" IsChecked="{Binding GridViewHeaders[CommunityScore]}" />
154160
</ContextMenu>
155161
</GridView.ColumnHeaderContextMenu>
156162

@@ -614,6 +620,65 @@
614620
</GridViewColumn.CellTemplate>
615621
</GridViewColumn>
616622

623+
<!-- UserScore -->
624+
<GridViewColumn Width="{Binding Path=DataContext.GridViewHeaders[UserScore], ElementName=HeaderMenu, Mode=TwoWay, Converter={StaticResource BoolToAutoWidthConverter}}">
625+
<GridViewColumn.Header>
626+
<GridViewColumnHeader Tag="{x:Static playnite:SortOrder.UserScore}">
627+
<GridViewColumnHeader.Content>
628+
<StackPanel Orientation="Horizontal">
629+
<TextBlock Text="{DynamicResource UserScore}" Style="{StaticResource BaseTextBlockStyle}" />
630+
<ContentControl Style="{StaticResource SortIndicator}"
631+
Visibility="{Binding Path=SortingOrder, Converter={StaticResource EnumCompVisibilityConverter}, ConverterParameter={x:Static playnite:SortOrder.UserScore}}"/>
632+
</StackPanel>
633+
</GridViewColumnHeader.Content>
634+
</GridViewColumnHeader>
635+
</GridViewColumn.Header>
636+
<GridViewColumn.CellTemplate>
637+
<DataTemplate>
638+
<TextBlock Text="{Binding UserScore, Mode=OneWay}" />
639+
</DataTemplate>
640+
</GridViewColumn.CellTemplate>
641+
</GridViewColumn>
642+
643+
<!-- CriticScore -->
644+
<GridViewColumn Width="{Binding Path=DataContext.GridViewHeaders[CriticScore], ElementName=HeaderMenu, Mode=TwoWay, Converter={StaticResource BoolToAutoWidthConverter}}">
645+
<GridViewColumn.Header>
646+
<GridViewColumnHeader Tag="{x:Static playnite:SortOrder.CriticScore}">
647+
<GridViewColumnHeader.Content>
648+
<StackPanel Orientation="Horizontal">
649+
<TextBlock Text="{DynamicResource CriticScore}" Style="{StaticResource BaseTextBlockStyle}" />
650+
<ContentControl Style="{StaticResource SortIndicator}"
651+
Visibility="{Binding Path=SortingOrder, Converter={StaticResource EnumCompVisibilityConverter}, ConverterParameter={x:Static playnite:SortOrder.CriticScore}}"/>
652+
</StackPanel>
653+
</GridViewColumnHeader.Content>
654+
</GridViewColumnHeader>
655+
</GridViewColumn.Header>
656+
<GridViewColumn.CellTemplate>
657+
<DataTemplate>
658+
<TextBlock Text="{Binding CriticScore, Mode=OneWay}" />
659+
</DataTemplate>
660+
</GridViewColumn.CellTemplate>
661+
</GridViewColumn>
662+
663+
<!-- CommunityScore -->
664+
<GridViewColumn Width="{Binding Path=DataContext.GridViewHeaders[CommunityScore], ElementName=HeaderMenu, Mode=TwoWay, Converter={StaticResource BoolToAutoWidthConverter}}">
665+
<GridViewColumn.Header>
666+
<GridViewColumnHeader Tag="{x:Static playnite:SortOrder.CommunityScore}">
667+
<GridViewColumnHeader.Content>
668+
<StackPanel Orientation="Horizontal">
669+
<TextBlock Text="{DynamicResource CommunityScore}" Style="{StaticResource BaseTextBlockStyle}" />
670+
<ContentControl Style="{StaticResource SortIndicator}"
671+
Visibility="{Binding Path=SortingOrder, Converter={StaticResource EnumCompVisibilityConverter}, ConverterParameter={x:Static playnite:SortOrder.CommunityScore}}"/>
672+
</StackPanel>
673+
</GridViewColumnHeader.Content>
674+
</GridViewColumnHeader>
675+
</GridViewColumn.Header>
676+
<GridViewColumn.CellTemplate>
677+
<DataTemplate>
678+
<TextBlock Text="{Binding CommunityScore, Mode=OneWay}" />
679+
</DataTemplate>
680+
</GridViewColumn.CellTemplate>
681+
</GridViewColumn>
617682
</GridView>
618683
</ListView.View>
619684
</ListView>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
using System.Windows.Controls;
8+
using System.Windows.Data;
9+
10+
namespace PlayniteUI.Controls
11+
{
12+
public class NullableIntBox : TextBox
13+
{
14+
public int MinValue
15+
{
16+
get
17+
{
18+
return (int)GetValue(MinValueProperty);
19+
}
20+
21+
set
22+
{
23+
SetValue(MinValueProperty, value);
24+
}
25+
}
26+
27+
public int MaxValue
28+
{
29+
get
30+
{
31+
return (int)GetValue(MaxLongValueProperty);
32+
}
33+
34+
set
35+
{
36+
SetValue(MaxLongValueProperty, value);
37+
}
38+
}
39+
40+
private int? lastValue;
41+
public int? Value
42+
{
43+
get
44+
{
45+
return (int?)GetValue(ValueProperty);
46+
}
47+
48+
set
49+
{
50+
lastValue = value;
51+
SetValue(ValueProperty, value);
52+
}
53+
}
54+
55+
public static readonly DependencyProperty ValueProperty =
56+
DependencyProperty.Register("Value", typeof(int?), typeof(NullableIntBox),
57+
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ValuePropertyChanged, CoerceValue, false, UpdateSourceTrigger.PropertyChanged));
58+
59+
public static readonly DependencyProperty MinValueProperty =
60+
DependencyProperty.Register("MinValue", typeof(int?), typeof(NullableIntBox),
61+
new PropertyMetadata(0, MinValuePropertyChanged));
62+
63+
public static readonly DependencyProperty MaxLongValueProperty =
64+
DependencyProperty.Register("MaxValue", typeof(int?), typeof(NullableIntBox),
65+
new PropertyMetadata(int.MaxValue, MaxValuePropertyChanged));
66+
67+
static NullableIntBox()
68+
{
69+
DefaultStyleKeyProperty.OverrideMetadata(typeof(NullableIntBox), new FrameworkPropertyMetadata(typeof(NullableIntBox)));
70+
}
71+
72+
public NullableIntBox()
73+
{
74+
Text = Value.ToString();
75+
LostFocus += NumericBox_LostFocus;
76+
Loaded += NumericBox_Loaded;
77+
}
78+
79+
private void NumericBox_Loaded(object sender, RoutedEventArgs e)
80+
{
81+
lastValue = Value;
82+
}
83+
84+
private void NumericBox_LostFocus(object sender, RoutedEventArgs e)
85+
{
86+
if (string.IsNullOrEmpty(Text))
87+
{
88+
Value = null;
89+
}
90+
else
91+
{
92+
if (!int.TryParse(Text, out var result))
93+
{
94+
Value = lastValue;
95+
}
96+
else
97+
{
98+
if (result >= MinValue && result <= MaxValue)
99+
{
100+
Value = result;
101+
}
102+
else
103+
{
104+
Value = lastValue;
105+
}
106+
}
107+
}
108+
}
109+
110+
private static object CoerceValue(DependencyObject element, object baseValue)
111+
{
112+
var box = (NullableIntBox)element;
113+
var value = (int?)baseValue;
114+
if (value == null)
115+
{
116+
box.Text = string.Empty;
117+
}
118+
else
119+
{
120+
box.Text = value.ToString();
121+
}
122+
123+
return value;
124+
}
125+
126+
private static void ValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
127+
{
128+
}
129+
130+
private static void MinValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
131+
{
132+
}
133+
134+
private static void MaxValuePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
135+
{
136+
}
137+
}
138+
}

source/PlayniteUI/GamesCollectionView.cs

+3
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ public class GameViewEntry : INotifyPropertyChanged
221221
public string Region => Game.Region;
222222
public string Source => Game.Source;
223223
public CompletionStatus CompletionStatus => Game.CompletionStatus;
224+
public int? UserScore => Game.UserScore;
225+
public int? CriticScore => Game.CriticScore;
226+
public int? CommunityScore => Game.CommunityScore;
224227

225228
public string Name
226229
{

source/PlayniteUI/Localization/english.xaml

+4
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,9 @@ It's currently being used by {1} game(s) and {2} emulator(s).</sys:String>
428428
<sys:String x:Key="Beaten">Beaten</sys:String>
429429
<sys:String x:Key="Completed">Completed</sys:String>
430430
<sys:String x:Key="CompletionStatus">Completion Status</sys:String>
431+
<sys:String x:Key="UserScore">User Score</sys:String>
432+
<sys:String x:Key="CriticScore">Critic Score</sys:String>
433+
<sys:String x:Key="CommunityScore">Community Score</sys:String>
431434

432435
<sys:String x:Key="EmulatorArguments">Emulator Arguments</sys:String>
433436
<sys:String x:Key="AdditionalEmulatorArguments">Additional Emulator Arguments</sys:String>
@@ -465,6 +468,7 @@ It's currently being used by {1} game(s) and {2} emulator(s).</sys:String>
465468
<sys:String x:Key="ProgreessAvailabilityMessage">Not available when some action is in progress.</sys:String>
466469
<sys:String x:Key="DescriptionHTMLSupportTooltip">Description text is HTML syntax sensitive</sys:String>
467470
<sys:String x:Key="DescriptionPlaytimeSeconds">Playtime is tracked and stored in seconds.</sys:String>
471+
<sys:String x:Key="DescriptionScoreValues">Accepts 0 to 100 or empty for no score.</sys:String>
468472
<sys:String x:Key="PatreonDevelopMessage">Playnite's development is supported by these patrons:</sys:String>
469473
<sys:String x:Key="AboutContributorsMessage">Code, localization and other contributors in no particular order:</sys:String>
470474

source/PlayniteUI/PlayniteUI.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
<Compile Include="Commands\GeneralCommands.cs" />
192192
<Compile Include="Commands\GenericCommands.cs" />
193193
<Compile Include="Commands\RelayCommand.cs" />
194+
<Compile Include="Controls\NullableIntBox.cs" />
194195
<Compile Include="Controls\NumericBox.cs" />
195196
<Compile Include="Controls\ExtendedListBox.cs" />
196197
<Compile Include="Controls\HtmlTextView.cs" />

0 commit comments

Comments
 (0)