Line   1:// Program to convert VS cut and paste code to nice HTML                                                           
Line   2:// Chris Lomont, 2008, C# 3.5, Visual Studio.NET                                                                   
Line   3:// www.lomont.org                                                                                                  
Line   4:// Based on Kevin Moore's http://work.j832.com/2008/01/source-code-html-and-exercise-for.html                      
Line   5:// Support for tabs, coloring, numbering, color selction, persistence, etc. added                                  
Line   6:using System;                                                                                                      
Line   7:using System.Collections.Generic;                                                                                  
Line   8:using System.Diagnostics;                                                                                          
Line   9:using System.Linq;                                                                                                 
Line  10:using System.Web;                                                                                                  
Line  11:using System.Windows;                                                                                              
Line  12:using System.Windows.Controls;                                                                                     
Line  13:using System.Windows.Documents;                                                                                    
Line  14:using System.Windows.Media;                                                                                        
Line  15:using System.Text;                                                                                                 
Line  16:using System.ComponentModel;                                                                                       
Line  17:using System.Windows.Input;                                                                                        
Line  18:                                                                                                                   
Line  19:/* TODO                                                                                                            
Line  20: * 1. Work on ColorPicker: color list, editable RGB, HSV, color wheel, visual picking.                             
Line  21: * 2. Clean up Value Converters - learn Data Binding better and make cleaner                                       
Line  22: * 3. Threaded working if possible, better visual of progress (nice progress bar)                                  
Line  23: * 4. Create much cleaner HTML if possible- extract CSS elsewhere?                                                 
Line  24: * 5. Make into Visual Studio plug-in: selected or all code to HTML                                                
Line  25: * */                                                                                                              
Line  26:                                                                                                                   
Line  27:namespace VSToHTML                                                                                                 
Line  28:    {                                                                                                              
Line  29:    /// <summary>                                                                                                  
Line  30:    /// Main window class                                                                                          
Line  31:    /// </summary>                                                                                                 
Line  32:    public partial class MainWindow : WindowINotifyPropertyChanged                                               
Line  33:        {                                                                                                          
Line  34:        /// <summary>                                                                                              
Line  35:        /// Spaces per tab, and a string representation for HTML                                                   
Line  36:        /// </summary>                                                                                             
Line  37:        int tabSize_ = 4;                                                                                          
Line  38:        public int TabSize                                                                                         
Line  39:            {                                                                                                      
Line  40:            get                                                                                                    
Line  41:                {                                                                                                  
Line  42:                return tabSize_;                                                                                   
Line  43:                }                                                                                                  
Line  44:            set                                                                                                    
Line  45:                {                                                                                                  
Line  46:                tabSize_ = value;                                                                                  
Line  47:                StringBuilder sb = new StringBuilder();                                                            
Line  48:                for (int i = 0; i < tabSize_; ++i)                                                                 
Line  49:                    sb.Append("&nbsp;");                                                                           
Line  50:                tabString = sb.ToString();                                                                         
Line  51:                }                                                                                                  
Line  52:            }                                                                                                      
Line  53:        string tabString = null;                                                                                   
Line  54:                                                                                                                   
Line  55:        /// <summary>                                                                                              
Line  56:        /// Colors for the coding of the HTML                                                                      
Line  57:        /// </summary>                                                                                             
Line  58:        public Color OddColor { getset; }                                                                        
Line  59:        public Color EvenColor { getset; }                                                                       
Line  60:        public Color LineColor { getset; }                                                                       
Line  61:                                                                                                                   
Line  62:        public MainWindow()                                                                                        
Line  63:            {                                                                                                      
Line  64:            // restore settings                                                                                    
Line  65:            OddColor = Properties.Settings.Default.OddColor;                                                       
Line  66:            EvenColor = Properties.Settings.Default.EvenColor;                                                     
Line  67:            LineColor = Properties.Settings.Default.LineColor;                                                     
Line  68:            TabSize = Properties.Settings.Default.tabSize;                                                         
Line  69:                                                                                                                   
Line  70:            InitializeComponent();                                                                                 
Line  71:                                                                                                                   
Line  72:            // set these settings after the UI has been constructed                                                
Line  73:            showLineNumberBox.IsChecked = Properties.Settings.Default.Numbering;                                   
Line  74:            showLineTextBox.IsChecked = Properties.Settings.Default.LineText;                                      
Line  75:            }                                                                                                      
Line  76:                                                                                                                   
Line  77:                                                                                                                   
Line  78:        #region UI events                                                                                          
Line  79:        private void richTextBox_TextChanged(object sender, TextChangedEventArgs e)                                
Line  80:            {                                                                                                      
Line  81:            ComputeHTML();                                                                                         
Line  82:            }                                                                                                      
Line  83:                                                                                                                   
Line  84:        private void convertButton_Click(object sender, RoutedEventArgs e)                                         
Line  85:            {                                                                                                      
Line  86:            ComputeHTML();                                                                                         
Line  87:            }                                                                                                      
Line  88:                                                                                                                   
Line  89:        private void evenColorButton_Click(object sender, RoutedEventArgs e)                                       
Line  90:            {                                                                                                      
Line  91:            EvenColor = SelectColor(EvenColor);                                                                    
Line  92:            OnPropertyChanged("EvenColor");                                                                        
Line  93:            }                                                                                                      
Line  94:                                                                                                                   
Line  95:        private void oddColorButton_Click(object sender, RoutedEventArgs e)                                        
Line  96:            {                                                                                                      
Line  97:            OddColor = SelectColor(OddColor);                                                                      
Line  98:            OnPropertyChanged("OddColor");                                                                         
Line  99:            }                                                                                                      
Line 100:                                                                                                                   
Line 101:        private void lineColorButton_Click(object sender, RoutedEventArgs e)                                       
Line 102:            {                                                                                                      
Line 103:            LineColor = SelectColor(LineColor);                                                                    
Line 104:            OnPropertyChanged("LineColor");                                                                        
Line 105:            }                                                                                                      
Line 106:                                                                                                                   
Line 107:        Color SelectColor(Color color)                                                                             
Line 108:            {                                                                                                      
Line 109:            ColorPicker cp = new ColorPicker(color);                                                               
Line 110:            cp.ShowDialog();                                                                                       
Line 111:            return cp.Color;                                                                                       
Line 112:            }                                                                                                      
Line 113:                                                                                                                   
Line 114:        private void Hyperlink_Click(object sender, RoutedEventArgs e)                                             
Line 115:            {                                                                                                      
Line 116:            string navigateUri = ((Hyperlink)(sender)).NavigateUri.ToString();                                     
Line 117:            Process.Start(new ProcessStartInfo(navigateUri));                                                      
Line 118:            e.Handled = true;                                                                                      
Line 119:            }                                                                                                      
Line 120:        #endregion                                                                                                 
Line 121:                                                                                                                   
Line 122:        #region HTML Conversion                                                                                    
Line 123:        /// <summary>                                                                                              
Line 124:        /// Convert the colored text in the left pane to HTML in                                                   
Line 125:        /// the right pane while applying the user options                                                         
Line 126:        /// </summary>                                                                                             
Line 127:        void ComputeHTML()                                                                                         
Line 128:            {                                                                                                      
Line 129:            Cursor = Cursors.Wait;                                                                                 
Line 130:            // statusText.Content = "Thinking...!"; // todo - make work                                            
Line 131:            int lineNumber = 1, maxLine = 1, maxLength = 0;                                                        
Line 132:                                                                                                                   
Line 133:            // Compute the number of lines to allow proper spacing of counter                                      
Line 134:            foreach (Paragraph paragraph in richTextBox.Document.Blocks.Cast<Paragraph>())                         
Line 135:                {                                                                                                  
Line 136:                ++maxLine;                                                                                         
Line 137:                int length = 0;                                                                                    
Line 138:                foreach (Run run in Decompose(paragraph.Inlines))                                                  
Line 139:                    length += TextLength(run.Text);                                                                
Line 140:                maxLength = Math.Max(length,maxLength);                                                            
Line 141:                }                                                                                                  
Line 142:                                                                                                                   
Line 143:            // Get a formatting string for line counter region                                                     
Line 144:            bool showLines = (showLineNumberBox.IsChecked == true);                                                
Line 145:            string lineText = "";                                                                                  
Line 146:            if ((showLineTextBox.IsChecked == true) && (showLines == true))                                        
Line 147:                lineText = "Line ";                                                                                
Line 148:            string format = String.Format("{0}{{0,{1}}}:",                                                         
Line 149:                lineText,                                                                                          
Line 150:                (int)Math.Ceiling(Math.Log(maxLine, 10)));                                                         
Line 151:                                                                                                                   
Line 152:            textBoxHTML.Clear();                                                                                   
Line 153:            textBoxHTML.AppendText("<div style=\"font-family:monospace;\">" + Environment.NewLine);                
Line 154:            textBoxHTML.AppendText("<code>" + Environment.NewLine);                                                
Line 155:                                                                                                                   
Line 156:            // todo - make cleaner HTML if colors same                                                             
Line 157:            string lineColor = String.Format("<span style=\"color:#000; background-color: #{0}\">",                
Line 158:                LineColor.ToString().Substring(3));                                                                
Line 159:            string evenLineString = String.Format("<span style=\"background-color: #{0}\">",                       
Line 160:                EvenColor.ToString().Substring(3));                                                                
Line 161:            string oddLineString = String.Format("<span style=\"background-color: #{0}\">",                        
Line 162:                OddColor.ToString().Substring(3));                                                                 
Line 163:                                                                                                                   
Line 164:            // Iterate over items in the left pane                                                                 
Line 165:            foreach (Paragraph paragraph in richTextBox.Document.Blocks.Cast<Paragraph>())                         
Line 166:                {                                                                                                  
Line 167:                if (showLines)                                                                                     
Line 168:                    {                                                                                              
Line 169:                    string temp = lineColor + String.Format(format, lineNumber).Replace(" ""&nbsp;") + "</span>";
Line 170:                    textBoxHTML.AppendText(temp);                                                                  
Line 171:                    }                                                                                              
Line 172:                if ((lineNumber&1) == 1)                                                                           
Line 173:                    textBoxHTML.AppendText(evenLineString);                                                        
Line 174:                else                                                                                               
Line 175:                    textBoxHTML.AppendText(oddLineString);                                                         
Line 176:                ++lineNumber;                                                                                      
Line 177:                                                                                                                   
Line 178:                int lineLength = 0;                                                                                
Line 179:                foreach (Run run in Decompose(paragraph.Inlines))                                                  
Line 180:                    {                                                                                              
Line 181:                    lineLength += TextLength(run.Text);                                                            
Line 182:                    textBoxHTML.AppendText(ToCleanedColoredSpan(run));                                             
Line 183:                    }                                                                                              
Line 184:                // append spaces to make all lines same length                                                     
Line 185:                // todo - not needed if colors not same and whole block same color?!                               
Line 186:                while (lineLength++ < maxLength)                                                                   
Line 187:                    textBoxHTML.AppendText("&nbsp;");                                                              
Line 188:                textBoxHTML.AppendText("</span><br/>" + Environment.NewLine);                                      
Line 189:                }                                                                                                  
Line 190:            textBoxHTML.AppendText("</div>");                                                                      
Line 191:            textBoxHTML.AppendText("</code>" + Environment.NewLine);                                               
Line 192:            Clipboard.SetText(textBoxHTML.Text);                                                                   
Line 193:            statusText.Content = "Done!"// todo - reset after a few secs?                                        
Line 194:            Cursor = null;                                                                                         
Line 195:            } // ComputeHTML                                                                                       
Line 196:                                                                                                                   
Line 197:        /// <summary>                                                                                              
Line 198:        /// Compute the string length, including tab replacements                                                  
Line 199:        /// </summary>                                                                                             
Line 200:        /// <param name="str">The string to measure</param>                                                        
Line 201:        /// <returns>String length</returns>                                                                       
Line 202:        private int TextLength(string str)                                                                         
Line 203:            {                                                                                                      
Line 204:            string str2 = str.Replace("\t"new string(' ', TabSize));                                             
Line 205:            return str2.Length;                                                                                    
Line 206:            }                                                                                                      
Line 207:                                                                                                                   
Line 208:        private string ToCleanedColoredSpan(Run run)                                                               
Line 209:            {                                                                                                      
Line 210:            //Debug.WriteLine(run.Text);                                                                           
Line 211:            SolidColorBrush solidColorBrush = run.Foreground as SolidColorBrush;                                   
Line 212:            if (solidColorBrush == null)                                                                           
Line 213:                return CleanString(run.Text);                                                                      
Line 214:            else                                                                                                   
Line 215:                {                                                                                                  
Line 216:                if (solidColorBrush.Color == Colors.Black)                                                         
Line 217:                    return CleanString(run.Text);                                                                  
Line 218:                else                                                                                               
Line 219:                    {                                                                                              
Line 220:                    string colorString = solidColorBrush.Color.ToString();                                         
Line 221:                    Debug.Assert(colorString.Length == 9);                                                         
Line 222:                                                                                                                   
Line 223:                    colorString = colorString.Substring(3);                                                        
Line 224:                                                                                                                   
Line 225:                    return string.Format("<span style=\"color:#{0};\">{1}</span>",                                 
Line 226:                        colorString, CleanString(run.Text));                                                       
Line 227:                    }                                                                                              
Line 228:                }                                                                                                  
Line 229:            } // ToCleanedColoredSpan                                                                              
Line 230:                                                                                                                   
Line 231:        private string CleanString(string source)                                                                  
Line 232:            {                                                                                                      
Line 233:            source = HttpUtility.HtmlEncode(source);                                                               
Line 234:            source = source.Replace("\t", tabString);                                                              
Line 235:            source = source.Replace(" ""&nbsp;");                                                                
Line 236:            return source;                                                                                         
Line 237:            }                                                                                                      
Line 238:                                                                                                                   
Line 239:        private static IEnumerable<Run> Decompose(IEnumerable<Inline> inlines)                                     
Line 240:            {                                                                                                      
Line 241:            foreach (Inline inline in inlines)                                                                     
Line 242:                {                                                                                                  
Line 243:                if (inline is Span)                                                                                
Line 244:                    {                                                                                              
Line 245:                    foreach (Run run in Decompose(((Span)inline).Inlines))                                         
Line 246:                        yield return run;                                                                          
Line 247:                    }                                                                                              
Line 248:                else if (inline is Run)                                                                            
Line 249:                    yield return (Run)inline;                                                                      
Line 250:                else                                                                                               
Line 251:                    throw new NotSupportedException();                                                             
Line 252:                }                                                                                                  
Line 253:            }                                                                                                      
Line 254:        #endregion                                                                                                 
Line 255:                                                                                                                   
Line 256:        #region App events                                                                                         
Line 257:        private void mainWindow_Closing(object sender, CancelEventArgs e)                                          
Line 258:            {                                                                                                      
Line 259:            // save settings to Properties                                                                         
Line 260:            Properties.Settings.Default.OddColor = OddColor;                                                       
Line 261:            Properties.Settings.Default.EvenColor = EvenColor;                                                     
Line 262:            Properties.Settings.Default.LineColor = LineColor;                                                     
Line 263:            Properties.Settings.Default.tabSize = TabSize;                                                         
Line 264:            Properties.Settings.Default.Numbering = showLineNumberBox.IsChecked == true;                           
Line 265:            Properties.Settings.Default.LineText = showLineTextBox.IsChecked == true;                              
Line 266:                                                                                                                   
Line 267:            // save Properties                                                                                     
Line 268:            Properties.Settings.Default.Save();                                                                    
Line 269:            }                                                                                                      
Line 270:                                                                                                                   
Line 271:        private void doneButton_Click(object sender, RoutedEventArgs e)                                            
Line 272:            {                                                                                                      
Line 273:            Close();                                                                                               
Line 274:            }                                                                                                      
Line 275:        #endregion                                                                                                 
Line 276:                                                                                                                   
Line 277:        #region INotifyPropertyChanged Members                                                                     
Line 278:                                                                                                                   
Line 279:        public event PropertyChangedEventHandler PropertyChanged;                                                  
Line 280:                                                                                                                   
Line 281:        // Create the OnPropertyChanged method to raise the event                                                  
Line 282:        protected void OnPropertyChanged(string property)                                                          
Line 283:            {                                                                                                      
Line 284:            PropertyChangedEventHandler handler = PropertyChanged;                                                 
Line 285:            if (handler != null)                                                                                   
Line 286:                handler(thisnew PropertyChangedEventArgs(property));                                             
Line 287:            }                                                                                                      
Line 288:        #endregion                                                                                                 
Line 289:                                                                                                                   
Line 290:        }                                                                                                          
Line 291:    }                                                                                                              
Line 292:                                                                                                                   
Line 293:// end of file                                                                                                     
Line 294: