sources/Google.Solutions.IapDesktop/Windows/MainFormViewModel.cs (172 lines of code) (raw):

// // Copyright 2020 Google LLC // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // using Google.Solutions.Apis.Auth; using Google.Solutions.Common.Util; using Google.Solutions.IapDesktop.Application.Host; using Google.Solutions.IapDesktop.Application.Profile; using Google.Solutions.IapDesktop.Application.Windows; using Google.Solutions.Mvvm.Binding; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows.Forms; namespace Google.Solutions.IapDesktop.Windows { internal class MainFormViewModel : ViewModelBase { private readonly IInstall install; private readonly UserProfile profile; private readonly IAuthorization authorization; // NB. This list is only access from the UI thread, so no locking required. private readonly LinkedList<BackgroundJob> backgroundJobs = new LinkedList<BackgroundJob>(); private string windowTitle = Install.ProductName; private bool isBackgroundJobStatusVisible = false; private string? profileState = null; public MainFormViewModel( Control view, IInstall install, UserProfile profile, IAuthorization authorization) { this.View = view.ExpectNotNull(nameof(view)); this.install = install.ExpectNotNull(nameof(install)); this.profile = profile.ExpectNotNull(nameof(profile)); this.authorization = authorization.ExpectNotNull(nameof(authorization)); this.ProfileStateCaption = $"{this.profile.Name}: {this.authorization.Session.Username}"; } //--------------------------------------------------------------------- // Observable properties. //--------------------------------------------------------------------- public string WindowTitle { get => this.windowTitle; private set { this.windowTitle = value; RaisePropertyChange(); } } public bool IsLoggingEnabled { get => Program.IsLoggingEnabled; set { Program.IsLoggingEnabled = value; RaisePropertyChange(); RaisePropertyChange((MainFormViewModel m) => m.StatusText); } } public string StatusText { get => this.IsLoggingEnabled ? $"Logging to {Program.LogFile}, performance might be degraded while logging is enabled." : string.Empty; } public bool IsBackgroundJobStatusVisible { get => this.isBackgroundJobStatusVisible; private set { this.isBackgroundJobStatusVisible = value; RaisePropertyChange(); RaisePropertyChange((MainFormViewModel m) => m.BackgroundJobStatus); } } public string? BackgroundJobStatus { get { var count = this.backgroundJobs.Count; if (count == 0) { return null; } else if (count == 1) { return this.backgroundJobs.First().Description.StatusMessage; } else { return this.backgroundJobs.First().Description.StatusMessage + $" (+{count - 1} more background jobs)"; } } } public string ProfileStateCaption { get => this.profileState!; set { this.profileState = value; RaisePropertyChange(); } } public IEnumerable<string> AlternativeProfileNames { get => this.install .Profiles .Where(name => name != this.profile.Name); } //--------------------------------------------------------------------- // Background job actions. //--------------------------------------------------------------------- public IJobUserFeedback CreateBackgroundJob( JobDescription jobDescription, CancellationTokenSource cancellationSource) { return new BackgroundJob(this, jobDescription, cancellationSource); } public void CancelBackgroundJobs() { // NB. Use ToList to create a snapshot of the list because Cancel() // modifies the list while we are iterating it. foreach (var job in this.backgroundJobs.ToList()) { job.Cancel(); } } //--------------------------------------------------------------------- // Other actions. //--------------------------------------------------------------------- public void SwitchToDocument(string? title) { // // Update window title so that it shows the current document. // var newTitle = title == null ? Install.ProductName : $"{title} - {Install.ProductName}"; if (!this.profile.IsDefault) { newTitle += $" ({this.profile.Name})"; } this.WindowTitle = newTitle; } public void LaunchInstanceWithProfile(string profileName) { // // Launch a new instance, passing the specified profile // as parameter (unless it's the default profile). // Program.LaunchNewInstance(new CommandLineOptions() { Profile = profileName != UserProfile.DefaultName ? profileName : null }); } //--------------------------------------------------------------------- // Helper classes. //--------------------------------------------------------------------- private class BackgroundJob : IJobUserFeedback { private readonly MainFormViewModel viewModel; private readonly CancellationTokenSource cancellationSource; public JobDescription Description { get; } public bool IsShowing => true; public BackgroundJob( MainFormViewModel viewModel, JobDescription jobDescription, CancellationTokenSource cancellationSource) { this.viewModel = viewModel; this.Description = jobDescription; this.cancellationSource = cancellationSource; } public void Cancel() { this.cancellationSource.Cancel(); Finish(); } public void Finish() { this.viewModel.backgroundJobs.Remove(this); this.viewModel.IsBackgroundJobStatusVisible = this.viewModel.backgroundJobs.Any(); } public void Start() { this.viewModel.backgroundJobs.AddLast(this); this.viewModel.IsBackgroundJobStatusVisible = true; } } } }