Skip to content

Commit

Permalink
Merge pull request #120 from XanatosX/feature/fix-non-hotkey-closeabl…
Browse files Browse the repository at this point in the history
…e-modals

Fix windows which are not closeable via hotkey
  • Loading branch information
XanatosX authored Jan 1, 2024
2 parents 8b47f05 + 7a1d9d3 commit bf872dd
Show file tree
Hide file tree
Showing 31 changed files with 195 additions and 69 deletions.
51 changes: 51 additions & 0 deletions docs/user/add-new-function.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Add a new function

This documentation will tell you on how to add a new function to the application. If you are unsure what a function is check out the [what is a function][what-is-a-function] documentation.

To add a new function click on `File->New Function` while being in the main window. This will open up the add function screen

![add-a-function]

Provide display name for the function, this will be shown on the button. The name needs to be 5 - 25 chars. If you want add an description, this will be shown as a tooltip if you hover over the button later on.

![select-plugin]

Select the plugin to start the application or binary. Checkout the [plugin overview][available-plugins] for more information.

![additional-settings]

Select the setting specific for this function. For more information about the [setting scope][setting-scope] check the documentation.

If required enter any function parameters, those are arguments which are getting parsed to the script or application.

Select the path to the script or application to start. To do so press the `...` next to the text field

![final-function]

If everything is entered as expected, press the `Ok` button. If the button is still grayed out something is wrong or could not be found.

The function will now be shown in the main view like this.

![function-in-tool]

Showing the tooltip on hover

![function-in-tool-tooltip]

Press the button you created to start the tool. If this is not working you will need to check the log file for further information.

## User Manual

Go back to the [user manual][back]

[back]: user-manual.md
[what-is-a-function]: ./what-is-a-function.md
[available-plugins]: ./plugin-overview.md
[setting-scope]: ./scope-of-a-setting.md
[main-window]: https://i.imgur.com/oswayay.png
[add-a-function]: https://i.imgur.com/mr3Folx.png
[select-plugin]: https://i.imgur.com/8ITUSA3.png
[additional-settings]: https://i.imgur.com/O8va6Gd.png
[final-function]: https://i.imgur.com/lmiIzjX.png
[function-in-tool]: https://i.imgur.com/60cHafm.png
[function-in-tool-tooltip]: https://i.imgur.com/8lUHaiU.png
4 changes: 4 additions & 0 deletions docs/user/user-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ The manual of the application. This page does list all the things you as a user
- [[1] Installation][installation]
- [[2] Plugin Overview][plugin-overview]
- [[3] Languages][language]
- [[4] Add a function][add-a-function]
- [[4a] What is a function][what-is-a-function]
- [[4] Scope of a Setting][scope-of-a-setting]
- [[5] Hotkeys][hotkey-overview]

[installation]: ./installation.md
[language]: ./languages.md
[scope-of-a-setting]: ./scope-of-a-setting.md
[add-a-function]: ./add-new-function.md
[what-is-a-function]: ./what-is-a-function.md
[plugin-overview]: ./plugin-overview.md
[hotkey-overview]: ./hotkey-overview.md
15 changes: 15 additions & 0 deletions docs/user/what-is-a-function.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# What is a function

The term function in connection with the `Modular Tool Manager` is a set of data required to start a specific application or script. Those functions are displayed as buttons on the main window

![main-window]

`My test function` is a function which will start a specific application or script.

## User Manual

Go back to the [user manual][back]

[back]: user-manual.md

[main-window]: https://i.imgur.com/oswayay.png
6 changes: 5 additions & 1 deletion src/ModularToolManager/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,16 @@ public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop is null || desktop.MainWindow is null)
{
return;
}
desktop.ShutdownMode = Avalonia.Controls.ShutdownMode.OnExplicitShutdown;
if (desktop.MainWindow is IDisposable disposable)
{
disposable.Dispose();
}
desktop.MainWindow.Close();
desktop!.MainWindow!.Close();
SetupMainWindow(provider);
desktop.MainWindow.Show();
desktop.ShutdownMode = Avalonia.Controls.ShutdownMode.OnLastWindowClose;
Expand Down
2 changes: 1 addition & 1 deletion src/ModularToolManager/Models/ApplicationStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class ApplicationStyle
/// Is this a dark or light style variant
/// </summary>
[JsonPropertyName("mode")]
public ThemeVariant Variant { get; init; }
public ThemeVariant? Variant { get; init; }

