Browse Source

Change ScriptingConsoleOutputStream to call console text editor on UI thread.

pull/1/head
mrward 15 years ago
parent
commit
ecee05b53e
  1. 10
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs
  2. 5
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsoleHost.cs
  3. 10
      src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyConsole.cs
  4. 3
      src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyConsoleHost.cs
  5. 16
      src/AddIns/BackendBindings/Scripting/Project/Src/ScriptingConsoleOutputStream.cs
  6. 59
      src/AddIns/BackendBindings/Scripting/Test/Console/ScriptingConsoleOutputStreamTests.cs

10
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs

@ -12,17 +12,27 @@ namespace ICSharpCode.PythonBinding
{ {
public class PythonConsole : ThreadSafeScriptingConsole, IConsole, IMemberProvider public class PythonConsole : ThreadSafeScriptingConsole, IConsole, IMemberProvider
{ {
IScriptingConsoleTextEditor textEditor;
IControlDispatcher dispatcher;
public PythonConsole(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher) public PythonConsole(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher)
: this(new ScriptingConsole(textEditor), dispatcher) : this(new ScriptingConsole(textEditor), dispatcher)
{ {
this.textEditor = textEditor;
} }
PythonConsole(ScriptingConsole console, IControlDispatcher dispatcher) PythonConsole(ScriptingConsole console, IControlDispatcher dispatcher)
: base(console, dispatcher) : base(console, dispatcher)
{ {
this.dispatcher = dispatcher;
console.MemberProvider = this; console.MemberProvider = this;
} }
public ScriptingConsoleOutputStream CreateOutputStream()
{
return new ScriptingConsoleOutputStream(textEditor, dispatcher);
}
public CommandLine CommandLine { get; set; } public CommandLine CommandLine { get; set; }
public TextWriter Output { public TextWriter Output {

5
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsoleHost.cs

@ -16,12 +16,10 @@ namespace ICSharpCode.PythonBinding
public class PythonConsoleHost : ConsoleHost, IScriptingConsoleHost public class PythonConsoleHost : ConsoleHost, IScriptingConsoleHost
{ {
Thread thread; Thread thread;
IScriptingConsoleTextEditor textEditor;
PythonConsole pythonConsole; PythonConsole pythonConsole;
public PythonConsoleHost(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher) public PythonConsoleHost(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher)
{ {
this.textEditor = textEditor;
pythonConsole = new PythonConsole(textEditor, dispatcher); pythonConsole = new PythonConsole(textEditor, dispatcher);
} }
@ -71,7 +69,8 @@ namespace ICSharpCode.PythonBinding
/// </remarks> /// </remarks>
protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options) protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options)
{ {
SetOutput(new ScriptingConsoleOutputStream(textEditor)); ScriptingConsoleOutputStream stream = pythonConsole.CreateOutputStream();
SetOutput(stream);
pythonConsole.CommandLine = commandLine; pythonConsole.CommandLine = commandLine;
return pythonConsole; return pythonConsole;
} }

10
src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyConsole.cs

@ -12,17 +12,27 @@ namespace ICSharpCode.RubyBinding
{ {
public class RubyConsole : ThreadSafeScriptingConsole, IConsole, IMemberProvider public class RubyConsole : ThreadSafeScriptingConsole, IConsole, IMemberProvider
{ {
IScriptingConsoleTextEditor textEditor;
IControlDispatcher dispatcher;
public RubyConsole(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher) public RubyConsole(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher)
: this(new ScriptingConsole(textEditor), dispatcher) : this(new ScriptingConsole(textEditor), dispatcher)
{ {
this.textEditor = textEditor;
} }
RubyConsole(ScriptingConsole console, IControlDispatcher dispatcher) RubyConsole(ScriptingConsole console, IControlDispatcher dispatcher)
: base(console, dispatcher) : base(console, dispatcher)
{ {
this.dispatcher = dispatcher;
console.MemberProvider = this; console.MemberProvider = this;
} }
public ScriptingConsoleOutputStream CreateOutputStream()
{
return new ScriptingConsoleOutputStream(textEditor, dispatcher);
}
public CommandLine CommandLine { get; set; } public CommandLine CommandLine { get; set; }
public TextWriter Output { public TextWriter Output {

3
src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyConsoleHost.cs

@ -87,7 +87,8 @@ namespace ICSharpCode.RubyBinding
/// </remarks> /// </remarks>
protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options) protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options)
{ {
SetOutput(new ScriptingConsoleOutputStream(textEditor)); ScriptingConsoleOutputStream stream = rubyConsole.CreateOutputStream();
SetOutput(stream);
rubyConsole.CommandLine = commandLine; rubyConsole.CommandLine = commandLine;
return rubyConsole; return rubyConsole;
} }

16
src/AddIns/BackendBindings/Scripting/Project/Src/ScriptingConsoleOutputStream.cs

@ -10,10 +10,12 @@ namespace ICSharpCode.Scripting
public class ScriptingConsoleOutputStream : Stream public class ScriptingConsoleOutputStream : Stream
{ {
IScriptingConsoleTextEditor textEditor; IScriptingConsoleTextEditor textEditor;
IControlDispatcher dispatcher;
public ScriptingConsoleOutputStream(IScriptingConsoleTextEditor textEditor) public ScriptingConsoleOutputStream(IScriptingConsoleTextEditor textEditor, IControlDispatcher dispatcher)
{ {
this.textEditor = textEditor; this.textEditor = textEditor;
this.dispatcher = dispatcher;
} }
public override bool CanRead { public override bool CanRead {
@ -61,7 +63,17 @@ namespace ICSharpCode.Scripting
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
string text = UTF8Encoding.UTF8.GetString(buffer, offset, count); string text = UTF8Encoding.UTF8.GetString(buffer, offset, count);
textEditor.Write(text); ThreadSafeTextEditorWrite(text);
}
void ThreadSafeTextEditorWrite(string text)
{
if (dispatcher.CheckAccess()) {
textEditor.Write(text);
} else {
Action<string> action = ThreadSafeTextEditorWrite;
dispatcher.Invoke(action, text);
}
} }
} }
} }

59
src/AddIns/BackendBindings/Scripting/Test/Console/ScriptingConsoleOutputStreamTests.cs

@ -12,54 +12,87 @@ using NUnit.Framework;
namespace ICSharpCode.Scripting.Tests.Console namespace ICSharpCode.Scripting.Tests.Console
{ {
[TestFixture] [TestFixture]
public class ScriptingConsoleOutputStreamTestFixture public class ScriptingConsoleOutputStreamTests
{ {
ScriptingConsoleOutputStream stream; ScriptingConsoleOutputStream stream;
FakeConsoleTextEditor textEditor; FakeConsoleTextEditor textEditor;
FakeControlDispatcher dispatcher;
[TestFixtureSetUp] [SetUp]
public void SetUpFixture() public void Init()
{ {
textEditor = new FakeConsoleTextEditor(); textEditor = new FakeConsoleTextEditor();
stream = new ScriptingConsoleOutputStream(textEditor); dispatcher = new FakeControlDispatcher();
dispatcher.CheckAccessReturnValue = true;
stream = new ScriptingConsoleOutputStream(textEditor, dispatcher);
} }
[Test] [Test]
public void CanReadIsFalse() public void CanRead_NewInstance_ReturnsFalse()
{ {
Assert.IsFalse(stream.CanRead); Assert.IsFalse(stream.CanRead);
} }
[Test] [Test]
public void CanSeekIsFalse() public void CanSeek_NewInstance_ReturnsFalse()
{ {
Assert.IsFalse(stream.CanSeek); Assert.IsFalse(stream.CanSeek);
} }
[Test] [Test]
public void CanWriteIsTrue() public void CanWrite_NewInstance_ReturnsTrue()
{ {
Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanWrite);
} }
[Test] [Test]
public void WriteAddsTextToTextEditor() public void Write_UTF8ByteArrayPassed_AddsTextToTextEditor()
{ {
textEditor.Text = String.Empty;
byte[] bytes = UTF8Encoding.UTF8.GetBytes("test"); byte[] bytes = UTF8Encoding.UTF8.GetBytes("test");
stream.Write(bytes, 0, bytes.Length); stream.Write(bytes, 0, bytes.Length);
Assert.AreEqual("test", textEditor.Text); string text = textEditor.TextPassedToWrite;
string expectedText = "test";
Assert.AreEqual(expectedText, text);
} }
[Test] [Test]
public void OffsetAndLengthUsedInWriteMethod() public void Write_UTF8ByteArrayPassed_OffsetAndLengthUsedInWriteMethod()
{ {
textEditor.Text = String.Empty; textEditor.Text = String.Empty;
byte[] bytes = UTF8Encoding.UTF8.GetBytes("0output1"); byte[] bytes = UTF8Encoding.UTF8.GetBytes("0output1");
stream.Write(bytes, 1, bytes.Length - 2); stream.Write(bytes, 1, bytes.Length - 2);
Assert.AreEqual("output", textEditor.Text); string text = textEditor.TextPassedToWrite;
} string expectedText = "output";
Assert.AreEqual(expectedText, text);
}
[Test]
public void Write_DispatcherCheckAccessReturnsFalse_WriteMethodIsInvoked()
{
dispatcher.CheckAccessReturnValue = false;
byte[] bytes = UTF8Encoding.UTF8.GetBytes("test");
stream.Write(bytes, 0, bytes.Length);
Assert.IsNotNull(dispatcher.MethodInvoked);
}
[Test]
public void Write_DispatcherCheckAccessReturnsFalse_WriteMethodIsInvokedWithTextAsArgument()
{
dispatcher.CheckAccessReturnValue = false;
byte[] bytes = UTF8Encoding.UTF8.GetBytes("test");
stream.Write(bytes, 0, bytes.Length);
object[] expectedArgs = new object[] { "test" };
Assert.AreEqual(expectedArgs, dispatcher.MethodInvokedArgs);
}
} }
} }

Loading…
Cancel
Save