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
43 changes: 7 additions & 36 deletions .github/workflows/Integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,14 @@ name: Integration

on:
pull_request:
branches: [main]
branches: [ main ]
push:
branches: [main]
branches: [ main ]
workflow_dispatch:

jobs:
build-and-test:
name: Build and Test
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Restore
run: dotnet restore WPF-Framework.sln

- name: Build
run: dotnet build WPF-Framework.sln --no-restore --configuration Release

- name: Test
run: >-
dotnet test WPF-Framework.sln
--no-build
--configuration Release
--logger "trx;LogFileName=TestResults.trx"
--results-directory TestResults

- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-results
path: TestResults/**/*.trx
retention-days: 14
CI:
uses: HydrologicEngineeringCenter/dotnet-workflows/.github/workflows/integration.yml@main
with:
dotnet-version: '10.0.x'
run-tests: true
70 changes: 70 additions & 0 deletions .github/workflows/NuGetPublish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Publish to NuGet.org

on:
release:
types: [published]

permissions:
contents: read

jobs:
publish:
runs-on: windows-latest
timeout-minutes: 90

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Extract version from tag
shell: pwsh
run: |
$version = $env:GITHUB_REF_NAME -replace '^v', ''
"VERSION=$version" >> $env:GITHUB_ENV

- name: Restore
run: dotnet restore WPF-Framework.sln

- name: Build
shell: pwsh
run: dotnet build WPF-Framework.sln -c Release --no-restore /p:Version=$env:VERSION

- name: Test
env:
VSTEST_CONNECTION_TIMEOUT: '600'
run: dotnet test WPF-Framework.sln -c Release --no-build

- name: Pack
shell: pwsh
run: .\scripts\pack-wpf-framework.ps1 -Configuration Release -Version $env:VERSION -OutputDirectory packages -SkipRestore -SkipBuild

- name: Push to NuGet.org
shell: pwsh
env:
NUGET_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }}
run: |
$packageIds = @(
"RMC.Wpf.Framework.Core",
"RMC.Wpf.Framework.Models",
"RMC.Wpf.Framework.Support",
"RMC.Wpf.Framework.Controls"
)

foreach ($packageId in $packageIds) {
$packagePath = Join-Path "packages" "$packageId.$env:VERSION.nupkg"
if (-not (Test-Path $packagePath)) {
throw "Missing package: $packagePath"
}

dotnet nuget push $packagePath --api-key $env:NUGET_API_KEY --source "https://api.nuget.org/v3/index.json" --skip-duplicate
if ($LASTEXITCODE -ne 0) {
throw "NuGet push failed for $packagePath."
}
}
55 changes: 55 additions & 0 deletions .github/workflows/Release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Release

on:
push:
tags:
- "v*.*.*"

permissions:
contents: read

jobs:
build:
runs-on: windows-latest
timeout-minutes: 90

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Create version number
shell: pwsh
run: |
$tag = $env:GITHUB_REF -replace 'refs/tags/', ''
$version = $tag -replace '^v', ''
"VERSION=$version" >> $env:GITHUB_ENV

- name: Restore
run: dotnet restore WPF-Framework.sln

- name: Build
shell: pwsh
run: dotnet build WPF-Framework.sln -c Release --no-restore /p:Version=$env:VERSION

- name: Test
env:
VSTEST_CONNECTION_TIMEOUT: '600'
run: dotnet test WPF-Framework.sln -c Release --no-build

- name: Pack
shell: pwsh
run: .\scripts\pack-wpf-framework.ps1 -Configuration Release -Version $env:VERSION -OutputDirectory packages -SkipRestore -SkipBuild

- name: Upload packages
uses: actions/upload-artifact@v4
with:
name: wpf-framework-packages
path: packages/*.nupkg
retention-days: 30
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,6 @@ FodyWeavers.xsd
# AI-assistant metadata (not tracked in this repo)
CLAUDE.md
**/CLAUDE.md
AGENTS.md
**/AGENTS.md
.claude/
25 changes: 13 additions & 12 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,38 @@
<FileVersion>1.0.0.0</FileVersion>

