Skip to content

Instantly share code, notes, and snippets.

@julesx
Created March 12, 2015 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save julesx/f5624c6885b5e9f62514 to your computer and use it in GitHub Desktop.
Save julesx/f5624c6885b5e9f62514 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using Gizmox.WebGUI.Forms;
using Microsoft.ClearScript;
using Microsoft.ClearScript.V8;
namespace ScriptingDemo4
{
public partial class itScriptingFrm : Form
{
#region Protected Vars
protected ScriptEngine ScriptEngine;
protected string EventCount { get { return _scriptEvents.Count.ToString(); } }
protected string MethodCount { get { return _scriptMethods.Count.ToString(); } }
#endregion
#region Private Vars
private readonly string _scriptPath;
private readonly Dictionary<string, List<string>> _scriptEvents = new Dictionary<string, List<string>>();
private readonly List<string> _scriptMethods = new List<string>();
private readonly List<Control> _controls = new List<Control>();
private Dictionary<Control, List<ClearScriptEvent>> _assignedEvents = new Dictionary<Control, List<ClearScriptEvent>>();
private bool _hasLoaded;
#endregion
#region C'Tor
public itScriptingFrm()
{
InitializeComponent();
_scriptPath = @"C:\tmp\scripts\" + GetType().Name + ".js";
Load += itScriptingFrm_Load;
}
#endregion
#region Events
void itScriptingFrm_Load(object sender, EventArgs e)
{
try
{
ScriptEngine = new V8ScriptEngine();
LoadScriptingEngine();
_hasLoaded = true;
if (_scriptMethods.Contains("MainForm_Load"))
ScriptEngine.Script["MainForm_Load"]();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
#region Protected Methods
protected void LoadScriptingEngine()
{
GetMethods();//parses script file for all methods
GetEvents();//parses methods for all events
//execute script so we can call its methods through the script engine
ScriptEngine.Execute(System.IO.File.ReadAllText(_scriptPath));
ScriptEngine.Execute(System.IO.File.ReadAllText(@"c:\tmp\scripts\GlobalScript.js"));
//find all controls on the form, and attach the appropriate events
AttachEvents();
if (_hasLoaded) return;
AddHostTypes();//add any and all types a script would want to use
AddHostObjects();//add any and all objects a script would want to use
}
#endregion
#region Private Methods
private void AddHostObjects()
{
ScriptEngine.AddHostObject("MainForm", this);
ScriptEngine.AddHostObject("Gbl", new Globals(ScriptEngine));
foreach (var control in _controls)
ScriptEngine.AddHostObject(control.Name, control);
}
private void AddHostTypes()
{
ScriptEngine.AddHostType("Button", typeof(Button));
}
private void GetMethods()
{
_scriptMethods.Clear();
var script = System.IO.File.ReadAllLines(_scriptPath);
foreach (var line in script.Where(x => x.StartsWith("function")))
{
var method = line.Replace("function ", "");
method = method.Substring(0, method.IndexOf("("));
_scriptMethods.Add(method);
}
}
private void GetEvents()
{
_scriptEvents.Clear();
foreach (var method in _scriptMethods.Where(x => x.Contains("_")))
{
var split = method.Split('_');
var control = Controls.Find(split[0], true).FirstOrDefault();
if (control != null)
ScriptEngine.AddHostObject(split[0], control);
var key = split[0];
var value = split[1];
if (!_scriptEvents.ContainsKey(key))
_scriptEvents.Add(key, new List<string>());
_scriptEvents[key].Add(value);
}
}
private void RemoveEvents(Control control)
{
foreach (var clearScriptEvent in _assignedEvents[control])
{
var controlEvent = control.GetType().GetEvent(clearScriptEvent.Event);
controlEvent.RemoveEventHandler(control, clearScriptEvent.EventHandler);
}
_assignedEvents[control].Clear();
}
private void AttachEvent(Control control, string @event)
{
var controlEvent = control.GetType().GetEvent(@event);
if (controlEvent == null)
throw new Exception(@event + " not supported");
Action<object, EventArgs> myDelegate = (sender, e) =>
{
ScriptEngine.Script[control.Name + "_" + @event](sender, e);
};
EventHandler eventHandler = myDelegate.Invoke;
_assignedEvents[control].Add(new ClearScriptEvent(@event, eventHandler));
controlEvent.AddEventHandler(control, eventHandler);
}
private void AttachEvents(Control.ControlCollection controlCollection = null)
{
_controls.Clear();
var controls = controlCollection ?? Controls;
foreach (Control control in controls)
{
var controlName = control.Name;
_controls.Add(control);
if (_assignedEvents.ContainsKey(control))
RemoveEvents(control);
else
_assignedEvents.Add(control, new List<ClearScriptEvent>());
if (control.GetType() == typeof (ControlCollection))
{
AttachEvents();
}
else if (_scriptEvents.ContainsKey(controlName))
{
foreach (var @event in _scriptEvents[controlName])
AttachEvent(control, @event);
}
}
}
#endregion
private class ClearScriptEvent
{
public EventHandler EventHandler;
public string Event;
public ClearScriptEvent(string @event, EventHandler eventHandler)
{
Event = @event;
EventHandler = eventHandler;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment