mirror of
https://github.com/stride3d/stride.git
synced 2026-10-12 02:23:23 +00:00
A few fixes following merge from master
This commit is contained in:
@@ -51,10 +51,10 @@ Global
|
||||
{78695DE1-E621-45DF-975D-CFD407081E23}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78695DE1-E621-45DF-975D-CFD407081E23}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78695DE1-E621-45DF-975D-CFD407081E23}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BAC8FB10-95ED-4FBB-9925-F6F0E15BD936}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BAC8FB10-95ED-4FBB-9925-F6F0E15BD936}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BAC8FB10-95ED-4FBB-9925-F6F0E15BD936}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -107,10 +107,10 @@ Global
|
||||
{3B613E66-671E-4049-8EF5-43CDAA549210}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3B613E66-671E-4049-8EF5-43CDAA549210}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3B613E66-671E-4049-8EF5-43CDAA549210}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{835D46B3-1E85-4D28-9F25-A1BD7A2C30F7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A321E09-24D6-4446-8E95-2C29404C8B76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
<ProjectReference Include="..\..\tests\xunit.runner.stride\xunit.runner.stride.csproj" />
|
||||
<ProjectReference Include="..\Stride.Core.Yaml\Stride.Core.Yaml.csproj" />
|
||||
<PackageReference Include="System.Drawing.Common" Condition="'$(TargetFramework)' == '$(StrideFramework)'" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(StrideRoot)sources/sdk/Stride.Build.Sdk.Tests/Sdk/Sdk.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -27,6 +27,9 @@ internal sealed class FakeDialogService : IDialogService
|
||||
public Task<CheckedMessageBoxResult> CheckedMessageBoxAsync(string message, bool? isChecked, string checkboxMessage, IReadOnlyCollection<DialogButtonInfo> buttons, MessageBoxImage image = MessageBoxImage.None)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task<int> CheckedMessageBoxAsync(string message, IReadOnlyCollection<DialogCheckBoxInfo> checkBoxes, IReadOnlyCollection<DialogButtonInfo> buttons, MessageBoxImage image = MessageBoxImage.None)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task<UFile?> OpenFilePickerAsync(UDirectory? initialPath = null, IReadOnlyList<FilePickerFilter>? filters = null)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
|
||||
@@ -30,13 +30,12 @@ public class ImageComparisonViewModel : ViewModelBase
|
||||
public string? StatsSummary { get; }
|
||||
public string Label { get; }
|
||||
|
||||
Bitmap? currentBitmap;
|
||||
public Bitmap? CurrentBitmap
|
||||
{
|
||||
get => currentBitmap;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref currentBitmap, value))
|
||||
if (SetValue(ref field, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowCurrentImage));
|
||||
OnPropertyChanged(nameof(ShowCurrentPlaceholder));
|
||||
@@ -44,13 +43,12 @@ public class ImageComparisonViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap? referenceBitmap;
|
||||
public Bitmap? ReferenceBitmap
|
||||
{
|
||||
get => referenceBitmap;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref referenceBitmap, value))
|
||||
if (SetValue(ref field, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowReferenceImage));
|
||||
OnPropertyChanged(nameof(ShowReferencePlaceholder));
|
||||
@@ -58,13 +56,12 @@ public class ImageComparisonViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
WriteableBitmap? diffBitmap;
|
||||
public WriteableBitmap? DiffBitmap
|
||||
{
|
||||
get => diffBitmap;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref diffBitmap, value))
|
||||
if (SetValue(ref field, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowDiffImage));
|
||||
OnPropertyChanged(nameof(ShowDiffPassed));
|
||||
@@ -73,11 +70,11 @@ public class ImageComparisonViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowCurrentImage => currentBitmap is not null;
|
||||
public bool ShowCurrentPlaceholder => currentBitmap is null && Passed;
|
||||
public bool ShowReferenceImage => referenceBitmap is not null;
|
||||
public bool ShowReferencePlaceholder => referenceBitmap is null;
|
||||
public bool ShowDiffImage => diffBitmap is not null;
|
||||
public bool ShowDiffPassed => diffBitmap is null && Passed;
|
||||
public bool ShowDiffPlaceholder => diffBitmap is null && !Passed;
|
||||
public bool ShowCurrentImage => CurrentBitmap is not null;
|
||||
public bool ShowCurrentPlaceholder => CurrentBitmap is null && Passed;
|
||||
public bool ShowReferenceImage => ReferenceBitmap is not null;
|
||||
public bool ShowReferencePlaceholder => ReferenceBitmap is null;
|
||||
public bool ShowDiffImage => DiffBitmap is not null;
|
||||
public bool ShowDiffPassed => DiffBitmap is null && Passed;
|
||||
public bool ShowDiffPlaceholder => DiffBitmap is null && !Passed;
|
||||
}
|
||||
|
||||
@@ -50,35 +50,32 @@ public class TestCaseViewModel : TestNodeViewModel
|
||||
}
|
||||
}
|
||||
|
||||
string? failureMessage;
|
||||
/// <summary>Combined exception messages from the most recent run (newline-joined). Empty if the test passed or hasn't run.</summary>
|
||||
public string? FailureMessage
|
||||
{
|
||||
get => failureMessage;
|
||||
set => SetProperty(ref failureMessage, value);
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
}
|
||||
|
||||
string? failureStackTrace;
|
||||
/// <summary>Combined stack traces from the most recent run. Empty if the test passed or hasn't run.</summary>
|
||||
public string? FailureStackTrace
|
||||
{
|
||||
get => failureStackTrace;
|
||||
set => SetProperty(ref failureStackTrace, value);
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
}
|
||||
|
||||
string? output;
|
||||
/// <summary>Captured stdout/stderr produced during the most recent run.</summary>
|
||||
public string? Output
|
||||
{
|
||||
get => output;
|
||||
get;
|
||||
set
|
||||
{
|
||||
SetProperty(ref output, value);
|
||||
SetValue(ref field, value);
|
||||
OnPropertyChanged(nameof(HasOutput));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasOutput => !string.IsNullOrEmpty(output);
|
||||
public bool HasOutput => !string.IsNullOrEmpty(Output);
|
||||
|
||||
// === Image comparison (populated from ImageComparisonCompleted event in GameTestBase) ===
|
||||
|
||||
|
||||
@@ -11,89 +11,81 @@ public abstract class TestNodeViewModel : ViewModelBase
|
||||
|
||||
public abstract TestCaseViewModel? LocateTestCase(ITestCase testCase);
|
||||
|
||||
bool running;
|
||||
public bool Running
|
||||
{
|
||||
get => running;
|
||||
set { if (SetProperty(ref running, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
get;
|
||||
set { if (SetValue(ref field, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
}
|
||||
|
||||
bool failed;
|
||||
public bool Failed
|
||||
{
|
||||
get => failed;
|
||||
set { if (SetProperty(ref failed, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
get;
|
||||
set { if (SetValue(ref field, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
}
|
||||
|
||||
bool succeeded;
|
||||
public bool Succeeded
|
||||
{
|
||||
get => succeeded;
|
||||
set { if (SetProperty(ref succeeded, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
get;
|
||||
set { if (SetValue(ref field, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
}
|
||||
|
||||
bool skipped;
|
||||
public bool Skipped
|
||||
{
|
||||
get => skipped;
|
||||
set { if (SetProperty(ref skipped, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
get;
|
||||
set { if (SetValue(ref field, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
}
|
||||
|
||||
bool pending;
|
||||
/// <summary>True after the test was queued for a run but before it actually starts;
|
||||
/// drives the "…" icon so multi-test runs show what's still waiting.</summary>
|
||||
public bool Pending
|
||||
{
|
||||
get => pending;
|
||||
set { if (SetProperty(ref pending, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
get;
|
||||
set { if (SetValue(ref field, value)) OnPropertyChanged(nameof(HasResult)); }
|
||||
}
|
||||
|
||||
/// <summary>True once the test has any kind of result (running, queued, or finished).
|
||||
/// The detail view shows a big "Run" call-to-action when this is false.</summary>
|
||||
public bool HasResult => running || failed || succeeded || skipped || pending || elapsedSeconds.HasValue;
|
||||
public bool HasResult => Running || Failed || Succeeded || Skipped || Pending || ElapsedSeconds.HasValue;
|
||||
|
||||
decimal? elapsedSeconds;
|
||||
/// <summary>Last execution time in seconds. <see langword="null"/> if not yet run.</summary>
|
||||
public decimal? ElapsedSeconds
|
||||
{
|
||||
get => elapsedSeconds;
|
||||
get;
|
||||
set
|
||||
{
|
||||
SetProperty(ref elapsedSeconds, value);
|
||||
SetValue(ref field, value);
|
||||
OnPropertyChanged(nameof(ElapsedDisplay));
|
||||
OnPropertyChanged(nameof(HasElapsed));
|
||||
OnPropertyChanged(nameof(HasResult));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasElapsed => elapsedSeconds.HasValue;
|
||||
public bool HasElapsed => ElapsedSeconds.HasValue;
|
||||
|
||||
public string ElapsedDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!elapsedSeconds.HasValue) return string.Empty;
|
||||
var ms = (double)elapsedSeconds.Value * 1000.0;
|
||||
if (!ElapsedSeconds.HasValue) return string.Empty;
|
||||
var ms = (double)ElapsedSeconds.Value * 1000.0;
|
||||
return ms < 1000.0 ? $"{ms:F0} ms" : $"{ms / 1000.0:F2} s";
|
||||
}
|
||||
}
|
||||
|
||||
bool isVisible = true;
|
||||
/// <summary>Whether this node passes the current filter. Group nodes are visible if any descendant is visible.</summary>
|
||||
public bool IsVisible
|
||||
{
|
||||
get => isVisible;
|
||||
set => SetProperty(ref isVisible, value);
|
||||
}
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
} = true;
|
||||
|
||||
bool isPrimarySelection;
|
||||
/// <summary>True for the focused row in a multi-selection — the one shown in the inspect
|
||||
/// pane. Drives a small left accent stripe so the primary stands out from the rest of
|
||||
/// the selection.</summary>
|
||||
public bool IsPrimarySelection
|
||||
{
|
||||
get => isPrimarySelection;
|
||||
set => SetProperty(ref isPrimarySelection, value);
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
}
|
||||
|
||||
public abstract string DisplayName { get; }
|
||||
|
||||
@@ -375,24 +375,22 @@ public class TestsViewModel : ViewModelBase
|
||||
|
||||
// === Filter ===
|
||||
|
||||
string filterText = string.Empty;
|
||||
public string FilterText
|
||||
{
|
||||
get => filterText;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref filterText, value ?? string.Empty))
|
||||
if (SetValue(ref field, value ?? string.Empty))
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
} = string.Empty;
|
||||
|
||||
StatusFilter statusFilter = StatusFilter.All;
|
||||
public StatusFilter StatusFilter
|
||||
{
|
||||
get => statusFilter;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref statusFilter, value))
|
||||
if (SetValue(ref field, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(StatusFilterIsAll));
|
||||
OnPropertyChanged(nameof(StatusFilterIsPassed));
|
||||
@@ -402,38 +400,38 @@ public class TestsViewModel : ViewModelBase
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
} = StatusFilter.All;
|
||||
|
||||
// ToggleButton bindings (one-way set true; user can't un-toggle the active one)
|
||||
public bool StatusFilterIsAll
|
||||
{
|
||||
get => statusFilter == StatusFilter.All;
|
||||
get => StatusFilter == StatusFilter.All;
|
||||
set { if (value) StatusFilter = StatusFilter.All; else OnPropertyChanged(nameof(StatusFilterIsAll)); }
|
||||
}
|
||||
public bool StatusFilterIsPassed
|
||||
{
|
||||
get => statusFilter == StatusFilter.Passed;
|
||||
get => StatusFilter == StatusFilter.Passed;
|
||||
set { if (value) StatusFilter = StatusFilter.Passed; else OnPropertyChanged(nameof(StatusFilterIsPassed)); }
|
||||
}
|
||||
public bool StatusFilterIsFailed
|
||||
{
|
||||
get => statusFilter == StatusFilter.Failed;
|
||||
get => StatusFilter == StatusFilter.Failed;
|
||||
set { if (value) StatusFilter = StatusFilter.Failed; else OnPropertyChanged(nameof(StatusFilterIsFailed)); }
|
||||
}
|
||||
public bool StatusFilterIsSkipped
|
||||
{
|
||||
get => statusFilter == StatusFilter.Skipped;
|
||||
get => StatusFilter == StatusFilter.Skipped;
|
||||
set { if (value) StatusFilter = StatusFilter.Skipped; else OnPropertyChanged(nameof(StatusFilterIsSkipped)); }
|
||||
}
|
||||
public bool StatusFilterIsNotRun
|
||||
{
|
||||
get => statusFilter == StatusFilter.NotRun;
|
||||
get => StatusFilter == StatusFilter.NotRun;
|
||||
set { if (value) StatusFilter = StatusFilter.NotRun; else OnPropertyChanged(nameof(StatusFilterIsNotRun)); }
|
||||
}
|
||||
|
||||
public void ApplyFilter()
|
||||
{
|
||||
var needle = filterText.Trim();
|
||||
var needle = FilterText.Trim();
|
||||
foreach (var root in TestCases)
|
||||
ApplyFilter(root, needle);
|
||||
}
|
||||
@@ -451,7 +449,7 @@ public class TestsViewModel : ViewModelBase
|
||||
else if (node is TestCaseViewModel testCase)
|
||||
{
|
||||
bool matchesText = needle.Length == 0 || testCase.DisplayName.Contains(needle, StringComparison.OrdinalIgnoreCase);
|
||||
bool matchesStatus = statusFilter switch
|
||||
bool matchesStatus = StatusFilter switch
|
||||
{
|
||||
StatusFilter.All => true,
|
||||
StatusFilter.Passed => testCase.Succeeded,
|
||||
@@ -468,19 +466,18 @@ public class TestsViewModel : ViewModelBase
|
||||
|
||||
// === Counts / summary ===
|
||||
|
||||
int passedCount, failedCount, skippedCount, notRunCount, totalCount;
|
||||
decimal totalElapsedSeconds;
|
||||
public int PassedCount { get => passedCount; private set => SetProperty(ref passedCount, value); }
|
||||
public int FailedCount { get => failedCount; private set => SetProperty(ref failedCount, value); }
|
||||
public int SkippedCount { get => skippedCount; private set => SetProperty(ref skippedCount, value); }
|
||||
public int NotRunCount { get => notRunCount; private set => SetProperty(ref notRunCount, value); }
|
||||
public int TotalCount { get => totalCount; private set => SetProperty(ref totalCount, value); }
|
||||
|
||||
public int PassedCount { get; private set => SetValue(ref field, value); }
|
||||
public int FailedCount { get; private set => SetValue(ref field, value); }
|
||||
public int SkippedCount { get; private set => SetValue(ref field, value); }
|
||||
public int NotRunCount { get; private set => SetValue(ref field, value); }
|
||||
public int TotalCount { get; private set => SetValue(ref field, value); }
|
||||
public decimal TotalElapsedSeconds
|
||||
{
|
||||
get => totalElapsedSeconds;
|
||||
get;
|
||||
private set
|
||||
{
|
||||
if (SetProperty(ref totalElapsedSeconds, value))
|
||||
if (SetValue(ref field, value))
|
||||
OnPropertyChanged(nameof(TotalElapsedDisplay));
|
||||
}
|
||||
}
|
||||
@@ -489,15 +486,15 @@ public class TestsViewModel : ViewModelBase
|
||||
{
|
||||
get
|
||||
{
|
||||
var s = (double)totalElapsedSeconds;
|
||||
var s = (double)TotalElapsedSeconds;
|
||||
return s < 60 ? $"{s:F2}s" : $"{(int)(s / 60)}m {s % 60:F1}s";
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFailures => failedCount > 0;
|
||||
public bool HasFailures => FailedCount > 0;
|
||||
|
||||
/// <summary>True when there's at least one failed test AND no run in progress; drives the "Re-run failed" button.</summary>
|
||||
public bool CanRunFailed => failedCount > 0 && !runningTests;
|
||||
public bool CanRunFailed => FailedCount > 0 && !RunningTests;
|
||||
|
||||
void RecomputeCounts()
|
||||
{
|
||||
@@ -545,20 +542,18 @@ public class TestsViewModel : ViewModelBase
|
||||
|
||||
// === State ===
|
||||
|
||||
double testCompletion;
|
||||
public double TestCompletion
|
||||
{
|
||||
get => testCompletion;
|
||||
set => SetProperty(ref testCompletion, value);
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
}
|
||||
|
||||
bool runningTests;
|
||||
public bool RunningTests
|
||||
{
|
||||
get => runningTests;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref runningTests, value))
|
||||
if (SetValue(ref field, value))
|
||||
OnPropertyChanged(nameof(CanRunFailed));
|
||||
}
|
||||
}
|
||||
@@ -571,15 +566,14 @@ public class TestsViewModel : ViewModelBase
|
||||
/// (typically <c>GameTestBase.RenderDocMode</c>). Accepts <c>null</c> ("never"), "error", "always".</summary>
|
||||
public Action<string?>? SetRenderDocMode { get; set; }
|
||||
|
||||
bool isForceSaveImage;
|
||||
/// <summary>Persistent toggle: when on, every run sets <c>ForceSaveImageOnSuccess</c> so
|
||||
/// the rendered output is written to disk even when the gold comparison passes.</summary>
|
||||
public bool IsForceSaveImage
|
||||
{
|
||||
get => isForceSaveImage;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isForceSaveImage, value))
|
||||
if (SetValue(ref field, value))
|
||||
SetForceSaveImage?.Invoke(value);
|
||||
}
|
||||
}
|
||||
@@ -592,7 +586,7 @@ public class TestsViewModel : ViewModelBase
|
||||
get => renderDocMode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref renderDocMode, value))
|
||||
if (SetValue(ref renderDocMode, value))
|
||||
{
|
||||
var s = value switch
|
||||
{
|
||||
@@ -617,15 +611,14 @@ public class TestsViewModel : ViewModelBase
|
||||
|
||||
// === Mobile / narrow-viewport state ===
|
||||
|
||||
bool isNarrowMode;
|
||||
/// <summary>True when the main split is in stacked (phone/portrait) mode. Drives the
|
||||
/// drill-down nav (tap-to-detail / back) and hides per-row run buttons.</summary>
|
||||
public bool IsNarrowMode
|
||||
{
|
||||
get => isNarrowMode;
|
||||
get;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isNarrowMode, value))
|
||||
if (SetValue(ref field, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsWideMode));
|
||||
OnPropertyChanged(nameof(RowMinHeight));
|
||||
@@ -637,18 +630,17 @@ public class TestsViewModel : ViewModelBase
|
||||
|
||||
/// <summary>Inverse of <see cref="IsNarrowMode"/>; convenience for per-row "show on wide
|
||||
/// only" visibility bindings.</summary>
|
||||
public bool IsWideMode => !isNarrowMode;
|
||||
public bool IsWideMode => !IsNarrowMode;
|
||||
|
||||
/// <summary>Minimum tree-row height; bumped in narrow mode to give touch targets enough
|
||||
/// surface to be reliably tappable.</summary>
|
||||
public double RowMinHeight => isNarrowMode ? 44 : 0;
|
||||
public double RowMinHeight => IsNarrowMode ? 44 : 0;
|
||||
|
||||
bool isDetailPageActive;
|
||||
/// <summary>In narrow mode, true means the detail pane is showing instead of the list.
|
||||
/// Ignored in wide mode.</summary>
|
||||
public bool IsDetailPageActive
|
||||
{
|
||||
get => isDetailPageActive;
|
||||
set => SetProperty(ref isDetailPageActive, value);
|
||||
get;
|
||||
set => SetValue(ref field, value);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user