====== Arhitektura kontrola ======
Arhitektura i obrasci za WvdS UI Controls.
===== Pregled =====
Sve WvdS Controls prate **Properties/ViewInfo/Control Pattern** (WPF-inspiriran):
TWvdSDependencyObject
└── TWvdSFrameworkElement
└── TWvdSControl
└── TWvdS{ControlName}
===== Hijerarhija klasa =====
==== TWvdSDependencyObject ====
Baza za sve objekte s 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 ====
Proširuje s layoutom i vizualnim svojstvima.
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 ====
Baza za sve interaktivne kontrole.
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;
===== Properties/ViewInfo/Control Pattern =====
==== Troslojna arhitektura ====
┌─────────────────────────────────────────────────┐
│ Properties Layer │
│ - Javni API (Properties, Events) │
│ - Dependency Properties │
│ - Bindable, PXAML-kompatibilno │
├─────────────────────────────────────────────────┤
│ ViewInfo Layer │
│ - Izračunate vizualne informacije │
│ - Cache za rendering │
│ - Bounds, Rects, izračunate vrijednosti │
├─────────────────────────────────────────────────┤
│ Control Layer │
│ - Rendering-logika │
│ - Input-Handling │
│ - Target-specifično (TUI/GUI/Web) │
└─────────────────────────────────────────────────┘
==== Primjer: 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 =====
Svaka kontrola ima specijalizirani renderer po targetu.
==== Renderer-Interface ====
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;
==== Target-specifične implementacije ====
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
└── ...
==== TUI Renderer Primjer ====
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);
(* Odabir stila na temelju stanja *)
if not Btn.IsEnabled then
Style := Theme.ButtonDisabled
else if Btn.IsFocused then
Style := Theme.ButtonFocused
else
Style := Theme.ButtonDefault;
(* Crtanje obruba *)
ASurface.DrawBorder(Btn.Bounds, bsSingle, Style);
(* Centrirano crtanje Caption *)
ASurface.DrawTextCentered(Btn.ViewInfo.ContentBounds,
Btn.Caption, Style);
end;
===== Dependency Properties =====
==== Definicija ====
class var
CaptionProperty: TWvdSDependencyProperty;
class constructor TWvdSButton.Create;
begin
CaptionProperty := TWvdSDependencyProperty.Register(
'Caption', (* Naziv *)
TypeInfo(string), (* Tip *)
TWvdSButton, (* Owner *)
'', (* Default *)
@OnCaptionChanged (* Callback *)
);
end;
**pas2js-kompatibilnost:** ''class var'' ne radi u pas2js. Koristi Unit-Level varijable umjesto toga.
==== pas2js-kompatibilna alternativa ====
var
GButtonCaptionProperty: TWvdSDependencyProperty = nil;
function ButtonCaptionProperty: TWvdSDependencyProperty;
begin
if GButtonCaptionProperty = nil then
GButtonCaptionProperty := TWvdSDependencyProperty.Register(...);
Result := GButtonCaptionProperty;
end;
===== Visual States =====
Obvezna stanja:
├─ Normal (* Zadano stanje *)
├─ Focused (* Ima tipkovnički fokus *)
├─ Disabled (* IsEnabled = False *)
└─ Invalid (* Validacijska greška *)
Opcionalna stanja:
├─ MouseOver (* Miš iznad *)
├─ Pressed (* Aktivno pritisnuto *)
└─ Selected (* Odabrano *)
===== Input-Handling =====
==== Redoslijed događaja ====
1. PreviewKeyDown (Tunneling)
2. KeyDown (Bubbling)
3. Kontrola-specifična obrada
4. Izvršavanje Command (ako je povezan)
==== Focus-Management ====
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 =====
==== Binding-sintaksa u PXAML ====
==== Binding-Modes ====
| Mode | Opis |
^ OneTime | Jednom kod inicijalizacije |
^ OneWay | Source → Target |
^ TwoWay | Source ↔ Target |
^ OneWayToSource | Target → Source |
===== Životni ciklus kontrole =====
1. Konstruktor
└─ Inicijalizacija svojstava
2. Primjena predloška
└─ Učitavanje i primjena ControlTemplate
3. Measure
└─ Izračun željene veličine
4. Arrange
└─ Finalna pozicija i veličina
5. Render
└─ Crtanje u RenderSurface
6. Input-Events
└─ Tipkovnica, miš, dodir
7. Destruktor
└─ Oslobađanje resursa
===== Struktura datoteka =====
sources/common/ui/
├── framework/ # Bazni Framework (42 Unit-a)
│ ├── WvdS.UI.DependencyObject.pas
│ ├── WvdS.UI.FrameworkElement.pas
│ ├── WvdS.UI.Control.pas
│ ├── WvdS.UI.ViewInfo.pas
│ └── ...
│
├── controls/ # Implementacije kontrola
│ ├── basic/
│ │ ├── WvdS.UI.Controls.Button.pas
│ │ ├── WvdS.UI.Controls.Label.pas
│ │ └── ...
│ ├── editors/
│ ├── data/
│ └── ...
│
├── targets/ # Target-specifični Rendereri
│ ├── tui/
│ ├── gui/
│ └── web/
│
└── themes/ # Definicije tema
├── WvdS.UI.Themes.Default.pas
└── WvdS.UI.Themes.Dark.pas
===== Vidi također =====
* [[.:control-bibliothek|Biblioteka kontrola]]
* [[.:control-entwicklung|Razvoj kontrola (7-koraka)]]
* [[.:tui-controls|TUI Controls]]
* [[.:pxaml-pipeline|PXAML-Pipeline]]