====== 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;
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 ====
==== 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 =====
* [[.:control-bibliothek|Libreria Control]]
* [[.:control-entwicklung|Sviluppo Control (7 Passi)]]
* [[.:tui-controls|TUI Controls]]
* [[.:pxaml-pipeline|Pipeline PXAML]]