# MyCodeEditor.HDEUtils

Embeddable C# editor for **vvvv Gamma (HDE)** as a dockable window inside Gamma, not a separate external window.

## Project Goal

Create an embedded C# editor dock panel in Gamma with:
- Syntax highlighting
- IntelliSense and code completion
- Code diagnostics (errors/warnings)
- Support for "virtual documents" (code doesn't have to be a file, but can be mapped to a temp/virtual path)

## Architecture

### Overview

```
Gamma HDE Extension (.HDE.vl)
    ↓
WindowFactory (VL)
    ↓
DockedWpfWindow (C# ProcessNode)
    ↓
HDEForm (WinForms dock content)
    ↓
ElementHost (WinForms → WPF bridge)
    ↓
RoslynPadEditorView (WPF UserControl)
    ↓
RoslynCodeEditor (RoslynPad)
```

### Key Components

1. **HDE Extension** (`MyCodeEditor.HDE.vl`)
   - Created via `Quad > Extensions > New Extension...`
   - Assigned a hotkey (e.g., Alt+P)
   - Uses `WindowFactory` to create a dockable window
   - Command (Command) is triggered

2. **DockedWpfWindow.cs** (ProcessNode)
   - **Create phase**: public constructor `DockedWpfWindow(WindowContext context)`
     - Creates `HDEForm` (WinForms dock content)
     - Creates `RoslynPadEditorView` (WPF UIElement)
     - Sets working directory = temp
     - Sets virtual path: `inmemory://vvvv-gamma/code-editor.cs`
     - Applies theme (BackColor/ForeColor from Gamma)
   - **Update phase**: public methods `Update(...)` with overloads
     - Called every frame by WindowFactory
     - **Important**: does not overwrite text every frame (uses `applyText` gate)
     - Always returns `currentText` for synchronization

3. **RoslynPadEditorView.cs** (WPF UserControl)
   - Wrapper around `RoslynCodeEditor` from RoslynPad
   - Initialization via `InitializeAsync` (RoslynPad 4.4+)
   - Thread-safe methods: `SetText()`, `GetText()`
   - Theme integration: `ApplyHostColors(System.Drawing.Color, System.Drawing.Color)`

4. **WpfDockForm** (internal class in DockedWpfWindow)
   - Inherits from `HDEForm`
   - Contains `ElementHost` for hosting WPF content
   - Thread-safe methods: `SetTitleSafe()`, `SetWpfContentSafe()`, `SetVisibilitySafe()`

## File Structure

```
MyCodeEditor.HDEUtils/
├── DockedWpfWindow.cs          # Main ProcessNode for dockable window
├── RoslynPadEditorView.cs      # WPF UserControl with RoslynPad editor
├── WpfHost.cs                  # Deprecated file (test, not used)
├── MyCodeEditor.HDEUtils.csproj
├── NuGet.config                 # Feed configuration (nuget.org + vvvv TeamCity)
└── Properties/
    └── AssemblyInfo.cs         # [assembly: ImportAsIs] for VL
```

## Compilation

The project compiles via **Visual Studio** or **dotnet CLI**.

### Requirements

- .NET 8.0 SDK
- Visual Studio 2022 (recommended) or any IDE with .NET support
- Installed vvvv Gamma (for DLL references)

### Compilation via Visual Studio

1. Open `MyCodeEditor.HDEUtils.sln` in Visual Studio
2. Restore NuGet packages (automatically on open or via `Restore NuGet Packages`)
3. Build the project: `Build > Build Solution` (Ctrl+Shift+B)

### Compilation via dotnet CLI

```bash
cd "c:\Users\USER\Documents\vvvv\gamma-preview\Sketches\Code Editor\csharp\MyCodeEditor.HDEUtils"
dotnet restore
dotnet build
```

### Important Notes

- **Paths to DLLs from Gamma**: The `csproj` uses relative paths to DLLs from the Gamma installation. Ensure the path `Program Files\vvvv\vvvv_gamma_7.1-0136-g42c85d3d1e-win-x64\` exists on your machine, or update the `HintPath` in `csproj` to match your installation.
- **Warnings**: A `NU1701` warning about `MouseKeyHook` (transitive dependency) may appear. This is not critical and does not affect functionality.
- **Output**: The compiled DLL is located at `bin\Debug\net8.0-windows\MyCodeEditor.HDEUtils.dll`

## Dependencies

### NuGet Packages

**RoslynPad packages:**
- **RoslynPad.Editor.Windows** (4.8.0)
- **RoslynPad.Roslyn** (4.8.0)
- **RoslynPad.Roslyn.Windows** (4.8.0)

**Microsoft.CodeAnalysis packages (forced to 4.11.0 to match Gamma):**
- **Microsoft.CodeAnalysis.Features** (4.11.0)
- **Microsoft.CodeAnalysis.CSharp.Features** (4.11.0)
- **Microsoft.CodeAnalysis.Workspaces.Common** (4.11.0)
- **Microsoft.CodeAnalysis.CSharp.Workspaces** (4.11.0)
- **Microsoft.CodeAnalysis.Common** (4.11.0)
- **Microsoft.CodeAnalysis.CSharp** (4.11.0)
- **Microsoft.CodeAnalysis.Scripting.Common** (4.11.0)
- **Microsoft.CodeAnalysis.CSharp.Scripting** (4.11.0)

**VL packages:**
- **VL.Core** (2025.7.1-0136-g42c85d3d1e)
- **VL.HDE** (2025.7.1-0136-g42c85d3d1e)

### DLLs from Gamma Installation (Copy Local = False)

These DLLs must be from the Gamma installation, not from NuGet, to avoid version conflicts:

- **VL.UI.Core.dll**
- **VL.UI.Forms.dll**
- **WeifenLuo.WinFormsUI.Docking.dll** (version 1.0.0.0, expected by Gamma)
- **WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll**

**Important**: Set `Private = False` (Copy Local = False) for these references to avoid duplicating assemblies that Gamma already loads.

### NuGet Feeds

Configured in `NuGet.config`:
- `nuget.org` (standard)
- `vvvv-public-feed` (TeamCity): `https://teamcity.vvvv.org/guestAuth/app/nuget/v1/FeedService.svc/`

## Current Status

### ✅ What Works

- ✅ Docked window inside Gamma is created and displayed
- ✅ WPF content is shown through ElementHost
- ✅ RoslynPad editor is displayed (text input is visible)
- ✅ Basic theme integration (BackColor/ForeColor from Gamma)
- ✅ Thread-safe operations (SetText/GetText via Dispatcher)
- ✅ Gate mechanism `applyText` prevents text overwrite every frame

### ❌ Known Issues

#### 1. RoslynHost Initialization ⚠️ PARTIALLY RESOLVED

**Problem:**
- Gamma uses **Roslyn 4.11.0.0**
- RoslynPad 4.8.0 uses an internal API (`IIncrementalAnalyzerProvider`) that was **removed** from Roslyn between versions 4.8.0 and 4.11.0
- RoslynPad 4.12.1 requires Roslyn 4.12.0.0 (incompatible with Gamma)
- **No version of RoslynPad is compatible with Roslyn 4.11.0**

**Current Solution (fallback):**
- The editor works in **basic mode** with C# syntax highlighting via AvalonEdit
- On RoslynHost initialization error, the editor automatically switches to basic mode
- ✅ Works: code editing, syntax highlighting, line numbers
- ❌ Doesn't work: IntelliSense, diagnostics (errors/warnings), code completion

**Possible Future Improvements:**
1. Wait for Gamma update to Roslyn 4.12.0+ (then RoslynPad 4.12.1 will work)
2. Use Monaco Editor via WebView2 (VS Code editor, with full IntelliSense)
3. Contact the vvvv team for recommendations

#### 2. Color Type Conflict

**Resolved**: Using fully qualified names `System.Drawing.Color` instead of `Color` (due to global `Using Stride.Core.Mathematics`).

## Usage in Gamma

### Creating HDE Extension

1. In Gamma: `Quad > Extensions > New Extension...`
2. Create a file with the `.HDE.vl` suffix (e.g., `MyCodeEditor.HDE.vl`)
3. Assign a hotkey (e.g., Alt+P)

### Patch in .HDE.vl

```vl
// Create region (white pins)
WindowFactory.Create(WindowContext) -> DockedWpfWindow

// Update region (called every frame)
Channel<bool> Show (toggle state)
Command (pulse) -> Toggle(Show) -> Show

DockedWpfWindow.Update(
    Show: Show,
    Title: "Code Editor",
    ApplyText: ApplyText,  // Gate: true only when text needs to be loaded
    Text: Text,            // Incoming text (applied only if ApplyText=true)
    BringToFront: false,
    CurrentText: CurrentText  // Always returns current text from editor
)
```

### Important Points

1. **Create is called once** per process node. `WindowContext` is passed from `WindowFactory.Create()`.

2. **Update is called every frame**. Therefore:
   - Don't pass `ApplyText=true` every frame, otherwise text will be overwritten
   - Use `Channel<bool>` for persistent toggling of `Show`
   - Always read `CurrentText` to synchronize with your data model

3. **Virtual Documents**: 
   - Path is set via `SetVirtualDocumentPath("inmemory://vvvv-gamma/code-editor.cs")`
   - Can map different objects to different virtual paths
   - RoslynPad uses this path for diagnostics and IntelliSense

## Next Steps

### Current Status

**Editor works in basic mode:**
- ✅ Code editing
- ✅ C# syntax highlighting (via AvalonEdit)  
- ✅ Line numbers
- ❌ IntelliSense (requires compatible Roslyn version)
- ❌ Diagnostics (errors/warnings)

### Priority 1: IntelliSense Improvement

**Options:**
1. **Wait for Gamma update** to Roslyn 4.12.0+ → then RoslynPad 4.12.1 will work
2. **Monaco Editor via WebView2** → full IntelliSense, but requires browser embedding
3. **OmniSharp Language Server** → alternative approach to IntelliSense

### Priority 2: Testing in Gamma

1. ⏳ Test IntelliSense (code completion)
2. ⏳ Test diagnostics (errors/warnings underlining)
3. ⏳ Test classification (syntax highlighting)
4. ⏳ Improve theme integration (scrollbars, margins via WPF resources/brushes)

### Priority 3: Virtual Documents and Events

1. ⏳ Implement object mapping to virtual paths (stable path per object)
2. ⏳ Implement event stream from editor to VL:
   - `TextChanged` → observable/event
   - Without overwrite every frame
   - Synchronization only on explicit `ApplyText=true`

## Technical Details

### ProcessNode Signatures

VL sometimes ignores optional args in generated call sites. Therefore, **overloads** are needed for `WindowFactory`:

```csharp
// Minimal (show only)
public IWindow Update(bool show)

// With currentText
public IWindow Update(bool show, out string currentText)

// Full
public IWindow Update(
    bool show,
    string? title,
    bool applyText,
    string? text,
    bool bringToFront,
    out string currentText)
```

### Thread Safety

All UI operations must be thread-safe:
- `SetText()` / `GetText()` use `Dispatcher.Invoke()` if needed
- `SetTitleSafe()`, `SetWpfContentSafe()`, `SetVisibilitySafe()` check `InvokeRequired`

### RoslynPad Initialization

RoslynPad 4.4+ uses `InitializeAsync()` instead of the deprecated `Initialize()`. Initialization occurs in the `Loaded` event of the WPF UserControl for lifetime safety.

### Theme

Gamma sets `BackColor`/`ForeColor` for WinForms. These colors are applied to WPF via:
- `System.Windows.Media.Color.FromArgb()`
- `SolidColorBrush` for editor `Background`/`Foreground`
- Subscription to `BackColorChanged`/`ForeColorChanged` for synchronization

## License

Project for use with vvvv Gamma. Dependencies follow the licenses of their respective packages (RoslynPad, VL.*).