<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<IsPackable>false</IsPackable>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>

<PackageLicenseExpression>0BSD</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>

<!-- Public API XML documentation must be complete on packable RMC libraries. -->
<WarningsAsErrors>$(WarningsAsErrors);CS1591;CS1572;CS1573;CS1574;CS0419</WarningsAsErrors>
</PropertyGroup>

<PropertyGroup Condition="'$(EnforceXmlDocumentation)' == 'true'">
<!--
Treat XML-doc warnings as errors so missing or malformed documentation on public
API fails the build instead of shipping a partial reference. Scope limited to
IsWpfFrameworkLibrary=true so vendored forks (AvalonDock, upstream OxyPlot) are
unaffected.
CS1591 - missing XML comment for publicly visible type or member
CS1572 - XML comment has a param tag for a non-existent parameter
CS1573 - parameter has no matching param tag (but other parameters do)
CS1574 - XML comment has cref attribute that could not be resolved
CS0419 - ambiguous reference in cref attribute
Release validation enables the full XML documentation warning set. Run
scripts\validate-code-xml-docs.ps1 to combine this compiler gate with the
private class and method scanner.
-->
<WarningsAsErrors>$(WarningsAsErrors);CS1591;CS1572;CS1573;CS1574;CS0419</WarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<WarningsAsErrors>$(WarningsAsErrors);CS0419;CS1570;CS1571;CS1572;CS1573;CS1574;CS1584;CS1587;CS1589;CS1591</WarningsAsErrors>
</PropertyGroup>

<ItemGroup Condition="'$(IsWpfFrameworkLibrary)' == 'true'">
<None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="\" Visible="false" />

<!-- Reproducible builds: https://github.com/dotnet/reproducible-builds -->
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.2.39">
<PackageReference Include="DotNet.ReproducibleBuilds">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

<!-- Source Link: https://github.com/dotnet/sourcelink -->
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.102">
<PackageReference Include="Microsoft.SourceLink.GitHub">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
50 changes: 50 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageFloatingVersionsEnabled>true</CentralPackageFloatingVersionsEnabled>
<ClosedXmlVersion>0.105.0</ClosedXmlVersion>
<CoverletCollectorVersion>6.0.2</CoverletCollectorVersion>
<DocumentFormatOpenXmlVersion>3.4.1</DocumentFormatOpenXmlVersion>
<DotNetReproducibleBuildsVersion>1.2.39</DotNetReproducibleBuildsVersion>
<ExcelNumberFormatVersion>1.1</ExcelNumberFormatVersion>
<FastMemberVersion>1.5.0</FastMemberVersion>
<MicrosoftNetTestSdkVersion>17.12.0</MicrosoftNetTestSdkVersion>
<MicrosoftSourceLinkGitHubVersion>10.0.102</MicrosoftSourceLinkGitHubVersion>
<MSTestTestAdapterVersion>3.5.2</MSTestTestAdapterVersion>
<MSTestTestFrameworkVersion>3.5.2</MSTestTestFrameworkVersion>
<NSubstituteVersion>4.2.1</NSubstituteVersion>
<NUnitVersion>3.14.0</NUnitVersion>
<NUnit3TestAdapterVersion>4.5.0</NUnit3TestAdapterVersion>
<!-- Restore the latest compatible RMC.Numerics 2.x release for source builds. -->
<RmcNumericsVersion>2.*</RmcNumericsVersion>
<!-- NuGet package dependencies require a valid version range, not a floating wildcard. -->
<RmcNumericsPackageDependencyVersion>[2.1.1,3.0.0)</RmcNumericsPackageDependencyVersion>
<SourceGearSqlite3Version>3.50.4.5</SourceGearSqlite3Version>
<SystemDataSQLiteVersion>2.0.2</SystemDataSQLiteVersion>
<XunitVersion>2.9.2</XunitVersion>
<XunitRunnerVisualStudioVersion>2.8.2</XunitRunnerVisualStudioVersion>
<XunitStaFactVersion>1.1.11</XunitStaFactVersion>
</PropertyGroup>

