Avalonia Code OnlyItaliano

From the documentation of RAVAL, the MIT library of the books: the same as in its repository.

This page is available in Italian only for now.

Grafica, conversioni, tabelle, alberi, stili — RAVAL 2.3

Le funzioni che quasi ogni programma Avalonia di misura o di progetto si riscrive: un grafico a curve con i marcatori, i numeri con i prefissi SI, i colori da mescolare, le figure da stampare a 300 dpi, una tabella che si ordina, un elenco di proprietà, uno stile pulito da strumento. Tutto in codice, senza XAML e senza lambda, nel namespace RAVAL.

Spiegazione con un esempio completo (la finestra di misura di un filtro): TUTORIAL.md, capitolo 15. Ogni membro, con la sua firma, è nel riferimento API.md.

Gli eventi si collegano a metodi con un nome: RChart.MarkersChanged (un Action), RTable.SelectionChanged (un Action<int> con la riga, −1 per nessuna), RPropertyList.Changed (un Action<string, string> con il nome e il valore nuovo, solo dopo Invio o l'uscita dalla casella, e solo se il testo è cambiato).

Conversioni — Graphics\RFormat.cs, Graphics\RColor.cs, Graphics\RCsv.cs

MembroFa
RFormat.Si(1.296e9, "Hz")«1.296 GHz»: il prefisso che lascia da 1 a 999 prima del punto, al più digits cifre significative (4)
RFormat.Parse("4k7") · Parse("10 MHz", "Hz") · Parse("5%")rilegge i numeri scritti così, anche con il prefisso al posto della virgola e «u» per micro
RFormat.Round(v, cifre)arrotonda alle cifre significative
RColor.Mix(a, b, t) · Lighten · Darken · WithOpacitycolori mescolati canale per canale
RColor.Hex(c) · RColor.Luminance(c)il testo «#1a7fb5»; la luminanza relativa di WCAG 2 (scritta chiara o scura sopra?)
RColor.Palette · RColor.Series(i)otto colori per le curve, leggibili sul bianco e sul quasi nero
RCsv.Write(intestazioni, colonne...) · RCsv.Write("f", curve) · RCsv.Write(tabella) · RCsv.Read(testo)il CSV con la virgola e il punto; i numeri nel formato «R», che si rileggono identici; le celle con virgole o virgolette fra virgolette (RFC 4180)

Il grafico — Graphics\RChart.cs, RSeries.cs, RLimit.cs, RTicks.cs

var c = new RChart { TitleY = "dB", UnitX = "Hz" };
c.Series.Add(new RSeries("S21", f, s21));
c.Series.Add(new RSeries("misura", f, m, 1) { Dashed = true });
c.Limits.Add(new RLimit(1.27e9, 1.32e9, -1, RAva.Brush("#2b8a3e")) { Label = "S21 > −1" });
c.MarkersChanged += Leggi;          // un metodo senza argomenti
MembroFa
Series, Limits, Markersle curve, i limiti (segmenti orizzontali spessi: gli obiettivi di un ottimizzatore, una maschera) e le ascisse dei marcatori
TitleY, TitleY2, UnitX, LogX, MinY, MaxYtitoli degli assi, unità delle ascisse (scritte con RFormat.Si), ascissa logaritmica, limiti fissi dell'asse sinistro
RSeries.RightAxisla curva usa l'asse destro, che compare da solo
RSeries con il nome vuotosi disegna ma resta fuori dalla legenda e dalle letture dei marcatori: le cento curve di una nuvola Monte Carlo
FormatXcome scrivere le ascisse, se non con i prefissi SI (un gruppo di metodi)
Culturecome scrivere i numeri di assi e marcatori: il punto (invariante) se non si sceglie altro, come RTable e RCsv; CultureInfo.CurrentCulture per la virgola del computer
BackgroundKey, GridKey, InkKeyle risorse del tema dei colori («ChartBack», «ChartGrid», «ChartInk»), con quelli chiari o scuri di riserva
PixelX, PixelY, ValueX, PlotAreada valore a pixel e ritorno, dopo il primo disegno
il mouseun clic mette il primo marcatore, Maiusc+clic ne aggiunge uno, il tasto destro li toglie; ogni marcatore scrive il valore di ogni curva (RSeries.At interpola)
RSeries.Style (Line, Points, LineAndPoints) · PointSize · Sorted · With(x, y)curve, punti o tutti e due; le ascisse in qualunque ordine (solo le curve Sorted si leggono con i marcatori, At per bisezione)
MinX, MaxX · TimeAxislimiti fissi dell'ascissa; le ascisse come tempi (RTime.X(data)), divisioni su secondi, minuti, ore, giorni tondi
rotella, trascinamento, doppio clic · ZoomX, ZoomY, SetView, ResetView, Zoomed, ViewChanged, RangeX, RangeY, ValueYlo zoom intorno al puntatore (Maiusc: l'ordinata), lo spostamento della vista, il ritorno a tutti i dati; il clic fermo resta il marcatore
RLiveSeries(grafico, nome) · Add(x, y) · Add(data, y) · Window · MaxPoints · Drain · Clearuna curva che cresce mentre arrivano i dati, da qualunque thread, ridisegnata a lotti; con Window il grafico segue l'ultimo tratto
RTime.X, Date, Step, Ticks, Label, Longi tempi come ascisse: da data a secondi e ritorno, i passi tondi, le etichette
RTicks.Step, Expand, Linear, Logle divisioni «tonde» 1-2-5 di Heckbert, e 1-2-5 per decade sugli assi logaritmici

Gli altri grafici — Graphics\RSmithChart.cs, RPolarChart.cs, RBarChart.cs, RHeatMap.cs

Spiegati nel capitolo 21 del tutorial (esempio ESEMPI_RAVAL\Esempi\GraficiRF.cs); prove in TEST_RAVAL\ProveGraficiRF.cs. Tutti prendono i colori da «ChartBack», «ChartGrid», «ChartInk» con la riserva chiara o scura (Graphics\RPlot.cs, interno), scrivono i numeri con Culture (il punto) e si salvano con SavePng(file, cm, dpi).

MembroFa
RComplexSeries(nome, punti, frequenze) · RComplexSeries.Pattern(nome, gradi, valori, dB)una curva di complessi (Γ, S21) con le frequenze; un diagramma di radiazione
RSmithChart: Z0, ShowImpedance, ShowAdmittance, MaxGammala carta, le griglie, la carta espansa oltre \Γ\= 1
Series, Circles (RSmithCircle con Dashed e Fill), Markers (RSmithMarker con Frequency e Draggable)curve, cerchi, punti; ogni marcatore scrive frequenza, Z e VSWR (MarkerValues)
MarkerMoved · Move(marcatore, Γ) · Underil trascinamento per accordare; lo stesso da codice; il Γ sotto il puntatore, letto con Γ, Z, Y, VSWR, RL
ZoomAt(punto, fattore) · ResetView() · Zoom · ViewCenter · PixelOf · GammaAtla rotella, il trascinamento della vista, il doppio clic; da Γ a pixel e ritorno
RSmithMath (RF\RSmithMath.cs, senza Avalonia)Gamma, Impedance, Admittance, Vswr, ReturnLoss, Degrees, Polar; cerchi Resistance, Reactance, Conductance, Susceptance, Vswr, Q; OutputStability, InputStability, OutputStableInside, InputStableInside, Rollett; UnilateralGain, Noise
RPolarChart: Decibels, Range, Max, ZeroAngle, Clockwise, AngleStepmodulo e fase, o dB con il centro Range dB sotto il bordo; zero in alto e verso orario per le antenne
RBarChart: Categories, Series (RBarSeries), Stacked, ShowValues, Unit, BarRectbarre affiancate o impilate, i negativi verso il basso, il valore in cima
RHeatMap: SetValues(m, x0, x1, y0, y1), Scale (RColorScale), Min, Max, Smooth, ValueAt, ColorOfla matrice come immagine, con la barra della scala e il valore sotto il puntatore; NaN trasparente

La carta di Smith e il grafico polare vengono da ASTRIP (MIT), tradotti in inglese e completati con zoom, letture dei marcatori, regioni colorate, dB e orientamento.

Le figure — Graphics\RImage.cs

RImage.SavePng(controllo, file, larghezza, altezza, dpi) disegna un controllo, anche senza finestra, a qualunque risoluzione, e scrive i dpi nel PNG (RImage.SetDpi per i PNG fatti altrove, RImage.Dpi per leggerli). RImage.Dip(8) è la larghezza in dip di una figura stampata larga 8 cm, che a 300 dpi diventa 945 pixel. È il modo di fare nitide le figure dei libri (la regola: almeno 300 dpi alla misura di stampa).

Tabelle ed elenchi — UI\RTable.cs, UI\RPropertyList.cs

var t = new RTable().Columns("Parte", "Valore:R", "Note");
t.AddRow("C1", "1.5p", "ceramico").AddRow("L1", "10n");
t.SelectionChanged += Mostra;       // un metodo con un int

var p = new RPropertyList().Add("C", "1.5p").Add("ESR", "0.1");
p.Changed += Applica;               // un metodo (string nome, string valore)
  • RTable: «:R» in fondo a un'intestazione allinea la colonna a destra, «:C» al centro. Un clic sull'intestazione ordina (per valore se ogni cella è un numero, anche con il prefisso SI; se no in ordine alfabetico), un secondo clic rovescia; un clic su una riga la sceglie. È una Grid di TextBlock: va bene per decine o centinaia di righe.
  • RPropertyList: nomi a sinistra, valori in caselle a destra; Changed arriva con Invio o quando la casella perde il fuoco, solo se il testo è cambiato davvero.
    • Show(oggetto) elenca le proprietà pubbliche che stanno in una casella (testi, numeri, sì/no, enum) e scrive nell'oggetto i valori confermati, convertiti con RPropertyList.Convert (numeri come RFormat, anche «1 MHz»). Un testo che non si converte è rifiutato: Rejected con il motivo.
    • Si leggono gli attributi DisplayName, Description, ReadOnly e Browsable; Reload() rilegge l'oggetto; Target è l'oggetto mostrato.
  • RVirtualTable (UI\RVirtualTable.cs): la tabella per diecimila o centomila righe, che costruisce solo le righe visibili (un ListBox virtualizzato).
    • LoadCsv(testo), con la prima riga come intestazioni e le colonne numeriche a destra; AddRow e AddRows.
    • Sort(colonna, discendente), per valore o alfabetico; Filter, le righe con una cella che contiene il testo.
    • Rows (tutte), Shown (quelle mostrate), SelectedIndex sempre in Rows, SelectionChanged.
    • SetWidth(colonna, dip); Text() dà le righe con le tabulazioni, per gli appunti.
    • Centomila righe si aprono in un terzo di secondo e si ordinano in due decimi.
  • RFormat.TryParse(testo, out valore): Parse senza eccezioni, che scarta subito i testi che non cominciano come un numero. Parse senza unità indicata ora legge anche «10 MHz» (1e7) e «5 V» (5).

L'albero — UI\RTree.cs, UI\RTreeNode.cs

Spiegato nel capitolo 17 del tutorial, con l'esempio ESEMPI_RAVAL\Esempi\Albero.cs; prove in TEST_RAVAL\ProveAlbero.cs.

RTree t = RTree.FromJson(testo);                 // i membri in cima; FromXml: la radice
t.Searchable = true;                             // la casella di ricerca
t.SelectionChanged += Scelto;                    // void Scelto(RTreeNode? n)
t.Opened += Apri;                                // doppio clic o Invio
t.Add(RTreeNode.FromFolder("C:\\"));             // le cartelle si leggono quando si aprono
t.Select(t.Find("componenti[1].valore", "."));
MembroFa
new RTreeNode(testo, valore) · Add(figli...) · Removeun nodo con i figli aggiunti; il valore si vede tenue accanto al testo
new RTreeNode(testo, Caricatore) · Reload()i figli letti dal caricatore la prima volta che servono, e di nuovo dopo Reload
Key · Path(separatore) · Child(chiave) · Descendants()il pezzo di percorso (il testo, se non cambiato); «server.port», «items[2].name»; il figlio con quella chiave; i nodi già letti, senza chiamare i caricatori
Tag · Color · Iteml'oggetto del programma (l'RNode da cui è nato, il percorso del file); il colore del testo; la voce sullo schermo, se c'è già
RTreeNode.FromJson · FromXml · FromNode · FromFolderletti con RNode (scheda RDati.md): oggetti «{n}» e liste «[n]» con le foglie, elementi con gli attributi «@nome» e il testo; cartelle prima dei file, con la misura
RTree.FromJson · FromXml · LoadJson · LoadXml · LoadNodeil controllo già pieno, o lo stesso controllo con un altro testo o un RNode
Roots · Add · Remove · Cleari nodi in cima
Selected · Select(nodo) · SelectionChanged · Openedla scelta: Select apre la strada e porta il nodo in vista
Expand · Collapse · ExpandAll(livelli) · CollapseAllaprire e chiudere; ExpandAll chiama i caricatori che incontra
Find(percorso, separatore)il nodo a un percorso scritto come lo scrive Path
Filter · Found · Searchable · SearchBoxi nodi con le parole nel testo o nel valore, con quelli sopra (aperti) e sotto; quanti; la casella di ricerca e il suo testo segnaposto

Le voci (TreeViewItem) si costruiscono solo quando il nodo sopra si apre: al loro posto c'è una voce finta che fa vedere la freccia. Un caricatore che lancia un'eccezione dà un figlio rosso con il messaggio e una riga Warning nel log. Il filtro non chiama i caricatori: cerca fra i figli già letti.

Stile — UI\RStyles.cs, UI\RAvaLook.cs

public override void Initialize() {
  Styles.Add(new FluentTheme { DensityStyle = DensityStyle.Compact });
  RStyles.Clean().Apply(this);
  RStyles.Accent(this, Color.Parse("#1f5fa8"), Color.Parse("#5b9be0"));
}
MembroFa
new RStyles().For<Button>("toolbar").Set(prop, valore)...Apply(app)stili globali scritti in codice: il selettore si costruisce con Selectors.OfType e Selectors.Class, senza la lambda di new Style(x => ...)
RStyles.Clean()l'insieme pronto: schede a 13 punti (Fluent le fa da 24), bottoni con gli angoli tondi, Button.toolbar piatto, Button.small per le tavolozze, TextBlock.caption per i titoli delle sezioni, TextBox.code a spaziatura fissa, alberi ed elenchi compatti
stili.Apply(controllo)gli stili su un solo controllo e su quello che contiene, non su tutta l'applicazione
RStyles.Accent(app, chiaro, scuro)il colore d'accento di Fluent nei due temi, con le tre tinte più chiare e più scure che Fluent usa per il passaggio del mouse e la pressione
RAva.Caption, RAva.Card, RAva.Bar, RAva.ToolbarButton, RAva.CodeBoxi pezzi di un'interfaccia pulita: titolo di sezione, riquadro arrotondato, barra degli strumenti o di stato, bottone piatto, casella di codice

Perché è fatta così

  • I numeri si scrivono come li legge un tecnico. Su un asse «1.296 GHz» si legge, «1296000000» no; e chi scrive «4k7» in una cella deve poterlo rileggere. RFormat è usato dal grafico e dalla tabella (che ordina per valore anche le celle con i prefissi).
  • Il grafico è disegnato a mano, come la carta di Smith del libro: nessuna dipendenza, ogni pixel si può spiegare in un capitolo, e senza schermo si prova con il mouse finto (TEST_RAVAL\ProveGrafica.cs).
  • Le risorse dei colori hanno sempre una riserva. Un'applicazione che non definisce «ChartBack» vede comunque un grafico chiaro o scuro giusto.

Inciampi

  • Una risorsa che manca toglie lo sfondo, e con lo sfondo il clic. Uno sfondo legato con Resource a una chiave che l'applicazione non ha resta nullo, e un Border senza sfondo non riceve il mouse: le righe a strisce di RTable non si potevano scegliere nell'applicazione di prova, che chiama i colori in italiano. Ora la striscia è solo dipinta e il clic va a un Border trasparente sopra di lei.
  • Bitmap.Save(percorso) è obsoleto in Avalonia 12: si passa PngBitmapEncoderOptions.Default, se no l'avviso (che nei progetti con gli avvisi come errori ferma la compilazione).
  • Il nome Border dentro RAva è il metodo, non la classe: in RAvaLook.cs si scrive Avalonia.Controls.Border.BackgroundProperty (lo stesso inciampo di RAva.cs).
  • A 300 dpi le scritte dopo un ritaglio sparivano. Una RenderTargetBitmap creata a 300 dpi perdeva ogni testo disegnato dopo la chiusura di un PushClip: il grafico esportato per il libro non aveva né la legenda né i valori dei marcatori, mentre sullo schermo e a 96 dpi c'erano. Non dipende dal renderer di composizione (succede anche chiamando Render a mano). RImage crea la bitmap a 96 dpi con i pixel della risoluzione voluta e mette la scala come trasformazione: stessi pixel, tutto disegnato. Poi scrive nel PNG la risoluzione vera (il blocco pHYs, 11811 pixel al metro per 300 dpi), che i libri chiedono. La prova conta i pixel scritti nell'angolo della legenda (TEST_RAVAL/ProveGrafica.cs).
  • Nel disegno a mano l'opacità non la mette nessuno. RImage percorre l'albero visuale da sé, e fino alla 2.5.0 saltava solo gli elementi del tutto trasparenti: un testo con Opacity = 0.6 usciva pieno. Ora ogni elemento con opacità minore di 1 si disegna dentro un PushOpacity; la prova controlla che un rettangolo nero al 50% su bianco esca grigio (TEST_RAVAL/ProveCorrezioni.cs).