using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Reflection.Metadata; using System.Runtime.InteropServices; using WebWindow.Base; using WebWindowComplex.DTO; using WebWindowComplex.Json; using static WebWindowComplex.Json.WindowConst; namespace WebWindowComplex { public partial class TableComp : IDisposable { #region Public Properties [Parameter] public string CssSvg { get; set; } = "responsive-svg"; [Parameter] public EventCallback EC_OnClose { get; set; } [Parameter] public EventCallback EC_OnSelectedTemplate { get; set; } [Parameter] public EventCallback> EC_OnUpdate { get; set; } [Parameter] public string CurrJwd { get => m_CurrJwd; set { // Se viene passato un JWD if (m_CurrJwd != value && value != "") { m_CurrJwd = value; // Aggiornati parametri di ingresso selezionati UpdateSelParameter(); JsonWindow WindowFromJson = JsonConvert.DeserializeObject(m_CurrJwd, new PolymorphicJsonConverter()) ?? new JsonWindow("", "", "", ""); if (m_CurrWindow != null) { m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview; m_CurrWindow = null; } m_CurrWindow = WindowFromJson.Deserialize(); m_CurrWindow.OnPreview += M_CurrWindow_OnPreview; // Recupero dimensioni Frame e Joint del frame della finestra precedente if (m_PreviousWindow != null) { for (int i = 0; i < 2; i++) m_CurrWindow.AreaList[0].DimensionList[i] = m_PreviousWindow.AreaList[0].DimensionList[i]; for (int i = 0; i < 4; i++) m_CurrWindow.AreaList[0].JointList[i] = m_PreviousWindow.AreaList[0].JointList[i]; } } if (m_CurrWindow != null) { // Aggiornate liste di sash, split, splitted, fill e itemTable UpdateLists(); } } } [Parameter] public Template IN_SelTemplate { get => m_SelTemplate; set { // Se viene passato il template selezionato oppure se non è ancora stato selezionato un template oppure se si cambia template di selezione if (value != null && (m_SelTemplate == null || (m_SelTemplate != null && value.nIndex != m_SelTemplate.nIndex)) && !string.IsNullOrEmpty(value.JWD)) { m_SelTemplate = value; // Aggiornamento parametri di ingresso selezionati UpdateSelParameter(); JsonWindow WindowFromJson = JsonConvert.DeserializeObject(m_SelTemplate.JWD, new PolymorphicJsonConverter()) ?? new JsonWindow("", "", "", ""); if (m_CurrWindow != null) { m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview; m_CurrWindow = null; } m_CurrWindow = WindowFromJson.Deserialize(); m_CurrWindow.OnPreview += M_CurrWindow_OnPreview; // Recupero dimensioni Frame e Joint del frame della finestra precedente if (m_PreviousWindow != null) { for (int i = 0; i < 2; i++) m_CurrWindow.AreaList[0].DimensionList[i] = m_PreviousWindow.AreaList[0].DimensionList[i]; for (int i = 0; i < 4; i++) m_CurrWindow.AreaList[0].JointList[i] = m_PreviousWindow.AreaList[0].JointList[i]; } } if (m_CurrWindow != null) { // Aggiornamento liste sash, split, splitted, fill e itemTable UpdateLists(); } } } [Parameter] public List IN_TemplateDTOList { get; set; } = null!; [Parameter] public List IN_FamilyHardwareList { get; set; } = null!; [Parameter] public string IN_SelFamilyHardware { get; set; } = null!; [Parameter] public List IN_HardwareList { get; set; } = null!; [Parameter] public List IN_ColorMaterialList { get; set; } = null!; [Parameter] public string? IN_SelColorMaterial { get; set; } = null; [Parameter] public List IN_MaterialList { get; set; } = null!; [Parameter] public string? IN_SelMaterial { get; set; } = null; [Parameter] public List IN_GlassList { get; set; } = null!; [Parameter] public string? IN_SelGlass { get; set; } = null; [Parameter] public string LiveSVG { get => m_SelSVG; set => m_SelSVG = value; } #endregion Public Properties #region Public Methods public void Dispose() { if (m_CurrWindow != null) { m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview; m_CurrWindow = null; } } #endregion Public Methods #region Protected Enums protected enum CompileStep { Template = 0, Gerarchia = 1, Frame, Split, Sash, Fill, General } protected enum PositionJoints { BL = 0, // Bottom Left BR = 1, // Bottom Right TR, // Top Right TL // Top Left } #endregion Protected Enums #region Protected Properties protected Frame FrameWindow { get => m_Frame!; set => m_Frame = value; } protected string? m_CurrJwd { get; set; } protected string m_SelSVG { get; set; } = ""; /// /// Componente SVG da mostrare /// protected MarkupString outSvg { get { // aggiunta gestione classe svg per posizionamento con costraints var newSvg = LiveSVG.Replace(" SashList { get => m_SashList; } protected List SplitList { get => m_SplitList; } protected List FillList { get => m_FillList; } protected List SplittedList { get => m_SplittedList; } protected List ItemTableList { get => m_ItemTableList; } protected TemplateSelectDTO? SelTemplateDTO { get; set; } = null; protected string SelFamilyHardware { get { return m_SelFamilyHardware; } set { m_SelFamilyHardware = value; Sash.s_SelFamilyHW = value; for (int i = 0; i < SashList.Count; i++) { SashList[i].RefreshHardwareList(); SashList[i].RefreshHardwareOptionList(); SashList[i].SetFirstHardware(); } if (m_CurrWindow != null) { m_CurrWindow.OnUpdatePreview(m_CurrWindow.sSerialized()); } } } protected string SelColorMaterial { get; set; } = ""; protected string SelMaterial { get; set; } = ""!; protected string SelGlass { get; set; } = ""; #endregion Protected Properties #region Protected Methods protected override async Task OnInitializedAsync() { if (string.IsNullOrEmpty(CurrJwd)) { currStep = CompileStep.Template; } else { currStep = CompileStep.Gerarchia; } await DoPreviewSvg(); } /// /// Metodo che resetta le liste (sash, split, splitted, fill e itemTable) e le crea nuovamente /// protected void UpdateLists() { m_maxCol = 0; m_maxRow = 0; m_FillList = new List(); m_SashList = new List(); m_SplitList = new List(); m_SplittedList = new List(); m_ItemTableList = new List(); CreateWindowsList((m_CurrWindow!).AreaList[0], false); CreateElementTable(m_CurrWindow.AreaList[0], 1, 1, 1, 1); } /// /// Metodo per settare i parmateri di ingresso selezionati /// protected void UpdateSelParameter() { SelFamilyHardware = IN_SelFamilyHardware; SelColorMaterial = IN_SelColorMaterial ?? ""; SelMaterial = IN_SelMaterial ?? ""; SelGlass = IN_SelGlass ?? ""; Sash.m_HardwareCompleteList = IN_HardwareList; Sash.s_FamilyHardwareList = IN_FamilyHardwareList; Sash.s_SelFamilyHW = IN_SelFamilyHardware; } /// /// Metodo per la scelta della maniglia univoca /// /// anta su cui si seleziona la maniglia /// protected void changeHandle(SashDimension sashDim, Sash currSash) { // 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 bHasHandle foreach (SashDimension item in s.SashList) { if (item.Equals(sashDim)) { item.bHasHandle = true; } else { item.bHasHandle = false; } } } } } // Ancora da fare... protected async Task DoClose() { await EC_OnClose.InvokeAsync(true); } /// /// Anteprima SVG /// /// protected async Task DoPreviewSvg() { if (m_CurrWindow != null) { var CurrJwd = JsonConvert.SerializeObject(m_CurrWindow.Serialize(), Formatting.Indented); Dictionary Args = new Dictionary(); Args.Add("Mode", $"{(int)Enums.EngineQueryType.Preview}"); Args.Add("Jwd", CurrJwd); await EC_OnUpdate.InvokeAsync(Args); } } /// /// Metodo di reset dei dati a quelli del template /// protected async Task DoReset() { // Aggiornati parametri di ingresso selezionati UpdateSelParameter(); JsonWindow WindowFromJson; if (string.IsNullOrEmpty(CurrJwd)) WindowFromJson = JsonConvert.DeserializeObject(m_SelTemplate.JWD, new PolymorphicJsonConverter()) ?? new JsonWindow("", "", "", ""); else WindowFromJson = JsonConvert.DeserializeObject(m_CurrJwd!, new PolymorphicJsonConverter()) ?? new JsonWindow("", "", "", ""); if (m_CurrWindow != null) { m_CurrWindow.OnPreview -= M_CurrWindow_OnPreview; m_CurrWindow = null; } m_CurrWindow = WindowFromJson.Deserialize(); m_CurrWindow.OnPreview += M_CurrWindow_OnPreview; // Aggiorante liste sash, split, splitted, fill e itemTable UpdateLists(); currSash = -1; await DoPreviewSvg(); } // Ancora da fare.. protected async Task DoSave() { //manca salvataggio JWD await EC_OnClose.InvokeAsync(true); } /// /// Selezione del template /// /// template selezionato protected async void DoSelect(TemplateSelectDTO newSel) { SelTemplateDTO = newSel; await EC_OnSelectedTemplate.InvokeAsync(newSel); } /// /// Metodo per cambiare step e aggiornare preview svg /// /// step successivo protected async void NextStepAndPreview(CompileStep newStep, int Index = -1) { currStep = newStep; if (newStep == CompileStep.Sash) currSash = Index; else currSash = -1; await DoPreviewSvg(); } /// /// Metodo per riempire le liste Sash, Split, Splitted e Fill /// /// Area da classificare /// Parametro per sapere se si è dentro un'anta 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[0] is Fill) { m_SplittedList.Add((Splitted)node); } break; } } foreach (var item in node.AreaList) { CreateWindowsList(item, IntoSash); } } } /// /// Metodo per riempire la lista ItemTable in modo da poter rappresentarla come tabella /// /// Area da classificare /// numero di riga /// numero di colonna /// numero di riga massimo /// numero di colonna massimo 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: { // 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)) { // Se il nodo ha figli, salvo il numero nell'oggetto if (node.AreaList.Count >= 1) ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SH", maxRow, col, i, node.AreaList.Count)); else ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SH", 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, "SH", row, col, 0, node.AreaList.Count)); else ItemTableList.Add(new ItemTable(AreaTypes.SASH, "SH", row, col, 0, 0)); maxCol++; } row++; col++; maxRow++; break; } case AreaTypes.FILL: { if ((node.ParentArea.AreaList.Count > 1 && node.ParentArea.AreaList[0].Equals(node)) || (node.ParentArea.ParentArea != null && node.ParentArea.ParentArea.AreaList.Count > 1 && node.ParentArea.ParentArea.AreaList[0].AreaList[0].Equals(node))) maxCol++; ItemTableList.Add(new ItemTable(AreaTypes.FILL, "FL", maxRow, col, -1, 0)); row++; col++; maxRow++; break; } case AreaTypes.SPLIT: { if (node.ParentArea.AreaList.Count > 1 || (node.ParentArea.ParentArea != null && node.ParentArea.ParentArea.AreaList.Count > 1)) { if (node.ParentArea.AreaList[0].Equals(node) || node.ParentArea.ParentArea.AreaList[0].Equals(node)) maxCol++; if (node.AreaList.Count >= 1 || node.AreaList.Count >= 1) ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP", maxRow, col, -1, node.AreaList.Count)); else ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP", maxRow, col, -1, 0)); } else { if (node.AreaList.Count >= 1 || node.AreaList.Count >= 1) ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP", row, col, -1, node.AreaList.Count)); else ItemTableList.Add(new ItemTable(AreaTypes.SPLIT, "SP", row, col, -1, 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; } } /// /// Metodo per riempire tabella con contenuto vuoto o con i simboli per rappresentare la struttura /// /// riga della cella /// colonna della cella /// private string FillTable(int row, int col) { List itemSameCol = new List(); for (int k = 0; k < row; k++) { if (ItemTableList[k].Col == col + 1) { itemSameCol.Add(ItemTableList[k]); } continue; } int numItemNextCol = 0; for (int k = 0; k < row; k++) { if (ItemTableList[k].Row <= row && ItemTableList[k].Col == col + 2) { numItemNextCol++; } continue; } if (itemSameCol.Count > 1) { for (int i = 0; i <= itemSameCol.Count - 2; i++) { if (itemSameCol[i].NumChild > 0) numItemNextCol = numItemNextCol - itemSameCol[i].NumChild; } } if (itemSameCol.Count > 0) { // Sono alla riga successiva di un elemento e nella stessa colonna if (itemSameCol.Last().Row == row) { // se ha un solo figlio if (itemSameCol.Last().NumChild == 1) { return "└"; } else if (itemSameCol.Last().NumChild == 0) { return " "; } else { return "├"; } } // Non sono alla riga successiva else { // se ha un solo figlio if (itemSameCol.Last().NumChild == 1) { return " "; } else if (col + 2 <= m_maxCol && ItemTableList[row].Col == col + 2) { if (numItemNextCol < itemSameCol.Last().NumChild && numItemNextCol != (itemSameCol.Last().NumChild - 1)) { return "├"; } return "└"; } else if (numItemNextCol < itemSameCol.Last().NumChild) { return "│"; } else { return " "; } } } else { return " "; } } /// /// Metodo per settare tutti i Joints di Frame o Sash come ANGLED o FULL_H o FULL_V /// /// tipo di giunzione (ANGLED o FULL_H o FULL_V) /// area su cui eseguire la funzione (Frame o Sash) /// private async Task ChangeAllJoints(WindowConst.Joints type, Area area) { 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(); } /// /// Metodo per settare tutti i Fill in contemporanea /// /// tipo di riempimento (GLASS o WOOD) /// private async Task ChangeAllFill(WindowConst.FillTypes type) { foreach (Fill currFill in m_FillList) { currFill.SetFillType(type); } await DoPreviewSvg(); } /// /// Metodo per copiare contenuto di un'anta in un'altra anta /// /// Sash corrispondente all'anta /// Indice dell'anta che si copia /// Indice dell'anta che si modifica private async Task CopyContentSash(Sash sashItem, int IndexCopy, int 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 - 1].AreaList[0].Copy(sashSplitted); // Aggiungo copia all'anta selezionata sashItem.AreaList[IndexModify].AreaList.Add(a); await DoPreviewSvg(); } /// /// Metodo per copiare una Sash intera /// /// Area Splitted corrente /// Indice della Sash che si vuole copiare /// private async Task CopySash(Splitted currSplitted, int numSash) { //Rimuovo contenuto di Splitted currSplitted.AreaList.RemoveAll(i => i != null); // Copio sash Area a = SashList[numSash].Copy(currSplitted); a.SetParentArea(currSplitted); // Aggiungo copia a Splitted currSplitted.AreaList.Add(a); await DoPreviewSvg(); } /// /// Metodo per scambiare due aree di uno split /// /// Area corrente /// private async Task SwapTwoAree(Area currArea) { currArea.SwapAree(); await DoPreviewSvg(); } #endregion Protected Methods #region Private Fields private CompileStep currStep; private int currSash = -1; private Frame? m_Frame; private List m_SashList = new List(); private List m_SplitList = new List(); private List m_FillList = new List(); private List m_SplittedList = new List(); private List m_ItemTableList = new List(); private int m_maxCol = 0; private int m_maxRow = 0; #endregion Private Fields #region Private Properties private Window? m_CurrWindow { get; set; } = null; private Window? m_PreviousWindow { get; set; } = null; private Template m_SelTemplate { get; set; } = null!; private string m_SelFamilyHardware { get; set; } = ""; #endregion Private Properties #region Private Methods /// /// Metodo per andare allo step successivo /// /// step successivo private void AdvStep(CompileStep newStep) { currStep = newStep; currSash = -1; } private void M_CurrWindow_OnPreview(object? sender, OnPreviewEventArgs e) { Dictionary Args = new Dictionary(); Args.Add("Mode", $"{(int)Enums.EngineQueryType.Preview}"); Args.Add("Jwd", e.sJwd); EC_OnUpdate.InvokeAsync(Args); } /// /// Calcola il css del tab selezionato /// /// Step /// 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"; } return (testStep == currStep) ? "nav-link active fw-bold" : "nav-link text-secondary"; } /// /// Calcola larghezza colonna contenente nav da mostrare /// /// private string mainCss() { return (currStep == CompileStep.Template) ? "col-12" : "col-6"; } /// /// Calcola larghezza colonna header nav /// /// private string headerCss() { return (currStep == CompileStep.Template) ? "col-10 d-grid gap-1 px-2 d-md-flex justify-content-md-start" : "col-8 d-grid gap-1 px-2 d-md-flex justify-content-md-start"; } /// /// Calcola larghezza colonna button nav /// /// private string buttonCss() { return (currStep == CompileStep.Template) ? "col-2 d-grid gap-1 d-md-flex justify-content-md-end" : "col-4 d-grid gap-1 d-md-flex justify-content-md-end"; } #endregion Private Methods } }