/// <summary> /// Given an Html Table Element determines the table properties /// Returns the properties as an HtmlTableProperty class /// </summary> private HtmlTableProperty GetTableProperties(mshtmlTable table) { // define a set of base table properties var tableProperties = new HtmlTableProperty(true); // if user has selected a table extract those properties if (!table.IsNull()) { try { // have a table so extract the properties mshtmlTableCaption caption = table.caption; // if have a caption persist the values if (!caption.IsNull()) { tableProperties.CaptionText = ((mshtmlElement)table.caption).innerText; if (!caption.align.IsNull()) tableProperties.CaptionAlignment = (HorizontalAlignOption)typeof(HorizontalAlignOption).TryParseEnum(caption.align, HorizontalAlignOption.Default); if (!caption.vAlign.IsNull()) tableProperties.CaptionLocation = (VerticalAlignOption)typeof(VerticalAlignOption).TryParseEnum(caption.vAlign, VerticalAlignOption.Default); } // look at the table properties if (!GeneralUtil.IsNull(table.border)) tableProperties.BorderSize =GeneralUtil.TryParseByte(table.border.ToString(),tableProperties.BorderSize); if (!table.align.IsNull()) tableProperties.TableAlignment = (HorizontalAlignOption)typeof(HorizontalAlignOption).TryParseEnum(table.align, HorizontalAlignOption.Default); // define the table rows and columns int rows = Math.Min(table.rows.length, Byte.MaxValue); int cols = Math.Min(table.cols, Byte.MaxValue); if (cols == 0 && rows > 0) { // cols value not set to get the maxiumn number of cells in the rows foreach (mshtmlTableRow tableRow in table.rows) { cols = Math.Max(cols, tableRow.cells.length); } } tableProperties.TableRows = (byte)Math.Min(rows, byte.MaxValue); tableProperties.TableColumns = (byte)Math.Min(cols, byte.MaxValue); // define the remaining table properties if (!GeneralUtil.IsNull(table.cellPadding)) tableProperties.CellPadding = GeneralUtil.TryParseByte(table.cellPadding.ToString(),tableProperties.CellPadding); if (!GeneralUtil.IsNull(table.cellSpacing)) tableProperties.CellSpacing = GeneralUtil.TryParseByte(table.cellSpacing.ToString(),tableProperties.CellSpacing); if (!GeneralUtil.IsNull(table.width)) { string tableWidth = table.width.ToString(); if (tableWidth.TrimEnd(null).EndsWith("%")) { tableProperties.TableWidth = tableWidth.Remove(tableWidth.LastIndexOf("%", StringComparison.Ordinal), 1).TryParseUshort(tableProperties.TableWidth); tableProperties.TableWidthMeasurement = MeasurementOption.Percent; } else { tableProperties.TableWidth = tableWidth.TryParseUshort(tableProperties.TableWidth); tableProperties.TableWidthMeasurement = MeasurementOption.Pixel; } } else { tableProperties.TableWidth = 0; tableProperties.TableWidthMeasurement = MeasurementOption.Pixel; } } catch (Exception ex) { // throw an exception indicating table structure change be determined throw new HtmlEditorException("Unable to determine Html Table properties.", "GetTableProperties", ex); } } // return the table properties return tableProperties; } //GetTableProperties
} // ProcessTablePrompt /// <summary> /// Method to insert a basic table /// Will honour the existing table if passed in /// </summary> private void ProcessTable(mshtmlTable table, HtmlTableProperty tableProperties) { try { // obtain a reference to the body node and indicate table present var bodyNode = (mshtmlDomNode)document.body; bool tableCreated = false; // ensure a table node has been defined to work with if (table.IsNull()) { // create the table and indicate it was created table = (mshtmlTable)document.createElement(TABLE_TAG); tableCreated = true; } // define the table border, width, cell padding and spacing table.border = tableProperties.BorderSize; if (tableProperties.TableWidth > 0) table.width = (tableProperties.TableWidthMeasurement == MeasurementOption.Pixel) ? string.Format("{0}", tableProperties.TableWidth) : string.Format("{0}%", tableProperties.TableWidth); else table.width = string.Empty; table.align = tableProperties.TableAlignment != HorizontalAlignOption.Default ? tableProperties.TableAlignment.ToString().ToLower() : string.Empty; table.cellPadding = tableProperties.CellPadding.ToString(CultureInfo.InvariantCulture); table.cellSpacing = tableProperties.CellSpacing.ToString(CultureInfo.InvariantCulture); // define the given table caption and alignment string caption = tableProperties.CaptionText; mshtmlTableCaption tableCaption = table.caption; if (!caption.IsNullOrEmpty()) { // ensure table caption correctly defined if (tableCaption.IsNull()) tableCaption = table.createCaption(); ((mshtmlElement)tableCaption).innerText = caption; if (tableProperties.CaptionAlignment != HorizontalAlignOption.Default) tableCaption.align = tableProperties.CaptionAlignment.ToString().ToLower(); if (tableProperties.CaptionLocation != VerticalAlignOption.Default) tableCaption.vAlign = tableProperties.CaptionLocation.ToString().ToLower(); } else { // if no caption specified remove the existing one if (!tableCaption.IsNull()) { // prior to deleting the caption the contents must be cleared ((mshtmlElement)tableCaption).innerText = null; table.deleteCaption(); } } // determine the number of rows one has to insert int numberRows, numberCols; if (tableCreated) { numberRows = Math.Max((int)tableProperties.TableRows, 1); } else { numberRows = Math.Max((int)tableProperties.TableRows, 1) - table.rows.length; } // layout the table structure in terms of rows and columns table.cols = tableProperties.TableColumns; if (tableCreated) { // this section is an optimization based on creating a new table // the section below works but not as efficiently numberCols = Math.Max((int)tableProperties.TableColumns, 1); // insert the appropriate number of rows mshtmlTableRow tableRow; for (int idxRow = 0; idxRow < numberRows; idxRow++) { tableRow = (mshtmlTableRow)table.insertRow(); // add the new columns to the end of each row for (int idxCol = 0; idxCol < numberCols; idxCol++) { tableRow.insertCell(); } } } else { // if the number of rows is increasing insert the decrepency if (numberRows > 0) { // insert the appropriate number of rows for (int idxRow = 0; idxRow < numberRows; idxRow++) { table.insertRow(); } } else { // remove the extra rows from the table for (int idxRow = numberRows; idxRow < 0; idxRow++) { table.deleteRow(table.rows.length - 1); } } // have the rows constructed // now ensure the columns are correctly defined for each row mshtmlElementCollection rows = table.rows; foreach (mshtmlTableRow tableRow in rows) { numberCols = Math.Max((int)tableProperties.TableColumns, 1) - tableRow.cells.length; if (numberCols > 0) { // add the new column to the end of each row for (int idxCol = 0; idxCol < numberCols; idxCol++) { tableRow.insertCell(); } } else { // reduce the number of cells in the given row // remove the extra rows from the table for (int idxCol = numberCols; idxCol < 0; idxCol++) { tableRow.deleteCell(tableRow.cells.length - 1); } } } } // if the table was created then it requires insertion into the DOM // otherwise property changes are sufficient if (tableCreated) { // table processing all complete so insert into the DOM var tableNode = (mshtmlDomNode)table; var tableElement = (mshtmlElement)table; mshtmlTextRange textRange = GetTextRange(); // final insert dependant on what user has selected if (!textRange.IsNull()) { // text range selected so overwrite with a table try { string selectedText = textRange.text; if (!selectedText.IsNull()) { // place selected text into first cell var tableRow = (mshtmlTableRow)table.rows.item(0, null); ((mshtmlElement)tableRow.cells.item(0, null)).innerText = selectedText; } textRange.pasteHTML(tableElement.outerHTML); } catch (Exception ex) { throw new HtmlEditorException("Invalid Text selection for the Insertion of a Table.", "ProcessTable", ex); } } else { mshtmlControlRange controlRange = GetAllControls(); if (!controlRange.IsNull()) { // overwrite any controls the user has selected try { // clear the selection and insert the table // only valid if multiple selection is enabled for (int idx = 1; idx < controlRange.length; idx++) { controlRange.remove(idx); } controlRange.item(0).outerHTML = tableElement.outerHTML; // this should work with initial count set to zero // controlRange.add((mshtmlControlElement)table); } catch (Exception ex) { throw new HtmlEditorException("Cannot Delete all previously Controls selected.", "ProcessTable", ex); } } else { // insert the table at the end of the HTML bodyNode.appendChild(tableNode); } } } else { // table has been correctly defined as being the first selected item // need to remove other selected items mshtmlControlRange controlRange = GetAllControls(); if (!controlRange.IsNull()) { // clear the controls selected other than than the first table // only valid if multiple selection is enabled for (int idx = 1; idx < controlRange.length; idx++) { controlRange.remove(idx); } } } } catch (Exception ex) { // throw an exception indicating table structure change error throw new HtmlEditorException("Unable to modify Html Table properties.", "ProcessTable", ex); } } //ProcessTable
} //ProcessTable /// <summary> /// Method to determine if the current selection is a table /// If found will return the table element /// </summary> private void GetTableElement(out mshtmlTable table, out mshtmlTableRow row) { row = null; mshtmlTextRange range = GetTextRange(); try { // first see if the table element is selected table = GetFirstControl() as mshtmlTable; // if table not selected then parse up the selection tree if (table.IsNull() && !range.IsNull()) { var element = range.parentElement(); // parse up the tree until the table element is found while (!element.IsNull() && table.IsNull()) { element = element.parentElement; // extract the Table properties var htmlTable = element as mshtmlTable; if (!htmlTable.IsNull()) { table = htmlTable; } // extract the Row properties var htmlTableRow = element as mshtmlTableRow; if (!htmlTableRow.IsNull()) { row = htmlTableRow; } } } } catch (Exception) { // have unknown error so set return to null table = null; row = null; } } //GetTableElement
} //TableDeleteRow /// <summary> /// Method to present to the user the table properties dialog /// Uses all the default properties for the table based on an insert operation /// </summary> private void ProcessTablePrompt(mshtmlTable table) { using (var dialog = new TablePropertyForm()) { // define the base set of table properties HtmlTableProperty tableProperties = GetTableProperties(table); // set the dialog properties dialog.TableProperties = tableProperties; DefineDialogProperties(dialog); // based on the user interaction perform the neccessary action if (dialog.ShowDialog(ParentForm) == DialogResult.OK) { tableProperties = dialog.TableProperties; if (table.IsNull()) TableInsert(tableProperties); else ProcessTable(table, tableProperties); } } } // ProcessTablePrompt