When intellisense windows pop up in my winforms application I get traces of intellisense prompts. This happens all the time.
The above is a screenshot of my application.
I use the following code to initialise the JS Parser for the editor:
using Alternet.Common.TypeScript;
using Alternet.Syntax;
using Alternet.Syntax.CodeCompletion;
using DevExpress.XtraTreeList.Nodes;
using Excel.FinancialFunctions;
using PrimeThought.QubeXL.Objects;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Linq;
using System.Linq.Expressions;
namespace PrimeThought.QubeXL.Windows.Forms.Scripting
{
class MyJSParser : Alternet.Syntax.Parsers.TypeScript.JavaScriptParser
{
public MyJSParser(ITypeScriptProject project) : base(project)
{
}
public override void ReparseText(bool useThread, int first, int last)
{
SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext());
base.ReparseText(useThread, first, last);
}
public override void CodeCompletion(string text, StringItemInfo[] textData, Point position, bool useThread, CodeCompletionArgs e)
{
SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext());
base.CodeCompletion(text, textData, position, useThread, e);
}
}
public static class ScriptEditHelpers
{
/// <summary>
/// Does parser do async notifications.
/// If true can cause cross threading exceptions in some environments like in Microsoft Excel
/// </summary>
public static bool AsyncNotifyEnabled { get; set; } = true;
/// <summary>
/// Get a parser for our script
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static Alternet.Syntax.Parsers.TypeScript.JavaScriptParser GetJSParser(Dictionary<string, object> values)
{
var javaScriptParser = new MyJSParser(new Alternet.Common.TypeScript.TypeScriptProject());
if (!AsyncNotifyEnabled)
{
javaScriptParser.Options = javaScriptParser.Options & ~Alternet.Syntax.SyntaxOptions.NotifyOnParse;
}
foreach (var kvp in values)
{
AddScriptingObject(javaScriptParser, kvp.Key, kvp.Value);
}
AddScriptingObject(javaScriptParser, "Financial", typeof(Financial));
AddScriptingObject(javaScriptParser, "Lib", typeof(ScriptHelperFunctions));
InitializeParser(javaScriptParser);
return javaScriptParser;
}
/// <summary>
/// Add scripting object if it is not already added
/// </summary>
/// <param name="parser"></param>
/// <param name="name"></param>
/// <param name="value"></param>
static void AddScriptingObject(Alternet.Syntax.Parsers.TypeScript.JavaScriptParser parser, string name, object value)
{
foreach (var item in parser.Repository.Project.HostItemsConfiguration.Items)
{
if (item.Name == name)
{
return;
}
}
if (value is Type type)
{
parser.Repository.Project.HostItemsConfiguration.AddType(name, type);
}
else
{
parser.Repository.Project.HostItemsConfiguration.AddObject(name, value);
}
}
/// <summary>
/// Initialise JS parser
/// </summary>
/// <param name="parser"></param>
static void InitializeParser(Alternet.Syntax.Parsers.TypeScript.JavaScriptParser parser)
{
var incFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"PrimeThought\\PrimeThought.QubeXL.Windows.Forms\\editorinc.ts");
if (!File.Exists(incFilePath))
{
Directory.CreateDirectory(Path.GetDirectoryName(incFilePath));
File.WriteAllText(incFilePath, new StreamReader(typeof(ScriptEditHelpers).Assembly.GetManifestResourceStream("PrimeThought.QubeXL.Windows.Forms.editorInc.ts")).ReadToEnd());
}
parser.Repository.RegisterCodeFiles(new string[] { incFilePath });
}
/// <summary>
/// Set standard menus on Editors
/// </summary>
/// <param name="editor"></param>
/// <param name="filePrompt"></param>
/// <param name="defaultExt"></param>
/// <param name="inserts"></param>
public static void SetEditorMenus(Alternet.Editor.SyntaxEdit editor, string filePrompt, string defaultExt, string[] inserts = null)
{
var ctxmenu = new ContextMenuStrip();
editor.KeyList.Add(Keys.Control | Keys.P, () => new Forms.frmScriptEditor(editor) { Inserts = inserts }.ShowDialog());
ctxmenu.Items.Add("Pop out", Properties.Resources.Forward_16x16, (s, e) => { new Forms.frmScriptEditor(editor) { Inserts = inserts }.ShowDialog(); });
ctxmenu.Items.Add("-");
ctxmenu.Items.Add("Copy", Properties.Resources.Copy_16x16, (s, e) => { editor.Selection.Copy(); });
ctxmenu.Items.Add("Paste", Properties.Resources.Paste_16x16, (s, e) => { editor.Selection.Paste(); });
ctxmenu.Items.Add("Cut", Properties.Resources.Cut_16x16, (s, e) => { editor.Selection.Cut(); });
ctxmenu.Items.Add("-");
ctxmenu.Items.Add("Goto...", Properties.Resources.Forward_16x16, (s, e) => { editor.DisplayGotoLineDialog(editor); }) ;
ctxmenu.Items.Add("Select All", Properties.Resources.SelectAll_16x16, (s, e) => editor.Selection.SelectAll());
ctxmenu.Items.Add(new ToolStripSeparator());
ctxmenu.Items.Add("Save As", Properties.Resources.SaveAs_16x16, (s, e) =>
{
var sfd = new SaveFileDialog() { Title = "Save " + filePrompt, DefaultExt = defaultExt, Filter = filePrompt + " Files (*" + defaultExt + ")|*." + defaultExt + "|All files (*.*)|*.*" };
if (sfd.ShowDialog() == DialogResult.OK)
{
editor.SaveFile(sfd.FileName, Encoding.ASCII);
}
});
ctxmenu.Items.Add("Open", Properties.Resources.Open_16x16, (s, e) =>
{
var ofd = new OpenFileDialog() { Title = "Open " + filePrompt, DefaultExt = defaultExt, Filter = filePrompt + " Files (*" + defaultExt + ")|*." + defaultExt + "|All files (*.*)|*.*" };
if (ofd.ShowDialog() == DialogResult.OK)
{
editor.LoadFile(ofd.FileName);
}
});
//ctxmenu.Items.Add("-");
//ctxmenu.Items.Add("Definition", Properties.Resources.Forward_16x16, (s, e) =>
//{
// Alternet.Common.RangeList lst = new Alternet.Common.RangeList();
// editor.FindImplementations(editor., lst);
// if (lst.Count > 0)
// {
// editor.Position = lst[0].StartPoint;
// }
//});
editor.ContextMenuStrip = ctxmenu;
//editor.ApplyTheme(Alternet.Editor.DarkVisualTheme.Instance);//DCD
}
/// <summary>
/// Set editor completions given set of objects
/// </summary>
/// <param name="editor"></param>
/// <param name="model"></param>
/// <param name="thisObject"></param>
/// <param name="thisTable"></param>
/// <param name="row"></param>
public static void SetEditorCompletions(Alternet.Editor.SyntaxEdit editor, Model model, QubeXLObject thisObject, Table thisTable, Row row)
{
editor.NeedCodeCompletion += (s, e) =>
{
if (e.KeyChar == '[')
{
var lm = new ListMembers();
e.CompletionType = Alternet.Syntax.CodeCompletionType.ListMembers;
e.Provider = lm;
var pos = editor.Lines.TextPointToAbsolutePosition(e.DisplayPosition);
var code = editor.Text.Substring(0, pos);
if (model != null && code.EndsWith("Model.Objects.Item["))
{
var lst = model.Objects.Select(o => o.Name).ToList();
lst.Sort();
foreach (var n in lst)
{
Add(n);
}
}
else if (model != null && code.EndsWith("Model.Objects.Table["))
{
var lst = model.Tables.Select(t => t.FullName()).ToList();
lst.Sort();
foreach (var n in lst)
{
Add(n);
}
}
else if (model != null && code.EndsWith("Model.Objects.Column["))
{
foreach (var ob in model.Tables)
{
Add(ob.FullName());
}
}
else if (row != null && code.EndsWith("Row.Item["))
{
var lst = row.Table.Columns.Values.Select(c => c.Name).ToList();
lst.Sort();
foreach (var n in lst)
{
Add(n);
}
}
else if (row != null && code.EndsWith("Row.Tables["))
{
foreach (var table in row.Tables)
{
Add(table.Name);
}
}
else if (row != null && code.EndsWith("Row.Parent.Tables["))
{
foreach (var table in row.Parent.Tables)
{
Add(table.Name);
}
}
else if (row != null && code.EndsWith("Row.Parent.Children["))
{
foreach (var ob in row.Parent.Children)
{
Add(ob.Name);
}
}
else if (row != null && code.EndsWith("Row.Parent.Parent.Children["))
{
if (row.Parent.Parent != null)
{
foreach (var ob in row.Parent.Parent.Children)
{
Add(ob.Name);
}
}
}
else if (thisObject != null && code.EndsWith("thisObject.Parent.Children["))
{
if (thisObject.Parent != null)
{
foreach (var ob in thisObject.Parent.Children)
{
Add(ob.Name);
}
}
}
else if (thisObject != null && code.EndsWith("thisObject.Tables["))
{
foreach (var ob in thisObject.Tables)
{
Add(ob.Name);
}
}
else if (thisTable != null && code.EndsWith("thisTable.Columns["))
{
foreach (var col in thisTable.Columns)
{
Add(col.Name);
}
}
else if (thisTable != null && code.EndsWith("thisTable.Parent.Children["))
{
foreach (var ob in thisTable.Parent.Children)
{
Add(ob.Name);
}
}
else if (thisTable != null && code.EndsWith("thisTable.Parent.Tables["))
{
foreach (var ob in thisTable.Parent.Tables)
{
Add(ob.Name);
}
}
if (lm.Count > 0)
{
e.NeedShow = true;
}
void Add(string text)
{
lm.AddListMember(new ListMember() { InsertText = $"'{text}'", DisplayText = $"'{text}'", DataType = $"{text}" });
}
}
};
}
public static void AddSnippet(Alternet.Editor.SyntaxEdit tb, string name, string text)
{
if (tb.ContextMenuStrip == null)
{
tb.ContextMenuStrip = new ContextMenuStrip();
}
var ctxmenu = tb.ContextMenuStrip;
ToolStripMenuItem snItem;
if (!ctxmenu.Items.ContainsKey("Snippets"))
{
ctxmenu.Items.Add(new ToolStripSeparator());
snItem = ctxmenu.Items.Add("Snippets") as ToolStripMenuItem;
}
else
{
snItem = ctxmenu.Items["Snippets"] as ToolStripMenuItem;
}
snItem.DropDownItems.Add(name, null, (s, e) => tb.Selection.SelectedText = text);
}
/// <summary>
/// Enable code drag drop from structure tree
/// </summary>
/// <param name="edt"></param>
/// <param name="editItem"></param>
public static void EnableCodeDragDrop(Alternet.Editor.SyntaxEdit edt, IDependencyItem editItem)
{
edt.Tag = editItem;
edt.DragEnter += (s, e) => e.Effect = DragDropEffects.All;
edt.DragOver += (s, e) =>
{
var edit = s as Alternet.Editor.SyntaxEdit;
var cp = edit.PointToClient(new Point(e.X, e.Y));
var insertPoint = edit.ScreenToDisplay(cp.X, cp.Y);
edit.MoveToLine(insertPoint.Y);
edit.MoveToChar(insertPoint.X);
e.Effect = DragDropEffects.All;
};
edt.DragDrop += (s, e) =>
{
var edit = s as Alternet.Editor.SyntaxEdit;
var cp = edit.PointToClient(new Point(e.X, e.Y));
var insertPoint = edit.ScreenToDisplay(cp.X, cp.Y);
edit.MoveToLine(insertPoint.Y);
edit.MoveToChar(insertPoint.X);
var tNode = e.Data.GetData("DevExpress.XtraTreeList.Nodes.TreeListNode", true) as TreeListNode;
if (tNode != null)
{
var obj = tNode.GetValue(0) as IDependencyItem;
var refMgr = new ReferenceManager(edit.Tag as IDependencyItem);
edit.InsertBlock(refMgr.CodeReference(obj));
edit.Focus();
}
};
}
/// <summary>
/// JSEditor manager to allow just one instance of editor per dialog to avoid issues with the Alternet editor
/// </summary>
public class JSSyntaxEditor
{
Alternet.Editor.SyntaxEdit editor = new Alternet.Editor.SyntaxEdit();
public Alternet.Editor.SyntaxEdit Editor => editor;
public JSSyntaxEditor(Dictionary<string, object> values)
{
var psr = ScriptEditHelpers.GetJSParser(values);
editor.Dock = DockStyle.Fill;
editor.Lexer = psr;
editor.HighlightReferences = true;
ScriptEditHelpers.SetEditorMenus(editor, "Javascript files", "js");
}
/// <summary>
/// Get Editor text
/// </summary>
/// <returns></returns>
public string GetText() => editor.Text;
Action<string> saveLastValueFun = null;
/// <summary>
/// Set editor text
/// </summary>
/// <param name="text"></param>
/// <param name="saveLastValueFun"></param>
public void SetText(string text, Action<string> saveLastValueFun)
{
this.saveLastValueFun?.Invoke(editor.Text);
this.saveLastValueFun = saveLastValueFun;
editor.Text = text;
}
/// <summary>
/// Save edit text changes if any
/// </summary>
public void Save()
{
if (saveLastValueFun != null)
{
saveLastValueFun(editor.Text);
}
}
}
}
}