Created
June 30, 2010 07:51
-
-
Save chrisforbes/458370 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Drawing; | |
using System.Windows.Forms; | |
using System.Globalization; | |
namespace formatter | |
{ | |
// supported codes: | |
// \fb; \fr; -- font bold/regular. | |
// \al; \ar; -- align left/right | |
// \cRRGGBB; -- color | |
// \cz; -- reset to default color | |
// \n -- newline | |
// \t -- next tabstop | |
// \\; -- escaped slash | |
public partial class Form1 : Form | |
{ | |
public Form1() | |
{ | |
InitializeComponent(); | |
textBox1.Text = @"\fb;Tesla Coil (\cffff00;J\cz;)\ar;$1200\n;\fr;\al;\cff0000;Requires War Factory\cz;\ar;\fb;-150\n;\fr;\al;A hax weapon. Chews up tanks. A really insanely long LongDesc so Alzeih can see that wordwrap works, although color- and hyphenation-unaware typography really does nothing for me.\n;\t;Strong vs \fb;\c00cc00;Infantry, Vehicles\cz;\fr;\n;\t;Weak vs \fb;\ccc0000;Aircraft\cz;\fr;"; | |
} | |
static IEnumerable<string> Tokens(string s) | |
{ | |
var i = 0; | |
var inOpcode = false; | |
for( var j = 0; j < s.Length; j++ ) | |
if (!inOpcode) { if (s[j] == '\\') { yield return s.Substring(i, j - i); i = j; inOpcode = true; } } | |
else { if (s[j] == ';') { yield return s.Substring(i, j - i + 1); i = j + 1; inOpcode = false; } } | |
if (i < s.Length) yield return s.Substring(i); | |
} | |
string fmt = ""; | |
void UpdateRendering(object sender, EventArgs e) | |
{ | |
fmt = textBox1.Text; | |
panel1.Invalidate(); | |
} | |
Brush ReplaceBrush(Brush old, Color c) | |
{ | |
old.Dispose(); | |
return new SolidBrush(c); | |
} | |
int ParseHex(string s, int start, int length) | |
{ | |
var t = s.Substring(start, length); | |
return int.Parse(t, NumberStyles.HexNumber); | |
} | |
const int tabWidth = 20; | |
const int layoutWidth = 250; | |
const int leftEdge = 20; | |
void PaintPanel(object sender, PaintEventArgs e) | |
{ | |
var rf = panel1.Font; | |
var bf = new Font(rf, FontStyle.Bold); | |
var f = rf; | |
var b = new SolidBrush(Color.White) as Brush; | |
var y = 20; | |
var x = (float)leftEdge; | |
var rightAlign = false; | |
foreach (var t in Tokens(fmt.Replace("\r\n", ""))) | |
{ | |
if (t == @"\fb;") f = bf; | |
else if (t == @"\fr;") f = rf; | |
else if (t == @"\n;") { y += f.Height; x = rightAlign ? layoutWidth : leftEdge; } | |
else if (t == @"\cz;") { b = ReplaceBrush(b, Color.White); } | |
else if (t == @"\al;") { rightAlign = false; x = leftEdge; } | |
else if (t == @"\ar;") { rightAlign = true; x = layoutWidth; } | |
else if (t.StartsWith(@"\c")) { b = ReplaceBrush(b, Color.FromArgb(ParseHex(t, 2, 2), ParseHex(t, 4, 2), ParseHex(t, 6, 2))); } | |
else if (t == @"\t;") { x += tabWidth; x -= (int)(x-leftEdge) % tabWidth; } | |
else | |
{ | |
var s = (t == @"\\;") ? @"\" : t; | |
var w = e.Graphics.MeasureString(t, f); | |
if (rightAlign) | |
{ | |
e.Graphics.DrawString(t, f, b, x - w.Width, y); | |
x -= w.Width; | |
} | |
else | |
{ | |
if (w.Width + x > layoutWidth) | |
{ | |
// do wrapping | |
var spaceWidth = e.Graphics.MeasureString("._.", f).Width - e.Graphics.MeasureString("__",f).Width; | |
var words = t.Split(' '); | |
foreach (var ww in words) | |
{ | |
var width = e.Graphics.MeasureString(ww, f); | |
if (x + width.Width < layoutWidth) | |
{ | |
e.Graphics.DrawString(ww, f, b, x, y); | |
x += width.Width + spaceWidth; | |
} | |
else | |
{ | |
x = leftEdge; | |
y += f.Height; | |
e.Graphics.DrawString(ww, f, b, x, y); | |
x += width.Width + spaceWidth; | |
} | |
} | |
} | |
else | |
{ | |
e.Graphics.DrawString(t, f, b, x, y); | |
x += w.Width; | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment