< Summary

Information
Class: MyNet.UI.ViewModels.Workspace.TabWorkspaceViewModel
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Workspace/TabWorkspaceViewModel.cs
Tag: 323_28699572109
Line coverage
42%
Covered lines: 27
Uncovered lines: 36
Coverable lines: 63
Total lines: 227
Line coverage: 42.8%
Branch coverage
21%
Covered branches: 8
Total branches: 38
Branch coverage: 21%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
set_SelectedWorkspace(...)50%2280%
get_SelectedIndex()0%620%
Select(...)0%620%
Select(...)0%2040%
AddWorkspace(...)50%44100%
AddWorkspaces(...)100%22100%
RemoveWorkspace(...)0%2040%
ClearWorkspaces()100%210%
GoToTab(...)0%2040%
CanGoToTab(...)100%210%
GoToNextTab()0%620%
CanGoToNextTab()0%620%
GoToPreviousTab()0%620%
CanGoToPreviousTab()0%620%
RaiseTabNavigationCanExecuteChanged()50%66100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Workspace/TabWorkspaceViewModel.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="TabWorkspaceViewModel.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Collections.ObjectModel;
 10using System.Linq;
 11using System.Windows.Input;
 12using MyNet.Globalization.Culture;
 13using MyNet.UI.Commands;
 14
 15namespace MyNet.UI.ViewModels.Workspace;
 16
 17/// <summary>
 18/// Provides a reusable base implementation for tabbed workspace view models.
 19/// </summary>
 20public abstract class TabWorkspaceViewModel : WorkspaceViewModel, ITabWorkspaceViewModel
 21{
 1522    private readonly ObservableCollection<IWorkspaceViewModel> _workspaces = [];
 23
 24    /// <summary>
 25    /// Initializes a new instance of the <see cref="TabWorkspaceViewModel"/> class.
 26    /// </summary>
 27    /// <param name="commandFactory">Optional command factory used to create commands.</param>
 28    /// <param name="cultureService">Optional culture service used to manage culture changes.</param>
 29    protected TabWorkspaceViewModel(
 30        ICommandFactory? commandFactory = null,
 31        ICultureService? cultureService = null)
 1532        : base(commandFactory, cultureService)
 33    {
 1534        var commands = commandFactory.GetOrDefault();
 35
 1536        Workspaces = new(_workspaces);
 37
 1538        GoToTabCommand = commands.CreateRequired<object>(GoToTab, CanGoToTab);
 1539        GoToNextTabCommand = commands.Create(GoToNextTab, CanGoToNextTab);
 1540        GoToPreviousTabCommand = commands.Create(GoToPreviousTab, CanGoToPreviousTab);
 1541    }
 42
 43    /// <summary>
 44    /// Gets the command to navigate to a specific tab by index or workspace reference.
 45    /// </summary>
 46    public ICommand GoToTabCommand { get; }
 47
 48    /// <summary>
 49    /// Gets the command to navigate to the next tab.
 50    /// </summary>
 51    public ICommand GoToNextTabCommand { get; }
 52
 53    /// <summary>
 54    /// Gets the command to navigate to the previous tab.
 55    /// </summary>
 56    public ICommand GoToPreviousTabCommand { get; }
 57
 58    /// <summary>
 59    /// Gets the hosted workspaces.
 60    /// </summary>
 61    public ReadOnlyObservableCollection<IWorkspaceViewModel> Workspaces { get; }
 62
 63    /// <summary>
 64    /// Gets the currently selected workspace.
 65    /// </summary>
 66    public IWorkspaceViewModel? SelectedWorkspace
 67    {
 68        get;
 69        private set
 70        {
 1571            if (!SetProperty(ref field, value))
 072                return;
 73
 1574            NotifyPropertyChanged(nameof(SelectedIndex));
 1575            RaiseTabNavigationCanExecuteChanged();
 1576        }
 77    }
 78
 79    /// <summary>
 80    /// Gets the selected workspace index.
 81    /// </summary>
 082    public int SelectedIndex => SelectedWorkspace is null ? -1 : _workspaces.IndexOf(SelectedWorkspace);
 83
 84    /// <summary>
 85    /// Selects the specified workspace.
 86    /// </summary>
 87    /// <param name="workspace">The workspace to select.</param>
 88    public virtual void Select(IWorkspaceViewModel workspace)
 89    {
 090        ArgumentNullException.ThrowIfNull(workspace);
 91
 092        if (!_workspaces.Contains(workspace))
 093            throw new ArgumentException(null, nameof(workspace));
 94
 095        SelectedWorkspace = workspace;
 096    }
 97
 98    /// <summary>
 99    /// Selects the workspace at the specified index.
 100    /// </summary>
 101    /// <param name="index">The zero-based index to select.</param>
 102    public virtual void Select(int index)
 103    {
 0104        if (index < 0 || index >= _workspaces.Count)
 0105            throw new ArgumentOutOfRangeException(nameof(index));
 106
 0107        SelectedWorkspace = _workspaces[index];
 0108    }
 109
 110    /// <summary>
 111    /// Adds a hosted workspace.
 112    /// </summary>
 113    /// <param name="workspace">The workspace to add.</param>
 114    protected virtual void AddWorkspace(IWorkspaceViewModel workspace)
 115    {
 15116        ArgumentNullException.ThrowIfNull(workspace);
 117
 15118        _workspaces.Add(workspace);
 119
 15120        if (workspace.State != LoadState.Loaded)
 15121            _ = ExecuteSafeAsync(workspace.LoadAsync);
 122
 15123        SelectedWorkspace ??= workspace;
 15124        RaiseTabNavigationCanExecuteChanged();
 15125    }
 126
 127    /// <summary>
 128    /// Adds several hosted workspaces.
 129    /// </summary>
 130    /// <param name="workspaces">The workspaces to add.</param>
 131    protected void AddWorkspaces(IEnumerable<IWorkspaceViewModel> workspaces)
 132    {
 15133        ArgumentNullException.ThrowIfNull(workspaces);
 134
 60135        foreach (var workspace in workspaces)
 15136            AddWorkspace(workspace);
 15137    }
 138
 139    /// <summary>
 140    /// Removes a hosted workspace.
 141    /// </summary>
 142    /// <param name="workspace">The workspace to remove.</param>
 143    /// <returns><see langword="true"/> when the workspace was removed; otherwise <see langword="false"/>.</returns>
 144    protected virtual bool RemoveWorkspace(IWorkspaceViewModel workspace)
 145    {
 0146        ArgumentNullException.ThrowIfNull(workspace);
 147
 0148        var removed = _workspaces.Remove(workspace);
 149
 0150        if (!removed)
 0151            return false;
 152
 0153        if (ReferenceEquals(SelectedWorkspace, workspace))
 0154            SelectedWorkspace = _workspaces.FirstOrDefault();
 155
 0156        RaiseTabNavigationCanExecuteChanged();
 0157        return true;
 158    }
 159
 160    /// <summary>
 161    /// Clears all hosted workspaces.
 162    /// </summary>
 163    protected void ClearWorkspaces()
 164    {
 0165        _workspaces.Clear();
 0166        SelectedWorkspace = null;
 0167        RaiseTabNavigationCanExecuteChanged();
 0168    }
 169
 170    /// <summary>
 171    /// Navigates to the specified tab by index or workspace reference.
 172    /// </summary>
 173    /// <param name="indexOrWorkspace">An <see cref="int"/> index or an <see cref="IWorkspaceViewModel"/> reference.</pa
 174    protected virtual void GoToTab(object indexOrWorkspace)
 175    {
 176        switch (indexOrWorkspace)
 177        {
 178            case int index:
 0179                Select(index);
 0180                break;
 181            case IWorkspaceViewModel workspace:
 0182                Select(workspace);
 183                break;
 184        }
 0185    }
 186
 187    /// <summary>
 188    /// Determines whether navigation to the specified tab is allowed.
 189    /// </summary>
 0190    protected virtual bool CanGoToTab(object target) => _workspaces.Count > 0;
 191
 192    /// <summary>
 193    /// Navigates to the next tab.
 194    /// </summary>
 195    protected virtual void GoToNextTab()
 196    {
 0197        if (SelectedIndex < _workspaces.Count - 1)
 0198            Select(SelectedIndex + 1);
 0199    }
 200
 201    /// <summary>
 202    /// Determines whether navigation to the next tab is allowed.
 203    /// </summary>
 0204    protected virtual bool CanGoToNextTab() => SelectedWorkspace is not null && SelectedIndex < _workspaces.Count - 1;
 205
 206    /// <summary>
 207    /// Navigates to the previous tab.
 208    /// </summary>
 209    protected virtual void GoToPreviousTab()
 210    {
 0211        if (SelectedIndex > 0)
 0212            Select(SelectedIndex - 1);
 0213    }
 214
 215    /// <summary>
 216    /// Determines whether navigation to the previous tab is allowed.
 217    /// </summary>
 0218    protected virtual bool CanGoToPreviousTab() => SelectedWorkspace is not null && SelectedIndex > 0;
 219
 220    private void RaiseTabNavigationCanExecuteChanged()
 221    {
 30222        (GoToTabCommand as IRaiseCanExecuteChanged)?.RaiseCanExecuteChanged();
 30223        (GoToNextTabCommand as IRaiseCanExecuteChanged)?.RaiseCanExecuteChanged();
 30224        (GoToPreviousTabCommand as IRaiseCanExecuteChanged)?.RaiseCanExecuteChanged();
 30225    }
 226}
 227