1using CommunityToolkit.Mvvm.ComponentModel;
2using System.Collections.ObjectModel;
3using System.Globalization;
28 private ObservableCollection<string> _lastWorkspacePaths =
new ObservableCollection<string>();
32 get => _lastWorkspacePaths;
33 set { _lastWorkspacePaths = value; OnPropertyChanged(); }
57 private bool _isWorkspaceOpen;
63 get => _isWorkspaceOpen;
66 if (SetProperty(ref _isWorkspaceOpen, value))
68 OnPropertyChangedAllHasUnsavedChanges();
105 private void OnPropertyChangedAllHasUnsavedChanges()
116 #region Reset methods of services
123 _competitionService.ResetToLoadedState();
124 _competitionDistanceRuleService.ResetToLoadedState();
145 if (
Settings !=
null) { Settings.PropertyChanged -= Settings_PropertyChanged; }
148 Settings.PropertyChanged += Settings_PropertyChanged;
165 if (SetProperty(ref _settings, value))
173 private void Settings_PropertyChanged(
object sender,
System.ComponentModel.PropertyChangedEventArgs e)
175 OnPropertyChanged(nameof(
Settings));
206 _personService = personService;
207 _competitionService = competitionService;
209 _competitionDistanceRuleService = competitionDistanceRuleService;
210 _raceService = raceService;
212 _fileService = fileService;
214 _personService.OnFileProgress += (sender, p, currentStep) =>
OnFileProgress?.Invoke(
this, p / 3,
"Loading persons...");
215 _competitionService.OnFileProgress += (sender, p, currentStep) =>
OnFileProgress?.Invoke(
this, (100 / 3) + (p / 3),
"Loading competitions...");
216 _raceService.OnFileProgress += (sender, p, currentStep) =>
OnFileProgress?.Invoke(
this, (2 * (100 / 3)) + (p / 3),
"Loading best race...");
218 _personService.PropertyChanged += (sender, e) =>
220 switch(e.PropertyName)
226 _competitionService.PropertyChanged += (sender, e) =>
228 switch (e.PropertyName)
234 _competitionDistanceRuleService.PropertyChanged += (sender, e) =>
236 switch (e.PropertyName)
242 _raceService.PropertyChanged += (sender, e) =>
244 switch (e.PropertyName)
261 public async Task<bool>
Load(
string path, CancellationToken cancellationToken)
263 if (!Directory.Exists(path)) {
return false; }
273 bool openResult =
false;
274 Exception exception =
null;
278 string filePathCompetitionDistanceRules =
getFilePathToLoadFrom(KEY_FILENAME_COMPETITIONDISTANCERULES);
281 if (!File.Exists(
WorkspaceSettingsFilePath) && !File.Exists(filePathCompetitions) && !File.Exists(filePathPersons) && !File.Exists(filePathBestRace))
293 Settings.PropertyChanged += Settings_PropertyChanged;
296 openResult = await _competitionService.Load(filePathCompetitions, cancellationToken);
297 if (!openResult) {
return openResult; }
300 openResult = await _competitionDistanceRuleService.Load(filePathCompetitionDistanceRules, cancellationToken);
301 if (!openResult) {
return openResult; }
304 openResult = await _personService.Load(filePathPersons, cancellationToken);
305 if(!openResult) {
return openResult; }
307 _competitionService.UpdateAllCompetitionsForPerson();
308 _competitionService.UpdateAllCompetitionDistancesFromDistanceRules(
true);
311 openResult = await _raceService.Load(filePathBestRace, cancellationToken);
314 OnPropertyChangedAllHasUnsavedChanges();
322 OnPropertyChangedAllHasUnsavedChanges();
327 if (exception !=
null) {
throw exception; }
339 public async Task<bool>
Save(CancellationToken cancellationToken,
string path =
"")
343 bool saveResult =
false;
344 Exception exception =
null;
351 if (!await
saveServiceAsync(KEY_FILENAME_COMPETITIONS, _competitionService, cancellationToken))
355 if (!await
saveServiceAsync(KEY_FILENAME_COMPETITIONDISTANCERULES, _competitionDistanceRuleService, cancellationToken))
359 if (!await
saveServiceAsync(KEY_FILENAME_PERSON, _personService, cancellationToken))
363 if (!await
saveServiceAsync(KEY_FILENAME_BESTRACE, _raceService, cancellationToken))
368 OnPropertyChangedAllHasUnsavedChanges();
372 OnPropertyChangedAllHasUnsavedChanges();
376 if (exception !=
null) {
throw exception; }
393 !
string.Equals(saveableService.
PersistentPath, newPath, StringComparison.OrdinalIgnoreCase))
398 return await saveableService.
Save(cancellationToken, newPath);
409 public async Task<bool>
CloseWorkspace(CancellationToken cancellationToken,
bool save =
true)
411 bool saveResult =
true;
414 saveResult = await
Save(cancellationToken);
417 Settings.PropertyChanged -= Settings_PropertyChanged;
419 _personService.ClearAll();
420 _competitionService.ClearAll();
421 _competitionDistanceRuleService.ClearAll();
422 _raceService.AllRacesVariants.Clear();
432 #region File name handling
444 private readonly ResourceManager _fileNameResources =
new ResourceManager(typeof(
Properties.
Resources));
445 public const string KEY_FILENAME_PERSON =
"FileName_Person";
446 public const string KEY_FILENAME_COMPETITIONS =
"FileName_Competitions";
447 public const string KEY_FILENAME_COMPETITIONDISTANCERULES =
"FileName_CompetitionDistanceRules";
448 public const string KEY_FILENAME_BESTRACE =
"FileName_BestRace";
450 private string getLocalizedFilePath(
string resourceKey, CultureInfo culture =
null)
452 string localizedFileName = _fileNameResources.GetString(resourceKey, culture ==
null ? CultureInfo.CurrentUICulture : culture)
453 ?? _fileNameResources.GetString(resourceKey, CultureInfo.InvariantCulture);
463 => getLocalizedFilePath(resourceKey);
472 if (
string.IsNullOrEmpty(resourceKey)) {
return string.Empty; }
473 List<string> candidates =
new List<string>();
476 string current = getLocalizedFilePath(resourceKey);
477 if (File.Exists(current))
483 List<string> localizedFileNames = GeneralLocalizationHelper.GetAllTranslationsForKey(_fileNameResources, resourceKey).Values.ToList();
484 List<string> localizedFilePaths = localizedFileNames.Select(f => Path.Combine(
PersistentPath, f)).ToList();
485 foreach (
string localizedFilePath
in localizedFilePaths)
487 if (File.Exists(localizedFilePath) && !candidates.Contains(localizedFilePath, StringComparer.OrdinalIgnoreCase))
489 candidates.Add(localizedFilePath);
494 return candidates.Select(f =>
new FileInfo(f))
495 .OrderByDescending(f => f.LastWriteTimeUtc)
496 .FirstOrDefault()?.FullName;
Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
Service used to get and store a list of Competition objects.
bool HasUnsavedChanges
Check if the list of Competition has not saved changed.
Service used to get and store a list of Person objects.
bool HasUnsavedChanges
Check if the list of Person has not saved changed.
Service used to manage Race and RacesVariant objects.
bool HasUnsavedChanges
Check if the PersistedRacesVariant has not saved changed.
ObservableCollection< string > LastWorkspacePaths
List with previous workspace paths.
bool HasUnsavedChanges_Races
Unsaved changes exist in the RaceService
bool HasUnsavedChanges_Competitions
Unsaved changes exist in the <see cref="CompetitionService" or CompetitionDistanceRuleService/>
WorkspaceSettings Settings
Workspace settings for the current workspace.
void ResetRacesToLoadedState()
Call the IRaceService.ResetToLoadedState
WorkspaceSettings _settingsPersistedInFile
Last workspace settings that were loaded from the file.
void ResetCompetitionsToLoadedState()
Call the ICompetitionService.ResetToLoadedState and ICompetitionDistanceRuleService....
void AddLastWorkspacePath(string path)
Add a path to the LastWorkspacePaths
async Task< bool > Save(CancellationToken cancellationToken, string path="")
Save all workspace files.
EventHandler OnFileFinished
Event that is raised when the file operation is finished.
async Task< bool > Load(string path, CancellationToken cancellationToken)
Open the workspace and load all files Caution: If there is already a workspace opened that has unsave...
string getFilePathToSaveTo(string resourceKey)
This method returns the file path to save to.
bool _isCompletelyNewWorkspace
void ResetSettingsToLoadedState()
Reset the to the state when the method was called.
string WorkspaceSettingsFilePath
Combined path to the workspace settings file.
bool HasUnsavedChanges
Check if there are unsaved changes in the workspace.
bool IsWorkspaceOpen
If true, a workspace is loaded; if false, not workspace is loaded.
WorkspaceService(IPersonService personService, ICompetitionService competitionService, ICompetitionDistanceRuleService competitionDistanceRuleService, IRaceService raceService, IFileService fileService)
Constructor for the WorkspaceService.
bool HasUnsavedChanges_Settings
Unsaved changes exist in the Settings.
async Task< bool > CloseWorkspace(CancellationToken cancellationToken, bool save=true)
Close the current workspace (set the current path to string.Empty and the Settings to null)
void ClearAllLastWorkspacePaths()
Clear all LastWorkspacePaths
void ResetPersonsToLoadedState()
Call the IPersonService.ResetToLoadedState
string PersistentPath
Path of the current workspace.
bool HasUnsavedChanges_Persons
Unsaved changes exist in the PersonService
const string WorkspaceSettingsFileName
Name of the workspace settings file.
string getFilePathToLoadFrom(string resourceKey)
This method returns the file path to load from.
ProgressDelegate OnFileProgress
Event that is raised when the file operation progress changes.
async Task< bool > saveServiceAsync(string fileNameResourceKey, ISaveable saveableService, CancellationToken cancellationToken)
Helper method to save a service and delete the old file if the file name changed.
Class holding all workspace settings.
Interface for a service used to get and store a list of CompetitionDistanceRule objects.
Interface for a service used to get and store a list of objects.
void SetWorkspaceServiceObj(IWorkspaceService workspaceService)
Save the reference to the IWorkspaceService object.
Interface for a service that handles file operations.
Interface for a service used to get and store a list of Person objects.
Interface for a service used to manage Race and RacesVariant objects.
void SetWorkspaceServiceObj(IWorkspaceService workspaceService)
Save the reference to the IWorkspaceService object.
Interface for saveable objects.
Task< bool > Save(CancellationToken cancellationToken, string path="")
Save to a file.
string PersistentPath
Path to the used file.
Interface for a service used to manage a workspace.
bool IsCompletelyNewWorkspace
If true, the workspace wasn't loaded from previously saved files.
WorkspaceSettings SettingsPersistedInFile
Settings loaded from the file for the current workspace.
delegate void ProgressDelegate(object sender, float progress, string currentStep="")
Delegate void for progress changes.