Skip to main content

GUI Component Internals

This page describes the internal architecture of the Oidis GUI component system. It is primarily useful when building custom UserControls (components extending GuiCommons or BasePanel), debugging rendering or lifecycle issues, or understanding how the framework manages component state.

For everyday panel and controller development, you do not need this level of detail — see Panels and Controllers instead.


Inheritance Hierarchy​

All GUI components trace their lineage back through GuiCommons to BaseObject from io-oidis-commons.

BaseObject  (io-oidis-commons)
└── GuiCommons (abstract)
├── BaseGuiObject (abstract)
│ └── AbstractGuiObject
│ └── [standard UserControls: Button, TextField, Label, DropDown, …]
└── FormsObject (abstract)
└── BasePanel (abstract)
└── [custom Panels declared in solution projects]

GuiCommons​

GuiCommons is the root of all GUI objects. It carries:

  • guiId — unique element identifier (auto-generated from class name + counter, or overridden)
  • guiPath — path in the component hierarchy
  • parent / owner — parent GuiCommons element and the IBaseViewer controller that owns the element
  • visible / enabled — current visual and interaction state
  • options (GuiOptionsManager) — feature flag manager (see GuiOptionType)
  • events (ElementEventsManager) — local event subscription manager returned by .getEvents()
  • childElements / waitFor — collections of child elements managed by this component
  • innerHtmlMap (IGuiElement) — the GuiElement instance that builds the HTML output
  • Layout properties: alignment, fitToParent, widthOfColumn (PropagableNumber), wrappingElement, wrappingContainer
  • Lifecycle flags: cached, prepared, completed, loaded, contentLoaded

Key static method: GuiCommons.GuiElementClass($value?) — gets or sets the GuiElement class used for HTML rendering across all components. This is a global setting for the rendering engine.

BaseGuiObject​

Extends GuiCommons with:

  • Title() — lazy-initialized tooltip component (IToolTip)
  • changed flag — tracks whether the component's value has been modified
  • Static hover event handlers (onHoverEventHandler, onUnhoverEventHandler) — shared across all GUI objects that support hover state propagation to parent

AbstractGuiObject​

Used during development phases. Adds:

  • Notification component support
  • Size management helpers

Standard UserControls (Button, TextField, etc.) extend AbstractGuiObject.

FormsObject​

Base for all components that participate in form submission. Extends GuiCommons with form input handling. BasePanel extends FormsObject.

BasePanel​

The primary base class for all panels declared in solution projects. Extends FormsObject with:

  • verticalScrollBar / horizontalScrollBar — built-in scrollbar components (declared as public fields)
  • loaderIcon / loaderText — loading indicator components
  • contentType (PanelContentType) — controls how content is loaded: synchronous, async, or from a URL loader
  • childPanelList — registry of child panel viewers managed by this panel
  • Orientation support (OrientationType.HORIZONTAL / VERTICAL)
  • Keyboard navigation (arrow keys for panel focus traversal)

Lifecycle States​

GuiCommons tracks component state through four boolean flags. Understanding these is important when building components that react to lifecycle stages.

FlagSet whenCleared when
cachedHTML has been generated and cachedDraw() is called with $force = true
preparedComponent is ready for rendering (all dependencies resolved)Reset on reinitialize
completedRendering pipeline has finishedReset on reinitialize
loadedData has been loaded into the componentReset on data refresh
contentLoadedInner content (child panels, async content) has loadedReset on content refresh

You can query these via IsLoaded(), IsCompleted(), IsPrepared(), IsCached().

Show/Hide and the Lifecycle​

When GuiCommons.Show($element) is called (the static method), it:

  1. Calls ElementManager.Show($element.Id()) to make the DOM element visible
  2. Fires EventType.ON_SHOW via the global EventsManager
  3. If the element is already loaded, the show event fires immediately
  4. If not yet loaded, the show event fires after the next Draw() completes

The reverse applies to GuiCommons.Hide($element).


Rendering Pipeline​

