Moving much of the WindowsFormsEngine-specific, engine-agnostic stuff to Engine proper

This commit is contained in:
Michael Becker 2014-06-06 11:27:44 -04:00
parent 590328f2e4
commit a0aa58c1a3
6 changed files with 0 additions and 691 deletions

View File

@ -1,86 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.ObjectModels.Markup;
using UniversalEditor.DataFormats.Markup.XML;
using UniversalEditor.Accessors;
using UniversalEditor;
internal static class BookmarksManager
{
private static System.Collections.Specialized.StringCollection mvarFileNames = new System.Collections.Specialized.StringCollection();
public static System.Collections.Specialized.StringCollection FileNames { get { return mvarFileNames; } }
private static string mvarDataFileName = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Mike Becker's Software",
"Universal Editor",
"Bookmarks.xml"
});
public static string DataFileName { get { return mvarDataFileName; } set { mvarDataFileName = value; } }
private static Version mvarFormatVersion = new Version(1, 0);
public static void Load()
{
MarkupObjectModel mom = new MarkupObjectModel();
XMLDataFormat xml = new XMLDataFormat();
if (!System.IO.File.Exists(mvarDataFileName)) return;
Document.Load(mom, xml, new FileAccessor(mvarDataFileName), true);
MarkupTagElement tagBookmarks = (mom.Elements["Bookmarks"] as MarkupTagElement);
if (tagBookmarks == null) return;
MarkupAttribute attVersion = tagBookmarks.Attributes["Version"];
if (attVersion != null)
{
mvarFormatVersion = new Version(attVersion.Value);
}
foreach (MarkupElement elDocument in tagBookmarks.Elements)
{
MarkupTagElement tagBookmark = (elDocument as MarkupTagElement);
if (tagBookmark == null) continue;
if (tagBookmark.FullName != "Bookmark") continue;
MarkupAttribute attFileName = tagBookmark.Attributes["FileName"];
if (attFileName == null) continue;
mvarFileNames.Add(attFileName.Value);
}
}
public static void Save()
{
MarkupObjectModel mom = new MarkupObjectModel();
XMLDataFormat xml = new XMLDataFormat();
MarkupPreprocessorElement xmlp = new MarkupPreprocessorElement();
xmlp.FullName = "xml";
xmlp.Value = "version=\"1.0\" encoding=\"UTF-8\"";
mom.Elements.Add(xmlp);
MarkupTagElement tagBookmarks = new MarkupTagElement();
tagBookmarks.FullName = "Bookmarks";
tagBookmarks.Attributes.Add("Version", mvarFormatVersion.ToString());
mom.Elements.Add(tagBookmarks);
if (mvarFileNames.Count > 0)
{
foreach (string fileName in mvarFileNames)
{
MarkupTagElement tagBookmark = new MarkupTagElement();
tagBookmark.FullName = "Bookmark";
tagBookmark.Attributes.Add("FileName", fileName);
tagBookmarks.Elements.Add(tagBookmark);
}
}
Document.Save(mom, xml, new FileAccessor(mvarDataFileName, true, true), true);
}
}

View File

