Base Widget
The Widget class is the abstract base class for all UI components in Elaris.UI. Understanding how widgets work is essential for building applications and creating custom widgets.
Overview
Section titled “Overview”Every UI element in Elaris.UI inherits from Widget. This includes containers, labels, buttons, input fields, and more. The widget system provides a consistent interface for:
- Layout Management: Position and size properties
- Rendering: Custom drawing via virtual methods
- Parent-Child Relationships: Hierarchical widget trees
- Event Handling: Keyboard and mouse input
- Focus Management: Support for focusable widgets
- State Management: Visibility, enabled state, and more
Widget Hierarchy
Section titled “Widget Hierarchy”classDiagram
class Widget {
<<abstract>>
+Rectangle Bounds
+int X
+int Y
+int Width
+int Height
+bool Visible
+bool Enabled
+Color ForegroundColor
+Color BackgroundColor
+int ZIndex
+Widget Parent
+IReadOnlyList~Widget~ Children
+bool IsFocusable
+bool HasFocus
+void Add(Widget)
+bool Remove(Widget)
+void Clear()
+void Render(Screen)
#abstract void OnRender(Screen)
#virtual void OnBoundsChanged()
#virtual void OnFocus()
#virtual void OnBlur()
#virtual bool OnKeyPress(ConsoleKeyInfo)
#virtual bool OnMouseClick(Point)
}
class Container {
+LayoutMode LayoutMode
+int Padding
+int Spacing
}
class Frame {
+string Title
+BorderStyle BorderStyle
}
class Panel
class TabContainer
class TabContent
class ResponsiveContainer
class Label {
+string Text
+bool Bold
+bool Italic
}
class ProgressBar
class TreeView
class TextView
class Button {
+string Text
+ButtonStyle Style
+event Action Click
}
class Checkbox
class ListBox
class TextField
class AutoCompleteTextField
class Editor {
+string Text
+bool ShowLineNumbers
}
class CodeEditor {
+string Language
+string Theme
+bool SyntaxHighlighting
}
class Table
class StatusBar
class MenuBar
Widget <|-- Container
Container <|-- Frame
Frame <|-- Panel
Container <|-- TabContainer
Container <|-- TabContent
Container <|-- ResponsiveContainer
Widget <|-- Label
Widget <|-- ProgressBar
Widget <|-- TreeView
Widget <|-- TextView
Widget <|-- Button
Widget <|-- Checkbox
Widget <|-- ListBox
Widget <|-- TextField
TextField <|-- AutoCompleteTextField
Widget <|-- Editor
Editor <|-- CodeEditor
Widget <|-- Table
Widget <|-- StatusBar
Widget <|-- MenuBar
The diagram groups widgets by category:
- Layout —
Container,Frame,Panel,TabContainer,TabContent,ResponsiveContainer - Display —
Label,ProgressBar,TreeView,TextView - Input —
Button,Checkbox,ListBox,TextField,AutoCompleteTextField,Editor,CodeEditor - Data —
Table - Chrome —
StatusBar,MenuBar
Properties
Section titled “Properties”Position and Size
Section titled “Position and Size”Bounds (Rectangle)
Section titled “Bounds (Rectangle)”The bounding rectangle of the widget, defining its position and size on the screen.
widget.Bounds = new Rectangle(10, 5, 50, 20); // X=10, Y=5, Width=50, Height=20X, Y, Width, Height (int)
Section titled “X, Y, Width, Height (int)”Convenience properties for accessing and setting individual bounds components.
widget.X = 10;widget.Y = 5;widget.Width = 50;widget.Height = 20;Note: Setting these properties triggers OnBoundsChanged().
Visibility and State
Section titled “Visibility and State”Visible (bool)
Section titled “Visible (bool)”Controls whether the widget is rendered. Hidden widgets and their children are not rendered.
widget.Visible = false; // Hide the widgetEnabled (bool)
Section titled “Enabled (bool)”Controls whether the widget can receive input. Disabled widgets are still rendered but don’t respond to events.
widget.Enabled = false; // Disable the widgetAppearance
Section titled “Appearance”ForegroundColor (Color)
Section titled “ForegroundColor (Color)”The foreground (text) color of the widget.
widget.ForegroundColor = Color.White;widget.ForegroundColor = ColorHelper.FromRgb(255, 200, 100);BackgroundColor (Color)
Section titled “BackgroundColor (Color)”The background color of the widget. Use Color.Transparent for no background.
widget.BackgroundColor = Color.Black;widget.BackgroundColor = Color.Transparent; // No backgroundZIndex (int)
Section titled “ZIndex (int)”Controls rendering order. Higher Z-index values render on top of lower values.
widget.ZIndex = 10; // Render above widgets with lower Z-indexHierarchy
Section titled “Hierarchy”Parent (Widget?)
Section titled “Parent (Widget?)”The parent widget that contains this widget. null if the widget is not added to a parent.
if (widget.Parent != null){ Console.WriteLine($"Parent: {widget.Parent.GetType().Name}");}Children (IReadOnlyList<Widget>)
Section titled “Children (IReadOnlyList<Widget>)”A read-only list of child widgets contained by this widget.
foreach (var child in widget.Children){ Console.WriteLine($"Child: {child.GetType().Name}");}IsFocusable (bool, virtual)
Section titled “IsFocusable (bool, virtual)”Indicates whether the widget can receive keyboard focus. Override in derived classes to return true.
public override bool IsFocusable => true; // Make widget focusableHasFocus (bool)
Section titled “HasFocus (bool)”Indicates whether the widget currently has keyboard focus.
if (widget.HasFocus){ // Widget is focused}Methods
Section titled “Methods”Adding and Removing Children
Section titled “Adding and Removing Children”Add(Widget child)
Section titled “Add(Widget child)”Adds a child widget to this widget. The child must not already have a parent.
var container = new Container();var label = new Label("Hello");container.Add(label); // label.Parent is now containerThrows: InvalidOperationException if the child already has a parent.
Remove(Widget child)
Section titled “Remove(Widget child)”Removes a child widget from this widget.
container.Remove(label); // label.Parent is now nullReturns: true if the widget was removed, false if it wasn’t found.
Clear()
Section titled “Clear()”Removes all child widgets.
container.Clear(); // All children removedRendering
Section titled “Rendering”Render(Screen screen)
Section titled “Render(Screen screen)”Renders the widget and all its children to the screen. This method:
- Checks if the widget is visible
- Calls
OnRender()for the widget itself - Recursively renders all children
Note: You typically don’t call this directly; the Application class handles rendering.
OnRender(Screen screen) (abstract, protected)
Section titled “OnRender(Screen screen) (abstract, protected)”Override this method to implement custom rendering for your widget.
protected override void OnRender(Screen screen){ // Draw widget content screen.WriteText(X, Y, "Hello", ForegroundColor, BackgroundColor);}Virtual Methods and Hooks
Section titled “Virtual Methods and Hooks”Lifecycle Hooks
Section titled “Lifecycle Hooks”OnBoundsChanged() (virtual, protected)
Section titled “OnBoundsChanged() (virtual, protected)”Called when the widget’s bounds (X, Y, Width, or Height) change.
protected override void OnBoundsChanged(){ base.OnBoundsChanged(); // Update internal layout LayoutChildren();}OnVisibleChanged() (virtual, protected)
Section titled “OnVisibleChanged() (virtual, protected)”Called when the Visible property changes.
protected override void OnVisibleChanged(){ base.OnVisibleChanged(); // Handle visibility change}OnEnabledChanged() (virtual, protected)
Section titled “OnEnabledChanged() (virtual, protected)”Called when the Enabled property changes.
protected override void OnEnabledChanged(){ base.OnEnabledChanged(); // Update appearance for disabled state}Child Management Hooks
Section titled “Child Management Hooks”OnChildAdded(Widget child) (virtual, protected)
Section titled “OnChildAdded(Widget child) (virtual, protected)”Called when a child widget is added.
protected override void OnChildAdded(Widget child){ base.OnChildAdded(child); // Update layout when child is added LayoutChildren();}OnChildRemoved(Widget child) (virtual, protected)
Section titled “OnChildRemoved(Widget child) (virtual, protected)”Called when a child widget is removed.
protected override void OnChildRemoved(Widget child){ base.OnChildRemoved(child); // Clean up when child is removed}Focus Hooks
Section titled “Focus Hooks”OnFocus() (virtual, protected internal)
Section titled “OnFocus() (virtual, protected internal)”Called when the widget receives keyboard focus.
protected internal override void OnFocus(){ base.OnFocus(); // Update appearance to show focus _hasFocus = true;}OnBlur() (virtual, protected internal)
Section titled “OnBlur() (virtual, protected internal)”Called when the widget loses keyboard focus.
protected internal override void OnBlur(){ base.OnBlur(); // Restore normal appearance _hasFocus = false;}Input Hooks
Section titled “Input Hooks”OnKeyPress(ConsoleKeyInfo key) (virtual, protected internal)
Section titled “OnKeyPress(ConsoleKeyInfo key) (virtual, protected internal)”Called when a key is pressed and the widget has focus.
protected internal override bool OnKeyPress(ConsoleKeyInfo key){ if (key.Key == ConsoleKey.Enter) { // Handle Enter key PerformAction(); return true; // Event handled } return false; // Let parent handle it}Returns: true if the event was handled, false to propagate to parent.
OnMouseClick(Point position) (virtual, protected internal)
Section titled “OnMouseClick(Point position) (virtual, protected internal)”Called when the mouse is clicked on the widget.
protected internal override bool OnMouseClick(Point position){ if (Bounds.Contains(position)) { // Handle click PerformClick(); return true; } return false;}Creating Custom Widgets
Section titled “Creating Custom Widgets”To create a custom widget, inherit from Widget and implement OnRender:
public class MyCustomWidget : Widget{ private string _text = "Custom Widget";
public string Text { get => _text; set => _text = value ?? string.Empty; }
protected override void OnRender(Screen screen) { if (!Visible || Width <= 0 || Height <= 0) return;
// Draw background screen.FillRectangle(Bounds, ' ', ForegroundColor, BackgroundColor);
// Draw text screen.WriteText(X, Y, _text, ForegroundColor, BackgroundColor); }}Best Practices
Section titled “Best Practices”- Always check bounds: Verify
Width > 0andHeight > 0before rendering - Respect visibility: Don’t render if
Visibleisfalse(baseRenderhandles this) - Handle focus: Override
OnFocusandOnBlurto provide visual feedback - Return from OnKeyPress: Return
trueto consume the event,falseto propagate - Call base methods: Call
base.OnXxx()in overridden lifecycle methods when appropriate
Related Topics
Section titled “Related Topics”- Container - Container widgets for layout
- Layout Modes - Understanding layout modes
- Focus Management - How focus works in Elaris.UI
- Rendering Pipeline - How widgets are rendered