mattercontrol/research/02-application-controller.md

198 lines
8.4 KiB
Markdown
Raw Permalink Normal View History

2026-01-27 17:14:59 -08:00
# Application Controller
## Summary
The `ApplicationController` is the central singleton orchestrating all major application functionality in MatterControl. It manages workspaces, printers, library containers, tasks, theming, and serves as the plugin registration point for extensibility.
## Technical Description
### Singleton Architecture
`ApplicationController` uses a lazy singleton pattern accessed via `ApplicationController.Instance`. The constructor is private, ensuring only one instance exists throughout the application lifecycle. This design:
- Provides a single coordination point for all subsystems
- Enables plugins to register callbacks and hooks
- Maintains consistent state across the application
- Simplifies cross-component communication
### Workspace Management
The application uses an `ObservableCollection<PartWorkspace>` to manage open tabs:
```
PartWorkspace
├── SceneContext (ISceneContext) - 3D scene editing context
├── Printer (PrinterConfig) - Associated printer (null for design-only tabs)
├── LibraryView (ILibraryContext) - Library browsing context
├── Name - Display name for the tab
└── ContentPath - Path to source file
```
**Workspace Types:**
1. **Design Workspaces**: `Printer == null`, standalone 3D design editing
2. **Printer Workspaces**: `Printer != null`, tied to a specific printer for printing
**Persistence**: Workspace layouts are persisted to `OpenTabsPath` as JSON when:
- Tabs are added/removed (via `CollectionChanged` event)
- Application closes
- User explicitly saves
### Library System Integration
ApplicationController initializes and manages the library hierarchy:
```
Library.RootLibaryContainer
├── Computer (FileSystemContainer)
├── Local Library (SqliteLibraryContainer) - if items exist
├── Queue (FileSystemContainer)
├── Bundled Parts (BundledPartsCollectionContainer)
├── Custom Library Folders (from CustomLibraryFoldersPath)
└── History (RootHistoryContainer)
```
Content providers are registered for file types:
| Extensions | Provider |
|------------|----------|
| stl, obj, 3mf, amf, mcx | `MeshContentProvider` |
| gcode | `GCodeContentProvider` |
| png, gif, jpg, jpeg | `ImageContentProvider` |
| scad | `OpenScadContentProvider` |
### Task Management System
The `Tasks` property (`RunningTasksConfig`) provides background task execution:
```csharp
Tasks.Execute("Task Name", owner, async (progress, cancellationToken) => {
// Background work with progress reporting
progress?.Invoke(0.5, "Halfway done");
});
```
Features:
- Progress reporting with percentage and status text
- Cancellation support
- Optional pause/resume/stop actions
- Visual task display in UI via `RunningTasksWidget`
### Plugin Registration Points
ApplicationController exposes several `Func` and `Action` delegates for plugin integration:
| Property | Type | Purpose |
|----------|------|---------|
| `GetPrinterProfileAsync` | `Func<PrinterInfo, string, Task<PrinterSettings>>` | Cloud profile retrieval |
| `SyncCloudProfiles` | `Func<string, Action<double,string>, Task>` | Cloud sync execution |
| `GetPublicProfileList` | `Func<Task<OemProfileDictionary>>` | Public profile listing |
| `DownloadPublicProfileAsync` | `Func<string, Task<PrinterSettings>>` | Public profile download |
| `GuestUserActive` | `Func<bool>` | Authentication state check |
| `GetAuthPage` | `Func<AuthenticationContext, DialogPage>` | Auth dialog factory |
| `UserHasPermission` | `Func<IObject3D, bool>` | Object permission check |
| `UserHasPro` | `Func<bool>` | Pro license validation |
| `PushPrintTaskToServer` | `Func<PrintTask, Task<Dictionary<string,string>>>` | Cloud print tracking |
### Font Management
The `TypeFaceCache` dictionary manages loaded fonts with lazy loading:
1. Static fonts loaded at startup (Liberation Sans/Mono)
2. User fonts loaded from `ApplicationFontsDataPath` on demand
3. System fonts loaded from Windows Fonts folder as fallback
4. Falls back to Liberation_Sans if font not found
### Event System
Key events for application coordination:
| Event | Purpose |
|-------|---------|
| `WorkspacesChanged` | Tab added/removed/restored |
| `CloudSyncStatusChanged` | Cloud sync state changes |
| `DoneReloadingAll` | Full UI reload completed |
| `ActiveProfileModified` | Printer profile changed |
| `ReloadSettingsTriggered` | Settings panel refresh needed |
| `ShellFileOpened` | External file opened |
| `AnyPrintStarted/Canceled/Complete` | Print lifecycle |
| `ApplicationError` | Error logging |
| `ApplicationEvent` | General event logging |
### AppContext Static Class
`AppContext` provides global application state:
| Property | Type | Description |
|----------|------|-------------|
| `Platform` | `INativePlatformFeatures` | Platform-specific functionality |
| `Options` | `MatterControlOptions` | Runtime options |
| `IsLoading` | `bool` | Application loading state |
| `RootSystemWindow` | `SystemWindow` | Main window reference |
| `Theme` | `ThemeConfig` | Current theme |
| `MenuTheme` | `ThemeConfig` | Menu theme variant |
| `ThemeProviders` | `Dictionary<string, IColorTheme>` | Available themes |
### Design Rationale
**Singleton vs Dependency Injection**: The singleton pattern was chosen over DI for simplicity and because the application has a single-user, single-window model. All state is naturally global.
**Plugin Delegates vs Interfaces**: Using `Func`/`Action` delegates instead of interfaces for plugins allows:
- Optional plugin features (null = not implemented)
- Simple registration without assembly scanning
- Runtime flexibility in plugin loading
**Observable Workspaces**: Using `ObservableCollection` enables automatic UI updates when tabs change without manual event wiring in the view layer.
## Reference
### Core Classes
| Class | Location | Description |
|-------|----------|-------------|
| `ApplicationController` | [ApplicationView/ApplicationController.cs](MatterControlLib/ApplicationView/ApplicationController.cs) | Central singleton |
| `AppContext` | [ApplicationView/AppContext.cs](MatterControlLib/ApplicationView/AppContext.cs) | Global static state |
| `PartWorkspace` | [ApplicationView/PartWorkspace.cs](MatterControlLib/ApplicationView/PartWorkspace.cs) | Tab/workspace definition |
| `WorkspacesChangedEventArgs` | [ApplicationView/WorkspacesChangedEventArgs.cs](MatterControlLib/ApplicationView/WorkspacesChangedEventArgs.cs) | Workspace change event |
### Key Properties
| Property | Type | Description |
|----------|------|-------------|
| `Instance` | `ApplicationController` | Singleton accessor |
| `Workspaces` | `ObservableCollection<PartWorkspace>` | Open tabs |
| `ActivePrinters` | `IEnumerable<PrinterConfig>` | Connected printers |
| `Library` | `LibraryConfig` | Library configuration |
| `LibraryTabContext` | `ILibraryContext` | SaveAs library context |
| `Tasks` | `RunningTasksConfig` | Background task manager |
| `Thumbnails` | `ThumbnailsConfig` | Thumbnail generation |
| `EditorExtensions` | `EditorExtensionsConfig` | Editor plugin registry |
| `Theme` | `ThemeConfig` | Current theme |
| `MenuTheme` | `ThemeConfig` | Menu theme |
| `MainView` | `MainViewWidget` | Main UI widget |
| `HelpArticles` | `HelpArticle` | Help content |
| `TypeFaceCache` | `Dictionary<string, TypeFace>` | Loaded fonts |
### Key Methods
| Method | Description |
|--------|-------------|
| `OnWorkspacesChanged()` | Fire workspace change event |
| `ClosePrinter()` | Disconnect and close printer |
| `ExportLibraryItems()` | Export items to file |
| `PersistOpenTabsLayout()` | Save workspace state |
| `PersistPrintTabsContent()` | Save printer workspace content |
| `ReloadSettings()` | Refresh settings UI |
| `ShowNotification()` | Display timed notification |
| `Shutdown()` | Graceful application shutdown |
| `GetTypeFace()` | Lazy-load font by name |
| `GetWorkspaceActions()` | Build context menu actions |
| `LaunchBrowser()` | Open URL in default browser |
### Supporting Classes
| Class | Location | Description |
|-------|----------|-------------|
| `RunningTasksConfig` | [PartPreviewWindow/RunningTasksConfig.cs](MatterControlLib/PartPreviewWindow/RunningTasksConfig.cs) | Task execution |
| `LibraryConfig` | [Library/LibraryConfig.cs](MatterControlLib/Library/LibraryConfig.cs) | Library management |
| `ThumbnailsConfig` | [Library/ThumbnailsConfig.cs](MatterControlLib/Library/ThumbnailsConfig.cs) | Thumbnail generation |
| `EditorExtensionsConfig` | [DesignTools/EditorExtensionsConfig.cs](MatterControlLib/DesignTools/EditorExtensionsConfig.cs) | Editor plugins |