@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.ObjectModels.Markup;
using UniversalEditor.DataFormats.Markup.XML;
using System.Drawing;
using UniversalEditor.Accessors;
namespace UniversalEditor.UserInterface.WindowsForms
{
public class Configuration
{
private static string mvarApplicationName = "Universal Editor";
public static string ApplicationName { get { return mvarApplicationName; } set { mvarApplicationName = value; } }
private static string mvarApplicationShortName = "universal-editor"; // polymolive
public static string ApplicationShortName { get { return mvarApplicationShortName; } set { mvarApplicationShortName = value; } }
private static string mvarCompanyName = "Mike Becker's Software";
public static string CompanyName { get { return mvarCompanyName; } set { mvarCompanyName = value; } }
private static SplashScreenSettings mvarSplashScreen = new SplashScreenSettings();
public static SplashScreenSettings SplashScreen { get { return mvarSplashScreen; } }
private static StartPageSettings mvarStartPage = new StartPageSettings();
public static StartPageSettings StartPage { get { return mvarStartPage; } }
private static ColorSchemeSettings mvarColorScheme = new ColorSchemeSettings();
public static ColorSchemeSettings ColorScheme { get { return mvarColorScheme; } }
private static bool mvarConfirmExit = false;
public static bool ConfirmExit { get { return mvarConfirmExit; } set { mvarConfirmExit = value; } }
private static void LoadPreliminaryConfiguration(ref MarkupObjectModel mom)
{
string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
LoadConfigurationFiles(path, ref mom);
MarkupTagElement tagTitle = (mom.FindElement("UniversalEditor", "Application", "Title") as MarkupTagElement);
if (tagTitle != null)
{
mvarApplicationName = tagTitle.Value;
}
MarkupTagElement tagShortTitle = (mom.FindElement("UniversalEditor", "Application", "ShortTitle") as MarkupTagElement);
if (tagShortTitle != null)
{
mvarApplicationShortName = tagShortTitle.Value;
}
MarkupTagElement tagCompanyName = (mom.FindElement("UniversalEditor", "Application", "CompanyName") as MarkupTagElement);
if (tagCompanyName != null)
{
mvarCompanyName = tagCompanyName.Value;
}
}
static Configuration()
{
MarkupObjectModel mom = new MarkupObjectModel();
LoadPreliminaryConfiguration(ref mom);
List<string> paths = new List<string>();
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
{
break;
}
case PlatformID.Unix:
{
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), mvarApplicationShortName }));
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), mvarApplicationShortName }));
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), mvarApplicationShortName }));
break;
}
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
{
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), mvarCompanyName, mvarApplicationName }));
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), mvarCompanyName, mvarApplicationName }));
paths.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Mike Becker's Software", "PolyMo Live!" }));
break;
}
}
foreach (string path in paths)
{
if (!System.IO.Directory.Exists(path)) continue;
LoadConfigurationFiles(path, ref mom);
}
}
private static void LoadConfigurationFiles(string path, ref MarkupObjectModel mom)
{
string[] xmlfiles = null;
try
{
xmlfiles = System.IO.Directory.GetFiles(path, "*.xml", System.IO.SearchOption.AllDirectories);
}
catch
{
}
if (xmlfiles == null) return;
foreach (string xmlfile in xmlfiles)
{
MarkupObjectModel local_mom = new MarkupObjectModel();
Document doc = new Document(local_mom, new XMLDataFormat(), new FileAccessor(xmlfile));
if (local_mom.FindElement("UniversalEditor") == null) continue;
local_mom.CopyTo(mom);
}
}
private static System.Drawing.Icon mvarMainIcon = null;
public static System.Drawing.Icon MainIcon { get { return mvarMainIcon; } set { mvarMainIcon = value; } }
private static string mvarDataPath = null;
public static string DataPath
{
get
{
if (mvarDataPath == null)
{
mvarDataPath = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Mike Becker's Software",
"Universal Editor"
});
}
return mvarDataPath;
}
}
}
public class StartPageSettings
{
private bool mvarShowOnStartup = true;
public bool ShowOnStartup { get { return mvarShowOnStartup; } set { mvarShowOnStartup = value; } }
private string mvarHeaderImageFileName = @"Images/SplashScreen/header2.png"; // null;
public string HeaderImageFileName { get { return mvarHeaderImageFileName; } set { mvarHeaderImageFileName = value; } }
}
public class ColorSchemeSettings
{
private Color mvarDarkColor = Color.FromArgb(30, 30, 30);
public Color DarkColor { get { return mvarDarkColor; } set { mvarDarkColor = value; } }
private Color mvarLightColor = Color.FromArgb(51, 51, 51);
public Color LightColor { get { return mvarLightColor; } set { mvarLightColor = value; } }
private Color mvarBackgroundColor = Color.FromArgb(77, 77, 77);
public Color BackgroundColor { get { return mvarBackgroundColor; } set { mvarBackgroundColor = value; } }
}
}

View File

