2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2011, Radegast Development Team
4 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 // * Neither the name of the application "Radegast", nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 using System.Collections.Generic;
33 using System.ComponentModel;
35 using System.Windows.Forms;
36 using Radegast.Netcom;
41 public partial class TabsConsole : UserControl
45 /// List of nearby avatars (radar data)
47 public List<NearbyAvatar> NearbyAvatars
51 List<NearbyAvatar> res = new List<NearbyAvatar>();
53 if (TabExists("chat"))
55 ChatConsole c = (ChatConsole)Tabs["chat"].Control;
56 lock (c.agentSimHandle)
58 foreach (ListViewItem item in c.lvwObjects.Items)
60 if (item.Name != client.Self.AgentID.ToString())
62 res.Add(new NearbyAvatar() { ID = new UUID(item.Name), Name = item.Text });
73 /// Delegate invoked on tab operations
75 /// <param name="sender">Event sender</param>
76 /// <param name="e">Event arguments</param>
77 public delegate void TabCallback(object sender, TabEventArgs e);
80 /// Fired when a tab is selected
82 public event TabCallback OnTabSelected;
86 /// Delegate invoked when chat notification is printed
88 /// <param name="sender">Event sender</param>
89 /// <param name="e">Event arguments</param>
90 public delegate void ChatNotificationCallback(object sender, ChatNotificationEventArgs e);
93 /// Fired when a tab is selected
95 public event ChatNotificationCallback OnChatNotification;
98 /// Fired when a new tab is added
100 public event TabCallback OnTabAdded;
103 /// Fired when a tab is removed
105 public event TabCallback OnTabRemoved;
107 private RadegastInstance instance;
108 private GridClient client { get { return instance.Client; } }
109 private RadegastNetcom netcom { get { return instance.Netcom; } }
110 private ChatTextManager mainChatManger;
112 private Dictionary<string, RadegastTab> tabs = new Dictionary<string, RadegastTab>();
113 public Dictionary<string, RadegastTab> Tabs { get { return tabs; } }
115 private ChatConsole chatConsole;
117 private RadegastTab selectedTab;
120 /// Currently selected tab
122 public RadegastTab SelectedTab
132 public TabsConsole(RadegastInstance instance)
134 InitializeComponent();
135 Disposed += new EventHandler(TabsConsole_Disposed);
137 this.instance = instance;
138 this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
146 RegisterClientEvents(client);
149 private void RegisterClientEvents(GridClient client)
151 client.Self.ScriptQuestion += new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);
152 client.Self.ScriptDialog += new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);
153 client.Self.LoadURL += new EventHandler<LoadUrlEventArgs>(Self_LoadURL);
154 client.Self.SetDisplayNameReply += new EventHandler<SetDisplayNameReplyEventArgs>(Self_SetDisplayNameReply);
155 client.Avatars.DisplayNameUpdate += new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
158 private void UnregisterClientEvents(GridClient client)
160 client.Self.ScriptQuestion -= new EventHandler<ScriptQuestionEventArgs>(Self_ScriptQuestion);
161 client.Self.ScriptDialog -= new EventHandler<ScriptDialogEventArgs>(Self_ScriptDialog);
162 client.Self.LoadURL -= new EventHandler<LoadUrlEventArgs>(Self_LoadURL);
163 client.Self.SetDisplayNameReply -= new EventHandler<SetDisplayNameReplyEventArgs>(Self_SetDisplayNameReply);
164 client.Avatars.DisplayNameUpdate -= new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
167 void instance_ClientChanged(object sender, ClientChangedEventArgs e)
169 UnregisterClientEvents(e.OldClient);
170 RegisterClientEvents(client);
173 void TabsConsole_Disposed(object sender, EventArgs e)
175 RemoveNetcomEvents();
176 UnregisterClientEvents(client);
179 private void AddNetcomEvents()
181 netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
182 netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
183 netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
184 netcom.ChatSent += new EventHandler<ChatSentEventArgs>(netcom_ChatSent);
185 netcom.AlertMessageReceived += new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);
186 netcom.InstantMessageReceived += new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);
189 private void RemoveNetcomEvents()
191 netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
192 netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
193 netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
194 netcom.ChatSent -= new EventHandler<ChatSentEventArgs>(netcom_ChatSent);
195 netcom.AlertMessageReceived -= new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);
196 netcom.InstantMessageReceived -= new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);
199 void Self_ScriptDialog(object sender, ScriptDialogEventArgs e)
201 // Is this object muted
202 if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.ObjectID) // muted object by id
203 || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
206 instance.MainForm.AddNotification(new ntfScriptDialog(instance, e.Message, e.ObjectName, e.ImageID, e.ObjectID, e.FirstName, e.LastName, e.Channel, e.ButtonLabels));
209 void Self_ScriptQuestion(object sender, ScriptQuestionEventArgs e)
211 // Is this object muted
212 if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.TaskID) // muted object by id
213 || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
216 instance.MainForm.AddNotification(new ntfPermissions(instance, e.Simulator, e.TaskID, e.ItemID, e.ObjectName, e.ObjectOwnerName, e.Questions));
219 private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)
221 if (e.Status == LoginStatus.Failed)
223 DisplayNotificationInChat("Login error: " + e.Message, ChatBufferTextStyle.Error);
225 else if (e.Status == LoginStatus.Success)
227 DisplayNotificationInChat("Logged in as " + netcom.LoginOptions.FullName + ".", ChatBufferTextStyle.StatusDarkBlue);
228 DisplayNotificationInChat("Login reply: " + e.Message, ChatBufferTextStyle.StatusDarkBlue);
230 InitializeOnlineTabs();
232 if (tabs.ContainsKey("login"))
234 if (selectedTab.Name == "login")
236 ForceCloseTab("login");
239 client.Self.RetrieveInstantMessages();
243 private void netcom_ClientLoggedOut(object sender, EventArgs e)
248 DisplayNotificationInChat("Logged out.");
252 private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
254 if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;
258 DisplayNotificationInChat("Disconnected: " + e.Message, ChatBufferTextStyle.Error);
261 void Avatars_DisplayNameUpdate(object sender, DisplayNameUpdateEventArgs e)
263 DisplayNotificationInChat(string.Format("({0}) is now known as {1}", e.DisplayName.UserName, e.DisplayName.DisplayName));
266 void Self_SetDisplayNameReply(object sender, SetDisplayNameReplyEventArgs e)
270 DisplayNotificationInChat("You are now knows as " + e.DisplayName.DisplayName);
274 DisplayNotificationInChat("Failed to set a new display name: " + e.Reason, ChatBufferTextStyle.Error);
278 private void netcom_AlertMessageReceived(object sender, AlertMessageEventArgs e)
280 tabs["chat"].Highlight();
283 private void netcom_ChatSent(object sender, ChatSentEventArgs e)
285 tabs["chat"].Highlight();
288 void Self_LoadURL(object sender, LoadUrlEventArgs e)
290 // Is the object or the owner muted?
291 if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.ObjectID) // muted object by id
292 || (m.Type == MuteType.ByName && m.Name == e.ObjectName) // object muted by name
293 || (m.Type == MuteType.Resident && m.ID == e.OwnerID) // object's owner muted
296 instance.MainForm.AddNotification(new ntfLoadURL(instance, e));
299 private void netcom_InstantMessageReceived(object sender, InstantMessageEventArgs e)
301 // Messaage from someone we muted?
302 if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Resident && me.ID == e.IM.FromAgentID)) return;
306 case InstantMessageDialog.SessionSend:
307 if (instance.Groups.ContainsKey(e.IM.IMSessionID))
313 HandleConferenceIM(e);
317 case InstantMessageDialog.MessageFromAgent:
318 if (e.IM.FromAgentName == "Second Life")
320 HandleIMFromObject(e);
322 else if (e.IM.GroupIM || instance.Groups.ContainsKey(e.IM.IMSessionID))
326 else if (e.IM.BinaryBucket.Length > 1)
328 HandleConferenceIM(e);
336 case InstantMessageDialog.MessageFromObject:
337 HandleIMFromObject(e);
340 case InstantMessageDialog.StartTyping:
341 if (TabExists(e.IM.FromAgentName))
343 RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];
344 if (!tab.Highlighted) tab.PartialHighlight();
349 case InstantMessageDialog.StopTyping:
350 if (TabExists(e.IM.FromAgentName))
352 RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];
353 if (!tab.Highlighted) tab.Unhighlight();
358 case InstantMessageDialog.MessageBox:
359 instance.MainForm.AddNotification(new ntfGeneric(instance, e.IM.Message));
362 case InstantMessageDialog.RequestTeleport:
363 if (instance.RLV.AutoAcceptTP(e.IM.FromAgentID))
365 DisplayNotificationInChat("Auto accepting teleprot from " + e.IM.FromAgentName);
366 instance.Client.Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, true);
370 instance.MainForm.AddNotification(new ntfTeleport(instance, e.IM));
374 case InstantMessageDialog.GroupInvitation:
375 instance.MainForm.AddNotification(new ntfGroupInvitation(instance, e.IM));
378 case InstantMessageDialog.FriendshipOffered:
379 if (e.IM.FromAgentName == "Second Life")
381 HandleIMFromObject(e);
385 instance.MainForm.AddNotification(new ntfFriendshipOffer(instance, e.IM));
389 case InstantMessageDialog.InventoryAccepted:
390 DisplayNotificationInChat(e.IM.FromAgentName + " accepted your inventory offer.");
393 case InstantMessageDialog.InventoryDeclined:
394 DisplayNotificationInChat(e.IM.FromAgentName + " declined your inventory offer.");
397 case InstantMessageDialog.GroupNotice:
398 // Is this group muted?
399 if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Group && me.ID == e.IM.FromAgentID)) break;
401 instance.MainForm.AddNotification(new ntfGroupNotice(instance, e.IM));
404 case InstantMessageDialog.InventoryOffered:
405 instance.MainForm.AddNotification(new ntfInventoryOffer(instance, e.IM));
408 case InstantMessageDialog.TaskInventoryOffered:
409 // Is the object muted by name?
410 if (null != client.Self.MuteList.Find(me => me.Type == MuteType.ByName && me.Name == e.IM.FromAgentName)) break;
412 instance.MainForm.AddNotification(new ntfInventoryOffer(instance, e.IM));
418 /// Make default tab (chat) active
420 public void SelectDefaultTab()
422 if (TabExists("chat"))
423 tabs["chat"].Select();
427 /// Displays notification in the main chat tab
429 /// <param name="msg">Message to be printed in the chat tab</param>
430 public void DisplayNotificationInChat(string msg)
432 DisplayNotificationInChat(msg, ChatBufferTextStyle.ObjectChat);
436 /// Displays notification in the main chat tab
438 /// <param name="msg">Message to be printed in the chat tab</param>
439 /// <param name="style">Style of the message to be printed, normal, object, etc.</param>
440 public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style)
442 DisplayNotificationInChat(msg, style, true);
446 /// Displays notification in the main chat tab
448 /// <param name="msg">Message to be printed in the chat tab</param>
449 /// <param name="style">Style of the message to be printed, normal, object, etc.</param>
450 /// <param name="highlightChatTab">Highligt (and flash in taskbar) chat tab if not selected</param>
451 public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style, bool highlightChatTab)
455 if (!instance.MonoRuntime || IsHandleCreated)
456 BeginInvoke(new MethodInvoker(() => DisplayNotificationInChat(msg, style, highlightChatTab)));
460 if (style != ChatBufferTextStyle.Invisible)
462 ChatBufferItem line = new ChatBufferItem(
470 mainChatManger.ProcessBufferItem(line, true);
471 if (highlightChatTab)
473 tabs["chat"].Highlight();
476 catch (Exception) { }
479 if (OnChatNotification != null)
481 try { OnChatNotification(this, new ChatNotificationEventArgs(msg, style)); }
486 private void HandleIMFromObject(InstantMessageEventArgs e)
488 // Is the object or the owner muted?
489 if (null != client.Self.MuteList.Find(m => (m.Type == MuteType.Object && m.ID == e.IM.IMSessionID) // muted object by id
490 || (m.Type == MuteType.ByName && m.Name == e.IM.FromAgentName) // object muted by name
491 || (m.Type == MuteType.Resident && m.ID == e.IM.FromAgentID) // object's owner muted
494 DisplayNotificationInChat(e.IM.FromAgentName + ": " + e.IM.Message);
497 private void HandleIM(InstantMessageEventArgs e)
499 if (TabExists(e.IM.IMSessionID.ToString()))
501 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
502 if (!tab.Selected) tab.Highlight();
506 instance.MediaManager.PlayUISound(UISounds.IM);
508 IMTabWindow imTab = AddIMTab(e);
509 tabs[e.IM.IMSessionID.ToString()].Highlight();
512 private void HandleConferenceIM(InstantMessageEventArgs e)
514 if (TabExists(e.IM.IMSessionID.ToString()))
516 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
517 if (!tab.Selected) tab.Highlight();
521 instance.MediaManager.PlayUISound(UISounds.IM);
523 ConferenceIMTabWindow imTab = AddConferenceIMTab(e);
524 tabs[e.IM.IMSessionID.ToString()].Highlight();
527 private void HandleGroupIM(InstantMessageEventArgs e)
529 // Ignore group IM from a muted group
530 if (null != client.Self.MuteList.Find(me => me.Type == MuteType.Group && (me.ID == e.IM.IMSessionID || me.ID == e.IM.FromAgentID))) return;
532 if (TabExists(e.IM.IMSessionID.ToString()))
534 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];
535 if (!tab.Selected) tab.Highlight();
539 instance.MediaManager.PlayUISound(UISounds.IM);
541 GroupIMTabWindow imTab = AddGroupIMTab(e);
542 tabs[e.IM.IMSessionID.ToString()].Highlight();
545 private void InitializeMainTab()
547 LoginConsole loginConsole = new LoginConsole(instance);
549 RadegastTab tab = AddTab("login", "Login", loginConsole);
550 tab.AllowClose = false;
551 tab.AllowDetach = false;
552 tab.AllowMerge = false;
553 tab.AllowHide = false;
555 loginConsole.RegisterTab(tab);
558 private void InitializeChatTab()
560 chatConsole = new ChatConsole(instance);
561 mainChatManger = chatConsole.ChatManager;
563 RadegastTab tab = AddTab("chat", "Chat", chatConsole);
564 tab.AllowClose = false;
565 tab.AllowDetach = false;
566 tab.AllowHide = false;
571 /// Create Tabs that only make sense when connected
573 private void InitializeOnlineTabs()
575 RadegastTab tab = AddTab("friends", "Friends", new FriendsConsole(instance));
576 tab.AllowClose = false;
577 tab.AllowDetach = true;
580 tab = AddTab("groups", "Groups", new GroupsConsole(instance));
581 tab.AllowClose = false;
582 tab.AllowDetach = true;
585 // Ugly workaround for a mono bug
586 InventoryConsole inv = new InventoryConsole(instance);
587 if (instance.MonoRuntime) inv.invTree.Scrollable = false;
588 tab = AddTab("inventory", "Inventory", inv);
589 if (instance.MonoRuntime) inv.invTree.Scrollable = true;
590 tab.AllowClose = false;
591 tab.AllowDetach = true;
594 tab = AddTab("search", "Search", new SearchConsole(instance));
595 tab.AllowClose = false;
596 tab.AllowDetach = true;
599 tab = AddTab("map", "Map", new MapConsole(instance));
600 tab.AllowClose = false;
601 tab.AllowDetach = true;
604 tab = AddTab("voice", "Voice", new VoiceConsole(instance));
605 tab.AllowClose = false;
606 tab.AllowDetach = true;
611 /// Close tabs that make no sense when not connected
613 private void DisposeOnlineTabs()
617 ForceCloseTab("voice");
618 ForceCloseTab("map");
619 ForceCloseTab("search");
620 ForceCloseTab("inventory");
621 ForceCloseTab("groups");
622 ForceCloseTab("friends");
626 private void ForceCloseTab(string name)
628 if (!TabExists(name)) return;
630 RadegastTab tab = tabs[name];
631 if (tab.Merged) SplitTab(tab);
633 tab.AllowClose = true;
639 public void RegisterContextAction(Type libomvType, String label, EventHandler handler)
641 instance.ContextActionManager.RegisterContextAction(libomvType, label, handler);
644 public void RegisterContextAction(ContextAction handler)
646 instance.ContextActionManager.RegisterContextAction(handler);
649 public void AddTab(RadegastTab tab)
651 ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(tab.Label);
652 button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
654 button.AutoToolTip = false;
655 button.Tag = tab.Name;
656 button.Click += new EventHandler(TabButtonClick);
658 tabs.Add(tab.Name, tab);
660 if (OnTabAdded != null)
662 try { OnTabAdded(this, new TabEventArgs(tab)); }
663 catch (Exception) { }
667 public RadegastTab AddTab(string name, string label, Control control)
669 // WORKAROUND: one should never add tab that alrady exists
670 // but under some weird conditions disconnect/connect
671 // fire in the wrong order
674 Logger.Log("Force closing tab '" + name + "'", Helpers.LogLevel.Warning, client);
678 control.Visible = false;
679 control.Dock = DockStyle.Fill;
680 toolStripContainer1.ContentPanel.Controls.Add(control);
682 ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(label);
683 button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
685 button.AutoToolTip = false;
686 button.Tag = name.ToLower();
687 button.Click += new EventHandler(TabButtonClick);
689 RadegastTab tab = new RadegastTab(instance, button, control, name.ToLower(), label);
690 if (control is RadegastTabControl)
691 ((RadegastTabControl)control).RadegastTab = tab;
692 tab.TabAttached += new EventHandler(tab_TabAttached);
693 tab.TabDetached += new EventHandler(tab_TabDetached);
694 tab.TabSelected += new EventHandler(tab_TabSelected);
695 tab.TabClosed += new EventHandler(tab_TabClosed);
696 tab.TabHidden += new EventHandler(tab_TabHidden);
697 tabs.Add(name.ToLower(), tab);
699 if (OnTabAdded != null)
701 try { OnTabAdded(this, new TabEventArgs(tab)); }
702 catch (Exception) { }
708 private void tab_TabAttached(object sender, EventArgs e)
710 RadegastTab tab = (RadegastTab)sender;
714 private void tab_TabDetached(object sender, EventArgs e)
716 RadegastTab tab = (RadegastTab)sender;
717 frmDetachedTab form = (frmDetachedTab)tab.Owner;
719 form.ReattachStrip = tstTabs;
720 form.ReattachContainer = toolStripContainer1.ContentPanel;
723 private void tab_TabSelected(object sender, EventArgs e)
725 RadegastTab tab = (RadegastTab)sender;
727 if (selectedTab != null &&
729 { selectedTab.Deselect(); }
733 tbtnCloseTab.Enabled = tab.AllowClose || tab.AllowHide;
737 owner.AcceptButton = tab.DefaultControlButton;
740 if (OnTabSelected != null)
742 try { OnTabSelected(this, new TabEventArgs(selectedTab)); }
743 catch (Exception) { }
747 void tab_TabHidden(object sender, EventArgs e)
749 RadegastTab tab = (RadegastTab)sender;
751 if (selectedTab != null && selectedTab == tab)
758 private void tab_TabClosed(object sender, EventArgs e)
760 RadegastTab tab = (RadegastTab)sender;
762 if (selectedTab != null && selectedTab == tab && tab.Name != "chat")
768 tabs.Remove(tab.Name);
770 if (OnTabRemoved != null)
772 try { OnTabRemoved(this, new TabEventArgs(tab)); }
773 catch (Exception) { }
779 private void TabButtonClick(object sender, EventArgs e)
781 ToolStripButton button = (ToolStripButton)sender;
783 RadegastTab tab = tabs[button.Tag.ToString()];
787 public void RemoveTabEntry(RadegastTab tab)
789 if (tstTabs.Items.Contains(tab.Button))
791 tstTabs.Items.Remove(tab.Button);
794 tab.Button.Dispose();
795 tabs.Remove(tab.Name);
798 public void RemoveTab(string name)
800 if (tabs.ContainsKey(name))
806 //Used for outside classes that have a reference to TabsConsole
807 public void SelectTab(string name)
809 if (TabExists(name.ToLower()))
810 tabs[name.ToLower()].Select();
813 public bool TabExists(string name)
815 return tabs.ContainsKey(name.ToLower());
818 public RadegastTab GetTab(string name)
820 if (TabExists(name.ToLower()))
821 return tabs[name.ToLower()];
826 public List<RadegastTab> GetOtherTabs()
828 List<RadegastTab> otherTabs = new List<RadegastTab>();
830 foreach (ToolStripItem item in tstTabs.Items)
832 if (item.Tag == null) continue;
833 if ((ToolStripItem)item == selectedTab.Button) continue;
835 RadegastTab tab = tabs[item.Tag.ToString()];
836 if (!tab.AllowMerge) continue;
837 if (tab.Merged) continue;
846 /// Activates the next tab
848 public void SelectNextTab()
850 List<ToolStripItem> buttons = new List<ToolStripItem>();
852 foreach (ToolStripItem item in tstTabs.Items)
854 if (item.Tag == null || !item.Visible) continue;
861 for (int i = 0; i < buttons.Count; i++)
863 if (buttons[i] == selectedTab.Button)
872 if (current == buttons.Count)
875 SelectTab(tabs[buttons[current].Tag.ToString()].Name);
879 /// Activates the previous tab
881 public void SelectPreviousTab()
883 List<ToolStripItem> buttons = new List<ToolStripItem>();
885 foreach (ToolStripItem item in tstTabs.Items)
887 if (item.Tag == null || !item.Visible) continue;
894 for (int i = 0; i < buttons.Count; i++)
896 if (buttons[i] == selectedTab.Button)
906 current = buttons.Count - 1;
908 SelectTab(tabs[buttons[current].Tag.ToString()].Name);
912 public IMTabWindow AddIMTab(UUID target, UUID session, string targetName)
914 IMTabWindow imTab = new IMTabWindow(instance, target, session, targetName);
916 RadegastTab tab = AddTab(session.ToString(), "IM: " + targetName, imTab);
917 imTab.SelectIMInput();
923 public ConferenceIMTabWindow AddConferenceIMTab(UUID session, string name)
925 ConferenceIMTabWindow imTab = new ConferenceIMTabWindow(instance, session, name);
927 RadegastTab tab = AddTab(session.ToString(), name, imTab);
928 imTab.SelectIMInput();
934 public ConferenceIMTabWindow AddConferenceIMTab(InstantMessageEventArgs e)
936 ConferenceIMTabWindow imTab = AddConferenceIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));
937 imTab.TextManager.ProcessIM(e);
941 public GroupIMTabWindow AddGroupIMTab(UUID session, string name)
943 GroupIMTabWindow imTab = new GroupIMTabWindow(instance, session, name);
945 RadegastTab tab = AddTab(session.ToString(), name, imTab);
946 imTab.SelectIMInput();
951 public GroupIMTabWindow AddGroupIMTab(InstantMessageEventArgs e)
953 GroupIMTabWindow imTab = AddGroupIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));
954 imTab.TextManager.ProcessIM(e);
958 public IMTabWindow AddIMTab(InstantMessageEventArgs e)
960 IMTabWindow imTab = AddIMTab(e.IM.FromAgentID, e.IM.IMSessionID, e.IM.FromAgentName);
961 imTab.TextManager.ProcessIM(e);
965 public OutfitTextures AddOTTab(Avatar avatar)
967 OutfitTextures otTab = new OutfitTextures(instance, avatar);
969 RadegastTab tab = AddTab("OT: " + avatar.Name, "OT: " + avatar.Name, otTab);
974 public MasterTab AddMSTab(Avatar avatar)
976 MasterTab msTab = new MasterTab(instance, avatar);
978 RadegastTab tab = AddTab("MS: " + avatar.Name, "MS: " + avatar.Name, msTab);
982 public AttachmentTab AddATTab(Avatar avatar)
984 AttachmentTab atTab = new AttachmentTab(instance, avatar);
986 RadegastTab tab = AddTab("AT: " + avatar.Name, "AT: " + avatar.Name, atTab);
990 public AnimTab AddAnimTab(Avatar avatar)
992 AnimTab animTab = new AnimTab(instance, avatar);
994 RadegastTab tab = AddTab("Anim: " + avatar.Name, "Anim: " + avatar.Name, animTab);
998 private void tbtnTabOptions_Click(object sender, EventArgs e)
1000 tmnuMergeWith.Enabled = selectedTab.AllowMerge;
1001 tmnuDetachTab.Enabled = selectedTab.AllowDetach;
1003 tmnuMergeWith.DropDown.Items.Clear();
1005 if (!selectedTab.AllowMerge) return;
1006 if (!selectedTab.Merged)
1008 tmnuMergeWith.Text = "Merge With";
1010 List<RadegastTab> otherTabs = GetOtherTabs();
1012 tmnuMergeWith.Enabled = (otherTabs.Count > 0);
1013 if (!tmnuMergeWith.Enabled) return;
1015 foreach (RadegastTab tab in otherTabs)
1017 ToolStripItem item = tmnuMergeWith.DropDown.Items.Add(tab.Label);
1018 item.Tag = tab.Name;
1019 item.Click += new EventHandler(MergeItemClick);
1024 tmnuMergeWith.Text = "Split";
1025 tmnuMergeWith.Click += new EventHandler(SplitClick);
1029 private void MergeItemClick(object sender, EventArgs e)
1031 ToolStripItem item = (ToolStripItem)sender;
1032 RadegastTab tab = tabs[item.Tag.ToString()];
1034 selectedTab.MergeWith(tab);
1036 SplitContainer container = (SplitContainer)selectedTab.Control;
1037 toolStripContainer1.ContentPanel.Controls.Add(container);
1039 selectedTab.Select();
1040 RemoveTabEntry(tab);
1042 tabs.Add(tab.Name, selectedTab);
1045 private void SplitClick(object sender, EventArgs e)
1047 SplitTab(selectedTab);
1048 selectedTab.Select();
1051 public void SplitTab(RadegastTab tab)
1053 RadegastTab otherTab = tab.Split();
1054 if (otherTab == null) return;
1056 toolStripContainer1.ContentPanel.Controls.Add(tab.Control);
1057 toolStripContainer1.ContentPanel.Controls.Add(otherTab.Control);
1059 tabs.Remove(otherTab.Name);
1063 private void tmnuDetachTab_Click(object sender, EventArgs e)
1065 if (!selectedTab.AllowDetach) return;
1066 RadegastTab tab = selectedTab;
1068 tab.Detach(instance);
1071 private void tbtnCloseTab_Click(object sender, EventArgs e)
1073 RadegastTab tab = selectedTab;
1076 else if (tab.AllowHide)
1080 private void TabsConsole_Load(object sender, EventArgs e)
1082 owner = this.FindForm();
1085 private void ctxTabs_Opening(object sender, CancelEventArgs e)
1087 Point pt = this.PointToClient(Cursor.Position);
1088 ToolStripItem stripItem = tstTabs.GetItemAt(pt);
1090 if (stripItem == null)
1096 tabs[stripItem.Tag.ToString()].Select();
1098 ctxBtnClose.Enabled = selectedTab.AllowClose || selectedTab.AllowHide;
1099 ctxBtnDetach.Enabled = selectedTab.AllowDetach;
1100 ctxBtnMerge.Enabled = selectedTab.AllowMerge;
1101 ctxBtnMerge.DropDown.Items.Clear();
1103 if (!ctxBtnClose.Enabled && !ctxBtnDetach.Enabled && !ctxBtnMerge.Enabled)
1109 if (!selectedTab.AllowMerge) return;
1110 if (!selectedTab.Merged)
1112 ctxBtnMerge.Text = "Merge With";
1114 List<RadegastTab> otherTabs = GetOtherTabs();
1116 ctxBtnMerge.Enabled = (otherTabs.Count > 0);
1117 if (!ctxBtnMerge.Enabled) return;
1119 foreach (RadegastTab tab in otherTabs)
1121 ToolStripItem item = ctxBtnMerge.DropDown.Items.Add(tab.Label);
1122 item.Tag = tab.Name;
1123 item.Click += new EventHandler(MergeItemClick);
1128 ctxBtnMerge.Text = "Split";
1129 ctxBtnMerge.Click += new EventHandler(SplitClick);
1138 /// Arguments for tab events
1140 public class TabEventArgs : EventArgs
1143 /// Tab that was manipulated in the event
1145 public RadegastTab Tab;
1147 public TabEventArgs()
1152 public TabEventArgs(RadegastTab tab)
1160 /// Argument for chat notification events
1162 public class ChatNotificationEventArgs : EventArgs
1164 public string Message;
1165 public ChatBufferTextStyle Style;
1167 public ChatNotificationEventArgs(string message, ChatBufferTextStyle style)
1175 /// Element of list of nearby avatars
1177 public class NearbyAvatar
1179 public UUID ID { get; set; }
1180 public string Name { get; set; }