|
|
@@ -0,0 +1,564 @@
|
|
|
+using DevExpress.Data;
|
|
|
+using DevExpress.XtraEditors.Controls;
|
|
|
+using DevExpress.XtraPrinting;
|
|
|
+using DevExpress.XtraReports.UI;
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Drawing;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Net.Mime;
|
|
|
+using System.Web;
|
|
|
+
|
|
|
+namespace GreenTree.Nachtragsmanagement.Web.Extensions
|
|
|
+{
|
|
|
+ public class MVCxGridViewGeneratorHelper
|
|
|
+ {
|
|
|
+ public delegate void CustomizeColumnsCollectionEventHandler(object source, ColumnsCreationEventArgs e);
|
|
|
+ public delegate void CustomizeColumnEventHandler(object source, ControlCustomizationEventArgs e);
|
|
|
+ public delegate void CustomizeColumnSummaryEventHandler(object source, ColumnSummaryCreationEventArgs e);
|
|
|
+
|
|
|
+ public class MVCReportGeneratonHelper
|
|
|
+ {
|
|
|
+ const int initialGroupOffset = 0;
|
|
|
+ const int subGroupOffset = 10;
|
|
|
+ const int bandHeight = 20;
|
|
|
+ const bool shouldRepeatGroupHeadersOnEveryPage = false;
|
|
|
+
|
|
|
+ XtraReport report;
|
|
|
+
|
|
|
+ Hashtable detailsInfo = new Hashtable();
|
|
|
+ Hashtable detailsWidth = new Hashtable();
|
|
|
+
|
|
|
+ public event CustomizeColumnsCollectionEventHandler CustomizeColumnsCollection;
|
|
|
+ public event CustomizeColumnEventHandler CustomizeColumn;
|
|
|
+ public event CustomizeColumnSummaryEventHandler CustomizeColumnSummary;
|
|
|
+
|
|
|
+ public XtraReport GenerateMVCReport(MVCxGridViewState gridViewState, object model)
|
|
|
+ {
|
|
|
+ report = new XtraReport
|
|
|
+ {
|
|
|
+ Font = new Font("Calibri", 10f, FontStyle.Regular),
|
|
|
+ Landscape = true,
|
|
|
+ PaperKind = System.Drawing.Printing.PaperKind.A4
|
|
|
+ };
|
|
|
+
|
|
|
+ InitStyles();
|
|
|
+ InitDataSource(model);
|
|
|
+ InitDetailsAndPageHeader(gridViewState);
|
|
|
+ InitSortings(gridViewState);
|
|
|
+ InitGroupHeaders(gridViewState);
|
|
|
+ InitFilters(gridViewState);
|
|
|
+ InitTotalSummaries(gridViewState);
|
|
|
+
|
|
|
+ return report;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitStyles()
|
|
|
+ {
|
|
|
+ report.StyleSheet.Add(new XRControlStyle
|
|
|
+ {
|
|
|
+ Name = "OddRow",
|
|
|
+ Borders = (DevExpress.XtraPrinting.BorderSide.Bottom |
|
|
|
+ DevExpress.XtraPrinting.BorderSide.Left |
|
|
|
+ DevExpress.XtraPrinting.BorderSide.Right),
|
|
|
+ Padding = new PaddingInfo(30, 600)
|
|
|
+ });
|
|
|
+
|
|
|
+ report.StyleSheet.Add(new XRControlStyle
|
|
|
+ {
|
|
|
+ Name = "EvenRow",
|
|
|
+ BackColor = Color.LightGray,
|
|
|
+ Borders = (DevExpress.XtraPrinting.BorderSide.Bottom |
|
|
|
+ DevExpress.XtraPrinting.BorderSide.Left |
|
|
|
+ DevExpress.XtraPrinting.BorderSide.Right),
|
|
|
+ Padding = new PaddingInfo(30, 600)
|
|
|
+ });
|
|
|
+
|
|
|
+ report.StyleSheet.Add(new XRControlStyle
|
|
|
+ {
|
|
|
+ Name = "HeaderRow",
|
|
|
+ BackColor = Color.FromArgb(156, 183, 191),
|
|
|
+ Borders = DevExpress.XtraPrinting.BorderSide.All,
|
|
|
+ Padding = new PaddingInfo(30, 600),
|
|
|
+ Font = new Font(report.Font, FontStyle.Bold)
|
|
|
+ });
|
|
|
+
|
|
|
+ report.StyleSheet.Add(new XRControlStyle
|
|
|
+ {
|
|
|
+ Name = "SummaryRow",
|
|
|
+ BackColor = Color.FromArgb(35, 133, 160),
|
|
|
+ Borders = DevExpress.XtraPrinting.BorderSide.All,
|
|
|
+ BorderColor = Color.FromArgb(35, 133, 160),
|
|
|
+ Padding = new PaddingInfo(30, 600),
|
|
|
+ ForeColor = Color.White,
|
|
|
+ Font = new Font(report.Font, FontStyle.Bold)
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitDataSource(object model)
|
|
|
+ {
|
|
|
+ report.DataSource = model;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitDetailsAndPageHeader(MVCxGridViewState gridViewState)
|
|
|
+ {
|
|
|
+ var groupedColumns = gridViewState.GroupedColumns;
|
|
|
+
|
|
|
+ var pagewidth = (report.PageWidth - (report.Margins.Left + report.Margins.Right)) - groupedColumns.Count * subGroupOffset;
|
|
|
+ var columns = GetColumnsInfo(gridViewState, pagewidth);
|
|
|
+
|
|
|
+ if (CustomizeColumnsCollection != null)
|
|
|
+ CustomizeColumnsCollection(report, new ColumnsCreationEventArgs(pagewidth)
|
|
|
+ {
|
|
|
+ ColumnsInfo = columns
|
|
|
+ });
|
|
|
+
|
|
|
+ report.Bands.Add(new DetailBand()
|
|
|
+ {
|
|
|
+ HeightF = bandHeight
|
|
|
+ });
|
|
|
+ report.Bands.Add(new PageHeaderBand()
|
|
|
+ {
|
|
|
+ HeightF = bandHeight
|
|
|
+ });
|
|
|
+
|
|
|
+ var headerTable = new XRTable()
|
|
|
+ {
|
|
|
+ StyleName = "HeaderRow"
|
|
|
+ };
|
|
|
+ var row = new XRTableRow();
|
|
|
+
|
|
|
+ var detailTable = new XRTable
|
|
|
+ {
|
|
|
+ OddStyleName = "OddRow",
|
|
|
+ EvenStyleName = "EvenRow"
|
|
|
+ };
|
|
|
+ var row2 = new XRTableRow();
|
|
|
+
|
|
|
+ for (var i = 0; i < columns.Count; i++)
|
|
|
+ {
|
|
|
+ if (columns[i].IsVisible)
|
|
|
+ {
|
|
|
+ var cell = new XRTableCell
|
|
|
+ {
|
|
|
+ Width = columns[i].ColumnWidth,
|
|
|
+ Text = columns[i].GridViewColumn.Caption,
|
|
|
+ Borders = DevExpress.XtraPrinting.BorderSide.All,
|
|
|
+ TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
|
|
|
+ };
|
|
|
+ row.Cells.Add(cell);
|
|
|
+
|
|
|
+ var cell2 = new XRTableCell
|
|
|
+ {
|
|
|
+ Width = columns[i].ColumnWidth
|
|
|
+ };
|
|
|
+
|
|
|
+ var cc = new ControlCustomizationEventArgs
|
|
|
+ {
|
|
|
+ FieldName = columns[i].FieldName,
|
|
|
+ IsModified = false,
|
|
|
+ Owner = cell2,
|
|
|
+ Header = cell
|
|
|
+ };
|
|
|
+
|
|
|
+ if (CustomizeColumn != null)
|
|
|
+ CustomizeColumn(report, cc);
|
|
|
+
|
|
|
+ if (cc.IsModified == false)
|
|
|
+ cell2.DataBindings.Add("Text", null, columns[i].FieldName,
|
|
|
+ "{0:" + columns[i].GridViewColumn.DisplayFormat + "}");
|
|
|
+
|
|
|
+ detailsInfo.Add(columns[i].GridViewColumn, cell2);
|
|
|
+
|
|
|
+ row2.Cells.Add(cell2);
|
|
|
+
|
|
|
+ detailsWidth.Add(columns[i].GridViewColumn, cell2.WidthF);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ headerTable.Rows.Add(row);
|
|
|
+ headerTable.Width = pagewidth;
|
|
|
+ headerTable.LocationF = new PointF(groupedColumns.Count * subGroupOffset, 0);
|
|
|
+ headerTable.Borders = DevExpress.XtraPrinting.BorderSide.Bottom;
|
|
|
+
|
|
|
+ detailTable.Rows.Add(row2);
|
|
|
+ detailTable.LocationF = new PointF(groupedColumns.Count * subGroupOffset, 0);
|
|
|
+ detailTable.Width = pagewidth;
|
|
|
+
|
|
|
+ report.Bands[BandKind.PageHeader].Controls.Add(headerTable);
|
|
|
+ report.Bands[BandKind.Detail].Controls.Add(detailTable);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitSortings(MVCxGridViewState gridViewState)
|
|
|
+ {
|
|
|
+ var columns = gridViewState.Columns;
|
|
|
+ var groupedColumns = gridViewState.GroupedColumns;
|
|
|
+
|
|
|
+ for (var i = 0; i < columns.Count; i++)
|
|
|
+ {
|
|
|
+ if (!groupedColumns.Contains(columns[i]))
|
|
|
+ {
|
|
|
+ if (columns[i].SortOrder != ColumnSortOrder.None)
|
|
|
+ ((DetailBand)report.Bands[BandKind.Detail]).SortFields.Add(new GroupField(columns[i].FieldName, columns[i].SortOrder == ColumnSortOrder.Ascending ? XRColumnSortOrder.Ascending : XRColumnSortOrder.Descending));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitGroupHeaders(MVCxGridViewState gridViewState)
|
|
|
+ {
|
|
|
+ GridViewDataColumnStateCollection groupedColumns = gridViewState.GroupedColumns;
|
|
|
+ for (int i = groupedColumns.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ {
|
|
|
+ GridViewDataColumnState groupedColumn = groupedColumns[i];
|
|
|
+ GroupHeaderBand gb = new GroupHeaderBand();
|
|
|
+ gb.Height = bandHeight;
|
|
|
+ XRLabel l = new XRLabel();
|
|
|
+ l.Text = groupedColumn.FieldName + ": [" + groupedColumn.FieldName + "]";
|
|
|
+ l.LocationF = new PointF(initialGroupOffset + i * 10, 0);
|
|
|
+ l.BackColor = Color.Beige;
|
|
|
+ l.SizeF = new SizeF((report.PageWidth - (report.Margins.Left + report.Margins.Right)) - (initialGroupOffset + i * subGroupOffset), bandHeight);
|
|
|
+ gb.Controls.Add(l);
|
|
|
+ gb.RepeatEveryPage = shouldRepeatGroupHeadersOnEveryPage;
|
|
|
+ GroupField gf = new GroupField(groupedColumn.FieldName, groupedColumn.SortOrder == ColumnSortOrder.Ascending ? XRColumnSortOrder.Ascending : XRColumnSortOrder.Descending);
|
|
|
+ gb.GroupFields.Add(gf);
|
|
|
+ report.Bands.Add(gb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitFilters(MVCxGridViewState gridViewState)
|
|
|
+ {
|
|
|
+ report.FilterString = gridViewState.FilterExpression;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitTotalSummaries(MVCxGridViewState gridViewState)
|
|
|
+ {
|
|
|
+ if (gridViewState.TotalSummary.Count == 0) return;
|
|
|
+
|
|
|
+ report.Bands.Add(new ReportFooterBand
|
|
|
+ {
|
|
|
+ HeightF = bandHeight,
|
|
|
+ StyleName = "SummaryRow"
|
|
|
+ });
|
|
|
+
|
|
|
+ foreach (MVCxSummaryItemState item in gridViewState.TotalSummary)
|
|
|
+ {
|
|
|
+ var col = gridViewState.Columns[item.ShowInColumn == string.Empty ? item.FieldName : item.ShowInColumn];
|
|
|
+
|
|
|
+ if (col == null) continue;
|
|
|
+
|
|
|
+ if (!detailsInfo.Contains(col)) return;
|
|
|
+
|
|
|
+ var label = new XRLabel
|
|
|
+ {
|
|
|
+ LocationF = ((XRTableCell)detailsInfo[col]).LocationF,
|
|
|
+ SizeF = ((XRTableCell)detailsInfo[col]).SizeF
|
|
|
+ };
|
|
|
+ label.DataBindings.Add("Text", null, col.FieldName);
|
|
|
+ label.Summary = new XRSummary
|
|
|
+ {
|
|
|
+ Running = SummaryRunning.Report
|
|
|
+ };
|
|
|
+ label.Summary.FormatString = item.DisplayFormat;
|
|
|
+ label.Summary.Func = GetSummaryFunc(item.SummaryType);
|
|
|
+
|
|
|
+ report.Bands[BandKind.ReportFooter].Controls.Add(label);
|
|
|
+
|
|
|
+ if (CustomizeColumnSummary != null)
|
|
|
+ CustomizeColumnSummary(report, new ColumnSummaryCreationEventArgs(col.FieldName, label.Summary));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<MVCxColumnInfo> GetColumnsInfo(MVCxGridViewState gridViewState, int pagewidth)
|
|
|
+ {
|
|
|
+ var columns = new List<MVCxColumnInfo>();
|
|
|
+ var visibleColumns = gridViewState.Columns;
|
|
|
+
|
|
|
+ foreach (var dataColumn in visibleColumns)
|
|
|
+ {
|
|
|
+ MVCxColumnInfo column = new MVCxColumnInfo(dataColumn)
|
|
|
+ {
|
|
|
+ ColumnCaption = string.IsNullOrEmpty(dataColumn.Caption) ? dataColumn.FieldName : dataColumn.Caption,
|
|
|
+ ColumnWidth = ((int)pagewidth / visibleColumns.Count),
|
|
|
+ FieldName = dataColumn.FieldName,
|
|
|
+ IsVisible = true
|
|
|
+ };
|
|
|
+ columns.Add(column);
|
|
|
+ }
|
|
|
+
|
|
|
+ return columns;
|
|
|
+ }
|
|
|
+
|
|
|
+ private SummaryFunc GetSummaryFunc(SummaryItemType summaryItemType)
|
|
|
+ {
|
|
|
+ switch (summaryItemType)
|
|
|
+ {
|
|
|
+ case SummaryItemType.Sum:
|
|
|
+ return SummaryFunc.Sum;
|
|
|
+ case SummaryItemType.Average:
|
|
|
+ return SummaryFunc.Avg;
|
|
|
+ case SummaryItemType.Max:
|
|
|
+ return SummaryFunc.Max;
|
|
|
+ case SummaryItemType.Min:
|
|
|
+ return SummaryFunc.Min;
|
|
|
+ case SummaryItemType.Count:
|
|
|
+ return SummaryFunc.Count;
|
|
|
+ default:
|
|
|
+ return SummaryFunc.Custom;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void WritePdfToResponse(HttpResponseBase Response, string fileName, string type)
|
|
|
+ {
|
|
|
+ report.CreateDocument(false);
|
|
|
+ using (MemoryStream ms = new MemoryStream())
|
|
|
+ {
|
|
|
+ report.ExportToPdf(ms);
|
|
|
+ ms.Seek(0, SeekOrigin.Begin);
|
|
|
+ WriteResponse(Response, ms.ToArray(), "application/pdf", type, fileName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void WriteXlsToResponse(HttpResponseBase Response, string fileName, string type)
|
|
|
+ {
|
|
|
+ report.CreateDocument(false);
|
|
|
+ using (MemoryStream ms = new MemoryStream())
|
|
|
+ {
|
|
|
+ report.ExportToXls(ms);
|
|
|
+ ms.Seek(0, SeekOrigin.Begin);
|
|
|
+ WriteResponse(Response, ms.ToArray(), "application/vnd.ms-excel", type, fileName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void WriteXlsxToResponse(HttpResponseBase Response, string fileName, string type)
|
|
|
+ {
|
|
|
+ report.CreateDocument(false);
|
|
|
+ using (MemoryStream ms = new MemoryStream())
|
|
|
+ {
|
|
|
+ report.ExportToXlsx(ms);
|
|
|
+ ms.Seek(0, SeekOrigin.Begin);
|
|
|
+ WriteResponse(Response, ms.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", type, fileName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void WriteResponse(HttpResponseBase response, byte[] filearray, string contentType, string type, string fileName)
|
|
|
+ {
|
|
|
+ response.ClearContent();
|
|
|
+ response.Buffer = true;
|
|
|
+ response.Cache.SetCacheability(HttpCacheability.Private);
|
|
|
+ response.ContentType = contentType;
|
|
|
+ ContentDisposition contentDisposition = new ContentDisposition();
|
|
|
+ contentDisposition.FileName = fileName;
|
|
|
+ contentDisposition.DispositionType = type;
|
|
|
+ response.AddHeader("Content-Disposition", contentDisposition.ToString());
|
|
|
+ response.BinaryWrite(filearray);
|
|
|
+ HttpContext.Current.ApplicationInstance.CompleteRequest();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ response.End();
|
|
|
+ }
|
|
|
+ catch (System.Threading.ThreadAbortException)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ControlCustomizationEventArgs : EventArgs
|
|
|
+ {
|
|
|
+ XRControl owner;
|
|
|
+
|
|
|
+ public XRControl Owner
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return owner;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ owner = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ XRControl header;
|
|
|
+
|
|
|
+ public XRControl Header
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return header;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ header = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool isModified;
|
|
|
+
|
|
|
+ public bool IsModified
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return isModified;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ isModified = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ string fieldName;
|
|
|
+
|
|
|
+ public string FieldName
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return fieldName;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ fieldName = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ColumnSummaryCreationEventArgs : EventArgs
|
|
|
+ {
|
|
|
+ public ColumnSummaryCreationEventArgs(string fieldName, XRSummary summary)
|
|
|
+ {
|
|
|
+ this.fieldName = fieldName;
|
|
|
+ this.summary = summary;
|
|
|
+ }
|
|
|
+
|
|
|
+ XRSummary summary;
|
|
|
+
|
|
|
+ public XRSummary Summary
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return summary;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ summary = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ string fieldName;
|
|
|
+
|
|
|
+ public string FieldName
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return fieldName;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ fieldName = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ColumnsCreationEventArgs : EventArgs
|
|
|
+ {
|
|
|
+ int pageWidth;
|
|
|
+ public int PageWidth
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return pageWidth;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public ColumnsCreationEventArgs(int pageWidth)
|
|
|
+ {
|
|
|
+ this.pageWidth = pageWidth;
|
|
|
+ }
|
|
|
+ List<MVCxColumnInfo> columnsInfo;
|
|
|
+
|
|
|
+ public List<MVCxColumnInfo> ColumnsInfo
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return columnsInfo;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ columnsInfo = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class MVCxColumnInfo
|
|
|
+ {
|
|
|
+ public MVCxColumnInfo(GridViewDataColumnState gridViewColumn)
|
|
|
+ {
|
|
|
+ this.gridViewColumn = gridViewColumn;
|
|
|
+ }
|
|
|
+ GridViewDataColumnState gridViewColumn;
|
|
|
+
|
|
|
+ public GridViewDataColumnState GridViewColumn
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return gridViewColumn;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ string columnCaption;
|
|
|
+ public string ColumnCaption
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return columnCaption;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ columnCaption = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ string fieldName;
|
|
|
+
|
|
|
+ public string FieldName
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return fieldName;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ fieldName = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int columnWidth;
|
|
|
+
|
|
|
+ public int ColumnWidth
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return columnWidth;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ columnWidth = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bool isVisible;
|
|
|
+
|
|
|
+ public bool IsVisible
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return isVisible;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ isVisible = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|