Skip to content

Commit

Permalink
fix projectwatchinstance
Browse files Browse the repository at this point in the history
  • Loading branch information
HendrikMennen committed Nov 15, 2023
1 parent 9ed4d76 commit f6c1256
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 68 deletions.
15 changes: 14 additions & 1 deletion src/OneWare.Core/Views/Windows/AdvancedWindow.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using OneWare.Shared.Controls;
using OneWare.Shared.ViewModels;

namespace OneWare.Core.Views.Windows
{
Expand Down Expand Up @@ -87,5 +90,15 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
}
}
}

protected override void OnClosing(WindowClosingEventArgs e)
{
if (Content is FlexibleWindow {DataContext: FlexibleWindowViewModelBase {IsDirty: true} vm} flexibleWindow)
{
e.Cancel = true;
vm.Close(flexibleWindow);
}
base.OnClosing(e);
}
}
}
5 changes: 3 additions & 2 deletions src/OneWare.ProjectExplorer/Services/ProjectWatchInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ private async Task ProcessAsync(string path, IReadOnlyCollection<FileSystemEvent
case WatcherChangeTypes.Changed:
if (entry is ISavable savable)
{
if (File.GetLastWriteTime(savable.FullPath) > savable.LastSaveTime)
var lastWriteTime = File.GetLastWriteTime(savable.FullPath);
if (lastWriteTime > savable.LastSaveTime)
await _projectExplorerService.ReloadAsync(entry);

if (savable is IProjectFile { Root: IProjectRootWithFile rootWithFile } &&
rootWithFile.ProjectFilePath == savable.FullPath)
rootWithFile.ProjectFilePath == savable.FullPath && lastWriteTime > rootWithFile.LastSaveTime)
{
await _projectExplorerService.ReloadAsync(rootWithFile);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ public void ConstructContextMenu(TopLevel topLevel)
{
if(reg.Invoke(SelectedItems) is {} items) menuItems.AddRange(items);
}

if (manager != null) menuItems.AddRange(manager.ConstructContextMenu(entry));

if (entry is IProjectRoot root)
{
Expand Down
2 changes: 0 additions & 2 deletions src/OneWare.Shared/Models/IProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ public interface IProjectManager
public Task<IProjectRoot?> LoadProjectAsync(string path);

public Task<bool> SaveProjectAsync(IProjectRoot root);

public IEnumerable<MenuItemModel> ConstructContextMenu(IProjectEntry entry);
}
11 changes: 10 additions & 1 deletion src/OneWare.Shared/ViewModels/FlexibleWindowViewModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ namespace OneWare.Shared.ViewModels;

public class FlexibleWindowViewModelBase : Document
{
public void Close(FlexibleWindow window)
private bool _isDirty;

public bool IsDirty
{
get => _isDirty;
set => SetProperty(ref _isDirty, value);
}

public virtual void Close(FlexibleWindow window)
{
IsDirty = false;
window.Close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public string SearchTextNodes
get => _searchTextNodes;
set => SetProperty(ref _searchTextNodes, value);
}

public event EventHandler NodeConnected;

public event EventHandler NodeDisconnected;

public FpgaModelBase()
{
Expand Down Expand Up @@ -115,6 +119,7 @@ private void Connect()
SelectedNode.Connection = SelectedPin;
ConnectCommand.NotifyCanExecuteChanged();
DisconnectCommand.NotifyCanExecuteChanged();
NodeConnected?.Invoke(this, EventArgs.Empty);
}

private void Disconnect()
Expand All @@ -124,6 +129,7 @@ private void Disconnect()
SelectedNode!.Connection = null;
ConnectCommand.NotifyCanExecuteChanged();
DisconnectCommand.NotifyCanExecuteChanged();
NodeDisconnected?.Invoke(this, EventArgs.Empty);
}

protected void LoadFromJson(string path)
Expand Down
105 changes: 58 additions & 47 deletions src/OneWare.UniversalFpgaProjectSystem/UniversalFpgaProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ public class UniversalFpgaProjectManager : IProjectManager
private readonly IProjectExplorerService _projectExplorerService;
private readonly IDockService _dockService;
private readonly IWindowService _windowService;

public UniversalFpgaProjectManager(IProjectExplorerService projectExplorerService, IDockService dockService, IWindowService windowService)

public UniversalFpgaProjectManager(IProjectExplorerService projectExplorerService, IDockService dockService,
IWindowService windowService)
{
_projectExplorerService = projectExplorerService;
_dockService = dockService;
_windowService = windowService;

_projectExplorerService.RegisterConstructContextMenu(ConstructContextMenu);
}

public async Task NewProjectDialogAsync()
Expand All @@ -32,18 +35,18 @@ await _windowService.ShowDialogAsync(new UniversalFpgaProjectCreatorView()
DataContext = ContainerLocator.Container.Resolve<UniversalFpgaProjectCreatorViewModel>()
});
}