/// <summary>
/// The name of the translation key which is getting used for the name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ internal class DeleteFunctionMessage : RequestMessage<bool>
/// <param name="functionModel">The function to delete</param>
public DeleteFunctionMessage(FunctionModel functionModel)
{
Identifier = functionModel.UniqueIdentifier;
Identifier = functionModel.Id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ internal class EditFunctionMessage : AsyncRequestMessage<bool>
/// <param name="functionModel">The function model to edit</param>
public EditFunctionMessage(FunctionModel functionModel)
{
Identifier = functionModel.UniqueIdentifier;
Identifier = functionModel.Id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
namespace ModularToolManager.Models.Messages;

/// <summary>
/// Get the current visiblilty for the application
/// Get the current visibility for the application
/// </summary>
internal class RequestApplicationVisiblity : RequestMessage<bool> { }
internal class RequestApplicationVisibility : RequestMessage<bool> { }
7 changes: 4 additions & 3 deletions src/ModularToolManager/Models/ShowOpenFileDialogModel.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using System.Collections.Generic;

namespace ModularToolManager.Models;

/// <summary>
/// Record for the openinig a file open dialog
/// Record for the opening a file open dialog
/// </summary>
/// <param name="FileDialogFilters">The filter for the dialog</param>
/// <param name="InialDirectory">The directory to start in</param>
/// <param name="InitialDirectory">The directory to start in</param>
/// <param name="AllowMultipleSelection">Allow selecting multiple files</param>
public record ShowOpenFileDialogModel(List<FileDialogFilter> FileDialogFilters, string? InialDirectory, bool AllowMultipleSelection);
public record ShowOpenFileDialogModel(List<FilePickerFileType> FileDialogFilters, string? InitialDirectory, bool AllowMultipleSelection);
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ public List<CultureInfo> GetAvailableCultures()
}
logger.LogTrace("Load available cultures from resources");
string applicationLocation = pathService.GetApplicationExecutableString();
string resoureFileName = Path.GetFileNameWithoutExtension(applicationLocation) + ".resources.dll";
string resourceFileName = Path.GetFileNameWithoutExtension(applicationLocation) + ".resources.dll";
DirectoryInfo? rootDirectory = pathService.GetApplicationPath();
availableCultures = rootDirectory?.GetDirectories()
.Where(dir => CultureInfo.GetCultures(CultureTypes.AllCultures).Any(culture => culture.Name == dir.Name))
.Where(dir => File.Exists(Path.Combine(dir.FullName, resoureFileName)))
.Where(dir => File.Exists(Path.Combine(dir.FullName, resourceFileName)))
.Select(dir => CultureInfo.GetCultureInfo(dir.Name))
.ToList() ?? new();
if (!availableCultures.Contains(CultureInfo.GetCultureInfo(Properties.Properties.FallbackLanguage)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public IEnumerable<Style> GetAllStylesWithinResource(IStyle? style)
/// <inheritdoc/>
public IEnumerable<IStyle> GetCurrentAppIncludeStyles()
{
if (App.Current is null)
{
return Enumerable.Empty<IStyle>();
}
var styles = App.Current.Styles.Where(style => style.GetType() == typeof(Styles)).ToList(); ;
var types = styles.Select(style => style.GetType());
return App.Current?.Styles.Where(style => style.GetType() == typeof(Styles)) ?? Enumerable.Empty<IStyle>();
Expand Down
19 changes: 8 additions & 11 deletions src/ModularToolManager/Services/Ui/WindowManagementService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Microsoft.Extensions.Logging;
using ModularToolManager.Models;
using ModularToolManager.Services.Settings;
Expand Down Expand Up @@ -50,7 +51,7 @@ internal class WindowManagementService : IWindowManagementService
private readonly IDependencyResolverService dependencyResolverService;

/// <summary>
/// Create a new isntance of this class
/// Create a new instance of this class
/// </summary>
/// <param name="loggingService">The logging service to use</param>
public WindowManagementService(
Expand Down Expand Up @@ -143,17 +144,13 @@ public async Task ShowModalWindowAsync(ShowWindowModel modalData, Window? parent
/// <inheritdoc/>
public async Task<string[]> ShowOpenFileDialogAsync(ShowOpenFileDialogModel fileDialogModel, Window parent)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
IStorageFolder? initialDirectory = await parent.StorageProvider.TryGetFolderFromPathAsync(fileDialogModel.InitialDirectory ?? string.Empty);
var files = await parent.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions() {
AllowMultiple = fileDialogModel.AllowMultipleSelection,
Filters = fileDialogModel.FileDialogFilters.ToList(),
};
if (!string.IsNullOrEmpty(fileDialogModel.InialDirectory))
{
openFileDialog.Directory = fileDialogModel.InialDirectory;
}
string[] files = await openFileDialog.ShowAsync(parent) ?? Array.Empty<string>();
return files;
FileTypeFilter = fileDialogModel.FileDialogFilters.ToList(),
SuggestedStartLocation = initialDirectory
});
return files.Select(file => file.Path.LocalPath).ToArray();
}

/// <inheritdoc/>
Expand Down
8 changes: 6 additions & 2 deletions src/ModularToolManager/ViewLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ public ViewLocator(IDependencyResolverService dependencyResolverService)
}

/// <inheritdoc/>
public Control Build(object data)
public Control Build(object? data)
{
if (data is null)
{
return new TextBlock { Text = "Request data was null" };
}
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);

Expand All @@ -43,7 +47,7 @@ public Control Build(object data)
}

/// <inheritdoc/>
public bool Match(object data)
public bool Match(object? data)
{
return data is ObservableObject;
}
Expand Down
11 changes: 11 additions & 0 deletions src/ModularToolManager/ViewModels/AboutViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
using ModularToolManager.Models.Messages;
using ModularToolManager.Services.IO;
using ModularToolManagerModel.Services.Dependency;
using ModularToolManagerModel.Services.IO;
Expand Down Expand Up @@ -83,4 +85,13 @@ private void OpenUrl(string url)
{
urlOpenerService.OpenUrl(url);
}

/// <summary>
/// Command to use to close the modal
/// </summary>
[RelayCommand]
private void Abort()
{
WeakReferenceMessenger.Default.Send(new CloseModalMessage(this));
}
}
12 changes: 6 additions & 6 deletions src/ModularToolManager/ViewModels/AddFunctionViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
Expand Down Expand Up @@ -53,7 +54,7 @@ internal partial class AddFunctionViewModel : ObservableValidator
/// <summary>
/// Service to use for opening windows or modals
/// </summary>
private readonly IWindowManagementService windowManagmentService;
private readonly IWindowManagementService windowManagementService;

