using System; using AppKit; using Foundation; using System.Collections.Generic; namespace Cauldron.Macos.SourceWriter; [Register("LanguageDescriptor")] public class LanguageDescriptor : NSObject { #region Computed Properties /// Gets the language identifier. /// The language identifier. public virtual string LanguageIdentifier { get => "Default"; } /// /// Gets or sets the language separators that can be used to define a "word" in the given /// language. /// /// The language separators. public virtual char[] LanguageSeparators { get; set; } = new char[] { '.' }; /// /// Gets the escape character for the given language. /// /// The escape character. public virtual char EscapeCharacter { get => '\\'; } /// /// Gets or sets the collection of used to define /// the keywords for this language. /// /// The keywords. public Dictionary Keywords { get; set; } = new Dictionary(); /// /// Gets or sets the collection of formats used to syntax /// highlight this language. /// /// The formats. public List Formats { get; set; } = new List(); /// /// Gets or sets the collection of used to auto complete to /// closure of text such as (), [], "" or ''. /// /// The closures. public List Closures { get; set; } = new List(); /// /// Gets or sets the formatting commands that can be added to the user interface for the user to /// select and apply to a selection of text in the editor. /// /// The items. public List FormattingCommands { get; set; } = new List(); /// Gets or sets the color of generic keywords. /// The NSColor of the keyword. [Export("KeywordColor")] public NSColor KeywordColor { get => LoadColor("KeywordColor", NSColor.SystemTeal); set { WillChangeValue("KeywordColor"); SaveColor("KeywordColor", value, true); DidChangeValue("KeywordColor"); } } /// Gets or sets the color of generic keyword type. /// The NSColor of the type. [Export("TypeColor")] public NSColor TypeColor { get => LoadColor("TypeColor", NSColor.SystemTeal); set { WillChangeValue("TypeColor"); SaveColor("TypeColor", value, true); DidChangeValue("TypeColor"); } } /// Gets or sets the color of a value type keyword. /// The NSColor of the value type. [Export("ValueTypeColor")] public NSColor ValueTypeColor { get => LoadColor("ValueTypeColor", NSColor.SystemBlue); set { WillChangeValue("ValueTypeColor"); SaveColor("ValueTypeColor", value, true); DidChangeValue("ValueTypeColor"); } } /// Gets or sets the color of a reference type keyword. /// The NSColor of the reference type. [Export("ReferenceTypeColor")] public NSColor ReferenceTypeColor { get => LoadColor("ReferenceTypeColor", NSColor.SystemCyan); set { WillChangeValue("ReferenceTypeColor"); SaveColor("ReferenceTypeColor", value, true); DidChangeValue("ReferenceTypeColor"); } } /// Gets or sets the color of a access modifier keyword. /// The NSColor of the access modifier. [Export("AccessModifierColor")] public NSColor AccessModifierColor { get => LoadColor("AccessModifierColor", NSColor.SystemTeal); set { WillChangeValue("AccessModifierColor"); SaveColor("AccessModifierColor", value, true); DidChangeValue("AccessModifierColor"); } } /// Gets or sets the color of a generic modifier keyword. /// The NSColor of the modifier. [Export("ModifierColor")] public NSColor ModifierColor { get => LoadColor("ModifierColor", NSColor.SystemTeal); set { WillChangeValue("ModifierColor"); SaveColor("ModifierColor", value, true); DidChangeValue("ModifierColor"); } } /// Gets or sets the color of a selection statement keyword. /// The NSColor of the selection statement. [Export("SelectionStatementColor")] public NSColor SelectionStatementColor { get => LoadColor("SelectionStatementColor", NSColor.SystemBrown); set { WillChangeValue("SelectionStatementColor"); SaveColor("SelectionStatementColor", value, true); DidChangeValue("SelectionStatementColor"); } } /// Gets or sets the color of a iteration statement keyword. /// The NSColor of the iteration statement. [Export("IterationStatementColor")] public NSColor IterationStatementColor { get => LoadColor("IterationStatementColor", NSColor.SystemRed); set { WillChangeValue("IterationStatementColor"); SaveColor("IterationStatementColor", value, true); DidChangeValue("IterationStatementColor"); } } /// Gets or sets the color of a jump statement keyword. /// The NSColor of the jump statement. [Export("JumpStatementColor")] public NSColor JumpStatementColor { get => LoadColor("JumpStatementColor", NSColor.SystemYellow); set { WillChangeValue("JumpStatementColor"); SaveColor("JumpStatementColor", value, true); DidChangeValue("JumpStatementColor"); } } /// Gets or sets the color of a exception handling keyword. /// The NSColor of the exception handling. [Export("ExceptionHandlingColor")] public NSColor ExceptionHandlingColor { get => LoadColor("ExceptionHandlingColor", NSColor.SystemRed); set { WillChangeValue("ExceptionHandlingColor"); SaveColor("ExceptionHandlingColor", value, true); DidChangeValue("ExceptionHandlingColor"); } } /// Gets or sets the color of a generic statement keyword. /// The NSColor of the statement. [Export("StatementColor")] public NSColor StatementColor { get => LoadColor("StatementColor", NSColor.SystemPink); set { WillChangeValue("StatementColor"); SaveColor("StatementColor", value, true); DidChangeValue("StatementColor"); } } /// Gets or sets the color of a method parameter keyword. /// The NSColor of the method parameter. [Export("MethodParameterColor")] public NSColor MethodParameterColor { get => LoadColor("MethodParameterColor", NSColor.SystemTeal); set { WillChangeValue("MethodParameterColor"); SaveColor("MethodParameterColor", value, true); DidChangeValue("MethodParameterColor"); } } /// Gets or sets the color of a namespace keyword. /// The NSColor of the namespace. [Export("NamespaceColor")] public NSColor NamespaceColor { get => LoadColor("NamespaceColor", NSColor.SystemTeal); set { WillChangeValue("NamespaceColor"); SaveColor("NamespaceColor", value, true); DidChangeValue("NamespaceColor"); } } /// Gets or sets the color of a operator keyword. /// The NSColor of the operator keyword. [Export("OperatorKeywordColor")] public NSColor OperatorKeywordColor { get => LoadColor("OperatorKeywordColor", NSColor.SystemPurple); set { WillChangeValue("OperatorKeywordColor"); SaveColor("OperatorKeywordColor", value, true); DidChangeValue("OperatorKeywordColor"); } } /// Gets or sets the color of a conversion keyword. /// The NSColor of the conversion keyword. [Export("ConversionKeywordColor")] public NSColor ConversionKeywordColor { get => LoadColor("ConversionKeywordColor", NSColor.SystemPurple); set { WillChangeValue("ConversionKeywordColor"); SaveColor("ConversionKeywordColor", value, true); DidChangeValue("ConversionKeywordColor"); } } /// Gets or sets the color of a access keyword. /// The NSColor of the access keyword. [Export("AccessKeywordColor")] public NSColor AccessKeywordColor { get => LoadColor("AccessKeywordColor", NSColor.SystemPurple); set { WillChangeValue("AccessKeywordColor"); SaveColor("AccessKeywordColor", value, true); DidChangeValue("AccessKeywordColor"); } } /// Gets or sets the color of a literal keyword. /// The NSColor of the literal keyword. [Export("LiteralKeywordColor")] public NSColor LiteralKeywordColor { get => LoadColor("LiteralKeywordColor", NSColor.SystemPurple); set { WillChangeValue("LiteralKeywordColor"); SaveColor("LiteralKeywordColor", value, true); DidChangeValue("LiteralKeywordColor"); } } /// Gets or sets the color of a contextual keyword. /// The NSColor of the contextual keyword. [Export("ContextualKeywordColor")] public NSColor ContextualKeywordColor { get => LoadColor("ContextualKeywordColor", NSColor.SystemGreen); set { WillChangeValue("ContextualKeywordColor"); SaveColor("ContextualKeywordColor", value, true); DidChangeValue("ContextualKeywordColor"); } } /// Gets or sets the color of a query keyword. /// The NSColor of the query keyword. [Export("QueryKeywordColor")] public NSColor QueryKeywordColor { get => LoadColor("QueryKeywordColor", NSColor.SystemOrange); set { WillChangeValue("QueryKeywordColor"); SaveColor("QueryKeywordColor", value, true); DidChangeValue("QueryKeywordColor"); } } /// Gets or sets the color of a preprocessor directive keyword. /// The NSColor of the preprocessor directive. [Export("PreprocessorDirectiveColor")] public NSColor PreprocessorDirectiveColor { get => LoadColor("PreprocessorDirectiveColor", NSColor.SystemPurple); set { WillChangeValue("PreprocessorDirectiveColor"); SaveColor("PreprocessorDirectiveColor", value, true); DidChangeValue("PreprocessorDirectiveColor"); } } /// Gets or sets the color of a comment. /// The NSColor of the comment. [Export("CommentColor")] public NSColor CommentColor { get => LoadColor("CommentColor", NSColor.SystemGray); set { WillChangeValue("CommentColor"); SaveColor("CommentColor", value, true); DidChangeValue("CommentColor"); } } /// Gets or sets the color of a string literal. /// The NSColor of the string literal. [Export("StringLiteralColor")] public NSColor StringLiteralColor { get => LoadColor("StringLiteralColor", NSColor.SystemOrange); set { WillChangeValue("StringLiteralColor"); SaveColor("StringLiteralColor", value, true); DidChangeValue("StringLiteralColor"); } } #endregion #region Constructors /// /// Initializes a new instance of the class. /// public LanguageDescriptor() { } #endregion #region Public Methods /// Define this instance. public virtual void Define() { // Initialize this.Keywords.Clear(); this.Formats.Clear(); this.Closures.Clear(); this.FormattingCommands.Clear(); // Define the default set of closures this.Closures.Add(new LanguageClosure('(', ')')); this.Closures.Add(new LanguageClosure('[', ']')); this.Closures.Add(new LanguageClosure('<', '>')); this.Closures.Add(new LanguageClosure('{', '}')); this.Closures.Add(new LanguageClosure('"')); } /// Formats the passed in string of text for previewing. /// The string formatted for preview. /// Text. public virtual string FormatForPreview(string text) { return text; } /// /// Resets all of the for this language to their default states /// of unmatched and inactive. /// /// This should only be called ba a . public virtual void ClearFormats() { // Clear the process state of all formats foreach (FormatDescriptor format in Formats) { format.CharIndex = 0; format.Active = false; } } /// /// Converts the given color into a web style hex string in the form #RRBBGG or optionally /// #RRBBGGAA. /// /// The web hex string representing the given color. /// The NSColor to convert. /// /// If set to true with the alpha (transparency) of the color will be included. /// public static string NSColorToHexString(NSColor color, bool withAlpha) { // Break color into pieces color.GetRgba(out nfloat red, out nfloat green, out nfloat blue, out nfloat alpha); // Adjust to byte alpha *= 255; red *= 255; green *= 255; blue *= 255; //With the alpha value? if (withAlpha) { return string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", (int)alpha, (int)red, (int)green, (int)blue); } else { return string.Format("#{0:X2}{1:X2}{2:X2}", (int)red, (int)green, (int)blue); } } /// /// Converts a web formatted hex string in the form #RRGGBB or #RRGGBBAA into a color. /// /// The NSColor represented by the hex string. /// The web formatted hex string in the form #RRGGBB or #RRGGBBAA. public static NSColor NSColorFromHexString(string hexValue) { string colorString = hexValue.Replace("#", ""); float red, green, blue, alpha; // Convert color based on length switch (colorString.Length) { case 3: // #RGB red = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(0, 1)), 16) / 255f; green = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(1, 1)), 16) / 255f; blue = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(2, 1)), 16) / 255f; return NSColor.FromRgba(red, green, blue, 1.0f); case 6: // #RRGGBB red = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f; green = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f; blue = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f; return NSColor.FromRgba(red, green, blue, 1.0f); case 8: // #AARRGGBB alpha = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f; red = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f; green = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f; blue = Convert.ToInt32(colorString.Substring(6, 2), 16) / 255f; return NSColor.FromRgba(red, green, blue, alpha); default: throw new ArgumentOutOfRangeException(string.Format("Invalid color value '{0}'. " + "It should be a hex value of the form #RBG, #RRGGBB or #AARRGGBB", hexValue)); } } /// Loads the requested color from system-wide user defaults. /// The NSColor for the given key or the default value if the key /// cannot be found in the user defaults. /// The user default key for the color. /// The default NSColor value. public NSColor LoadColor(string key, NSColor defaultValue) { // Attempt to read color, add the language ID to make unique string hex = NSUserDefaults.StandardUserDefaults.StringForKey(LanguageIdentifier + key); // Take action based on value if (hex == null) { return defaultValue; } else { return NSColorFromHexString(hex); } } /// /// Saves the given color to the systwm-wide user defaults with the give keyword. /// /// The NSColor to save to the user defaults. /// The user default key to assign the color to. /// If set to true sync changes to preferences. public void SaveColor(string key, NSColor color, bool sync) { // Save to default, add the language ID to make unique NSUserDefaults.StandardUserDefaults.SetString(NSColorToHexString(color, true), LanguageIdentifier + key); if (sync) NSUserDefaults.StandardUserDefaults.Synchronize(); } #endregion }