Razvoj kontrolnikov

Potek dela za ustvarjanje novih UI kontrolnikov za WvdS FPC RAD Suite.

Kontrolniki morajo delovati tako v načrtovalnem času (VS Code Designer) kot v izvajalnem času (Desktop/TUI/Web).

Pregled

Kontrolnik sestoji iz več plasti:

Plast Namen Pot
Runtime Model Cilju nevtralna logika ~/sources/common/ui/controls/{category}/
Target Renderer Cilju specifična predstavitev ~/sources/common/ui/targets/{target}/renderers/
Pack Manifest PXAML oznaka → Preslikava razreda ~/packs/controls/{control_id}/
Designer Metadata Orodjarna, lastnosti, dogodki ~/sources/extensions/wvds.vscode.ui.meta/

Spremenljivke

Pri ustvarjanju kontrolnika določite te spremenljivke:

Spremenljivka Primer Opis
{CONTROL_ID} dateedit Enolični identifikator (male črke)
{CONTROL_CLASS} TWvdSDateEdit Ime Pascal razreda
{PXAML_TAG} DateEdit Ime oznake v PXAML
{PXAML_NS} wvds Imenski prostor (wvds za notranje kontrolnike)
{TARGETS} tui,desktop,web Podprti cilji

Potek dela (7 korakov)

Korak 1: Zamrznitev pogodbe

Definirajte javni API kontrolnika:

Lastnosti:

(* Minimalni nabor javnih lastnosti *)
property Value: TDateTime read FValue write SetValue;
property Format: string read FFormat write SetFormat;
property MinDate: TDateTime read FMinDate write FMinDate;
property MaxDate: TDateTime read FMaxDate write FMaxDate;
property ReadOnly: Boolean read FReadOnly write FReadOnly;

Dogodki:

(* Zahtevani dogodki *)
property OnValueChanged: TWvdSNotifyEvent read FOnValueChanged write FOnValueChanged;
property OnValidating: TWvdSValidateEvent read FOnValidating write FOnValidating;

TargetCaps:

Zmožnost TUI Desktop Web
Tipkovnica Zahtevano Zahtevano Zahtevano
Miška Opcijsko Zahtevano Zahtevano
Dotik N/A Opcijsko Opcijsko
Pojavno okno Opcijsko Zahtevano Zahtevano

Korak 2: Enota izvajalnega modela

Ustvarite cilju nevtralno enoto modela:

Pot: ~/sources/common/ui/controls/{category}/WvdS.UI.Controls.{Category}.{ControlId}.pas

unit WvdS.UI.Controls.Editors.DateEdit;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  WvdS.UI.Core.Base,
  WvdS.UI.Core.Events;
 
type
  (*
    @abstract(Polje za vnos datuma s pojavnim koledarjem)
 
    Cilju nevtralen model za DateEdit.
    Ne vsebuje NOBENIH odvisnosti od upodabljanja ali gostitelja.
  *)
  TWvdSDateEdit = class(TWvdSControl)
  private
    FValue: TDateTime;
    FFormat: string;
    FOnValueChanged: TWvdSNotifyEvent;
    procedure SetValue(AValue: TDateTime);
  protected
    procedure DoValueChanged; virtual;
  public
    constructor Create(AOwner: TWvdSComponent); override;
    property Value: TDateTime read FValue write SetValue;
    property Format: string read FFormat write FFormat;
    property OnValueChanged: TWvdSNotifyEvent read FOnValueChanged write FOnValueChanged;
  end;
 
implementation
 
(* Implementacija brez cilju specifične kode *)
 
end.
Brez cilju specifičnih odvisnosti! Brez DOM, brez terminalskih I/O, brez LCL enot.

Korak 3: Enote ciljnih upodabljalnikov

Za vsak cilj v {TARGETS} ustvarite upodabljalnik:

TUI upodabljalnik

Pot: ~/sources/common/ui/targets/tui/renderers/WvdS.UI.TUI.Renderers.DateEdit.pas

unit WvdS.UI.TUI.Renderers.DateEdit;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  WvdS.UI.TUI.Renderer.Base,
  WvdS.UI.Controls.Editors.DateEdit;
 
type
  TWvdSTUIDateEditRenderer = class(TWvdSTUIRenderer)
  public
    procedure Measure(AControl: TWvdSControl; out AWidth, AHeight: Integer); override;
    procedure Paint(AControl: TWvdSControl; ACanvas: TWvdSTUICanvas); override;
    procedure HandleInput(AControl: TWvdSControl; AEvent: TWvdSInputEvent); override;
  end;
 
implementation
 
procedure TWvdSTUIDateEditRenderer.Measure(AControl: TWvdSControl; out AWidth, AHeight: Integer);
begin
  AWidth := 12;  (* [YYYY-MM-DD] *)
  AHeight := 1;
end;
 
procedure TWvdSTUIDateEditRenderer.Paint(AControl: TWvdSControl; ACanvas: TWvdSTUICanvas);
var
  DateEdit: TWvdSDateEdit;
begin
  DateEdit := AControl as TWvdSDateEdit;
  ACanvas.DrawText(0, 0, FormatDateTime(DateEdit.Format, DateEdit.Value));
end;
 
procedure TWvdSTUIDateEditRenderer.HandleInput(AControl: TWvdSControl; AEvent: TWvdSInputEvent);
begin
  (* Obravnava tipkovnice za spremembo datuma *)
end;
 
end.

Desktop upodabljalnik

