Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions Source/NETworkManager.Profiles/IProfileHostViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using NETworkManager.Controls;
using System.ComponentModel;
using System.Windows.Input;

namespace NETworkManager.Profiles;

/// <summary>
/// Interface for a view model that hosts the shared profile panel (search, tag filter, group list) next to a
/// tool-specific view, extending <see cref="IProfileManager" /> with the additional members the reusable
/// profile panel control binds to.
/// </summary>
public interface IProfileHostViewModel : IProfileManager
{
/// <summary>
/// Gets or sets the selected profile.
/// </summary>
ProfileInfo SelectedProfile { get; set; }

/// <summary>
/// Gets or sets the search text.
/// </summary>
string Search { get; set; }

/// <summary>
/// Gets or sets a value indicating whether a search is in progress.
/// </summary>
bool IsSearching { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the profile filter popup is open.
/// </summary>
bool ProfileFilterIsOpen { get; set; }

/// <summary>
/// Gets the view for the profile filter tags.
/// </summary>
ICollectionView ProfileFilterTagsView { get; }

/// <summary>
/// Gets or sets a value indicating whether to match any profile filter tag.
/// </summary>
bool ProfileFilterTagsMatchAny { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to match all profile filter tags.
/// </summary>
bool ProfileFilterTagsMatchAll { get; set; }

/// <summary>
/// Gets or sets a value indicating whether a profile filter is currently applied.
/// </summary>
bool IsProfileFilterSet { get; set; }

/// <summary>
/// Gets the group expander state store for the profile list.
/// </summary>
GroupExpanderStateStore GroupExpanderStateStore { get; }

/// <summary>
/// Gets the command to open the profile filter popup.
/// </summary>
ICommand OpenProfileFilterCommand { get; }

/// <summary>
/// Gets the command to apply the profile filter.
/// </summary>
ICommand ApplyProfileFilterCommand { get; }

/// <summary>
/// Gets the command to clear the profile filter.
/// </summary>
ICommand ClearProfileFilterCommand { get; }

/// <summary>
/// Gets the command to expand all profile groups.
/// </summary>
ICommand ExpandAllProfileGroupsCommand { get; }

/// <summary>
/// Gets the command to collapse all profile groups.
/// </summary>
ICommand CollapseAllProfileGroupsCommand { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NETworkManager.Controls\NETworkManager.Controls.csproj" />
<ProjectReference Include="..\NETworkManager.Models\NETworkManager.Models.csproj" />
<ProjectReference Include="..\NETworkManager.Settings\NETworkManager.Settings.csproj" />
<ProjectReference Include="..\NETworkManager.Utilities\NETworkManager.Utilities.csproj" />
Expand Down
123 changes: 123 additions & 0 deletions Source/NETworkManager.Settings/ProfileViewState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Windows;
using NETworkManager.Utilities;

namespace NETworkManager.Settings;

/// <summary>
/// Shared expanded/width state of the profile panel, used by every tool that hosts a profile list. Because all
/// tools observe the same <see cref="Current" /> instance, resizing or collapsing the profile panel in one tool
/// is reflected in every other tool automatically through data binding - no manual synchronization needed.
/// </summary>
/// <remarks>
/// <see cref="Current" /> reads <see cref="SettingsManager.Current" /> the first time it is accessed. This is
/// only safe once <see cref="SettingsManager.Load" /> has completed (done early in App.xaml.cs, before the main
/// window - and therefore any tool view - is created). Do not reference <see cref="Current" /> from eagerly
/// loaded resources (e.g. App.xaml or globally merged style dictionaries).
/// </remarks>
public sealed class ProfileViewState : PropertyChangedBase
{
public static ProfileViewState Current { get; }

static ProfileViewState()
{
Current = new ProfileViewState();
}

private readonly bool _isLoading;
private bool _canProfileWidthChange = true;
private double _tempProfileWidth;

private ProfileViewState()
{
_isLoading = true;

// Must be set before ExpandProfileView below, since assigning it can synchronously trigger
// ResizeProfile(false), which reads _tempProfileWidth.
_tempProfileWidth = SettingsManager.Current.Profile_Width;

ExpandProfileView = SettingsManager.Current.Profile_ExpandView;

ProfileWidth = ExpandProfileView
? new GridLength(SettingsManager.Current.Profile_Width)
: new GridLength(GlobalStaticConfiguration.Profile_WidthCollapsed);

_isLoading = false;
}

/// <summary>
/// Gets or sets a value indicating whether the profile panel is expanded, shared across all tools.
/// </summary>
public bool ExpandProfileView
{
get;
set
{
if (value == field)
return;

if (!_isLoading)
SettingsManager.Current.Profile_ExpandView = value;

field = value;

if (_canProfileWidthChange)
ResizeProfile(false);

OnPropertyChanged();
}
}

/// <summary>
/// Gets or sets the width of the profile panel, shared across all tools.
/// </summary>
public GridLength ProfileWidth
{
get;
set
{
if (value == field)
return;

if (!_isLoading && Math.Abs(value.Value - GlobalStaticConfiguration.Profile_WidthCollapsed) >
GlobalStaticConfiguration.FloatPointFix) // Do not save the size when collapsed
SettingsManager.Current.Profile_Width = value.Value;

field = value;

if (_canProfileWidthChange)
ResizeProfile(true);

OnPropertyChanged();
}
}

private void ResizeProfile(bool dueToChangedSize)
{
_canProfileWidthChange = false;

if (dueToChangedSize)
{
ExpandProfileView = Math.Abs(ProfileWidth.Value - GlobalStaticConfiguration.Profile_WidthCollapsed) >
GlobalStaticConfiguration.FloatPointFix;
}
else
{
if (ExpandProfileView)
{
ProfileWidth =
Math.Abs(_tempProfileWidth - GlobalStaticConfiguration.Profile_WidthCollapsed) <
GlobalStaticConfiguration.FloatPointFix
? new GridLength(GlobalStaticConfiguration.Profile_DefaultWidthExpanded)
: new GridLength(_tempProfileWidth);
}
else
{
_tempProfileWidth = ProfileWidth.Value;
ProfileWidth = new GridLength(GlobalStaticConfiguration.Profile_WidthCollapsed);
}
}

_canProfileWidthChange = true;
}
}
Loading
Loading