diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71800322..ac3ba51c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,11 +98,16 @@ jobs: # Keep current repo LAST. Do not duplicate SAM_UI earlier in the list. $buildOrder = @( 'SAM' + 'SAM_Mollier' 'SAM_Systems' 'SAM_Windows' - 'SAM_Mollier' 'SAM_gbXML' 'SAM_SolarCalculator' + # Must precede SAM_Tas: SAM_Tas\benchmark\SAM.Analytical.Tas.Benchmark references + # SAM_Validation\build\SAM.Analytical.Benchmark.dll by HintPath, and without it it fails + # CS0234. Same slot as BuildAlls_v4.csproj uses locally. Needs only SAM and SAM_Mollier, + # both already above. + 'SAM_Validation' 'SAM_Tas' 'SAM_Excel' 'SAM_GEM' @@ -123,7 +128,18 @@ jobs: # Current sow branch: base_ref on PR events, ref_name on push events. $sowRef = if ($baseRef -match '^sow/') { $baseRef } elseif ($refName -match '^sow/') { $refName } else { '' } if ($sowRef -and $sowRef -ne $headRef) { $candidates += $sowRef } - $candidates += 'sow/2026-Q2' + # Canonical quarter branch (strip suffixes like -update-optimization): e.g. sow/2026-Q3. + # On push events base_ref is empty and ref_name may be a feature branch off a sow branch, + # so without this the dep clone falls back to master and misses in-quarter API changes. + $canonical = '' + foreach ($cref in @($headRef, $baseRef, $refName)) { + if ($cref -match 'sow/(\d{4})-Q(\d)') { $canonical = "sow/$($Matches[1])-Q$($Matches[2])"; break } + } + if ($canonical -and $candidates -notcontains $canonical) { $candidates += $canonical } + # Hard fallbacks to the active quarter branches (in priority order). + foreach ($fb in @('sow/2026-Q3', 'sow/2026-Q2')) { + if ($candidates -notcontains $fb) { $candidates += $fb } + } # Use the auth-token form so private deps (e.g. SAM_Solver) don't prompt $url = if ($token) { "https://$token@github.com/$org/$r.git" } else { "https://github.com/$org/$r.git" } $cloned = $false @@ -170,11 +186,16 @@ jobs: # Keep current repo LAST. SAM_Solver must be built before SAM_UI. $buildOrder = @( 'SAM' + 'SAM_Mollier' 'SAM_Systems' 'SAM_Windows' - 'SAM_Mollier' 'SAM_gbXML' 'SAM_SolarCalculator' + # Must precede SAM_Tas: SAM_Tas\benchmark\SAM.Analytical.Tas.Benchmark references + # SAM_Validation\build\SAM.Analytical.Benchmark.dll by HintPath, and without it it fails + # CS0234. Same slot as BuildAlls_v4.csproj uses locally. Needs only SAM and SAM_Mollier, + # both already above. + 'SAM_Validation' 'SAM_Tas' 'SAM_Excel' 'SAM_GEM' diff --git a/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj b/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj index 6f3692a9..3bfcb556 100644 --- a/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj +++ b/Application/SAM Analytical Mollier/SAM Analytical Mollier.csproj @@ -11,7 +11,7 @@ false true true - Debug;Release;net48-windows + Debug;Release SAM.ico diff --git a/Application/SAM Analytical/SAM Analytical.csproj b/Application/SAM Analytical/SAM Analytical.csproj index 4f5fa489..9d3684f8 100644 --- a/Application/SAM Analytical/SAM Analytical.csproj +++ b/Application/SAM Analytical/SAM Analytical.csproj @@ -11,7 +11,7 @@ false true true - Debug;Release;net48-windows + Debug;Release SAM.ico @@ -50,11 +50,9 @@ ..\..\..\SAM\build\SAM.Core.dll - ..\..\..\SAM\build\SAM.Geometry.dll - @@ -153,7 +151,7 @@ 2.27.0 - + 1.9.7 diff --git a/Application/SAM Geometry/SAM Geometry.csproj b/Application/SAM Geometry/SAM Geometry.csproj index c9984bab..dae119eb 100644 --- a/Application/SAM Geometry/SAM Geometry.csproj +++ b/Application/SAM Geometry/SAM Geometry.csproj @@ -9,7 +9,7 @@ false true true - Debug;Release;net48-windows + Debug;Release ..\..\build\ @@ -24,8 +24,6 @@ - - diff --git a/Application/SAM Weather/SAM Weather.csproj b/Application/SAM Weather/SAM Weather.csproj index 545f4072..f5ff0ba4 100644 --- a/Application/SAM Weather/SAM Weather.csproj +++ b/Application/SAM Weather/SAM Weather.csproj @@ -10,7 +10,7 @@ false true true - Debug;Release;net48-windows + Debug;Release SAM.ico @@ -22,8 +22,6 @@ ..\..\..\SAM\build\SAM.Weather.dll - - diff --git a/Directory.Build.props b/Directory.Build.props index 509f4c68..39ed51d0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,6 +23,15 @@ true + + + 2.6.0 + + + + ..\..\..\SAM\build\SAM.Architectural.dll + + + + ..\..\..\SAM\build\SAM.Weather.dll + + + + ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.dll + + + + + ..\..\..\SAM_Systems\build\SAM.Analytical.Systems.dll + + + ..\..\..\SAM_Systems\build\SAM.Core.Systems.dll + + + ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.TPD.dll + + + ..\..\..\SAM_Tas\build\SAM.Core.Tas.dll + + + ..\..\..\SAM_Tas\build\SAM.Analytical.Tas.TM59.dll + + + + ..\..\..\SAM\build\SAM.Analytical.Reporting.dll + + + ..\..\..\SAM\build\SAM.Core.Reporting.dll + + + ..\..\..\SAM\build\SAM.Core.Reporting.Pdf.dll + + + ..\..\..\SAM\build\SAM.Units.dll + + + + + + + + + + + + diff --git a/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs b/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs new file mode 100644 index 00000000..11c5fb54 --- /dev/null +++ b/WPF/SAM.Analytical.UI.WPF.Tests/SearchWindowConfirmTests.cs @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (c) 2020–2026 Michal Dengusiak & Jakub Ziolkowski and contributors + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Windows; +using System.Windows.Automation.Peers; +using System.Windows.Automation.Provider; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Threading; +using SAM.Core.UI.WPF; +using Xunit; + +namespace SAM.Analytical.UI.WPF.Tests +{ + /// + /// - the "Select Construction" / "Select Filter" / ... picker - can be + /// confirmed. Before this it had an OK button with no Click handler and no IsDefault, and nothing wired + /// to double-click, so every ShowDialog() != true caller (Assign Construction, Assign Aperture + /// Construction, Assign Internal Condition, the Create Case controls, ...) could only ever be closed with + /// Cancel and the choice was never applied. + /// + /// Each test opens a real modal window and drives it from the dispatcher once it has rendered. A watchdog + /// closes the window if a confirm path is broken, so a regression fails the assertion instead of hanging + /// the run. + /// + /// + [Collection(WpfCollection.Name)] + public class SearchWindowConfirmTests + { + private sealed class Item + { + public Item(string name) + { + Name = name; + } + + public string Name { get; } + } + + private static SearchWindow Create(out List items, SelectionMode selectionMode = SelectionMode.Single) + { + items = new List { new Item("Brick"), new Item("Concrete"), new Item("Timber") }; + + return new SearchWindow(items, x => (x as Item)?.Name) { SelectionMode = selectionMode }; + } + + private static T Field(object instance, string name) where T : class + { + FieldInfo fieldInfo = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + + return fieldInfo?.GetValue(instance) as T; + } + + private static ListBox ListBoxOf(SearchWindow window) + { + return Field(Field(window, "SearchControl_Main"), "ListBox_Main"); + } + + private static Button OKOf(SearchWindow window) + { + return Field