912 lines
34 KiB
C#
912 lines
34 KiB
C#
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;
|
||
|
||
|
||
namespace hMarkdown
|
||
{
|
||
public partial class Form1 : Form
|
||
{
|
||
private string startupFile = "";
|
||
|
||
public Form1(string fn)
|
||
{
|
||
InitializeComponent();
|
||
webBrowser.ScriptErrorsSuppressed = true;
|
||
this.DragEnter += Form1_DragEnter;
|
||
this.Resize += Form1_Resize;
|
||
this.Load += Form1_Load;
|
||
|
||
if (!string.IsNullOrEmpty(fn)) {
|
||
startupFile = fn.Trim('"', ' ');
|
||
}
|
||
|
||
InitializeCustomControls();
|
||
SetMode(false);
|
||
}
|
||
|
||
private void Form1_Load(object sender, EventArgs e)
|
||
{
|
||
AdjustDosyaTextBoxWidth();
|
||
|
||
// Set window title with dynamic version
|
||
string version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||
this.Text = $"hOLOlu Markdown Viewer (v{version})";
|
||
|
||
// WebBrowser kontrolünün ActiveX nesnesini ve dokümanını başlatmak için about:blank'e yönlendirip bekliyoruz.
|
||
webBrowser.Navigate("about:blank");
|
||
while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
|
||
{
|
||
System.Windows.Forms.Application.DoEvents();
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(startupFile)) {
|
||
tbDosya.Text = startupFile;
|
||
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 = @"<html>
|
||
<head>
|
||
<meta http-equiv=""X-UA-Compatible"" content=""IE=edge"" />
|
||
<link rel=""stylesheet"" href=""https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown-light.min.css"">
|
||
<link rel=""stylesheet"" href=""https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.5/styles/github.min.css"">
|
||
<script src=""https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.5/highlight.min.js""></script>
|
||
<script>hljs.initHighlightingOnLoad();</script>
|
||
<style>
|
||
body {
|
||
margin: 0;
|
||
padding: 0;
|
||
background-color: #ffffff;
|
||
}
|
||
.markdown-body {
|
||
box-sizing: border-box;
|
||
min-width: 200px;
|
||
max-width: 980px;
|
||
margin: 0 auto;
|
||
padding: 45px;
|
||
}
|
||
@media (max-width: 767px) {
|
||
.markdown-body {
|
||
padding: 15px;
|
||
}
|
||
}
|
||
table { width: 100%; }
|
||
img { max-width: 100%; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class=""markdown-body"">";
|
||
|
||
result = bas + result + @"
|
||
</div>
|
||
</body>
|
||
</html>";
|
||
if (webBrowser.Document != null)
|
||
{
|
||
webBrowser.Document.OpenNew(true);
|
||
webBrowser.Document.Write(result);
|
||
}
|
||
else
|
||
{
|
||
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.FileName = "";
|
||
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)
|
||
{
|
||
if (e.Url != null && e.Url.IsFile)
|
||
{
|
||
string file = e.Url.LocalPath;
|
||
tbDosya.Text = 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 {}
|
||
}
|
||
}
|
||
}
|