@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.ObjectModels.Markup;
using UniversalEditor.DataFormats.Markup.XML;
using UniversalEditor.Accessors;
using UniversalEditor;
internal static class RecentFileManager
{
private static System.Collections.Specialized.StringCollection mvarFileNames = new System.Collections.Specialized.StringCollection();
public static System.Collections.Specialized.StringCollection FileNames { get { return mvarFileNames; } }
private static int mvarMaximumDocumentFileNames = 5;
public static int MaximumDocumentFileNames { get { return mvarMaximumDocumentFileNames; } set { mvarMaximumDocumentFileNames = value; } }
private static string mvarDataFileName = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Mike Becker's Software",
"Universal Editor",
"RecentItems.xml"
});
public static string DataFileName { get { return mvarDataFileName; } set { mvarDataFileName = value; } }
private static Version mvarFormatVersion = new Version(1, 0);
public static void Load()
{
MarkupObjectModel mom = new MarkupObjectModel();
XMLDataFormat xml = new XMLDataFormat();
if (!System.IO.File.Exists(mvarDataFileName)) return;
Document doc = new Document(mom, xml, new FileAccessor(mvarDataFileName));
MarkupTagElement tagRecentItems = (mom.Elements["RecentItems"] as MarkupTagElement);
if (tagRecentItems == null) return;
MarkupAttribute attVersion = tagRecentItems.Attributes["Version"];
if (attVersion != null)
{
mvarFormatVersion = new Version(attVersion.Value);
}
MarkupTagElement tagSolutions = (tagRecentItems.Elements["Solutions"] as MarkupTagElement);
MarkupTagElement tagDocuments = (tagRecentItems.Elements["Documents"] as MarkupTagElement);
if (tagDocuments != null)
{
foreach (MarkupElement elDocument in tagDocuments.Elements)
{
MarkupTagElement tagDocument = (elDocument as MarkupTagElement);
if (tagDocument == null) continue;
if (tagDocument.FullName != "Document") continue;
MarkupAttribute attFileName = tagDocument.Attributes["FileName"];
if (attFileName == null) continue;
mvarFileNames.Add(attFileName.Value);
}
}
}
public static void Save()
{
MarkupObjectModel mom = new MarkupObjectModel();
XMLDataFormat xml = new XMLDataFormat();
MarkupPreprocessorElement xmlp = new MarkupPreprocessorElement();
xmlp.FullName = "xml";
xmlp.Value = "version=\"1.0\" encoding=\"UTF-8\"";
mom.Elements.Add(xmlp);
MarkupTagElement tagRecentItems = new MarkupTagElement();
tagRecentItems.FullName = "RecentItems";
tagRecentItems.Attributes.Add("Version", mvarFormatVersion.ToString());
mom.Elements.Add(tagRecentItems);
if (mvarFileNames.Count > 0)
{
MarkupTagElement tagDocuments = new MarkupTagElement();
tagDocuments.FullName = "Documents";
tagDocuments.Attributes.Add("Maximum", mvarMaximumDocumentFileNames.ToString());
foreach (string fileName in mvarFileNames)
{
MarkupTagElement tagDocument = new MarkupTagElement();
tagDocument.FullName = "Document";
tagDocument.Attributes.Add("FileName", fileName);
tagDocuments.Elements.Add(tagDocument);
}
tagRecentItems.Elements.Add(tagDocuments);
}
Document.Save(mom, xml, new FileAccessor(mvarDataFileName, true, true), true);
}
}

View File

