Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common/Themes.md
2026-04-17 14:55:32 -04:00

98 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common/Themes/CommonStyles.xaml.cs
- Common/DTS.Common/Themes/BrushesAndColors.cs
generated_at: "2026-04-16T02:56:39.284443+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f6ea4f0f3bc31d60"
---
# Documentation: `DTS.Common` Theme Utilities
## 1. Purpose
This module provides shared WPF styling infrastructure for the DTS application suite, specifically offering two key capabilities: (1) centralized event handling for tooltip requests via `ToolTipEventHandler`, which routes help text requests through Prisms event aggregator, and (2) a static cache of pre-frozen WPF `Brush` and `Color` resources to avoid repeated resource lookups and improve rendering performance. It serves as a shared dependency for consistent UI theming across modules, decoupling resource consumption from XAML resource keys and reducing boilerplate in UI controls.
## 2. Public Interface
### `CommonStyles` (partial class)
- **`void ToolTipEventHandler(object sender, System.Windows.Controls.ToolTipEventArgs e)`**
Handles tooltip requests by marking the event as handled and publishing a `HelpTextEvent` (via `IEventAggregator`) with the original `sender` and `ToolTipEventArgs`. This enables centralized help-text provisioning for tooltip triggers.
### `BrushesAndColors` (abstract class)
All members are **static properties** returning cached `Brush` or `Color` instances. Each property corresponds to a specific resource key defined in external XAML (`brushes.xaml` or application resources). Properties are lazily initialized on first access.
#### Brush Properties (selected examples — full list below):
- **`Brush_ApplicationTileExport`** → `SolidColorBrush`
- **`Brush__ApplicationTileCollectData`** → `SolidColorBrush` *(note double underscore in name)*
- **`Brush_ApplicationStatus_Failed`**, **`Brush_ApplicationStatus_TSRAIRGo_Failed`** → `SolidColorBrush`
- **`Brush_Dimmed_Text`** → `SolidColorBrush`
- **`Brush_Application_Idle`**, **`Brush_ApplicationStatus_Idle`** → `SolidColorBrush` *(duplicate keys?)*
- **`Brush_ApplicationStatus_Busy`**, **`Brush_ApplicationStatus_TSRAIRGo_Busy`** → `SolidColorBrush`
- **`Brush_Run_SensorIdNotFound`**, **`Brush_Run_SensorIdOutOfPlace`** → `SolidColorBrush`
- **`Brush_Table_RowBackground`**, **`Brush_Table_AlternatingRowBackground`** → `SolidColorBrush`
- **`Brush_FlatControlPressedBackground`**, **`Brush_FlatControlPressedForeground`** → `Brush`
- **`Brush_Transparent`** → `Brush` (created internally as `new SolidColorBrush(Colors.Transparent)`)
- **`Brush_NoError`**, **`Brush_Error`**, **`Brush_Warning`**, **`Brush_Attention`** → `Brush`/`SolidColorBrush`
- **`Brush_FlatControlDisabledForeground`**, **`Brush_FlatControlDisabledBackground`** → `Brush`
- **`Brush_ApplicationStatus_Waiting`**, **`Brush_ApplicationStatus_Failed_ActionBackground`**, etc.
- **`Brush_Realtime_OSC_SELECTED`**, **`Brush_Realtime_OSC_UNSELECTED`**, **`Brush_Realtime_METER_SELECTED`**, **`Brush_Realtime_METER_UNSELECTED`** → `Brush`
- **`Brush_SensorIdFound`**, **`Brush_ArmSystemForeground`**, **`Brush_ApplicationTilePrepare`**, **`Brush_ApplicationTileSetup`** → `SolidColorBrush`
- **`BrushApplicationStatusPowerRed`**, **`BrushApplicationStatusPowerYellow`**, **`BrushApplicationStatusPowerGreen`**, **`BrushApplicationStatusPowerClear`** → `SolidColorBrush`
- **`BrushFlatControlDarkForeground`**, **`BrushButtonBorderForeground`** → `SolidColorBrush`
#### Color Properties (read-only, no caching):
- **`Color_ActionBackground`**, **`Color_ApplicationTileCollectData`**, **`Color_ItemBackground`**, **`Color_ActionForeground`**, **`Color_ItemForeground`**, **`Color_ApplicationTileSetup`**, **`Color_ApplicationTilePrepare`**, **`Color_ApplicationTileCalibration`**, **`Color_ApplicationTileExport`**, **`Color_ApplicationTileAdmin`**
`Color` (returned directly from `Application.Current.FindResource(...)` on each access; **not cached**)
> **Note**: The class is `abstract`, but no abstract members exist — likely a design artifact to prevent instantiation.
## 3. Invariants
- **Resource keys must exist at runtime**: All `FindResource` calls assume the resource key (e.g., `"Brush_ApplicationTileExport"`) is defined in `Application.Current.Resources` or in the merged dictionary `/DTS.Common;component/Themes/brushes.xaml`. Failure to define a key results in a `ResourceReferenceKeyNotFoundException`.
- **Brushes are frozen**: All `Brush`/`SolidColorBrush` instances are frozen (`Freeze()`) after retrieval to ensure thread-safety and immutability. Attempting to modify them will throw `InvalidOperationException`.
- **Lazy initialization with null-checks**: Each brush property uses a null-check pattern to ensure initialization occurs only once per app domain. However, some properties (e.g., `Brush_Warning`, `Brush_FlatControlDisabledForeground`) have inconsistent null-checking logic (see *Gotchas*).
- **No theme-switching support**: As noted in the class comment, the static caching means brushes may become stale if themes change at runtime (though the comment states themes are not currently used).
- **`Brush_Transparent` is internally constructed**: Unlike others, this brush is created via `new SolidColorBrush(Colors.Transparent)` rather than from a resource key.
## 4. Dependencies
### Dependencies *of* this module:
- **`DTS.Common.Events`** → Provides `HelpTextEvent` and `HelpTextEventArg`.
- **`Prism.Ioc`** and **`Prism.Events`** → Used for `ContainerLocator` and `IEventAggregator`.
- **`System.Windows`**, **`System.Windows.Media`** → WPF base types (`Brush`, `SolidColorBrush`, `Color`, `Application`, `ResourceDictionary`).
### Dependencies *on* this module:
- Any module requiring consistent UI styling (e.g., `DTS.DataPro`, UI projects) likely references `DTS.Common` and consumes `BrushesAndColors` properties directly.
- The `ToolTipEventHandler` is presumably wired to tooltip events in XAML (e.g., `ToolTipOpening="CommonStyles.ToolTipEventHandler"`), implying UI controls depend on this handler for help-text integration.
## 5. Gotchas
- **Inconsistent null-checking in `Brush_Warning`**:
The property `Brush_Warning` incorrectly assigns to `_brushError` instead of `_brushWarning` in its getter:
```csharp
_brushError = (SolidColorBrush)_resourceDictionary["Brush_Warning"]; // ❌ Should be _brushWarning
```
This causes `_brushWarning` to remain `null` indefinitely, leading to a `NullReferenceException` on first access.
- **Duplicate resource keys**:
`Brush_Application_Idle` and `Brush_ApplicationStatus_Idle` both resolve to `"Brush_ApplicationStatus_Idle"`. This redundancy suggests a naming inconsistency or refactoring artifact.
- **`Brush_FlatControlDisabledForeground` returns `null` silently**:
If the resource `"Brush_FlatControlDisabledForeground"` is missing, the property returns `null` (after `Freeze()` on `null` is a no-op). This may cause subtle rendering issues.
- **`BrushesAndColors` is `abstract` but not sealed**:
While no abstract members exist, the class could be `static` instead of `abstract` to enforce non-instantiability and prevent accidental subclassing.
- **Resource dictionary path is hardcoded**:
The `brushes.xaml` path (`/DTS.Common;component/Themes/brushes.xaml`) is embedded as a string. A typo or path change would break resource loading.
- **No thread-safety for first-time initialization**:
Although `Freeze()` is called, the lazy initialization (null-check + assignment) is not thread-safe. Concurrent first access could result in multiple instantiations (though freezing mitigates side effects).
- **Missing documentation for properties**:
No XML comments describe what each brush/color represents semantically (e.g., `Brush_ApplicationStatus_TSRAIRGo_Failed` vs `Brush_ApplicationStatus_Failed`), making maintenance difficult.
- **`Brush_ApplicationTileCollectData` has double underscore**:
`Brush__ApplicationTileCollectData` (two underscores) likely stems from a copy-paste or refactoring error (`Brush_ApplicationTileCollectData` would be consistent with others). This is a potential source of typos in consuming code.