using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WebWindowComplex.Json; using static WebWindowComplex.Json.WindowConst; namespace WebWindowComplex.Models { public class SplitDimension { #region Public Constructors public SplitDimension(double dDimension, MeasureTypes MeasureType, bool bIsRelative, Split Parent, bool IsVertList) { m_dDimension = dDimension; m_SelMeasureType = MeasureType; m_bIsRelative = bIsRelative; m_Parent = Parent; m_bIsVertListDim = IsVertList; } #endregion Public Constructors #region Public Properties public bool bIsRelative { get { return m_bIsRelative; } } public bool bIsVertListDim { get { return m_bIsVertListDim; } } public double dDimension { get { return m_dDimension; } set { double widthTot = CalculateWidthSplitGroup(m_Parent.ParentWindow.AreaList.FirstOrDefault(), m_Parent.ParentWindow.AreaList.FirstOrDefault().DimensionList.Where(x => x.sName == "Width").First().dValue); List dimensions = null; if (bIsVertListDim) dimensions = m_Parent.SplitVertList; else dimensions = m_Parent.SplitHorizList; double valMinAbsolut = 100; double valMaxAbsolut = widthTot - valMinAbsolut * (dimensions.Count - 1); bool valueAccept = false; switch (MeasureType) { case MeasureTypes.ABSOLUTE: { valueAccept = (value < valMaxAbsolut && value > valMinAbsolut) ? true : false; break; } case MeasureTypes.PROPORTIONAL: { valMaxAbsolut = 20; valueAccept = (value > 1) ? true : false; break; } case MeasureTypes.PERCENTAGE: { valMaxAbsolut = valMaxAbsolut / widthTot * 100; valMinAbsolut = valMinAbsolut / widthTot * 100; valueAccept = (value < valMaxAbsolut && value > valMinAbsolut) ? true : false; break; } } if (valueAccept) { List absolutValList = new List(); foreach (var item in dimensions) { absolutValList.Add(item.CalculateAbsolutValue(widthTot, dimensions)); } int nIndex = dimensions.IndexOf(this); int proportionalCount = dimensions.Where(x => x.MeasureType.Equals(MeasureTypes.PROPORTIONAL)).ToList().Count; int percentageCount = dimensions.Where(x => x.MeasureType.Equals(MeasureTypes.PERCENTAGE)).ToList().Count; // Le dimensioni sono solo in proporzionale if (proportionalCount == absolutValList.Count) { m_dDimension = value; } // Le dimensioni sono solo in percentuale else if (percentageCount == dimensions.Count) { if (value < dDimension) { // L'anta modificata non è l'ultima if (nIndex < dimensions.Count - 1) dimensions[nIndex + 1].SetDimension(dimensions[nIndex + 1].dDimension + (m_dDimension - value)); else if (dimensions.Count > 1) dimensions[nIndex - 1].SetDimension(dimensions[nIndex - 1].dDimension + (m_dDimension - value)); else { m_dDimension = 100; return; } } else { double dRes = value; // se non ultima anta if (nIndex < dimensions.Count - 1) { for (var nInd = 0; nInd <= nIndex - 1; nInd++) dRes += dimensions[nInd].dDimension; dRes = (100 - dRes) / (dimensions.Count - nIndex - 1); for (var Ind = nIndex + 1; Ind <= dimensions.Count - 1; Ind++) dimensions[Ind].SetDimension(dRes); } // se ultima anta else if (dimensions.Count > 1) { if (dimensions.Count > 2) { for (var Ind = 0; Ind <= nIndex - 2; Ind++) dRes += dimensions[Ind].dDimension; } dRes = (100 - dRes); dimensions[nIndex - 1].SetDimension(dRes); } else { m_dDimension = 100; return; } } m_dDimension = value; } // Le dimensioni sono miste o solo in assoluto else { double valueInAbsolute = 0; switch (MeasureType) { case MeasureTypes.ABSOLUTE: { valueInAbsolute = value; break; } case MeasureTypes.PROPORTIONAL: { var pesi = value + dimensions .Where(x => x.MeasureType.Equals(MeasureTypes.PROPORTIONAL) && !x.Equals(this)) .Sum(x => x.m_dDimension); valueInAbsolute = widthTot / pesi * value; break; } case MeasureTypes.PERCENTAGE: { valueInAbsolute = (value / 100) * widthTot; break; } } if (value < dDimension) { // L'anta modificata non è l'ultima if (nIndex < absolutValList.Count - 1) { absolutValList[nIndex + 1] = absolutValList[nIndex + 1] + (absolutValList[nIndex] - valueInAbsolute); absolutValList[nIndex] = valueInAbsolute; } // L'anta modificata è l'ultima else if (dimensions.Count > 1) { absolutValList[nIndex - 1] = absolutValList[nIndex - 1] + (absolutValList[nIndex] - valueInAbsolute); absolutValList[nIndex] = valueInAbsolute; } } else { // L'anta modificata non è l'ultima if (nIndex < absolutValList.Count - 1) { absolutValList[nIndex + 1] = absolutValList[nIndex + 1] - (valueInAbsolute - absolutValList[nIndex]); absolutValList[nIndex] = valueInAbsolute; } // L'anta modificata è l'ultima else if (dimensions.Count > 1) { absolutValList[nIndex - 1] = absolutValList[nIndex - 1] - (valueInAbsolute - absolutValList[nIndex]); absolutValList[nIndex] = valueInAbsolute; } } if (MeasureType.Equals(MeasureTypes.PROPORTIONAL)) m_dDimension = value; for (int i = 0; i < absolutValList.Count; i++) { var item = dimensions.ElementAt(i); item.SetDimension(ConvertIn(absolutValList[i], (MeasureTypes)item.SelMeasureTypeIndex, widthTot, dimensions)); } } //m_Parent.ParentWindow.OnUpdatePreview(m_Parent.ParentWindow.sSerialized()); } //// Controllo che il valore inserito sia compreso tra 0 e 100 //if (value > 0 && value < 100) //{ // // se sono in percentuale // if (m_bIsRelative) // { // List RelativeDimList = new List(); // if (bIsVertListDim) // RelativeDimList = m_Parent.SplitVertList.Where(x => x.bIsRelative).ToList(); // else // RelativeDimList = m_Parent.SplitHorizList.Where(x => x.bIsRelative).ToList(); // // verifico se ci sono assoluti // //List RelativeDimList = m_Parent.SplitPositionList.Where(x => x.bIsRelative).ToList(); // if (RelativeDimList.Count > 0) // { // if (m_Parent.bIsPercentage) // { // int nIndex = RelativeDimList.IndexOf(this); // if (value < m_dDimension) // { // if (nIndex < RelativeDimList.Count - 1) // RelativeDimList[nIndex + 1].SetDimension(RelativeDimList[nIndex + 1].dDimension + (m_dDimension - value)); // else if (RelativeDimList.Count > 1) // RelativeDimList[nIndex - 1].SetDimension(RelativeDimList[nIndex - 1].dDimension + (m_dDimension - value)); // else // { // m_dDimension = 100; // return; // } // } // else // { // double dRes = value; // if (nIndex < RelativeDimList.Count - 1) // { // for (var nInd = 0; nInd <= nIndex - 1; nInd++) // dRes += RelativeDimList[nInd].dDimension; // dRes = (100 - dRes) / (RelativeDimList.Count - nIndex - 1); // if (dRes != 0) // { // for (var Ind = nIndex + 1; Ind <= RelativeDimList.Count - 1; Ind++) // RelativeDimList[Ind].SetDimension(dRes); // } // else // return; // } // else if (RelativeDimList.Count > 1) // { // if (RelativeDimList.Count > 2) // { // for (var Ind = 0; Ind <= nIndex - 2; Ind++) // dRes += RelativeDimList[Ind].dDimension; // } // dRes = (100 - dRes); // if (dRes != 0) // RelativeDimList[nIndex - 1].SetDimension(dRes); // else // return; // } // else // { // m_dDimension = 100; // return; // } // } // } // else // { // } // } // } // m_dDimension = value; // m_Parent.ParentWindow.OnUpdatePreview(m_Parent.ParentWindow.sSerialized()); //} } } public Split Parent { get { return m_Parent; } set { m_Parent = value; } } public MeasureTypes MeasureType { get { return m_SelMeasureType; } } public List MeasureTypeList { get { return m_MeasureTypeList; } } public MeasureTypes SelMeasureType { get { return m_SelMeasureType; } set { m_SelMeasureType = value; } } public int SelMeasureTypeIndex { get { return (int)m_SelMeasureType; } set { if (m_SelMeasureType != (MeasureTypes)value) { MeasureTypes newType = (MeasureTypes)value; List splitList = null; double tot = 0; if (bIsVertListDim) { splitList = m_Parent.SplitVertList; tot = CalculateWidthSplitGroup(m_Parent.ParentWindow.AreaList.FirstOrDefault(), m_Parent.ParentWindow.AreaList.FirstOrDefault().DimensionList.Where(x => x.sName == "Width").First().dValue); } else { splitList = m_Parent.SplitHorizList; tot = CalculateHeightSplitGroup(m_Parent.ParentWindow.AreaList.FirstOrDefault(), m_Parent.ParentWindow.AreaList.FirstOrDefault().DimensionList.Where(x => x.sName == "Height").First().dValue); } m_dDimension = ConvertDimension(m_SelMeasureType, newType, tot, splitList); m_SelMeasureType = (MeasureTypes)value; //m_Parent.ParentWindow.OnUpdatePreview(m_Parent.ParentWindow.sSerialized()); } } } #endregion Public Properties #region Public Methods /// /// Metodo per convertire la dimensione dal vecchio tipo al nuovo tipo /// /// Vecchio tipo /// Nuovo tipo /// public double ConvertDimension(MeasureTypes oldType, MeasureTypes newType, double widthTot, List splitList) { switch (oldType) { case MeasureTypes.ABSOLUTE: { if (newType.Equals(MeasureTypes.PERCENTAGE)) { //return Double.Round((m_dDimension / m_Parent.Width) * 100, 1); return (m_dDimension / widthTot) * 100; } else { return CalculatePropVal(widthTot, splitList); } } case MeasureTypes.PROPORTIONAL: { if (newType.Equals(MeasureTypes.ABSOLUTE)) { //return Double.Round(ConvertFromPropVal(newType), 2); return ConvertFromPropVal(newType, widthTot, splitList); } else { //return Double.Round(ConvertFromPropVal(newType), 1); return ConvertFromPropVal(newType, widthTot, splitList); } } case MeasureTypes.PERCENTAGE: { if (newType.Equals(MeasureTypes.ABSOLUTE)) { //return Double.Round((m_dDimension * m_Parent.Width) / 100, 2); return (m_dDimension * widthTot) / 100; } else { return CalculatePropVal(widthTot, splitList); } } } return -1; } public SplitDimension Copy() { SplitDimension newSplitDim = new SplitDimension(dDimension, MeasureTypes.PERCENTAGE, bIsRelative, m_Parent, bIsVertListDim); return newSplitDim; } #endregion Public Methods #region Internal Methods /// /// Metodo per calcolare larghezza intero split group /// /// area di partenza /// larghezza di partenza /// internal double CalculateWidthSplitGroup(Area area, double width) { for (int i = 0; i < area.AreaList.Count; i++) { double risultato = -1; if (area.Equals(m_Parent)) return width; Area item = area.AreaList[i]; if (area is Split) { Split split = (Split)area; if(split.SplitVertList.Count > 0) { switch (split.SplitVertList.ElementAt(i).SelMeasureType) { case MeasureTypes.ABSOLUTE: { risultato = CalculateWidthSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension); break; } case MeasureTypes.PROPORTIONAL: { //risultato = CalculateWidthSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension); break; } case MeasureTypes.PERCENTAGE: { risultato = CalculateWidthSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension * width / 100); break; } } if (risultato != -1) return risultato; } else { risultato = CalculateWidthSplitGroup(item, width); } } else if (area is Sash) { Sash sash = (Sash)area; switch (sash.SashList.ElementAt(i).SelMeasureType) { case MeasureTypes.ABSOLUTE: { risultato = CalculateWidthSplitGroup(item, sash.SashList.ElementAt(i).dDimension); break; } case MeasureTypes.PROPORTIONAL: { //risultato = CalculateWidthSplitGroup(item, sash.SashList.ElementAt(i).dDimension); break; } case MeasureTypes.PERCENTAGE: { risultato = CalculateWidthSplitGroup(item, sash.SashList.ElementAt(i).dDimension * width / 100); break; } } if (risultato != -1) return risultato; } else { risultato = CalculateWidthSplitGroup(item, width); if (risultato != -1) return risultato; } } return width; } /// /// Metodo per calcolare altezza intero split group /// /// area di partenza /// larghezza di partenza /// internal double CalculateHeightSplitGroup(Area area, double width) { for (int i = 0; i < area.AreaList.Count; i++) { double risultato = -1; if (area.Equals(m_Parent)) return width; Area item = area.AreaList[i]; if (area is Split) { Split split = (Split)area; if (split.SplitHorizList.Count > 0) { switch (split.SplitHorizList.ElementAt(i).SelMeasureType) { case MeasureTypes.ABSOLUTE: { risultato = CalculateHeightSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension); break; } case MeasureTypes.PROPORTIONAL: { //risultato = CalculateHeightSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension); break; } case MeasureTypes.PERCENTAGE: { risultato = CalculateHeightSplitGroup(item, split.SplitVertList.ElementAt(i).dDimension * width / 100); break; } } if (risultato != -1) return risultato; } else { risultato = CalculateHeightSplitGroup(item, width); } } else if (area is Sash) { Sash sash = (Sash)area; switch (sash.SashList.ElementAt(i).SelMeasureType) { case MeasureTypes.ABSOLUTE: { risultato = CalculateHeightSplitGroup(item, sash.SashList.ElementAt(i).dDimension); break; } case MeasureTypes.PROPORTIONAL: { //risultato = CalculateHeightSplitGroup(item, sash.SashList.ElementAt(i).dDimension); break; } case MeasureTypes.PERCENTAGE: { risultato = CalculateHeightSplitGroup(item, sash.SashList.ElementAt(i).dDimension * width / 100); break; } } if (risultato != -1) return risultato; } else { risultato = CalculateHeightSplitGroup(item, width); if (risultato != -1) return risultato; } } return width; } /// /// Calcolo MCD /// /// /// /// internal static double CalculateMCD(double a, double b) { while (b >= 0.01) { double temp = b; b = a % b; a = temp; } //return Double.Round(a,2); return a; } /// /// Metodo per ricalcolare i valori proporzionali a causa della modifica di uno /// /// internal double CalculatePropVal(double widthTot, List splitList) { if (splitList.Where(m => m.MeasureType.Equals(MeasureTypes.PROPORTIONAL)).ToList().Count == 0) { return 1; } List absolutValue = new List(); foreach (var item in splitList) { absolutValue.Add(item.CalculateAbsolutValue(widthTot, splitList)); } for (int i = 0; i < splitList.Count; i++) { if (!splitList.ElementAt(i).Equals(this) && splitList.ElementAt(i).MeasureType.Equals(MeasureTypes.PROPORTIONAL)) { int nIndex = splitList.IndexOf(this); if (absolutValue.ElementAt(nIndex) <= absolutValue.ElementAt(i)) { var mcd = CalculateMCD(absolutValue.ElementAt(nIndex), absolutValue.ElementAt(i)); //m_Parent.SashList.ElementAt(i).m_dDimension = Double.Round(absolutValue.ElementAt(i) / mcd, 2); //m_dDimension = Double.Round(absolutValue.ElementAt(nIndex) / mcd, 2); splitList.ElementAt(i).m_dDimension = absolutValue.ElementAt(i) / mcd; m_dDimension = absolutValue.ElementAt(nIndex) / mcd; } else { var mcd = CalculateMCD(absolutValue.ElementAt(nIndex), absolutValue.ElementAt(i)); //m_Parent.SashList.ElementAt(i).m_dDimension = Double.Round(absolutValue.ElementAt(i) / mcd, 2); //m_dDimension = Double.Round(absolutValue.ElementAt(nIndex) / mcd, 2); splitList.ElementAt(i).m_dDimension = absolutValue.ElementAt(i) / mcd; m_dDimension = absolutValue.ElementAt(nIndex) / mcd; } break; } } return m_dDimension; } /// /// Metodo per trasformare una dimensione in valore assoluto rispetto alla larghezza totale /// /// Larghezza totale /// internal double CalculateAbsolutValue(double widthTot, List splitList) { switch (MeasureType) { case MeasureTypes.ABSOLUTE: { //return Double.Round(dDimension, 2); return dDimension; } case MeasureTypes.PROPORTIONAL: { //return Double.Round(Proportional2AbsolutVal(), 2); return Proportional2AbsolutVal(widthTot, splitList); } case MeasureTypes.PERCENTAGE: { //return Double.Round((dDimension / 100) * widthTot, 1); return (dDimension / 100) * widthTot; } } return 0; } /// /// Metodo per convertire una dimensione da un valore assoluto al suo rispettivo tipo /// /// Valore assoluto /// Tipo di misura della dimensione /// Larghezza totale /// internal double ConvertIn(double absolutVal, MeasureTypes type, double widthTot, List splitList) { switch (type) { case MeasureTypes.ABSOLUTE: { //return Double.Round(absolutVal, 2); return absolutVal; } case MeasureTypes.PROPORTIONAL: { //return Proportional2AbsolutVal(); return Proportional2AbsolutVal(widthTot, splitList); } case MeasureTypes.PERCENTAGE: { //return Double.Round((absolutVal / widthTot) * 100, 1); return (absolutVal / widthTot) * 100; } } return -1; } /// /// Metodo per convertire da misura proporzionale a misura assoluta o percentuale /// /// /// internal double ConvertFromPropVal(MeasureTypes newType, double widthTot, List splitList) { double tot = widthTot; //Somma misura non proporzionali double sumNotProp = splitList .Where(m => m.MeasureType != MeasureTypes.PROPORTIONAL && !m.Equals(this)) .Sum(m => m.CalculateAbsolutValue(tot, splitList)); //Calcolo residuo double res = tot - sumNotProp; if (res < 0) res = 0; //Misure proporzionali var proportionalList = splitList .Where(m => m.SelMeasureType == MeasureTypes.PROPORTIONAL) .ToList(); double sumPesi = proportionalList.Sum(p => p.dDimension); if (sumPesi == 0) sumPesi = 1; if (newType.Equals(MeasureTypes.ABSOLUTE)) { return res / sumPesi * dDimension; } else { return (res / sumPesi * dDimension) / tot * 100; } } /// /// Metodo per trasformare il valore proporzionale in assoluto /// /// internal double Proportional2AbsolutVal(double widthTot, List splitList) { double tot = widthTot; //Somma misura non proporzionali double sumNotProp = splitList .Where(m => m.MeasureType != MeasureTypes.PROPORTIONAL) .Sum(m => m.CalculateAbsolutValue(tot, splitList)); //Calcolo residuo double res = tot - sumNotProp; if (res < 0) res = 0; //Misure proporzionali var proportionalList = splitList .Where(m => m.SelMeasureType == MeasureTypes.PROPORTIONAL) .ToList(); double sumPesi = proportionalList.Sum(p => p.dDimension); if (sumPesi == 0) sumPesi = 1; return res / sumPesi * dDimension; } internal JsonSplitDimension Serialize() { JsonSplitDimension JsonSplitDimension = new JsonSplitDimension(m_bIsRelative, m_dDimension, MeasureType); return JsonSplitDimension; } internal void SetDimension(double dValue) { m_dDimension = dValue; } internal void SetIsRelative(bool value) { m_bIsRelative = value; } internal void SetIsVertListDim(bool value) { m_bIsVertListDim = value; } internal void SetMeasureType(MeasureTypes value) { m_SelMeasureType = value; } internal void SetSelMeasureType(MeasureTypes value) { if (m_SelMeasureType != (MeasureTypes)value) { MeasureTypes newType = (MeasureTypes)value; double tot = 0; if (bIsVertListDim) { tot = CalculateWidthSplitGroup(m_Parent.ParentWindow.AreaList.FirstOrDefault(), m_Parent.ParentWindow.AreaList.FirstOrDefault().DimensionList.Where(x => x.sName == "Width").First().dValue); m_dDimension = ConvertDimension(m_SelMeasureType, newType, tot, m_Parent.SplitVertList); } else { tot = CalculateHeightSplitGroup(m_Parent.ParentWindow.AreaList.FirstOrDefault(), m_Parent.ParentWindow.AreaList.FirstOrDefault().DimensionList.Where(x => x.sName == "Height").First().dValue); m_dDimension = ConvertDimension(m_SelMeasureType, newType, tot, m_Parent.SplitHorizList); } m_SelMeasureType = (MeasureTypes)value; //m_Parent.ParentWindow.OnUpdatePreview(m_Parent.ParentWindow.sSerialized()); } } #endregion Internal Methods #region Private Fields private bool m_bIsRelative = false; private bool m_bIsVertListDim = false; private double m_dDimension; private List m_MeasureTypeList = new List { new IdNameStruct((int)MeasureTypes.ABSOLUTE, "Absolute"), new IdNameStruct((int)MeasureTypes.PROPORTIONAL, "Proportional"), new IdNameStruct((int)MeasureTypes.PERCENTAGE, "Percentage"), }; private MeasureTypes m_SelMeasureType; // reference private Split m_Parent; #endregion Private Fields } }