All GUI components output HTML through a common pipeline:

component.Draw()
│
▼
GuiElement (innerHtmlMap)
│ builds HTML <div> structure with:
│ - component id
│ - CSS class names (interface, style, container)
│ - layout metadata (data-* attributes)
│ - child element HTML (recursive Draw() calls)
│
▼
HTML string output
│
▼
DOM insertion → ElementEventsManager.Subscribe()
(hooks registered events to DOM element)

GuiElement — The HTML Builder​

GuiElement implements IGuiElement and IResponsiveElement. It is the low-level HTML structure builder used by every component. It generates <div> elements with:

  • Element id attribute (mapped from guiId)
  • CSS class names from interfaceClassName, styleClassName, containerClassName
  • Layout attributes for the responsive grid system
  • Nested child element HTML via recursive rendering

The GuiElement class used can be swapped globally via GuiCommons.GuiElementClass($newClass), allowing custom rendering backends.

Async Drawing​

Components support async rendering via asyncDrawEnabled. When enabled, the rendering is deferred to avoid blocking the UI thread during complex component trees. The AnimationThreadPool may be involved for animation-dependent renders.


ResponsiveElement Layout System​

GuiCommons supports a responsive grid through IResponsiveElement:

PropertyTypePurpose
AlignmentAlignment enumLEFT, CENTER, RIGHT, JUSTIFY
FitToParentFitToParent enumHow to fill parent container
WidthOfColumnPropagableNumberColumn width that propagates to children
HeightOfRowPropagableNumberRow height that propagates to children

PropagableNumber is a special structure that carries a numeric value and propagates it down the component tree when not overridden at a lower level. This enables responsive percentage-based sizing where child elements inherit layout constraints from their parent unless they define their own.


GuiOptionsManager — Feature Flags​

Each component has a GuiOptionsManager (accessible via getOptions()) that manages which optional features are enabled. Feature flags are defined in GuiOptionType:

OptionEffect
GuiOptionType.TOOL_TIPEnables tooltip rendering and the Title() component
GuiOptionType.NOTIFICATIONEnables notification indicator rendering

Custom UserControls can define their own GuiOptionType values and check them via getOptions().IsEnabled($type).


Viewer Pattern​

Legacy System — Deprecated

The viewer layer (BasePanelViewer, BaseViewer) is part of the legacy GUI system. In the Bootstrap 5 system, BasePanelController<Panel> talks directly to the panel — there is no viewer intermediary.

If you encounter BasePanelViewer or BaseViewer in existing code, do not extend these classes in new code. See Bootstrap 5 vs Legacy for the full picture.

In the legacy system, controllers work through a viewer layer:

BasePanelViewer (legacy controller)
│
└── renders → BasePanel from Primitives/ (legacy, monolithic)
  • BaseViewer (abstract, legacy) — base for all viewer-based controllers. Manages async drawing and element lifecycle internally.
  • BasePanelViewer (legacy) — viewer that acts as controller + renderer. Ties a BasePanel (Primitives) instance to its rendering context.

In contrast, the Bootstrap 5 pattern has no viewer intermediary:

BasePanelController<MyPanel>   ← Bootstrap 5 controller (no viewer)
│
└── manages → MyPanel (extends Bootstrap/Primitives/BasePanel)
  • BasePanelController<Panel> — the Bootstrap 5 MVC controller. Generic over the Panel type, providing FetchData(), beforeLoad(), resolver() lifecycle hooks and access to HttpManager and EventsManager.

ImageProcessor​

The ImageProcessor module (Io.Oidis.Gui.ImageProcessor) provides canvas-based image manipulation utilities:

  • ImageFilters — pixel-level operations (brightness, contrast, grayscale, sepia, etc.)
  • ImageTransform — geometric transformations (crop, scale, rotate)

These are used internally by the CropBox and image viewer components. Solution developers interact with these capabilities through those components' APIs rather than calling ImageProcessor directly.


See also: Panels and Controllers | Data Binding | Events System | Page-Panel-Controller