docs: conventii COMUN (cautare vcx/vct, encoding cp1252, goExecutor ALTER TABLE, UX formulare)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
139
docs/cautare_vcx_vct.md
Normal file
139
docs/cautare_vcx_vct.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
||||||
|
|
||||||
|
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder,
|
||||||
|
care e varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
||||||
|
|
||||||
|
Cum se caută cod-sursă (proceduri, metode, parametri) care **nu** stă în fișiere `.prg`, ci
|
||||||
|
în interiorul fișierelor binare VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`),
|
||||||
|
rapoarte (`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
|
||||||
|
|
||||||
|
## De ce e nevoie de asta
|
||||||
|
|
||||||
|
Un `.vcx` este de fapt o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. Un
|
||||||
|
`grep` direct pe `.vct` *găsește* textul, dar îl vede ca fișier binar (octeți `\0` între linii),
|
||||||
|
fără numere de linie utile și greu de citit. Soluția: convertim binarul în reprezentarea lui
|
||||||
|
**TEXT** (`.vc2`, `.sc2`, …) — un PRG-style lizibil, cu metode sortate alfabetic — și căutăm
|
||||||
|
în text cu `grep`/`Grep`.
|
||||||
|
|
||||||
|
> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru
|
||||||
|
> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi
|
||||||
|
> `PROMPT_cautare_vfp.md` pasul 3 pentru fluxul complet (ordine obligatorie, encoding,
|
||||||
|
> fidelity check). Pentru `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot
|
||||||
|
> în **IDE-ul VFP**.
|
||||||
|
|
||||||
|
## Unelte disponibile (verificate)
|
||||||
|
|
||||||
|
| Unealtă | Cale | Rol | Recomandare |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Complet, fidel, include corpul metodelor, parametri, comentarii |
|
||||||
|
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` *compilabil* | Alternativă; mai vechi, doar clase, necesită IDE VFP deschis pentru a rula forma |
|
||||||
|
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (e direcția opusă) |
|
||||||
|
|
||||||
|
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
||||||
|
toate tipurile de container, și produce text mult mai fidel decât vcx2prg.
|
||||||
|
|
||||||
|
> Dacă `FoxBin2Prg.EXE` lipsește, se compilează o singură dată: deschide
|
||||||
|
> `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și *Build > Build Executable*. Lângă EXE trebuie
|
||||||
|
> să existe `filename_caps.exe` și fișierele `props*.txt` (sunt deja în folder).
|
||||||
|
|
||||||
|
## Mod recomandat: scriptul `vcx2txt.ps1`
|
||||||
|
|
||||||
|
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` automatizează tot: copiază binarul + memo-ul într-un
|
||||||
|
**cache** care oglindește structura proiectului (ca să nu murdărească arborele SVN), rulează
|
||||||
|
FoxBin2Prg, păstrează doar fișierul text. E **incremental** (sare peste ce e deja la zi).
|
||||||
|
|
||||||
|
Parametrizează scriptul cu proiectul curent și un cache separat per proiect (nu amesteca
|
||||||
|
cache-urile mai multor proiecte ROA):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
|
||||||
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||||
|
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||||
|
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>'
|
||||||
|
|
||||||
|
# include și rapoartele (.frx) și meniurile (.mnx)
|
||||||
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||||
|
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||||
|
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Types vcx,scx,frx,mnx
|
||||||
|
|
||||||
|
# conversie punctuală a unui fișier sau folder (chiar dacă NU e în proiect, ex. o clasă din COMUN)
|
||||||
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '<RADACINA_PROIECT>\COMUN\clase\caut.vcx'
|
||||||
|
|
||||||
|
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
|
||||||
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||||
|
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||||
|
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Clean
|
||||||
|
```
|
||||||
|
|
||||||
|
Exemplu concret (ROAAUTO):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||||
|
-Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO `
|
||||||
|
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_roaauto
|
||||||
|
```
|
||||||
|
|
||||||
|
Rezultatul ajunge în cache-ul indicat, cu aceeași structură de directoare ca proiectul (ex.:
|
||||||
|
`_textcache_roaauto\Clase\odevize.vc2`, `_textcache_roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# cu unealta Grep (preferat) sau grep:
|
||||||
|
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>"
|
||||||
|
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>" # ce clase ating subiectul
|
||||||
|
```
|
||||||
|
|
||||||
|
Flux tipic pentru o problemă: rulează scriptul cu parametrii de mai sus o dată (populează
|
||||||
|
cache-ul), apoi caută cu `Grep` în cache. La sesiuni următoare rescrie doar ce s-a schimbat
|
||||||
|
(incremental). Dacă ai nevoie de o librărie din `COMUN\` care nu e în proiect, convertește-o
|
||||||
|
punctual cu `-Source`.
|
||||||
|
|
||||||
|
## Alternativă manuală (fără script)
|
||||||
|
|
||||||
|
FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului,
|
||||||
|
copiază perechea binar+memo într-un folder temporar și convertește acolo:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG)
|
||||||
|
Copy-Item D:\ROA\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\Clase\odevize.vct D:\tmp\
|
||||||
|
& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1'
|
||||||
|
# => D:\tmp\odevize.vc2
|
||||||
|
```
|
||||||
|
|
||||||
|
Pozițiile parametrilor folosite: `fișier, cType, cTextName, lGenText, cDontShowErrors=1,
|
||||||
|
cDebug=0, cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția.
|
||||||
|
(Nu da explicit `"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
|
||||||
|
|
||||||
|
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
|
||||||
|
|
||||||
|
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
|
||||||
|
|
||||||
|
Pentru o verificare rapidă „există metoda X undeva în librărie?", `grep` merge direct pe `.vct`
|
||||||
|
(o vede ca binar, dar găsește potrivirile):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||||
|
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||||
|
```
|
||||||
|
|
||||||
|
Bun pentru „da/nu" și nume de metode; pentru citit corpul/contextul, folosește conversia în text.
|
||||||
|
|
||||||
|
## Corespondență extensii binar → text
|
||||||
|
|
||||||
|
| Container | Binar (+memo) | Text |
|
||||||
|
|---|---|---|
|
||||||
|
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
|
||||||
|
| Formă | `.scx` + `.sct` | `.sc2` |
|
||||||
|
| Raport | `.frx` + `.frt` | `.fr2` |
|
||||||
|
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
|
||||||
|
| Meniu | `.mnx` + `.mnt` | `.mn2` |
|
||||||
|
| Bază de date | `.dbc` + `.dct` | `.dc2` |
|
||||||
|
|
||||||
|
## Note
|
||||||
|
|
||||||
|
- Codul aplicației stă mai ales în `Clase\*.vcx`; o mare parte din `.vcx`-uri sunt în
|
||||||
|
`COMUN\` (framework partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
||||||
|
- Cache-ul text e regenerabil și e în afara arborelui SVN/git al proiectului — poate fi șters
|
||||||
|
oricând.
|
||||||
|
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).
|
||||||
|
- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la
|
||||||
|
editarea `.sc2`/`.vc2` (nu doar la căutare).
|
||||||
82
docs/conventie_encoding_cp1252.md
Normal file
82
docs/conventie_encoding_cp1252.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
|
||||||
|
|
||||||
|
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md` din acest folder) — capcana
|
||||||
|
ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg, nu de un proiect anume.
|
||||||
|
|
||||||
|
Descoperit de 2 ori în aceeași sesiune (2026-07-10, în ROAAUTO): odată în
|
||||||
|
`COMUN/clase/cmd_butoane.vc2` (clasa `cmd_select_adv`), odată în `Clase/ofundal_dev.vc2`
|
||||||
|
(meniul principal) — de fiecare dată un agent anterior a editat text-cache-ul cu un tool care
|
||||||
|
nu scrie cp1252 nativ, și a corupt TOATE caracterele cu diacritice din fișier, nu doar linia
|
||||||
|
pe care voia s-o schimbe.
|
||||||
|
|
||||||
|
## De ce se întâmplă
|
||||||
|
|
||||||
|
Fișierele `.sc2`/`.vc2` generate de FoxBin2Prg sunt **cp1252 (Windows-1252)**, nu UTF-8
|
||||||
|
(vezi antetul fiecărui fișier: `CPID="1252"`). Dacă un editor/tool citește fișierul ca UTF-8
|
||||||
|
(sau alt encoding), fiecare byte >= 0x80 (diacritic) devine invalid ca secvență UTF-8 și e
|
||||||
|
înlocuit cu caracterul de replacement U+FFFD. Dacă apoi tool-ul **salvează rezultatul tot ca
|
||||||
|
UTF-8**, acel U+FFFD e scris ca 3 octeți UTF-8 (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca
|
||||||
|
cp1252 (cum face FoxBin2Prg la write-back), apar ca `�`. Rezultatul: caracterul original e
|
||||||
|
**ireversibil pierdut** (nu mai există în fișier sub nicio formă) — recuperabil DOAR din altă
|
||||||
|
sursă (git history, backup).
|
||||||
|
|
||||||
|
Codebase-ul ROA folosește un hack vechi de "reciclare" a unor caractere cp1252 needependente
|
||||||
|
de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice românești:
|
||||||
|
|
||||||
|
| Literă românească | Caracter folosit (cp1252) | Byte |
|
||||||
|
|---|---|---|
|
||||||
|
| ă | ã (a-tilde) | `0xE3` |
|
||||||
|
| Ă | Ã | `0xC3` |
|
||||||
|
| ț | þ (thorn minuscul) | `0xFE` |
|
||||||
|
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
|
||||||
|
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
|
||||||
|
| î, â | î, â (existente nativ în cp1252) | `0xEE`, `0xE2` |
|
||||||
|
|
||||||
|
Aceste caractere par "gunoi"/typo la prima vedere într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) —
|
||||||
|
**sunt corecte, nu le "corecta" fără să verifici encoding-ul.**
|
||||||
|
|
||||||
|
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$bytes = [System.IO.File]::ReadAllBytes("<path>.vc2")
|
||||||
|
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
|
||||||
|
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
|
||||||
|
```
|
||||||
|
|
||||||
|
Dacă apare `�` (sau `$text` conține U+FFFD) în output — fișierul are corupere de encoding.
|
||||||
|
|
||||||
|
## Cum se repară
|
||||||
|
|
||||||
|
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul
|
||||||
|
curent.
|
||||||
|
2. Dacă fișierul e sub control de versiune (git) și corupera s-a întâmplat **într-o sesiune
|
||||||
|
anterioară necomisă** (deci HEAD-ul git încă are versiunea curată): recuperează originalul
|
||||||
|
convertind binarul din HEAD în text și comparând:
|
||||||
|
```bash
|
||||||
|
git show HEAD:<cale>.vcx > /tmp/head.vcx
|
||||||
|
git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz)
|
||||||
|
powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out
|
||||||
|
```
|
||||||
|
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
|
||||||
|
linie (PowerShell, nu `diff` direct — `diff`/Bash nu decodează cp1252 corect pentru afișare,
|
||||||
|
deși detectează totuși diferența de octeți).
|
||||||
|
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), și reaplică DOAR
|
||||||
|
modificările intenționate din sesiunea curentă peste ea (nu invers — nu încerca să "cârpești"
|
||||||
|
fișierul corupt caracter cu caracter, e mai sigur să repornești de la baza curată).
|
||||||
|
4. Scrie rezultatul înapoi ca bytes cp1252 (`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`),
|
||||||
|
NU ca string UTF-8/`Out-File` implicit (care scrie UTF-8 sau UTF-16 după caz).
|
||||||
|
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
||||||
|
|
||||||
|
## Cum se evită pe viitor
|
||||||
|
|
||||||
|
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
|
||||||
|
conține diacritice (`ã`, `þ`, `ª`, `º`, `î`, `â` etc.) — dacă da, **orice rescrie completă a
|
||||||
|
fișierului trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând
|
||||||
|
UTF-8 implicit. Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul
|
||||||
|
păstrează restul fișierului byte-identic (nu rescrie tot fișierul reîncodat).
|
||||||
|
|
||||||
|
## Vezi și
|
||||||
|
|
||||||
|
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează deja riscul ("Headerul
|
||||||
|
CPID="1252" poate minți...") pe scurt; acest fișier e detalierea completă (tabel de caractere,
|
||||||
|
pași de recuperare din git).
|
||||||
65
docs/conventie_goexecutor_alter_table.md
Normal file
65
docs/conventie_goexecutor_alter_table.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()`
|
||||||
|
|
||||||
|
Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în
|
||||||
|
`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru
|
||||||
|
interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*.
|
||||||
|
|
||||||
|
## Ce nu funcționează
|
||||||
|
|
||||||
|
```foxpro
|
||||||
|
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
|
||||||
|
...
|
||||||
|
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
||||||
|
```
|
||||||
|
|
||||||
|
Cursorul întors de `oExecute()` (rezultatul unui `SQLExec`) poate refuza comenzi DDL
|
||||||
|
ulterioare, cu erori în lanț (descoperite empiric, în această ordine, în ROAAUTO
|
||||||
|
`autopass_cursor_comenzi`/`autopass_cursor_operatii`):
|
||||||
|
|
||||||
|
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul
|
||||||
|
original.
|
||||||
|
2. Chiar și după o încercare de rematerializare (`SELECT * FROM (cursor) INTO CURSOR
|
||||||
|
(acelasi_nume) READWRITE`) → `Alias name is already in use.` (sursa și ținta nu pot
|
||||||
|
avea același nume într-un `SELECT...INTO CURSOR`).
|
||||||
|
3. Cu un alias scratch diferit ca țintă (`SELECT * FROM (cursor) INTO CURSOR
|
||||||
|
(nume_final_diferit_de_sursa) READWRITE`) → tot `Invalid operation for the cursor.` pe
|
||||||
|
`ALTER TABLE`, chiar dacă acum cursorul final teoretic ar trebui să fie unul local
|
||||||
|
obișnuit.
|
||||||
|
|
||||||
|
Nu există niciun alt loc în codul ROA* care să facă `ALTER TABLE` imediat după
|
||||||
|
`goExecutor.oExecute()` — deci acest pattern nu avea niciun precedent testat înainte de
|
||||||
|
funcțiile AUTOPASS.
|
||||||
|
|
||||||
|
## Ce funcționează
|
||||||
|
|
||||||
|
**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele
|
||||||
|
suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*`
|
||||||
|
(VFP suportă `SELECT *, expr AS coloana FROM ...`):
|
||||||
|
|
||||||
|
```foxpro
|
||||||
|
lcCursorRaw = lcCursor + '_raw'
|
||||||
|
IF USED(lcCursorRaw)
|
||||||
|
USE IN (lcCursorRaw)
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
lnSucces = goExecutor.oExecute(lcSql, lcCursorRaw)
|
||||||
|
IF lnSucces < 0
|
||||||
|
* tratare eroare, RETURN
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
SELECT *, .F. AS coloananoua, SPACE(100) AS altacoloana ;
|
||||||
|
FROM (lcCursorRaw) INTO CURSOR (lcCursor) READWRITE
|
||||||
|
USE IN (lcCursorRaw)
|
||||||
|
|
||||||
|
* de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor)
|
||||||
|
```
|
||||||
|
|
||||||
|
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
|
||||||
|
normal pe el DUPĂ ACEEA (ex. dintr-o altă funcție care primește cursorul deja gata construit,
|
||||||
|
nu direct rezultatul unui `oExecute`), doar comanda imediat următoare unui `oExecute()` e
|
||||||
|
restricționată.
|
||||||
|
|
||||||
|
## Vezi și
|
||||||
|
|
||||||
|
Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`,
|
||||||
|
`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`.
|
||||||
48
docs/conventie_ux_formulare.md
Normal file
48
docs/conventie_ux_formulare.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
||||||
|
|
||||||
|
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md`, `prompt_project_insights_docs.md`
|
||||||
|
din acest folder) — pentru că `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul
|
||||||
|
corect pentru o convenție de design care nu ține de un singur proiect.
|
||||||
|
|
||||||
|
Origine: confirmat de Marius pe `frm_autopass.scx` (ROAAUTO) după o rundă de regrupare vizuală
|
||||||
|
(2026-07-10) — "imi place designul acesta" pe layout-ul cu rânduri clar separate pe funcție,
|
||||||
|
butoane grupate la margini, fără elemente lipite unele de altele.
|
||||||
|
|
||||||
|
## Ce înseamnă in practică, pe proprietăți VFP
|
||||||
|
|
||||||
|
- **Fiecare grup funcțional pe rândul lui** — nu înghesui controale fără legătură directă pe
|
||||||
|
același `Top`. Ex: rândul de perioadă (date + Actualizează) separat de rândul de
|
||||||
|
statistici (Declarabile/Transmise/Blocate), separat de panoul de configurare.
|
||||||
|
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din
|
||||||
|
aceeași acțiune (ex. Validează dry-run → Transmite → Renunță) la 6-10px unele de altele;
|
||||||
|
gap de 20-30px față de următorul grup funcțional (ex. Selectează tot vs. grupul
|
||||||
|
Validare/Transmitere vs. Actualizează statusuri).
|
||||||
|
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**,
|
||||||
|
nu lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting vizual ca
|
||||||
|
acțiune separată de câmpul de input.
|
||||||
|
- **Acțiunea principală + oprirea ei alăturate** — un buton de tip "Renunță/Oprește" trebuie
|
||||||
|
poziționat lângă acțiunea pe care o anulează (ex. Transmite + Renunță), nu împrăștiat în
|
||||||
|
altă parte a rândului.
|
||||||
|
- **Un singur rând de acțiuni cât se poate** — dacă mai multe grupuri de butoane încap pe
|
||||||
|
lățimea formei, preferă un singur rând orizontal în loc să adaugi rânduri noi dedesubt;
|
||||||
|
păstrează formele compacte pe verticală.
|
||||||
|
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE";
|
||||||
|
"Dashboard AutoPass" nu "Deschide dashboard AUTOPASS". ALL CAPS/text lung pe un buton
|
||||||
|
citește ca zgomot, nu ca ierarhie.
|
||||||
|
- **Culoare = semnal, nu decor** — folosește culoare distinctă doar pentru acțiuni cu
|
||||||
|
semnificație clară (verde = acțiune pozitivă/transmite, roșu = oprire/pericol, albastru =
|
||||||
|
navigare/deschidere link extern); restul butoanelor rămân stilul implicit din `_baza.vcx`.
|
||||||
|
|
||||||
|
## Vocabular
|
||||||
|
|
||||||
|
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, aer aerisit,
|
||||||
|
modern — asta e reperul calitativ pentru orice formular nou sau refacere de layout, dincolo de
|
||||||
|
regulile mecanice de mai sus, pe orice aplicație ROA*.
|
||||||
|
|
||||||
|
## Vezi și
|
||||||
|
|
||||||
|
- `PROMPT_cautare_vfp.md` din acest folder — cum se caută/editează cod în binarele VFP text-cache
|
||||||
|
(relevant când aplici aceste reguli prin fluxul `.sc2`/`.vc2` + write-back).
|
||||||
|
- Capcana de encoding cp1252 la editarea `.sc2`/`.vc2` (corupere diacritice) — documentată în
|
||||||
|
proiectul unde a fost descoperită (ROAAUTO `docs/conventie_encoding_cp1252.md`); relevantă ori
|
||||||
|
de câte ori editezi text-cache-ul unui formular/librărie pentru a aplica aceste reguli de UX.
|
||||||
Reference in New Issue
Block a user