-// \r
-// Radegast Metaverse Client\r
-// Copyright (c) 2009, Radegast Development Team\r
-// All rights reserved.\r
-// \r
-// Redistribution and use in source and binary forms, with or without\r
-// modification, are permitted provided that the following conditions are met:\r
-// \r
-// * Redistributions of source code must retain the above copyright notice,\r
-// this list of conditions and the following disclaimer.\r
-// * Redistributions in binary form must reproduce the above copyright\r
-// notice, this list of conditions and the following disclaimer in the\r
-// documentation and/or other materials provided with the distribution.\r
-// * Neither the name of the application "Radegast", nor the names of its\r
-// contributors may be used to endorse or promote products derived from\r
-// this software without specific prior written permission.\r
-// \r
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-//\r
-// $Id$\r
-//\r
-using System;\r
-using System.Collections.Generic;\r
-using System.ComponentModel;\r
-using System.Drawing;\r
-using System.Windows.Forms;\r
-using Radegast.Netcom;\r
-using OpenMetaverse;\r
-\r
-namespace Radegast\r
-{\r
- public partial class TabsConsole : UserControl\r
- {\r
- /// <summary>\r
- /// Delegate inviked on tab operations\r
- /// </summary>\r
- /// <param name="sender">Event sender</param>\r
- /// <param name="e">Event arguments</param>\r
- public delegate void TabCallback(object sender, TabEventArgs e);\r
-\r
- /// <summary>\r
- /// Fired when a tab is selected\r
- /// </summary>\r
- public event TabCallback OnTabSelected;\r
-\r
- /// <summary>\r
- /// Fired when a new tab is added\r
- /// </summary>\r
- public event TabCallback OnTabAdded;\r
-\r
- /// <summary>\r
- /// Fired when a tab is removed\r
- /// </summary>\r
- public event TabCallback OnTabRemoved;\r
-\r
- private RadegastInstance instance;\r
- private GridClient client { get { return instance.Client; } }\r
- private RadegastNetcom netcom { get { return instance.Netcom; } }\r
- private ChatTextManager mainChatManger;\r
-\r
- private Dictionary<string, RadegastTab> tabs = new Dictionary<string, RadegastTab>();\r
- public Dictionary<string, RadegastTab> Tabs { get { return tabs; } }\r
-\r
- private ChatConsole chatConsole;\r
-\r
- private RadegastTab selectedTab;\r
-\r
- /// <summary>\r
- /// Currently selected tab\r
- /// </summary>\r
- public RadegastTab SelectedTab\r
- {\r
- get\r
- {\r
- return selectedTab;\r
- }\r
- }\r
-\r
- private Form owner;\r
-\r
- public TabsConsole(RadegastInstance instance)\r
- {\r
- InitializeComponent();\r
- Disposed += new EventHandler(TabsConsole_Disposed);\r
-\r
- this.instance = instance;\r
- this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
-\r
- AddNetcomEvents();\r
-\r
- InitializeMainTab();\r
- InitializeChatTab();\r
-\r
- // Callbacks\r
- RegisterClientEvents(client);\r
- }\r
-\r
- private void RegisterClientEvents(GridClient client)\r
- {\r
- client.Self.ScriptQuestion += new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);\r
- client.Self.ScriptDialog += new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);\r
- }\r
-\r
- private void UnregisterClientEvents(GridClient client)\r
- {\r
- client.Self.ScriptQuestion -= new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);\r
- client.Self.ScriptDialog -= new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);\r
- }\r
-\r
- void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
- {\r
- UnregisterClientEvents(e.OldClient);\r
- RegisterClientEvents(client);\r
- }\r
-\r
- void TabsConsole_Disposed(object sender, EventArgs e)\r
- {\r
- RemoveNetcomEvents();\r
- UnregisterClientEvents(client);\r
- }\r
-\r
- private void AddNetcomEvents()\r
- {\r
- netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
- netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);\r
- netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
- netcom.ChatReceived += new EventHandler<ChatEventArgs>(netcom_ChatReceived);\r
- netcom.ChatSent += new EventHandler<ChatSentEventArgs>(netcom_ChatSent);\r
- netcom.AlertMessageReceived += new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);\r
- netcom.InstantMessageReceived += new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);\r
- }\r
-\r
- private void RemoveNetcomEvents()\r
- {\r
- netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
- netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);\r
- netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
- netcom.ChatReceived -= new EventHandler<ChatEventArgs>(netcom_ChatReceived);\r
- netcom.ChatSent -= new EventHandler<ChatSentEventArgs>(netcom_ChatSent);\r
- netcom.AlertMessageReceived -= new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);\r
- netcom.InstantMessageReceived -= new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);\r
- }\r
-\r
- void Self_ScriptDialog(object sender, ScriptDialogEventArgs e)\r
- {\r
- instance.MainForm.AddNotification(new ntfScriptDialog(instance, e.Message, e.ObjectName, e.ImageID, e.ObjectID, e.FirstName, e.LastName, e.Channel, e.ButtonLabels));\r
- }\r
-\r
- void Self_ScriptQuestion(object sender, ScriptQuestionEventArgs e)\r
- {\r
- instance.MainForm.AddNotification(new ntfPermissions(instance, e.Simulator, e.TaskID, e.ItemID, e.ObjectName, e.ObjectOwnerName, e.Questions));\r
- }\r
-\r
- private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)\r
- {\r
- if (e.Status == LoginStatus.Failed)\r
- {\r
- DisplayNotificationInChat("Login error: " + e.Message, ChatBufferTextStyle.Error);\r
- }\r
- else if (e.Status == LoginStatus.Success)\r
- {\r
- DisplayNotificationInChat("Logged in as " + netcom.LoginOptions.FullName + ".", ChatBufferTextStyle.StatusDarkBlue);\r
- DisplayNotificationInChat("Login reply: " + e.Message, ChatBufferTextStyle.StatusDarkBlue);\r
-\r
- InitializeOnlineTabs();\r
-\r
- if (tabs.ContainsKey("login"))\r
- {\r
- if (selectedTab.Name == "login")\r
- tabs["chat"].Select();\r
- ForceCloseTab("login");\r
- }\r
-\r
- client.Self.RetrieveInstantMessages();\r
- }\r
- }\r
-\r
- private void netcom_ClientLoggedOut(object sender, EventArgs e)\r
- {\r
- DisposeOnlineTabs();\r
-\r
- tabs["chat"].Select();\r
- DisplayNotificationInChat("Logged out.");\r
-\r
- }\r
-\r
- private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)\r
- {\r
- if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;\r
-\r
- DisposeOnlineTabs();\r
-\r
- tabs["chat"].Select();\r
- DisplayNotificationInChat("Disconnected: " + e.Message, ChatBufferTextStyle.Error);\r
- }\r
-\r
- private void netcom_AlertMessageReceived(object sender, AlertMessageEventArgs e)\r
- {\r
- tabs["chat"].Highlight();\r
- }\r
-\r
- private void netcom_ChatSent(object sender, ChatSentEventArgs e)\r
- {\r
- tabs["chat"].Highlight();\r
- }\r
-\r
- private void netcom_ChatReceived(object sender, ChatEventArgs e)\r
- {\r
- if (string.IsNullOrEmpty(e.Message)) return;\r
-\r
- tabs["chat"].Highlight();\r
- }\r
-\r
- private void netcom_InstantMessageReceived(object sender, InstantMessageEventArgs e)\r
- {\r
- switch (e.IM.Dialog)\r
- {\r
- case InstantMessageDialog.SessionSend:\r
- if (instance.Groups.ContainsKey(e.IM.IMSessionID))\r
- {\r
- HandleGroupIM(e);\r
- }\r
- else\r
- {\r
- HandleConferenceIM(e);\r
- }\r
- break;\r
-\r
- case InstantMessageDialog.MessageFromAgent:\r
- if (e.IM.FromAgentName == "Second Life")\r
- {\r
- HandleIMFromObject(e);\r
- }\r
- else if (e.IM.GroupIM || instance.Groups.ContainsKey(e.IM.IMSessionID))\r
- {\r
- HandleGroupIM(e);\r
- }\r
- else if (e.IM.BinaryBucket.Length > 1)\r
- { // conference\r
- HandleConferenceIM(e);\r
- }\r
- else\r
- {\r
- HandleIM(e);\r
- }\r
- break;\r
-\r
- case InstantMessageDialog.MessageFromObject:\r
- HandleIMFromObject(e);\r
- break;\r
-\r
- case InstantMessageDialog.StartTyping:\r
- if (TabExists(e.IM.FromAgentName))\r
- {\r
- RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];\r
- if (!tab.Highlighted) tab.PartialHighlight();\r
- }\r
-\r
- break;\r
-\r
- case InstantMessageDialog.StopTyping:\r
- if (TabExists(e.IM.FromAgentName))\r
- {\r
- RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];\r
- if (!tab.Highlighted) tab.Unhighlight();\r
- }\r
-\r
- break;\r
-\r
- case InstantMessageDialog.MessageBox:\r
- instance.MainForm.AddNotification(new ntfGeneric(instance, e.IM.Message));\r
- break;\r
-\r
- case InstantMessageDialog.RequestTeleport:\r
- instance.MainForm.AddNotification(new ntfTeleport(instance, e.IM));\r
- break;\r
-\r
- case InstantMessageDialog.GroupInvitation:\r
- instance.MainForm.AddNotification(new ntfGroupInvitation(instance, e.IM));\r
- break;\r
-\r
- case InstantMessageDialog.FriendshipOffered:\r
- instance.MainForm.AddNotification(new ntfFriendshipOffer(instance, e.IM));\r
- break;\r
-\r
- case InstantMessageDialog.InventoryAccepted:\r
- DisplayNotificationInChat(e.IM.FromAgentName + " accepted your inventory offer.");\r
- break;\r
-\r
- case InstantMessageDialog.GroupNotice:\r
- instance.MainForm.AddNotification(new ntfGroupNotice(instance, e.IM));\r
- break;\r
-\r
- case InstantMessageDialog.InventoryOffered:\r
- case InstantMessageDialog.TaskInventoryOffered:\r
- instance.MainForm.AddNotification(new ntfInventoryOffer(instance, e.IM));\r
- break;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Displays notification in the main chat tab\r
- /// </summary>\r
- /// <param name="msg">Message to be printed in the chat tab</param>\r
- public void DisplayNotificationInChat(string msg)\r
- {\r
- DisplayNotificationInChat(msg, ChatBufferTextStyle.ObjectChat);\r
- }\r
-\r
- /// <summary>\r
- /// Displays notification in the main chat tab\r
- /// </summary>\r
- /// <param name="msg">Message to be printed in the chat tab</param>\r
- /// <param name="style">Style of the message to be printed, normal, object, etc.</param>\r
- public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate()\r
- {\r
- DisplayNotificationInChat(msg, style);\r
- }));\r
- return;\r
- }\r
-\r
- ChatBufferItem line = new ChatBufferItem(\r
- DateTime.Now,\r
- msg,\r
- style\r
- );\r
- try\r
- {\r
- mainChatManger.ProcessBufferItem(line, true);\r
- tabs["chat"].Highlight();\r
- }\r
- catch (Exception) { }\r
- }\r
-\r
- private void HandleIMFromObject(InstantMessageEventArgs e)\r
- {\r
- DisplayNotificationInChat(e.IM.FromAgentName + ": " + e.IM.Message);\r
- }\r
-\r
- private void HandleIM(InstantMessageEventArgs e)\r
- {\r
- if (TabExists(e.IM.IMSessionID.ToString()))\r
- {\r
- RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
- if (!tab.Selected) tab.Highlight();\r
- return;\r
- }\r
-\r
- IMTabWindow imTab = AddIMTab(e);\r
- tabs[e.IM.IMSessionID.ToString()].Highlight();\r
- }\r
-\r
- private void HandleConferenceIM(InstantMessageEventArgs e)\r
- {\r
- if (TabExists(e.IM.IMSessionID.ToString()))\r
- {\r
- RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
- if (!tab.Selected) tab.Highlight();\r
- return;\r
- }\r
-\r
- ConferenceIMTabWindow imTab = AddConferenceIMTab(e);\r
- tabs[e.IM.IMSessionID.ToString()].Highlight();\r
- }\r
-\r
- private void HandleGroupIM(InstantMessageEventArgs e)\r
- {\r
- if (TabExists(e.IM.IMSessionID.ToString()))\r
- {\r
- RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
- if (!tab.Selected) tab.Highlight();\r
- return;\r
- }\r
-\r
- GroupIMTabWindow imTab = AddGroupIMTab(e);\r
- tabs[e.IM.IMSessionID.ToString()].Highlight();\r
- }\r
-\r
- private void InitializeMainTab()\r
- {\r
- LoginConsole loginConsole = new LoginConsole(instance);\r
-\r
- RadegastTab tab = AddTab("login", "Login", loginConsole);\r
- tab.AllowClose = false;\r
- tab.AllowDetach = false;\r
- tab.AllowMerge = false;\r
- tab.AllowHide = false;\r
-\r
- loginConsole.RegisterTab(tab);\r
- }\r
-\r
- private void InitializeChatTab()\r
- {\r
- chatConsole = new ChatConsole(instance);\r
- mainChatManger = chatConsole.ChatManager;\r
-\r
- RadegastTab tab = AddTab("chat", "Chat", chatConsole);\r
- tab.AllowClose = false;\r
- tab.AllowDetach = false;\r
- tab.AllowHide = false;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// Create Tabs that only make sense when connected\r
- /// </summary>\r
- private void InitializeOnlineTabs()\r
- {\r
- RadegastTab tab = AddTab("friends", "Friends", new FriendsConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
-\r
- tab = AddTab("groups", "Groups", new GroupsConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
-\r
- tab = AddTab("inventory", "Inventory", new InventoryConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
-\r
- tab = AddTab("search", "Search", new SearchConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
-\r
- if (!TabExists("map"))\r
- {\r
- tab = AddTab("map", "Map", new MapConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
- }\r
-\r
- tab = AddTab("voice", "Voice", new VoiceConsole(instance));\r
- tab.AllowClose = false;\r
- tab.AllowDetach = true;\r
- tab.Visible = false;\r
- }\r
-\r
- /// <summary>\r
- /// Close tabs that make no sense when not connected\r
- /// </summary>\r
- private void DisposeOnlineTabs()\r
- {\r
- ForceCloseTab("voice");\r
-\r
- // Mono crashes if we try to open map for the second time\r
- if (!instance.MonoRuntime)\r
- ForceCloseTab("map");\r
- else\r
- tabs["map"].Hide();\r
-\r
- ForceCloseTab("search");\r
- ForceCloseTab("inventory");\r
- ForceCloseTab("groups");\r
- ForceCloseTab("friends");\r
- }\r
-\r
- private void ForceCloseTab(string name)\r
- {\r
- if (!TabExists(name)) return;\r
-\r
- RadegastTab tab = tabs[name];\r
- if (tab.Merged) SplitTab(tab);\r
-\r
- tab.AllowClose = true;\r
- tab.Close();\r
- tab = null;\r
- }\r
-\r
-\r
- public void RegisterContextAction(Type libomvType, String label, EventHandler handler)\r
- {\r
- instance.ContextActionManager.RegisterContextAction(libomvType, label, handler);\r
- }\r
-\r
- public void RegisterContextAction(ContextAction handler)\r
- {\r
- instance.ContextActionManager.RegisterContextAction(handler);\r
- }\r
-\r
- public void AddTab(RadegastTab tab)\r
- {\r
- ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(tab.Label);\r
- button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;\r
- button.Image = null;\r
- button.AutoToolTip = false;\r
- button.Tag = tab.Name;\r
- button.Click += new EventHandler(TabButtonClick);\r
- tab.Button = button;\r
- tabs.Add(tab.Name, tab);\r
-\r
- if (OnTabAdded != null)\r
- {\r
- try { OnTabAdded(this, new TabEventArgs(tab)); }\r
- catch (Exception) { }\r
- }\r
- }\r
-\r
- public RadegastTab AddTab(string name, string label, Control control)\r
- {\r
- // WORKAROUND: one should never add tab that alrady exists\r
- // but under some weird conditions disconnect/connect\r
- // fire in the wrong order\r
- if (TabExists(name))\r
- {\r
- Logger.Log("Force closing tab '" + name + "'", Helpers.LogLevel.Warning, client);\r
- ForceCloseTab(name);\r
- }\r
-\r
- control.Visible = false;\r
- control.Dock = DockStyle.Fill;\r
- toolStripContainer1.ContentPanel.Controls.Add(control);\r
-\r
- ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(label);\r
- button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;\r
- button.Image = null;\r
- button.AutoToolTip = false;\r
- button.Tag = name.ToLower();\r
- button.Click += new EventHandler(TabButtonClick);\r
-\r
- RadegastTab tab = new RadegastTab(instance, button, control, name.ToLower(), label);\r
- tab.TabAttached += new EventHandler(tab_TabAttached);\r
- tab.TabDetached += new EventHandler(tab_TabDetached);\r
- tab.TabSelected += new EventHandler(tab_TabSelected);\r
- tab.TabClosed += new EventHandler(tab_TabClosed);\r
- tab.TabHidden += new EventHandler(tab_TabHidden);\r
- tabs.Add(name.ToLower(), tab);\r
-\r
- if (OnTabAdded != null)\r
- {\r
- try { OnTabAdded(this, new TabEventArgs(tab)); }\r
- catch (Exception) { }\r
- }\r
-\r
- return tab;\r
- }\r
-\r
- private void tab_TabAttached(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = (RadegastTab)sender;\r
- tab.Select();\r
- }\r
-\r
- private void tab_TabDetached(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = (RadegastTab)sender;\r
- frmDetachedTab form = (frmDetachedTab)tab.Owner;\r
-\r
- form.ReattachStrip = tstTabs;\r
- form.ReattachContainer = toolStripContainer1.ContentPanel;\r
- }\r
-\r
- private void tab_TabSelected(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = (RadegastTab)sender;\r
-\r
- if (selectedTab != null &&\r
- selectedTab != tab)\r
- { selectedTab.Deselect(); }\r
-\r
- selectedTab = tab;\r
-\r
- tbtnCloseTab.Enabled = tab.AllowClose || tab.AllowHide;\r
- owner.AcceptButton = tab.DefaultControlButton;\r
-\r
- if (OnTabSelected != null)\r
- {\r
- try { OnTabSelected(this, new TabEventArgs(selectedTab)); }\r
- catch (Exception) { }\r
- }\r
- }\r
-\r
- void tab_TabHidden(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = (RadegastTab)sender;\r
-\r
- if (selectedTab != null && selectedTab == tab)\r
- {\r
- tab.Deselect();\r
- tabs["chat"].Select();\r
- }\r
- }\r
-\r
- private void tab_TabClosed(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = (RadegastTab)sender;\r
-\r
- if (selectedTab != null && selectedTab == tab)\r
- {\r
- tab.Deselect();\r
- tabs["chat"].Select();\r
- }\r
-\r
- tabs.Remove(tab.Name);\r
-\r
- if (OnTabRemoved != null)\r
- {\r
- try { OnTabRemoved(this, new TabEventArgs(tab)); }\r
- catch (Exception) { }\r
- }\r
-\r
- tab = null;\r
- }\r
-\r
- private void TabButtonClick(object sender, EventArgs e)\r
- {\r
- ToolStripButton button = (ToolStripButton)sender;\r
-\r
- RadegastTab tab = tabs[button.Tag.ToString()];\r
- tab.Select();\r
- }\r
-\r
- public void RemoveTabEntry(RadegastTab tab)\r
- {\r
- if (tstTabs.Items.Contains(tab.Button))\r
- {\r
- tstTabs.Items.Remove(tab.Button);\r
- }\r
-\r
- tab.Button.Dispose();\r
- tabs.Remove(tab.Name);\r
- }\r
-\r
- public void RemoveTab(string name)\r
- {\r
- if (tabs.ContainsKey(name))\r
- {\r
- tabs.Remove(name);\r
- }\r
- }\r
-\r
- //Used for outside classes that have a reference to TabsConsole\r
- public void SelectTab(string name)\r
- {\r
- tabs[name.ToLower()].Select();\r
- }\r
-\r
- public bool TabExists(string name)\r
- {\r
- return tabs.ContainsKey(name.ToLower());\r
- }\r
-\r
- public RadegastTab GetTab(string name)\r
- {\r
- return tabs[name.ToLower()];\r
- }\r
-\r
- public List<RadegastTab> GetOtherTabs()\r
- {\r
- List<RadegastTab> otherTabs = new List<RadegastTab>();\r
-\r
- foreach (ToolStripItem item in tstTabs.Items)\r
- {\r
- if (item.Tag == null) continue;\r
- if ((ToolStripItem)item == selectedTab.Button) continue;\r
-\r
- RadegastTab tab = tabs[item.Tag.ToString()];\r
- if (!tab.AllowMerge) continue;\r
- if (tab.Merged) continue;\r
-\r
- otherTabs.Add(tab);\r
- }\r
-\r
- return otherTabs;\r
- }\r
-\r
- /// <summary>\r
- /// Activates the next tab\r
- /// </summary>\r
- public void SelectNextTab()\r
- {\r
- List<ToolStripItem> buttons = new List<ToolStripItem>();\r
-\r
- foreach (ToolStripItem item in tstTabs.Items)\r
- {\r
- if (item.Tag == null || !item.Visible) continue;\r
-\r
- buttons.Add(item);\r
- }\r
-\r
- int current = 0;\r
-\r
- for (int i = 0; i < buttons.Count; i++)\r
- {\r
- if (buttons[i] == selectedTab.Button)\r
- {\r
- current = i;\r
- break;\r
- }\r
- }\r
-\r
- current++;\r
-\r
- if (current == buttons.Count)\r
- current = 0;\r
-\r
- SelectTab(tabs[buttons[current].Tag.ToString()].Name);\r
- }\r
-\r
- /// <summary>\r
- /// Activates the previous tab\r
- /// </summary>\r
- public void SelectPreviousTab()\r
- {\r
- List<ToolStripItem> buttons = new List<ToolStripItem>();\r
-\r
- foreach (ToolStripItem item in tstTabs.Items)\r
- {\r
- if (item.Tag == null || !item.Visible) continue;\r
-\r
- buttons.Add(item);\r
- }\r
-\r
- int current = 0;\r
-\r
- for (int i = 0; i < buttons.Count; i++)\r
- {\r
- if (buttons[i] == selectedTab.Button)\r
- {\r
- current = i;\r
- break;\r
- }\r
- }\r
-\r
- current--;\r
-\r
- if (current == -1)\r
- current = buttons.Count - 1;\r
-\r
- SelectTab(tabs[buttons[current].Tag.ToString()].Name);\r
- }\r
-\r
-\r
- public IMTabWindow AddIMTab(UUID target, UUID session, string targetName)\r
- {\r
- IMTabWindow imTab = new IMTabWindow(instance, target, session, targetName);\r
-\r
- RadegastTab tab = AddTab(session.ToString(), "IM: " + targetName, imTab);\r
- imTab.SelectIMInput();\r
- tab.Highlight();\r
-\r
- return imTab;\r
- }\r
-\r
- public ConferenceIMTabWindow AddConferenceIMTab(UUID session, string name)\r
- {\r
- ConferenceIMTabWindow imTab = new ConferenceIMTabWindow(instance, session, name);\r
-\r
- RadegastTab tab = AddTab(session.ToString(), name, imTab);\r
- imTab.SelectIMInput();\r
-\r
- return imTab;\r
- }\r
-\r
-\r
- public ConferenceIMTabWindow AddConferenceIMTab(InstantMessageEventArgs e)\r
- {\r
- ConferenceIMTabWindow imTab = AddConferenceIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));\r
- imTab.TextManager.ProcessIM(e);\r
- return imTab;\r
- }\r
-\r
- public GroupIMTabWindow AddGroupIMTab(UUID session, string name)\r
- {\r
- GroupIMTabWindow imTab = new GroupIMTabWindow(instance, session, name);\r
-\r
- RadegastTab tab = AddTab(session.ToString(), name, imTab);\r
- imTab.SelectIMInput();\r
-\r
- return imTab;\r
- }\r
-\r
- public GroupIMTabWindow AddGroupIMTab(InstantMessageEventArgs e)\r
- {\r
- GroupIMTabWindow imTab = AddGroupIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));\r
- imTab.TextManager.ProcessIM(e);\r
- return imTab;\r
- }\r
-\r
- public IMTabWindow AddIMTab(InstantMessageEventArgs e)\r
- {\r
- IMTabWindow imTab = AddIMTab(e.IM.FromAgentID, e.IM.IMSessionID, e.IM.FromAgentName);\r
- imTab.TextManager.ProcessIM(e);\r
- return imTab;\r
- }\r
-\r
- public OutfitTextures AddOTTab(Avatar avatar)\r
- {\r
- OutfitTextures otTab = new OutfitTextures(instance, avatar);\r
-\r
- RadegastTab tab = AddTab("OT: " + avatar.Name, "OT: " + avatar.Name, otTab);\r
- otTab.GetTextures();\r
- return otTab;\r
- }\r
-\r
- public MasterTab AddMSTab(Avatar avatar)\r
- {\r
- MasterTab msTab = new MasterTab(instance, avatar);\r
-\r
- RadegastTab tab = AddTab("MS: " + avatar.Name, "MS: " + avatar.Name, msTab);\r
- return msTab;\r
- }\r
-\r
- public AttachmentTab AddATTab(Avatar avatar)\r
- {\r
- AttachmentTab atTab = new AttachmentTab(instance, avatar);\r
-\r
- RadegastTab tab = AddTab("AT: " + avatar.Name, "AT: " + avatar.Name, atTab);\r
- return atTab;\r
- }\r
-\r
- public AnimTab AddAnimTab(Avatar avatar)\r
- {\r
- AnimTab animTab = new AnimTab(instance, avatar);\r
-\r
- RadegastTab tab = AddTab("Anim: " + avatar.Name, "Anim: " + avatar.Name, animTab);\r
- return animTab;\r
- }\r
-\r
- private void tbtnTabOptions_Click(object sender, EventArgs e)\r
- {\r
- tmnuMergeWith.Enabled = selectedTab.AllowMerge;\r
- tmnuDetachTab.Enabled = selectedTab.AllowDetach;\r
-\r
- tmnuMergeWith.DropDown.Items.Clear();\r
-\r
- if (!selectedTab.AllowMerge) return;\r
- if (!selectedTab.Merged)\r
- {\r
- tmnuMergeWith.Text = "Merge With";\r
-\r
- List<RadegastTab> otherTabs = GetOtherTabs();\r
-\r
- tmnuMergeWith.Enabled = (otherTabs.Count > 0);\r
- if (!tmnuMergeWith.Enabled) return;\r
-\r
- foreach (RadegastTab tab in otherTabs)\r
- {\r
- ToolStripItem item = tmnuMergeWith.DropDown.Items.Add(tab.Label);\r
- item.Tag = tab.Name;\r
- item.Click += new EventHandler(MergeItemClick);\r
- }\r
- }\r
- else\r
- {\r
- tmnuMergeWith.Text = "Split";\r
- tmnuMergeWith.Click += new EventHandler(SplitClick);\r
- }\r
- }\r
-\r
- private void MergeItemClick(object sender, EventArgs e)\r
- {\r
- ToolStripItem item = (ToolStripItem)sender;\r
- RadegastTab tab = tabs[item.Tag.ToString()];\r
-\r
- selectedTab.MergeWith(tab);\r
-\r
- SplitContainer container = (SplitContainer)selectedTab.Control;\r
- toolStripContainer1.ContentPanel.Controls.Add(container);\r
-\r
- selectedTab.Select();\r
- RemoveTabEntry(tab);\r
-\r
- tabs.Add(tab.Name, selectedTab);\r
- }\r
-\r
- private void SplitClick(object sender, EventArgs e)\r
- {\r
- SplitTab(selectedTab);\r
- selectedTab.Select();\r
- }\r
-\r
- public void SplitTab(RadegastTab tab)\r
- {\r
- RadegastTab otherTab = tab.Split();\r
- if (otherTab == null) return;\r
-\r
- toolStripContainer1.ContentPanel.Controls.Add(tab.Control);\r
- toolStripContainer1.ContentPanel.Controls.Add(otherTab.Control);\r
-\r
- tabs.Remove(otherTab.Name);\r
- AddTab(otherTab);\r
- }\r
-\r
- private void tmnuDetachTab_Click(object sender, EventArgs e)\r
- {\r
- if (!selectedTab.AllowDetach) return;\r
- RadegastTab tab = selectedTab;\r
- tabs["chat"].Select();\r
- tab.Detach(instance);\r
- }\r
-\r
- private void tbtnCloseTab_Click(object sender, EventArgs e)\r
- {\r
- RadegastTab tab = selectedTab;\r
- if (tab.AllowClose)\r
- tab.Close();\r
- else if (tab.AllowHide)\r
- tab.Hide();\r
- }\r
-\r
- private void TabsConsole_Load(object sender, EventArgs e)\r
- {\r
- owner = this.FindForm();\r
- }\r
-\r
- private void ctxTabs_Opening(object sender, CancelEventArgs e)\r
- {\r
- Point pt = this.PointToClient(Cursor.Position);\r
- ToolStripItem stripItem = tstTabs.GetItemAt(pt);\r
-\r
- if (stripItem == null)\r
- {\r
- e.Cancel = true;\r
- }\r
- else\r
- {\r
- tabs[stripItem.Tag.ToString()].Select();\r
-\r
- ctxBtnClose.Enabled = selectedTab.AllowClose || selectedTab.AllowHide;\r
- ctxBtnDetach.Enabled = selectedTab.AllowDetach;\r
- ctxBtnMerge.Enabled = selectedTab.AllowMerge;\r
- ctxBtnMerge.DropDown.Items.Clear();\r
-\r
- if (!ctxBtnClose.Enabled && !ctxBtnDetach.Enabled && !ctxBtnMerge.Enabled)\r
- {\r
- e.Cancel = true;\r
- return;\r
- }\r
-\r
- if (!selectedTab.AllowMerge) return;\r
- if (!selectedTab.Merged)\r
- {\r
- ctxBtnMerge.Text = "Merge With";\r
-\r
- List<RadegastTab> otherTabs = GetOtherTabs();\r
-\r
- ctxBtnMerge.Enabled = (otherTabs.Count > 0);\r
- if (!ctxBtnMerge.Enabled) return;\r
-\r
- foreach (RadegastTab tab in otherTabs)\r
- {\r
- ToolStripItem item = ctxBtnMerge.DropDown.Items.Add(tab.Label);\r
- item.Tag = tab.Name;\r
- item.Click += new EventHandler(MergeItemClick);\r
- }\r
- }\r
- else\r
- {\r
- ctxBtnMerge.Text = "Split";\r
- ctxBtnMerge.Click += new EventHandler(SplitClick);\r
- }\r
-\r
- }\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// Arguments for tab events\r
- /// </summary>\r
- public class TabEventArgs : EventArgs\r
- {\r
- /// <summary>\r
- /// Tab that was manipulated in the event\r
- /// </summary>\r
- public RadegastTab Tab;\r
-\r
- public TabEventArgs()\r
- : base()\r
- {\r
- }\r
-\r
- public TabEventArgs(RadegastTab tab)\r
- : base()\r
- {\r
- Tab = tab;\r
- }\r
- }\r
-}\r
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using Radegast.Netcom;
+using OpenMetaverse;
+
+namespace Radegast
+{
+ public partial class TabsConsole : UserControl
+ {
+
+ /// <summary>
+ /// List of nearby avatars (radar data)
+ /// </summary>
+ public List<NearbyAvatar> NearbyAvatars
+ {
+ get
+ {
+ List<NearbyAvatar> res = new List<NearbyAvatar>();
+
+ if (TabExists("chat"))
+ {
+ ChatConsole c = (ChatConsole)Tabs["chat"].Control;
+ lock (c.agentSimHandle)
+ {
+ foreach (ListViewItem item in c.lvwObjects.Items)
+ {
+ if (item.Name != client.Self.AgentID.ToString())
+ {
+ res.Add(new NearbyAvatar() { ID = new UUID(item.Name), Name = item.Text });
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+ }
+
+ /// <summary>
+ /// Delegate invoked on tab operations
+ /// </summary>
+ /// <param name="sender">Event sender</param>
+ /// <param name="e">Event arguments</param>
+ public delegate void TabCallback(object sender, TabEventArgs e);
+
+ /// <summary>
+ /// Fired when a tab is selected
+ /// </summary>
+ public event TabCallback OnTabSelected;
+
+
+ /// <summary>
+ /// Delegate invoked when chat notification is printed
+ /// </summary>
+ /// <param name="sender">Event sender</param>
+ /// <param name="e">Event arguments</param>
+ public delegate void ChatNotificationCallback(object sender, ChatNotificationEventArgs e);
+
+ /// <summary>
+ /// Fired when a tab is selected
+ /// </summary>
+ public event ChatNotificationCallback OnChatNotification;
+
+ /// <summary>
+ /// Fired when a new tab is added
+ /// </summary>
+ public event TabCallback OnTabAdded;
+
+ /// <summary>
+ /// Fired when a tab is removed
+ /// </summary>
+ public event TabCallback OnTabRemoved;
+
+ private RadegastInstance instance;
+ private GridClient client { get { return instance.Client; } }
+ private RadegastNetcom netcom { get { return instance.Netcom; } }
+ private ChatTextManager mainChatManger;
+ public ChatTextManager MainChatManger { get { return mainChatManger; } }
+
+ private Dictionary<string, RadegastTab> tabs = new Dictionary<string, RadegastTab>();
+ public Dictionary<string, RadegastTab> Tabs { get { return tabs; } }
+
+ private ChatConsole chatConsole;
+
+ private RadegastTab selectedTab;
+
+ /// <summary>
+ /// Currently selected tab
+ /// </summary>
+ public RadegastTab SelectedTab
+ {
+ get
+ {
+ return selectedTab;
+ }
+ }
+
+ private Form owner;
+
+ public TabsConsole(RadegastInstance instance)
+ {
+ InitializeComponent();
+ Disposed += new EventHandler(TabsConsole_Disposed);
+
+ this.instance = instance;
+ this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
+
+ AddNetcomEvents();
+
+ InitializeMainTab();
+ InitializeChatTab();
+
+ // Callbacks
+ RegisterClientEvents(client);
+ }
+
+ private void RegisterClientEvents(GridClient client)
+ {
+ client.Self.ScriptQuestion += new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);
+ client.Self.ScriptDialog += new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);
+ client.Self.LoadURL += new EventHandler<LoadUrlEventArgs>(Self_LoadURL);
+ client.Self.SetDisplayNameReply += new EventHandler<SetDisplayNameReplyEventArgs>(Self_SetDisplayNameReply);
+ client.Avatars.DisplayNameUpdate += new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
+ client.Network.EventQueueRunning += new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
+ client.Network.RegisterCallback(OpenMetaverse.Packets.PacketType.ScriptTeleportRequest, ScriptTeleportRequestHandler);
+ }
+
+ private void UnregisterClientEvents(GridClient client)
+ {
+ client.Self.ScriptQuestion -= new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);
+ client.Self.ScriptDialog -= new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);
+ client.Self.LoadURL -= new EventHandler<LoadUrlEventArgs>(Self_LoadURL);
+ client.Self.SetDisplayNameReply -= new EventHandler<SetDisplayNameReplyEventArgs>(Self_SetDisplayNameReply);
+ client.Avatars.DisplayNameUpdate -= new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
+ client.Network.EventQueueRunning -= new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
+ client.Network.UnregisterCallback(OpenMetaverse.Packets.PacketType.ScriptTeleportRequest, ScriptTeleportRequestHandler);
+ }
+
+ void instance_ClientChanged(object sender, ClientChangedEventArgs e)
+ {
+ UnregisterClientEvents(e.OldClient);
+ RegisterClientEvents(client);
+ }
+
+ void TabsConsole_Disposed(object sender, EventArgs e)
+ {
+ RemoveNetcomEvents();
+ UnregisterClientEvents(client);
+ }
+
+ private void AddNetcomEvents()
+ {
+ netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+ netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
+ netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+ netcom.ChatSent += new EventHandler<ChatSentEventArgs>(netcom_ChatSent);
+ netcom.AlertMessageReceived += new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);
+ netcom.InstantMessageReceived += new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);
+ }
+
+ private void RemoveNetcomEvents()
+ {
+ netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+ netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
+ netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+ netcom.ChatSent -= new EventHandler<ChatSentEventArgs>(netcom_ChatSent);
+ netcom.AlertMessageReceived -= new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);
+ netcom.InstantMessageReceived -= new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);
+ }
+
+ void ScriptTeleportRequestHandler(object sender, PacketReceivedEventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ if (IsHandleCreated || !instance.MonoRuntime)
+ BeginInvoke(new MethodInvoker(() => ScriptTeleportRequestHandler(sender, e)));
+ return;
+ }
+
+ var msg = (OpenMetaverse.Packets.ScriptTeleportRequestPacket)e.Packet;
+
+ if (TabExists("map"))
+ {
+ Tabs["map"].Select();
+ ((MapConsole)Tabs["map"].Control).CenterOnGlobalPos(
+ (float)(client.Self.GlobalPosition.X - client.Self.SimPosition.X) + msg.Data.SimPosition.X,
+ (float)(client.Self.GlobalPosition.Y - client.Self.SimPosition.Y) + msg.Data.SimPosition.Y,
+ msg.Data.SimPosition.Z);
+ }
+ }
+
+ void Network_EventQueueRunning(object sender, EventQueueRunningEventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => Network_EventQueueRunning(sender, e)));
+ return;
+ }
+
+ if (TabExists("friends")) return;
+ if (e.Simulator == client.Network.CurrentSim)
+ {
+ client.Self.UpdateAgentLanguage("en", true);
+ InitializeOnlineTabs();
+ }
+ }
+
+ void Self_ScriptDialog(object sender, ScriptDialogEventArgs e)
+ {
+ if (instance.MainForm.InvokeRequired)
+ {
+ instance.MainForm.BeginInvoke(new MethodInvoker(() => Self_ScriptDialog(sender, e)));
+ return;
+ }
+
+ // Is this object muted
+ if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.ObjectID) // muted object by id
+ || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
+ )) return;
+
+ instance.MainForm.AddNotification(new ntfScriptDialog(instance, e.Message, e.ObjectName, e.ImageID, e.ObjectID, e.FirstName, e.LastName, e.Channel, e.ButtonLabels));
+ }
+
+ void Self_ScriptQuestion(object sender, ScriptQuestionEventArgs e)
+ {
+ // Is this object muted
+ if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.TaskID) // muted object by id
+ || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
+ )) return;
+
+ if (instance.GlobalSettings["on_script_question"] == "Auto Decline"
+ || instance.RLV.RestictionActive("denypermission"))
+ {
+ instance.Client.Self.ScriptQuestionReply(e.Simulator, e.ItemID, e.TaskID, 0);
+ }
+ else if (instance.GlobalSettings["on_script_question"] == "Auto Accept"
+ || instance.RLV.RestictionActive("acceptpermission"))
+ {
+ instance.Client.Self.ScriptQuestionReply(e.Simulator, e.ItemID, e.TaskID, e.Questions);
+ }
+ else
+ {
+ instance.MainForm.AddNotification(new ntfPermissions(instance, e.Simulator, e.TaskID, e.ItemID, e.ObjectName, e.ObjectOwnerName, e.Questions));
+ }
+ }
+
+ private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)
+ {
+ if (e.Status == LoginStatus.Failed)
+ {
+ DisplayNotificationInChat("Login error: " + e.Message, ChatBufferTextStyle.Error);
+ }
+ else if (e.Status == LoginStatus.Success)
+ {
+ DisplayNotificationInChat("Logged in as " + netcom.LoginOptions.FullName + ".", ChatBufferTextStyle.StatusDarkBlue);
+ DisplayNotificationInChat("Login reply: " + e.Message, ChatBufferTextStyle.StatusDarkBlue);
+
+ if (tabs.ContainsKey("login"))
+ {
+ if (selectedTab.Name == "login")
+ SelectDefaultTab();
+ ForceCloseTab("login");
+ }
+
+ client.Self.RetrieveInstantMessages();
+ }
+ }
+
+ private void netcom_ClientLoggedOut(object sender, EventArgs e)
+ {
+ DisposeOnlineTabs();
+
+ SelectDefaultTab();
+ DisplayNotificationInChat("Logged out.");
+
+ }
+
+ private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
+ {
+ if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;
+
+ DisposeOnlineTabs();
+ SelectDefaultTab();
+ DisplayNotificationInChat("Disconnected: " + e.Message, ChatBufferTextStyle.Error);
+ }
+
+ void Avatars_DisplayNameUpdate(object sender, DisplayNameUpdateEventArgs e)
+ {
+ DisplayNotificationInChat(string.Format("({0}) is now known as {1}", e.DisplayName.UserName, e.DisplayName.DisplayName));
+ }
+
+ void Self_SetDisplayNameReply(object sender, SetDisplayNameReplyEventArgs e)
+ {
+ if (e.Status == 200)
+ {
+ DisplayNotificationInChat("You are now knows as " + e.DisplayName.DisplayName);
+ }
+ else
+ {
+ DisplayNotificationInChat("Failed to set a new display name: " + e.Reason, ChatBufferTextStyle.Error);
+ }
+ }
+
+ private void netcom_AlertMessageReceived(object sender, AlertMessageEventArgs e)
+ {
+ tabs["chat"].Highlight();
+ }
+
+ private void netcom_ChatSent(object sender, ChatSentEventArgs e)
+ {
+ tabs["chat"].Highlight();
+ }
+
+ void Self_LoadURL(object sender, LoadUrlEventArgs e)
+ {
+ // Is the object or the owner muted?
+ if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.ObjectID) // muted object by id
+ || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
+ || (m.Type == MuteType.Resident && m.ID == e.OwnerID) // object's owner muted
+ )) return;
+
+ instance.MainForm.AddNotification(new ntfLoadURL(instance, e));
+ }
+
+ private void netcom_InstantMessageReceived(object sender, InstantMessageEventArgs e)
+ {
+ // Messaage from someone we muted?
+ if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Resident && me.ID == e.IM.FromAgentID)) return;
+
+ try
+ {
+ if (instance.State.LSLHelper.ProcessIM(e))
+ {
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log("Failed executing automation action: " + ex.ToString(), Helpers.LogLevel.Warning);
+ }
+
+ switch (e.IM.Dialog)
+ {
+ case InstantMessageDialog.SessionSend:
+ if (instance.Groups.ContainsKey(e.IM.IMSessionID))
+ {
+ HandleGroupIM(e);
+ }
+ else
+ {
+ HandleConferenceIM(e);
+ }
+ break;
+
+ case InstantMessageDialog.MessageFromAgent:
+ if (e.IM.FromAgentName == "Second Life")
+ {
+ HandleIMFromObject(e);
+ }
+ else if (e.IM.FromAgentID == UUID.Zero)
+ {
+ instance.MainForm.AddNotification(new ntfGeneric(instance, e.IM.Message));
+ }
+ else if (e.IM.GroupIM || instance.Groups.ContainsKey(e.IM.IMSessionID))
+ {
+ HandleGroupIM(e);
+ }
+ else if (e.IM.BinaryBucket.Length > 1)
+ { // conference
+ HandleConferenceIM(e);
+ }
+ else if (e.IM.IMSessionID == UUID.Zero)
+ {
+ String msg = string.Format("Message from {0}: {1}", instance.Names.Get(e.IM.FromAgentID, e.IM.FromAgentName), e.IM.Message);
+ instance.MainForm.AddNotification(new ntfGeneric(instance, msg));
+ DisplayNotificationInChat(msg);
+ }
+ else
+ {
+ HandleIM(e);
+ }
+ break;
+
+ case InstantMessageDialog.MessageFromObject:
+ HandleIMFromObject(e);
+ break;
+
+ case InstantMessageDialog.StartTyping:
+ if (TabExists(e.IM.FromAgentName))
+ {
+ RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];
+ if (!tab.Highlighted) tab.PartialHighlight();
+ }
+
+ break;
+
+ case InstantMessageDialog.StopTyping:
+ if (TabExists(e.IM.FromAgentName))
+ {
+ RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];
+ if (!tab.Highlighted) tab.Unhighlight();
+ }
+
+ break;
+
+ case InstantMessageDialog.MessageBox:
+ instance.MainForm.AddNotification(new ntfGeneric(instance, e.IM.Message));
+ break;
+
+ case InstantMessageDialog.RequestTeleport:
+ if (instance.RLV.AutoAcceptTP(e.IM.FromAgentID))
+ {
+ DisplayNotificationInChat("Auto accepting teleprot from " + e.IM.FromAgentName);
+ instance.Client.Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, true);
+ }
+ else
+ {
+ instance.MainForm.AddNotification(new ntfTeleport(instance, e.IM));
+ }
+ break;
+
+ case InstantMessageDialog.RequestLure:
+ instance.MainForm.AddNotification(new ntfRequestLure(instance, e.IM));
+ break;
+
+ case InstantMessageDialog.GroupInvitation:
+ instance.MainForm.AddNotification(new ntfGroupInvitation(instance, e.IM));
+ break;
+
+ case InstantMessageDialog.FriendshipOffered:
+ if (e.IM.FromAgentName == "Second Life")
+ {
+ HandleIMFromObject(e);
+ }
+ else
+ {
+ instance.MainForm.AddNotification(new ntfFriendshipOffer(instance, e.IM));
+ }
+ break;
+
+ case InstantMessageDialog.InventoryAccepted:
+ DisplayNotificationInChat(e.IM.FromAgentName + " accepted your inventory offer.");
+ break;
+
+ case InstantMessageDialog.InventoryDeclined:
+ DisplayNotificationInChat(e.IM.FromAgentName + " declined your inventory offer.");
+ break;
+
+ case InstantMessageDialog.GroupNotice:
+ // Is this group muted?
+ if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Group && me.ID == e.IM.FromAgentID)) break;
+
+ instance.MainForm.AddNotification(new ntfGroupNotice(instance, e.IM));
+ break;
+
+ case InstantMessageDialog.InventoryOffered:
+ var ion = new ntfInventoryOffer(instance, e.IM);
+ instance.MainForm.AddNotification(ion);
+ if (instance.GlobalSettings["inv_auto_accept_mode"].AsInteger() == 1)
+ {
+ ion.btnAccept.PerformClick();
+ }
+ else if (instance.GlobalSettings["inv_auto_accept_mode"].AsInteger() == 2)
+ {
+ ion.btnDiscard.PerformClick();
+ }
+ break;
+
+ case InstantMessageDialog.TaskInventoryOffered:
+ // Is the object muted by name?
+ if (null != client.Self.MuteList.Find(me => me.Type == MuteType.ByName && me.Name == e.IM.FromAgentName)) break;
+
+ var iont = new ntfInventoryOffer(instance, e.IM);
+ instance.MainForm.AddNotification(iont);
+ if (instance.GlobalSettings["inv_auto_accept_mode"].AsInteger() == 1)
+ {
+ iont.btnAccept.PerformClick();
+ }
+ else if (instance.GlobalSettings["inv_auto_accept_mode"].AsInteger() == 2)
+ {
+ iont.btnDiscard.PerformClick();
+ }
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Make default tab (chat) active
+ /// </summary>
+ public void SelectDefaultTab()
+ {
+ if (IsHandleCreated && TabExists("chat"))
+ tabs["chat"].Select();
+ }
+
+ /// <summary>
+ /// Displays notification in the main chat tab
+ /// </summary>
+ /// <param name="msg">Message to be printed in the chat tab</param>
+ public void DisplayNotificationInChat(string msg)
+ {
+ DisplayNotificationInChat(msg, ChatBufferTextStyle.ObjectChat);
+ }
+
+ /// <summary>
+ /// Displays notification in the main chat tab
+ /// </summary>
+ /// <param name="msg">Message to be printed in the chat tab</param>
+ /// <param name="style">Style of the message to be printed, normal, object, etc.</param>
+ public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style)
+ {
+ DisplayNotificationInChat(msg, style, true);
+ }
+
+ /// <summary>
+ /// Displays notification in the main chat tab
+ /// </summary>
+ /// <param name="msg">Message to be printed in the chat tab</param>
+ /// <param name="style">Style of the message to be printed, normal, object, etc.</param>
+ /// <param name="highlightChatTab">Highligt (and flash in taskbar) chat tab if not selected</param>
+ public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style, bool highlightChatTab)
+ {
+ if (InvokeRequired)
+ {
+ if (!instance.MonoRuntime || IsHandleCreated)
+ BeginInvoke(new MethodInvoker(() => DisplayNotificationInChat(msg, style, highlightChatTab)));
+ return;
+ }
+
+ if (style != ChatBufferTextStyle.Invisible)
+ {
+ ChatBufferItem line = new ChatBufferItem(
+ DateTime.Now,
+ string.Empty,
+ UUID.Zero,
+ msg,
+ style
+ );
+
+ try
+ {
+ mainChatManger.ProcessBufferItem(line, true);
+ if (highlightChatTab)
+ {
+ tabs["chat"].Highlight();
+ }
+ }
+ catch (Exception) { }
+ }
+
+ if (OnChatNotification != null)
+ {
+ try { OnChatNotification(this, new ChatNotificationEventArgs(msg, style)); }
+ catch { }
+ }
+ }
+
+ private void HandleIMFromObject(InstantMessageEventArgs e)
+ {
+ // Is the object or the owner muted?
+ if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.IM.IMSessionID) // muted object by id
+ || (m.Type == MuteType.ByName && m.Name == e.IM.FromAgentName) // object muted by name
+ || (m.Type == MuteType.Resident && m.ID == e.IM.FromAgentID) // object's owner muted
+ )) return;
+
+ DisplayNotificationInChat(e.IM.FromAgentName + ": " + e.IM.Message);
+ }
+
+ public static Control FindFocusedControl(Control control)
+ {
+ var container = control as ContainerControl;
+ while (container != null)
+ {
+ control = container.ActiveControl;
+ container = control as ContainerControl;
+ }
+ return control;
+ }
+
+ /// <summary>
+ /// Creates new IM tab if needed
+ /// </summary>
+ /// <param name="agentID">IM session with agentID</param>
+ /// <param name="label">Tab label</param>
+ /// <param name="makeActive">Should tab be selected and focused</param>
+ /// <returns>True if there was an existing IM tab, false if it was created</returns>
+ public bool ShowIMTab(UUID agentID, string label, bool makeActive)
+ {
+ if (instance.TabConsole.TabExists((client.Self.AgentID ^ agentID).ToString()))
+ {
+ if (makeActive)
+ {
+ instance.TabConsole.SelectTab((client.Self.AgentID ^ agentID).ToString());
+ }
+ return false;
+ }
+
+ if (makeActive)
+ {
+ instance.MediaManager.PlayUISound(UISounds.IMWindow);
+ }
+ else
+ {
+ instance.MediaManager.PlayUISound(UISounds.IM);
+ }
+
+ Control active = FindFocusedControl(instance.MainForm);
+
+ instance.TabConsole.AddIMTab(agentID, client.Self.AgentID ^ agentID, label);
+
+ if (makeActive)
+ {
+ instance.TabConsole.SelectTab((client.Self.AgentID ^ agentID).ToString());
+ }
+ else if (active != null)
+ {
+ active.Focus();
+ }
+
+ return true;
+ }
+
+ private void HandleIM(InstantMessageEventArgs e)
+ {
+ bool isNew = ShowIMTab(e.IM.FromAgentID, e.IM.FromAgentName, false);
+ if (!TabExists(e.IM.IMSessionID.ToString())) return; // this should now exist. sanity check anyway
+ RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
+ tab.Highlight();
+
+ if (isNew)
+ {
+ ((IMTabWindow)tab.Control).TextManager.ProcessIM(e);
+ }
+ }
+
+ private void HandleConferenceIM(InstantMessageEventArgs e)
+ {
+ if (TabExists(e.IM.IMSessionID.ToString()))
+ {
+ RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
+ tab.Highlight();
+ return;
+ }
+
+ instance.MediaManager.PlayUISound(UISounds.IM);
+
+ Control active = FindFocusedControl(instance.MainForm);
+
+ ConferenceIMTabWindow imTab = AddConferenceIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));
+ tabs[e.IM.IMSessionID.ToString()].Highlight();
+ imTab.TextManager.ProcessIM(e);
+
+ if (active != null)
+ {
+ active.Focus();
+ }
+ }
+
+ private void HandleGroupIM(InstantMessageEventArgs e)
+ {
+ // Ignore group IM from a muted group
+ if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Group && (me.ID == e.IM.IMSessionID || me.ID == e.IM.FromAgentID))) return;
+
+ if (TabExists(e.IM.IMSessionID.ToString()))
+ {
+ RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
+ tab.Highlight();
+ return;
+ }
+
+ instance.MediaManager.PlayUISound(UISounds.IM);
+
+ Control active = FindFocusedControl(instance.MainForm);
+
+ GroupIMTabWindow imTab = AddGroupIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));
+ imTab.TextManager.ProcessIM(e);
+ tabs[e.IM.IMSessionID.ToString()].Highlight();
+
+ if (active != null)
+ {
+ active.Focus();
+ }
+ }
+
+ public void InitializeMainTab()
+ {
+ if (TabExists("login"))
+ {
+ ForceCloseTab("login");
+ }
+
+ LoginConsole loginConsole = new LoginConsole(instance);
+
+ RadegastTab tab = AddTab("login", "Login", loginConsole);
+ tab.AllowClose = false;
+ tab.AllowDetach = false;
+ tab.AllowMerge = false;
+ tab.AllowHide = false;
+
+ loginConsole.RegisterTab(tab);
+ }
+
+ private void InitializeChatTab()
+ {
+ chatConsole = new ChatConsole(instance);
+ mainChatManger = chatConsole.ChatManager;
+
+ RadegastTab tab = AddTab("chat", "Chat", chatConsole);
+ tab.AllowClose = false;
+ tab.AllowDetach = false;
+ tab.AllowHide = false;
+ }
+
+
+ /// <summary>
+ /// Create Tabs that only make sense when connected
+ /// </summary>
+ private void InitializeOnlineTabs()
+ {
+ RadegastTab tab = AddTab("friends", "Friends", new FriendsConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+
+ tab = AddTab("groups", "Groups", new GroupsConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+
+ // Ugly workaround for a mono bug
+ InventoryConsole inv = new InventoryConsole(instance);
+ if (instance.MonoRuntime) inv.invTree.Scrollable = false;
+ tab = AddTab("inventory", "Inventory", inv);
+ if (instance.MonoRuntime) inv.invTree.Scrollable = true;
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+
+ tab = AddTab("search", "Search", new SearchConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+
+ tab = AddTab("map", "Map", new MapConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+
+ tab = AddTab("voice", "Voice", new VoiceConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowDetach = true;
+ tab.Visible = false;
+ }
+
+ /// <summary>
+ /// Close tabs that make no sense when not connected
+ /// </summary>
+ private void DisposeOnlineTabs()
+ {
+ lock (tabs)
+ {
+ ForceCloseTab("voice");
+ ForceCloseTab("map");
+ ForceCloseTab("search");
+ ForceCloseTab("inventory");
+ ForceCloseTab("groups");
+ ForceCloseTab("friends");
+ }
+ }
+
+ private void ForceCloseTab(string name)
+ {
+ if (!TabExists(name)) return;
+
+ RadegastTab tab = tabs[name];
+ if (tab.Merged) SplitTab(tab);
+
+ tab.AllowClose = true;
+ tab.Close();
+ tab = null;
+ }
+
+
+ public void RegisterContextAction(Type libomvType, String label, EventHandler handler)
+ {
+ instance.ContextActionManager.RegisterContextAction(libomvType, label, handler);
+ }
+
+ public void RegisterContextAction(ContextAction handler)
+ {
+ instance.ContextActionManager.RegisterContextAction(handler);
+ }
+
+ public void AddTab(RadegastTab tab)
+ {
+ ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(tab.Label);
+ button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
+ button.Image = null;
+ button.AutoToolTip = false;
+ button.Tag = tab.Name;
+ button.Click += new EventHandler(TabButtonClick);
+ tab.Button = button;
+ tabs.Add(tab.Name, tab);
+
+ if (OnTabAdded != null)
+ {
+ try { OnTabAdded(this, new TabEventArgs(tab)); }
+ catch (Exception) { }
+ }
+ }
+
+ public RadegastTab AddTab(string name, string label, Control control)
+ {
+ // WORKAROUND: one should never add tab that alrady exists
+ // but under some weird conditions disconnect/connect
+ // fire in the wrong order
+ if (TabExists(name))
+ {
+ Logger.Log("Force closing tab '" + name + "'", Helpers.LogLevel.Warning, client);
+ ForceCloseTab(name);
+ }
+
+ control.Visible = false;
+ control.Dock = DockStyle.Fill;
+ toolStripContainer1.ContentPanel.Controls.Add(control);
+
+ ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(label);
+ button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
+ button.Image = null;
+ button.AutoToolTip = false;
+ button.Tag = name.ToLower();
+ button.AllowDrop = true;
+ button.Click += new EventHandler(TabButtonClick);
+
+ RadegastTab tab = new RadegastTab(instance, button, control, name.ToLower(), label);
+ if (control is RadegastTabControl)
+ ((RadegastTabControl)control).RadegastTab = tab;
+ tab.TabAttached += new EventHandler(tab_TabAttached);
+ tab.TabDetached += new EventHandler(tab_TabDetached);
+ tab.TabSelected += new EventHandler(tab_TabSelected);
+ tab.TabClosed += new EventHandler(tab_TabClosed);
+ tab.TabHidden += new EventHandler(tab_TabHidden);
+ tabs.Add(name.ToLower(), tab);
+
+ if (OnTabAdded != null)
+ {
+ try { OnTabAdded(this, new TabEventArgs(tab)); }
+ catch (Exception) { }
+ }
+
+ button.MouseDown += (msender, margs) =>
+ {
+ if (margs.Button == MouseButtons.Middle)
+ {
+ if (tab.AllowClose)
+ {
+ tab.Close();
+ }
+ else if (tab.AllowHide)
+ {
+ tab.Hide();
+ }
+ }
+ };
+
+ return tab;
+ }
+
+ private void tab_TabAttached(object sender, EventArgs e)
+ {
+ RadegastTab tab = (RadegastTab)sender;
+ tab.Select();
+ }
+
+ private void tab_TabDetached(object sender, EventArgs e)
+ {
+ RadegastTab tab = (RadegastTab)sender;
+ frmDetachedTab form = (frmDetachedTab)tab.Owner;
+
+ form.ReattachStrip = tstTabs;
+ form.ReattachContainer = toolStripContainer1.ContentPanel;
+ }
+
+ private void tab_TabSelected(object sender, EventArgs e)
+ {
+ RadegastTab tab = (RadegastTab)sender;
+
+ if (selectedTab != null &&
+ selectedTab != tab)
+ { selectedTab.Deselect(); }
+
+ selectedTab = tab;
+
+ tbtnCloseTab.Enabled = !tab.Merged && (tab.AllowClose || tab.AllowHide);
+
+ if (owner != null)
+ {
+ owner.AcceptButton = tab.DefaultControlButton;
+ }
+
+ if (OnTabSelected != null)
+ {
+ try { OnTabSelected(this, new TabEventArgs(selectedTab)); }
+ catch (Exception) { }
+ }
+ }
+
+ void tab_TabHidden(object sender, EventArgs e)
+ {
+ RadegastTab tab = (RadegastTab)sender;
+
+ if (selectedTab != null && selectedTab == tab)
+ {
+ tab.Deselect();
+ SelectDefaultTab();
+ }
+ }
+
+ private void tab_TabClosed(object sender, EventArgs e)
+ {
+ RadegastTab tab = (RadegastTab)sender;
+
+ if (selectedTab != null && selectedTab == tab && tab.Name != "chat")
+ {
+ tab.Deselect();
+ SelectDefaultTab();
+ }
+
+ tabs.Remove(tab.Name);
+
+ if (OnTabRemoved != null)
+ {
+ try { OnTabRemoved(this, new TabEventArgs(tab)); }
+ catch (Exception) { }
+ }
+
+ tab = null;
+ }
+
+ private void TabButtonClick(object sender, EventArgs e)
+ {
+ ToolStripButton button = (ToolStripButton)sender;
+
+ RadegastTab tab = tabs[button.Tag.ToString()];
+ tab.Select();
+ }
+
+ public void RemoveTabEntry(RadegastTab tab)
+ {
+ if (tstTabs.Items.Contains(tab.Button))
+ {
+ tstTabs.Items.Remove(tab.Button);
+ }
+
+ tab.Button.Dispose();
+ tabs.Remove(tab.Name);
+ }
+
+ public void RemoveTab(string name)
+ {
+ if (tabs.ContainsKey(name))
+ {
+ tabs.Remove(name);
+ }
+ }
+
+ //Used for outside classes that have a reference to TabsConsole
+ public void SelectTab(string name)
+ {
+ if (TabExists(name.ToLower()))
+ tabs[name.ToLower()].Select();
+ }
+
+ public bool TabExists(string name)
+ {
+ return tabs.ContainsKey(name.ToLower());
+ }
+
+ public RadegastTab GetTab(string name)
+ {
+ if (TabExists(name.ToLower()))
+ return tabs[name.ToLower()];
+ else
+ return null;
+ }
+
+ public List<RadegastTab> GetOtherTabs()
+ {
+ List<RadegastTab> otherTabs = new List<RadegastTab>();
+
+ foreach (ToolStripItem item in tstTabs.Items)
+ {
+ if (item.Tag == null) continue;
+ if ((ToolStripItem)item == selectedTab.Button) continue;
+
+ RadegastTab tab = tabs[item.Tag.ToString()];
+ if (!tab.AllowMerge) continue;
+ if (tab.Merged) continue;
+
+ otherTabs.Add(tab);
+ }
+
+ return otherTabs;
+ }
+
+ /// <summary>
+ /// Activates the next tab
+ /// </summary>
+ public void SelectNextTab()
+ {
+ List<ToolStripItem> buttons = new List<ToolStripItem>();
+
+ foreach (ToolStripItem item in tstTabs.Items)
+ {
+ if (item.Tag == null || !item.Visible) continue;
+
+ buttons.Add(item);
+ }
+
+ int current = 0;
+
+ for (int i = 0; i < buttons.Count; i++)
+ {
+ if (buttons[i] == selectedTab.Button)
+ {
+ current = i;
+ break;
+ }
+ }
+
+ current++;
+
+ if (current == buttons.Count)
+ current = 0;
+
+ SelectTab(tabs[buttons[current].Tag.ToString()].Name);
+ }
+
+ /// <summary>
+ /// Activates the previous tab
+ /// </summary>
+ public void SelectPreviousTab()
+ {
+ List<ToolStripItem> buttons = new List<ToolStripItem>();
+
+ foreach (ToolStripItem item in tstTabs.Items)
+ {
+ if (item.Tag == null || !item.Visible) continue;
+
+ buttons.Add(item);
+ }
+
+ int current = 0;
+
+ for (int i = 0; i < buttons.Count; i++)
+ {
+ if (buttons[i] == selectedTab.Button)
+ {
+ current = i;
+ break;
+ }
+ }
+
+ current--;
+
+ if (current == -1)
+ current = buttons.Count - 1;
+
+ SelectTab(tabs[buttons[current].Tag.ToString()].Name);
+ }
+
+
+ public IMTabWindow AddIMTab(UUID target, UUID session, string targetName)
+ {
+ IMTabWindow imTab = new IMTabWindow(instance, target, session, targetName);
+
+ RadegastTab tab = AddTab(session.ToString(), "IM: " + targetName, imTab);
+ imTab.SelectIMInput();
+
+ return imTab;
+ }
+
+ public ConferenceIMTabWindow AddConferenceIMTab(UUID session, string name)
+ {
+ ConferenceIMTabWindow imTab = new ConferenceIMTabWindow(instance, session, name);
+
+ RadegastTab tab = AddTab(session.ToString(), name, imTab);
+ imTab.SelectIMInput();
+
+ return imTab;
+ }
+
+ public GroupIMTabWindow AddGroupIMTab(UUID session, string name)
+ {
+ GroupIMTabWindow imTab = new GroupIMTabWindow(instance, session, name);
+
+ RadegastTab tab = AddTab(session.ToString(), name, imTab);
+ imTab.SelectIMInput();
+
+ return imTab;
+ }
+
+ public OutfitTextures AddOTTab(Avatar avatar)
+ {
+ OutfitTextures otTab = new OutfitTextures(instance, avatar);
+
+ RadegastTab tab = AddTab("OT: " + avatar.Name, "OT: " + avatar.Name, otTab);
+ otTab.GetTextures();
+ return otTab;
+ }
+
+ public MasterTab AddMSTab(Avatar avatar)
+ {
+ MasterTab msTab = new MasterTab(instance, avatar);
+
+ RadegastTab tab = AddTab("MS: " + avatar.Name, "MS: " + avatar.Name, msTab);
+ return msTab;
+ }
+
+ public AnimTab AddAnimTab(Avatar avatar)
+ {
+ AnimTab animTab = new AnimTab(instance, avatar);
+
+ RadegastTab tab = AddTab("Anim: " + avatar.Name, "Anim: " + avatar.Name, animTab);
+ return animTab;
+ }
+
+ private void tbtnTabOptions_Click(object sender, EventArgs e)
+ {
+ tmnuMergeWith.Enabled = selectedTab.AllowMerge;
+ tmnuDetachTab.Enabled = selectedTab.AllowDetach;
+
+ tmnuMergeWith.DropDown.Items.Clear();
+
+ if (!selectedTab.AllowMerge) return;
+ if (!selectedTab.Merged)
+ {
+ tmnuMergeWith.Text = "Merge With";
+
+ List<RadegastTab> otherTabs = GetOtherTabs();
+
+ tmnuMergeWith.Enabled = (otherTabs.Count > 0);
+ if (!tmnuMergeWith.Enabled) return;
+
+ foreach (RadegastTab tab in otherTabs)
+ {
+ ToolStripItem item = tmnuMergeWith.DropDown.Items.Add(tab.Label);
+ item.Tag = tab.Name;
+ item.Click += new EventHandler(MergeItemClick);
+ }
+ }
+ else
+ {
+ tmnuMergeWith.Text = "Split";
+ tmnuMergeWith.Click += new EventHandler(SplitClick);
+ }
+ }
+
+ private void MergeItemClick(object sender, EventArgs e)
+ {
+ ToolStripItem item = (ToolStripItem)sender;
+ RadegastTab tab = tabs[item.Tag.ToString()];
+
+ selectedTab.MergeWith(tab);
+
+ SplitContainer container = (SplitContainer)selectedTab.Control;
+ toolStripContainer1.ContentPanel.Controls.Add(container);
+
+ selectedTab.Select();
+ RemoveTabEntry(tab);
+
+ tabs.Add(tab.Name, selectedTab);
+ }
+
+ private void SplitClick(object sender, EventArgs e)
+ {
+ SplitTab(selectedTab);
+ selectedTab.Select();
+ }
+
+ public void SplitTab(RadegastTab tab)
+ {
+ RadegastTab otherTab = tab.Split();
+ if (otherTab == null) return;
+
+ toolStripContainer1.ContentPanel.Controls.Add(tab.Control);
+ toolStripContainer1.ContentPanel.Controls.Add(otherTab.Control);
+
+ tabs.Remove(otherTab.Name);
+ AddTab(otherTab);
+ }
+
+ private void tmnuDetachTab_Click(object sender, EventArgs e)
+ {
+ if (!selectedTab.AllowDetach) return;
+ RadegastTab tab = selectedTab;
+ SelectDefaultTab();
+ tab.Detach(instance);
+ }
+
+ private void tbtnCloseTab_Click(object sender, EventArgs e)
+ {
+ RadegastTab tab = selectedTab;
+ if (tab.Merged)
+ return;
+ else if (tab.AllowClose)
+ tab.Close();
+ else if (tab.AllowHide)
+ tab.Hide();
+ }
+
+ private void TabsConsole_Load(object sender, EventArgs e)
+ {
+ owner = this.FindForm();
+ }
+
+ private void ctxTabs_Opening(object sender, CancelEventArgs e)
+ {
+ e.Cancel = false;
+
+ Point pt = this.PointToClient(Cursor.Position);
+ ToolStripItem stripItem = tstTabs.GetItemAt(pt);
+
+ if (stripItem == null)
+ {
+ e.Cancel = true;
+ }
+ else
+ {
+ tabs[stripItem.Tag.ToString()].Select();
+
+ ctxBtnClose.Enabled = !selectedTab.Merged && (selectedTab.AllowClose || selectedTab.AllowHide);
+ ctxBtnDetach.Enabled = selectedTab.AllowDetach;
+ ctxBtnMerge.Enabled = selectedTab.AllowMerge;
+ ctxBtnMerge.DropDown.Items.Clear();
+
+ if (!ctxBtnClose.Enabled && !ctxBtnDetach.Enabled && !ctxBtnMerge.Enabled)
+ {
+ e.Cancel = true;
+ return;
+ }
+
+ if (!selectedTab.AllowMerge) return;
+ if (!selectedTab.Merged)
+ {
+ ctxBtnMerge.Text = "Merge With";
+
+ List<RadegastTab> otherTabs = GetOtherTabs();
+
+ ctxBtnMerge.Enabled = (otherTabs.Count > 0);
+ if (!ctxBtnMerge.Enabled) return;
+
+ foreach (RadegastTab tab in otherTabs)
+ {
+ ToolStripItem item = ctxBtnMerge.DropDown.Items.Add(tab.Label);
+ item.Tag = tab.Name;
+ item.Click += new EventHandler(MergeItemClick);
+ }
+ }
+ else
+ {
+ ctxBtnMerge.Text = "Split";
+ ctxBtnMerge.Click += new EventHandler(SplitClick);
+ }
+
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Arguments for tab events
+ /// </summary>
+ public class TabEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Tab that was manipulated in the event
+ /// </summary>
+ public RadegastTab Tab;
+
+ public TabEventArgs()
+ : base()
+ {
+ }
+
+ public TabEventArgs(RadegastTab tab)
+ : base()
+ {
+ Tab = tab;
+ }
+ }
+
+ /// <summary>
+ /// Argument for chat notification events
+ /// </summary>
+ public class ChatNotificationEventArgs : EventArgs
+ {
+ public string Message;
+ public ChatBufferTextStyle Style;
+
+ public ChatNotificationEventArgs(string message, ChatBufferTextStyle style)
+ {
+ Message = message;
+ Style = style;
+ }
+ }
+
+ /// <summary>
+ /// Element of list of nearby avatars
+ /// </summary>
+ public class NearbyAvatar
+ {
+ public UUID ID { get; set; }
+ public string Name { get; set; }
+ }
+
+}