diff options
author | Halil İbrahim Kalkan <hi_kalkan@yahoo.com> | 2013-04-08 21:44:58 +0300 |
---|---|---|
committer | Halil İbrahim Kalkan <hi_kalkan@yahoo.com> | 2013-04-08 21:44:58 +0300 |
commit | 79953cb56cda204f190ffcd9995b27ebea25e62d (patch) | |
tree | de939755c2e32eaa5fa3e41e21114e1c727ed0a4 /samples/IrcChatSystem/ChatClientApp/Client | |
parent | 934c543eb6b0bd7173038e45a7dac0241d091da4 (diff) | |
download | scs-79953cb56cda204f190ffcd9995b27ebea25e62d.zip scs-79953cb56cda204f190ffcd9995b27ebea25e62d.tar.gz scs-79953cb56cda204f190ffcd9995b27ebea25e62d.tar.bz2 |
Adding to github
Adding to github
Diffstat (limited to 'samples/IrcChatSystem/ChatClientApp/Client')
8 files changed, 727 insertions, 0 deletions
diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs b/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs new file mode 100644 index 0000000..709df89 --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/ChatClient.cs @@ -0,0 +1,103 @@ +using System; +using Hik.Samples.Scs.IrcChat.Arguments; +using Hik.Samples.Scs.IrcChat.Contracts; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This class implements IChatClient to use to be invoked by Chat Server. + /// </summary> + internal class ChatClient : IChatClient + { + #region Private fields + + /// <summary> + /// Reference to Chat Room window. + /// </summary> + private readonly IChatRoomView _chatRoom; + + #endregion + + #region Constructor + + /// <summary> + /// Creates a new ChatClient. + /// </summary> + /// <param name="chatRoom">Reference to Chat Room window</param> + public ChatClient(IChatRoomView chatRoom) + { + _chatRoom = chatRoom; + } + + #endregion + + #region IChatClient implementation + + /// <summary> + /// This method is used to get user list from chat server. + /// It is called by server, once after user logged in to server. + /// </summary> + /// <param name="users">All online user informations</param> + public void GetUserList(UserInfo[] users) + { + foreach (var user in users) + { + _chatRoom.AddUserToList(user); + } + } + + /// <summary> + /// This method is called from chat server to inform that a message + /// is sent to chat room publicly. + /// </summary> + /// <param name="nick">Nick of sender</param> + /// <param name="message">Message text</param> + public void OnMessageToRoom(string nick, ChatMessage message) + { + _chatRoom.OnMessageReceived(nick, message); + } + + /// <summary> + /// This method is called from chat server to inform that a message + /// is sent to the current used privately. + /// </summary> + /// <param name="nick">Nick of sender</param> + /// <param name="message">Message</param> + public void OnPrivateMessage(string nick, ChatMessage message) + { + _chatRoom.OnPrivateMessageReceived(nick, message); + } + + /// <summary> + /// This method is called from chat server to inform that a new user + /// joined to chat room. + /// </summary> + /// <param name="userInfo">Informations of new user</param> + public void OnUserLogin(UserInfo userInfo) + { + _chatRoom.AddUserToList(userInfo); + } + + /// <summary> + /// This method is called from chat server to inform that an existing user + /// has left the chat room. + /// </summary> + /// <param name="nick">Informations of new user</param> + public void OnUserLogout(string nick) + { + _chatRoom.RemoveUserFromList(nick); + } + + /// <summary> + /// This method is called from chat server to inform that a user changed his/her status. + /// </summary> + /// <param name="nick">Nick of the user</param> + /// <param name="newStatus">New status of the user</param> + public void OnUserStatusChange(string nick, UserStatus newStatus) + { + _chatRoom.OnUserStatusChange(nick, newStatus); + } + + #endregion + } +} diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs b/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs new file mode 100644 index 0000000..91a2241 --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/ChatController.cs @@ -0,0 +1,155 @@ +using System; +using Hik.Communication.Scs.Communication; +using Hik.Communication.Scs.Communication.EndPoints.Tcp; +using Hik.Communication.ScsServices.Client; +using Hik.Communication.ScsServices.Communication.Messages; +using Hik.Samples.Scs.IrcChat.Arguments; +using Hik.Samples.Scs.IrcChat.Contracts; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This class is a mediator with view and SCS system. + /// </summary> + internal class ChatController : IChatController + { + #region Private fields + + /// <summary> + /// Reference to login form. + /// </summary> + public ILoginFormView LoginForm { get; set; } + + /// <summary> + /// Reference to chat room window. + /// </summary> + public IChatRoomView ChatRoom { get; set; } + + /// <summary> + /// The object which handles remote method calls from server. + /// It implements IChatClient contract. + /// </summary> + private ChatClient _chatClient; + + /// <summary> + /// This object is used to connect to SCS Chat Service as a client. + /// </summary> + private IScsServiceClient<IChatService> _scsClient; + + #endregion + + #region IChatController implementation + + /// <summary> + /// Connects to the server. + /// It automatically Logins to server if connection success. + /// </summary> + public void Connect() + { + //Disconnect if currently connected + Disconnect(); + + //Create a ChatClient to handle remote method invocations by server + _chatClient = new ChatClient(ChatRoom); + + //Create a SCS client to connect to SCS server + _scsClient = ScsServiceClientBuilder.CreateClient<IChatService>(new ScsTcpEndPoint(LoginForm.ServerIpAddress, LoginForm.ServerTcpPort), _chatClient); + + //Register events of SCS client + _scsClient.Connected += ScsClient_Connected; + _scsClient.Disconnected += ScsClient_Disconnected; + + //Connect to the server + _scsClient.Connect(); + } + + /// <summary> + /// Disconnects from server if it is connected. + /// </summary> + public void Disconnect() + { + if (_scsClient != null && _scsClient.CommunicationState == CommunicationStates.Connected) + { + try + { + _scsClient.Disconnect(); + } + catch + { + + } + + _scsClient = null; + } + } + + /// <summary> + /// Sends a public message to room. + /// It will be seen by all users in room. + /// </summary> + /// <param name="message">Message to be sent</param> + public void SendMessageToRoom(ChatMessage message) + { + _scsClient.ServiceProxy.SendMessageToRoom(message); + } + + /// <summary> + /// Change status of user. + /// </summary> + /// <param name="newStatus">New status</param> + public void ChangeStatus(UserStatus newStatus) + { + _scsClient.ServiceProxy.ChangeStatus(newStatus); + } + + /// <summary> + /// Sends a private message to a user. + /// </summary> + /// <param name="nick">Destination nick</param> + /// <param name="message">Message</param> + public void SendPrivateMessage(string nick, ChatMessage message) + { + _scsClient.ServiceProxy.SendPrivateMessage(nick, message); + } + + #endregion + + #region Private methods + + /// <summary> + /// This method handles Connected event of _scsClient. + /// </summary> + /// <param name="sender">Source of event</param> + /// <param name="e">Event arguments</param> + private void ScsClient_Connected(object sender, EventArgs e) + { + try + { + _scsClient.ServiceProxy.Login(LoginForm.CurrentUserInfo); + ChatRoom.OnLoggedIn(); + } + catch (ScsRemoteException ex) + { + Disconnect(); + ChatRoom.OnLoginError(ex.InnerException != null ? ex.InnerException.Message : ex.Message); + } + catch + { + Disconnect(); + ChatRoom.OnLoginError("Can not login to server. Please try again later."); + } + } + + /// <summary> + /// This method handles Disconnected event of _scsClient. + /// </summary> + /// <param name="sender">Source of event</param> + /// <param name="e">Event arguments</param> + private void ScsClient_Disconnected(object sender, EventArgs e) + { + ChatRoom.OnLoggedOut(); + } + + #endregion + } +} diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs b/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs new file mode 100644 index 0000000..9b417db --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/ClientHelper.cs @@ -0,0 +1,93 @@ +using System.IO; +using System.Media; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This class includes come helper methods that are using in chat client. + /// </summary> + public static class ClientHelper + { + /// <summary> + /// Gets the directory of executing assembly. + /// </summary> + /// <returns>Current directory</returns> + public static string GetCurrentDirectory() + { + return (new FileInfo(Assembly.GetExecutingAssembly().Location)).Directory.FullName; + } + + /// <summary> + /// Gets the size of a file as bytes + /// </summary> + /// <param name="filePath">Path of file</param> + /// <returns>Size of file</returns> + public static long GetFileSize(string filePath) + { + using (var file = File.Open(filePath, FileMode.Open)) + { + var lengthOfFile = file.Length; + file.Close(); + return lengthOfFile; + } + } + + /// <summary> + /// Serializes an object and writes it to a file. + /// Uses .NET binary serialization. + /// </summary> + /// <param name="obj">object to be serialized</param> + /// <param name="filePath">Path of file to serialize</param> + /// <returns>bytes of object</returns> + public static void SerializeObjectToFile(object obj, string filePath) + { + using (var file = new FileStream(filePath, FileMode.Create)) + { + new BinaryFormatter().Serialize(file, obj); + file.Flush(); + } + } + + /// <summary> + /// Deserializes an object from a file. + /// Uses .NET binary deserialization. + /// </summary> + /// <param name="filePath">Path of file to deserialize</param> + /// <returns>deserialized object</returns> + public static object DeserializeObjectFromFile(string filePath) + { + using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + return new BinaryFormatter().Deserialize(file); + } + } + + /// <summary> + /// Plays incoming message sound (if sound is on). + /// </summary> + public static void PlayIncomingMessageSound() + { + if (!UserPreferences.Current.IsSoundOn) + { + return; + } + + try + { + var filePath = Path.Combine(GetCurrentDirectory(), @"Sounds\incoming_message.wav"); + if (!File.Exists(filePath)) + { + return; + } + + new SoundPlayer(filePath).Play(); + } + catch + { + + } + } + } +} diff --git a/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs b/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs new file mode 100644 index 0000000..4fd90cf --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/IChatController.cs @@ -0,0 +1,41 @@ +using Hik.Samples.Scs.IrcChat.Arguments; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This interface defines method of chat controller that can be used by views. + /// </summary> + public interface IChatController + { + /// <summary> + /// Connects to the server. + /// It automatically Logins to server if connection success. + /// </summary> + void Connect(); + + /// <summary> + /// Disconnects from server if it is connected. + /// </summary> + void Disconnect(); + + /// <summary> + /// Sends a public message to room. + /// It will be seen all users in room. + /// </summary> + /// <param name="message">Message to be sent</param> + void SendMessageToRoom(ChatMessage message); + + /// <summary> + /// Change status of user. + /// </summary> + /// <param name="newStatus">New status</param> + void ChangeStatus(UserStatus newStatus); + + /// <summary> + /// Sends a private message to a user. + /// </summary> + /// <param name="nick">Destination nick</param> + /// <param name="message">Message</param> + void SendPrivateMessage(string nick, ChatMessage message); + } +}
\ No newline at end of file diff --git a/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs b/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs new file mode 100644 index 0000000..b5f11a8 --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/IChatRoomView.cs @@ -0,0 +1,60 @@ +using Hik.Samples.Scs.IrcChat.Arguments; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This interface is used to interact with main chat room window by ChatController. + /// It is implemented by main window. + /// </summary> + public interface IChatRoomView + { + /// <summary> + /// This method is called when a message is sent to chat room. + /// </summary> + /// <param name="nick">Nick of sender</param> + /// <param name="message">Message</param> + void OnMessageReceived(string nick, ChatMessage message); + + /// <summary> + /// This method is called when a private message is sent to the current user. + /// </summary> + /// <param name="nick">Nick of sender</param> + /// <param name="message">The message</param> + void OnPrivateMessageReceived(string nick, ChatMessage message); + + /// <summary> + /// This method is called when user successfully logged in to chat server. + /// </summary> + void OnLoggedIn(); + + /// <summary> + /// This method is used to inform view if login is failed. + /// </summary> + /// <param name="errorMessage">Detail of error</param> + void OnLoginError(string errorMessage); + + /// <summary> + /// This method is called when connection to server is closed. + /// </summary> + void OnLoggedOut(); + + /// <summary> + /// This methos is used to add a new user to user list in room view. + /// </summary> + /// <param name="userInfo">Informations of new user</param> + void AddUserToList(UserInfo userInfo); + + /// <summary> + /// This metrhod is used to remove a user (that is disconnected from server) from user list in room view. + /// </summary> + /// <param name="nick">Nick of user to remove</param> + void RemoveUserFromList(string nick); + + /// <summary> + /// This method is called from chat server to inform that a user changed his/her status. + /// </summary> + /// <param name="nick">Nick of the user</param> + /// <param name="newStatus">New status of the user</param> + void OnUserStatusChange(string nick, UserStatus newStatus); + } +}
\ No newline at end of file diff --git a/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs b/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs new file mode 100644 index 0000000..1f746d9 --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/ILoginFormView.cs @@ -0,0 +1,26 @@ +using Hik.Samples.Scs.IrcChat.Arguments; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This interface is used to interact with login form by ChatController. + /// ChatController gets user informations over this interface. + /// </summary> + public interface ILoginFormView + { + /// <summary> + /// IP address of server to be connected. + /// </summary> + string ServerIpAddress { get; } + + /// <summary> + /// TCP Port number of server to be connected. + /// </summary> + int ServerTcpPort { get; } + + /// <summary> + /// User Login informations to be used while logging on to the server. + /// </summary> + UserInfo CurrentUserInfo { get; } + } +}
\ No newline at end of file diff --git a/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs b/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs new file mode 100644 index 0000000..64143c6 --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/UserPreferences.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; +using Hik.Samples.Scs.IrcChat.Arguments; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This class is used to save and load preferences of the user. + /// </summary> + [Serializable] + internal class UserPreferences + { + /// <summary> + /// Gets the singleton instance of this class. + /// </summary> + public static UserPreferences Current + { + get + { + if (_current == null) + { + lock (SyncObj) + { + if (_current == null) + { + _current = LoadPreferences(); + } + } + } + + return _current; + } + } + + /// <summary> + /// Nick of the user. + /// </summary> + public string Nick { get; set; } + + /// <summary> + /// Path of user's avatar file. + /// </summary> + public string AvatarFile { get; set; } + + /// <summary> + /// Sound preference of user. + /// True if sound is on. + /// </summary> + public bool IsSoundOn { get; set; } + + /// <summary> + /// Ip address of the chat server. + /// </summary> + public string ServerIpAddress { get; set; } + + /// <summary> + /// TCP port of the chat server. + /// </summary> + public int ServerTcpPort { get; set; } + + /// <summary> + /// Text style of user. + /// </summary> + public MessageTextStyle TextStyle { get; private set; } + + /// <summary> + /// The singleton instance of this class. + /// </summary> + private static UserPreferences _current; + + /// <summary> + /// Used to synronize threads while creating singleton object. + /// </summary> + private static readonly object SyncObj = new object(); + + /// <summary> + /// Constructor. + /// </summary> + private UserPreferences() + { + IsSoundOn = true; + TextStyle = new MessageTextStyle(); + } + + /// <summary> + /// Saves preferences to the disc. + /// </summary> + public void Save() + { + try + { + ClientHelper.SerializeObjectToFile( + this, + Path.Combine(ClientHelper.GetCurrentDirectory(), "Preferences.bin") + ); + } + catch + { + + } + } + + /// <summary> + /// Load last preferences from the disc. + /// </summary> + /// <returns>Last user preferences (or default values if not found)</returns> + private static UserPreferences LoadPreferences() + { + try + { + var preferenceFile = Path.Combine(ClientHelper.GetCurrentDirectory(), "Preferences.bin"); + if (File.Exists(preferenceFile)) + { + return (UserPreferences)ClientHelper.DeserializeObjectFromFile(preferenceFile); + } + } + catch + { + + } + + return CreateDefault(); + } + + /// <summary> + /// Creates a default-valued instance of this class. + /// </summary> + /// <returns>UserPreferences object with default values</returns> + private static UserPreferences CreateDefault() + { + return new UserPreferences + { + Nick = "User Nick", + AvatarFile = Path.Combine(ClientHelper.GetCurrentDirectory(), @"Images\user_male.png"), + ServerIpAddress = "127.0.0.1", + ServerTcpPort = 10048 + }; + } + } +} diff --git a/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs b/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs new file mode 100644 index 0000000..517bc1d --- /dev/null +++ b/samples/IrcChatSystem/ChatClientApp/Client/WindowsHelper.cs @@ -0,0 +1,109 @@ +using System; +using System.Runtime.InteropServices; + +namespace Hik.Samples.Scs.IrcChat.Client +{ + /// <summary> + /// This class is used to flash window caption / taskbar button when a message received + /// and window is not active. + /// </summary> + public static class WindowsHelper + { + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FlashWindowEx(ref FLASHWINFO pwfi); + + [StructLayout(LayoutKind.Sequential)] + public struct FLASHWINFO + { + /// <summary> + /// The size of the structure in bytes. + /// </summary> + public uint cbSize; + /// <summary> + /// A Handle to the Window to be Flashed. The window can be either opened or minimized. + /// </summary> + public IntPtr hwnd; + /// <summary> + /// The Flash Status. + /// </summary> + public FlashWindowFlags dwFlags; //uint + /// <summary> + /// The number of times to Flash the window. + /// </summary> + public uint uCount; + /// <summary> + /// The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate. + /// </summary> + public uint dwTimeout; + } + + public enum FlashWindowFlags : uint + { + /// <summary> + /// Stop flashing. The system restores the window to its original state. + /// </summary> + FLASHW_STOP = 0, + + /// <summary> + /// Flash the window caption. + /// </summary> + FLASHW_CAPTION = 1, + + /// <summary> + /// Flash the taskbar button. + /// </summary> + FLASHW_TRAY = 2, + + /// <summary> + /// Flash both the window caption and taskbar button. + /// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags. + /// </summary> + FLASHW_ALL = 3, + + /// <summary> + /// Flash continuously, until the FLASHW_STOP flag is set. + /// </summary> + FLASHW_TIMER = 4, + + /// <summary> + /// Flash continuously until the window comes to the foreground. + /// </summary> + FLASHW_TIMERNOFG = 12 + } + + + public static bool FlashWindow(IntPtr hWnd, + FlashWindowFlags fOptions, + uint FlashCount, + uint FlashRate) + { + if (IntPtr.Zero != hWnd) + { + FLASHWINFO fi = new FLASHWINFO(); + fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO)); + fi.dwFlags = fOptions; + fi.uCount = FlashCount; + fi.dwTimeout = FlashRate; + fi.hwnd = hWnd; + + return FlashWindowEx(ref fi); + } + return false; + } + + public static bool StopFlashingWindow(IntPtr hWnd) + { + if (IntPtr.Zero != hWnd) + { + FLASHWINFO fi = new FLASHWINFO(); + fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO)); + fi.dwFlags = (uint)FlashWindowFlags.FLASHW_STOP; + fi.hwnd = hWnd; + + return FlashWindowEx(ref fi); + } + return false; + } + } +} |