#region Imported Libraries
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Microsoft.Scripting.Hosting;
using System.IO;
using System.Windows.Input;
using IronRuby;
using Microsoft.Scripting;
using System.Windows;
using System.Threading;
using System.Reflection;
#endregion
#region Namespace Declaration
namespace Org.TechA.Wpf.UserControls
{
internal sealed class IronRubyConsolePresenter
{
#region Private Members
private readonly IronRubyConsoleModel _model;
private readonly IronRubyConsole _view;
#endregion
#region Constructor
///
/// Default Constructor.
///
///
/// The View.
///
internal IronRubyConsolePresenter(UserControl view)
{
//set the model and the view
_view = (IronRubyConsole)view;
_model = SetupModel();
//set the default scope vars
SetDefaultScopeVariables(_model.Scopes[0]);
//setup the view
InitializeView();
//subscribe to all the view events
WireupEvents();
}
#endregion
#region Accessor Mutators
///
/// The View.
///
internal IronRubyConsole View
{
get { return _view; }
}
///
/// The Model.
///
internal IronRubyConsoleModel Model
{
get { return _model; }
}
#endregion
#region Event Subscriptions
///
/// Wireup all the views events.
///
internal void WireupEvents()
{
_view.txtUserCodeInput.KeyDown +=
new KeyEventHandler(txtUserCodeInput_KeyDown);
_view.mitmPrintState.Click +=
new RoutedEventHandler(mitmPrintState_Click);
_view.mitmAbout.Click +=
new RoutedEventHandler(mitmAbout_Click);
_view.mitmAddScope.Click +=
new RoutedEventHandler(mitmAddScope_Click);
_view.mitmClearScreen.Click +=
new RoutedEventHandler(mitmClearScreen_Click);
_view.VariablesAdded +=
new Action>(_view_VariablesAdded);
}
void _view_VariablesAdded(Dictionary obj)
{
foreach (var key in obj.Keys)
{
_model.Scopes[0].SetVariable(key, obj[key]);
}
}
///
/// Clears the IronRuby output screen.
///
///
/// The menu item.
///
///
/// The routed event arguments.
///
void mitmClearScreen_Click(object sender, RoutedEventArgs e)
{
_view.txtIronRubyOutput.Clear();
}
///
/// Menu item click event for added a scope.
///
///
/// The menu item.
///
///
/// The Routed event args.
///
void mitmAddScope_Click(object sender, RoutedEventArgs e)
{
}
///
/// About window menu item
/// click event hanlder.
///
///
/// The Menu Item.
///
///
/// The routed event arguments.
///
void mitmAbout_Click(object sender, RoutedEventArgs e)
{
AboutDialog dlg = new AboutDialog();
dlg.ShowDialog();
}
///
///
///
///
///
void mitmPrintState_Click(object sender, RoutedEventArgs e)
{
var scope = _model.Scopes[0];
var source =
scope.Engine
.CreateScriptSourceFromString("puts 'PRINTING VARIABLES FROM DEFAULT SCOPE';" +
"puts '************************************************'");
var result = source.Execute(scope);
foreach(var varName in scope.GetVariableNames())
{
//get the variable by name
var variable = scope.GetVariable(varName);
//get the script source from string which will
//simply print the name of the variable
source = scope.Engine
.CreateScriptSourceFromString("puts 'Variable Name is [" +
varName + "] and value is [" + variable + "]'");
result = source.Execute(scope);
_model.Writer.WriteLine(FormatResult(result));
}
source =
scope.Engine
.CreateScriptSourceFromString("puts; puts '************************************************'");
result = source.Execute(scope);
}
#endregion
#region Private Worker Methods
///
/// Setup of the View.
///
private void InitializeView()
{
FocusHelper.Focus(_view.txtUserCodeInput);
_view.txtUserCodeInput.SelectionStart = 1;
}
///
/// Setup the IronRuby Runtime, Engine
/// and create a default scope.
///
private IronRubyConsoleModel SetupModel()
{
var runtime = Ruby.CreateRuntime();
// give ruby access to all our assemblies
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
runtime.LoadAssembly(assembly);
}
var writer = SetupIO(runtime);
var engine = runtime.GetEngine("Ruby");
var default_scope = engine.CreateScope();
var model = new IronRubyConsoleModel(writer, engine);
model.Scopes.Add(default_scope);
return model;
}
///
/// Setup the IO classes that will have
/// the IronRuby runtime have its IO
/// redirected to.
///
///
/// The IronRuby runtime.
///
///
/// The Texwriter that the IronRuby
/// runtime will write to.
///
private TextWriter SetupIO(ScriptRuntime runtime)
{
var writer = new TextBoxWriter(_view.txtIronRubyOutput);
var stream = new TextWriterStream(writer);
runtime.IO.SetOutput(stream, writer);
runtime.IO.SetErrorOutput(stream, writer);
return writer;
}
///
/// Formats the result of the of
/// execution of code by a ScriptSource.
///
///
/// The result of running a given script.
///
///
/// Returns the formatted result from
/// running a given script.
///
private string FormatResult(object obj)
{
var prefix = "=> ";
var result = default(string);
if (obj == null)
result = "nil";
else
result = obj.ToString();
return prefix + result;
}
///
/// Runs the code typed in the console window.
///
///
/// The code string.
///
private void RunCode(string theCode)
{
_model.Writer.WriteLine(">>> " + theCode);
try
{
var scriptSource = _model.Engine.
CreateScriptSourceFromString(theCode,
SourceCodeKind.Statements);
var result = scriptSource.Execute(_model.Scopes[0]);
_model.Writer.WriteLine(FormatResult(result));
}
catch (Exception e)
{
_model.Writer.WriteLine(e.Message);
}
}
///
/// Sets any variables required
/// for the default scope.
///
///
/// The default scope.
///
private void SetDefaultScopeVariables(ScriptScope scope)
{
scope.SetVariable("scopename", "Default");
scope.SetVariable("windowcount", Application.Current.Windows.Count);
}
#endregion
#region Event Delegates
///
/// The user entry code textbox
/// key down event handler.
///
///
/// The code text box.
///
///
/// The keys event args.
///
void txtUserCodeInput_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
RunCode(this._view.txtUserCodeInput.Text);
e.Handled = true;
this._view.txtUserCodeInput.Clear();
}
}
#endregion
}
}
#endregion