<ItemGroup>
<PackageVersion Include="ClosedXML" Version="$(ClosedXmlVersion)" />
<PackageVersion Include="coverlet.collector" Version="$(CoverletCollectorVersion)" />
<PackageVersion Include="DocumentFormat.OpenXml" Version="$(DocumentFormatOpenXmlVersion)" />
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="$(DotNetReproducibleBuildsVersion)" />
<PackageVersion Include="ExcelNumberFormat" Version="$(ExcelNumberFormatVersion)" />
<PackageVersion Include="FastMember" Version="$(FastMemberVersion)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNetTestSdkVersion)" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="$(MicrosoftSourceLinkGitHubVersion)" />
<PackageVersion Include="MSTest.TestAdapter" Version="$(MSTestTestAdapterVersion)" />
<PackageVersion Include="MSTest.TestFramework" Version="$(MSTestTestFrameworkVersion)" />
<PackageVersion Include="NSubstitute" Version="$(NSubstituteVersion)" />
<PackageVersion Include="NUnit" Version="$(NUnitVersion)" />
<PackageVersion Include="NUnit3TestAdapter" Version="$(NUnit3TestAdapterVersion)" />
<PackageVersion Include="RMC.Numerics" Version="$(RmcNumericsVersion)" />
<PackageVersion Include="SourceGear.sqlite3" Version="$(SourceGearSqlite3Version)" />
<PackageVersion Include="System.Data.SQLite" Version="$(SystemDataSQLiteVersion)" />
<PackageVersion Include="xunit" Version="$(XunitVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioVersion)" />
<PackageVersion Include="Xunit.StaFact" Version="$(XunitStaFactVersion)" />
</ItemGroup>
</Project>
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
# WPF Framework

