using com.insanitydesign.MarkdownViewerPlusPlus.Properties; using com.insanitydesign.MarkdownViewerPlusPlus.Windows; using Kbg.NppPluginNET; using Kbg.NppPluginNET.PluginInfrastructure; using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using static com.insanitydesign.MarkdownViewerPlusPlus.Windows.WindowsMessage; using System.Drawing.Printing; using TheArtOfDev.HtmlRenderer.PdfSharp; using System.Xml.Linq; using PdfSharp.Pdf; using System.IO; using System.Net; using com.insanitydesign.MarkdownViewerPlusPlus.Helper; using static com.insanitydesign.MarkdownViewerPlusPlus.MarkdownViewer; using Markdig; using System.Text.RegularExpressions; using System.Linq; using System.Collections.Generic; /// <summary> /// /// </summary> namespace com.insanitydesign.MarkdownViewerPlusPlus.Forms { /// <summary> /// /// </summary> public abstract partial class AbstractRenderer : Form { /// <summary> /// /// </summary> protected Icon toolbarIcon; /// <summary> /// /// </summary> protected MarkdownViewer markdownViewer; /// <summary> /// /// </summary> protected string assemblyTitle; /// <summary> /// /// </summary> protected virtual string RawText { get; set; } /// <summary> /// /// </summary> protected virtual string ConvertedText { get; set; } /// <summary> /// /// </summary> protected virtual FileInformation FileInfo { get; set; } /// <summary> /// /// </summary> protected MarkdownPipeline markdownPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); /// <summary> /// /// </summary> protected string patternCSSImportStatements = "(@import\\s.+;)"; /// <summary> /// /// </summary> /// <param name="markdownViewer"></param> public AbstractRenderer(MarkdownViewer markdownViewer) { this.markdownViewer = markdownViewer; InitializeComponent(); Init(); } /// <summary> /// /// </summary> protected virtual void Init() { // using (Bitmap newBmp = new Bitmap(16, 16)) { Graphics g = Graphics.FromImage(newBmp); ColorMap[] colorMap = new ColorMap[1]; colorMap[0] = new ColorMap(); colorMap[0].OldColor = Color.Fuchsia; colorMap[0].NewColor = Color.FromKnownColor(KnownColor.ButtonFace); ImageAttributes attr = new ImageAttributes(); attr.SetRemapTable(colorMap); g.DrawImage(Resources.markdown_16x16_solid_bmp, new Rectangle(0, 0, 16, 16), 0, 0, 16, 16, GraphicsUnit.Pixel, attr); toolbarIcon = Icon.FromHandle(newBmp.GetHicon()); } //Get the AssemblyTitle this.assemblyTitle = ((AssemblyTitleAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false)).Title; // NppTbData _nppTbData = new NppTbData(); _nppTbData.hClient = this.Handle; _nppTbData.pszName = this.assemblyTitle; _nppTbData.dlgID = this.markdownViewer.commandId; _nppTbData.uMask = NppTbMsg.DWS_DF_CONT_RIGHT | NppTbMsg.DWS_ICONTAB | NppTbMsg.DWS_ICONBAR; _nppTbData.hIconTab = (uint)toolbarIcon.Handle; _nppTbData.pszModuleName = Main.PluginName; IntPtr _ptrNppTbData = Marshal.AllocHGlobal(Marshal.SizeOf(_nppTbData)); Marshal.StructureToPtr(_nppTbData, _ptrNppTbData, false); //Register dockable window and hide initially Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_DMMREGASDCKDLG, 0, _ptrNppTbData); Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_DMMHIDE, 0, this.Handle); //Hide the E-mail items if Outlook is not installed this.sendAsTextMail.Visible = IsOutlookInstalled(); this.sendAsHTMLMail.Visible = IsOutlookInstalled(); } /// <summary> /// /// </summary> /// <param name="m"></param> protected override void WndProc(ref Message m) { //Listen for the closing of the dockable panel to toggle the toolbar icon switch (m.Msg) { case (int)WM_NOTIFY: var notify = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR)); if (notify.code == (int)DockMgrMsg.DMN_CLOSE) { this.markdownViewer.ToggleToolbarIcon(false); } break; } //Continue the processing, as we only toggle base.WndProc(ref m); } /// <summary> /// /// </summary> /// <param name="text"></param> /// <param name="fileInfo"></param> public virtual void Render(string text, FileInformation fileInfo) { FileInfo = fileInfo; RawText = text; ConvertedText = Markdown.ToHtml(text, this.markdownPipeline); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void refreshToolStripMenuItem_Click(object sender, EventArgs e) { this.markdownViewer.Update(); } /// <summary> /// Scroll the rendered panel vertically based on the given ration /// taken from Notepad++ /// </summary> /// <param name="scrollRatio"></param> public abstract void ScrollByRatioVertically(double scrollRatio); /// <summary> /// /// </summary> /// <param name="html"></param> /// <param name="title"></param> /// <returns></returns> protected string BuildHtml(string html = "", string title = "") { // if (title == "") title = this.assemblyTitle; // return $@" <!DOCTYPE html> <html> <head> <meta charset=""UTF-8"" /> <meta name=""author"" content=""{this.assemblyTitle}"" /> <title>{title}</title> <style type=""text/css""> {this.getCSS()} </style> </head> <body> {html} </body> </html> "; } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void sendAsTextMail_Click(object sender, EventArgs e) { //Double-check if (IsOutlookInstalled()) { //Outlook.Application outlook = new Outlook.Application(); //Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem); //// //message.Subject = this.FileInfo.FileName; //message.BodyFormat = Outlook.OlBodyFormat.olFormatPlain; //message.Body = RawText; //message.Display(); } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void sendAsHTMLMail_Click(object sender, EventArgs e) { //Double-check if (IsOutlookInstalled()) { //Outlook.Application outlook = new Outlook.Application(); //Outlook.MailItem message = (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem); //// //message.Subject = this.FileInfo.FileName; //message.BodyFormat = Outlook.OlBodyFormat.olFormatHTML; //message.HTMLBody = BuildHtml(ConvertedText, this.FileInfo.FileName); //message.Display(true); } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void exportAsHTMLMenuItem_Click(object sender, EventArgs e) { //Save! SaveFileDialog saveFileDialog = new SaveFileDialog(); //Default name of the file is the editor file name saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".html"; //The current path saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory(); // saveFileDialog.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*"; // if (saveFileDialog.ShowDialog() == DialogResult.OK) { using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName)) { string html = BuildHtml(ConvertedText, this.FileInfo.FileName); try { html = XDocument.Parse(html).ToString(); } catch { } sw.WriteLine(html); } //Open if requested if (this.markdownViewer.Options.htmlOpenExport) { Process.Start(saveFileDialog.FileName); } } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void exportAsPDFMenuItem_Click(object sender, EventArgs e) { //Save! SaveFileDialog saveFileDialog = new SaveFileDialog(); //Default name of the file is the editor file name saveFileDialog.FileName = Path.GetFileNameWithoutExtension(this.FileInfo.FileName) + ".pdf"; //The current path saveFileDialog.InitialDirectory = this.markdownViewer.Notepad.GetCurrentDirectory(); // saveFileDialog.Filter = "PDF files (*.pdf)|*.pdf|All files (*.*)|*.*"; // if (saveFileDialog.ShowDialog() == DialogResult.OK) { //Build a config based on made settings PdfGenerateConfig pdfConfig = new PdfGenerateConfig(); pdfConfig.PageOrientation = this.markdownViewer.Options.pdfOrientation; pdfConfig.PageSize = this.markdownViewer.Options.pdfPageSize; //Set margins int[] margins = this.markdownViewer.Options.GetMargins(); pdfConfig.MarginLeft = MilimiterToPoint(margins[0]); pdfConfig.MarginTop = MilimiterToPoint(margins[1]); pdfConfig.MarginRight = MilimiterToPoint(margins[2]); pdfConfig.MarginBottom = MilimiterToPoint(margins[3]); //Generate PDF and save PdfDocument pdf = PdfGenerator.GeneratePdf(BuildHtml(ConvertedText, this.FileInfo.FileName), pdfConfig, PdfGenerator.ParseStyleSheet(this.getCSS())); pdf.Save(saveFileDialog.FileName); //Open if requested if (this.markdownViewer.Options.pdfOpenExport) { Process.Start(saveFileDialog.FileName); } } } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void sendToPrinter_Click(object sender, EventArgs e) { // WebBrowser webBrowser = new WebBrowser(); webBrowser.Parent = this; webBrowser.DocumentCompleted += (browser, webBrowserEvent) => { ((WebBrowser)browser).Size = webBrowser.MaximumSize; ((WebBrowser)browser).ShowPrintPreviewDialog(); }; webBrowser.DocumentText = BuildHtml(ConvertedText, this.FileInfo.FileName); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void sendToClipboard_Click(object sender, EventArgs e) { ClipboardHelper.CopyToClipboard(BuildHtml(ConvertedText, this.FileInfo.FileName), ConvertedText); } /// <summary> /// /// </summary> /// <returns></returns> protected virtual String getCSS() { string cssImportStatements = ""; //Get all @import statements from the custom CSS List<Match> matches = Regex.Matches(this.markdownViewer.Options.HtmlCssStyle, this.patternCSSImportStatements).Cast<Match>().ToList(); matches.ForEach(match => match.Captures.Cast<Capture>().ToList().ForEach(capture => cssImportStatements += capture.Value + Environment.NewLine)); //Return a CSS with the @import statements in front, the base MarkdownViewer++ CSS and the rest of the custom CSS from the user return cssImportStatements + Environment.NewLine + Resources.MarkdownViewerHTML + Environment.NewLine + Regex.Replace(this.markdownViewer.Options.HtmlCssStyle, this.patternCSSImportStatements, "").Trim(); } /// <summary> /// /// </summary> /// <param name="mm"></param> /// <returns></returns> protected int MilimiterToPoint(int mm) { return (int)(mm * 2.834646); } /// <summary> /// /// </summary> /// <returns></returns> public bool IsOutlookInstalled() { try { if (Type.GetTypeFromProgID("Outlook.Application") != null) { return true; } } catch { } return false; } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void optionsToolStripMenuItem_Click(object sender, EventArgs e) { this.markdownViewer.OptionsCommand(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void aboutToolStripMenuItem1_Click(object sender, EventArgs e) { this.markdownViewer.AboutCommand(); } } }