Arhitektura kontrol

Arhitektura in vzorci za WvdS UI kontrole.

Pregled

Vse WvdS kontrole sledijo vzorcu Properties/ViewInfo/Control Pattern (navdahnjeno z WPF):

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

Hierarhija razredov

TWvdSDependencyObject

Osnova za vse objekte z 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

Razširjeno s postavitvijo in vizualnimi lastnostmi.

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

Osnova za vse 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

Triplastna arhitektura

+-------------------------------------------------+
|  Plast Properties                               |
|  - Javni API (Properties, Events)               |
|  - Dependency Properties                        |
|  - Možnost vezave, PXAML-združljivo             |
+-------------------------------------------------+
|  Plast ViewInfo                                 |
|  - Izračunane vizualne informacije              |
|  - Predpomnilnik za upodabljanje                |
|  - Bounds, Rects, izračunane vrednosti          |
+-------------------------------------------------+
|  Plast Control                                  |
|  - Logika upodabljanja                          |
|  - Obdelava vnosa                               |
|  - Specifično za cilj (TUI/GUI/Web)             |
+-------------------------------------------------+

Primer: TWvdSButton

(* Plast Properties *)
TWvdSButtonProperties = class(TWvdSControlProperties)
published
  property Caption: string;
  property ImageSource: TWvdSImageSource;
  property IsDefault: Boolean;
  property IsCancel: Boolean;
  property Command: IWvdSCommand;
end;
 
(* Plast ViewInfo *)
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;
 
(* Plast Control *)
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

Vsaka kontrola ima specializiran upodabljalnik za vsak cilj.

Vmesnik upodabljalnika

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;

Implementacije specifične za cilj

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
    +-- ...

Primer TUI upodabljalnika

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);
 
  (* Izbira sloga glede na stanje *)
  if not Btn.IsEnabled then
    Style := Theme.ButtonDisabled
  else if Btn.IsFocused then
    Style := Theme.ButtonFocused
  else
    Style := Theme.ButtonDefault;
 
  (* Risanje obrobe *)
  ASurface.DrawBorder(Btn.Bounds, bsSingle, Style);
 
  (* Risanje sredinske oznake *)
  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',                    (* Ime *)
    TypeInfo(string),             (* Tip *)
    TWvdSButton,                  (* Lastnik *)
    '',                           (* Privzeto *)
    @OnCaptionChanged             (* Povratni klic *)
  );
end;
pas2js-združljivost: class var ne deluje v pas2js. Namesto tega uporabite spremenljivke na ravni enote.

pas2js-združljiva alternativa

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

Visual States

Obvezna stanja:
+-- Normal       (* Privzeto stanje *)
+-- Focused      (* Ima fokus tipkovnice *)
+-- Disabled     (* IsEnabled = False *)
+-- Invalid      (* Napaka validacije *)

Izbirna stanja:
+-- MouseOver    (* Miška nad *)
+-- Pressed      (* Aktivno pritisnjen *)
+-- Selected     (* Izbrano *)

Obdelava vnosa

Vrstni red dogodkov

1. PreviewKeyDown (Tunneling)
2. KeyDown (Bubbling)
3. Obdelava specifična za kontrolo
4. Izvajanje ukaza (če je vezan)

Upravljanje fokusa

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

Sintaksa vezave v PXAML

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

Načini vezave

Način Opis
OneTime Enkratno ob inicializaciji
OneWay Vir → Cilj
TwoWay Vir ↔ Cilj
OneWayToSource Cilj → Vir

Življenjski cikel kontrole

1. Konstruktor
   +-- Inicializacija lastnosti

2. Uporaba predloge
   +-- Nalaganje in uporaba ControlTemplate

3. Measure
   +-- Izračun želene velikosti

4. Arrange
   +-- Končna pozicija in velikost

5. Render
   +-- Risanje v RenderSurface

6. Dogodki vnosa
   +-- Tipkovnica, miška, dotik

7. Destruktor
   +-- Sprostitev virov

Struktura datotek

sources/common/ui/
+-- framework/                    # Osnovno ogrodje (42 enot)
|   +-- WvdS.UI.DependencyObject.pas
|   +-- WvdS.UI.FrameworkElement.pas
|   +-- WvdS.UI.Control.pas
|   +-- WvdS.UI.ViewInfo.pas
|   +-- ...
|
+-- controls/                     # Implementacije kontrol
|   +-- basic/
|   |   +-- WvdS.UI.Controls.Button.pas
|   |   +-- WvdS.UI.Controls.Label.pas
|   |   +-- ...
|   +-- editors/
|   +-- data/
|   +-- ...
|
+-- targets/                      # Upodabljalniki specifični za cilj
|   +-- tui/
|   +-- gui/
|   +-- web/
|
+-- themes/                       # Definicije tem
    +-- WvdS.UI.Themes.Default.pas
    +-- WvdS.UI.Themes.Dark.pas

Glejte tudi

Zuletzt geändert: dne 29.01.2026 ob 22:27