Skip to content

Commit

Permalink
一通り移植完了
Browse files Browse the repository at this point in the history
  • Loading branch information
miyaji255 committed Jun 11, 2023
1 parent 2342c48 commit 9b94dcb
Show file tree
Hide file tree
Showing 22 changed files with 915 additions and 259 deletions.
7 changes: 7 additions & 0 deletions EasyPlot/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,20 @@ public App()
services.AddSingleton<IActivationService, ActivationService>();
services.AddSingleton<IPageService, PageService>();
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<ISharedConfigService, SharedConfigService>();
// Core Services
services.AddSingleton<IFileService, FileService>();
// Views and ViewModels
services.AddTransient<SettingsViewModel>();
services.AddTransient<SettingsPage>();
services.AddTransient<RightPanelViewModel>();
services.AddTransient<RightPanelPage>();
services.AddTransient<GraphWholeSettingsViewModel>();
services.AddTransient<GraphWholeSettingsPage>();
services.AddTransient<GraphGroupPage>();
// TODO: 全部ここに集約してしまっている。できたら解消する
services.AddSingleton<MainViewModel>();
services.AddTransient<MainPage>();
Expand Down
16 changes: 16 additions & 0 deletions EasyPlot/Contracts/Services/ISharedConfigService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace EasyPlot.Contracts.Services;

public interface ISharedConfigService
{
string TempDirectory { get; }

string ResultGpPath { get; }

string ResultPngPath { get; }

// gnuplot では \ をパスとして認識しないので / のものを用意しておく
/// <summary>
/// パス区切り文字を / で返します
/// </summary>
string ResultPngPathNotBackSlash { get; }
}
12 changes: 12 additions & 0 deletions EasyPlot/EasyPlot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
<None Remove="Assets\Icon\StoreLogo.scale-100.png" />
<None Remove="Assets\Icon\StoreLogo.scale-400.png" />
<None Remove="Assets\Square150x150Logo.scale-100.png" />
<None Remove="Views\GraphGroupPage.xaml" />
<None Remove="Views\GraphWholeSettingsPage.xaml" />
<None Remove="Views\RightPanelPage.xaml" />
</ItemGroup>

<ItemGroup>
Expand All @@ -107,6 +110,15 @@
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Page Update="Views\GraphGroupPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\GraphWholeSettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\RightPanelPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>

<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
Expand Down
2 changes: 2 additions & 0 deletions EasyPlot/Services/PageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public PageService()
{
Configure<MainViewModel, MainPage>();
Configure<SettingsViewModel, SettingsPage>();
Configure<RightPanelViewModel, RightPanelPage>();
Configure<GraphWholeSettingsViewModel, GraphWholeSettingsPage>();
}

public Type GetPageType(string key)
Expand Down
27 changes: 27 additions & 0 deletions EasyPlot/Services/SharedConfigService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using EasyPlot.Contracts.Services;

namespace EasyPlot.Services;

public class SharedConfigService : ISharedConfigService
{
public string TempDirectory { get; }

public string ResultGpPath { get; }

public string ResultPngPath { get; }

public string ResultPngPathNotBackSlash { get; }

public SharedConfigService()
{
// TODO: GUID に変更するか検討
TempDirectory = Path.Combine(Path.GetTempPath(), "EasyPlot");

ResultGpPath = Path.Combine(TempDirectory, "result.gp");
ResultPngPath = Path.Combine(TempDirectory, "result.png");
ResultPngPathNotBackSlash = ResultPngPath.Replace('\\', '/');

if (!Directory.Exists(TempDirectory))
Directory.CreateDirectory(TempDirectory);
}
}
14 changes: 14 additions & 0 deletions EasyPlot/ViewModels/GraphWholeSettingsViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using CommunityToolkit.Mvvm.ComponentModel;
using EasyPlot.ViewModels.Wrapper;

namespace EasyPlot.ViewModels;

public class GraphWholeSettingsViewModel: ObservableObject
{
public WholeSettings WholeSettings { get; }

public GraphWholeSettingsViewModel(MainViewModel mainViewModel)
{
WholeSettings = mainViewModel.WholeSettings;
}
}
10 changes: 10 additions & 0 deletions EasyPlot/ViewModels/MainTabType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace EasyPlot.ViewModels;