Pot: ~/sources/common/ui/targets/gui/renderers/WvdS.UI.Desktop.Renderers.DateEdit.pas

Web upodabljalnik

Pot: ~/sources/common/ui/targets/web/renderers/WvdS.UI.Web.Renderers.DateEdit.pas

Korak 4: Pack manifest

Ustvarite Pack manifest za PXAML razreševalnik:

Pot: ~/packs/controls/{control_id}/pack.wvds.json

{
  "id": "dateedit",
  "vendor": "wvds",
  "version": "0.1.0",
  "xml": {
    "namespace": "wvds",
    "tag": "DateEdit"
  },
  "model": {
    "unit": "WvdS.UI.Controls.Editors.DateEdit",
    "class": "TWvdSDateEdit"
  },
  "renderers": {
    "tui": {
      "unit": "WvdS.UI.TUI.Renderers.DateEdit",
      "class": "TWvdSTUIDateEditRenderer"
    },
    "desktop": {
      "unit": "WvdS.UI.Desktop.Renderers.DateEdit",
      "class": "TWvdSDesktopDateEditRenderer"
    },
    "web": {
      "unit": "WvdS.UI.Web.Renderers.DateEdit",
      "class": "TWvdSWebDateEditRenderer"
    }
  },
  "targetCaps": {
    "requires": ["keyboard"],
    "optional": ["mouse", "popup"]
  }
}

Korak 5: Metapodatki načrtovalnika

Ustvarite metapodatke načrtovalnika za orodjarno in lastnosti:

Dodajte deskriptor v: ~/sources/common/core/meta/WvdS.Meta.Controls.Editors.pas

procedure RegisterDateEditMeta(ARegistry: TMetaRegistry);
var
  TypeMeta: TTypeMeta;
begin
  TypeMeta := CreateTypeMeta('DateEdit', 'TWvdSDateEdit', 'Editors');
  TypeMeta.Description := 'Polje za vnos datuma s pojavnim koledarjem';
  TypeMeta.Icon := 'calendar';
 
  (* Lastnosti *)
  TypeMeta.AddProperty(CreatePropertyMeta('Value', pkDateTime, 'Trenutna vrednost datuma'));
  TypeMeta.AddProperty(CreatePropertyMeta('Format', pkString, 'Format prikaza (npr. yyyy-mm-dd)'));
  TypeMeta.AddProperty(CreatePropertyMeta('MinDate', pkDateTime, 'Najzgodnejši dovoljeni datum'));
  TypeMeta.AddProperty(CreatePropertyMeta('MaxDate', pkDateTime, 'Najpoznejši dovoljeni datum'));
  TypeMeta.AddProperty(CreatePropertyMeta('ReadOnly', pkBoolean, 'Način samo za branje'));
 
  (* Dogodki *)
  TypeMeta.AddEvent(CreateEventMeta('OnValueChanged', 'Sproži se ob spremembi Value'));
  TypeMeta.AddEvent(CreateEventMeta('OnValidating', 'Sproži se pred spremembo vrednosti'));
 
  ARegistry.RegisterType(TypeMeta);
end;

Korak 6: Registracija v registru

Registrirajte kontrolnik v izvajalnih registrih:

PXAML razreševalnik

pxamlc prevajalnik samodejno bere pack.wvds.json iz ~/packs/.

Register izvajalnika ciljev

Za vsak cilj posodobite register upodabljalnikov:

(* V WvdS.UI.TUI.Render.Registry.pas *)
procedure RegisterTUIRenderers;
begin
  (* ... drugi upodabljalniki ... *)
  RegisterRenderer(TWvdSDateEdit, TWvdSTUIDateEditRenderer);
end;

Korak 7: Dokumentacija

Ustvarite API dokumentacijo za kontrolnik:

Pot: ~/docs/api/controls/dateedit.md

# TWvdSDateEdit
 
Polje za vnos datuma z opcijskim pojavnim koledarjem.
 
## Kdaj uporabiti
 
- Uporabnik mora vnesti datum
- Omejitev datumskega razpona (MinDate/MaxDate)
- Potreben formatiran prikaz datuma
 
## Lastnosti
 
| Lastnost | Tip | Opis |
|----------|-----|------|
| Value | TDateTime | Trenutna vrednost datuma |
| Format | string | Format prikaza |
| MinDate | TDateTime | Najzgodnejši dovoljeni datum |
| MaxDate | TDateTime | Najpoznejši dovoljeni datum |
| ReadOnly | Boolean | Način samo za branje |
 
## Dogodki
 
| Dogodek | Opis |
|---------|------|
| OnValueChanged | Sproži se ob spremembi Value |
| OnValidating | Omogoča validacijo pred spremembo vrednosti |
 
## Primer
 
```xml
<DateEdit Value="{Binding BirthDate}"
          Format="dd.MM.yyyy"
          MinDate="1900-01-01"
          MaxDate="2100-12-31" />
```

Merila za dokončanje

Kontrolnik je dokončan, ko:

[ ] VS Code Designer lahko postavi {PXAML_NS}:{PXAML_TAG}
[ ] Lastnosti so urejalne v načrtovalniku
[ ] Predogled v načrtovalniku deluje
[ ] Ciljna gradnja (tui/desktop/web) se uspešno prevede
[ ] Pack manifest je prisoten in razreševalnik ga prepozna
[ ] API dokumentacija je napisana

Glejte tudi

Zuletzt geändert: dne 29.01.2026 ob 22:24