/// <summary>
/// The settings service to use
Expand Down Expand Up @@ -145,7 +146,7 @@ public AddFunctionViewModel(IPluginService pluginService,
this.pluginService = pluginService;
this.functionService = functionService;
this.functionSettingsService = functionSettingsService;
this.windowManagmentService = windowManagmentService;
this.windowManagementService = windowManagmentService;
this.settingsService = settingsService;
this.pluginSettingView = pluginSettingView;

Expand Down Expand Up @@ -334,17 +335,16 @@ private bool CanExecuteOk()
[RelayCommand(CanExecute = nameof(CanOpenFunctionPath))]
private async Task OpenFunctionPath()
{
var fileDialogs = SelectedFunctionPlugin?.Plugin?.GetAllowedFileEndings().Select(fileEnding => new FileDialogFilter
var fileDialogs = SelectedFunctionPlugin?.Plugin?.GetAllowedFileEndings().Select(fileEnding => new FilePickerFileType(fileEnding.Name)
{
Extensions = new List<string> { fileEnding.Extension },
Name = fileEnding.Name
Patterns = new List<string> { $"*.{fileEnding.Extension}" },
}).ToList();
if (fileDialogs is null)
{
return;
}
ShowOpenFileDialogModel openConfig = new ShowOpenFileDialogModel(fileDialogs, null, false);
var files = await windowManagmentService.ShowOpenFileDialogAsync(openConfig);
var files = await windowManagementService.ShowOpenFileDialogAsync(openConfig);
string file = files.FirstOrDefault(string.Empty);
if (string.IsNullOrEmpty(file))
{
Expand Down
10 changes: 4 additions & 6 deletions src/ModularToolManager/ViewModels/AppViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
using ModularToolManager.Models.Messages;
using ModularToolManager.Services.Settings;
using ModularToolManager.Services.Ui;
using Serilog;
using System;
using System.Windows.Input;

namespace ModularToolManager.ViewModels;
Expand Down Expand Up @@ -38,7 +36,7 @@ public partial class AppViewModel : ObservableObject
private readonly ILogger<AppViewModel> logger;

/// <summary>
/// The service to use for loading and swichting a theme
/// The service to use for loading and switching a theme
/// </summary>
private readonly IThemeService themeService;

Expand Down Expand Up @@ -69,10 +67,10 @@ public AppViewModel(ILogger<AppViewModel> logger, IThemeService themeService, IS
{
if (numberOfOpenModalWindows > 0)
{
logger.LogWarning($"Tried to minimize app while {numberOfOpenModalWindows} where opend");
logger.LogWarning($"Tried to minimize app while {numberOfOpenModalWindows} where opened");
return;
}
var response = WeakReferenceMessenger.Default.Send(new RequestApplicationVisiblity());
var response = WeakReferenceMessenger.Default.Send(new RequestApplicationVisibility());
bool toggleMode = response.HasReceivedResponse ? response.Response : false;
WeakReferenceMessenger.Default.Send(new ToggleApplicationVisibilityMessage(toggleMode));
});
Expand All @@ -82,7 +80,7 @@ public AppViewModel(ILogger<AppViewModel> logger, IThemeService themeService, IS
private void SwitchTheme(int themeId)
{
var theme = themeService.GetStyleById(themeId);
if (theme is null)
if (theme is null || theme.Variant is null)
{
return;
}
Expand Down
10 changes: 5 additions & 5 deletions src/ModularToolManager/ViewModels/DependencyViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ internal partial class DependencyViewModel : ObservableObject
/// <summary>
/// The name of the dependency
/// </summary>
public string? Name => dependency?.Name;
public string? Name => Dependency?.Name;

/// <summary>
/// The version of the dependency
/// </summary>
public string? Version => dependency?.Version;
public string? Version => Dependency?.Version;

/// <summary>
/// The url to the project of the dependency
/// </summary>
public string? ProjectUrl => dependency?.ProjectUrl;
public string? ProjectUrl => Dependency?.ProjectUrl;

/// <summary>
/// Is the project url set
Expand All @@ -51,7 +51,7 @@ internal partial class DependencyViewModel : ObservableObject
/// <summary>
/// The url to the license of the dependency
/// </summary>
public string? LicenseUrl => dependency?.LicenseUrl;
public string? LicenseUrl => Dependency?.LicenseUrl;

/// <summary>
/// is the license for the dependency set
Expand All @@ -62,7 +62,7 @@ internal partial class DependencyViewModel : ObservableObject
/// <summary>
/// Create a new instance of this class
/// </summary>
/// <param name="dependency">The depencency to show</param>
/// <param name="dependency">The dependency to show</param>
/// <param name="urlOpenerService">The service used to open the url</param>
public DependencyViewModel(DependencyModel dependency, IUrlOpenerService urlOpenerService)
{
Expand Down
Loading

0 comments on commit bf872dd

Please sign in to comment.