Architettura Control

Architettura e pattern per WvdS UI Controls.

Panoramica

Tutti i WvdS Controls seguono il Pattern Properties/ViewInfo/Control (ispirato a WPF):

TWvdSDependencyObject
    +-- TWvdSFrameworkElement
            +-- TWvdSControl
                    +-- TWvdS{NomeControl}

Gerarchia Classi

TWvdSDependencyObject

Base per tutti gli oggetti con Dependency Properties.

TWvdSDependencyObject = class
private
  FPropertyValues: TDictionary<string, TValue>;
public
  function GetValue(AProperty: TWvdSDependencyProperty): TValue;
  procedure SetValue(AProperty: TWvdSDependencyProperty; AValue: TValue);
  procedure ClearValue(AProperty: TWvdSDependencyProperty);
end;

TWvdSFrameworkElement

Estende con layout e proprieta visuali.

TWvdSFrameworkElement = class(TWvdSDependencyObject)
private
  FWidth, FHeight: Double;
  FMinWidth, FMinHeight: Double;
  FMaxWidth, FMaxHeight: Double;
  FMargin, FPadding: TWvdSThickness;
  FHorizontalAlignment: TWvdSHorizontalAlignment;
  FVerticalAlignment: TWvdSVerticalAlignment;
public
  function MeasureOverride(AAvailableSize: TWvdSSize): TWvdSSize; virtual;
  function ArrangeOverride(AFinalSize: TWvdSSize): TWvdSSize; virtual;
  procedure Render(ASurface: TWvdSRenderSurface); virtual; abstract;
end;

TWvdSControl

Base per tutti i control interattivi.

TWvdSControl = class(TWvdSFrameworkElement)
private
  FIsEnabled: Boolean;
  FIsFocused: Boolean;
  FTabIndex: Integer;
  FTemplate: TWvdSControlTemplate;
  FViewInfo: TWvdSViewInfo;
public
  property IsEnabled: Boolean read FIsEnabled write SetIsEnabled;
  property IsFocused: Boolean read FIsFocused;
  property TabIndex: Integer read FTabIndex write FTabIndex;
  property Template: TWvdSControlTemplate read FTemplate write FTemplate;
  property ViewInfo: TWvdSViewInfo read FViewInfo;
 
  procedure OnGotFocus; virtual;
  procedure OnLostFocus; virtual;
  procedure OnKeyDown(AEvent: TWvdSKeyEventArgs); virtual;
  procedure OnMouseDown(AEvent: TWvdSMouseEventArgs); virtual;
end;

Pattern Properties/ViewInfo/Control

Architettura a Tre Strati

+-------------------------------------------------+
|  Properties Layer                               |
|  - API pubblica (Properties, Events)            |
|  - Dependency Properties                        |
|  - Bindable, compatibile PXAML                  |
+-------------------------------------------------+
|  ViewInfo Layer                                 |
|  - Informazioni visuali calcolate               |
|  - Cache per rendering                          |
|  - Bounds, Rects, valori calcolati              |
+-------------------------------------------------+
|  Control Layer                                  |
|  - Logica di rendering                          |
|  - Gestione input                               |
|  - Specifico per target (TUI/GUI/Web)           |
+-------------------------------------------------+

Esempio: TWvdSButton

(* Properties Layer *)
TWvdSButtonProperties = class(TWvdSControlProperties)
published
  property Caption: string;
  property ImageSource: TWvdSImageSource;
  property IsDefault: Boolean;
  property IsCancel: Boolean;
  property Command: IWvdSCommand;
end;
 
(* ViewInfo Layer *)
TWvdSButtonViewInfo = class(TWvdSViewInfo)
private
  FCaptionBounds: TRect;
  FImageBounds: TRect;
  FContentBounds: TRect;
public
  procedure Calculate(AAvailableRect: TRect); override;
  property CaptionBounds: TRect read FCaptionBounds;
  property ImageBounds: TRect read FImageBounds;
end;
 
(* Control Layer *)
TWvdSButton = class(TWvdSControl)
private
  FProperties: TWvdSButtonProperties;
  FViewInfo: TWvdSButtonViewInfo;
public
  constructor Create;
  procedure Render(ASurface: TWvdSRenderSurface); override;
  procedure OnClick; virtual;
published
  property Caption: string read GetCaption write SetCaption;
  property OnClick: TNotifyEvent read FOnClick write FOnClick;
end;

Target-Renderer

Ogni control ha un renderer specializzato per target.

Interfaccia Renderer

IWvdSControlRenderer = interface
  function Measure(AControl: TWvdSControl; AAvailable: TWvdSSize): TWvdSSize;
  procedure Arrange(AControl: TWvdSControl; ARect: TRect);
  procedure Paint(AControl: TWvdSControl; ASurface: TWvdSRenderSurface);
  function HandleInput(AControl: TWvdSControl; AEvent: TWvdSInputEvent): Boolean;
end;

Implementazioni Specifiche per Target

sources/common/ui/targets/
+-- tui/
|   +-- WvdS.UI.TUI.ButtonRenderer.pas
|   +-- WvdS.UI.TUI.TextEditRenderer.pas
|   +-- ...
+-- gui/
|   +-- WvdS.UI.GUI.ButtonRenderer.pas
|   +-- ...
+-- web/
    +-- WvdS.UI.Web.ButtonRenderer.pas
    +-- ...