@ -1,210 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.ObjectModels.Markup;
using UniversalEditor.DataFormats.Markup.XML;
using UniversalEditor.Accessors;
using UniversalEditor;
internal static class SessionManager
{
public class Window
{
public class WindowCollection
: System.Collections.ObjectModel.Collection<Window>
{
}
private int mvarLeft = 0;
public int Left { get { return mvarLeft; } set { mvarLeft = value; } }
private int mvarTop = 0;
public int Top { get { return mvarTop; } set { mvarTop = value; } }
private int mvarWidth = 0;
public int Width { get { return mvarWidth; } set { mvarWidth = value; } }
private int mvarHeight = 0;
public int Height { get { return mvarHeight; } set { mvarHeight = value; } }
private System.Windows.Forms.FormWindowState mvarWindowState = System.Windows.Forms.FormWindowState.Normal;
public System.Windows.Forms.FormWindowState WindowState { get { return mvarWindowState; } set { mvarWindowState = value; } }
private List<string> mvarFileNames = new List<string>();
public List<string> FileNames { get { return mvarFileNames; } }
}
public class Session
{
public class SessionCollection
: System.Collections.ObjectModel.Collection<Session>
{
}
private string mvarTitle = String.Empty;
public string Title { get { return mvarTitle; } set { mvarTitle = value; } }
private Window.WindowCollection mvarWindows = new Window.WindowCollection();
public Window.WindowCollection Windows { get { return mvarWindows; } }
}
private static string mvarDataFileName = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Mike Becker's Software",
"Universal Editor",
"Sessions.xml"
});
public static string DataFileName { get { return mvarDataFileName; } set { mvarDataFileName = value; } }
private static Session.SessionCollection mvarSessions = new Session.SessionCollection();
public static Session.SessionCollection Sessions { get { return mvarSessions; } }
private static Version mvarFormatVersion = new Version(1, 0);
public static void Load()
{
MarkupObjectModel mom = new MarkupObjectModel();
XMLDataFormat xml = new XMLDataFormat();
if (!System.IO.File.Exists(mvarDataFileName)) return;
Document.Load(mom, xml, new FileAccessor(mvarDataFileName), true);
MarkupTagElement tagSessions = (mom.Elements["Sessions"] as MarkupTagElement);
if (tagSessions == null) return;
MarkupAttribute attVersion = tagSessions.Attributes["Version"];
if (attVersion != null)
{
mvarFormatVersion = new Version(attVersion.Value);
}
foreach (MarkupElement elSession in tagSessions.Elements)
{
MarkupTagElement tagSession = (elSession as MarkupTagElement);
if (tagSession == null) continue;
if (tagSession.FullName != "Session") continue;
MarkupAttribute attTitle = tagSession.Attributes["Title"];
if (attTitle == null) continue;
Session session = new Session();
session.Title = attTitle.Value;
MarkupTagElement tagWindows = (tagSession.Elements["Windows"] as MarkupTagElement);
foreach (MarkupElement elWindow in tagWindows.Elements)
{
MarkupTagElement tagWindow = (elWindow as MarkupTagElement);
if (tagWindow == null) continue;
if (tagWindow.FullName != "Window") continue;
Window window = new Window();
int left = 0, top = 0, width = 600, height = 400;
MarkupAttribute attLeft = tagWindow.Attributes["Left"];
if (attLeft != null) Int32.TryParse(attLeft.Value, out left);
MarkupAttribute attTop = tagWindow.Attributes["Top"];
if (attTop != null) Int32.TryParse(attTop.Value, out top);
MarkupAttribute attWidth = tagWindow.Attributes["Width"];
if (attWidth != null) Int32.TryParse(attWidth.Value, out width);
MarkupAttribute attHeight = tagWindow.Attributes["Height"];
if (attHeight != null) Int32.TryParse(attHeight.Value, out height);
window.Left = left;
window.Top = top;
window.Width = width;
window.Height = height;
MarkupTagElement tagDocuments = (tagWindow.Elements["Documents"] as MarkupTagElement);
if (tagDocuments != null)
{
foreach (MarkupElement elDocument in tagDocuments.Elements)
{
MarkupTagElement tagDocument = (elDocument as MarkupTagElement);
if (tagDocument == null) continue;
if (tagDocument.FullName != "Document") continue;
MarkupAttribute attFileName = tagDocument.Attributes["FileName"];
if (attFileName == null) continue;
window.FileNames.Add(attFileName.Value);
}
}
session.Windows.Add(window);
}
mvarSessions.Add(session);
}
}
public static void Save()
{
MarkupObjectModel mom = new MarkupObjectModel();
UniversalEditor.ObjectModel om = mom;
XMLDataFormat xml = new XMLDataFormat();
MarkupPreprocessorElement xmlp = new MarkupPreprocessorElement();
xmlp.FullName = "xml";
xmlp.Value = "version=\"1.0\" encoding=\"UTF-8\"";
mom.Elements.Add(xmlp);
MarkupTagElement tagSessions = new MarkupTagElement();
tagSessions.FullName = "Sessions";
tagSessions.Attributes.Add("Version", mvarFormatVersion.ToString());
mom.Elements.Add(tagSessions);
if (mvarSessions.Count > 0)
{
foreach (Session session in mvarSessions)
{
if (session.Windows.Count < 1) continue;
MarkupTagElement tagSession = new MarkupTagElement();
tagSession.FullName = "Session";
tagSession.Attributes.Add("Title", session.Title);
MarkupTagElement tagWindows = new MarkupTagElement();
tagWindows.FullName = "Windows";
foreach (Window window in session.Windows)
{
MarkupTagElement tagWindow = new MarkupTagElement();
tagWindow.FullName = "Window";
tagWindow.Attributes.Add("Left", window.Left.ToString());
tagWindow.Attributes.Add("Top", window.Top.ToString());
tagWindow.Attributes.Add("Width", window.Width.ToString());
tagWindow.Attributes.Add("Height", window.Height.ToString());
if (window.FileNames.Count > 0)
{
MarkupTagElement tagDocuments = new MarkupTagElement();
tagDocuments.FullName = "Documents";
foreach (string fileName in window.FileNames)
{
MarkupTagElement tagDocument = new MarkupTagElement();
tagDocument.FullName = "Document";
tagDocument.Attributes.Add("FileName", fileName);
tagDocuments.Elements.Add(tagDocument);
}
tagWindow.Elements.Add(tagDocuments);
}
tagWindows.Elements.Add(tagWindow);
}
tagSession.Elements.Add(tagWindows);
tagSessions.Elements.Add(tagSession);
}
}
Document.Save(om, xml, new FileAccessor(mvarDataFileName, true, true), true);
}
}

