From 1de2054709d87f31e15cd29ec6692ed158a5b595 Mon Sep 17 00:00:00 2001 From: hOLOlu Date: Sat, 4 Jul 2026 22:20:26 +0300 Subject: [PATCH] Fix toolstrip textbox scaling, browse button alignment, and WebBrowser optical zoom --- hMarkdown/Form1.cs | 1075 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 884 insertions(+), 191 deletions(-) diff --git a/hMarkdown/Form1.cs b/hMarkdown/Form1.cs index 7f55a23..7b52e5a 100644 --- a/hMarkdown/Form1.cs +++ b/hMarkdown/Form1.cs @@ -1,191 +1,884 @@ -using Markdig; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using static System.Net.Mime.MediaTypeNames; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrayNotify; - - -namespace hMarkdown -{ - public partial class Form1 : Form - { - public Form1(string fn) - { - InitializeComponent(); - this.DragEnter += Form1_DragEnter; - this.Resize += Form1_Resize; - - if (fn.Length>0) { - tbDosya.Text = fn; - DosyaAc(); - } - } - - private void Form1_Resize(object sender, EventArgs e) - { - if (this.Width > 200) - tbDosya.Width = this.Width - 250; - } - - private void Form1_DragEnter(object sender, DragEventArgs e) - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - e.Effect = DragDropEffects.Copy; - } - - private void DosyaAc() - { - try { - if(File.Exists(tbDosya.Text)) { - rtbEditor.Text = File.ReadAllText(tbDosya.Text); - } - } catch {} - RenderHtml(); - } - - private void RenderHtml() - { - string contents = rtbEditor.Text; - - var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); - var result = Markdown.ToHtml(contents, pipeline); - - var bas = @" - - - - - - - - - "; - - result = bas + result + @" - - "; - webBrowser.DocumentText = result; - - //webBrowser.Document.Body.Style.font = "font-family: Tahoma, Threbucet, Verdana; font-size: large;"; - //webBrowser.Document.ExecCommand("SelectAll", false, "null"); - //webBrowser.Document.ExecCommand("font-family", false, "Tahoma"); - //webBrowser.Document.ExecCommand("Unselect", false, "null"); - } - - private void tbGozat_Click(object sender, EventArgs e) - { - openFileDialog.Filter = "(*.md)|*.md|Tüm Dosyalar (*.*)|*.*"; - openFileDialog.FilterIndex = 2; - openFileDialog.RestoreDirectory = true; - - if (openFileDialog.ShowDialog() == DialogResult.OK) - { - tbDosya.Text = openFileDialog.FileName; - DosyaAc(); - } - } - - private void Form1_DragDrop(object sender, DragEventArgs e) - { - string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); - if (files.Length > 0) - { - tbDosya.Text = files[0]; - DosyaAc(); - } - } - - private void tbEdit_Click(object sender, EventArgs e) - { - if (rtbEditor.Visible) - { - rtbEditor.Visible = false; - webBrowser.Visible = true; - tbEdit.Text = "Düzenle"; - RenderHtml(); - } - else - { - rtbEditor.Visible = true; - webBrowser.Visible = false; - tbEdit.Text = "Görüntüle"; - } - } - - private void tbSave_Click(object sender, EventArgs e) - { - try - { - if (!string.IsNullOrEmpty(tbDosya.Text)) - { - File.WriteAllText(tbDosya.Text, rtbEditor.Text); - MessageBox.Show("Dosya kaydedildi."); - } - else - { - // Save as... logic could go here, but for now just warn - MessageBox.Show("Lütfen önce bir dosya açın veya oluşturun."); - } - } - catch (Exception ex) - { - MessageBox.Show("Hata: " + ex.Message); - } - } - - private void tbHelp_Click(object sender, EventArgs e) - { - ShowHelp(); - } - - private void rtbEditor_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.F1) - { - ShowHelp(); - } - } - - private void ShowHelp() - { - var helpForm = new HelpForm(); - helpForm.Show(); - } - - private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e) - { - string file = e.Url.LocalPath.ToString(); - - if (file!="blank") - { - - tbDosya.Text = file.Replace("file:///", ""); ; - DosyaAc(); - } - } - } -} +using Markdig; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using static System.Net.Mime.MediaTypeNames; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrayNotify; + + +namespace hMarkdown +{ + public partial class Form1 : Form + { + public Form1(string fn) + { + InitializeComponent(); + this.DragEnter += Form1_DragEnter; + this.Resize += Form1_Resize; + this.Load += (s, e) => AdjustDosyaTextBoxWidth(); + + InitializeCustomControls(); + SetMode(false); + + if (fn.Length>0) { + tbDosya.Text = fn; + DosyaAc(); + } + } + + private void Form1_Resize(object sender, EventArgs e) + { + AdjustDosyaTextBoxWidth(); + } + + private void Form1_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + } + + private void DosyaAc() + { + try { + if(File.Exists(tbDosya.Text)) { + rtbEditor.Text = File.ReadAllText(tbDosya.Text); + } + } catch {} + RenderHtml(); + UpdateStatusBar(); + } + + private void RenderHtml() + { + string contents = rtbEditor.Text; + + var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); + var result = Markdown.ToHtml(contents, pipeline); + + var bas = @" + + + + + + + + + +
"; + + result = bas + result + @" +
+ + "; + webBrowser.DocumentText = result; + + //webBrowser.Document.Body.Style.font = "font-family: Tahoma, Threbucet, Verdana; font-size: large;"; + //webBrowser.Document.ExecCommand("SelectAll", false, "null"); + //webBrowser.Document.ExecCommand("font-family", false, "Tahoma"); + //webBrowser.Document.ExecCommand("Unselect", false, "null"); + } + + private void tbGozat_Click(object sender, EventArgs e) + { + openFileDialog.Filter = "(*.md)|*.md|Tüm Dosyalar (*.*)|*.*"; + openFileDialog.FilterIndex = 2; + openFileDialog.RestoreDirectory = true; + + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + tbDosya.Text = openFileDialog.FileName; + DosyaAc(); + } + } + + private void Form1_DragDrop(object sender, DragEventArgs e) + { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + if (files.Length > 0) + { + tbDosya.Text = files[0]; + DosyaAc(); + } + } + + private void tbEdit_Click(object sender, EventArgs e) + { + if (rtbEditor.Visible) + { + SetMode(false); + } + else + { + SetMode(true); + } + } + + private void tbSave_Click(object sender, EventArgs e) + { + try + { + if (!string.IsNullOrEmpty(tbDosya.Text)) + { + File.WriteAllText(tbDosya.Text, rtbEditor.Text); + MessageBox.Show("Dosya kaydedildi."); + SetMode(false); + } + else + { + // Save as... logic could go here, but for now just warn + MessageBox.Show("Lütfen önce bir dosya açın veya oluşturun."); + } + } + catch (Exception ex) + { + MessageBox.Show("Hata: " + ex.Message); + } + } + + private void tbHelp_Click(object sender, EventArgs e) + { + ShowHelp(); + } + + private void rtbEditor_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.F1) + { + ShowHelp(); + } + } + + private void ShowHelp() + { + var helpForm = new HelpForm(); + helpForm.Show(); + } + + private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e) + { + string file = e.Url.LocalPath.ToString(); + + if (file!="blank") + { + + tbDosya.Text = file.Replace("file:///", ""); ; + DosyaAc(); + } + } + + // --- CUSTOM IMPLEMENTATION --- + private ToolStripStatusLabel lblCharCount; + private ToolStripStatusLabel lblFormat; + private ToolStripStatusLabel lblEncoding; + private TrackBar zoomTrackBar; + private ToolStripButton btnStatusZoomOut; + private ToolStripButton btnStatusZoomIn; + private ToolStripStatusLabel lblStatusZoomText; + private float currentZoom = 1.0f; + private bool isAdjustingWidth = false; + + private void InitializeCustomControls() + { + // 1. StatusStrip + statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + + lblCharCount = new ToolStripStatusLabel(); + lblCharCount.Text = "Karakter: 0"; + + ToolStripStatusLabel spacer = new ToolStripStatusLabel(); + spacer.Spring = true; + spacer.Text = ""; + + lblFormat = new ToolStripStatusLabel(); + lblFormat.Text = "Biçim: Markdown"; + lblFormat.Margin = new Padding(10, 3, 10, 2); + + lblEncoding = new ToolStripStatusLabel(); + lblEncoding.Text = "Kodlama: UTF-8"; + lblEncoding.Margin = new Padding(10, 3, 10, 2); + + // TrackBar control for Zooming + zoomTrackBar = new TrackBar(); + zoomTrackBar.Minimum = 50; + zoomTrackBar.Maximum = 300; + zoomTrackBar.Value = 100; + zoomTrackBar.TickStyle = TickStyle.None; + zoomTrackBar.AutoSize = false; + zoomTrackBar.Height = 16; + zoomTrackBar.Width = 100; + zoomTrackBar.BackColor = SystemColors.Control; + zoomTrackBar.Scroll += (s, e) => SetZoom(zoomTrackBar.Value / 100f); + + var trackBarHost = new ToolStripControlHost(zoomTrackBar); + trackBarHost.Margin = new Padding(5, 2, 5, 2); + + btnStatusZoomOut = new ToolStripButton("➖"); + btnStatusZoomOut.DisplayStyle = ToolStripItemDisplayStyle.Text; + btnStatusZoomOut.Click += (s, e) => SetZoom(currentZoom - 0.1f); + + btnStatusZoomIn = new ToolStripButton("➕"); + btnStatusZoomIn.DisplayStyle = ToolStripItemDisplayStyle.Text; + btnStatusZoomIn.Click += (s, e) => SetZoom(currentZoom + 0.1f); + + lblStatusZoomText = new ToolStripStatusLabel("%100"); + lblStatusZoomText.Margin = new Padding(5, 3, 5, 2); + + statusStrip1.Items.AddRange(new ToolStripItem[] { + lblCharCount, + spacer, + lblFormat, + lblEncoding, + btnStatusZoomOut, + trackBarHost, + btnStatusZoomIn, + lblStatusZoomText + }); + + // 2. toolStripEditor + toolStripEditor.ImageScalingSize = new System.Drawing.Size(24, 24); + toolStripEditor.RenderMode = ToolStripRenderMode.Professional; + toolStripEditor.Visible = false; + + // Menus + var menuDosya = new ToolStripDropDownButton(); + ConfigureEditorButton(menuDosya, "document", "Dosya"); + var mDosyaAc = new ToolStripMenuItem("📂 Aç", null, (s, e) => tbGozat_Click(s, e)); + var mDosyaKaydet = new ToolStripMenuItem("💾 Kaydet", null, (s, e) => tbSave_Click(s, e)); + var mDosyaFarkliKaydet = new ToolStripMenuItem("💾 Farklı Kaydet...", null, (s, e) => DosyaFarkliKaydet()); + var mDosyaKapat = new ToolStripMenuItem("❌ Kapat", null, (s, e) => DosyaKapat()); + menuDosya.DropDownItems.AddRange(new ToolStripItem[] { mDosyaAc, mDosyaKaydet, mDosyaFarkliKaydet, new ToolStripSeparator(), mDosyaKapat }); + + var menuDuzen = new ToolStripDropDownButton(); + ConfigureEditorButton(menuDuzen, "edit", "Düzen"); + var mDuzenUndo = new ToolStripMenuItem("↩️ Geri Al", null, (s, e) => { if (rtbEditor.CanUndo) rtbEditor.Undo(); }); + var mDuzenRedo = new ToolStripMenuItem("↪️ İleri Al", null, (s, e) => { if (rtbEditor.CanRedo) rtbEditor.Redo(); }); + var mDuzenCut = new ToolStripMenuItem("✂️ Kes", null, (s, e) => rtbEditor.Cut()); + var mDuzenCopy = new ToolStripMenuItem("📋 Kopyala", null, (s, e) => rtbEditor.Copy()); + var mDuzenPaste = new ToolStripMenuItem("📥 Yapıştır", null, (s, e) => rtbEditor.Paste()); + var mDuzenSelectAll = new ToolStripMenuItem("🧹 Tümünü Seç", null, (s, e) => rtbEditor.SelectAll()); + menuDuzen.DropDownItems.AddRange(new ToolStripItem[] { mDuzenUndo, mDuzenRedo, new ToolStripSeparator(), mDuzenCut, mDuzenCopy, mDuzenPaste, new ToolStripSeparator(), mDuzenSelectAll }); + + var menuGorunum = new ToolStripDropDownButton(); + ConfigureEditorButton(menuGorunum, "visible", "Görünüm"); + var mGorunumZoomIn = new ToolStripMenuItem("➕ Yakınlaştır (%+)", null, (s, e) => ZoomIn()); + var mGorunumZoomOut = new ToolStripMenuItem("➖ Uzaklaştır (%-)", null, (s, e) => ZoomOut()); + var mGorunumZoomReset = new ToolStripMenuItem("🔄 Varsayılan Zoom (%100)", null, (s, e) => ZoomReset()); + menuGorunum.DropDownItems.AddRange(new ToolStripItem[] { mGorunumZoomIn, mGorunumZoomOut, mGorunumZoomReset }); + + // Header Dropdown + var btnHeading = new ToolStripDropDownButton(); + ConfigureEditorButton(btnHeading, "heading", "Başlık"); + for (int i = 1; i <= 6; i++) + { + int level = i; + btnHeading.DropDownItems.Add(new ToolStripMenuItem($"Başlık {level} (H{level})", null, (s, e) => InsertHeader(level))); + } + + // Lists Dropdown + var btnLists = new ToolStripDropDownButton(); + ConfigureEditorButton(btnLists, "list", "Liste & No"); + btnLists.DropDownItems.Add(new ToolStripMenuItem("• Madde İşaretli Liste", null, (s, e) => InsertMarkdownPrefix("* "))); + btnLists.DropDownItems.Add(new ToolStripMenuItem("1. Numaralı Liste", null, (s, e) => InsertMarkdownPrefix("1. "))); + + // Indent Dropdown + var btnIndent = new ToolStripDropDownButton(); + ConfigureEditorButton(btnIndent, "indent", "Girinti"); + btnIndent.DropDownItems.Add(new ToolStripMenuItem("➡️ Girintiyi Arttır", null, (s, e) => InsertMarkdownPrefix(" "))); + btnIndent.DropDownItems.Add(new ToolStripMenuItem("⬅️ Girintiyi Azalt", null, (s, e) => DecreaseIndent())); + + // Formatting Buttons + var btnBold = new ToolStripButton(); + ConfigureEditorButton(btnBold, "bold", "Koyu"); + btnBold.Click += (s, e) => WrapSelection("**", "**"); + btnBold.Font = new Font(btnBold.Font, FontStyle.Bold); + + var btnItalic = new ToolStripButton(); + ConfigureEditorButton(btnItalic, "italic", "İtelik"); + btnItalic.Click += (s, e) => WrapSelection("*", "*"); + btnItalic.Font = new Font(btnItalic.Font, FontStyle.Italic); + + var btnStrikethrough = new ToolStripButton(); + ConfigureEditorButton(btnStrikethrough, "strikethrough", "Üstü Çizgili"); + btnStrikethrough.Click += (s, e) => WrapSelection("~~", "~~"); + + var btnLink = new ToolStripButton(); + ConfigureEditorButton(btnLink, "link", "Link"); + btnLink.Click += (s, e) => InsertLink(); + + var btnClearFormatting = new ToolStripButton(); + ConfigureEditorButton(btnClearFormatting, "eraser", "Temizle"); + btnClearFormatting.Click += (s, e) => ClearFormatting(); + + // Table Dropdown + var btnTable = new ToolStripDropDownButton(); + ConfigureEditorButton(btnTable, "table", "Tablo"); + btnTable.DropDownItems.Add(new ToolStripMenuItem("2x2 Tablo", null, (s, e) => InsertTable(2, 2))); + btnTable.DropDownItems.Add(new ToolStripMenuItem("3x3 Tablo", null, (s, e) => InsertTable(3, 3))); + btnTable.DropDownItems.Add(new ToolStripMenuItem("4x3 Tablo", null, (s, e) => InsertTable(4, 3))); + btnTable.DropDownItems.Add(new ToolStripSeparator()); + btnTable.DropDownItems.Add(new ToolStripMenuItem("Özel Tablo...", null, (s, e) => InsertCustomTable())); + + // Add items to toolStripEditor + toolStripEditor.Items.AddRange(new ToolStripItem[] { + menuDosya, + menuDuzen, + menuGorunum, + new ToolStripSeparator(), + btnHeading, + btnLists, + btnIndent, + new ToolStripSeparator(), + btnBold, + btnItalic, + btnStrikethrough, + btnLink, + btnClearFormatting, + new ToolStripSeparator(), + btnTable + }); + + // Reorganize toolStrip1 items for correct alignment + tbDosya.AutoSize = false; + tbDosya.Height = 22; + tbHelp.Alignment = ToolStripItemAlignment.Right; + tbSave.Alignment = ToolStripItemAlignment.Right; + tbEdit.Alignment = ToolStripItemAlignment.Right; + tbGozat.Alignment = ToolStripItemAlignment.Right; + + toolStrip1.Items.Clear(); + toolStrip1.Items.Add(toolStripLabel1); + toolStrip1.Items.Add(tbDosya); + toolStrip1.Items.Add(tbHelp); + toolStrip1.Items.Add(tbSave); + toolStrip1.Items.Add(tbEdit); + toolStrip1.Items.Add(tbGozat); + + // Configure main toolstrip buttons with PNG icons + System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; + ConfigureMainButton(tbGozat, "opened-folder", "..."); + ConfigureMainButton(tbSave, "save", "Kaydet"); + ConfigureMainButton(tbHelp, "help", "Yardım"); + ConfigureMainButton(tbEdit, "edit", "Düzenle"); + + rtbEditor.TextChanged += (s, e) => UpdateStatusBar(); + rtbEditor.SelectionChanged += (s, e) => UpdateStatusBar(); + + webBrowser.DocumentCompleted += (s, e) => ApplyWebBrowserZoom(); + + UpdateZoomUI(); + RefreshControlLayout(); + } + + private void SetMode(bool editMode) + { + if (editMode) + { + rtbEditor.Visible = true; + webBrowser.Visible = false; + + toolStripEditor.Visible = true; + tbSave.Visible = true; + tbHelp.Visible = true; + + ConfigureMainButton(tbEdit, "visible", "Görüntüle"); + } + else + { + rtbEditor.Visible = false; + webBrowser.Visible = true; + + toolStripEditor.Visible = false; + tbSave.Visible = false; + tbHelp.Visible = false; + + ConfigureMainButton(tbEdit, "edit", "Düzenle"); + RenderHtml(); + } + + RefreshControlLayout(); + AdjustDosyaTextBoxWidth(); + } + + private void RefreshControlLayout() + { + this.SuspendLayout(); + + // 1-pixel separator line border styling + rtbEditor.BorderStyle = BorderStyle.FixedSingle; + + // Absolute winforms docking z-order setup (from back to front): + // 1. Workspace content fill + rtbEditor.SendToBack(); + webBrowser.SendToBack(); + // 2. StatusStrip bottom + statusStrip1.SendToBack(); + // 3. toolStripEditor below toolStrip1 + if (toolStripEditor != null) + { + toolStripEditor.SendToBack(); + } + // 4. toolStrip1 at very top edge + toolStrip1.SendToBack(); + + this.ResumeLayout(true); + } + + + + + private void AdjustDosyaTextBoxWidth() + { + if (isAdjustingWidth) return; + if (toolStrip1 == null || tbDosya == null) return; + + int totalWidth = toolStrip1.DisplayRectangle.Width; + if (totalWidth <= 0) return; + + isAdjustingWidth = true; + + try + { + int originalWidth = tbDosya.Width; + + // Temporarily set tbDosya to a small width to allow other items to layout fully + tbDosya.Width = 50; + toolStrip1.PerformLayout(); + + int occupiedWidth = 0; + foreach (ToolStripItem item in toolStrip1.Items) + { + if (item != tbDosya && item.Visible) + { + occupiedWidth += item.Width + item.Margin.Horizontal; + } + } + + int newWidth = totalWidth - occupiedWidth - tbDosya.Margin.Horizontal - 25; + if (newWidth < 100) newWidth = 100; + + if (tbDosya.Width != newWidth) + { + tbDosya.Width = newWidth; + } + else + { + tbDosya.Width = originalWidth; + } + } + finally + { + isAdjustingWidth = false; + } + } + + private void UpdateStatusBar() + { + if (rtbEditor == null || lblCharCount == null) return; + int charCount = rtbEditor.Text.Length; + lblCharCount.Text = $"Karakter: {charCount}"; + + if (Math.Abs(rtbEditor.ZoomFactor - currentZoom) > 0.01f) + { + currentZoom = rtbEditor.ZoomFactor; + UpdateZoomUI(); + ApplyWebBrowserZoom(); + } + } + + private void SetZoom(float zoomFactor) + { + currentZoom = Math.Max(0.5f, Math.Min(3.0f, zoomFactor)); + + try + { + rtbEditor.ZoomFactor = currentZoom; + } + catch {} + + ApplyWebBrowserZoom(); + UpdateZoomUI(); + } + + private void UpdateZoomUI() + { + if (zoomTrackBar != null) + { + int val = (int)(currentZoom * 100); + zoomTrackBar.Value = Math.Max(zoomTrackBar.Minimum, Math.Min(zoomTrackBar.Maximum, val)); + } + if (lblStatusZoomText != null) + { + lblStatusZoomText.Text = $"%{(int)(currentZoom * 100)}"; + } + } + + private void DosyaFarkliKaydet() + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.Filter = "(*.md)|*.md|Tüm Dosyalar (*.*)|*.*"; + if (sfd.ShowDialog() == DialogResult.OK) + { + tbDosya.Text = sfd.FileName; + try + { + File.WriteAllText(tbDosya.Text, rtbEditor.Text); + MessageBox.Show("Dosya farklı kaydedildi."); + SetMode(false); + } + catch (Exception ex) + { + MessageBox.Show("Hata: " + ex.Message); + } + } + } + + private void DosyaKapat() + { + rtbEditor.Clear(); + tbDosya.Text = ""; + webBrowser.DocumentText = ""; + UpdateStatusBar(); + } + + private void ZoomIn() + { + SetZoom(currentZoom + 0.1f); + } + + private void ZoomOut() + { + SetZoom(currentZoom - 0.1f); + } + + private void ZoomReset() + { + SetZoom(1.0f); + } + + private void InsertMarkdownPrefix(string prefix) + { + int selectionStart = rtbEditor.SelectionStart; + int lineIndex = rtbEditor.GetLineFromCharIndex(selectionStart); + int lineStartCharIndex = rtbEditor.GetFirstCharIndexFromLine(lineIndex); + + rtbEditor.Select(lineStartCharIndex, 0); + rtbEditor.SelectedText = prefix; + rtbEditor.Focus(); + } + + private void InsertHeader(int level) + { + string prefix = new string('#', level) + " "; + InsertMarkdownPrefix(prefix); + } + + private void DecreaseIndent() + { + if (rtbEditor.Lines.Length == 0) return; + + int selectionStart = rtbEditor.SelectionStart; + int lineIndex = rtbEditor.GetLineFromCharIndex(selectionStart); + if (lineIndex < 0 || lineIndex >= rtbEditor.Lines.Length) return; + + int lineStartCharIndex = rtbEditor.GetFirstCharIndexFromLine(lineIndex); + string lineText = rtbEditor.Lines[lineIndex]; + + if (lineText.StartsWith(" ")) + { + rtbEditor.Select(lineStartCharIndex, 4); + rtbEditor.SelectedText = ""; + } + else if (lineText.StartsWith("\t")) + { + rtbEditor.Select(lineStartCharIndex, 1); + rtbEditor.SelectedText = ""; + } + rtbEditor.Focus(); + } + + private void WrapSelection(string prefix, string suffix) + { + string selectedText = rtbEditor.SelectedText; + int selectionStart = rtbEditor.SelectionStart; + + rtbEditor.SelectedText = prefix + selectedText + suffix; + rtbEditor.SelectionStart = selectionStart + prefix.Length; + rtbEditor.SelectionLength = selectedText.Length; + rtbEditor.Focus(); + } + + private void InsertLink() + { + string selectedText = rtbEditor.SelectedText; + string title = string.IsNullOrEmpty(selectedText) ? "Link Başlığı" : selectedText; + string url = Prompt.ShowDialog("Link URL'sini girin:", "Link Ekle"); + if (!string.IsNullOrEmpty(url)) + { + rtbEditor.SelectedText = $"[{title}]({url})"; + } + rtbEditor.Focus(); + } + + private void ClearFormatting() + { + string text = rtbEditor.SelectedText; + if (string.IsNullOrEmpty(text)) return; + + text = System.Text.RegularExpressions.Regex.Replace(text, @"(\*\*|\*|~~|`|_)", ""); + var lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + for (int i = 0; i < lines.Length; i++) + { + lines[i] = System.Text.RegularExpressions.Regex.Replace(lines[i], @"^(#+\s+|\*\s+|-\s+|\d+\.\s+)", ""); + } + rtbEditor.SelectedText = string.Join(Environment.NewLine, lines); + rtbEditor.Focus(); + } + + private void InsertTable(int rows, int cols) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(); + for (int c = 1; c <= cols; c++) + { + sb.Append($"| Başlık {c} "); + } + sb.AppendLine("|"); + for (int c = 1; c <= cols; c++) + { + sb.Append("| --- "); + } + sb.AppendLine("|"); + for (int r = 1; r <= rows; r++) + { + for (int c = 1; c <= cols; c++) + { + sb.Append($"| Hücre {r},{c} "); + } + sb.AppendLine("|"); + } + sb.AppendLine(); + + rtbEditor.SelectedText = sb.ToString(); + rtbEditor.Focus(); + } + + private void InsertCustomTable() + { + string input = Prompt.ShowDialog("Satır ve Sütun sayısını girin (Örn: 3x4):", "Özel Tablo Ekle"); + if (!string.IsNullOrEmpty(input)) + { + var parts = input.Split('x'); + if (parts.Length == 2 && int.TryParse(parts[0], out int rows) && int.TryParse(parts[1], out int cols)) + { + InsertTable(rows, cols); + } + else + { + MessageBox.Show("Geçersiz format. Lütfen 'SatırxSütun' şeklinde girin (örn. 3x3)."); + } + } + } + + private void ConfigureEditorButton(ToolStripItem item, string iconName, string label) + { + item.Text = label; + item.ToolTipText = label; + + System.Drawing.Image img = LoadIcon(iconName); + if (img != null) + { + item.Image = img; + item.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; + } + else + { + item.Image = CreateEmojiImage(GetFallbackEmoji(iconName), 24); + item.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; + } + + if (item is ToolStripButton btn) + { + btn.TextImageRelation = TextImageRelation.ImageAboveText; + btn.ImageAlign = ContentAlignment.TopCenter; + btn.TextAlign = ContentAlignment.BottomCenter; + } + else if (item is ToolStripDropDownButton dd) + { + dd.TextImageRelation = TextImageRelation.ImageAboveText; + dd.ImageAlign = ContentAlignment.TopCenter; + dd.TextAlign = ContentAlignment.BottomCenter; + } + } + + private void ConfigureMainButton(ToolStripItem item, string iconName, string label) + { + item.Text = label; + item.ToolTipText = label; + + System.Drawing.Image img = LoadIcon(iconName); + if (img != null) + { + item.Image = img; + item.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; + } + else + { + item.Text = GetFallbackEmoji(iconName) + " " + label; + item.DisplayStyle = ToolStripItemDisplayStyle.Text; + } + } + + private System.Drawing.Image LoadIcon(string iconName) + { + string cacheDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "icons"); + if (!Directory.Exists(cacheDir)) + { + Directory.CreateDirectory(cacheDir); + } + + string localPath = Path.Combine(cacheDir, iconName + ".png"); + if (!File.Exists(localPath)) + { + string url = $"https://img.icons8.com/material-outlined/24/000000/{iconName}.png"; + try + { + using (var webClient = new System.Net.WebClient()) + { + webClient.DownloadFile(url, localPath); + } + } + catch + { + return null; + } + } + + try + { + return System.Drawing.Image.FromFile(localPath); + } + catch + { + return null; + } + } + + private string GetFallbackEmoji(string iconName) + { + switch (iconName) + { + case "document": return "📄"; + case "edit": return "✏️"; + case "visible": return "👁️"; + case "heading": return "🏷️"; + case "list": return "📋"; + case "indent": return "➡️"; + case "bold": return "𝐁"; + case "italic": return "𝘐"; + case "strikethrough": return "̶S̶"; + case "link": return "🔗"; + case "eraser": return "🧼"; + case "table": return "📅"; + case "opened-folder": return "📂"; + case "save": return "💾"; + case "help": return "❓"; + default: return "⚙️"; + } + } + + private System.Drawing.Image CreateEmojiImage(string emoji, int size) + { + Bitmap bmp = new Bitmap(size, size); + using (Graphics g = Graphics.FromImage(bmp)) + { + g.Clear(Color.Transparent); + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; + + using (Font font = new Font("Segoe UI Emoji", 12, FontStyle.Regular, GraphicsUnit.Point)) + { + var format = new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center + }; + g.DrawString(emoji, font, Brushes.Black, new RectangleF(0, 0, size, size), format); + } + } + return bmp; + } + + // Simple nested modal input prompt helper + public static class Prompt + { + public static string ShowDialog(string text, string caption) + { + Form prompt = new Form() + { + Width = 400, + Height = 150, + FormBorderStyle = FormBorderStyle.FixedDialog, + Text = caption, + StartPosition = FormStartPosition.CenterParent, + MaximizeBox = false, + MinimizeBox = false + }; + Label textLabel = new Label() { Left = 20, Top = 20, Text = text, Width = 350 }; + TextBox textBox = new TextBox() { Left = 20, Top = 45, Width = 350 }; + Button confirmation = new Button() { Text = "Tamam", Left = 270, Width = 100, Top = 80, DialogResult = DialogResult.OK }; + confirmation.Click += (sender, e) => { prompt.Close(); }; + prompt.Controls.Add(textBox); + prompt.Controls.Add(confirmation); + prompt.Controls.Add(textLabel); + prompt.AcceptButton = confirmation; + return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : ""; + } + } + + private void ApplyWebBrowserZoom() + { + if (webBrowser == null || webBrowser.Document == null) return; + try + { + int zoomPercent = (int)(currentZoom * 100); + object ax = webBrowser.ActiveXInstance; + ax.GetType().InvokeMember( + "ExecWB", + System.Reflection.BindingFlags.InvokeMethod, + null, + ax, + new object[] { 63, 2, zoomPercent, null } + ); + } + catch {} + } + } +}