public enum MainTabType
{
GraphWholeSettings,

GraphGroup,

AppSettings,
}
137 changes: 84 additions & 53 deletions EasyPlot/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
using EasyPlot.Contracts.Services;
using EasyPlot.Utilities;
using EasyPlot.ViewModels.Wrapper;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Pickers;

namespace EasyPlot.ViewModels;
Expand All @@ -19,7 +23,9 @@ public partial class MainViewModel : ObservableRecipient

public WholeSettings WholeSettings { get; } = new();

public ObservableCollection<ObservableObject> TabItems { get; }
public List<GraphGroupViewModel> GraphGroups { get; }

public ObservableCollection<MainTabViewModel> TabItems { get; }

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsGenerateError))]
Expand All @@ -30,11 +36,9 @@ public partial class MainViewModel : ObservableRecipient

public bool IsGenerateSuccess => ErrorText == string.Empty;

public string ResultImagePath { get; set; } = Path.Combine(Path.GetTempPath(), "EasyPlot", "result.png");

public ImageSource? ResultImage { get; private set; }

private readonly object _lockObj = new();
public Uri ResultPath => new Uri(_sharedConfigService.ResultPngPath);

private readonly CancellationTokenSource _cts = new();

Expand All @@ -44,58 +48,81 @@ public partial class MainViewModel : ObservableRecipient

private readonly INavigationService _navigationService;

private readonly ISharedConfigService _sharedConfigService;

public MainViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
_sharedConfigService = App.GetService<ISharedConfigService>();

TabItems = new(new ObservableObject[] { WholeSettings, new GraphGroupViewModel() { GroupTitle = "Group 1" } });
GraphGroups = new(new[] { new GraphGroupViewModel() { GroupTitle = "Group 1" } });
TabItems = new();

_loopTimer = new PeriodicTimer(TimeSpan.FromSeconds(1));
PlotImageLoopAsync();
}

#region commands

public void OnAddTabButtonClick(TabView sender, object args)
public void OnAddTabButtonClick(TabView sender, object _)
{
TabItems.Add(new GraphGroupViewModel()
// タイトルをBindするかが異なるため、直接バインディング
var newGroup = new GraphGroupViewModel()
{
GroupTitle = $"Group {TabItems.Count + 1}",
});
GroupTitle = $"Group {GraphGroups.Count + 1}",
};
GraphGroups.Add(newGroup);
TabItems.Add(new MainTabViewModel(newGroup));

sender.SelectedIndex = TabItems.Count - 1;
}

public void OnTabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
public void OnTabCloseRequested(TabView _, TabViewTabCloseRequestedEventArgs args)
{
TabItems.Remove((args.Item as ObservableObject)!);
if (TabItems.Count < 2)
var item = (MainTabViewModel)args.Item;
TabItems.Remove(item);
if (item.Data is not null)
{
TabItems.Add(new GraphGroupViewModel { GroupTitle = "Group 1" });
GraphGroups.Remove(item.Data);

if (GraphGroups.Count == 0)
{
var newGroup = new GraphGroupViewModel()
{
GroupTitle = "Group 1",
};
GraphGroups.Add(newGroup);
TabItems.Add(new MainTabViewModel(newGroup));
}
}
}

[RelayCommand]
private void OnSettingClicked()
public void OnComponentInitialized()
{
_navigationService.NavigateTo(typeof(SettingsViewModel).FullName!);
// なかで ViewModel を要求するので初期化後に呼ぶ
TabItems.Add(new MainTabViewModel(WholeSettings));
TabItems.Add(new MainTabViewModel(GraphGroups[0]));
}

[RelayCommand]
private async Task OnSaveImageAsync()
private void OnOpenSettingTab(TabView tabView)
{
var copiedPath = Path.Combine(Path.GetTempPath(), "EasyPlot", "result-copied.png");
File.Copy(ResultImagePath, copiedPath, true);
var settingTab = TabItems
.Select((tab, index) => (tab, index))
.FirstOrDefault(t => t.tab.TabType == MainTabType.AppSettings);
if (settingTab.tab is null)
{
settingTab = (MainTabViewModel.CreateSetting(), TabItems.Count);

var picker = new FileSavePicker();
picker.FileTypeChoices.Add("png", new[] { ".png" });
picker.SuggestedFileName = "result";
var file = await picker.PickSaveFileAsync();
TabItems.Add(settingTab.tab);
}

if (file is null)
return;
tabView.SelectedIndex = settingTab.index;
}

