\r
namespace Radegast\r
{\r
- struct LSLKeyWord\r
+ public struct LSLKeyWord\r
{\r
public string KeyWord;\r
public string ToolTip;\r
}\r
}\r
\r
- class LSLKeywordParser\r
+ public class LSLKeywordParser\r
{\r
private static Dictionary<string, LSLKeyWord> keyWords;\r
\r
using System.Linq;\r
using System.Text;\r
using System.Windows.Forms;\r
+using System.Drawing;\r
+using System.Runtime.InteropServices;\r
+using HWND = System.IntPtr;\r
\r
namespace Radegast\r
{\r
\r
private const short WM_PAINT = 0x00f;\r
private bool _Paint = true;\r
+ private bool monoRuntime;\r
+ private System.Threading.Timer ttTimer;\r
+ private ToolTip ttKeyWords = new ToolTip();\r
\r
public RRichTextBox()\r
: base()\r
{\r
SetStyle(ControlStyles.SupportsTransparentBackColor, true);\r
+ \r
+ // Are we running mono?\r
+ if (null == Type.GetType("Mono.Runtime"))\r
+ {\r
+ monoRuntime = false;\r
+ }\r
+ else\r
+ {\r
+ monoRuntime = true;\r
+ }\r
+ \r
+ ttTimer = new System.Threading.Timer(ttTimerElapsed, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
}\r
\r
protected override void WndProc(ref System.Windows.Forms.Message m)\r
public virtual void BeginUpdate()\r
{\r
_Paint = false;\r
- SuspendLayout();\r
+ if (!monoRuntime)\r
+ Win32.LockWindowUpdate(Handle);\r
}\r
\r
public virtual void EndUpdate()\r
{\r
- ResumeLayout();\r
+ if (!monoRuntime)\r
+ {\r
+ Win32.LockWindowUpdate((IntPtr)0);\r
+ Invalidate();\r
+ }\r
_Paint = true;\r
}\r
\r
+ #region Syntax highligting\r
+ private string rtfEscaped(string s)\r
+ {\r
+ return s.Replace(@"\", @"\\").Replace("{", @"\{").Replace("}", @"\}").Replace("\n", "\\par\n");\r
+ }\r
+\r
+ private List<Color> usedColors = new List<Color>();\r
+\r
+ private string colorTag(Color c, string s)\r
+ {\r
+ int index;\r
+\r
+ if (usedColors.Contains(c))\r
+ {\r
+ index = usedColors.IndexOf(c) + 1;\r
+ }\r
+ else\r
+ {\r
+ usedColors.Add(c);\r
+ index = usedColors.Count;\r
+ }\r
+\r
+ return "\\cf" + index + " " + rtfEscaped(s) + "\\cf1 ";\r
+ }\r
+\r
+ public Color CommentColor = Color.FromArgb(204, 76, 38);\r
+ public Color StringColor = Color.FromArgb(0, 51, 0);\r
+ public Dictionary<string, LSLKeyWord> KeyWords = LSLKeywordParser.KeyWords;\r
+\r
+ protected override void OnTextChanged(EventArgs e)\r
+ {\r
+ if (monoRuntime)\r
+ {\r
+ // base.OnTextChanged(e);\r
+ // return;\r
+ }\r
+\r
+ if (!_Paint) return;\r
+ \r
+ BeginUpdate();\r
+ Win32.POINT scrollStatus = GetScrollPos();\r
+ int selectionStart = SelectionStart;\r
+ int selectionLength = SelectionLength;\r
+\r
+ StringTokenizer tokenizer = new StringTokenizer(Text.Replace("\t", " "));\r
+ Token token;\r
+ StringBuilder body = new StringBuilder();\r
+ usedColors.Clear();\r
+ usedColors.Add(ForeColor);\r
+\r
+ do\r
+ {\r
+ token = tokenizer.Next();\r
+\r
+ switch (token.Kind)\r
+ {\r
+ case TokenKind.Word:\r
+ if (KeyWords.ContainsKey(token.Value))\r
+ {\r
+ body.Append(colorTag(KeyWords[token.Value].Color, token.Value));\r
+ }\r
+ else\r
+ {\r
+ goto default;\r
+ }\r
+ break;\r
+\r
+ case TokenKind.QuotedString:\r
+ body.Append(colorTag(StringColor, token.Value));\r
+ break;\r
+\r
+ case TokenKind.Comment:\r
+ body.Append(colorTag(CommentColor, token.Value));\r
+ break;\r
+\r
+ case TokenKind.EOL:\r
+ body.Append("\\par\n\\cf1 ");\r
+ break;\r
+\r
+ default:\r
+ body.Append(rtfEscaped(token.Value));\r
+ break;\r
+ }\r
+\r
+ } while (token.Kind != TokenKind.EOF);\r
+\r
+ StringBuilder colorTable = new StringBuilder();\r
+ colorTable.Append(@"{\colortbl;");\r
+\r
+ foreach (Color color in usedColors)\r
+ {\r
+ colorTable.AppendFormat("\\red{0}\\green{1}\\blue{2};", color.R, color.G, color.B);\r
+ }\r
+\r
+ colorTable.Append("}");\r
+\r
+ // Construct final rtf\r
+ StringBuilder rtf = new StringBuilder();\r
+ rtf.AppendLine(@"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}}");\r
+ //rtf.Append(@"\viewkind4\uc1\pard\lang1033\f0\fs20 ");\r
+ //rtf.AppendLine(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\f0\fnil\fcharset0 Courier New;}}");\r
+ rtf.AppendLine(colorTable.ToString());\r
+ rtf.Append(@"\pard\f0\fs18 ");\r
+ rtf.Append(body);\r
+ rtf.AppendLine(@"\par}");\r
+\r
+ // System.Console.WriteLine(rtf);\r
+\r
+ // Restore scrollbars and cursor position\r
+ Rtf = rtf.ToString();\r
+ SelectionStart = selectionStart;\r
+ SelectionLength = selectionLength;\r
+ SetScrollPos(scrollStatus);\r
+ EndUpdate();\r
+ }\r
+ #endregion\r
+\r
public struct CursorLocation\r
{\r
public CursorLocation(int Line, int Column)\r
Select(Offset + value.Column, 0);\r
}\r
}\r
+\r
+ #region ToolTips\r
+ private bool validWordChar(char c)\r
+ {\r
+ return\r
+ (c >= 'a' && c <= 'z') ||\r
+ (c >= 'A' && c <= 'Z') ||\r
+ (c >= '0' && c <= '9') ||\r
+ c == '_';\r
+ }\r
+\r
+ private void ttTimerElapsed(Object sender)\r
+ {\r
+ if (InvokeRequired)\r
+ {\r
+ BeginInvoke(new MethodInvoker(delegate() { ttTimerElapsed(sender); }));\r
+ return;\r
+ }\r
+\r
+ char trackedChar = GetCharFromPosition(trackedMousePos);\r
+\r
+ if (!validWordChar(trackedChar))\r
+ {\r
+ return;\r
+ }\r
+\r
+ string trackedString = Text;\r
+ int trackedPos = GetCharIndexFromPosition(trackedMousePos);\r
+ int starPos;\r
+ int endPos;\r
+\r
+ for (starPos = trackedPos; starPos >= 0 && validWordChar(trackedString[starPos]); starPos--) ;\r
+ for (endPos = trackedPos; endPos < trackedString.Length && validWordChar(trackedString[endPos]); endPos++) ;\r
+ string word = trackedString.Substring(starPos + 1, endPos - starPos - 1);\r
+\r
+ if (!KeyWords.ContainsKey(word) || KeyWords[word].ToolTip == string.Empty)\r
+ {\r
+ return;\r
+ }\r
+\r
+ ttKeyWords.Show(KeyWords[word].ToolTip, this, new Point(trackedMousePos.X, trackedMousePos.Y + 15), 120 * 1000);\r
+ }\r
+\r
+ private Point trackedMousePos = new Point(0, 0);\r
+\r
+ protected override void OnMouseMove(MouseEventArgs e)\r
+ {\r
+ Point currentMousePos = new Point(e.X, e.Y);\r
+\r
+ if (currentMousePos != trackedMousePos)\r
+ {\r
+ trackedMousePos = currentMousePos;\r
+ ttTimer.Change(500, System.Threading.Timeout.Infinite);\r
+ ttKeyWords.Hide(this);\r
+ }\r
+ base.OnMouseMove(e);\r
+ }\r
+ #endregion\r
+\r
+ #region Scrollbar positions functions\r
+ /// <summary>\r
+ /// Sends a win32 message to get the scrollbars' position.\r
+ /// </summary>\r
+ /// <returns>a POINT structre containing horizontal\r
+ /// and vertical scrollbar position.</returns>\r
+ private unsafe Win32.POINT GetScrollPos()\r
+ {\r
+ Win32.POINT res = new Win32.POINT();\r
+ IntPtr ptr = new IntPtr(&res);\r
+ Win32.SendMessage(Handle, Win32.EM_GETSCROLLPOS, 0, ptr);\r
+ return res;\r
+\r
+ }\r
+\r
+ /// <summary>\r
+ /// Sends a win32 message to set scrollbars position.\r
+ /// </summary>\r
+ /// <param name="point">a POINT\r
+ /// conatining H/Vscrollbar scrollpos.</param>\r
+ private unsafe void SetScrollPos(Win32.POINT point)\r
+ {\r
+ IntPtr ptr = new IntPtr(&point);\r
+ Win32.SendMessage(Handle, Win32.EM_SETSCROLLPOS, 0, ptr);\r
+\r
+ }\r
+\r
+ /// <summary>\r
+ /// Summary description for Win32.\r
+ /// </summary>\r
+ private class Win32\r
+ {\r
+ private Win32()\r
+ {\r
+ }\r
+\r
+ public const int WM_USER = 0x400;\r
+ public const int WM_PAINT = 0xF;\r
+ public const int WM_KEYDOWN = 0x100;\r
+ public const int WM_KEYUP = 0x101;\r
+ public const int WM_CHAR = 0x102;\r
+\r
+ public const int EM_GETSCROLLPOS = (WM_USER + 221);\r
+ public const int EM_SETSCROLLPOS = (WM_USER + 222);\r
+\r
+ public const int VK_CONTROL = 0x11;\r
+ public const int VK_UP = 0x26;\r
+ public const int VK_DOWN = 0x28;\r
+ public const int VK_NUMLOCK = 0x90;\r
+\r
+ public const short KS_ON = 0x01;\r
+ public const short KS_KEYDOWN = 0x80;\r
+\r
+ [StructLayout(LayoutKind.Sequential)]\r
+ public struct POINT\r
+ {\r
+ public int x;\r
+ public int y;\r
+ }\r
+\r
+ [DllImport("user32")]\r
+ public static extern int SendMessage(HWND hwnd, int wMsg, int wParam, IntPtr lParam);\r
+ [DllImport("user32")]\r
+ public static extern int PostMessage(HWND hwnd, int wMsg, int wParam, int lParam);\r
+ [DllImport("user32")]\r
+ public static extern short GetKeyState(int nVirtKey);\r
+ [DllImport("user32")]\r
+ public static extern int LockWindowUpdate(HWND hwnd);\r
+ }\r
+ #endregion\r
}\r
}
\ No newline at end of file
--- /dev/null
+/********************************************************8\r
+ * Author: Andrew Deren\r
+ * Date: July, 2004\r
+ * http://www.adersoftware.com\r
+ * \r
+ * StringTokenizer class. You can use this class in any way you want\r
+ * as long as this header remains in this file.\r
+ * \r
+ **********************************************************/\r
+using System;\r
+using System.IO;\r
+using System.Text;\r
+\r
+namespace Radegast\r
+{\r
+ public enum TokenKind\r
+ {\r
+ Unknown,\r
+ Word,\r
+ Number,\r
+ QuotedString,\r
+ WhiteSpace,\r
+ Symbol,\r
+ Comment,\r
+ EOL,\r
+ EOF\r
+ }\r
+\r
+ public class Token\r
+ {\r
+ int line;\r
+ int column;\r
+ string value;\r
+ TokenKind kind;\r
+\r
+ public Token(TokenKind kind, string value, int line, int column)\r
+ {\r
+ this.kind = kind;\r
+ this.value = value;\r
+ this.line = line;\r
+ this.column = column;\r
+ }\r
+\r
+ public int Column\r
+ {\r
+ get { return this.column; }\r
+ }\r
+\r
+ public TokenKind Kind\r
+ {\r
+ get { return this.kind; }\r
+ }\r
+\r
+ public int Line\r
+ {\r
+ get { return this.line; }\r
+ }\r
+\r
+ public string Value\r
+ {\r
+ get { return this.value; }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// StringTokenizer tokenized string (or stream) into tokens.\r
+ /// </summary>\r
+ public class StringTokenizer\r
+ {\r
+ const char EOF = (char)0;\r
+\r
+ int line;\r
+ int column;\r
+ int pos; // position within data\r
+\r
+ string data;\r
+\r
+ bool ignoreWhiteSpace;\r
+ char[] symbolChars;\r
+\r
+ int saveLine;\r
+ int saveCol;\r
+ int savePos;\r
+\r
+ public StringTokenizer(TextReader reader)\r
+ {\r
+ if (reader == null)\r
+ throw new ArgumentNullException("reader");\r
+\r
+ data = reader.ReadToEnd();\r
+\r
+ Reset();\r
+ }\r
+\r
+ public StringTokenizer(string data)\r
+ {\r
+ if (data == null)\r
+ throw new ArgumentNullException("data");\r
+\r
+ this.data = data;\r
+\r
+ Reset();\r
+ }\r
+\r
+ /// <summary>\r
+ /// gets or sets which characters are part of TokenKind.Symbol\r
+ /// </summary>\r
+ public char[] SymbolChars\r
+ {\r
+ get { return this.symbolChars; }\r
+ set { this.symbolChars = value; }\r
+ }\r
+\r
+ /// <summary>\r
+ /// if set to true, white space characters will be ignored,\r
+ /// but EOL and whitespace inside of string will still be tokenized\r
+ /// </summary>\r
+ public bool IgnoreWhiteSpace\r
+ {\r
+ get { return this.ignoreWhiteSpace; }\r
+ set { this.ignoreWhiteSpace = value; }\r
+ }\r
+\r
+ private void Reset()\r
+ {\r
+ this.ignoreWhiteSpace = false;\r
+ this.symbolChars = new char[]{'=', '+', '-', '/', ',', '.', '*', '~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', ':', ';', '<', '>', '?', '|', '\\'};\r
+\r
+ line = 1;\r
+ column = 1;\r
+ pos = 0;\r
+ }\r
+\r
+ protected char LA(int count)\r
+ {\r
+ if (pos + count >= data.Length)\r
+ return EOF;\r
+ else\r
+ return data[pos+count];\r
+ }\r
+\r
+ protected char Consume()\r
+ {\r
+ char ret = data[pos];\r
+ pos++;\r
+ column++;\r
+\r
+ return ret;\r
+ }\r
+\r
+ protected Token CreateToken(TokenKind kind, string value)\r
+ {\r
+ return new Token(kind, value, line, column);\r
+ }\r
+\r
+ protected Token CreateToken(TokenKind kind)\r
+ {\r
+ string tokenData = data.Substring(savePos, pos-savePos);\r
+ return new Token(kind, tokenData, saveLine, saveCol);\r
+ }\r
+\r
+ public Token Next()\r
+ {\r
+ ReadToken:\r
+\r
+ char ch = LA(0);\r
+ switch (ch)\r
+ {\r
+ case EOF:\r
+ return CreateToken(TokenKind.EOF, string.Empty);\r
+\r
+ case ' ':\r
+ case '\t':\r
+ {\r
+ if (this.ignoreWhiteSpace)\r
+ {\r
+ Consume();\r
+ goto ReadToken;\r
+ }\r
+ else\r
+ return ReadWhitespace();\r
+ }\r
+ case '0':\r
+ case '1':\r
+ case '2':\r
+ case '3':\r
+ case '4':\r
+ case '5':\r
+ case '6':\r
+ case '7':\r
+ case '8':\r
+ case '9':\r
+ return ReadNumber();\r
+\r
+ case '\r':\r
+ {\r
+ StartRead();\r
+ Consume();\r
+ if (LA(0) == '\n')\r
+ Consume(); // on DOS/Windows we have \r\n for new line\r
+\r
+ line++;\r
+ column=1;\r
+\r
+ return CreateToken(TokenKind.EOL);\r
+ }\r
+ case '\n':\r
+ {\r
+ StartRead();\r
+ Consume();\r
+ line++;\r
+ column=1;\r
+ \r
+ return CreateToken(TokenKind.EOL);\r
+ }\r
+\r
+ case '"':\r
+ {\r
+ return ReadString();\r
+ }\r
+\r
+ case '/':\r
+ {\r
+ if (LA(1) == '/')\r
+ {\r
+ return ReadComment();\r
+ }\r
+ else if (LA(1) == '*')\r
+ {\r
+ return ReadStarComment();\r
+ }\r
+ else\r
+ {\r
+ StartRead();\r
+ Consume();\r
+ return CreateToken(TokenKind.Symbol);\r
+ }\r
+ }\r
+\r
+ default:\r
+ {\r
+ if (Char.IsLetter(ch) || ch == '_')\r
+ return ReadWord();\r
+ else if (IsSymbol(ch))\r
+ {\r
+ StartRead();\r
+ Consume();\r
+ return CreateToken(TokenKind.Symbol);\r
+ }\r
+ else\r
+ {\r
+ StartRead();\r
+ Consume();\r
+ return CreateToken(TokenKind.Unknown); \r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// save read point positions so that CreateToken can use those\r
+ /// </summary>\r
+ private void StartRead()\r
+ {\r
+ saveLine = line;\r
+ saveCol = column;\r
+ savePos = pos;\r
+ }\r
+\r
+ /// <summary>\r
+ /// reads all whitespace characters (does not include newline)\r
+ /// </summary>\r
+ /// <returns></returns>\r
+ protected Token ReadWhitespace()\r
+ {\r
+ StartRead();\r
+\r
+ Consume(); // consume the looked-ahead whitespace char\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (ch == '\t' || ch == ' ')\r
+ Consume();\r
+ else\r
+ break;\r
+ }\r
+\r
+ return CreateToken(TokenKind.WhiteSpace);\r
+ \r
+ }\r
+\r
+ /// <summary>\r
+ /// reads number. Number is: DIGIT+ ("." DIGIT*)?\r
+ /// </summary>\r
+ /// <returns></returns>\r
+ protected Token ReadNumber()\r
+ {\r
+ StartRead();\r
+\r
+ bool hadDot = false;\r
+\r
+ Consume(); // read first digit\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (Char.IsDigit(ch))\r
+ Consume();\r
+ else if (ch == '.' && !hadDot)\r
+ {\r
+ hadDot = true;\r
+ Consume();\r
+ }\r
+ else\r
+ break;\r
+ }\r
+\r
+ return CreateToken(TokenKind.Number);\r
+ }\r
+\r
+ /// <summary>\r
+ /// reads word. Word contains any alpha character or _\r
+ /// </summary>\r
+ protected Token ReadWord()\r
+ {\r
+ StartRead();\r
+\r
+ Consume(); // consume first character of the word\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (Char.IsLetter(ch) || ch == '_')\r
+ Consume();\r
+ else\r
+ break;\r
+ }\r
+\r
+ return CreateToken(TokenKind.Word);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Reads he rest of line in // comment\r
+ /// </summary>\r
+ protected Token ReadComment()\r
+ {\r
+ StartRead();\r
+\r
+ Consume(); // consume first character of the comment\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (ch != EOF && ch != '\n' && ch != '\r')\r
+ Consume();\r
+ else\r
+ break;\r
+ }\r
+\r
+ return CreateToken(TokenKind.Comment);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Read c-style comments /* */\r
+ /// </summary>\r
+ protected Token ReadStarComment()\r
+ {\r
+ StartRead();\r
+\r
+ Consume(); // consume first character of the comment\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (ch == EOF)\r
+ {\r
+ break;\r
+ }\r
+ else if (ch == '*' && LA(1) == '/')\r
+ {\r
+ Consume();\r
+ Consume();\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ Consume();\r
+ }\r
+ }\r
+\r
+ return CreateToken(TokenKind.Comment);\r
+ }\r
+\r
+ /// <summary>\r
+ /// reads all characters until next " is found.\r
+ /// If "" (2 quotes) are found, then they are consumed as\r
+ /// part of the string\r
+ /// </summary>\r
+ /// <returns></returns>\r
+ protected Token ReadString()\r
+ {\r
+ StartRead();\r
+\r
+ Consume(); // read "\r
+\r
+ while (true)\r
+ {\r
+ char ch = LA(0);\r
+ if (ch == EOF)\r
+ break;\r
+ else if (ch == '\r') // handle CR in strings\r
+ {\r
+ Consume();\r
+ if (LA(0) == '\n') // for DOS & windows\r
+ Consume();\r
+\r
+ line++;\r
+ column = 1;\r
+ }\r
+ else if (ch == '\n') // new line in quoted string\r
+ {\r
+ Consume();\r
+\r
+ line++;\r
+ column = 1;\r
+ }\r
+ else if (ch == '"')\r
+ {\r
+ Consume();\r
+ if (LA(0) != '"')\r
+ break; // done reading, and this quotes does not have escape character\r
+ else\r
+ Consume(); // consume second ", because first was just an escape\r
+ }\r
+ else\r
+ Consume();\r
+ }\r
+\r
+ return CreateToken(TokenKind.QuotedString);\r
+ }\r
+\r
+ /// <summary>\r
+ /// checks whether c is a symbol character.\r
+ /// </summary>\r
+ protected bool IsSymbol(char c)\r
+ {\r
+ for (int i=0; i<symbolChars.Length; i++)\r
+ if (symbolChars[i] == c)\r
+ return true;\r
+\r
+ return false;\r
+ }\r
+ }\r
+}\r
this.tbtbLoadFromDisk = new System.Windows.Forms.ToolStripMenuItem();\r
this.tbtbSave = new System.Windows.Forms.ToolStripMenuItem();\r
this.tbtbSaveToDisk = new System.Windows.Forms.ToolStripMenuItem();\r
+ this.tbtbSaveToDiskAs = new System.Windows.Forms.ToolStripMenuItem();\r
this.tSeparator1 = new System.Windows.Forms.ToolStripSeparator();\r
this.tbtnExit = new System.Windows.Forms.ToolStripMenuItem();\r
this.tbtnAttach = new System.Windows.Forms.ToolStripButton();\r
this.strpStatus = new System.Windows.Forms.ToolStrip();\r
this.lblScripStatus = new System.Windows.Forms.ToolStripLabel();\r
- this.lblLine = new System.Windows.Forms.ToolStripLabel();\r
this.lblCol = new System.Windows.Forms.ToolStripLabel();\r
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();\r
+ this.lblLine = new System.Windows.Forms.ToolStripLabel();\r
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();\r
this.rtbCode = new Radegast.RRichTextBox();\r
this.strpMenu.SuspendLayout();\r
this.tbtbLoadFromDisk,\r
this.tbtbSave,\r
this.tbtbSaveToDisk,\r
+ this.tbtbSaveToDiskAs,\r
this.tSeparator1,\r
this.tbtnExit});\r
this.tbtbFile.Image = ((System.Drawing.Image)(resources.GetObject("tbtbFile.Image")));\r
// tbtbLoadFromDisk\r
// \r
this.tbtbLoadFromDisk.Name = "tbtbLoadFromDisk";\r
- this.tbtbLoadFromDisk.Size = new System.Drawing.Size(165, 22);\r
+ this.tbtbLoadFromDisk.Size = new System.Drawing.Size(168, 22);\r
this.tbtbLoadFromDisk.Text = "Open...";\r
this.tbtbLoadFromDisk.Click += new System.EventHandler(this.tbtbLoadFromDisk_Click);\r
// \r
// \r
this.tbtbSave.Enabled = false;\r
this.tbtbSave.Name = "tbtbSave";\r
- this.tbtbSave.Size = new System.Drawing.Size(165, 22);\r
- this.tbtbSave.Text = "Save to inventory";\r
+ this.tbtbSave.Size = new System.Drawing.Size(168, 22);\r
+ this.tbtbSave.Text = "Save To Inventory";\r
// \r
// tbtbSaveToDisk\r
// \r
this.tbtbSaveToDisk.Name = "tbtbSaveToDisk";\r
- this.tbtbSaveToDisk.Size = new System.Drawing.Size(165, 22);\r
- this.tbtbSaveToDisk.Text = "Save to disk...";\r
- this.tbtbSaveToDisk.Click += new System.EventHandler(this.tbtbSaveToDisk_Click);\r
+ this.tbtbSaveToDisk.Size = new System.Drawing.Size(168, 22);\r
+ this.tbtbSaveToDisk.Text = "Save To Disk";\r
+ this.tbtbSaveToDisk.Click += new System.EventHandler(this.tbtbSaveToDisk_Click_1);\r
+ // \r
+ // tbtbSaveToDiskAs\r
+ // \r
+ this.tbtbSaveToDiskAs.Name = "tbtbSaveToDiskAs";\r
+ this.tbtbSaveToDiskAs.Size = new System.Drawing.Size(168, 22);\r
+ this.tbtbSaveToDiskAs.Text = "Save To Disk As...";\r
+ this.tbtbSaveToDiskAs.Click += new System.EventHandler(this.tbtbSaveToDisk_Click);\r
// \r
// tSeparator1\r
// \r
this.tSeparator1.Name = "tSeparator1";\r
- this.tSeparator1.Size = new System.Drawing.Size(162, 6);\r
+ this.tSeparator1.Size = new System.Drawing.Size(165, 6);\r
this.tSeparator1.Visible = false;\r
// \r
// tbtnExit\r
// \r
this.tbtnExit.Name = "tbtnExit";\r
- this.tbtnExit.Size = new System.Drawing.Size(165, 22);\r
+ this.tbtnExit.Size = new System.Drawing.Size(168, 22);\r
this.tbtnExit.Text = "Close";\r
this.tbtnExit.Visible = false;\r
this.tbtnExit.Click += new System.EventHandler(this.tbtnExit_Click);\r
this.lblScripStatus.Size = new System.Drawing.Size(59, 22);\r
this.lblScripStatus.Text = "Loading...";\r
// \r
- // lblLine\r
- // \r
- this.lblLine.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
- this.lblLine.AutoSize = false;\r
- this.lblLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
- this.lblLine.Name = "lblLine";\r
- this.lblLine.Size = new System.Drawing.Size(55, 22);\r
- this.lblLine.Text = "Ln 1";\r
- this.lblLine.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\r
- // \r
// lblCol\r
// \r
this.lblCol.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
this.toolStripSeparator1.Name = "toolStripSeparator1";\r
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);\r
// \r
+ // lblLine\r
+ // \r
+ this.lblLine.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
+ this.lblLine.AutoSize = false;\r
+ this.lblLine.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
+ this.lblLine.Name = "lblLine";\r
+ this.lblLine.Size = new System.Drawing.Size(55, 22);\r
+ this.lblLine.Text = "Ln 1";\r
+ this.lblLine.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\r
+ // \r
// toolStripSeparator2\r
// \r
this.toolStripSeparator2.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;\r
// \r
// rtbCode\r
// \r
- this.rtbCode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(250)))), ((int)(((byte)(255)))), ((int)(((byte)(250)))));\r
+ this.rtbCode.BackColor = System.Drawing.Color.WhiteSmoke;\r
this.rtbCode.Dock = System.Windows.Forms.DockStyle.Fill;\r
- this.rtbCode.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));\r
+ this.rtbCode.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));\r
this.rtbCode.HideSelection = false;\r
this.rtbCode.Location = new System.Drawing.Point(0, 25);\r
this.rtbCode.Name = "rtbCode";\r
this.rtbCode.TabIndex = 1;\r
this.rtbCode.Text = "";\r
this.rtbCode.WordWrap = false;\r
+ this.rtbCode.KeyDown += new System.Windows.Forms.KeyEventHandler(this.rtbCode_KeyDown);\r
this.rtbCode.SelectionChanged += new System.EventHandler(this.rtbCode_SelectionChanged);\r
- this.rtbCode.MouseMove += new System.Windows.Forms.MouseEventHandler(this.rtbCode_MouseMove);\r
- this.rtbCode.TextChanged += new System.EventHandler(this.rtbCode_TextChanged);\r
+ this.rtbCode.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.rtbCode_KeyPress);\r
// \r
// ScriptEditor\r
// \r
private System.Windows.Forms.ToolStrip strpMenu;\r
private System.Windows.Forms.ToolStripDropDownButton tbtbFile;\r
private System.Windows.Forms.ToolStripMenuItem tbtbSave;\r
- private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDisk;\r
+ private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDiskAs;\r
private System.Windows.Forms.ToolStripMenuItem tbtbLoadFromDisk;\r
private System.Windows.Forms.ToolStripButton tbtnAttach;\r
private System.Windows.Forms.ToolStripSeparator tSeparator1;\r
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;\r
private System.Windows.Forms.ToolStripLabel lblLine;\r
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;\r
+ private System.Windows.Forms.ToolStripMenuItem tbtbSaveToDisk;\r
}\r
}\r
{\r
private RadegastInstance instance;\r
private GridClient client { get { return instance.Client; } }\r
- private Dictionary<string, LSLKeyWord> keywords = LSLKeywordParser.KeyWords;\r
private InventoryLSL script;\r
private UUID requestID;\r
private bool populating = true;\r
- private List<WordAndPosition> lineBuffer = new List<WordAndPosition>();\r
- private Color commentColor = Color.FromArgb(204, 76, 38);\r
private string scriptName;\r
- private System.Threading.Timer ttTimer;\r
+ private string fileName;\r
\r
public ScriptEditor(RadegastInstance instance)\r
: this(instance, null)\r
this.instance = instance;\r
this.script = script;\r
lblScripStatus.Text = string.Empty;\r
- ttTimer = new System.Threading.Timer(ttTimerElapsed, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);\r
-\r
+ Dock = DockStyle.Fill;\r
+ this.TabStop = false;\r
// Callbacks\r
client.Assets.OnAssetReceived += new AssetManager.AssetReceivedCallback(Assets_OnAssetReceived);\r
\r
}\r
\r
asset.Decode();\r
- rtbCode.BeginUpdate();\r
rtbCode.Text = ((AssetScriptText)asset).Source;\r
- MakeColorSyntaxForAllText();\r
- rtbCode.EndUpdate();\r
- lblScripStatus.Text = scriptName;\r
- }\r
-\r
- #region Syntax highlighting\r
- struct WordAndPosition\r
- {\r
- public string Word;\r
- public int Position;\r
- public int Length;\r
- public override string ToString()\r
- {\r
- string s = "Word = " + Word + ", Position = " + Position + ", Length = " + Length + "\n";\r
- return s;\r
- }\r
- };\r
-\r
- private int ParseLine(string s)\r
- {\r
- lineBuffer.Clear();\r
- Regex r = new Regex(@"\w+|[^A-Za-z0-9_ \f\t\v]", RegexOptions.IgnoreCase | RegexOptions.Compiled);\r
- Match m;\r
-\r
- for (m = r.Match(s); m.Success; m = m.NextMatch())\r
- {\r
- WordAndPosition w = new WordAndPosition();\r
- w.Word = m.Value;\r
- w.Position = m.Index;\r
- w.Length = m.Length;\r
- lineBuffer.Add(w);\r
- }\r
-\r
- return lineBuffer.Count();\r
- }\r
-\r
- private Color Lookup(string s)\r
- {\r
- if (keywords.ContainsKey(s))\r
- {\r
- return keywords[s].Color;\r
- }\r
- else\r
- {\r
- return Color.Black;\r
- }\r
- }\r
-\r
- private bool TestComment(string s)\r
- {\r
- string testString = s.Trim();\r
- if ((testString.Length >= 2) &&\r
- (testString[0] == '/') &&\r
- (testString[1] == '/')\r
- )\r
- return true;\r
-\r
- return false;\r
- }\r
-\r
- private void MakeColorSyntaxForCurrentLine()\r
- {\r
- int CurrentSelectionStart = rtbCode.SelectionStart;\r
- int CurrentSelectionLength = rtbCode.SelectionLength;\r
-\r
- // find start of line\r
- int pos = CurrentSelectionStart;\r
- while ((pos > 0) && (rtbCode.Text[pos - 1] != '\n'))\r
- pos--;\r
-\r
- int pos2 = CurrentSelectionStart;\r
- while ((pos2 < rtbCode.Text.Length) &&\r
- (rtbCode.Text[pos2] != '\n'))\r
- pos2++;\r
-\r
- string s = rtbCode.Text.Substring(pos, pos2 - pos);\r
- if (TestComment(s) == true)\r
- {\r
- rtbCode.Select(pos, pos2 - pos);\r
- rtbCode.SelectionColor = commentColor;\r
- }\r
- else\r
- {\r
- string previousWord = "";\r
- int count = ParseLine(s);\r
- for (int i = 0; i < count; i++)\r
- {\r
- WordAndPosition wp = lineBuffer[i];\r
-\r
- // check for comment\r
- if (wp.Word == "/" && previousWord == "/")\r
- {\r
- // color until end of line\r
- int posCommentStart = wp.Position - 1;\r
- int posCommentEnd = pos2;\r
- while (wp.Word != "\n" && i < count)\r
- {\r
- wp = lineBuffer[i];\r
- i++;\r
- }\r
-\r
- i--;\r
-\r
- posCommentEnd = pos2;\r
- rtbCode.Select(posCommentStart + pos, posCommentEnd - (posCommentStart + pos));\r
- rtbCode.SelectionColor = this.commentColor;\r
-\r
- }\r
- else\r
- {\r
-\r
- Color c = Lookup(wp.Word);\r
- rtbCode.Select(wp.Position + pos, wp.Length);\r
- rtbCode.SelectionColor = c;\r
- }\r
-\r
- previousWord = wp.Word;\r
-\r
- }\r
- }\r
-\r
- if (CurrentSelectionStart >= 0)\r
- rtbCode.Select(CurrentSelectionStart, CurrentSelectionLength);\r
- }\r
-\r
- private void MakeColorSyntaxForAllText()\r
- {\r
- populating = true;\r
-\r
- string s = rtbCode.Text;\r
- int CurrentSelectionStart = rtbCode.SelectionStart;\r
- int CurrentSelectionLength = rtbCode.SelectionLength;\r
-\r
- int count = ParseLine(s);\r
- string previousWord = "";\r
- for (int i = 0; i < count; i++)\r
- {\r
- WordAndPosition wp = lineBuffer[i];\r
-\r
- // check for comment\r
- if (wp.Word == "/" && previousWord == "/")\r
- {\r
- // color until end of line\r
- int posCommentStart = wp.Position - 1;\r
- int posCommentEnd = i;\r
- while (wp.Word != "\n" && i < count)\r
- {\r
- wp = lineBuffer[i];\r
- i++;\r
- }\r
-\r
- i--;\r
-\r
- posCommentEnd = wp.Position;\r
- rtbCode.Select(posCommentStart, posCommentEnd - posCommentStart);\r
- rtbCode.SelectionColor = this.commentColor;\r
-\r
- }\r
- else\r
- {\r
-\r
- Color c = Lookup(wp.Word);\r
- rtbCode.Select(wp.Position, wp.Length);\r
- rtbCode.SelectionColor = c;\r
- }\r
-\r
- previousWord = wp.Word;\r
-\r
- // Console.WriteLine(wp.ToString());\r
- }\r
-\r
- if (CurrentSelectionStart >= 0)\r
- rtbCode.Select(CurrentSelectionStart, CurrentSelectionLength);\r
-\r
- populating = false;\r
-\r
+ SetTitle();\r
}\r
\r
- private void rtbCode_TextChanged(object sender, EventArgs e)\r
+ private void SetTitle()\r
{\r
- if (populating)\r
+ if (detached)\r
{\r
- return;\r
+ FindForm().Text = scriptName + " - " + Properties.Resources.ProgramName + " script editor";\r
}\r
- rtbCode.BeginUpdate();\r
- MakeColorSyntaxForCurrentLine();\r
- rtbCode.EndUpdate();\r
}\r
- #endregion\r
\r
#region Detach/Attach\r
private Control originalParent;\r
originalParent = Parent;\r
Parent = detachedForm;\r
detachedForm.ClientSize = new Size(873, 580);\r
- detachedForm.Text = scriptName + " - " + Properties.Resources.ProgramName + " script editor"; \r
+ SetTitle();\r
+ detachedForm.ActiveControl = this;\r
detachedForm.Show();\r
detachedForm.FormClosing += new FormClosingEventHandler(detachedForm_FormClosing);\r
\r
}\r
#endregion\r
\r
- #region ToolTips\r
- private bool validWordChar(char c)\r
+ \r
+ #region File I/O\r
+ private void tbtbSaveToDisk_Click_1(object sender, EventArgs e)\r
{\r
- return\r
- (c >= 'a' && c <= 'z') ||\r
- (c >= 'A' && c <= 'Z') ||\r
- (c >= '0' && c <= '9') ||\r
- c == '_';\r
- }\r
-\r
- private void ttTimerElapsed(Object sender)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate() { ttTimerElapsed(sender); }));\r
- return;\r
- }\r
-\r
- char trackedChar = rtbCode.GetCharFromPosition(trackedMousePos);\r
- \r
- if (!validWordChar(trackedChar))\r
- {\r
- return;\r
- }\r
-\r
- string trackedString = rtbCode.Text;\r
- int trackedPos = rtbCode.GetCharIndexFromPosition(trackedMousePos);\r
- int starPos;\r
- int endPos;\r
-\r
- for (starPos = trackedPos; starPos >= 0 && validWordChar(trackedString[starPos]); starPos--) ;\r
- for (endPos = trackedPos; endPos < trackedString.Length && validWordChar(trackedString[endPos]); endPos++) ;\r
- string word = trackedString.Substring(starPos + 1, endPos - starPos - 1);\r
-\r
- if (!keywords.ContainsKey(word) || keywords[word].ToolTip == string.Empty)\r
+ if (string.IsNullOrEmpty(fileName))\r
{\r
+ tbtbSaveToDisk_Click(sender, e);\r
return;\r
}\r
-\r
- ttKeyWords.Show(keywords[word].ToolTip, rtbCode, new Point(trackedMousePos.X, trackedMousePos.Y + 15), 120 * 1000);\r
+ File.WriteAllText(fileName, rtbCode.Text);\r
}\r
\r
- private Point trackedMousePos = new Point(0, 0);\r
-\r
- private void rtbCode_MouseMove(object sender, MouseEventArgs e)\r
- {\r
- Point currentMousePos = new Point(e.X, e.Y);\r
-\r
- if (currentMousePos != trackedMousePos)\r
- {\r
- trackedMousePos = currentMousePos;\r
- ttTimer.Change(500, System.Threading.Timeout.Infinite);\r
- ttKeyWords.Hide(rtbCode);\r
- }\r
- }\r
- #endregion\r
-\r
private void tbtbSaveToDisk_Click(object sender, EventArgs e)\r
{\r
SaveFileDialog dlg = new SaveFileDialog();\r
dlg.Title = "Save script";\r
- dlg.Filter = "LSL script file (*.lsl)|*.lsl";\r
+ dlg.Filter = "LSL script file (*.lsl)|*.lsl|Plain text file (*.txt)|*.txt";\r
dlg.FileName = RadegastMisc.SafeFileName(scriptName);\r
DialogResult res = dlg.ShowDialog();\r
\r
if (res == DialogResult.OK)\r
{\r
- File.WriteAllText(dlg.FileName, rtbCode.Text);\r
+ fileName = dlg.FileName;\r
+ scriptName = Path.GetFileName(fileName);\r
+ SetTitle();\r
+ File.WriteAllText(fileName, rtbCode.Text);\r
}\r
\r
}\r
{\r
OpenFileDialog dlg = new OpenFileDialog();\r
dlg.Title = "Open script";\r
- dlg.Filter = "LSL script file (*.lsl)|*.lsl";\r
+ dlg.Filter = "LSL script files (*.lsl)|*.lsl|Plain text files (*.txt)|*.txt|All files (*.*)|*.*";\r
dlg.Multiselect = false;\r
DialogResult res = dlg.ShowDialog();\r
\r
if (res == DialogResult.OK)\r
{\r
- scriptName = dlg.FileName;\r
- rtbCode.Text = File.ReadAllText(dlg.FileName);\r
- rtbCode.BeginUpdate();\r
- MakeColorSyntaxForAllText();\r
- rtbCode.EndUpdate();\r
+ fileName = dlg.FileName;\r
+ scriptName = Path.GetFileName(fileName);\r
+ SetTitle();\r
+ rtbCode.Text = File.ReadAllText(fileName);\r
}\r
}\r
+ #endregion\r
\r
private void tbtnExit_Click(object sender, EventArgs e)\r
{\r
lblLine.Text = string.Format("Ln {0}", c.Line + 1);\r
lblCol.Text = string.Format("Col {0}", c.Column + 1);\r
}\r
+\r
+ private bool spaceOrTab(char c)\r
+ {\r
+ return c == ' ' || c == '\t';\r
+ }\r
+\r
+ private int lastPos(string s, char c)\r
+ {\r
+ s = s.TrimEnd();\r
+ \r
+ if (s == string.Empty)\r
+ return -1;\r
+\r
+ if (s[s.Length - 1] == c)\r
+ {\r
+ return s.LastIndexOf(c);\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ private void rtbCode_KeyDown(object sender, KeyEventArgs e)\r
+ {\r
+ if (e.KeyCode == Keys.Tab)\r
+ {\r
+ rtbCode.SelectedText = " ";\r
+ e.Handled = true;\r
+ }\r
+ else if (e.KeyCode == Keys.Enter)\r
+ {\r
+ if (rtbCode.Lines.Length > 0)\r
+ {\r
+ RRichTextBox.CursorLocation cl = rtbCode.CursorPosition;\r
+ string prevLine = rtbCode.Lines[cl.Line];\r
+ string addIndent = "\n";\r
+ int pos;\r
+\r
+ for (int spaces = 0;\r
+ spaces < prevLine.Length && spaceOrTab(prevLine[spaces]);\r
+ addIndent += prevLine[spaces++]) ;\r
+\r
+ if ((pos = lastPos(prevLine.Substring(0, cl.Column), '{')) != -1)\r
+ {\r
+ addIndent += " ";\r
+ }\r
+\r
+ rtbCode.SelectedText = addIndent;\r
+ int eat = 0;\r
+ for (eat = 0; (eat + rtbCode.SelectionStart) < rtbCode.Text.Length && rtbCode.Text[rtbCode.SelectionStart + eat] == ' '; eat++) ;\r
+ rtbCode.SelectionLength = eat;\r
+ rtbCode.SelectedText = "";\r
+ e.Handled = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ private void rtbCode_KeyPress(object sender, KeyPressEventArgs e)\r
+ {\r
+ if (e.KeyChar == '}' && rtbCode.Lines.Length > 0)\r
+ {\r
+ string li = rtbCode.Lines[rtbCode.GetLineFromCharIndex(rtbCode.SelectionStart)];\r
+\r
+ if (li.Trim() == "")\r
+ {\r
+ rtbCode.BeginUpdate();\r
+ int toDelete = li.Length;\r
+\r
+ if (toDelete > 4)\r
+ {\r
+ toDelete = 4;\r
+ }\r
+\r
+ rtbCode.SelectionStart -= toDelete;\r
+ rtbCode.SelectionLength = toDelete;\r
+ rtbCode.SelectedText = "}";\r
+ rtbCode.EndUpdate();\r
+ e.Handled = true;\r
+ }\r
+ }\r
+ }\r
}\r
}\r
}\r
\r
\r
- //if (folder.PreferredType == AssetType.Unknown)\r
+ if (folder.PreferredType == AssetType.Unknown)\r
{\r
ctxInv.Items.Add(new ToolStripSeparator());\r
ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);\r
\r
ToolStripMenuItem ctxItem;\r
\r
+ if (item.InventoryType == InventoryType.LSL)\r
+ {\r
+ ctxItem = new ToolStripMenuItem("Edit script", null, OnInvContextClick);\r
+ ctxItem.Name = "edit_script";\r
+ ctxInv.Items.Add(ctxItem);\r
+ }\r
+\r
ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);\r
ctxItem.Name = "rename_item";\r
ctxInv.Items.Add(ctxItem);\r
AttachmentPoint pt = (AttachmentPoint)((ToolStripMenuItem)sender).Tag;\r
client.Appearance.Attach(item, pt);\r
break;\r
+\r
+ case "edit_script":\r
+ ScriptEditor se = new ScriptEditor(instance, (InventoryLSL)item);\r
+ se.Detached = true;\r
+ return;\r
}\r
#endregion\r
}\r
<DefineConstants>DEBUG;TRACE</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
<WarningLevel>4</WarningLevel>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
</PropertyGroup>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
<DebugType>pdbonly</DebugType>\r
<DefineConstants>TRACE</DefineConstants>\r
<ErrorReport>prompt</ErrorReport>\r
<WarningLevel>4</WarningLevel>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
</PropertyGroup>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
<DebugSymbols>true</DebugSymbols>\r
<DebugType>full</DebugType>\r
<PlatformTarget>x86</PlatformTarget>\r
<ErrorReport>prompt</ErrorReport>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
</PropertyGroup>\r
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
<OutputPath>..\bin\Release\</OutputPath>\r
<DebugType>pdbonly</DebugType>\r
<PlatformTarget>x86</PlatformTarget>\r
<ErrorReport>prompt</ErrorReport>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
</PropertyGroup>\r
<ItemGroup>\r
<Reference Include="AIMLbot, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />\r
<Compile Include="Core\Types\RRichTextBox.cs">\r
<SubType>Component</SubType>\r
</Compile>\r
+ <Compile Include="Core\Types\StringTokenizer.cs" />\r
<Compile Include="Core\Types\TransparentButton.cs">\r
<SubType>Component</SubType>\r
</Compile>\r