[![CI](https://github.com/USACE-RMC/WPF-Framework/actions/workflows/Integration.yml/badge.svg)](https://github.com/USACE-RMC/WPF-Framework/actions/workflows/Integration.yml)
[![NuGet](https://img.shields.io/nuget/v/RMC.Wpf.Framework.Controls)](https://www.nuget.org/packages/RMC.Wpf.Framework.Controls/)
[![License: 0BSD](https://img.shields.io/badge/License-0BSD-blue.svg)](LICENSE)

WPF Framework is a free and open-source .NET 10.0 application framework for building desktop project management applications, developed by the U.S. Army Corps of Engineers Risk Management Center ([USACE-RMC](https://www.rmc.usace.army.mil/)). It provides a complete application shell with docking layout, project explorer, theme switching, undo/redo, and specialized controls for charting, databases, expression parsing, and directed acyclic graphs.

> [!NOTE]
> This repository is under active development. Expect ongoing bug fixes and minor enhancements as the framework is prepared for broader public use.

## Supported Frameworks

| Platform | Version |
|----------|---------|
| .NET | 10.0 |
| OS | Windows 10+ |

WPF Framework is currently distributed as source only. NuGet package publishing is planned for a future release; until then, clone the repository and reference the individual library projects directly, or build them as local NuGet packages.
WPF Framework can be consumed from source project references or packaged into NuGet bundles with `scripts/pack-wpf-framework.ps1`. The package layout follows the internal dependency map: Core, Models, Support, then Controls.

The framework depends on the [Numerics](https://github.com/USACE-RMC/Numerics) library (built separately and referenced via `HintPath`). See [Prerequisites](#prerequisites) for the expected layout.
The framework depends on [RMC.Numerics](https://github.com/USACE-RMC/Numerics) through central NuGet package management in `Directory.Packages.props`. Source builds restore the latest compatible 2.x package; NuGet bundles declare compatibility with RMC.Numerics 2.1.1 or later, below 3.0.0.

## Solution Structure

| Folder | Projects | Description |
|--------|----------|-------------|
| **Core** | FrameworkInterfaces, FrameworkUI, Themes | Core contracts, application shell, and theming engine |
| **Controls** | GenericControls, NumericControls, OxyPlotControls, DatabaseControls, ExpressionParserControls, DAGControls | Reusable WPF control libraries |
| **Core** | FrameworkInterfaces, Themes | Core contracts and theming engine |
| **Controls** | FrameworkUI, GenericControls, NumericControls, OxyPlotControls, DatabaseControls, ExpressionParserControls, DAGControls, Xceed.Wpf.AvalonDock, Xceed.Wpf.AvalonDock.Themes.VS2013 | Application shell, reusable WPF controls, and docking UI |
| **Models** | DatabaseManager, ExpressionParser, OxyPlot, OxyPlot.Wpf, OxyPlot.Wpf.Shared, DAG | Platform-agnostic model and engine libraries |
| **Support** | SoftwareUpdate, SoftwareUpdate.Updater | GitHub Releases-based auto-update system |
| **AvalonDock** | Xceed.Wpf.AvalonDock, Xceed.Wpf.AvalonDock.Themes.VS2013 | Modified VS2013-themed docking layout (vendored fork) |
| **Demos** | FrameworkUI.Demo, GenericControls.Demo, NumericControls.Demo, OxyPlotControls.Demo, DatabaseControls.Demo, ExpressionParserControls.Demo, DAG.Demo | Interactive demo applications |
| **Tests** | OxyPlot.ExampleLibrary + 13 test projects | Example chart models and xunit, MSTest, and NUnit test suites |
| **Packaging** | RMC.Wpf.Framework.Core, RMC.Wpf.Framework.Models, RMC.Wpf.Framework.Support, RMC.Wpf.Framework.Controls | NuGet bundle projects |

## Quick Start

Expand All @@ -43,6 +47,21 @@ dotnet build WPF-Framework.sln
dotnet test WPF-Framework.sln
```

### Build Packages

```bash
.\scripts\pack-wpf-framework.ps1 -Configuration Release -Version 1.0.0
```

This creates and validates the following NuGet packages in `artifacts/packages/`:

| Package | Includes | Depends on |
|---------|----------|------------|
| [`RMC.Wpf.Framework.Core`](https://www.nuget.org/packages/RMC.Wpf.Framework.Core/) | FrameworkInterfaces, Themes | None |
| [`RMC.Wpf.Framework.Models`](https://www.nuget.org/packages/RMC.Wpf.Framework.Models/) | DAG, DatabaseManager, ExpressionParser, OxyPlot libraries | ClosedXML, DocumentFormat.OpenXml, ExcelNumberFormat, FastMember, SourceGear.sqlite3, System.Data.SQLite |
| [`RMC.Wpf.Framework.Support`](https://www.nuget.org/packages/RMC.Wpf.Framework.Support/) | SoftwareUpdate and updater content files | None |
| [`RMC.Wpf.Framework.Controls`](https://www.nuget.org/packages/RMC.Wpf.Framework.Controls/) | FrameworkUI, control libraries, AvalonDock fork | Core, Models, Support, RMC.Numerics 2.x |

### Minimal Application

```csharp
Expand All @@ -67,6 +86,7 @@ Comprehensive documentation is available in the [docs/](docs/index.md) folder:

| Document | Description |
|----------|-------------|
| [Gallery](docs/gallery.md) | Screenshot guide to the framework control libraries |
| [Getting Started](docs/getting-started.md) | Step-by-step guide to building your first application |
| [Architecture](docs/architecture.md) | Solution structure, dependencies, and design patterns |
| [Themes](docs/themes.md) | Runtime theme switching with Light, Dark, and Blue themes |
Expand Down Expand Up @@ -142,7 +162,7 @@ WPF Framework powers the following USACE-RMC desktop applications:

## Related Libraries

- [Numerics](https://github.com/USACE-RMC/Numerics) — .NET library for numerical computing, statistical analysis, and Bayesian inference (required dependency for NumericControls and DatabaseControls)
- [RMC.Numerics](https://github.com/USACE-RMC/Numerics) - NuGet package for numerical computing, statistical analysis, and Bayesian inference (required dependency for NumericControls and DatabaseControls)

## Contributing

Expand Down
Loading
Loading