CachedFileManager.DeferUpdates(file);
File.Copy(copiedPath, file.Path);
_ = await CachedFileManager.CompleteUpdatesAsync(file);
[RelayCommand]
private void OnSettingClicked()
{
_navigationService.NavigateTo(typeof(SettingsViewModel).FullName!);
}
#endregion

Expand All @@ -113,10 +140,10 @@ private async void PlotImageLoopAsync()
try
{
// 起動直後はメインスレッドが確定していないので待つ
await Task.Delay(2000);
await Task.Delay(1000);

if (!File.Exists(ResultImagePath))
using (File.Create(ResultImagePath)) { }
if (!File.Exists(_sharedConfigService.ResultPngPath))
using (File.Create(_sharedConfigService.ResultPngPath)) { }

while (await _loopTimer.WaitForNextTickAsync(token))
{
Expand All @@ -127,9 +154,13 @@ private async void PlotImageLoopAsync()

if (plotText != _lastPlotText)
{
_lastPlotText = plotText;
await CreatePlotImageAsync(plotText, token);
}
_lastPlotText = plotText;
else
{
_lastPlotText = plotText;
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Expand All @@ -140,14 +171,14 @@ private async void PlotImageLoopAsync()
catch (OperationCanceledException) { }
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
ErrorText = ex.ToString();
}
}

private async Task CreatePlotImageAsync(string plotText, CancellationToken cancellationToken)
{
var basePath = Path.Combine(Path.GetTempPath(), "EasyPlot");
var gpFilePath = Path.Combine(basePath, "result.gp");
var basePath = _sharedConfigService.TempDirectory;
var gpFilePath = _sharedConfigService.ResultGpPath;
await File.WriteAllTextAsync(gpFilePath, plotText, UTF8WithoutBOM, cancellationToken);
var info = new ProcessStartInfo
{
Expand All @@ -170,22 +201,24 @@ private async Task CreatePlotImageAsync(string plotText, CancellationToken cance
if (errorText != string.Empty)
errorText = errorText.Replace($"\"{gpFilePath}\"", string.Empty);

lock (_lockObj)
if (process.ExitCode != 0 && errorText == string.Empty)
{
if (process.ExitCode != 0 && errorText == string.Empty)
{
ErrorText = "unknown error occured";
ErrorText = "unknown error occured";
return;
}
else
{
ErrorText = errorText;
if (IsGenerateError)
return;
}
else
{
ErrorText = errorText;
if (IsGenerateError)
return;
}
}

//ResultImage = ImageSource.FromFile(ResultImagePath);
var imageFile = await StorageFile.GetFileFromPathAsync(_sharedConfigService.ResultPngPath);
var stream = await imageFile.OpenReadAsync();
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(stream);
ResultImage = bitmap;
OnPropertyChanged(nameof(ResultPath));
OnPropertyChanged(nameof(ResultImage));
OnPropertyChanged(nameof(ErrorText));
OnPropertyChanged(nameof(IsGenerateError));
Expand All @@ -198,11 +231,9 @@ private string GeneratePlotText()
builder.Append($"""
set encoding utf8
set terminal pngcairo
set output "{ResultImagePath.Replace('\\', '/')}"
set output "{_sharedConfigService.ResultPngPathNotBackSlash}"
""");

var graphGroups = TabItems.OfType<GraphGroupViewModel>().ToArray();

if (WholeSettings.Title.Enabled)
builder.Append($"\nset title \"{WholeSettings.Title.Value}\"");
if (WholeSettings.XLabel.Enabled)
Expand All @@ -220,10 +251,10 @@ set terminal pngcairo
if (WholeSettings.Sampling.Enabled)
builder.Append($"\nset sample {WholeSettings.Sampling.Value}");

if (graphGroups.Any(g => g.Settings.Any()))
if (GraphGroups.Any(g => g.Settings.Any()))
builder.Append("\nplot ");

foreach (var g in graphGroups)
foreach (var g in GraphGroups)
{
foreach (var s in g.Settings)
{
Expand Down
Loading

0 comments on commit 9b94dcb

Please sign in to comment.