ROZPISKY.md §3 popisuje nové rozhraní (KresliciStav, Vypln, rozšířený TextStyle) a hlavně *proč* barva nese původ, ne jen RGB. Přibyla tabulka DXF entit, které se čtou, a seznam známých omezení — inline kódy MTEXTu, zarovnání Aligned/Fit, typy čar, dohledávání vzoru šrafy v CADu. Opraveno tvrzení, že tloušťka čáry je jen Layer.LineWeight; zapisuje se i na entitu. CLAUDE.md doplněno druhé pravidlo architektury: co má přežít cestu DXF → model → DXF, musí protéct rozhraním — obcházet ho zpátky na CadDocument šablony je porušení toho prvního. Baseline testů 57 → 114 (i v subagentech). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
306 lines
19 KiB
Markdown
306 lines
19 KiB
Markdown
# Rozpisky – generátor výkresových rohových razítek (C# / .NET)
|
||
|
||
Standalone WPF aplikace (náhrada původního excelového nástroje „Rozpisky 1.0.8"). Spravuje projekt,
|
||
seznam příloh, revize a číselníky, a z **DXF šablony rozpisky** generuje **náhled**, **PDF na A4**,
|
||
**hromadný DXF** (pole jako `TEXT`/`MTEXT` entity), **seznam příloh do XLSX** a přes připojený CAD
|
||
i **tisk rozvržení**.
|
||
|
||
Celé kreslení stojí na jedné myšlence: existuje jedno **kreslicí rozhraní**
|
||
([`IProfileRenderer`](../Rozpisky/Rendering/IProfileRenderer.cs) – „kam se kreslí") a několik jeho
|
||
implementací. Tatáž kresba teče na obrazovku (náhled), do PNG, do PDF i do DXF. Čtečka šablony
|
||
([`DxfTemplate`](../Rozpisky/Dxf/DxfTemplate.cs)) jen čte DXF a „přehrává" ho do tohoto rozhraní.
|
||
|
||
---
|
||
|
||
## 1. NuGet balíčky
|
||
|
||
Cílový framework: **`net10.0-windows`**, `UseWPF=true`, platforma **AnyCPU**. Připojení na běžící CAD
|
||
a MS Excel jde přes COM (pozdní vazba přes `dynamic`) – bitness běhového procesu se řídí hostitelem,
|
||
zvláštní `PlatformTarget` se nenastavuje.
|
||
|
||
| Balíček | Verze | K čemu | Klíčové API |
|
||
|---|---|---|---|
|
||
| **SkiaSharp** | `2.88.8` | 2D rasterizace + **PDF**. Kreslení geometrie/textu/obrázků; export PNG i PDF. | `SKCanvas`, `SKPaint`, `SKPath`, `SKBitmap`, `SKImage`, `SKTypeface`, `SKDocument.CreatePdf`, `SKFileWStream` |
|
||
| **SkiaSharp.Views.WPF** | `2.88.8` | WPF plátno pro živý náhled (zoom/posun). **Jen pro GUI** – headless export ho nepotřebuje. | `SKElement`, `OnPaintSurface(SKPaintSurfaceEventArgs)` |
|
||
| **ACadSharp** | `3.6.29` | Čtení i **zápis** DXF (novější verze, výplně HATCH, XRecord metadata atributů). Nahradilo dřívější netDxf. | `DxfReader.Read`, `DxfWriter.Write`, `CadDocument`, `ACadSharp.Entities.*`, `ACadSharp.Tables.TextStyle` |
|
||
| **ClosedXML** | `0.105.0` | Vyplnění mustru „Seznam příloh" (`SEZNAM.xlsx`) při exportu seznamu. | `XLWorkbook`, `IXLWorksheet`, `Cell(...).Value`, `SaveAs` |
|
||
|
||
> **Pozn. k ACadSharp:** na rozdíl od netDxf vystaví font ze stylu i box-šířku víceřádkových atributů
|
||
> (XRecord, group 41), takže jde dlouhý text v poli správně zalomit. DXF se zapisuje **binárně**
|
||
> (`DxfWriter.Write(..., binary: true)`) – výrazně menší soubor. Převod XLSX → PDF (tisk seznamu) jde
|
||
> přes **nainstalovaný MS Excel** (COM), ne přes ACadSharp/ClosedXML.
|
||
|
||
### Zápis DXF – co je potřeba vědět
|
||
|
||
- **Tloušťka čáry** je enum v 1/100 mm (standardní hodnoty
|
||
`0,5,9,13,15,18,20,25,30,35,40,50,53,60,70,80,90,100,106,120,140,158,200,211`); zapisuje se
|
||
na hladinu (`Layer.LineWeight`) i na entitu, která ji přebíjí. Milimetry z kreslicího rozhraní
|
||
se přichytí k nejbližší standardní hodnotě.
|
||
- **Barva** se zapisuje ve stejném druhu, v jakém přišla ze zdroje: indexovaná číslem (group 62),
|
||
přímá jako RGB (group 420), `ByLayer`/`ByBlock` odkazem. Zplošťování na RGB by výkres v CADu
|
||
odřízlo od tabulky barev.
|
||
- **Diakritika** se do DXF ukládá jako Unicode escape `\U+XXXX` (např. `š` → `\U+0161`) – AutoCAD
|
||
i ostatní čtečky to čtou správně.
|
||
- Pole, která byla v šabloně `ATTDEF`, se při vyplnění zapisují jako obyčejné `TEXT`/`MTEXT` entity
|
||
(žádné atributy bloku).
|
||
- Objekty v netisknutelných hladinách (`PlotFlag=0`) se **nevykreslují**, ale ví se o nich kvůli
|
||
místům pro loga (viz [`DxfTemplate.PlaceholderHladiny`](../Rozpisky/Dxf/DxfTemplate.cs)).
|
||
|
||
---
|
||
|
||
## 2. Struktura kódu
|
||
|
||
Aplikace je členěná dle vrstev (MVVM + služby):
|
||
|
||
```
|
||
Rozpisky/
|
||
├─ Rendering/ ← kreslicí vrstva (nezávislá na cíli)
|
||
│ ├─ IProfileRenderer.cs ← kreslicí rozhraní + HAlign/VAlign + TextStyle + Vypln
|
||
│ ├─ SkiaProfileRenderer.cs ← výstup přes SkiaSharp (obrazovka / PNG / PDF)
|
||
│ ├─ DxfProfileRenderer.cs ← výstup do DXF (ACadSharp)
|
||
│ ├─ BoundsRenderer.cs ← spočítá bbox kresby (fit / umístění na A4)
|
||
│ ├─ TransformRenderer.cs ← dekorátor: afinní transformace (fit loga, rozvinutí bloku)
|
||
│ ├─ KresliciStav.cs ← barva s původem (ACI/RGB/ByLayer), hladina, typ čáry, tloušťka
|
||
│ └─ AciPaleta.cs ← indexované barvy AutoCADu (ACI 0–255) → RGB
|
||
├─ Dxf/ ← čtení šablony, mapování hodnot, kódy
|
||
│ ├─ DxfTemplate.cs ← načte DXF šablonu a přehraje ji do IProfileRenderer
|
||
│ ├─ SrafaVzor.cs ← rozvine vzor šrafy (ANSI31 apod.) na čáry
|
||
│ ├─ RozpiskaRenderer.cs ← spojuje šablonu + hodnoty + exportéry (fasáda pro UI)
|
||
│ ├─ RozpiskaValues.cs ← „tag DXF → hodnota" z projektu/přílohy/číselníků (reflexí dle mapovani.json)
|
||
│ ├─ MapovaniStore.cs ← načtení mapování z mapovani.json (config vedle .exe)
|
||
│ ├─ KodPrilohy.cs ← 47-poziční strojový kód přílohy (manuál SŽ kap. 3)
|
||
│ ├─ Exporters.cs ← PngA4 / PdfA4 / RenderView (kreslí libovolný Action<IProfileRenderer>)
|
||
│ └─ LogaResolver.cs ← dohledání DXF log/schémat k příloze
|
||
├─ Cad/ ← připojení na běžící CAD (COM) + aktualizace/tisk rozvržení
|
||
├─ Xlsx/ ← export seznamu příloh (ClosedXML) + XLSX→PDF (Excel COM)
|
||
├─ Data/ ← persistence: .rzp projekt, číselníky, atomický zápis configů
|
||
├─ Models/ ← datový model (Projekt, Priloha, Revize, Ciselniky, Nastaveni…)
|
||
├─ ViewModels/ ← MainViewModel (stav, akce, dirty-flag, export)
|
||
├─ Views/ + Themes/ + Theming/ + Behaviors/ ← WPF UI (dark theme, grid chování)
|
||
├─ App.xaml(.cs) ← vstupní bod + globální záchytná síť výjimek (error.log)
|
||
└─ MainWindow.xaml(.cs) ← hlavní okno
|
||
```
|
||
|
||
Datové soubory jsou rozdělené podle toho, kdo je vlastní:
|
||
|
||
| Kde | Co | Kdo zapisuje |
|
||
|---|---|---|
|
||
| vedle `.exe` (zdroj `Rozpisky/Podklady/`) | `Rozpiska.dxf`, `SEZNAM.xlsx`, `ciselniky.vychozi.json`, `mapovani.json`, `loga/`, manuál SŽ (PDF) | nikdo – dodává se s programem, každá instalace přepíše |
|
||
| `%APPDATA%\Rozpisky` ([`UzivatelskaData`](../Rozpisky/Data/UzivatelskaData.cs)) | `ciselniky.user.json`, `cad.json`, `layout.json`, `error.log`, `tisk_diag.log`, `loga/` (vlastní loga uživatele) | aplikace a uživatel |
|
||
| kdekoli u uživatele | projekty `.rzp` | aplikace na vyžádání |
|
||
|
||
Rozdělení existuje proto, aby přeinstalace novou verzí (nebo `.exe` v `Program Files`, kam se nesmí
|
||
psát) nesmazala nic, co si uživatel nastřádal. Portable režim se zapíná souborem `portable.txt`
|
||
vedle `.exe` – pak se všechno vrátí do složky aplikace.
|
||
|
||
---
|
||
|
||
## 3. Kreslicí rozhraní
|
||
|
||
Vše se kreslí ve **výkresových milimetrech**, osa **Y nahoru** (jako v CAD/DXF).
|
||
|
||
```csharp
|
||
public enum HAlign { Left, Center, Right }
|
||
public enum VAlign { Baseline, Bottom, Middle, Top }
|
||
|
||
public enum BarvaDruh { ByLayer, ByBlock, Index, True }
|
||
public readonly record struct Barva(BarvaDruh Druh, byte Index, int Rgb);
|
||
public readonly record struct HladinaStav(string Nazev, Barva Barva, string TypCary = "Continuous",
|
||
double TloustkaMm = 0, bool Tisknout = true, bool Zapnuta = true);
|
||
public readonly record struct KresliciStav(HladinaStav Hladina, Barva Barva,
|
||
string? TypCary = null, double? TloustkaMm = null);
|
||
|
||
public readonly record struct TextStyle(string? FontFamily = null, bool Bold = false, bool Italic = false,
|
||
string? FontFile = null, double ObliqueDeg = 0,
|
||
string? Nazev = null, bool JeShx = false);
|
||
|
||
public readonly record struct Usecka(double X1, double Y1, double X2, double Y2);
|
||
public readonly record struct Vypln(string? Vzor = null, double Meritko = 1, double UhelDeg = 0,
|
||
IReadOnlyList<Usecka>? Cary = null);
|
||
|
||
public interface IProfileRenderer
|
||
{
|
||
void Stav(in KresliciStav s);
|
||
void Line(double x1, double y1, double x2, double y2);
|
||
void Polyline(IReadOnlyList<(double X, double Y)> pts, bool closed = false);
|
||
void Circle(double cx, double cy, double r);
|
||
void Stroke(Contour c); // obrys se zachovanými oblouky
|
||
void Text(double x, double y, string text, double heightMm,
|
||
HAlign h = HAlign.Left, VAlign v = VAlign.Baseline, double rotationDeg = 0,
|
||
TextStyle style = default, double widthFactor = 1, double maxWidthMm = 0);
|
||
void Fill(IReadOnlyList<Contour> loops, Vypln vypln = default); // HATCH výplně (even-odd)
|
||
}
|
||
```
|
||
|
||
**Proč `KresliciStav` a ne `int rgb`.** Šablona i všech 9 log jsou zapsané výhradně
|
||
**indexovanými barvami AutoCADu** (group 62). Kdyby rozhraní neslo jen výsledné RGB, export by
|
||
z nich udělal natvrdo true color (group 420), výkres by v CADu přestal reagovat na tabulku barev
|
||
a `ByLayer` by se rozpadlo na kopie barvy hladiny. Barva proto nese **původ**, ne jen hodnotu:
|
||
rastrové renderery si vyžádají hotové RGB přes `RgbProKresbu()`, DXF export zapíše původní druh.
|
||
Ze stejného důvodu se přenáší celý popis hladiny – ve výstupu se staví z tabulky hladin, ne
|
||
z první entity, která na ní přistála.
|
||
|
||
- **Paleta ACI** ([`AciPaleta`](../Rozpisky/Rendering/AciPaleta.cs)) je vlastní, ne z ACadSharp:
|
||
ta se od AutoCADu liší u 33 indexů, mimo jiné u 8 (v šabloně použitý) a u posledního indexu
|
||
většiny desítek odstínů, kde vrací barvu ze sousední skupiny (29 a 39 mají dokonce tutéž).
|
||
Rozsah 10–249 se dopočítává, ne vypisuje: 24 odstínů × 5 jasů × 2 sytosti.
|
||
- `TextStyle.Nazev` = jméno stylu ve zdroji („Popis základní"). Nese se dál, aby ho export zapsal
|
||
beze změny – jeden zdrojový styl = jeden styl ve výstupu.
|
||
- `widthFactor` = horizontální měřítko písma (DXF width factor). `maxWidthMm` = šířka pro zalomení
|
||
víceřádkového textu (0 = jen explicitní zlomy).
|
||
- **Bílá se kreslí černě** (bílá na bílém papíře by zmizela) – jen v rastrových rendererech;
|
||
do DXF jde barva beze změny.
|
||
|
||
Implementace:
|
||
|
||
- **`SkiaProfileRenderer`** – kreslí na `SKCanvas`. Dostane funkci `Map(mmX, mmY) → bod plátna`
|
||
a `pxPerMm`. Text vzpřímeně (rotace opačně, plátno má Y dolů), fonty ze stylu/souboru s fallbackem.
|
||
Je `IDisposable` (uvolní typefaces) – používat přes `using`.
|
||
- **`DxfProfileRenderer`** – staví ACadSharp entity do `Document`; hladiny, textové styly i barvy
|
||
podle zdroje. Verze výstupu je zafixovaná (`VerzeVystupu`), ať ji neurčí default balíčku.
|
||
Výsledek zapíše `DxfWriter.Write(path, renderer.Document, binary: true)`.
|
||
- **`BoundsRenderer`** – nic nekreslí, jen sčítá min/max souřadnic (fit / vystředění na A4).
|
||
- **`TransformRenderer`** – dekorátor s afinní transformací: měřítko + posun (umístění loga do
|
||
rámečku), nebo měřítko os + natočení + posun (rozvinutí bloku, `ProBlok`). Oblouk zůstane
|
||
obloukem jen u podobnosti bez zrcadlení – jinak by z kružnice byla elipsa, kterou rozhraní nezná,
|
||
a tvar se rozloží na lomenou čáru.
|
||
|
||
### Které DXF entity se čtou
|
||
|
||
| Entita | Jak se kreslí |
|
||
|---|---|
|
||
| `LINE`, `CIRCLE`, `ARC` | přímo; oblouk analyticky, hladký v každém přiblížení |
|
||
| `LWPOLYLINE`, `POLYLINE` (2D) | lomená čára, s `bulge` jako obrys s kruhovými oblouky |
|
||
| `POLYLINE` (3D) | promítnuto do roviny XY |
|
||
| `SPLINE` | lomená čára, dílek ≈ 0,3 mm podle délky řídicího polygonu |
|
||
| `ELLIPSE` | lomená čára (rozhraní zná jen kruhové oblouky) |
|
||
| `TEXT`, `MTEXT`, `ATTDEF` | text se stylem, zarovnáním, sklonem a šířkovým faktorem |
|
||
| `HATCH` | plná výplň, nebo vzor rozvinutý na čáry ([`SrafaVzor`](../Rozpisky/Dxf/SrafaVzor.cs)) |
|
||
| `SOLID`, `3DFACE` | vyplněný čtyřúhelník (v DXF jsou 3. a 4. roh prohozené) |
|
||
| `POINT` | tečka |
|
||
| `INSERT` | rekurzivně rozvinutý blok: vztažný bod, měřítko os, natočení, `ByBlock` barvy |
|
||
| ostatní | nekreslí se, ale **spočítá se** do `DxfTemplate.NezpracovaneEntity`; souhrn exportu to vypíše |
|
||
|
||
### Známá omezení
|
||
|
||
- **Vnitřní formátovací kódy MTEXTu** (`\H` výška, `\C` barva, `\f` font, `\S` zlomek) se ztrácejí –
|
||
čte se `MText.PlainText`, který je odstraňuje. Zvlášť se čte jen `\W` (šířkový faktor), protože
|
||
ho ACadSharp v `PlainText` nechává a jinak by se vykreslil jako text.
|
||
- **Zarovnání textu `Aligned` / `Fit`** se aproximuje na `Left` – text se neroztáhne na cílovou délku.
|
||
- **Typ čáry** se přenáší jako název, ale rastrové renderery kreslí vždy plnou čáru; čárkované styly
|
||
se projeví až v DXF (v dodávaných souborech je stejně všude `Continuous`).
|
||
- **Šrafy** se do DXF zapisují se jménem vzoru, měřítkem a úhlem, ale bez definice čar vzoru – CAD
|
||
si ji dohledá ve svých `.pat`. Vzor, který cílový CAD nezná, se v něm nevykreslí.
|
||
|
||
---
|
||
|
||
## 4. Čtečka šablony a fasáda pro UI
|
||
|
||
Nízkoúrovňová čtečka [`DxfTemplate`](../Rozpisky/Dxf/DxfTemplate.cs):
|
||
|
||
```csharp
|
||
var tpl = new DxfTemplate("Rozpiska.dxf");
|
||
tpl.Replay(g); // NÁHLED: pole se vykreslí jako jejich názvy (tagy)
|
||
tpl.Replay(g, values); // VYPLNĚNÍ: pole = hodnota; nevyplněné = prázdné
|
||
tpl.Replay(g, values, includeNoPrint); // + volitelně A4 rámeček !!NOPRINT (pro DXF export/tisk)
|
||
```
|
||
|
||
`Replay` přehraje statickou geometrii (`Line`/`Polyline`), popisky (`Text`/`MText`) a pole
|
||
(`ATTDEF` z model space) do rozhraní. `SheetFrame` vrací A4 rámeček šablony (referenční obdélník pro
|
||
vystředění), `Placeholders` vrací rámečky pro loga/schéma podle vyhrazených hladin, `Bounds` bbox
|
||
kresby (pro fit vkládaného fragmentu).
|
||
|
||
Fasáda pro UI [`RozpiskaRenderer`](../Rozpisky/Dxf/RozpiskaRenderer.cs) spojuje šablonu, mapování hodnot
|
||
a exportéry na jedno místo (šablona se cachuje):
|
||
|
||
```csharp
|
||
var r = new RozpiskaRenderer(Nastaveni.SablonaDxf);
|
||
Action<IProfileRenderer> draw = r.BuildDraw(projekt, priloha, revize, ciselniky,
|
||
vyplnene: true, loga, ramecekA4: false);
|
||
r.ExportPdf(projekt, priloha, revize, ciselniky, "rozpiska.pdf", loga); // A4 PDF vč. log
|
||
r.ExportPng(projekt, priloha, revize, ciselniky, "nahled.png", loga); // A4 PNG
|
||
```
|
||
|
||
Hodnoty polí sestavuje [`RozpiskaValues`](../Rozpisky/Dxf/RozpiskaValues.cs): mapování „pole programu →
|
||
DXF atribut" **není v kódu**, čte se z `mapovani.json` a hodnoty se dotahují reflexí. K tomu se
|
||
algoritmicky doplní 47-poziční strojový kód (`K1`–`K47`, viz
|
||
[`KodPrilohy`](../Rozpisky/Dxf/KodPrilohy.cs)).
|
||
|
||
---
|
||
|
||
## 5. Export na A4 (`Exporters`)
|
||
|
||
[`Exporters`](../Rozpisky/Dxf/Exporters.cs) vykreslí **libovolný** `Action<IProfileRenderer>`:
|
||
|
||
```csharp
|
||
Exporters.PngA4(draw, "rozpiska.png", dpi: 200, frame: sheetFrame); // A4 raster
|
||
Exporters.PdfA4(draw, "rozpiska.pdf", frame: sheetFrame); // A4 vektor (PDF, 1:1)
|
||
Exporters.RenderView(canvas, wpx, hpx, draw, frame, zoom, panX, panY); // živý náhled na SKElement
|
||
```
|
||
|
||
Princip A4: referenční obdélník (`frame` = A4 rámeček šablony, jinak `BoundsRenderer`) se mapuje
|
||
**1:1** a vystředí na papír; zmenší se jen tehdy, když se do tisknutelné plochy nevejde. PDF se kreslí
|
||
přes `SKDocument.CreatePdf` (1 mm = 72/25,4 bodu; text vektorový, tloušťky v reálných mm).
|
||
|
||
---
|
||
|
||
## 6. Demo data (`DemoData`)
|
||
|
||
[`DemoData`](../Rozpisky/Data/DemoData.cs) naplní úvodní stav při startu:
|
||
`SeedProjekt(vm)` (ukázkový projekt + přílohy), `SeedCiselniky(c)` a `SeedKraje(c)` (výchozí
|
||
číselníky, pokud `ciselniky.json` chybí).
|
||
|
||
---
|
||
|
||
## 7. Toky exportu (přehled)
|
||
|
||
| Akce | Vstup | Výstup | Přes |
|
||
|---|---|---|---|
|
||
| Náhled rozpisky | příloha | okno se SKElement | `RozpiskaRenderer.BuildDraw` → `Exporters.RenderView` |
|
||
| Export do PDF (výběr/vše) | přílohy | `Rozpisky\*.pdf` | `RozpiskaRenderer.ExportPdf` (per-item, chyby se sbírají) |
|
||
| Export do DXF (hromadně) | přílohy | `__ Otevřená\_rozpisky.dxf` | dlaždicová mřížka do `DxfProfileRenderer` → `DxfWriter.Write` |
|
||
| Export seznamu | objekt | `SEZNAM_<objekt>.xlsx` vedle .rzp | `SeznamExporter` (ClosedXML mustr) |
|
||
| Tisk seznamu | dřív exportovaný XLSX | `Přílohy\*.pdf` | `ExcelToPdf` (MS Excel COM) |
|
||
| Aktualizace/tisk rozvržení | přílohy | přejmenování/tisk v CADu | `Cad/CadLayoutService`, `Cad/CadTiskService` (COM) |
|
||
|
||
Aplikace **nemá CLI režim** – vše jede z GUI. Neočekávané výjimky zachytává globální síť v
|
||
[`App.xaml.cs`](../Rozpisky/App.xaml.cs) a zapisuje je do `error.log` vedle .exe.
|
||
|
||
---
|
||
|
||
## 8. Persistence a robustnost
|
||
|
||
- **Projekt `.rzp`** ([`ProjektStore`](../Rozpisky/Data/ProjektStore.cs)) – JSON s exkluzivním zámkem
|
||
drženým po dobu otevření (ostatní procesy smí jen číst). Zápis serializuje **před** useknutím
|
||
souboru, aby pád nezanechal prázdný soubor.
|
||
- **JSON configy** (`ciselniky.user.json`, `cad.json`, `layout.json` v uživatelské složce,
|
||
`mapovani.json` vedle .exe) jdou přes [`JsonConfigFile`](../Rozpisky/Data/JsonConfigFile.cs):
|
||
**atomický zápis** (přes `.tmp`) a při poškozeném souboru **záloha do `.bak` + upozornění**
|
||
(místo tichého přepsání výchozími daty).
|
||
- **Číselníky ve dvou vrstvách** ([`CiselnikyStore`](../Rozpisky/Data/CiselnikyStore.cs)) – dodávaná
|
||
`ciselniky.vychozi.json` (jen ke čtení) a uživatelská `ciselniky.user.json`, kde je uložený jen
|
||
**rozdíl** proti ní (přidané/upravené položky + klíče skrytých). Nová verze programu tak smí
|
||
dodávaný číselník měnit, aniž by uživatel přišel o svoje záznamy.
|
||
- **Migrace starých poloh** ([`Migrace`](../Rozpisky/Data/Migrace.cs)) – data zapisovaná dřív vedle
|
||
.exe se při startu přenesou do uživatelské složky; originál se jen přejmenuje na `.migrovano`.
|
||
- **Loga ve dvou složkách** ([`LogaResolver`](../Rozpisky/Dxf/LogaResolver.cs)) – hledá se nejdřív
|
||
v uživatelské `loga\`, pak v dodávané; nabídka v UI je sjednocením obou.
|
||
- **Zamčený cíl exportu** – před zápisem PDF/XLSX/DXF se ověří, zda soubor nedrží jiný program
|
||
(Excel, prohlížeč PDF), a nabídne Pokračovat/Přerušit.
|
||
|
||
---
|
||
|
||
## 9. Závislost na šabloně
|
||
|
||
Šablona je libovolný DXF, kde:
|
||
- rám a mřížku tvoří `LINE` / `LWPOLYLINE`,
|
||
- pevné popisky jsou `TEXT` / `MTEXT`,
|
||
- **vyplňovaná pole jsou `ATTDEF`** v model space (jejich `Tag` = klíč do hodnot),
|
||
- placeholdery pro loga jsou uzavřené polylinie na vyhrazených netisknutelných hladinách
|
||
(`Rozpiska_logo1`…, `Rozpiska_Orientační schéma`) – logo/schéma se fitne do jejich ohraničení,
|
||
samotný placeholder se nekreslí (`PlotFlag=0`),
|
||
- A4 hranici papíru vymezuje rámeček na hladině `!!NOPRINT`.
|
||
|
||
Tím je celý vzhled rozpisky daný **datovým souborem a mapováním** (`Rozpiska.dxf` + `mapovani.json`),
|
||
ne kódem – pro jinou rozpisku stačí jiný DXF a mapování.
|