View File

@ -1,123 +0,0 @@
using System;
using System.Security.Permissions;
using System.Threading;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using System.Diagnostics;
using System.Runtime.Remoting.Channels.Ipc;
internal static class SingleInstanceManager
{
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[Serializable]
private class InstanceProxy : MarshalByRefObject
{
public static bool IsFirstInstance
{
get;
internal set;
}
public static string[] CommandLineArgs
{
get;
internal set;
}
public void SetCommandLineArgs(bool isFirstInstance, string[] commandLineArgs)
{
SingleInstanceManager.InstanceProxy.IsFirstInstance = isFirstInstance;
SingleInstanceManager.InstanceProxy.CommandLineArgs = commandLineArgs;
}
}
public class InstanceCallbackEventArgs : EventArgs
{
public bool IsFirstInstance
{
get;
private set;
}
public string[] CommandLineArgs
{
get;
private set;
}
internal InstanceCallbackEventArgs(bool isFirstInstance, string[] commandLineArgs)
{
this.IsFirstInstance = isFirstInstance;
this.CommandLineArgs = commandLineArgs;
}
}
public static bool CreateSingleInstance(string name, EventHandler<SingleInstanceManager.InstanceCallbackEventArgs> callback)
{
bool result;
switch (Environment.OSVersion.Platform)
{
case PlatformID.Unix:
case PlatformID.Xbox:
case PlatformID.MacOSX:
result = true;
return result;
}
name = name.Replace("\\", "_");
name = name.Replace("/", "_");
EventWaitHandle eventWaitHandle = null;
string name2 = string.Format("{0}-{1}", Environment.MachineName, name);
SingleInstanceManager.InstanceProxy.IsFirstInstance = false;
SingleInstanceManager.InstanceProxy.CommandLineArgs = Environment.GetCommandLineArgs();
try
{
eventWaitHandle = EventWaitHandle.OpenExisting(name2);
}
catch
{
SingleInstanceManager.InstanceProxy.IsFirstInstance = true;
}
if (SingleInstanceManager.InstanceProxy.IsFirstInstance)
{
eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, name2);
ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, new WaitOrTimerCallback(SingleInstanceManager.WaitOrTimerCallback), callback, -1, false);
eventWaitHandle.Close();
SingleInstanceManager.RegisterRemoteType(name);
}
else
{
SingleInstanceManager.UpdateRemoteObject(name);
if (eventWaitHandle != null)
{
eventWaitHandle.Set();
}
Environment.Exit(0);
}
result = SingleInstanceManager.InstanceProxy.IsFirstInstance;
return result;
}
private static void UpdateRemoteObject(string uri)
{
IpcClientChannel chnl = new IpcClientChannel();
ChannelServices.RegisterChannel(chnl, true);
SingleInstanceManager.InstanceProxy instanceProxy = Activator.GetObject(typeof(SingleInstanceManager.InstanceProxy), string.Format("ipc://{0}{1}/{1}", Environment.MachineName, uri)) as SingleInstanceManager.InstanceProxy;
if (instanceProxy != null)
{
instanceProxy.SetCommandLineArgs(SingleInstanceManager.InstanceProxy.IsFirstInstance, SingleInstanceManager.InstanceProxy.CommandLineArgs);
}
ChannelServices.UnregisterChannel(chnl);
}
private static void RegisterRemoteType(string uri)
{
IpcServerChannel serverChannel = new IpcServerChannel(Environment.MachineName + uri);
ChannelServices.RegisterChannel(serverChannel, true);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingleInstanceManager.InstanceProxy), uri, WellKnownObjectMode.Singleton);
Process currentProcess = Process.GetCurrentProcess();
currentProcess.Exited += delegate
{
ChannelServices.UnregisterChannel(serverChannel);
};
}
private static void WaitOrTimerCallback(object state, bool timedOut)
{
EventHandler<SingleInstanceManager.InstanceCallbackEventArgs> eventHandler = state as EventHandler<SingleInstanceManager.InstanceCallbackEventArgs>;
if (eventHandler != null)
{
eventHandler(state, new SingleInstanceManager.InstanceCallbackEventArgs(SingleInstanceManager.InstanceProxy.IsFirstInstance, SingleInstanceManager.InstanceProxy.CommandLineArgs));
}
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.UserInterface.WindowsForms
{
public enum UnsavedDocumentOption
{
Save,
Discard
}
}