|
//� 2005 Thaddaeus Parker thaddparker(at)usa(dot)net
//This code is free to use and modify as long as this statement is left intact.
//All other copyrights are held by their respective owners
using System;
using System.Text.RegularExpressions;
using System.Collections;
namespace OverLibWrapper.Design
{
/// <summary>
/// OverlibPopupTextBuilder builds complex text.
/// </summary>
public class OverlibPopupTextBuilder
{
private System.Web.UI.WebControls.Table _table;
private System.Text.StringBuilder text = new System.Text.StringBuilder("");
private string originalText;
private bool _hasHTML = false;
private bool _hasInnerPopups = false;
private System.IO.StringWriter stringWriter;
private System.Web.UI.HtmlTextWriter textWriter;
/// <summary>
/// Creates a new <see cref="OverlibPopupTextBuilder"/> instance.
/// </summary>
public OverlibPopupTextBuilder(){
}
/// <summary>
/// Returns the text that was built for the popup.
/// </summary>
/// <returns>A string that represents the text that will be shown in the popup</returns>
public string PopupText(){
if (this._table != null) {
stringWriter = new System.IO.StringWriter();
textWriter = new System.Web.UI.HtmlTextWriter(stringWriter);
this._table.RenderControl(textWriter);
textWriter.Close();
_hasHTML = true;
}
this.text = new System.Text.StringBuilder("");
this.text = stringWriter.GetStringBuilder().Insert(0,originalText+"\n");
stringWriter.Close();
return this.text.ToString();
}
/// <summary>
/// Gets a value indicating whether this instance has HTML.
/// </summary>
/// <value>
/// <c>true</c> if this instance has HTML; otherwise, <c>false</c>.
/// </value>
public bool HasHTML{
get{return _hasHTML;}
}
/// <summary>
/// Adds the inner tool tip. You must create a new popup and set the innerPopup property to true
/// </summary>
/// <param name="rowIndex">row number.</param>
/// <param name="cellIndex">cell number</param>
/// <param name="tipHyperlink">the hyperlink string</param>
public void AddInnerToolTip(int rowIndex,int cellIndex,string tipHyperlink){
if(tipHyperlink.Trim().Length !=0){
if(this._table != null){
if( this._table.Rows.Count > rowIndex){
if(this._table.Rows[rowIndex].Cells.Count > cellIndex ){
this._table.Rows[rowIndex].Cells[cellIndex].Text = tipHyperlink;
_hasInnerPopups = true;
}
}
}
}
}
/// <summary>
/// Adds a html table to the popup content.
/// </summary>
public void AddTable() {
if(this._table == null){
this._table = new System.Web.UI.WebControls.Table();
this._table.Attributes.Remove("border");
}
}
/// <summary>
/// Adds the table attribute.
/// </summary>
/// <param name="attrib">The attribute to add.</param>
/// <param name="value">The string value of that attribute.</param>
public void AddTableAttribute(string attrib, string value){
this._table.Attributes.Add(attrib,value);
}
/// <summary>
/// Adds a row to the internal table.
/// </summary>
/// <remarks>If another table is needed inside the current table create another OverlibPopupTextBuilder
/// and create the table there. Then add the html to a particular cell or row</remarks>
/// <returns>An integer index of the row that is added to the table</returns>
public int AddTableRow(){
System.Web.UI.WebControls.TableRow tableRow = new System.Web.UI.WebControls.TableRow();
int rowIndex = this._table.Rows.Add(tableRow);
return rowIndex;
}
/// <summary>
/// Adds the table row attribute.
/// </summary>
/// <param name="rowIndex">Row index.</param>
/// <param name="attrib">Attrib.</param>
/// <param name="value">Value.</param>
public void AddRowAttribute(int rowIndex, string attrib, string value){
if (this._table.Rows.Count > rowIndex) {
this._table.Rows[rowIndex].Attributes.Add(attrib, value);
}
}
/// <summary>
/// Adds the row cell. See remarks in <seealso cref="AddTableRow"/>
/// </summary>
/// <param name="rowIndex">Row index.</param>
/// <param name="contents">Contents.</param>
/// <returns>An integer index of the cell that is added to the row</returns>
public int AddRowCell(int rowIndex, string contents){
int cellIndex = -1;
if (this._table.Rows.Count > rowIndex) {
System.Web.UI.WebControls.TableCell cell = new System.Web.UI.WebControls.TableCell();
_hasInnerPopups = ParseContentsForInnerPopup(contents);
cell.Text = contents;
cellIndex = this._table.Rows[rowIndex].Cells.Add(cell);
}
return cellIndex;
}
/// <summary>
/// Adds the cell attribute.
/// </summary>
/// <param name="rowIndex">Row index.</param>
/// <param name="cellIndex">Cell index.</param>
/// <param name="attrib">Attrib.</param>
/// <param name="val">Val.</param>
public void AddCellAttribute(int rowIndex, int cellIndex, string attrib, string val){
if(this._table.Rows.Count > rowIndex){
if(this._table.Rows[rowIndex].Cells.Count > cellIndex){
this._table.Rows[rowIndex].Cells[cellIndex].Attributes.Add(attrib,val);
}
}
}
/// <summary>
/// Adds the bullet list.
/// </summary>
/// <param name="rowIndex">Row index.</param>
/// <param name="cellIndex">Cell index.</param>
/// <param name="bullets">Bullets.</param>
public void AddBulletList(int rowIndex, int cellIndex, params string[] bullets){
if(bullets.Length == 0){
return;
}
System.Text.StringBuilder str = new System.Text.StringBuilder();
str.Append("<ul>");
foreach(string s in bullets){
str.Append("<li>"+ s + "</li>");
}
str.Append("</ul>");
if(this._table.Rows.Count > rowIndex){
if(this._table.Rows[rowIndex].Cells.Count > cellIndex){
this._table.Rows[rowIndex].Cells[cellIndex].Text = str.ToString();
}
}
}
/// <summary>
/// Adds the numbered list.
/// </summary>
/// <param name="rowIndex">Row index.</param>
/// <param name="cellIndex">Cell index.</param>
/// <param name="bullets">Bullets.</param>
public void AddNumberedList(int rowIndex, int cellIndex, params string[] bullets){
if(bullets.Length == 0){
return;
}
System.Text.StringBuilder str = new System.Text.StringBuilder("");
str.Append("<ol>");
foreach(string s in bullets){
str.Append("<li>"+ s + "</li>");
}
str.Append("</ol>");
if(this._table.Rows.Count > rowIndex){
if(this._table.Rows[rowIndex].Cells.Count > cellIndex){
this._table.Rows[rowIndex].Cells[cellIndex].Text = str.ToString();
}
}
}
private bool ParseContentsForInnerPopup(string contents){
bool innerPopup = false;
int beginTag = -1;
beginTag = contents.Trim().IndexOf("<a");
int endTag = contents.Trim().IndexOf("/a>");
int overlib2Tag = contents.Trim().IndexOf("overlib2(");
if(overlib2Tag > -1){
innerPopup = true;
}
return innerPopup;
}
private string ParseInputString(string input){
string[] inputs = input.Split(' ');
System.Text.StringBuilder content = new System.Text.StringBuilder();
int index = input.IndexOf("<table");
if(index == -1){
return input;
}
if(index == 0){
this._table = new System.Web.UI.WebControls.Table();
}
return content.ToString();
}
/// <summary>
/// This parses text incoming that either is just text or html style text. This function
/// uses major regular expressions
/// </summary>
/// <param name="content">The string of content to parse</param>
/// <returns>A HTML table formatted group of text that represents the inner content of Popup text</returns>
public string ParseText(string content){
System.Text.StringBuilder str =new System.Text.StringBuilder("");
stringWriter = new System.IO.StringWriter(str);
textWriter = new System.Web.UI.HtmlTextWriter(stringWriter);
// string htmltable = "dsfalfdsalfds<table border='0' cellpadding=2><tr class='text'><td rowspan=3>hello</td><td>1</td><td class=yahoo>22222</td></tr>"+
// "<tr class='blah2'><td>2</td><td class='blah'>3</td><td>blahhhdndn</td></tr></table> endblah";
const string table = @"(?<content>[\w\W]*)\<table(?<attribs>[^\>]*)\>";
const string tr = @"\<tr(?<attribs>[^\>]*)\>";
const string td = @"\<td(?<attribs>[^\>]*)>(?<content>[^</td]*)";
const string endtable = @"\</table\>(?<content>[\w\W]*)";
string endText = "";
int patternCount = 0;
int rowCount = 0;
//puts the regular expressions in order of usual appearance within an HTML document
ArrayList regexs = new ArrayList();
regexs.Add(table);
regexs.Add(tr);
regexs.Add(td);
regexs.Add(endtable);
//grabs each one of the patterns specified
//TODO: find a way to extend this function to grab inner html content
foreach (string pattern in regexs) {
Regex regEx = new Regex(pattern, RegexOptions.Compiled|RegexOptions.IgnoreCase|RegexOptions.Singleline);
if (regEx.IsMatch(content)) {
MatchCollection matches = regEx.Matches(content);
int matchIndex = 0;
int rowCounter = 0;
int cellCount = 0;
foreach (Match match in matches) {
switch (patternCount) {
case 0: // table
//this gets the content before the table tag
if(match.Groups["content"].ToString().Trim().Length != 0){
str.Append(match.Groups["content"].ToString().Trim());
}
//we want to ensure about a new table here
_table = new System.Web.UI.WebControls.Table();
//clear the existing attributes with the premade table
//this seems to be a problem, because you cannot go in and edit a particular
//attribute. So we just clear them out and start fresh
_table.Attributes.Remove("border");
_table.Attributes.Clear();
Hashtable tableAttribHash = GetAttributes(match);
foreach(string key in tableAttribHash.Keys){
_table.Attributes.Add(key,tableAttribHash[key].ToString());
}
break;
case 1: //row
//creates a new row, adds the attributes found and inserts it into the table
Hashtable rowAttribHash = GetAttributes(match);
System.Web.UI.WebControls.TableRow row = new System.Web.UI.WebControls.TableRow();
foreach(string key in rowAttribHash.Keys){
row.Attributes.Add(key,rowAttribHash[key].ToString());
}
_table.Rows.Add(row);
rowCount++; //this is used for the "cell" install feature in case 2:
break;
case 2: //cell
//TODO: Figure out a way to deal with odd numbered cells for the rows.
//this particular case only deals with even numbered cells
//that is even if there is a rowspan attribute on the the function will fail miserably!!
int rowCells = matches.Count/rowCount;
Hashtable cellAttribHash = GetAttributes(match);
System.Web.UI.WebControls.TableCell cell = new System.Web.UI.WebControls.TableCell();
foreach(string key in cellAttribHash.Keys){
cell.Attributes.Add(key,cellAttribHash[key].ToString());
}
if(match.Groups["content"].ToString().Trim().Length != 0){
cell.Text = match.Groups["content"].ToString().Trim();
}
_table.Rows[rowCounter].Cells.Add(cell);
cellCount++;
if(cellCount == rowCells){
rowCounter++;
}
// cellsList.Add(cell);
break;
case 3: //end content
//this grabs the content that is immediately after the end table tag
if(match.Groups["content"].ToString().Trim().Length != 0){
endText = match.Groups["content"].ToString().Trim();
}
break;
}
matchIndex++;
} // foreach (Match match in regEx.Matches)
} else{ // if (regEx.IsMatch(table))
//if we don't any type of match we know that a table doesn't exist within the string
//we will just return the content assuming that it is a pure string.
if(patternCount == 0){
originalText = content; //maintain an original if there is nothing
this.text.Append(content); //this is to ensure that whatever text was sent in is retained by the builder
return content; //this is due to the fact that if the table wasn't found then
//why should we go any further;
}
}
patternCount++;
}
_table.RenderControl(textWriter);
textWriter.Close();
stringWriter.Close();
str.Append(endText);
this.text = str;
_hasHTML = true;
return text.ToString();
}
/// <summary>
/// Gets the attributes for a particular regular expression match.
/// </summary>
/// <param name="match">A found match that contains possible attributes</param>
/// <returns>A hashtable that contains the keys and their values</returns>
private Hashtable GetAttributes(Match match) {
Hashtable attribsHash = new Hashtable();
const string attrPattern = "(?<Keyword>\\w+)(?<equals>\\s*=\\s*)([\\s'\"]*)(?<Value>[^\\s'\"]*)([\\s'\"]*)(?<whitespace>\\s*)";
Group attributeGroup = match.Groups["attribs"];
Regex attribs = new Regex(attrPattern);
if (attribs.IsMatch(attributeGroup.ToString())) {
foreach (Match attribMatch in attribs.Matches(attributeGroup.ToString())) {
attribsHash.Add(attribMatch.Groups["Keyword"].ToString().Trim().ToLower(),attribMatch.Groups["Value"].ToString().Trim().ToLower());
}
}
return attribsHash;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
A software developer for a medium sized company with a Microsoft product core development strategy.