Files
webwindowconfigurator/WebWindowComplex/TableComp.razor.cs
T
Annamaria Sassi ea2044c863 - Aggiunto reset shape con eliminazione sash group
- Aggiunto salvataggio tipo richiesta precedente
- Aggiunta gestione famiglia hw se non trovata dopo update shape
2025-11-04 10:42:07 +01:00

1433 lines
52 KiB
C#

using Egw.Window.Data;
using Microsoft.AspNetCore.Components;
using Newtonsoft.Json;
using System.Reflection.Metadata;
using WebWindowComplex.Compo;
using WebWindowComplex.DTO;
using WebWindowComplex.Json;
using WebWindowComplex.Models;
using static WebWindowComplex.LayoutConst;
using static WebWindowComplex.Json.WindowConst;
namespace WebWindowComplex
{
public partial class TableComp : IDisposable
{
#region Public Enums
public enum DataAction
{
/// <summary>
/// Nessuna richiesta
/// </summary>
None = 0,
/// <summary>
/// Reset dizionario shape
/// </summary>
ResetDictShape
}
public enum DataReq
{
/// <summary>
/// Nessuna richiesta
/// </summary>
None = 0,
/// <summary>
/// Richiesta hardware opzioni
/// </summary>
ReqHwOpt,
/// <summary>
/// Richiesta svg
/// </summary>
ReqSvg,
/// <summary>
/// Richiesta shape sash group
/// </summary>
ReqShape
}
#endregion Public Enums
#region Public Properties
/// <summary>
/// Classe override css x SVG (x rescale)
/// </summary>
[Parameter]
public string CssSvg { get; set; } = "responsive-svg";
/// <summary>
/// Preselezione valori
/// </summary>
[Parameter]
public SelectPayload? CurrSelection { get; set; } = null;
/// <summary>
/// Richiesta azione al parent
/// </summary>
[Parameter]
public EventCallback<DataAction> EC_ActionReq { get; set; }
/// <summary>
/// Richiesta update da JWD (SVG, calcoli vari...)
/// </summary>
[Parameter]
public EventCallback<Dictionary<string, string>> EC_DoUpdate { get; set; }
/// <summary>
/// Richiesta chiusura JWD (+ refresh)
/// se torna true --> richiesta salvataggio
/// se torna false --> richiesta revert
/// </summary>
[Parameter]
public EventCallback<bool> EC_OnClose { get; set; }
/// <summary>
/// Evento selezione template
/// </summary>
[Parameter]
public EventCallback<TemplateSelectDTO> EC_OnSelectedTemplate { get; set; }
/// <summary>
/// Sollevo evento errore validazione con una lista di errori rilevati
/// </summary>
[Parameter]
public EventCallback<Dictionary<string, string>> EC_ValidError { get; set; }
/// <summary>
/// Elenco anagrafiche di base
/// </summary>
[Parameter]
public BaseListPayload ListPayload { get; set; } = null!;
/// <summary>
/// Dati live controllo (JWD, SVG, ...)
/// </summary>
[Parameter]
public LivePayload LiveData { get; set; } = null!;
#endregion Public Properties
#region Public Methods
public void Dispose()
{
if (m_CurrWindow != null)
{
m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview;
m_CurrWindow.OnReqHwOption -= M_CurrWindow_OnHwOption;
m_CurrWindow.OnReqShape -= M_CurrWindow_OnShape;
m_CurrWindow = null;
}
}
/// <summary>
/// Cerca e aggiorna la sash
/// </summary>
/// <param name="currentArea"> area corrente che si sta valutando </param>
/// <param name="idSearch"> id della sash che si sta cercando </param>
/// <param name="newSash"> nuova sash </param>
/// <returns></returns>
public Area SearchSash(Area currentArea, int idSearch, Sash newSash)
{
if (currentArea.GroupId == idSearch && currentArea.AreaType.Equals(AreaTypes.SASH))
{
currentArea = newSash;
return currentArea;
}
foreach (Area child in currentArea.AreaList)
{
Area found = SearchSash(child, idSearch, newSash);
if (found != null)
{
return found;
}
}
return null;
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// Dati live precedenti x comparazione
/// </summary>
protected LivePayload? prevLiveData = null;
#endregion Protected Fields
#region Protected Properties
protected List<Fill> FillList
{
get => m_FillList;
}
protected Frame FrameWindow
{
get => m_Frame!;
set => m_Frame = value;
}
protected List<ItemTable> ItemTableList
{
get => m_ItemTableList;
}
/// <summary>
/// Componente SVG da mostrare
/// </summary>
protected MarkupString outSvg
{
get
{
// aggiunta gestione classe svg per posizionamento con costraints
var newSvg = LiveData.SvgPreview.Replace("<svg", $"<svg class=\"{CssSvg}\"");
return (MarkupString)newSvg;
}
}
protected List<Sash> SashList
{
get => m_SashList;
}
protected string SelColorMaterial { get; set; } = "";
protected string SelFamilyHardware { get; set; } = "";
protected string SelGlass { get; set; } = "";
protected string SelMaterial { get; set; } = ""!;
protected string SelProfile { get; set; } = "";
protected TemplateSelectDTO? SelTemplateDTO { get; set; } = null;
protected List<Split> SplitList
{
get => m_SplitList;
}
protected List<Splitted> SplittedList
{
get => m_SplittedList;
}
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Metodo per la scelta della maniglia univoca
/// </summary>
/// <param name="sashDim"> anta su cui si seleziona la maniglia </param>
/// <returns></returns>
protected void changeHandle(DataChangeHandle Args)
{
SashDimension sashDim = Args.currSashDimension;
Sash currSash = Args.currItem;
// Cerco la Sash che si sta considerando nella lista Sash
foreach (Sash s in SashList)
{
if (s.Equals(currSash))
{
// Per ogni anta della Sash setto HasHandle
foreach (SashDimension item in s.SashList)
{
if (item.Equals(sashDim))
{
item.bHasHandle = true;
}
else
{
if (item.bHasHandle)
{
switch (item.SelOpeningType)
{
case Openings.TILTTURN_LEFT:
{
item.SetOpeningType(Openings.TURNONLY_LEFT);
break;
}
case Openings.TILTTURN_RIGHT:
{
item.SetOpeningType(Openings.TURNONLY_RIGHT);
break;
}
default:
{
break;
}
}
}
item.bHasHandle = false;
}
}
}
}
currSash.RefreshHardwareList();
currSash.SetFirstHardware();
_ = DoPreviewSvg();
}
/// <summary>
/// Metodo per la scelta dello split intero nella modalità griglia
/// </summary>
/// <param name="currSplit"> split su cui si sceglie </param>
/// <returns></returns>
protected async Task changeStartVert(DataChangeStartVert Args)
{
ChangeEventArgs e = Args.eventArg;
Split currSplit = Args.currItem;
// Cerco la Sash che si sta considerando nella lista Sash
foreach (Split s in SplitList)
{
if (s.Equals(currSplit))
{
s.SetSplitStartVert((bool)e.Value);
}
}
await DoPreviewSvg();
}
/// <summary>
/// Metodo per riempire la lista ItemTable in modo da poter rappresentarla come tabella
/// </summary>
/// <param name="node"> Area da classificare </param>
/// <param name="row"> numero di riga </param>
/// <param name="col"> numero di colonna </param>
/// <param name="maxRow"> numero di riga massimo </param>
/// <param name="maxCol"> numero di colonna massimo </param>
protected void CreateElementTable(Area node, int row, int col, int maxRow, int maxCol)
{
if (node != null)
{
switch (node.AreaType)
{
case AreaTypes.FRAME:
{
if (node.AreaList.Count >= 1)
ItemTableList.Add(new ItemTable(AreaTypes.FRAME, "FR", row, col, -1, node.AreaList.Count));
else
ItemTableList.Add(new ItemTable(AreaTypes.FRAME, "FR", row, col, -1, 0));
row++;
col++;
maxRow++;
maxCol++;
break;
}
case AreaTypes.SASH:
{
string nWIndow;
// Se ha fratelli
if ((node.ParentArea.ParentArea != null && node.ParentArea.ParentArea.AreaList.Count > 1) ||
(node.ParentArea != null && node.ParentArea.AreaList.Count > 1))
{
for (int i = 0; i < SashList.Count; i++)
{
if (SashList[i].Equals(node))
{
nWIndow = SashList.Count == 1 ? "" : $"{i + 1}";
// Se il nodo ha figli, salvo il numero nell'oggetto
if (node.AreaList.Count >= 1)
ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SG" + nWIndow, maxRow, col, i, node.AreaList.Count));
else
ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SG" + nWIndow, maxRow, col, i, 0));
}
}
maxCol++;
}
else
{
// Se il nodo ha figli, salvo il numero nell'oggetto
if (node.AreaList.Count >= 1)
ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SG", row, col, 0, node.AreaList.Count));
else
ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SG", row, col, 0, 0));
maxCol++;
}
row++;
col++;
maxRow++;
break;
}
case AreaTypes.FILL:
{
if ((node.ParentArea.AreaList.Count > 1 && node.ParentArea.AreaList.First().Equals(node)) ||
(node.ParentArea.ParentArea != null && node.ParentArea.ParentArea.AreaList.Count > 1 && node.ParentArea.ParentArea.AreaList.First().AreaList.First().Equals(node)))
maxCol++;
string nFill;
for (int i = 0; i < FillList.Count; i++)
{
if (FillList[i].Equals(node))
{
nFill = FillList.Count == 1 ? "" : $"{i + 1}";
ItemTableList.Add(new ItemTable(AreaTypes.FILL, "FL" + nFill, maxRow, col, i, 0));
break;
}
}
row++;
col++;
maxRow++;
break;
}
case AreaTypes.SPLIT:
{
// Se il nodo ha fratelli o cugini
if (node.ParentArea.AreaList.Count > 1 || (node.ParentArea.ParentArea != null && node.ParentArea.ParentArea.AreaList.Count > 1))
{
if (node.ParentArea.AreaList.First().Equals(node) || node.ParentArea.ParentArea.AreaList.First().Equals(node))
maxCol++;
for (int i = 0; i < SplitList.Count; i++)
{
if (SplitList[i].Equals(node))
{
string nSplit = SplitList.Count == 1 ? "" : $"{i + 1}";
if (node.AreaList.Count >= 1)
ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP" + nSplit, maxRow, col, i, node.AreaList.Count));
else
ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP" + nSplit, maxRow, col, i, 0));
}
}
}
else
{
for (int i = 0; i < SplitList.Count; i++)
{
if (SplitList[i].Equals(node))
{
string nSplit = SplitList.Count == 1 ? "" : $"{i + 1}";
if (node.AreaList.Count >= 1)
ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP" + nSplit, row, col, i, node.AreaList.Count));
else
ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP" + nSplit, row, col, i, 0));
maxCol++;
}
}
}
row++;
col++;
maxRow++;
break;
}
case AreaTypes.SPLITTED:
{
break;
}
}
foreach (var item in node.AreaList)
{
if (maxRow < m_maxRow)
CreateElementTable(item, row, col, m_maxRow, maxCol);
else
CreateElementTable(item, row, col, maxRow, maxCol);
}
}
if (maxCol > m_maxCol)
{
m_maxCol = maxCol;
}
if (maxRow > m_maxRow)
{
m_maxRow = maxRow;
}
}
/// <summary>
/// Metodo per riempire le liste Sash, Split, Splitted e Fill
/// </summary>
/// <param name="node"> Area da classificare </param>
/// <param name="IntoSash"> Parametro per sapere se si è dentro un'anta </param>
protected void CreateWindowsList(Area node, bool IntoSash)
{
if (node != null)
{
if (node.ParentArea is Sash || IntoSash == true)
IntoSash = true;
switch (node.AreaType)
{
case AreaTypes.FRAME:
{
FrameWindow = (Frame)node;
break;
}
case AreaTypes.SASH:
{
m_SashList.Add((Sash)node);
break;
}
case AreaTypes.FILL:
{
m_FillList.Add((Fill)node);
break;
}
case AreaTypes.SPLIT:
{
m_SplitList.Add((Split)node);
break;
}
case AreaTypes.SPLITTED:
{
if (node.ParentArea is Split && !IntoSash && node.AreaList.First() is Fill)
{
m_SplittedList.Add((Splitted)node);
}
break;
}
}
foreach (var item in node.AreaList)
{
CreateWindowsList(item, IntoSash);
}
}
}
/// <summary>
/// Calcola CSS warning
/// </summary>
/// <param name="fKey"></param>
/// <returns></returns>
protected string cssValid(string fKey)
{
return listWarnings.ContainsKey(fKey) ? "border border-danger" : "";
}
/// <summary>
/// Richiesta chiusura SENZA salvataggio (= restore prev)
/// </summary>
/// <returns></returns>
protected async Task DoClose()
{
editLock = false;
await EC_OnClose.InvokeAsync(false);
}
/// <summary>
/// Richiesta update anteprima SVG
/// </summary>
/// <param name="doForce">Forza richiesta anche con JWD invariato</param>
/// <param name="hideHw">Nasconde hw (def. false) poiché senza è piu rapido</param>
/// <returns></returns>
protected async Task DoPreviewSvg(bool doForce = false, bool hideHw = false)
{
if (m_CurrWindow != null)
{
#if DEBUG
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(false), Formatting.Indented);
var CalcJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(hideHw), Formatting.Indented);
#else
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(false));
var CalcJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(hideHw));
#endif
// verifico variazione JWD
if (!prevJwd.Equals(CurrJwd) || doForce || prevReq != (int)DataReq.ReqSvg)
{
prevJwd = CurrJwd;
prevReq = (int)DataReq.ReqSvg;
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.PREVIEW}");
Args.Add("Jwd", CalcJwd);
await EC_DoUpdate.InvokeAsync(Args);
}
}
}
/// <summary>
/// Richiesta calcolo Options HW da JWD
/// </summary>
/// <param name="groupIdList">Lista degli ID numerici dei gruppi da valutare</param>
/// <returns></returns>
protected async Task DoReqOptHardware(List<int> groupIdList, bool isFirst = false)
{
if (m_CurrWindow != null)
{
#if DEBUG
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(), Formatting.Indented);
#else
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize());
#endif
// verifico variazione JWD
if (!prevJwd.Equals(CurrJwd) || isFirst || prevReq != (int)DataReq.ReqHwOpt)
{
prevJwd = CurrJwd;
prevReq = (int)DataReq.ReqHwOpt;
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.HARDWARE}");
Args.Add("SubMode", $"{(int)Enums.QuestionHwSubModes.HARDWAREOPTIONS}");
Args.Add("Jwd", CurrJwd);
string listGroupId = JsonConvert.SerializeObject(groupIdList);
Args.Add("GroupId", listGroupId);
await EC_DoUpdate.InvokeAsync(Args);
}
}
}
/// <summary>
/// Richiesta Shape compatibile da JWD
/// </summary>
/// <param name="groupIdList">Lista degli ID numerici dei gruppi da valutare</param>
/// <returns></returns>
protected async Task DoReqShape(List<int> groupIdList)
{
if (m_CurrWindow != null)
{
#if DEBUG
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(), Formatting.Indented);
#else
var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize());
#endif
// verifico variazione JWD
if (!prevJwd.Equals(CurrJwd) || prevReq != (int)DataReq.ReqShape)
//if (!prevLiveData.CurrJwd.Equals(CurrJwd))
{
prevJwd = CurrJwd;
prevReq= (int)DataReq.ReqShape;
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.HARDWARE}");
Args.Add("SubMode", $"{(int)Enums.QuestionHwSubModes.SASHSHAPE}");
Args.Add("Jwd", CurrJwd);
string listGroupId = JsonConvert.SerializeObject(groupIdList);
Args.Add("GroupId", listGroupId);
await EC_DoUpdate.InvokeAsync(Args);
}
}
}
/// <summary>
/// Metodo di reset dei dati a quelli del template
/// </summary>
protected async Task DoReset()
{
// Da fare
}
/// <summary>
/// Richiesta chiusura con salvataggio
/// </summary>
/// <returns></returns>
protected async Task DoSave()
{
editLock = false;
//manca salvataggio JWD
await EC_OnClose.InvokeAsync(true);
}
/// <summary>
/// Selezione del template
/// </summary>
/// <param name="newSel"> template selezionato </param>
protected async void DoSelect(TemplateSelectDTO newSel)
{
editLock = false;
SelTemplateDTO = newSel;
await EC_OnSelectedTemplate.InvokeAsync(newSel);
}
protected override void OnAfterRender(bool firstRender)
{
isRendered = true;
}
/// <summary>
/// Primo init componente
/// </summary>
protected override void OnInitialized()
{
// reset editLock...
editLock = false;
listErrPre = new Dictionary<string, string>();
listErrLink = new Dictionary<string, string>();
listWarnings = new Dictionary<string, string>();
}
/// <summary>
/// Gestione update post ricezione parametri da controllo chiamante
/// </summary>
protected override async Task OnParametersSetAsync()
{
isLoading = true;
// SOLO SE sono presenti...
if (ListPayload.IsPopulated() && LiveData.IsValid())
{
bool updRequested = false;
listErrPre = new Dictionary<string, string>();
listErrLink = new Dictionary<string, string>();
listWarnings = new Dictionary<string, string>();
// controllo elenchi BasePayload siano validi...
if (ListPayload.IsValid())
{
// SOLO SE modificato live data...
if (prevLiveData == null || !prevLiveData.Equals(LiveData))
{
bool needDeser = prevLiveData == null || !prevLiveData.JwdEqual(LiveData);
updRequested = true;
prevLiveData = new LivePayload()
{
CurrJwd = LiveData.CurrJwd,
DictOptionsXml = LiveData.DictOptionsXml,
DictShape = LiveData.DictShape,
SvgPreview = LiveData.SvgPreview
};
// Aggiornati parametri di ingresso selezionati
UpdateSelParameter();
// provo a deserializzare SE necessario
if (needDeser)
{
JsonWindow WindowFromJson = new JsonWindow("", "", "", "");
try
{
WindowFromJson = JsonConvert.DeserializeObject<JsonWindow>(LiveData.CurrJwd, new PolymorphicJsonConverter()) ?? new JsonWindow("", "", "", "");
setCurrWindow(WindowFromJson);
//SOLO SE non sono in edit...
if (!editLock)
{
currStep = CompileStep.Tree;
}
}
// altrimenti errore!
catch (Exception ex)
{
listErrLink.Add("Window", $"Deserializing Error:{Environment.NewLine}{ex}");
}
}
else
{
// usando m_currWindow (preesistente) impostare i parametri...
UpdateDict();
}
}
checkWarnings();
if (SashList.Count > 0)
{
currAnta = 0;
}
if (updRequested)
{
// se mancasse dizionario forme chiamo quello
if (LiveData.DictShape.Count == 0)
{
if (firstDisplay && isRendered)
{
firstDisplay = false;
// preview SVG senza HW
await DoPreviewSvg(true, true);
}
List<int> reqList = SashList.Select(x => x.GroupId).ToList();
if (reqList.Count > 0)
{
await DoReqShape(reqList);
}
}
else
{
// chiedo SVG
await DoPreviewSvg(true);
}
}
}
else
{
checkErrorPre();
}
isLoading = false;
}
}
/// <summary>
/// Metodo per costruire oggetti della Window
/// </summary>
/// <param name="WindowFromJson"></param>
protected void setCurrWindow(JsonWindow WindowFromJson)
{
if (m_CurrWindow != null)
{
m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview;
m_CurrWindow.OnReqHwOption -= M_CurrWindow_OnHwOption;
m_CurrWindow.OnReqShape -= M_CurrWindow_OnShape;
m_CurrWindow = null;
}
m_CurrWindow = WindowFromJson.Deserialize();
m_CurrWindow.OnPreview += M_CurrWindow_OnPreview;
m_CurrWindow.OnReqHwOption += M_CurrWindow_OnHwOption;
m_CurrWindow.OnReqShape += M_CurrWindow_OnShape;
// Recupero dimensioni Frame e Joint del frame della finestra precedente
if (m_PreviousWindow != null)
{
for (int i = 0; i < 2; i++)
m_CurrWindow.AreaList.First().DimensionList[i] = m_PreviousWindow.AreaList.First().DimensionList[i];
for (int i = 0; i < 4; i++)
m_CurrWindow.AreaList.First().JointList[i] = m_PreviousWindow.AreaList.First().JointList[i];
}
if (m_CurrWindow != null)
{
// Aggiornamento liste sash, split, splitted, fill e itemTable
UpdateLists();
}
if (SashList.Count > 0)
currAnta = 0;
// Aggiorno window con dati shape e hw option
UpdateDict();
}
protected void UpdateDict()
{
// se ho i dizionari delle forme le aggiungo
if (LiveData.DictShape.Count > 0)
{
// Inserisco le forme ricevuto nei sash group
foreach (var item in LiveData.DictShape)
{
Sash sashFromGroupId = SashList.Where(x => x.GroupId == item.Key).ToList().First();
sashFromGroupId.SashShape = item.Value;
sashFromGroupId.UpdateShape(item.Value);
}
}
// se ho le opzioni hw le aggiungo
if (LiveData.DictOptionsXml.Count > 0)
{
foreach (var item in SashList)
{
if (LiveData.DictOptionsXml.ContainsKey(item.GroupId))
{
item.SetHardwareOption(LiveData.DictOptionsXml[item.GroupId]);
}
}
}
}
/// <summary>
/// Metodo che resetta le liste (sash, split, splitted, fill e itemTable) e le crea nuovamente
/// </summary>
protected void UpdateLists()
{
m_maxCol = 0;
m_maxRow = 0;
m_FillList = new List<Fill>();
m_SashList = new List<Sash>();
m_SplitList = new List<Split>();
m_SplittedList = new List<Splitted>();
m_ItemTableList = new List<ItemTable>();
CreateWindowsList((m_CurrWindow!).AreaList.First(), false);
CreateElementTable(m_CurrWindow.AreaList.First(), 1, 1, 1, 1);
}
/// <summary>
/// Metodo per settare i parmateri di ingresso selezionati
/// </summary>
protected void UpdateSelParameter()
{
Sash.m_HardwareCompleteList = ListPayload.Hardware;
Sash.s_FamilyHardwareList = ListPayload.FamilyHardware;
if (CurrSelection != null && CurrSelection.IsValid())
{
SelFamilyHardware = CurrSelection.FamilyHardware ?? "";
SelColorMaterial = CurrSelection.ColorMaterial ?? "";
SelMaterial = CurrSelection.Material ?? "";
SelGlass = CurrSelection.Glass ?? "";
SelProfile = CurrSelection.Profile ?? "";
}
}
#endregion Protected Methods
#region Private Fields
private int currAnta = 0;
private int currFill = -1;
private int currSash = -1;
private int currSplit = -1;
private CompileStep currStep;
private bool editLock = false;
private bool firstDisplay = true;
/// <summary>
/// Booleana fase loading
/// </summary>
private bool isLoading = false;
private bool isRendered = false;
/// <summary>
/// ELenco errori di coerenza/link dati (vanno risolti per disegnare/procedere)
/// </summary>
private Dictionary<string, string> listErrLink = new Dictionary<string, string>();
/// <summary>
/// Elenco errori preliminari (mancano elementi di base di validazione modello dati))
/// </summary>
private Dictionary<string, string> listErrPre = new Dictionary<string, string>();
/// <summary>
/// Elenco warnings non bloccanti
/// </summary>
private Dictionary<string, string> listWarnings = new Dictionary<string, string>();
private List<Fill> m_FillList = new List<Fill>();
private Frame? m_Frame;
private List<ItemTable> m_ItemTableList = new List<ItemTable>();
private int m_maxCol = 0;
private int m_maxRow = 0;
private List<Sash> m_SashList = new List<Sash>();
private List<Split> m_SplitList = new List<Split>();
private List<Splitted> m_SplittedList = new List<Splitted>();
#endregion Private Fields
#region Private Properties
private Window? m_CurrWindow { get; set; } = null;
private Window? m_PreviousWindow { get; set; } = null;
private string m_SelFamilyHardware { get; set; } = "";
private Template m_SelTemplate { get; set; } = null!;
/// <summary>
/// Salvataggio JWD precedente x evitare loop su update (aggiornato dopo chiamate redis)
/// </summary>
private string prevJwd { get; set; } = "";
/// <summary>
/// Salvataggio tipo di domanda precedente
/// </summary>
private int prevReq { get; set; } = 0;
#endregion Private Properties
#region Private Methods
/// <summary>
/// Metodo per aggiungere una Sash
/// </summary>
/// <param name="Args"></param>
/// <returns></returns>
private void AddSashIntoSplit(DataAreaSplitted Args)
{
Splitted currSplitted = Args.splitted;
currSplitted.AddFirstSash();
// ricalcolo liste
UpdateLists();
// richiedo update shape
List<int> reqList = SashList.Select(x => x.GroupId).ToList();
_ = DoReqShape(reqList);
}
/// <summary>
/// Metodo per aggiungere una sash di default al Frame
/// </summary>
/// <param name="f"></param>
private void AddSashToFrame(Frame f)
{
f.AddFirstSash();
// ricalcolo liste
UpdateLists();
// richiedo update shape
List<int> reqList = SashList.Select(x => x.GroupId).ToList();
_ = DoReqShape(reqList);
}
/// <summary>
/// Metodo per aggiungere uno split di default al Frame
/// </summary>
/// <param name="f"></param>
private void AddSplitToFrame(Frame f)
{
f.AddSplit();
}
/// <summary>
/// Metodo per andare allo step successivo
/// </summary>
/// <param name="newStep"> step successivo </param>
private void AdvStep(CompileStep newStep)
{
currStep = newStep;
currSash = -1;
currFill = -1;
currSplit = -1;
}
/// <summary>
/// Calcola larghezza colonna button nav
/// </summary>
/// <returns></returns>
private string buttonCss()
{
return (currStep == CompileStep.Template) ? "col-4 d-grid gap-1 d-md-flex justify-content-md-end align-items-center" : "col-4 d-grid gap-1 d-md-flex justify-content-md-end align-items-center";
}
/// <summary>
/// Calcola bottone selezionato per il Fill
/// </summary>
/// <returns></returns>
private string buttonFillCss(FillTypes currFillTypes)
{
if (FillList.ElementAt(currFill).SelFillType == currFillTypes)
return "btn btn-secondary btn-sm";
else
return "btn btn-outline-secondary btn-sm";
}
/// <summary>
/// Prima chiamata alle opzioni hardware
/// </summary>
/// <param name="groupId"> Group Id del sash group di cui si vuole Hw option </param>
/// <returns></returns>
private async Task CallFirstHwOpt(int groupId)
{
bool isFirst = true;
List<int> reqList = new List<int>() { groupId };
await DoReqOptHardware(reqList, isFirst);
}
/// <summary>
/// Metodo per settare tutti i Fill in contemporanea
/// </summary>
/// <param name="type"> tipo di riempimento (GLASS o WOOD) </param>
/// <returns></returns>
private async Task ChangeAllFill(FillTypes type)
{
foreach (Fill currFill in FillList)
{
currFill.SetSelFillType(type);
}
await DoPreviewSvg();
}
/// <summary>
/// Metodo per settare tutti i Joints di Frame o Sash come ANGLED o FULL_H o FULL_V
/// </summary>
/// <param name="Args"></param>
/// <returns></returns>
private async Task ChangeAllJoints(DataChangeJoints Args)
{
WindowConst.Joints type = Args.currJointType;
Area area = Args.currArea;
if (area is Frame)
{
foreach (Joint joint in FrameWindow.JointList)
{
joint.SetSelJointType(type);
}
}
else
{
Sash a = (Sash)area;
foreach (Joint joint in a.JointList)
{
joint.SetSelJointType(type);
}
}
await DoPreviewSvg();
}
/// <summary>
/// Metodo per settare tutti i Fill in contemporanea
/// </summary>
/// <param name="type"> tipo di riempimento (GLASS o WOOD) </param>
/// <returns></returns>
private async Task ChangeOneFill(FillTypes type)
{
Fill fillChange = FillList.ElementAt(currFill);
fillChange.SetSelFillType(type);
await DoPreviewSvg();
}
/// <summary>
/// Verifica errori prelimionari per mostrare dove sia il problema
/// </summary>
private void checkErrorPre()
{
// verifico 1:1 le liste e indico cosa manca
if (ListPayload.Hardware == null || ListPayload.Hardware.Count == 0)
{
listErrPre.Add("Hardware", "Missing Hardware List!");
}
else
{
if (ListPayload.FamilyHardware == null || ListPayload.FamilyHardware.Count == 0)
{
listErrPre.Add("FamilyHardware", "Missing Family HW List!");
}
}
if (ListPayload.Glass == null || ListPayload.Glass.Count == 0)
{
listErrPre.Add("Glass", "Missing Glass List!");
}
if (ListPayload.Material == null || ListPayload.Material.Count == 0)
{
listErrPre.Add("Material", "Missing Material List!");
}
if (ListPayload.ColorMaterial == null || ListPayload.ColorMaterial.Count == 0)
{
listErrPre.Add("ColorMaterial", "Missing ColorMaterial List!");
}
if (ListPayload.Profile == null || ListPayload.Profile.Count == 0)
{
listErrPre.Add("Profile", "Missing Profile List!");
}
}
/// <summary>
/// Verifica warning minori (es coerenza colori...)
/// </summary>
private void checkWarnings()
{
// verifico 1:1 le liste e i valori siano coerenti...
if (ListPayload.ColorMaterial != null && ListPayload.ColorMaterial.Count > 0)
{
// verifico colore attuale sia consistente...
if (m_CurrWindow != null)
{
if (!ListPayload.ColorMaterial.Contains(m_CurrWindow.sColorMaterial))
{
listWarnings.Add("ColorMaterial", $"Missing Color: {m_CurrWindow.sColorMaterial}");
}
if (!ListPayload.Glass.Contains(m_CurrWindow.sGlass))
{
listWarnings.Add("Glass", $"Missing Glass: {m_CurrWindow.sGlass}");
}
if (!ListPayload.Material.Contains(m_CurrWindow.sMaterial))
{
listWarnings.Add("Material", $"Missing Material: {m_CurrWindow.sMaterial}");
}
if (!ListPayload.Profile.Contains(m_CurrWindow.sProfilePath))
{
listWarnings.Add("Profile", $"Missing Profile: {m_CurrWindow.sProfilePath}");
}
}
}
}
/// <summary>
/// Metodo per copiare contenuto di un'anta in un'altra anta
/// </summary>
/// <param name="Args"></param>
private async Task CopyContentSash(DataCopyContentSash Args)
{
Sash sashItem = Args.currItem;
int IndexCopy = Args.indexCopy;
int IndexModify = Args.indexModify;
// Anta selezionata
Area sashSplitted = sashItem.AreaList[IndexModify];
// Rimuovo riempimento da anta selezionata
sashSplitted.AreaList.RemoveAt(0);
// Creo la copia dell'anta scelta
Area a = sashItem.AreaList[IndexCopy].AreaList.First().Copy(sashSplitted);
// Aggiungo copia all'anta selezionata
sashItem.AreaList[IndexModify].AreaList.Add(a);
await DoPreviewSvg();
}
/// <summary>
/// Metodo per copiare una Sash intera
/// </summary>
/// <param name="Args"></param>
/// <returns></returns>
private async Task CopySash(DataAreaSplit Args)
{
Splitted currSplitted = Args.splitted;
int numSash = Args.index;
//Rimuovo contenuto di Splitted e rimuovo area da conteggio gruppi
currSplitted.AreaList.RemoveAll(i => i != null);
//Area.DelCounterGroup();
// Copio sash
Area a = SashList[numSash].Copy(currSplitted);
a.SetParentArea(currSplitted);
// Aggiungo copia a Splitted
currSplitted.AreaList.Add(a);
await DoPreviewSvg();
}
/// <summary>
/// Calcola larghezza colonna header nav
/// </summary>
/// <returns></returns>
private string headerCss()
{
return (currStep == CompileStep.Template) ? "col-8 d-grid px-2 d-md-flex justify-content-md-start" : "col-8 d-grid px-2 d-md-flex justify-content-md-start";
}
private void M_CurrWindow_OnHwOption(object? sender, OnReqHwOptEventArgs e)
{
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.HARDWARE}");
Args.Add("SubMode", $"{(int)Enums.QuestionHwSubModes.HARDWAREOPTIONS}");
Args.Add("Jwd", e.sJwd);
string listGroupId = JsonConvert.SerializeObject(new List<int> { e.nGroupId });
Args.Add("GroupId", listGroupId);
_ = EC_DoUpdate.InvokeAsync(Args);
}
private void M_CurrWindow_OnPreview(object? sender, OnPreviewEventArgs e)
{
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.PREVIEW}");
Args.Add("Jwd", e.sJwd);
_ = EC_DoUpdate.InvokeAsync(Args);
}
private void M_CurrWindow_OnShape(object? sender, OnReqShapeEventArgs e)
{
Dictionary<string, string> Args = new Dictionary<string, string>();
Args.Add("Mode", $"{(int)Enums.QuestionModes.HARDWARE}");
Args.Add("SubMode", $"{(int)Enums.QuestionHwSubModes.SASHSHAPE}");
Args.Add("Jwd", e.sJwd);
string listGroupId = JsonConvert.SerializeObject(new List<int> { e.groupId });
Args.Add("GroupId", listGroupId);
_ = EC_DoUpdate.InvokeAsync(Args);
}
/// <summary>
/// Calcola larghezza colonna contenente nav da mostrare
/// </summary>
/// <returns></returns>
private string mainCss()
{
return (currStep == CompileStep.Template) ? "col-12" : "col-6";
}
/// <summary>
/// Metodo per cambiare step
/// </summary>
/// <param name="newStep"> step successivo </param>
private void NextStep(CompileStep newStep, int Index = 1)
{
editLock = true;
currStep = newStep;
switch (newStep)
{
case CompileStep.Sash:
{
currSash = Index;
currFill = -1;
currSplit = -1;
break;
}
case CompileStep.Fill:
{
currFill = Index;
currSash = -1;
currSplit = -1;
break;
}
case CompileStep.Split:
{
currSplit = Index;
currSash = -1;
currFill = -1;
break;
}
}
}
/// <summary>
/// Metodo per cambiare step
/// </summary>
/// <param name="Args"></param>
private void NextStepArgs(DataNextStep Args)
{
CompileStep newStep = Args.currCompileStep;
int Index = Args.index;
NextStep(newStep, Index);
}
/// <summary>
/// Metodo per eliminare Split o Sash
/// </summary>
/// <param name="currArea"> Area corrente </param>
/// <returns></returns>
private void RemoveArea(Area currArea)
{
if (currArea is Split)
((Split)currArea).Remove();
else if (currArea is Sash)
{
((Sash)currArea).Remove();
}
currStep = CompileStep.Tree;
}
/// <summary>
/// Richiesta reset dizionario Shape con action
/// </summary>
/// <param name="args"></param>
/// <exception cref="NotImplementedException"></exception>
private void ReqResetDict(bool args)
{
_ = EC_ActionReq.InvokeAsync(DataAction.ResetDictShape);
}
/// <summary>
/// Ritorno step Tree
/// </summary>
/// <param name="args"></param>
private void ReturnTree(bool args)
{
AdvStep(CompileStep.Tree);
}
/// <summary>
/// Selezione del colore
/// </summary>
/// <param name="newVal"></param>
private void SelectColor(string newVal)
{
if (m_CurrWindow != null)
{
m_CurrWindow.sColorMaterial = newVal;
}
}
/// <summary>
/// Selezione del vetro
/// </summary>
/// <param name="newVal"></param>
private void SelectGlass(string newVal)
{
if (m_CurrWindow != null)
{
m_CurrWindow.sGlass = newVal;
}
}
/// <summary>
/// Selezione del materiale
/// </summary>
/// <param name="newVal"></param>
private void SelectMat(string newVal)
{
if (m_CurrWindow != null)
{
m_CurrWindow.sMaterial = newVal;
}
}
/// <summary>
/// Selezione del profilo
/// </summary>
/// <param name="newVal"></param>
private void SelectProfile(string newVal)
{
if (m_CurrWindow != null)
{
m_CurrWindow.sProfilePath = newVal;
}
}
/// <summary>
/// Metodo per scambiare due aree di uno split
/// </summary>
/// <param name="currArea"> Area corrente </param>
/// <returns></returns>
private async Task SwapTwoAree(Area currArea)
{
currArea.SwapAree();
await DoPreviewSvg();
}
/// <summary>
/// Calcola il css del tab selezionato
/// </summary>
/// <param name="testStep"> Step </param>
/// <returns></returns>
private string tabNavCss(CompileStep testStep, int Index = -1)
{
if (testStep == CompileStep.Sash)
{
if ((currSash == 0 && Index == 0) || (currSash == 1 && Index == 1))
return "nav-link active fw-bold";
else
return "nav-link text-secondary";
}
else if (testStep == CompileStep.Fill)
{
if ((currFill == 0 && Index == 0) || (currFill == 1 && Index == 1))
return "nav-link active fw-bold";
else
return "nav-link text-secondary";
}
else if (testStep == CompileStep.Split)
{
if ((currSplit == 0 && Index == 0) || (currSplit == 1 && Index == 1))
return "nav-link active fw-bold";
else
return "nav-link text-secondary";
}
return (testStep == currStep) ? "nav-link active fw-bold" : "nav-link text-secondary";
}
/// <summary>
/// Aggiornamento Frame
/// </summary>
/// <param name="newFrame"></param>
/// <returns></returns>
private async Task UpdateFrame(Frame newFrame)
{
FrameWindow = newFrame;
await DoPreviewSvg();
}
/// <summary>
/// Aggiornamento opzioni dato update sash
/// </summary>
/// <param name="newSash"> nuova sash </param>
/// <returns></returns>
private async Task UpdateHwOptions(Sash newSash)
{
// richiesta calcolo opzioni hardware per la singola sash group
//string req = newSash.SelHardware.Id;
List<int> reqList = new List<int>() { newSash.GroupId };
// chiamo con gruppo della nuova sash
await DoReqOptHardware(reqList);
}
/// <summary>
/// Aggiornamento Sash e Frame
/// </summary>
/// <param name="newSash"> nuova sash </param>
/// <returns></returns>
private async Task UpdateSash(Sash newSash)
{
SearchSash(FrameWindow, newSash.GroupId, newSash);
await DoPreviewSvg();
}
/// <summary>
/// Aggiornamento Shape x ogni Group di Sash della finestra
/// </summary>
/// <param name="newFrame"></param>
/// <returns></returns>
private async Task UpdateShape(Frame newFrame)
{
FrameWindow = newFrame;
// ciclo x ogni group della mia frame
List<int> reqList = SashList.Select(x => x.GroupId).ToList();
await DoReqShape(reqList);
}
/// <summary>
/// Aggiornamento shape dato GroupId
/// </summary>
/// <param name="groupId"> nuova sash </param>
/// <returns></returns>
private async Task UpdateShape(int groupId)
{
List<int> reqList = new List<int>() { groupId };
await DoReqShape(reqList);
#if false
await DoReqShape(groupId);
#endif
}
#endregion Private Methods
}
}