177 lines
12 KiB
Markdown
177 lines
12 KiB
Markdown
---
|
||
source_files:
|
||
- DataPRO/DataPRO/Controls/TestObject/IEditObjectSensorsControlPage.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/TableOptionsTable.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/ImportObjectImport.xaml.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/ImportObjectOptions.xaml.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/EditObjectInfoControl.xaml.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/ImportObjectPreview.xaml.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/SensorLockAndContend.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/EditObjectHardwareControl.xaml.cs
|
||
- DataPRO/DataPRO/Controls/TestObject/ExportGroup.xaml.cs
|
||
generated_at: "2026-04-16T04:17:01.479504+00:00"
|
||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
schema_version: 1
|
||
sha256: "d08bce9ece7691a5"
|
||
---
|
||
|
||
# TestObject
|
||
|
||
**Documentation Page: Test Object Edit Control Module**
|
||
|
||
---
|
||
|
||
### 1. Purpose
|
||
This module provides UI controls and supporting logic for editing *test objects* (e.g., test setups, groups) in the DataPRO application. It enables users to configure sensors, hardware, import/export settings, and validate object state before saving. The controls implement the `IPageContent` interface to integrate with the application’s page navigation and permission system, and they coordinate with backend services (e.g., locking, hardware/channel management, import/export pipelines) via view models and domain interfaces. The module is part of the `DataPROWin7.Controls.TestObject` namespace and serves as the primary UI layer for test object editing workflows.
|
||
|
||
---
|
||
|
||
### 2. Public Interface
|
||
|
||
#### Interfaces
|
||
- **`IEditObjectSensorsControlPage`**
|
||
- `void SetOnlineSensors(DTS.SensorDB.SensorData[] sensors)`
|
||
Sets the list of online sensors to display or process in the sensors control page. Used to populate sensor selection UI.
|
||
|
||
#### Classes
|
||
- **`TableOptionsTable`**
|
||
- Inherits from `GenericTable2`.
|
||
- `enum TableColumns { ColumnName, ColumnHeader, Visible, DisplayOrder, Width, UserData }`
|
||
- Constructor: `TableOptionsTable(ContentControl container, DataPROPage page)`
|
||
Initializes a data grid with columns for table configuration (e.g., visibility, order, width).
|
||
- Overrides `CreateColumns(string resourcePrefix, Type enumType)`
|
||
Dynamically creates grid columns based on `TableColumns` enum values. Special handling for `Visible`, `DisplayOrder`, and `Width` (numeric/checkbox columns); `UserData` is skipped.
|
||
|
||
- **`ImportObjectImport`**
|
||
- `IGroupImportImportView ImportView { get; set; }`
|
||
Gets/sets the view model for import configuration. Setting it assigns the view to `Content`.
|
||
- `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)`
|
||
Always returns `true`; no validation logic implemented (placeholder).
|
||
- `void OnSetActive()`
|
||
No-op stub.
|
||
|
||
- **`ImportObjectOptions`**
|
||
- `IGroupImportOptionsView OptionsView { get; set; }`
|
||
Gets/sets the view model for import options. Setting it assigns the view to `Content`.
|
||
- `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)`
|
||
Delegates validation to `OptionsView.Validate(...)`. Aggregates errors/warnings into output parameters. If errors exist, reports them via `page.ReportErrors(...)` using the active page from `MainWindow`.
|
||
- `void OnSetActive()`
|
||
No-op stub.
|
||
|
||
- **`ImportObjectPreview`**
|
||
- `IGroupImportPreviewView PreviewView { get; set; }`
|
||
Gets/sets the view model for import preview. Setting it assigns the view to `Content`.
|
||
- `bool DontValidate { get; set; }`
|
||
Bypasses validation when `true`.
|
||
- `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)`
|
||
Calls `PreviewView.Validate(isAdmin, out errors, out warnings)`. If errors exist, reports them and returns `false`. If warnings exist, displays them via `ThreadPool.QueueUserWorkItem(DoWarning, ...)` and returns `false`.
|
||
- `static void DoWarning(object o)`
|
||
Shows a modal message box with warnings (using `App.DoMessageBox`) and OK/Cancel buttons.
|
||
- `void OnSetActive()`
|
||
No-op stub.
|
||
|
||
- **`SensorLockAndContend`**
|
||
- Constructor: `SensorLockAndContend(DataPROPage page)`
|
||
- `bool HasLockedSensors { get; }`
|
||
Returns `true` if any sensors are currently locked.
|
||
- `LockRecord[] GetLockRecords()`
|
||
Returns all currently locked sensor records.
|
||
- `void LockSensors(SensorData[] sensorsToLock)`
|
||
Attempts to lock each sensor. Handles lock contention:
|
||
- If lock is stale (timeout exceeded) or held by same user/machine, steals it.
|
||
- Otherwise, records as contentious and calls `ContendLocks(...)`.
|
||
- `void FreeSensors()`
|
||
Frees all locked sensors and clears contentious locks. Clears `_sensorsContentiousLocks` unconditionally.
|
||
- `private void ContendLocks(User user)`
|
||
For non-admin users: reports errors via `_page.ReportErrors(...)`. For admins: prompts to steal locks via `StealLocks()`.
|
||
- `private void StealLocks()`
|
||
Frees and re-locks contentious sensors.
|
||
|
||
- **`EditObjectHardwareControl`**
|
||
- Constructor: `EditObjectHardwareControl(DataPROPage page)`
|
||
- `string HardwareInfo { get; }`
|
||
Returns formatted string (e.g., `"X channels required. Y channels included."`) based on `ChannelsRequired` and hardware channel counts.
|
||
- `int ChannelsRequired { get; set; }`
|
||
Tracks required channel count (updated via `OnGroupChannelsChanged`).
|
||
- `void AddHardware(DASHardware hardware, IGroup group, Dictionary<string, DASHardware> lookup, DASHardware[] allHardware)`
|
||
Adds hardware to group’s `IncludedHardware` list. Special handling for TSRAIR (creates embedded channels) and SLICETC.
|
||
- `void OnSetActive()`
|
||
Initializes hardware view model, subscribes to events, sets compact view mode, and populates hardware list.
|
||
- `void UnSet(Action OnComplete = null)`
|
||
Unsubscribes from events and unsets hardware view model.
|
||
- `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)`
|
||
Delegates to `ValidateTestObjectHardware(...)`, which currently always returns `true`.
|
||
- `private void OnIncludedChanged(HardwareListHardwareIncludedEventArgs args)`
|
||
Adds/removes hardware from group when included state changes. Handles pseudo-rack and TSRAIR module dependencies.
|
||
- `private void OnGroupChannelsChanged(GroupChannelsChangedEventArgs obj)`
|
||
Updates `ChannelsRequired` when group channel count changes.
|
||
|
||
- **`ExportGroup`**
|
||
- Constructor: `ExportGroup(DataPROPage page)`
|
||
- `string ExportFile { get; set; }`
|
||
Target export file path.
|
||
- `string TCFFile { get; set; }`
|
||
TCF file path (unused in source).
|
||
- `bool UseFirstUseDate { get; set; } = true`
|
||
Flag for sensor first-use date inclusion (UI visibility controlled by `SerializedSettings.UseSensorFirstUseDate`).
|
||
- `bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)`
|
||
Checks `ExportFile` is non-empty and at least one group is selected. Marks invalid controls via `PageMainContentControl.MarkInvalid(...)`.
|
||
- `void OnSetActive()`
|
||
Populates `_dt` (DataTable) with groups from `IGroupListViewModel`, sorted by `LastModified`.
|
||
- `void Export()`
|
||
Starts export asynchronously via `Task.Run(ExportGroupFunc)`. If file exists, prompts for overwrite.
|
||
- `private void ExportGroupFunc()`
|
||
Calls `ExportTestSetup.ExportToFile(...)` with selected groups. Handles errors and updates status via delegates.
|
||
- `private void FileOverwriteWarning(object o)`
|
||
Shows overwrite warning modal; if OK, invokes `Export()` on dispatcher thread.
|
||
|
||
---
|
||
|
||
### 3. Invariants
|
||
- **Permissions**: All `IPageContent` implementations enforce permission checks via `SetPermissions(...)`. `IsEnabled` is set only if `actualPermission >= requiredPermission`.
|
||
- **Validation**:
|
||
- `Validate(...)` methods must populate `errors`/`warnings` lists; returning `false` indicates failure.
|
||
- `ImportObjectOptions.Validate` and `ImportObjectPreview.Validate` report errors via `page.ReportErrors(...)` on failure.
|
||
- `ExportGroup.Validate` requires a non-empty `ExportFile` and at least one selected group.
|
||
- **Locking**:
|
||
- `SensorLockAndContend.LockSensors` may steal locks only for admins (after user confirmation) or stale/self-held locks.
|
||
- `FreeSensors` clears `_sensorsContentiousLocks` unconditionally before freeing locks.
|
||
- **Hardware/Channel Consistency**:
|
||
- `EditObjectHardwareControl.OnIncludedChanged` ensures hardware inclusion/exclusion updates `group.IncludedHardware` and channels.
|
||
- TSRAIR and SLICETC hardware trigger special channel creation/removal logic.
|
||
- **Event Subscription**:
|
||
- `EditObjectHardwareControl` subscribes to `GroupChannelsChangedEvent`, `HardwareListHardwareIncludedEvent`, and `HardwareListShowCompactEvent` in `OnSetActive`.
|
||
- Unsubscribes in `UnSet` to prevent leaks.
|
||
|
||
---
|
||
|
||
### 4. Dependencies
|
||
**Imports/References (from source):**
|
||
- `DTS.*` namespaces:
|
||
- `DTS.SensorDB` (e.g., `SensorData`, `SensorsCollection`)
|
||
- `DTS.Slice.Users` (e.g., `User`, `UserPermissionLevels`)
|
||
- `DTS.Common.*` (e.g., `IGroup`, `IGroupImportImportView`, `LockManager`, `IEventAggregator`, `IUnityContainer`)
|
||
- `Prism.*` (e.g., `IEventAggregator`, `ContainerLocator`)
|
||
- `System.*` (e.g., `Data`, `Windows.Controls`, `Threading`)
|
||
- `DataPROWin7.*` (e.g., `DataModel`, `Common`, `Controls`)
|
||
- `C1.WPF.DataGrid` (for `ExportGroup` grid columns)
|
||
- `App`, `MainWindow`, `HomePage`, `DataPROPage`, `EditObjectPage`, `GenericTable2` (internal types).
|
||
|
||
**Depended on by:**
|
||
- `EditObjectPage` (inferred from `EditObjectHardwareControl`, `EditObjectInfoControl`, `ImportObject*`, `ExportGroup` constructors).
|
||
- `DataPROPage` and `App` (via `DoMessageBox`, `CurrentUser`, `DoWarning`).
|
||
|
||
---
|
||
|
||
### 5. Gotchas
|
||
- **`ExportGroup.Export` does not block**: It starts export in a background `Task.Run`, but `FileOverwriteWarning` uses `ManualResetEvent.WaitOne()` to block the dispatcher thread during overwrite confirmation. This risks deadlocks if not handled carefully.
|
||
- **`EditObjectHardwareControl.ValidateTestObjectHardware` is a stub**: Always returns `true`; no actual hardware/channel validation occurs.
|
||
- **`ImportObjectImport.Validate` is a stub**: Always returns `true`; no validation logic implemented.
|
||
- **`SensorLockAndContend.FreeSensors` clears `_sensorsContentiousLocks` before freeing**: If `FreeSensors` is called mid-contention, the contentious records are lost before resolution.
|
||
- **`EditObjectHardwareControl.OnSetActive` sets column widths to `0`**: Hardcoded column widths (`TestSampleRateColumnWidth = 0`, etc.) hide columns; may conflict with tile-specific settings (e.g., "Test Setups tile" comment).
|
||
- **`EditObjectInfoControl.TextBoxSourceUpdated` publishes `PageModifiedEvent` on data binding updates**: This may fire frequently (e.g., on every keystroke), potentially causing performance issues or race conditions.
|
||
- **`ImportObjectPreview.Validate` always returns `false` if warnings exist**: Even if `bValid` is `true`, warnings trigger a modal and return `false`. This may block progression despite valid data.
|
||
- **`ExportGroup.Export` uses `ExportTestSetup.PossibleStatus`**: Status enum is defined in `ExportTestSetup` (not in this module), implying tight coupling.
|
||
- **`TableOptionsTable` skips `TableColumns.UserData` in `CreateColumns`**: Intentional, but may confuse developers expecting a column.
|
||
- **`EditObjectHardwareControl` uses `DASHardware.GetChildrenDAS` and `GetEmbeddedModules`**: Logic for pseudo-rack/module dependencies is embedded in `AddHardware`/`RemoveFromChannels`; not centralized.
|
||
- **`SensorLockAndContend` uses `Properties.Settings.Default.StrandedLockTimeoutMinutes`**: Hardcoded timeout setting; no runtime configuration visible in source. |