diff --git a/SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs b/SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs
similarity index 67%
rename from SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs
rename to SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs
index 1f92811e..1d7a41ca 100644
--- a/SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs
+++ b/SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs
@@ -13,21 +13,34 @@ using SafeExamBrowser.Core.I18n;
namespace SafeExamBrowser.Core.UnitTests
{
[TestClass]
- public class StringsTests
+ public class TextTests
{
+ [TestMethod]
+ public void MustNeverBeNull()
+ {
+ Assert.IsNotNull(Text.Instance);
+ }
+
[TestMethod]
public void MustNeverReturnNull()
{
- var text = Strings.Get((Key) (-1));
+ var text = Text.Instance.Get((Key) (-1));
Assert.IsNotNull(text);
}
+ [TestMethod]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void MustNotAllowBeingNull()
+ {
+ Text.Instance = null;
+ }
+
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MustNotAllowNullResource()
{
- Strings.Initialize(null);
+ new Text(null);
}
}
}
diff --git a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
index ee138656..be1618ea 100644
--- a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
+++ b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj
@@ -48,7 +48,7 @@
-
+
diff --git a/SafeExamBrowser.Core/Contracts/IStringResource.cs b/SafeExamBrowser.Core/Contracts/ITextResource.cs
similarity index 84%
rename from SafeExamBrowser.Core/Contracts/IStringResource.cs
rename to SafeExamBrowser.Core/Contracts/ITextResource.cs
index e9884293..d136df42 100644
--- a/SafeExamBrowser.Core/Contracts/IStringResource.cs
+++ b/SafeExamBrowser.Core/Contracts/ITextResource.cs
@@ -11,8 +11,8 @@ using SafeExamBrowser.Core.I18n;
namespace SafeExamBrowser.Core.Contracts
{
- public interface IStringResource
+ public interface ITextResource
{
- IDictionary LoadStrings();
+ IDictionary LoadText();
}
}
diff --git a/SafeExamBrowser.Core/I18n/Key.cs b/SafeExamBrowser.Core/I18n/Key.cs
index 29624617..2a21e2bc 100644
--- a/SafeExamBrowser.Core/I18n/Key.cs
+++ b/SafeExamBrowser.Core/I18n/Key.cs
@@ -10,6 +10,7 @@ namespace SafeExamBrowser.Core.I18n
{
public enum Key
{
+ MessageBox_FatalErrorTitle,
MessageBox_SingleInstance,
MessageBox_SingleInstanceTitle
}
diff --git a/SafeExamBrowser.Core/I18n/NullTextResource.cs b/SafeExamBrowser.Core/I18n/NullTextResource.cs
new file mode 100644
index 00000000..29d64b3f
--- /dev/null
+++ b/SafeExamBrowser.Core/I18n/NullTextResource.cs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System.Collections.Generic;
+using SafeExamBrowser.Core.Contracts;
+
+namespace SafeExamBrowser.Core.I18n
+{
+ class NullTextResource : ITextResource
+ {
+ public IDictionary LoadText()
+ {
+ return new Dictionary();
+ }
+ }
+}
diff --git a/SafeExamBrowser.Core/I18n/Strings.cs b/SafeExamBrowser.Core/I18n/Text.cs
similarity index 53%
rename from SafeExamBrowser.Core/I18n/Strings.cs
rename to SafeExamBrowser.Core/I18n/Text.cs
index 543b6801..bec437c4 100644
--- a/SafeExamBrowser.Core/I18n/Strings.cs
+++ b/SafeExamBrowser.Core/I18n/Text.cs
@@ -12,21 +12,42 @@ using SafeExamBrowser.Core.Contracts;
namespace SafeExamBrowser.Core.I18n
{
- public static class Strings
+ public class Text
{
- private static IDictionary cache = new Dictionary();
+ private static Text instance;
+ private static readonly object @lock = new object();
- public static void Initialize(IStringResource resource)
+ private IDictionary cache = new Dictionary();
+
+ public Text(ITextResource resource)
{
if (resource == null)
{
throw new ArgumentNullException(nameof(resource));
}
- cache = resource.LoadStrings();
+ cache = resource.LoadText();
}
- public static string Get(Key key)
+ public static Text Instance
+ {
+ get
+ {
+ lock (@lock)
+ {
+ return instance ?? new Text(new NullTextResource());
+ }
+ }
+ set
+ {
+ lock (@lock)
+ {
+ instance = value ?? throw new ArgumentNullException(nameof(value));
+ }
+ }
+ }
+
+ public string Get(Key key)
{
return cache.ContainsKey(key) ? cache[key] : $"Could not find string for key '{key}'!";
}
diff --git a/SafeExamBrowser.Core/I18n/Text.xml b/SafeExamBrowser.Core/I18n/Text.xml
index 5c279b7a..10eec81e 100644
--- a/SafeExamBrowser.Core/I18n/Text.xml
+++ b/SafeExamBrowser.Core/I18n/Text.xml
@@ -1,5 +1,6 @@
+ Fatal Error
You can only run one instance of SEB at a time.
Startup Not Allowed
\ No newline at end of file
diff --git a/SafeExamBrowser.Core/I18n/XmlTextResource.cs b/SafeExamBrowser.Core/I18n/XmlTextResource.cs
new file mode 100644
index 00000000..72145520
--- /dev/null
+++ b/SafeExamBrowser.Core/I18n/XmlTextResource.cs
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Xml.Linq;
+using SafeExamBrowser.Core.Contracts;
+
+namespace SafeExamBrowser.Core.I18n
+{
+ public class XmlTextResource : ITextResource
+ {
+ public IDictionary LoadText()
+ {
+ var assembly = Assembly.GetAssembly(typeof(XmlTextResource)).Location;
+ var path = Path.GetDirectoryName(assembly) + $@"\{nameof(I18n)}\Text.xml";
+ var xml = XDocument.Load(path);
+ var text = new Dictionary();
+
+ foreach (var definition in xml.Root.Descendants())
+ {
+ if (Enum.TryParse(definition.Name.LocalName, out Key key))
+ {
+ text[key] = definition.Value;
+ }
+ }
+
+ return text;
+ }
+ }
+}
diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
index 233dc534..cade94a3 100644
--- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
+++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj
@@ -40,14 +40,18 @@
-
+
-
+
+
+
-
+
+ Always
+
\ No newline at end of file
diff --git a/SafeExamBrowser/App.cs b/SafeExamBrowser/App.cs
index 63b85973..647238df 100644
--- a/SafeExamBrowser/App.cs
+++ b/SafeExamBrowser/App.cs
@@ -10,7 +10,6 @@ using System;
using System.Threading;
using System.Windows;
using SafeExamBrowser.Core.I18n;
-using SafeExamBrowser.UserInterface;
namespace SafeExamBrowser
{
@@ -21,22 +20,36 @@ namespace SafeExamBrowser
[STAThread]
public static void Main()
{
- if (mutex.WaitOne(TimeSpan.Zero, true))
+ try
{
- StartApplication();
+ var compositionRoot = new CompositionRoot();
+
+ compositionRoot.InitializeGlobalModules();
+ compositionRoot.BuildObjectGraph();
+
+ StartApplication(compositionRoot.Taskbar);
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show(e.Message + "\n\n" + e.StackTrace, Text.Instance.Get(Key.MessageBox_FatalErrorTitle));
+ }
+ }
+
+ private static void StartApplication(Window taskbar)
+ {
+ if (NoInstanceRunning())
+ {
+ new App().Run(taskbar);
}
else
{
- MessageBox.Show(Strings.Get(Key.MessageBox_SingleInstance), Strings.Get(Key.MessageBox_SingleInstanceTitle));
+ MessageBox.Show(Text.Instance.Get(Key.MessageBox_SingleInstance), Text.Instance.Get(Key.MessageBox_SingleInstanceTitle));
}
}
- private static void StartApplication()
+ private static bool NoInstanceRunning()
{
- var app = new App();
- var taskbar = new Taskbar();
-
- app.Run(taskbar);
+ return mutex.WaitOne(TimeSpan.Zero, true);
}
}
}
diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs
new file mode 100644
index 00000000..97a3b6ff
--- /dev/null
+++ b/SafeExamBrowser/CompositionRoot.cs
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System.Windows;
+using SafeExamBrowser.Core.I18n;
+using SafeExamBrowser.UserInterface;
+
+namespace SafeExamBrowser
+{
+ class CompositionRoot
+ {
+ public Window Taskbar { get; private set; }
+
+ public void InitializeGlobalModules()
+ {
+ Text.Instance = new Text(new XmlTextResource());
+ }
+
+ public void BuildObjectGraph()
+ {
+ Taskbar = new Taskbar();
+ }
+ }
+}
diff --git a/SafeExamBrowser/SafeExamBrowser.csproj b/SafeExamBrowser/SafeExamBrowser.csproj
index 6fb37193..13d7278c 100644
--- a/SafeExamBrowser/SafeExamBrowser.csproj
+++ b/SafeExamBrowser/SafeExamBrowser.csproj
@@ -51,6 +51,7 @@
+
Code