OpenControls is a lightweight, renderer-agnostic UI logic library. It keeps control behavior separate from rendering so host apps (MonoGame, tooling, or custom engines) can share the same UI logic.
README.MD: this overview.Quickstart.MD: getting started guide.API.MD: core types and controls reference.Samples.MD: small usage examples.tools/parity/README.MD: parity baseline, status board, and tracking notes.tools/parity/WIDGET_DEMO_COVERAGE.MD: exhaustive widget and option coverage checklist forOpenControls.Examples.scripts/verify-phase0.sh: lightweight Phase 0 parity verification hook.LICENSE.MD: MIT license.
- Keep UI behavior and input handling independent from rendering APIs.
- Use a retained element tree so controls manage their own state.
- Provide a small, predictable control set for editor and runtime use.
- Keep layout explicit (manual bounds) so host apps stay in control.
OpenControls.Examples: shared examples UI library (renderer-agnostic).OpenControls.MonoGame: MonoGame DesktopGL renderer adapter library.OpenControls.MonoGame.Examples: runnable MonoGame host for the shared examples UI.OpenControls.SdlNet: SDL2-CS renderer adapter library.OpenControls.SilkNet: Silk.NET renderer adapter library (OpenGL 3.3 core profile).OpenControls.SilkNet.Examples: runnable Silk.NET host for the shared examples UI. This is the primary parity/reference host.OpenControls.OpenGL: OpenGL renderer adapter library (OpenTK).OpenControls.OpenGL.Examples: runnable OpenGL host for the shared examples UI.OpenControls.Tests: regression tests for editor-blocking shared behavior.OpenControls.SdlNet.Examples: SDL2-CS renderer example that mirrors the OpenControls.Examples UI (requires SDL2 native runtime; on Windows placeSDL2.dllon PATH or beside the executable).
- Build the core library:
dotnet build OpenControls/OpenControls.csproj - Run the MonoGame examples:
dotnet run --project OpenControls.MonoGame.Examples/OpenControls.MonoGame.Examples.csproj - Run the OpenGL examples:
dotnet run --project OpenControls.OpenGL.Examples/OpenControls.OpenGL.Examples.csproj - Run the Silk.NET examples:
dotnet run --project OpenControls.SilkNet.Examples/OpenControls.SilkNet.Examples.csproj - Run the shared regression tests:
dotnet test OpenControls.Tests/OpenControls.Tests.csproj - Run the current Phase 0 verification hook:
bash scripts/verify-phase0.sh
The Widgets window in OpenControls.Examples mirrors the structure of the reference demo source. Every demo marker was replaced with a working OpenControls demo panel so the tree now maps to the same sections (Help & Configuration, Menu, Basic widgets, Text, Sliders, Drag & Drop, Tables, Layout, Inputs & Focus, Tools, Examples, etc.).
The Widgets layout now also docks a dedicated Widget Gallery window beside the original Widgets tree. That gallery is where the option-level gap-filling lives for controls that were previously easy to miss, including UiArrowButton, UiSeparatorText, UiBullet, UiInputDouble, UiNumericField, UiNumericVector, UiSliderVector, UiPicker, empty-state list/combo/list-view paths, a dedicated Tables 2.0 demo (resize/reorder/hide/scroll/custom headers/rich cells), explicit UiScrollPanel, weighted/spanning UiGrid, retained layout alignment variants, tab-strip overflow/ellipsis coverage for both UiTabBar and UiDockHost, dock-tab overflow menus and bulk-close commands, a dedicated Milestone 10 selection/tree section for shared scopes, dual list boxes, anchor persistence, and UiTreeView open-state helpers, plus a dedicated Milestone 12 overlay section for command IDs, shortcut dispatch, keyboard menu navigation, attached context helpers, delayed tooltips, and nested popup dismissal.
The Clipping window is now the large-data proof surface for Milestone 9. It still includes the original clipped/resizable panel demo, and now also shows a 4,000-row UiListBox, a 6,000-row multi-select list, a 2,500-row UiTable, and an 8,040-row UiTreeView, all driven by the shared UiClipper / UiClipRange fixed-height virtualization layer with live visible-range status readouts.
Exhaustive demo coverage is now a tracked requirement, not an informal goal:
tools/parity/WIDGET_DEMO_COVERAGE.MDis the canonical checklist for which widgets, options, modes, and interaction paths are visibly demonstrated inOpenControls.Examples.- "Implemented but not shown" does not count as demo-complete.
- New public widgets or meaningful widget options should update the matrix in the same change that introduces them.
Parity deviations (documented and intentional):
- Menu shortcut routing is now real, but it is opt-in per menu through
UiMenuBar.EnableShortcutDispatchso multiple menu bars do not all claim the same shortcuts by default. - Dock and tab overflow policy:
UiTabBarandUiDockHostnow support overflow arrows; both can ellipsize long titles, andUiDockHostalso exposes an overflow menu plus right-click bulk-close commands (Close Others,Close Tabs To The Right,Close All) for editor-style tab strips. - Drag/slider polish tail: Milestone 11 landed the first-pass flag depth (
AlwaysClamp,NoInput,NoRoundToFormat,WrapAround) plus direct numeric input on Ctrl/Cmd+click or double-click. Optional follow-on polish like hue-wheel color picking and multi-component color markers remains deferred. - Multiline editor depth:
UiTextEditornow shares the same editing core asUiTextField, including selection, clipboard, undo/redo, word/page/home/end navigation, composition/preedit rendering, richer text-input requests, and real example coverage. Deferred follow-on work is now editor polish depth such as wrapping, tokenizer expansion, and deeper host-native IME integration across every backend. - WantCapture overrides:
UiContextnow exposes actualWantCaptureMouse,WantCaptureKeyboard, andWantTextInputoutputs, but manual override toggles are not part of the core API. - Image demos:
UiImageandUiImageButtonintentionally rely on the stabilized image-adapter contract (IUiImageSource/ draw callbacks), so hosts without texture bindings will show placeholders instead of pretending there is a first-class texture API today.
Current roadmap priority after the latest backend/editor-readiness re-audit:
- Milestone 13 is now complete for the shipped first-pass backend/editor-readiness target.
- The next major milestone is Milestone 14: tooling, style-editor, and examples cleanup.
- Remaining follow-on caveats are now mostly deeper bidi/RTL/layout polish beyond the shipped first-pass HarfBuzz shaping path, host-specific IME polish beyond the current SDL reference path plus the Silk bridge hooks, and general demo/tooling cleanup rather than per-pixel rendering or ultra-thin persistence fundamentals.
Phase 0 parity tracking now lives in checked-in markdown files:
tools/parity/README.MD: entry point for parity tracking.tools/parity/BASELINE.MD: frozen reference target, scope buckets, and verification notes.tools/parity/STATUS.MD: current status board that maps major parity areas to roadmap milestones.tools/parity/WIDGET_DEMO_COVERAGE.MD: exhaustive example-app coverage matrix for public widgets and options.PARITY_EXECUTION_PLAN.MD: execution roadmap and milestone checklists.
Current Phase 0 workflow:
- Review
tools/parity/BASELINE.MDbefore changing what "parity" means. - Update
tools/parity/STATUS.MDwhen priorities or milestone ordering change. - Update
tools/parity/WIDGET_DEMO_COVERAGE.MDwhenever widget surface area, example coverage, or intentional omissions change. - Refresh
README.MDwhenever a milestone lands, parity caveats change, or the recommended next milestone changes. - If no milestone has landed recently, do a quick README truthfulness pass before starting the next major parity phase so the top-level docs do not drift.
- Run
bash scripts/verify-phase0.shto verify the baseline files exist and the core/shared-examples projects still build. - Use
PARITY_EXECUTION_PLAN.MDas the working implementation roadmap.
Documentation cadence:
- Treat the top-level
README.MDas the public truth source for current parity, reference host guidance, and major caveats. - Update
README.MD,tools/parity/STATUS.MD,tools/parity/WIDGET_DEMO_COVERAGE.MD, and any affected API/quickstart docs in the same pass when milestone status changes or demo coverage meaningfully changes. - Do not let the roadmap become more current than the README for shipped behavior.
Historical note:
- Earlier README text referenced extracted
widgets/sources, demo marker artifacts, and PowerShell parity scripts. - Those assets and scripts are not checked into this repo snapshot, so Phase 0 replaces them with a truthful baseline and status board.
| Project | Type | Status | Notes |
|---|---|---|---|
OpenControls |
Core UI library | Active | Renderer-agnostic UI logic. |
OpenControls.Examples |
Shared UI | Active | Shared examples UI used by hosts. |
OpenControls.MonoGame |
Renderer adapter | Active | MonoGame DesktopGL adapter. |
OpenControls.MonoGame.Examples |
Host app | Active | MonoGame examples host. |
OpenControls.SdlNet |
Renderer adapter | Active | SDL2-CS adapter. |
OpenControls.SdlNet.Examples |
Host app | Active | Requires SDL2.dll at runtime. |
OpenControls.SilkNet |
Renderer adapter | Active | Silk.NET OpenGL 3.3 core-profile adapter. |
OpenControls.SilkNet.Examples |
Host app | Active | Silk.NET windowing/input host. |
OpenControls.OpenGL |
Renderer adapter | Active | OpenTK compatibility-profile adapter. |
OpenControls.OpenGL.Examples |
Host app | Active | OpenTK OpenGL host. |
OpenControls.Tests |
Test project | Active | Regression coverage for shared editor-blocking primitives. |
- Core:
UiPanel,UiGroup,UiLabel,UiTextBlock,UiTextLink,UiBullet,UiBulletText,UiButton,UiArrowButton,UiSeparator,UiSeparatorText,UiSpacer,UiDisabledGroup. - Inputs:
UiCheckbox,UiRadioButton,UiTextField,UiTextEditor,UiInputFloat/Int/Double,UiInputFloat2/3/4,UiInputInt2/3/4,UiNumericField,UiNumericVector,UiSlider,UiSliderFloat2/3/4,UiSliderInt2/3/4,UiSliderVector,UiVSlider,UiDragFloat,UiDragInt,UiDragFloat2/3/4,UiDragInt2/3/4,UiDragFloatRange,UiDragIntRange. - Lists and tables:
UiListBox,UiSelectable,UiComboBox,UiTable,UiTreeView. - Data display:
UiProgressBar(horizontal/vertical, segmented, radial),UiPlotPanel,UiWaveform,UiColorEdit,UiColorPicker,UiColorButton,UiImage,UiImageButton. - Layout:
UiStack,UiWrapPanel,UiGrid,UiSplitter,UiScrollPanel,UiCanvas,UiNodeGraph,UiNodeControl,UiWindow,UiDockHost,UiDockWorkspace. - Interaction:
UiTabBar,UiTabItem,UiTabItemButton,UiDragDropSource,UiDragDropTarget. - Overlays:
UiMenuBar,UiTreeNode,UiCollapsingHeader,UiTooltip,UiTooltipRegion,UiPopup,UiModal,UiModalHost.
OpenControls is renderer-agnostic; hosts provide an IUiRenderer implementation.
Current adapters:
- MonoGame DesktopGL (OpenControls.MonoGame).
- SDL2-CS (OpenControls.SdlNet).
- Silk.NET OpenGL 3.3 core profile (OpenControls.SilkNet).
- OpenGL (OpenControls.OpenGL).
Planned expansion:
- OpenGL or other native renderers.
- Headless test harnesses.
- Core element tree, focus management, and basic controls are implemented.
UiInputStatenow supports left/right/middle mouse buttons, Alt/Super modifiers, named keys, and per-key down/pressed/released state.UiContextnow exposesHovered,PointerCaptureTarget,WantCaptureMouse,WantCaptureKeyboard,WantTextInput, andRequestedMouseCursor, and the example hosts consume those outputs.UiContextnow also exposes per-frame item/container query snapshots (LastItemState, hovered/focused item, containing container, active input layer), visible-bounds helpers, and stronger focus APIs such as focus-by-id and next-frame focus requests.UiContextnow also exposesClipboard, with a default in-memory implementation plus host-swappable clipboard adapters for copy/cut/paste-aware controls.UiInputStatealso carries double-click state, drag origins/thresholds, and horizontal wheel deltas for richer host input plumbing.- The shipped example and editor hosts now generate held-key repeat for repeatable navigation/editing keys like arrows, backspace/delete, home/end, and page up/down.
- Shared fixed-height virtualization now lives in
UiClipper/UiClipRange, and the shipped examples use it for largeUiListBox,UiTable, andUiTreeViewdatasets in theClippingwindow. - Checkbox, radio, slider, and drag controls now cover scalar/vector/range editing, log scaling where relevant, wrap/no-input/no-round flag depth, and temporary direct numeric entry via Ctrl/Cmd+click or double-click where allowed.
- Table controls now include runtime column/view state, row selection, resize/reorder/hide, X/Y scrolling, row clipping, row-height hooks, per-cell styling hooks, and richer header/cell content via
UiTableCell,UiTableColumnState, andUiTableViewState. - Table headers support angled labels, sortable columns via
UiTable.SortSpecs, and built-in header context menus for hide/show/reset workflows. - Plotting panel control supports axes, tick labels, grid lines, and zoom/pan input.
- Waveform control renders sample buffers with min/max or line modes and an optional zero line.
- Grid layout control assigns children to rows/columns with spacing and padding.
- Canvas control supports pan/zoom with optional grid and origin helpers, plus public world/screen coordinate conversion helpers.
- Node graph primitives (
UiNodeGraph,UiNodeControl,UiNodePin,UiNodeWire) build onUiCanvasfor reusable editor-style nodes, exec/data pins, routed wires, wire-preview state, and debug layout metadata. - Color edit and color picker controls now cover RGB / HSV / HEX workflows, byte-vs-float value displays, picker-popup integration, side preview/input toggles, alpha bars, checkerboard transparency, and color drag/drop.
- Multi-select selection model for list boxes and selectables (Ctrl/Shift range) is available.
- Scroll panels support auto/always scrollbars for overflowing content.
UiStack,UiWrapPanel,UiGroup,UiThickness, andUiLayoutLengthnow provide retained row/column/wrap/group layout primitives with padding, gap, baseline alignment, and fixed/fill/percentage sizing.UiCombo,UiListView,UiSelectableRow,UiChildRegion, and popup open helpers now power the composed combo/list/popup demo inOpenControls.Examples, andUiComboBoxremains as a string-list convenience wrapper over that richer combo path.IUiImageSourceplusUiDelegateImageSourceprovide a reusable adapter path for repeated thumbnail/icon drawing inside rich rows and popup content.UiPickerprovides a richer editor-facing convenience surface for labeled/detail/icon picker rows whileUiComboBoxremains the simple string-list wrapper.UiChildRegionis the embedded, clipped, scrollable viewport primitive for content inside an existing window, panel, or popup; useUiWindowwhen you need independent title/chrome/focus behavior instead of an in-place framed region.- Windows can host optional scroll panels for overflow content (shown in docked/floating examples).
- Window and dock host controls support tabbed layouts with close buttons and overflow scrolling.
- Tab bars support
UiTabItemButtonwith leading/trailing placement. - Tabs, window titles, table headers, tree node headers, and labels can render bold text.
- Dock workspaces support drag previews, drop targets, floating windows, and draggable persisted splitters with minimum pane clamping.
- Drag/drop payloads are supported via
UiDragDropSource,UiDragDropTarget, andUiDragDropContext. - Menu bar control supports dropdowns, command IDs, shortcut dispatch, keyboard navigation, checkable items, nested submenus, popup menus, embedded content, and attached/context opening helpers for popup-mode composition.
- Tree nodes,
UiTreeView, collapsing headers, tooltips, popups, and modals are available, and tooltip/context helpers now support delayed hover, focus-target tooltips, and item-attached popup/menu opening. - Text editor control supports line numbers, scrolling, and syntax highlighting.
- Text fields now support selection, copy/cut/paste, undo/redo, commit/cancel hooks, password/read-only/filtering modes, completion/history callbacks, resize callbacks, and placeholder text.
- Numeric input fields (
UiInputFloat/Int/Double,UiNumericField, and vector variants) and vector sliders (UiSliderFloat2/3/4,UiSliderInt2/3/4,UiSliderVector) are available. - Image widgets (
UiImage,UiImageButton) support renderer-specific draw callbacks, and can also consume reusable image-source adapters for texture-backed UI. - Splitter control provides draggable horizontal/vertical splits for manual layouts.
- Arrow glyph helper (
UiArrow) keeps tree/combo/menu indicators consistent. - Common controls support rounded corners and masking for clipped children via
CornerRadiusandUiRenderHelpershelpers. - Panels and windows support child clipping and resize grips.
- UI state serialization now restores richer editor/view state including selection, scroll, table view, combo/list state, and custom extension hooks through
IUiStatefulElement. - OpenControls.MonoGame.Examples renders the shared examples UI using MonoGame DesktopGL (via OpenControls.MonoGame).
- OpenControls.SdlNet.Examples renders the shared examples UI using SDL2-CS (via OpenControls.SdlNet).
- OpenControls.SilkNet provides a Silk.NET-based renderer adapter using modern OpenGL 3.3 core-profile bindings.
- OpenControls.SilkNet.Examples renders the shared examples UI using Silk.NET windowing/input plus the Silk.NET renderer adapter, and now exposes a
SilkTextInputBridgehook so host apps can forward platform composition/candidate-window behavior through the sameUiTextInputRequest/UiInputState.Compositioncontract. - OpenControls.OpenGL provides an OpenTK-based renderer adapter (compatibility profile).
- OpenControls.OpenGL.Examples renders the shared examples UI using OpenGL (via OpenControls.OpenGL).
- OpenControls.Examples includes an Examples menu to open feature windows as dockable panels.
- OpenControls.Examples includes a dedicated Text Editor demo window.
- OpenControls.Examples widgets window groups controls into categorized tree nodes (collapsed by default, with header spacing).
- OpenControls.Examples now shows real shortcut, capture, and requested-cursor state in the Inputs & Focus demo.
- OpenControls.Examples now also shows text-input request details including caret bounds, candidate bounds, composition support, and live preedit/composition text in the Inputs & Focus demo.
- OpenControls.Examples now includes a custom-font and merged-icon demo in the Widgets text section, with Silk.NET as the reference parity host.
- OpenControls.Examples now also includes a dedicated
Widget Gallerywindow for the option-level coverage pass that complements the originalWidgetstree,Text Editor,Docking, andClippingwindows. - A dedicated UI editor is planned and will be documented once available.
- OpenControls includes a TinyBitmapFont helper that covers full printable ASCII plus Latin-1/CP437 code pages (shown in the Widgets ASCII table).
- OpenControls now ships
UiFont,UiFontBuilder,UiFontRegistry, per-element/inherited font selection, custom font-file loading, fallback chains, and merged icon-font ranges for inline icon text. - The shipped renderer path now uses shared atlas-backed grayscale glyph caches across MonoGame, SDL2-CS, Silk.NET, and OpenGL instead of per-pixel glyph loops, and outline-font shaping now has a first-pass HarfBuzz-backed path for ligatures, kerning, and script-aware glyph placement. Slug remains an optional follow-on GPU text-rendering path in the parity roadmap.
- OpenControls now also ships
UiDpiCompensationandUiScaledRendererfor default-on DPI-aware rendering from a 96 DPI baseline. The shipped Silk.NET, MonoGame, SDL2-CS, OpenGL, and editor hosts now keep layout/input in logical units while scaling rendering to the host DPI, and custom hosts can opt out by disabling the compensation object.
- The recommended host pattern is: keep UI bounds and input in logical coordinates, derive a content scale from logical window size vs physical framebuffer/backbuffer size (or monitor DPI), and render through
UiScaledRenderer. UiDpiCompensationdefaults toTargetDpi = 96andEnabled = true, with a default minimum scale of1.0so low-DPI hosts do not shrink below the current baseline.- Disable DPI compensation by setting
UiDpiCompensation.Enabled = false, or by flipping the host convenience property where the shipped example/editor hosts expose one.


