Skip to content

Commit

Permalink
source cache, keygen
Browse files Browse the repository at this point in the history
  • Loading branch information
ShinyZero0 committed Mar 6, 2023
1 parent 4204b99 commit 32fb862
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 72 deletions.
4 changes: 4 additions & 0 deletions App.axaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ToDo"
xmlns:v="clr-namespace:ToDo.Views"
x:Class="ToDo.App">
<Application.DataTemplates>
<local:ViewLocator/>
Expand All @@ -10,4 +11,7 @@
<Application.Styles>
<FluentTheme />
</Application.Styles>
<Application.Resources>
<v:IsNotNullOrWhiteSpace x:Key="IsNotNullOrWhiteSpace"/>
</Application.Resources>
</Application>
1 change: 0 additions & 1 deletion Models/DataBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ToDo.Models
{
Expand Down
8 changes: 3 additions & 5 deletions Models/Saver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ public static DataBase Get()
using (var jsonSR = new StreamReader(_data))
{
string jsonstr = jsonSR.ReadToEnd();
if (
!string.IsNullOrWhiteSpace(jsonstr)
&& jsonstr.StartsWith("{")
&& jsonstr.EndsWith("}")
)
if (!string.IsNullOrWhiteSpace(jsonstr))
// && jsonstr.StartsWith("{")
// && jsonstr.EndsWith("}")
{
dataBase = JsonConvert.DeserializeObject<DataBase>(jsonstr);
}
Expand Down
6 changes: 2 additions & 4 deletions Models/ToDoItem.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using ToDo.ViewModels;

namespace ToDo.Models
{
public class ToDoItem
{
public string Name {get; set;}
public string Content {get; set;}
public string? Content {get; set;}
public bool IsDone {get; set;}
public int Priority {get; set;}
public ToDoItem(string n, string c, bool i, int p)
public ToDoItem(string n, string? c, bool i, int p)
{
Name = n;
Content = c;
Expand Down
5 changes: 3 additions & 2 deletions ViewModels/EditItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public EditItemViewModel(ItemViewModel EditedItem)
AcceptEditedItemCommand = ReactiveCommand.Create(() =>
{
EditedItem.Name = Name;
if (string.IsNullOrWhiteSpace(Content)) Content = null;
EditedItem.Content = Content;
return EditedItem;
});
Expand All @@ -28,8 +29,8 @@ public string Name
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
private string _content;
public string Content
private string? _content;
public string? Content
{
get => _content;
set => this.RaiseAndSetIfChanged(ref _content, value);
Expand Down
8 changes: 5 additions & 3 deletions ViewModels/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ namespace ToDo.ViewModels;

public class ItemViewModel : ViewModelBase
{
public ItemViewModel(ToDoItem item)
public ItemViewModel(ToDoItem item, uint key)
{
Name = item.Name;
Content = item.Content;
IsDone = item.IsDone;
Priority = item.Priority;
Key = key;
}

public ToDoItem ToToDoItem()
{
return new ToDoItem(this.Name, this.Content, this.IsDone, this.Priority);
}

private string _content;
public string Content
private string? _content;
public string? Content
{
get => _content;
set => this.RaiseAndSetIfChanged(ref _content, value);
Expand All @@ -42,4 +43,5 @@ public int Priority
get => _priority;
set => this.RaiseAndSetIfChanged(ref _priority, value);
}
public uint Key;
}
78 changes: 48 additions & 30 deletions ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using ToDo.Models;
using System.Collections.Generic;
using System.Linq;

// using Lucene.Net;

namespace ToDo.ViewModels;
Expand All @@ -20,52 +21,58 @@ public MainWindowViewModel()
{
// Добавить элементы в список из JSON
DB = Saver.Get();
_sourceList = new SourceList<ItemViewModel>();
_sourceCache = new SourceCache<ItemViewModel, uint>(i => i.Key);
foreach (ToDoItem item in DB.Items)
{
_sourceList.Add(new ItemViewModel(item));
_sourceCache.AddOrUpdate(new ItemViewModel(item, KeyGen()));
}

// Поиск
var filter = this.WhenAnyValue(vm => vm.SearchText)
.Throttle(TimeSpan.FromMilliseconds(50))
.Select(MakeFilter);

// Забиндить список к ReadOnlyObservableCollection
_sourceList
// Забиндить список к Colle

_sourceCache
.Connect()
.StartWithEmpty()
// .AutoRefreshOnObservable(item => item.WhenAnyValue(i => i.IsDone, i => i.Name))
.Filter(filter)
// .Sort(SortExpressionComparer<ItemViewModel>.Ascending(i => Convert.ToByte(i.IsDone)))
// .AutoRefreshOnObservable(item => item.WhenAnyValue(i => i.IsDone, i => i.Name))
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _colle)
.DisposeMany()
.Subscribe();

// .AutoRefreshOnObservable(item => item.WhenAnyValue(i => i.IsDone, i => i.Name))
// .ThenByAscending(i => i.Name)

// СТАТИСТИКА

var shared = _sourceList
.Connect()
.AutoRefreshOnObservable(item => item.WhenAnyValue(x => x.IsDone))
.ObserveOn(RxApp.MainThreadScheduler)
.Publish();

_cleanStats = new CompositeDisposable(
shared.Filter(item => item.IsDone == true).Count().Subscribe(cnt => DoneItemsCnt = cnt),
shared.Count().Subscribe(cnt => ItemsCnt = cnt),
shared.Connect()
);
// var shared = _sourceCache
// .Connect()
// .AutoRefreshOnObservable(item => item.WhenAnyValue(x => x.IsDone))
// .ObserveOn(RxApp.MainThreadScheduler)
// .Publish();
//
// _cleanStats = new CompositeDisposable(
// shared.Filter(item => item.IsDone == true).Count().Subscribe(cnt => DoneItemsCnt = cnt),
// shared.Count().Subscribe(cnt => ItemsCnt = cnt),
// shared.Connect()
// );

// НОВАЯ ЗАДАЧА

ShowNewItemDialog = new Interaction<NewItemViewModel, ItemViewModel?>();
ShowNewItemDialog = new Interaction<NewItemViewModel, ToDoItem?>();

NewItemCommand = ReactiveCommand.CreateFromTask(async () =>
{
var adder = new NewItemViewModel();
var result = await ShowNewItemDialog.Handle(adder);
if (result is not null)
{
_sourceList.Add(result);
_sourceCache.AddOrUpdate(new ItemViewModel (result, KeyGen()));
}
});

Expand All @@ -75,15 +82,16 @@ public MainWindowViewModel()

EditItemCommand = ReactiveCommand.CreateFromTask(async () =>
{
var result = await ShowEditItemDialog.Handle(Colle[SelectedIndex]);
var result = await ShowEditItemDialog.Handle(SelectedItem);
if (result is not null)
{
_sourceList.ReplaceAt(SelectedIndex, result);
// _sourceCache.Remove(SelectedItem);
_sourceCache.AddOrUpdate(result);
}
});

// Удалить задачу
RemoveItemCommand = ReactiveCommand.Create(() => _sourceList.RemoveAt(SelectedIndex));
RemoveItemCommand = ReactiveCommand.Create(() => _sourceCache.Remove(SelectedItem));

// Активация VM
Activator = new ViewModelActivator();
Expand All @@ -101,25 +109,25 @@ public MainWindowViewModel()
}

// Коллекции
private SourceList<ItemViewModel> _sourceList;
private SourceCache<ItemViewModel, uint> _sourceCache;
private readonly ReadOnlyObservableCollection<ItemViewModel> _colle;
public ReadOnlyObservableCollection<ItemViewModel> Colle => _colle;

// Новая задача
public IReactiveCommand NewItemCommand { get; }
public Interaction<NewItemViewModel, ItemViewModel?> ShowNewItemDialog { get; set; }
public Interaction<NewItemViewModel, ToDoItem?> ShowNewItemDialog { get; set; }

// Редактирование задач
public IReactiveCommand EditItemCommand { get; }
public Interaction<ItemViewModel, ItemViewModel?> ShowEditItemDialog { get; set; }

// Удаление задач
public IReactiveCommand RemoveItemCommand { get; }
private int _selectedIndex;
public int SelectedIndex
private ItemViewModel _selectedItem;
public ItemViewModel SelectedItem
{
get => _selectedIndex;
set => this.RaiseAndSetIfChanged(ref _selectedIndex, value);
get => _selectedItem;
set => this.RaiseAndSetIfChanged(ref _selectedItem, value);
}

private string _searchText;
Expand All @@ -131,8 +139,9 @@ public string SearchText

private static Func<ItemViewModel, bool> MakeFilter(string searchText)
{
if (string.IsNullOrWhiteSpace(searchText)) return i => true;
return i => i.Name.Contains(searchText);
if (string.IsNullOrWhiteSpace(searchText))
return i => true;
return i => i.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase);
}

// Статистика
Expand All @@ -154,7 +163,7 @@ public int ItemsCnt
public void SaveData()
{
var list = new List<ToDoItem>();
foreach (ItemViewModel item in this._sourceList.Items)
foreach (ItemViewModel item in this._sourceCache.Items)
{
list.Add(item.ToToDoItem());
}
Expand All @@ -170,6 +179,15 @@ public DataBase DB
set => _db = value;
}

private uint KeyGen()
{
uint i = 0;
while (i < uint.MaxValue && this._sourceCache.Keys.Contains(i))
{
i++;
}
return i;
}
public ViewModelActivator Activator { get; }

private readonly IDisposable _cleanStats;
Expand Down
10 changes: 8 additions & 2 deletions ViewModels/NewItemViewModel.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public partial class NewItemViewModel : ReactiveObject
public NewItemViewModel()
{
AcceptNewItemCommand = ReactiveCommand.Create(
() => new ItemViewModel(new ToDoItem(Name, "Filler", false, 0))
() => new ToDoItem(Name, Content, false, 0)
);
CancelCommand = ReactiveCommand.Create(() => new Unit());
}
Expand All @@ -23,6 +23,12 @@ public string Name
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
public ReactiveCommand<Unit, ItemViewModel> AcceptNewItemCommand { get; }
private string? _content;
public string? Content
{
get => _content;
set => this.RaiseAndSetIfChanged(ref _content, value);
}
public ReactiveCommand<Unit, ToDoItem> AcceptNewItemCommand { get; }
public ReactiveCommand<Unit, Unit> CancelCommand { get; }
}
4 changes: 3 additions & 1 deletion Views/EditItemView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ToDo.Views.EditItemView"
Title="EditItemView">

<Grid ColumnDefinitions="*" RowDefinitions="auto, *, auto">
<TextBox x:Name="NameBox" Grid.Row="0" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Name}"/>
<TextBox x:Name="ContentBox" Grid.Row="1" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Content}"/>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Button IsEnabled="{Binding #NameBox.Text, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" Content="Принять" Command="{Binding AcceptEditedItemCommand}"/>
<Button IsEnabled="{Binding #NameBox.Text, Converter={StaticResource IsNotNullOrWhiteSpace}}" Content="Принять" Command="{Binding AcceptEditedItemCommand}"/>
<Button Content="Отмена" Command="{Binding CancelCommand}"/>
</StackPanel>
</Grid>

</Window>
5 changes: 1 addition & 4 deletions Views/EditItemView.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using ToDo.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;

namespace ToDo.Views;
Expand All @@ -14,7 +11,7 @@ public partial class EditItemView : ReactiveWindow<EditItemViewModel>
public EditItemView()
{
InitializeComponent();
var InputBox = this.FindControl<TextBox>("InputBox");
var InputBox = this.FindControl<TextBox>("NameBox");
if (InputBox is not null)
{
InputBox.AttachedToVisualTree += (s, e) => InputBox.Focus();
Expand Down
21 changes: 21 additions & 0 deletions Views/IsNotNullOrWhiteSpace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;

namespace ToDo.Views;

public class IsNotNullOrWhiteSpace : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
string strValue = value as string;
{
return (!string.IsNullOrWhiteSpace(strValue));
}

}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
28 changes: 13 additions & 15 deletions Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,21 @@
<Grid ColumnDefinitions="*" RowDefinitions="auto, *, auto">
<TextBox Grid.Row="0" Text="{Binding SearchText}"/>
<ScrollViewer Grid.Row="1">
<ListBox x:Name="TheListBox" SelectedIndex="{Binding SelectedIndex}" Items="{Binding Colle}">
<ListBox x:Name="TheListBox" SelectedItem="{Binding SelectedItem}" Items="{Binding Colle}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Grid RowDefinitions="auto" ColumnDefinitions="auto, *, auto">
<CheckBox Grid.Column="0" IsChecked="{Binding IsDone}"/>
<TextBlock Grid.Column="1" TextWrapping="Wrap" VerticalAlignment="Center" Text="{Binding Name}"/>
<CheckBox x:Name="VisibilityToggle" IsChecked="False" Grid.Column="3">
<CheckBox.Template>
<ControlTemplate>
<Image Source="{TemplateBinding IsChecked, Converter={StaticResource GetCheckBoxIcon}}" Width="20" Height="20" />
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
</Grid>
<TextBlock IsVisible="{Binding #VisibilityToggle.IsChecked}" TextWrapping="Wrap" Text="{Binding Content}" />
</StackPanel>
<Grid RowDefinitions="auto, auto" ColumnDefinitions="auto, *, auto">
<CheckBox Grid.Column="0" IsChecked="{Binding IsDone}"/>
<TextBlock Grid.Column="1" TextWrapping="Wrap" VerticalAlignment="Center" Text="{Binding Name}"/>
<CheckBox IsVisible="{Binding #ContentBlock.Text, Converter={x:Static ObjectConverters.IsNotNull}}" x:Name="VisibilityToggle" IsChecked="False" Grid.Column="2">
<CheckBox.Template>
<ControlTemplate>
<Image Source="{TemplateBinding IsChecked, Converter={StaticResource GetCheckBoxIcon}}" Margin="0,0,10,0" Width="24" Height="24" />
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
<TextBlock x:Name="ContentBlock" Grid.Row="1" Grid.Column="1" IsVisible="{Binding #VisibilityToggle.IsChecked}" TextWrapping="Wrap" Text="{Binding Content}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Expand Down
Loading

0 comments on commit 32fb862

Please sign in to comment.