public async Task<IProjectRoot?> LoadProjectAsync(string path)
{
var root = await UniversalFpgaProjectParser.DeserializeAsync(path);

if (root == null) return root;

ProjectHelper.ImportEntries(root.FullPath, root);

//Load Properties
var top = root.Properties["TopEntity"];
if (top != null && root.Search(top.ToString()) is {} entity)
if (top != null && root.Search(top.ToString()) is { } entity)
{
root.TopEntity = entity;
}
Expand All @@ -56,53 +59,61 @@ public async Task<bool> SaveProjectAsync(IProjectRoot root)
return root is UniversalFpgaProjectRoot uFpga && await UniversalFpgaProjectParser.SerializeAsync(uFpga);
}

public IEnumerable<MenuItemModel> ConstructContextMenu(IProjectEntry entry)
public IEnumerable<MenuItemModel> ConstructContextMenu(IList<IProjectEntry> selected)
{
switch (entry)
if (selected.Count == 1)
{
case UniversalFpgaProjectRoot root:
yield return new MenuItemModel("Save")
{
Header = "Save",
Command = new AsyncRelayCommand(() => SaveProjectAsync(root)),
ImageIconObservable = Application.Current!.GetResourceObservable("VsImageLib.Save16XMd"),
};
yield return new MenuItemModel("Reload")
{
Header = $"Reload",
Command = new AsyncRelayCommand(() => _projectExplorerService.ReloadAsync(root)),
ImageIconObservable = Application.Current!.GetResourceObservable("VsImageLib.RefreshGrey16X"),
};
yield return new MenuItemModel("Edit")
{
Header = $"Edit {Path.GetFileName(root.ProjectFilePath)}",
Command = new AsyncRelayCommand(() => _dockService.OpenFileAsync(_projectExplorerService.GetTemporaryFile(root.ProjectFilePath))),
};
break;
case IProjectFile { Root: UniversalFpgaProjectRoot universalFpgaProjectRoot } file:
if (universalFpgaProjectRoot.TopEntity == file)
{
yield return new MenuItemModel("Unset Top Entity")
switch (selected.First())
{
case UniversalFpgaProjectRoot root:
yield return new MenuItemModel("Save")
{
Header = $"Unset Top Entity",
Command = new RelayCommand(() =>
{
universalFpgaProjectRoot.TopEntity = null;
}),
Header = "Save",
Command = new AsyncRelayCommand(() => SaveProjectAsync(root)),
ImageIconObservable = Application.Current!.GetResourceObservable("VsImageLib.Save16XMd"),
};
}
else
{
yield return new MenuItemModel("Set Top Entity")
yield return new MenuItemModel("Reload")
{
Header = $"Set Top Entity",
Command = new RelayCommand(() =>
{
universalFpgaProjectRoot.TopEntity = file;
}),
Header = $"Reload",
Command = new AsyncRelayCommand(() => _projectExplorerService.ReloadAsync(root)),
ImageIconObservable = Application.Current!.GetResourceObservable("VsImageLib.RefreshGrey16X"),
};
}
break;
yield return new MenuItemModel("Edit")
{
Header = $"Edit {Path.GetFileName(root.ProjectFilePath)}",
Command = new AsyncRelayCommand(() =>
_dockService.OpenFileAsync(root.Search(root.ProjectFilePath) as IProjectFile
?? _projectExplorerService.GetTemporaryFile(root.ProjectFilePath))),
};
break;
case IProjectFile { Root: UniversalFpgaProjectRoot universalFpgaProjectRoot } file:
if (universalFpgaProjectRoot.TopEntity == file)
{
yield return new MenuItemModel("Unset Top Entity")
{
Header = $"Unset Top Entity",
Command = new RelayCommand(() =>
{
universalFpgaProjectRoot.TopEntity = null;
_ = SaveProjectAsync(universalFpgaProjectRoot);
}),
};
}
else
{
yield return new MenuItemModel("Set Top Entity")
{
Header = $"Set Top Entity",
Command = new RelayCommand(() =>
{
universalFpgaProjectRoot.TopEntity = file;
_ = SaveProjectAsync(universalFpgaProjectRoot);
}),
};
}

break;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
using System.Collections.ObjectModel;
using AvaloniaEdit.Utils;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Reactive.Linq;
using DynamicData.Binding;
using OneWare.Shared.Controls;
using OneWare.Shared.Enums;
using OneWare.Shared.Models;
using OneWare.Shared.Services;
using OneWare.Shared.ViewModels;
using OneWare.UniversalFpgaProjectSystem.Models;
using OneWare.UniversalFpgaProjectSystem.Services;
using OneWare.UniversalFpgaProjectSystem.Views;

namespace OneWare.UniversalFpgaProjectSystem.ViewModels;

public class UniversalFpgaProjectCompileViewModel : ObservableObject
public class UniversalFpgaProjectCompileViewModel : FlexibleWindowViewModelBase
{
private readonly IWindowService _windowService;
private readonly UniversalFpgaProjectRoot _project;
public string Title => "Connect and Compile - " + _project.Header;

public List<FpgaModelBase> FpgaModels { get; }
public ObservableCollection<FpgaModelBase> FpgaModels { get; } = new();

private FpgaModelBase? _selectedFpga;
public FpgaModelBase? SelectedFpga
Expand All @@ -30,11 +32,30 @@ public bool HideExtensions
set => SetProperty(ref _hideExtensions, value);
}

public UniversalFpgaProjectCompileViewModel(FpgaService fpgaService, NodeProviderService nodeProviderService, UniversalFpgaProjectRoot project)
public UniversalFpgaProjectCompileViewModel(IWindowService windowService, FpgaService fpgaService, NodeProviderService nodeProviderService, UniversalFpgaProjectRoot project)
{
_windowService = windowService;
_project = project;

FpgaModels = fpgaService.GetFpgas().ToList();
this.WhenValueChanged(x => x.IsDirty).Subscribe(x =>
{
Title = $"Connect and Compile - {_project.Header}{(x ? "*" : "")}";
});

foreach (var fpga in fpgaService.GetFpgas())
{
Observable.FromEventPattern(fpga, nameof(fpga.NodeConnected)).Subscribe(_ =>
{
IsDirty = true;
});

Observable.FromEventPattern(fpga, nameof(fpga.NodeDisconnected)).Subscribe(_ =>
{
IsDirty = true;
});

FpgaModels.Add(fpga);
}

SelectedFpga = FpgaModels.FirstOrDefault();

Expand All @@ -49,7 +70,31 @@ public UniversalFpgaProjectCompileViewModel(FpgaService fpgaService, NodeProvide
}
}

public async Task SaveAsync(FlexibleWindow window)
public override void Close(FlexibleWindow window)
{
if(!IsDirty) window.Close();
_ = SafeQuitAsync(window);
}

private async Task SafeQuitAsync(FlexibleWindow window)
{
var result = await _windowService.ShowYesNoCancelAsync("Warning", "Do you want to save changes?", MessageBoxIcon.Warning, window.Host);

switch (result)
{
case MessageBoxStatus.Yes:
SaveAndClose(window);
break;
case MessageBoxStatus.No:
IsDirty = false;
break;
case MessageBoxStatus.Canceled:
return;
}
window.Close();
}

public void SaveAndClose(FlexibleWindow window)
{
CreatePcf();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
using System.Text.Json.Nodes;
using CommunityToolkit.Mvvm.ComponentModel;
using OneWare.Settings;
using OneWare.Settings.ViewModels;
using OneWare.Settings.ViewModels.SettingTypes;
using OneWare.Shared.Controls;
using OneWare.Shared.Services;
using OneWare.Shared.ViewModels;
using OneWare.UniversalFpgaProjectSystem.Models;

namespace OneWare.UniversalFpgaProjectSystem.ViewModels;

public class UniversalFpgaProjectCreatorViewModel : ObservableObject
public class UniversalFpgaProjectCreatorViewModel : FlexibleWindowViewModelBase
{
public IPaths Paths { get; }
private readonly IProjectExplorerService _projectExplorerService;
Expand Down Expand Up @@ -92,7 +92,7 @@ public async Task SaveAsync(FlexibleWindow window)

_projectExplorerService.ActiveProject = root;

window?.Close();
Close(window);

_ = _projectExplorerService.SaveLastProjectsFileAsync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@

<StackPanel Grid.Row="1" DockPanel.Dock="Bottom" Margin="8" Classes="WindowButtons" HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Button Background="{DynamicResource HighlightBrush}" Command="{Binding SaveAsync}"
<Button Background="{DynamicResource HighlightBrush}" Command="{Binding SaveAndClose}"
CommandParameter="{Binding #UniversalFpgaProjectCompileViewView}">
<TextBlock Text="Save" />
</Button>
Expand Down

0 comments on commit f6c1256

Please sign in to comment.