diff --git a/src/Engine-XMPP/Protocols/Xmpp/XmppProtocolManager.cs b/src/Engine-XMPP/Protocols/Xmpp/XmppProtocolManager.cs index c5e98a594..82aaf1a7d 100644 --- a/src/Engine-XMPP/Protocols/Xmpp/XmppProtocolManager.cs +++ b/src/Engine-XMPP/Protocols/Xmpp/XmppProtocolManager.cs @@ -443,6 +443,36 @@ public override void CloseChat(FrontendManager fm, ChatModel chat) } } + [MethodImpl(MethodImplOptions.Synchronized)] + public override void SetChatState(FrontendManager fm, ChatModel chat, ChatState state) + { + base.SetChatState(fm, chat, state); + if (!(chat is PersonChatModel)) { + return; + } + var msg = new Message(chat.ID); + switch (state) { + case ChatState.Active: + msg.Chatstate = Chatstate.active; + break; + case ChatState.Inactive: + msg.Chatstate = Chatstate.inactive; + break; + case ChatState.Composing: + msg.Chatstate = Chatstate.composing; + break; + case ChatState.Paused: + msg.Chatstate = Chatstate.paused; + break; + case ChatState.Gone: + msg.Chatstate = Chatstate.gone; + break; + default: + throw new ArgumentOutOfRangeException(); + } + JabberClient.Send(msg); + } + [MethodImpl(MethodImplOptions.Synchronized)] public override void SetPresenceStatus(PresenceStatus status, string message) @@ -1144,17 +1174,23 @@ void _Say(ChatModel chat, string text, bool send, bool display) XmppPersonModel person = GetOrCreateContact(_person.ID, _person.IdentityName); Jid jid = person.Jid; if (!String.IsNullOrEmpty(jid.Resource)) { - JabberClient.Send(new Message(jid, XmppMessageType.chat, text)); + var msg = new Message(jid, XmppMessageType.chat, text); + msg.Chatstate = Chatstate.active; + JabberClient.Send(msg); } else { var resources = person.GetResourcesWithHighestPriority(); if (resources.Count == 0) { // no connected resource, send to bare jid - JabberClient.Send(new Message(jid.Bare, XmppMessageType.chat, text)); + var msg = new Message(jid.Bare, XmppMessageType.chat, text); + msg.Chatstate = Chatstate.active; + JabberClient.Send(msg); } else { foreach (var res in resources) { Jid j = new Jid(jid); j.Resource = res.Name; - JabberClient.Send(new Message(j, XmppMessageType.chat, text)); + var msg = new Message(j, XmppMessageType.chat, text); + msg.Chatstate = Chatstate.active; + JabberClient.Send(msg); } } } diff --git a/src/Engine/Chats/ChatState.cs b/src/Engine/Chats/ChatState.cs new file mode 100644 index 000000000..10dacf168 --- /dev/null +++ b/src/Engine/Chats/ChatState.cs @@ -0,0 +1,37 @@ +// Smuxi - Smart MUltipleXed Irc +// +// Copyright (c) 2013 oliver +// +// Full GPL License: +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; + +namespace Smuxi.Engine +{ + public enum ChatState { + // after sending a message or w/o any state + Active, + // this chat window is not the active one + Inactive, + // is typing right now + Composing, + // was typing but stopped + Paused, + // the chat window has been closed + Gone + } +} + diff --git a/src/Engine/Engine.csproj b/src/Engine/Engine.csproj index 4b5282d8f..d22e89055 100644 --- a/src/Engine/Engine.csproj +++ b/src/Engine/Engine.csproj @@ -99,6 +99,7 @@ + diff --git a/src/Engine/Protocols/IProtocolManager.cs b/src/Engine/Protocols/IProtocolManager.cs index 9596c6df9..3a7b97a4a 100644 --- a/src/Engine/Protocols/IProtocolManager.cs +++ b/src/Engine/Protocols/IProtocolManager.cs @@ -84,5 +84,6 @@ PresenceStatus PresenceStatus { void CloseChat(FrontendManager fm, ChatModel chat); void SetPresenceStatus(PresenceStatus status, string message); + void SetChatState(FrontendManager fm, ChatModel chat, ChatState state); } } diff --git a/src/Engine/Protocols/ProtocolManagerBase.cs b/src/Engine/Protocols/ProtocolManagerBase.cs index 22474f17a..6a10a58c3 100644 --- a/src/Engine/Protocols/ProtocolManagerBase.cs +++ b/src/Engine/Protocols/ProtocolManagerBase.cs @@ -159,6 +159,11 @@ public abstract void Connect(FrontendManager fm, public abstract void SetPresenceStatus(PresenceStatus status, string message); + public virtual void SetChatState(FrontendManager fm, ChatModel chat, + ChatState state) + { + } + protected void NotConnected(CommandModel cmd) { var msg = CreateMessageBuilder(); diff --git a/src/Frontend-GNOME-XMPP/XmppPersonChatView.cs b/src/Frontend-GNOME-XMPP/XmppPersonChatView.cs index 3df380379..feefc4f39 100644 --- a/src/Frontend-GNOME-XMPP/XmppPersonChatView.cs +++ b/src/Frontend-GNOME-XMPP/XmppPersonChatView.cs @@ -213,6 +213,20 @@ void _OnMenuWhoisItemActivated(object sender, EventArgs e) }); } + public override void OnSwitchedFrom() + { + base.OnSwitchedFrom(); + var entry = Frontend.MainWindow.Entry; + entry.SetChatState(ChatState.Inactive); + } + + public override void OnSwitchedTo() + { + base.OnSwitchedTo(); + var entry = Frontend.MainWindow.Entry; + entry.SetChatState(ChatState.Active); + } + void _OnMenuAddToContactsItemActivated(object sender, EventArgs e) { Trace.Call(sender, e); diff --git a/src/Frontend-GNOME/ChatViewManager.cs b/src/Frontend-GNOME/ChatViewManager.cs index 2b6fbbd47..491259c16 100644 --- a/src/Frontend-GNOME/ChatViewManager.cs +++ b/src/Frontend-GNOME/ChatViewManager.cs @@ -32,7 +32,7 @@ namespace Smuxi.Frontend.Gnome { - public class ChatViewManager : ChatViewManagerBase + public class ChatViewManager : ChatViewManagerBase { #if LOG4NET private static readonly log4net.ILog f_Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -46,14 +46,13 @@ public class ChatViewManager : ChatViewManagerBase bool AutoSwitchPersonChats { get; set; } bool AutoSwitchGroupChats { get; set; } - public event ChatViewManagerChatAddedEventHandler ChatAdded; - public event ChatViewManagerChatRemovedEventHandler ChatRemoved; - public event EventHandler ChatSynced; - - public override IChatView ActiveChat { + public override ChatView ActiveChat { get { return CurrentChatView; } + set { + CurrentChatView = value as ChatView; + } } public ChatView CurrentChatView { @@ -106,6 +105,8 @@ public bool IsSensitive { public ChatViewManager(Notebook notebook, Gtk.TreeView treeView) { f_Notebook = notebook; + f_Notebook.SwitchPage += HandleBeforeSwitchPage; + f_Notebook.SwitchPage += HandleSwitchPage; f_TreeView = treeView; SyncedChats = new List(); SyncManager = new ChatViewSyncManager(); @@ -114,6 +115,33 @@ public ChatViewManager(Notebook notebook, Gtk.TreeView treeView) SyncManager.WorkerException += OnWorkerException; } + void HandleSwitchPage(object sender, Gtk.SwitchPageArgs e) + { + Trace.Call(sender, e); + + if (f_Notebook.IsBrowseModeEnabled) { + return; + } + + // synchronize FrontManager.CurrenPage + ChatView chatView = f_Notebook.GetChat((int)e.PageNum); + if (chatView == null) { + return; + } + chatView.OnSwitchedTo(); + } + + [GLib.ConnectBefore] + void HandleBeforeSwitchPage(object sender, Gtk.SwitchPageArgs e) + { + if (f_Notebook.IsBrowseModeEnabled) { + return; + } + + var chatView = CurrentChatView; + chatView.OnSwitchedFrom(); + } + /// /// This method is thread safe. /// @@ -141,9 +169,7 @@ public override void RemoveChat(ChatModel chat) SyncManager.Remove(chat); SyncedChats.Remove(chatView); - if (ChatRemoved != null) { - ChatRemoved(this, new ChatViewManagerChatRemovedEventArgs(chatView)); - } + OnChatRemoved(new ChatViewManagerChatRemovedEventArgs(chatView)); chatView.Dispose(); } @@ -289,9 +315,7 @@ void OnChatAdded(object sender, ChatViewAddedEventArgs e) } } - if (ChatAdded != null) { - ChatAdded(this, new ChatViewManagerChatAddedEventArgs(chatView)); - } + OnChatAdded(new ChatViewManagerChatAddedEventArgs(chatView)); return false; }); } @@ -341,9 +365,7 @@ void OnChatSynced(object sender, ChatViewSyncedEventArgs e) chatView.ScrollToEnd(); SyncedChats.Add(chatView); - if (ChatSynced != null) { - ChatSynced(this, new ChatViewManagerChatSyncedEventArgs(chatView)); - } + OnChatSynced(new ChatViewManagerChatSyncedEventArgs(chatView)); return false; }); } @@ -410,50 +432,4 @@ int GetSortedChatPosition(ChatView chatView) return idx; } } - - public delegate void ChatViewManagerChatAddedEventHandler(object sender, ChatViewManagerChatAddedEventArgs e); - - public class ChatViewManagerChatAddedEventArgs : EventArgs - { - private ChatView f_ChatView; - - public ChatView ChatView { - get { - return f_ChatView; - } - } - - public ChatViewManagerChatAddedEventArgs(ChatView chatView) - { - f_ChatView = chatView; - } - } - - public delegate void ChatViewManagerChatRemovedEventHandler(object sender, ChatViewManagerChatRemovedEventArgs e); - - public class ChatViewManagerChatRemovedEventArgs : EventArgs - { - private ChatView f_ChatView; - - public ChatView ChatView { - get { - return f_ChatView; - } - } - - public ChatViewManagerChatRemovedEventArgs(ChatView chatView) - { - f_ChatView = chatView; - } - } - - public class ChatViewManagerChatSyncedEventArgs : EventArgs - { - public ChatView ChatView { get; private set; } - - public ChatViewManagerChatSyncedEventArgs(ChatView chatView) - { - ChatView = chatView; - } - } } diff --git a/src/Frontend-GNOME/Entry.cs b/src/Frontend-GNOME/Entry.cs index 6258c698e..2987b371f 100644 --- a/src/Frontend-GNOME/Entry.cs +++ b/src/Frontend-GNOME/Entry.cs @@ -126,6 +126,15 @@ public Entry(ChatViewManager chatViewManager) Activated += _OnActivated; KeyPressEvent += new Gtk.KeyPressEventHandler(_OnKeyPress); PasteClipboard += _OnClipboardPasted; + + Buffer.Changed += delegate { + if (Buffer.Text.Length == 0) { + return; + } + SetChatState(ChatState.Composing); + }; + + LastChatState = ChatState.Gone; } public void UpdateHistoryChangedLine() @@ -464,6 +473,61 @@ protected virtual void ProcessKey(Gtk.KeyPressEventArgs e) } } + ChatState LastChatState { get; set; } + DateTime LastChatStateCall { get; set; } + bool ComposingTimeoutActive { get; set; } + + bool ChatStateComposingTimeout() + { + if (LastChatState != ChatState.Composing) { + ComposingTimeoutActive = false; + return false; + } + var msleft = (LastChatStateCall + TimeSpan.FromSeconds(2)) - DateTime.Now; + if (msleft > TimeSpan.Zero) { + GLib.Timeout.Add((uint)msleft.Milliseconds, ChatStateComposingTimeout); + return false; + } + SetChatState(ChatState.Paused); + ComposingTimeoutActive = false; + return false; + } + + public void SetChatState(ChatState type) + { + if (Frontend.EngineVersion < new Version(0, 9, 1)) { + return; + } + var chatView = ChatViewManager.CurrentChatView as PersonChatView; + if (chatView == null) { + return; + } + + if (type == ChatState.Composing) { + LastChatStateCall = DateTime.Now; + } + if (LastChatState == type) { + // no duplication + return; + } + LastChatState = type; + var protocol = Frontend.FrontendManager.CurrentProtocolManager; + if (protocol == null) { + return; + } + + if (type == ChatState.Composing) { + if (!ComposingTimeoutActive) { + ComposingTimeoutActive = true; + GLib.Timeout.Add(2000, ChatStateComposingTimeout); + } + } + + protocol.SetChatState(Frontend.FrontendManager, + chatView.PersonChatModel, + type); + } + private void _OnActivated(object sender, EventArgs e) { Trace.Call(sender, e); diff --git a/src/Frontend-GNOME/IndicateManager.cs b/src/Frontend-GNOME/IndicateManager.cs index 6f89b0cf9..71c1e18e4 100644 --- a/src/Frontend-GNOME/IndicateManager.cs +++ b/src/Frontend-GNOME/IndicateManager.cs @@ -217,7 +217,7 @@ void OnMainWindowNotebookSwitchPage(object sender, Gtk.SwitchPageArgs e) #endif } - void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) + void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) { // we are only interested in highlights on person and group chats if (!(e.ChatView is PersonChatView) && @@ -236,7 +236,7 @@ void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs HighlightEventHandlers.Add(e.ChatView, handler); } - void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) + void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) { MessageTextViewMessageHighlightedEventHandler handler; if (!HighlightEventHandlers.TryGetValue(e.ChatView, out handler)) { diff --git a/src/Frontend-GNOME/MainWindow.cs b/src/Frontend-GNOME/MainWindow.cs index 0dfd7ea8d..85440f7dc 100644 --- a/src/Frontend-GNOME/MainWindow.cs +++ b/src/Frontend-GNOME/MainWindow.cs @@ -534,7 +534,7 @@ protected virtual void OnNotebookFocusInEvent(object sender, Gtk.FocusInEventArg Entry.GrabFocus(); } - protected void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) + protected void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) { Trace.Call(sender, e); @@ -548,14 +548,14 @@ protected void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAdde UpdateProgressBar(); } - protected void OnChatViewManagerChatSynced(object sender, ChatViewManagerChatSyncedEventArgs e) + protected void OnChatViewManagerChatSynced(object sender, ChatViewManagerChatSyncedEventArgs e) { Trace.Call(sender, e); UpdateProgressBar(); } - protected void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) + protected void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) { Trace.Call(sender, e); diff --git a/src/Frontend-GNOME/Notebook.cs b/src/Frontend-GNOME/Notebook.cs index 319e2731e..29d9414cc 100644 --- a/src/Frontend-GNOME/Notebook.cs +++ b/src/Frontend-GNOME/Notebook.cs @@ -198,6 +198,7 @@ protected virtual void OnBeforeSwitchPage(object sender, Gtk.SwitchPageArgs e) var chatView = CurrentChatView; chatView.OutputMessageTextView.UpdateMarkerline(); + chatView.OnSwitchedFrom(); } protected virtual void OnSwitchPage(object sender, Gtk.SwitchPageArgs e) @@ -214,6 +215,8 @@ protected virtual void OnSwitchPage(object sender, Gtk.SwitchPageArgs e) return; } + chatView.OnSwitchedTo(); + ChatModel chatModel = chatView.ChatModel; // clear activity and highlight diff --git a/src/Frontend-GNOME/NotifyManager.cs b/src/Frontend-GNOME/NotifyManager.cs index d8680cc24..7a2aa05a1 100644 --- a/src/Frontend-GNOME/NotifyManager.cs +++ b/src/Frontend-GNOME/NotifyManager.cs @@ -178,7 +178,7 @@ void Init() IsInitialized = true; } - void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) + void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) { // we are only interested in highlights on person and group chats if (!(e.ChatView is PersonChatView) && @@ -197,7 +197,7 @@ void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs HighlightEventHandlers.Add(e.ChatView, handler); } - void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) + void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) { MessageTextViewMessageHighlightedEventHandler handler; if (!HighlightEventHandlers.TryGetValue(e.ChatView, out handler)) { diff --git a/src/Frontend-GNOME/StatusIconManager.cs b/src/Frontend-GNOME/StatusIconManager.cs index 372f0e1c6..4e879d97c 100644 --- a/src/Frontend-GNOME/StatusIconManager.cs +++ b/src/Frontend-GNOME/StatusIconManager.cs @@ -199,12 +199,12 @@ private void OnMainWindowFocusInEvent(object sender, EventArgs e) f_StatusIcon.Blinking = false; } - protected void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) + protected void OnChatViewManagerChatAdded(object sender, ChatViewManagerChatAddedEventArgs e) { e.ChatView.MessageHighlighted += OnChatViewMessageHighlighted; } - protected void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) + protected void OnChatViewManagerChatRemoved(object sender, ChatViewManagerChatRemovedEventArgs e) { e.ChatView.MessageHighlighted -= OnChatViewMessageHighlighted; } diff --git a/src/Frontend-GNOME/Views/Chats/ChatView.cs b/src/Frontend-GNOME/Views/Chats/ChatView.cs index 32828d672..0d6ed0365 100644 --- a/src/Frontend-GNOME/Views/Chats/ChatView.cs +++ b/src/Frontend-GNOME/Views/Chats/ChatView.cs @@ -767,6 +767,14 @@ protected virtual void OnMessageTextViewPopulatePopup(object sender, Gtk.Populat popup.ShowAll(); } + public virtual void OnSwitchedTo() + { + } + + public virtual void OnSwitchedFrom() + { + } + protected virtual void OnMessageTextViewPersonClicked(object sender, MessageTextViewPersonClickedEventArgs e) { Trace.Call(sender, e); diff --git a/src/Frontend-STFL/ChatViewManager.cs b/src/Frontend-STFL/ChatViewManager.cs index 2b47ad81e..86681f015 100644 --- a/src/Frontend-STFL/ChatViewManager.cs +++ b/src/Frontend-STFL/ChatViewManager.cs @@ -32,7 +32,7 @@ namespace Smuxi.Frontend.Stfl { - public class ChatViewManager : ChatViewManagerBase + public class ChatViewManager : ChatViewManagerBase { #if LOG4NET private static readonly log4net.ILog _Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -42,12 +42,13 @@ public class ChatViewManager : ChatViewManagerBase private Dictionary f_ChatViews = new Dictionary(); private List f_ChatViewList = new List(); - public event ChatSwitchedEventHandler CurrentChatSwitched; - - public override IChatView ActiveChat { + public override ChatView ActiveChat { get { return CurrentChat; } + set { + CurrentChat = ActiveChat; + } } public ChatView CurrentChat { @@ -57,6 +58,7 @@ public ChatView CurrentChat { set { if (f_CurrentChat != null) { f_CurrentChat.IsVisible = false; + OnChatSwitchedFrom(new ChatViewManagerChatSwitchedFromEventArgs(f_CurrentChat)); } f_CurrentChat = value; @@ -71,9 +73,7 @@ public ChatView CurrentChat { UpdateTopic(); } - if (CurrentChatSwitched != null) { - CurrentChatSwitched(this, new ChatSwitchedEventArgs(f_CurrentChat)); - } + OnChatSwitchedTo(new ChatViewManagerChatSwitchedToEventArgs(f_CurrentChat)); } } @@ -107,6 +107,7 @@ public override void AddChat(ChatModel chat) ChatView chatView = (ChatView) CreateChatView(chat, f_MainWindow); f_ChatViews.Add(chat, chatView); f_ChatViewList.Add(chatView); + OnChatAdded(new ChatViewManagerChatAddedEventArgs(chatView)); if (CurrentChat == null) { CurrentChat = chatView; @@ -124,10 +125,12 @@ public override void RemoveChat(ChatModel chat) CurrentChatNumber--; } - chatView.Dispose(); f_ChatViews.Remove(chat); f_ChatViewList.Remove(chatView); + OnChatRemoved(new ChatViewManagerChatRemovedEventArgs(chatView)); + chatView.Dispose(); + UpdateNavigation(); } @@ -233,16 +236,4 @@ public void UpdateTopic() f_MainWindow.ShowTopic = !String.IsNullOrEmpty(topic); } } - - public delegate void ChatSwitchedEventHandler(object sender, ChatSwitchedEventArgs e); - - public class ChatSwitchedEventArgs : EventArgs - { - public ChatView ChatView { get; set; } - - public ChatSwitchedEventArgs(ChatView chatView) - { - ChatView = chatView; - } - } } diff --git a/src/Frontend-SWF/ChatViewManager.cs b/src/Frontend-SWF/ChatViewManager.cs index 33d1ccf13..7bd8c825c 100644 --- a/src/Frontend-SWF/ChatViewManager.cs +++ b/src/Frontend-SWF/ChatViewManager.cs @@ -36,7 +36,7 @@ namespace Smuxi.Frontend.Swf { - public class ChatViewManager : ChatViewManagerBase + public class ChatViewManager : ChatViewManagerBase { #if LOG4NET private static readonly log4net.ILog _Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -44,16 +44,28 @@ public class ChatViewManager : ChatViewManagerBase private List f_Chats = new List(); private Notebook f_Notebook; private UserConfig f_Config; - - public override IChatView ActiveChat { + + public override ChatView ActiveChat { get { return f_Notebook.CurrentChatView; } + set { + f_Notebook.CurrentChatView = value as ChatView; + } } public ChatViewManager(Notebook notebook) { f_Notebook = notebook; + f_Notebook.Selected += (sender, e) => + OnChatSwitchedTo(new ChatViewManagerChatSwitchedToEventArgs(e.TabPage as ChatView)); + f_Notebook.Selecting += delegate(object sender, System.Windows.Forms.TabControlCancelEventArgs e) { + var view = e.TabPage as ChatView; + if (view == null) { + return; + } + OnChatSwitchedFrom(new ChatViewManagerChatSwitchedFromEventArgs(view)); + }; } public override void AddChat(ChatModel chat) @@ -66,6 +78,7 @@ public override void AddChat(ChatModel chat) } f_Notebook.TabPages.Add(chatView); + OnChatAdded(new ChatViewManagerChatAddedEventArgs(chatView)); } public override void RemoveChat(ChatModel chat) @@ -73,6 +86,7 @@ public override void RemoveChat(ChatModel chat) ChatView chatView = f_Notebook.GetChat(chat); f_Notebook.TabPages.Remove(chatView); f_Chats.Remove(chatView); + OnChatRemoved(new ChatViewManagerChatRemovedEventArgs(chatView)); } public override void EnableChat(ChatModel chat) diff --git a/src/Frontend-SWF/Notebook.cs b/src/Frontend-SWF/Notebook.cs index 3d24de831..ad1c0738a 100644 --- a/src/Frontend-SWF/Notebook.cs +++ b/src/Frontend-SWF/Notebook.cs @@ -41,6 +41,9 @@ public ChatView CurrentChatView { get { return (ChatView)SelectedTab; } + set { + SelectedTab = value; + } } public Notebook() : base () diff --git a/src/Frontend-Tests/Mocks/MockProtocolManager.cs b/src/Frontend-Tests/Mocks/MockProtocolManager.cs index 309c7349b..e54a8ba1f 100644 --- a/src/Frontend-Tests/Mocks/MockProtocolManager.cs +++ b/src/Frontend-Tests/Mocks/MockProtocolManager.cs @@ -109,6 +109,11 @@ public void CloseChat(FrontendManager frontman, ChatModel chat) { public void SetPresenceStatus(PresenceStatus status, string message) { } + public void SetChatState(FrontendManager fm, ChatModel chat, + ChatState state) + { + } + public void Dispose() { } } diff --git a/src/Frontend/ChatViewManagerBase.cs b/src/Frontend/ChatViewManagerBase.cs index 3bd512167..25c191782 100644 --- a/src/Frontend/ChatViewManagerBase.cs +++ b/src/Frontend/ChatViewManagerBase.cs @@ -35,16 +35,21 @@ namespace Smuxi.Frontend { - public abstract class ChatViewManagerBase + + public abstract class ChatViewManagerBase where ChatViewType : IChatView { #if LOG4NET private static readonly log4net.ILog _Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endif private IDictionary _ChatViewTypes = new Dictionary(); - public abstract IChatView ActiveChat { - get; - } + public abstract ChatViewType ActiveChat { get; set; } + + public event EventHandler> ChatAdded; + public event EventHandler> ChatRemoved; + public event EventHandler> ChatSynced; + public event EventHandler> ChatSwitchedTo; + public event EventHandler> ChatSwitchedFrom; protected ChatViewManagerBase() { @@ -54,7 +59,42 @@ protected ChatViewManagerBase() public abstract void RemoveChat(ChatModel chat); public abstract void EnableChat(ChatModel chat); public abstract void DisableChat(ChatModel chat); - + + protected virtual void OnChatAdded(ChatViewManagerChatAddedEventArgs e) + { + if (ChatAdded != null) { + ChatAdded(this, e); + } + } + + protected virtual void OnChatRemoved(ChatViewManagerChatRemovedEventArgs e) + { + if (ChatRemoved != null) { + ChatRemoved(this, e); + } + } + + protected virtual void OnChatSynced(ChatViewManagerChatSyncedEventArgs e) + { + if (ChatSynced != null) { + ChatSynced(this, e); + } + } + + protected virtual void OnChatSwitchedTo(ChatViewManagerChatSwitchedToEventArgs e) + { + if (ChatSwitchedTo != null) { + ChatSwitchedTo(this, e); + } + } + + protected virtual void OnChatSwitchedFrom(ChatViewManagerChatSwitchedFromEventArgs e) + { + if (ChatSwitchedFrom != null) { + ChatSwitchedFrom(this, e); + } + } + private Type _GetChatViewType(ChatType chatType, Type protocolManagerType) { foreach (ChatViewInfoAttribute info in _ChatViewTypes.Keys) { @@ -171,4 +211,54 @@ public void Load(Assembly assembly) } } } + + public class ChatViewManagerChatAddedEventArgs : EventArgs where T : IChatView + { + public T ChatView { get; private set; } + + public ChatViewManagerChatAddedEventArgs(T chatView) + { + ChatView = chatView; + } + } + + public class ChatViewManagerChatRemovedEventArgs : EventArgs where T : IChatView + { + public T ChatView { get; private set; } + + public ChatViewManagerChatRemovedEventArgs(T chatView) + { + ChatView = chatView; + } + } + + public class ChatViewManagerChatSyncedEventArgs : EventArgs where T : IChatView + { + public T ChatView { get; private set; } + + public ChatViewManagerChatSyncedEventArgs(T chatView) + { + ChatView = chatView; + } + } + + public class ChatViewManagerChatSwitchedToEventArgs : EventArgs where T : IChatView + { + public T ChatView { get; private set; } + + public ChatViewManagerChatSwitchedToEventArgs(T chatView) + { + ChatView = chatView; + } + } + + public class ChatViewManagerChatSwitchedFromEventArgs : EventArgs where T : IChatView + { + public T ChatView { get; private set; } + + public ChatViewManagerChatSwitchedFromEventArgs(T chatView) + { + ChatView = chatView; + } + } }