Esempio Renderer TUI

TWvdSButtonTUIRenderer = class(TInterfacedObject, IWvdSControlRenderer)
public
  function Measure(AControl: TWvdSControl; AAvailable: TWvdSSize): TWvdSSize;
  procedure Arrange(AControl: TWvdSControl; ARect: TRect);
  procedure Paint(AControl: TWvdSControl; ASurface: TWvdSRenderSurface);
  function HandleInput(AControl: TWvdSControl; AEvent: TWvdSInputEvent): Boolean;
end;
 
procedure TWvdSButtonTUIRenderer.Paint(AControl: TWvdSControl;
  ASurface: TWvdSRenderSurface);
var
  Btn: TWvdSButton;
  Style: TWvdSStyle;
begin
  Btn := TWvdSButton(AControl);
 
  (* Selezione stile basata sullo stato *)
  if not Btn.IsEnabled then
    Style := Theme.ButtonDisabled
  else if Btn.IsFocused then
    Style := Theme.ButtonFocused
  else
    Style := Theme.ButtonDefault;
 
  (* Disegna bordo *)
  ASurface.DrawBorder(Btn.Bounds, bsSingle, Style);
 
  (* Disegna caption centrata *)
  ASurface.DrawTextCentered(Btn.ViewInfo.ContentBounds,
    Btn.Caption, Style);
end;

Dependency Properties

Definizione

class var
  CaptionProperty: TWvdSDependencyProperty;
 
class constructor TWvdSButton.Create;
begin
  CaptionProperty := TWvdSDependencyProperty.Register(
    'Caption',                    (* Nome *)
    TypeInfo(string),             (* Tipo *)
    TWvdSButton,                  (* Owner *)
    '',                           (* Default *)
    @OnCaptionChanged             (* Callback *)
  );
end;
Compatibilita pas2js: class var non funziona in pas2js. Usa invece variabili a livello Unit.

Alternativa Compatibile pas2js

var
  GButtonCaptionProperty: TWvdSDependencyProperty = nil;
 
function ButtonCaptionProperty: TWvdSDependencyProperty;
begin
  if GButtonCaptionProperty = nil then
    GButtonCaptionProperty := TWvdSDependencyProperty.Register(...);
  Result := GButtonCaptionProperty;
end;

Visual States

Stati obbligatori:
+-- Normal       (* Stato default *)
+-- Focused      (* Ha focus tastiera *)
+-- Disabled     (* IsEnabled = False *)
+-- Invalid      (* Errore validazione *)

Stati opzionali:
+-- MouseOver    (* Mouse sopra *)
+-- Pressed      (* Premuto attivamente *)
+-- Selected     (* Selezionato *)

Gestione Input

Ordine Eventi

1. PreviewKeyDown (Tunneling)
2. KeyDown (Bubbling)
3. Elaborazione specifica del control
4. Esecuzione Command (se bindato)

Gestione Focus

TWvdSFocusManager = class
public
  class function GetFocusedElement: TWvdSFrameworkElement;
  class procedure SetFocus(AElement: TWvdSFrameworkElement);
  class procedure MoveFocus(ADirection: TWvdSFocusNavigationDirection);
end;
 
TWvdSFocusNavigationDirection = (
  fndNext,      (* Tab *)
  fndPrevious,  (* Shift+Tab *)
  fndUp,
  fndDown,
  fndLeft,
  fndRight
);

Data Binding

Sintassi Binding in PXAML

<TextEdit Text="{Binding CustomerName, Mode=TwoWay}" />
<Button Caption="{Binding SaveCommand.Caption}"
        Command="{Binding SaveCommand}" />

Modalita Binding

Modalita Descrizione
OneTime Una volta all'inizializzazione
OneWay Source → Target
TwoWay Source ↔ Target
OneWayToSource Target → Source

Ciclo di Vita Control

1. Costruttore
   +-- Inizializzare properties

2. Applicare template
   +-- Caricare e applicare ControlTemplate

3. Measure
   +-- Calcolare dimensione desiderata

4. Arrange
   +-- Posizione e dimensione finale

5. Render
   +-- Disegnare in RenderSurface

6. Eventi Input
   +-- Tastiera, mouse, touch

7. Distruttore
   +-- Rilasciare risorse

Struttura File

sources/common/ui/
+-- framework/                    # Framework base (42 Unit)
|   +-- WvdS.UI.DependencyObject.pas
|   +-- WvdS.UI.FrameworkElement.pas
|   +-- WvdS.UI.Control.pas
|   +-- WvdS.UI.ViewInfo.pas
|   +-- ...
|
+-- controls/                     # Implementazioni control
|   +-- basic/
|   |   +-- WvdS.UI.Controls.Button.pas
|   |   +-- WvdS.UI.Controls.Label.pas
|   |   +-- ...
|   +-- editors/
|   +-- data/
|   +-- ...
|
+-- targets/                      # Renderer specifici per target
|   +-- tui/
|   +-- gui/
|   +-- web/
|
+-- themes/                       # Definizioni tema
    +-- WvdS.UI.Themes.Default.pas
    +-- WvdS.UI.Themes.Dark.pas

Vedi anche

Zuletzt geändert: il 29/01/2026 alle 22:32