OSDN Git Service

Workaround for closing already existing tabs.
[radegast/radegast.git] / Radegast / GUI / Consoles / TabsConsole.cs
1 // \r
2 // Radegast Metaverse Client\r
3 // Copyright (c) 2009, Radegast Development Team\r
4 // All rights reserved.\r
5 // \r
6 // Redistribution and use in source and binary forms, with or without\r
7 // modification, are permitted provided that the following conditions are met:\r
8 // \r
9 //     * Redistributions of source code must retain the above copyright notice,\r
10 //       this list of conditions and the following disclaimer.\r
11 //     * Redistributions in binary form must reproduce the above copyright\r
12 //       notice, this list of conditions and the following disclaimer in the\r
13 //       documentation and/or other materials provided with the distribution.\r
14 //     * Neither the name of the application "Radegast", nor the names of its\r
15 //       contributors may be used to endorse or promote products derived from\r
16 //       this software without specific prior written permission.\r
17 // \r
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 //\r
29 // $Id$\r
30 //\r
31 using System;\r
32 using System.Collections.Generic;\r
33 using System.ComponentModel;\r
34 using System.Drawing;\r
35 using System.Windows.Forms;\r
36 using Radegast.Netcom;\r
37 using OpenMetaverse;\r
38 \r
39 namespace Radegast\r
40 {\r
41     public partial class TabsConsole : UserControl\r
42     {\r
43         /// <summary>\r
44         /// Delegate inviked on tab operations\r
45         /// </summary>\r
46         /// <param name="sender">Event sender</param>\r
47         /// <param name="e">Event arguments</param>\r
48         public delegate void TabCallback(object sender, TabEventArgs e);\r
49 \r
50         /// <summary>\r
51         /// Fired when a tab is selected\r
52         /// </summary>\r
53         public event TabCallback OnTabSelected;\r
54 \r
55         /// <summary>\r
56         /// Fired when a new tab is added\r
57         /// </summary>\r
58         public event TabCallback OnTabAdded;\r
59 \r
60         /// <summary>\r
61         /// Fired when a tab is removed\r
62         /// </summary>\r
63         public event TabCallback OnTabRemoved;\r
64 \r
65         private RadegastInstance instance;\r
66         private GridClient client { get { return instance.Client; } }\r
67         private RadegastNetcom netcom { get { return instance.Netcom; } }\r
68         private ChatTextManager mainChatManger;\r
69 \r
70         private Dictionary<string, RadegastTab> tabs = new Dictionary<string, RadegastTab>();\r
71         public Dictionary<string, RadegastTab> Tabs { get { return tabs; } }\r
72 \r
73         private ChatConsole chatConsole;\r
74 \r
75         private RadegastTab selectedTab;\r
76 \r
77         /// <summary>\r
78         /// Currently selected tab\r
79         /// </summary>\r
80         public RadegastTab SelectedTab\r
81         {\r
82             get\r
83             {\r
84                 return selectedTab;\r
85             }\r
86         }\r
87 \r
88         private Form owner;\r
89 \r
90         public TabsConsole(RadegastInstance instance)\r
91         {\r
92             InitializeComponent();\r
93             Disposed += new EventHandler(TabsConsole_Disposed);\r
94 \r
95             this.instance = instance;\r
96 \r
97             AddNetcomEvents();\r
98 \r
99             InitializeMainTab();\r
100             InitializeChatTab();\r
101 \r
102             // Callbacks\r
103             client.Self.OnScriptQuestion += new AgentManager.ScriptQuestionCallback(Self_OnScriptQuestion);\r
104             client.Self.OnScriptDialog += new AgentManager.ScriptDialogCallback(Self_OnScriptDialog);\r
105         }\r
106 \r
107         void TabsConsole_Disposed(object sender, EventArgs e)\r
108         {\r
109             RemoveNetcomEvents();\r
110             client.Self.OnScriptQuestion -= new AgentManager.ScriptQuestionCallback(Self_OnScriptQuestion);\r
111             client.Self.OnScriptDialog -= new AgentManager.ScriptDialogCallback(Self_OnScriptDialog);\r
112         }\r
113 \r
114         private void AddNetcomEvents()\r
115         {\r
116             netcom.ClientLoginStatus += new EventHandler<ClientLoginEventArgs>(netcom_ClientLoginStatus);\r
117             netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);\r
118             netcom.ClientDisconnected += new EventHandler<ClientDisconnectEventArgs>(netcom_ClientDisconnected);\r
119             netcom.ChatReceived += new EventHandler<ChatEventArgs>(netcom_ChatReceived);\r
120             netcom.ChatSent += new EventHandler<ChatSentEventArgs>(netcom_ChatSent);\r
121             netcom.AlertMessageReceived += new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);\r
122             netcom.InstantMessageReceived += new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);\r
123         }\r
124 \r
125         private void RemoveNetcomEvents()\r
126         {\r
127             netcom.ClientLoginStatus -= new EventHandler<ClientLoginEventArgs>(netcom_ClientLoginStatus);\r
128             netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);\r
129             netcom.ClientDisconnected -= new EventHandler<ClientDisconnectEventArgs>(netcom_ClientDisconnected);\r
130             netcom.ChatReceived -= new EventHandler<ChatEventArgs>(netcom_ChatReceived);\r
131             netcom.ChatSent -= new EventHandler<ChatSentEventArgs>(netcom_ChatSent);\r
132             netcom.AlertMessageReceived -= new EventHandler<AlertMessageEventArgs>(netcom_AlertMessageReceived);\r
133             netcom.InstantMessageReceived -= new EventHandler<InstantMessageEventArgs>(netcom_InstantMessageReceived);\r
134         }\r
135 \r
136         void Self_OnScriptDialog(string message, string objectName, UUID imageID, UUID objectID, string firstName, string lastName, int chatChannel, List<string> buttons)\r
137         {\r
138             instance.MainForm.AddNotification(new ntfScriptDialog(instance, message, objectName, imageID, objectID, firstName, lastName, chatChannel, buttons));\r
139         }\r
140 \r
141         void Self_OnScriptQuestion(Simulator simulator, UUID taskID, UUID itemID, string objectName, string objectOwner, ScriptPermission questions)\r
142         {\r
143             instance.MainForm.AddNotification(new ntfPermissions(instance, simulator, taskID, itemID, objectName, objectOwner, questions));\r
144         }\r
145 \r
146         private void netcom_ClientLoginStatus(object sender, ClientLoginEventArgs e)\r
147         {\r
148             if (e.Status != LoginStatus.Success) return;\r
149 \r
150             InitializeOnlineTabs();\r
151 \r
152             if (tabs.ContainsKey("login"))\r
153             {\r
154                 if (selectedTab.Name == "login")\r
155                     tabs["chat"].Select();\r
156 \r
157                 tabs["login"].AllowClose = true;\r
158                 tabs["login"].Close();\r
159             }\r
160 \r
161             client.Self.RetrieveInstantMessages();\r
162         }\r
163 \r
164         private void netcom_ClientLoggedOut(object sender, EventArgs e)\r
165         {\r
166             DisposeOnlineTabs();\r
167 \r
168             tabs["chat"].Select();\r
169             DisplayNotificationInChat("Logged out.");\r
170 \r
171         }\r
172 \r
173         private void netcom_ClientDisconnected(object sender, ClientDisconnectEventArgs e)\r
174         {\r
175             if (e.Type == NetworkManager.DisconnectType.ClientInitiated) return;\r
176 \r
177             DisposeOnlineTabs();\r
178 \r
179             tabs["chat"].Select();\r
180             DisplayNotificationInChat("Disconnected.");\r
181         }\r
182 \r
183         private void netcom_AlertMessageReceived(object sender, AlertMessageEventArgs e)\r
184         {\r
185             tabs["chat"].Highlight();\r
186         }\r
187 \r
188         private void netcom_ChatSent(object sender, ChatSentEventArgs e)\r
189         {\r
190             tabs["chat"].Highlight();\r
191         }\r
192 \r
193         private void netcom_ChatReceived(object sender, ChatEventArgs e)\r
194         {\r
195             if (string.IsNullOrEmpty(e.Message)) return;\r
196 \r
197             tabs["chat"].Highlight();\r
198         }\r
199 \r
200         private void netcom_InstantMessageReceived(object sender, InstantMessageEventArgs e)\r
201         {\r
202             switch (e.IM.Dialog)\r
203             {\r
204                 case InstantMessageDialog.SessionSend:\r
205                     if (instance.Groups.ContainsKey(e.IM.IMSessionID))\r
206                     {\r
207                         HandleGroupIM(e);\r
208                     }\r
209                     else\r
210                     {\r
211                         HandleConferenceIM(e);\r
212                     }\r
213                     break;\r
214 \r
215                 case InstantMessageDialog.MessageFromAgent:\r
216                     if (e.IM.FromAgentName == "Second Life")\r
217                     {\r
218                         HandleIMFromObject(e);\r
219                     }\r
220                     else if (e.IM.GroupIM || instance.Groups.ContainsKey(e.IM.IMSessionID))\r
221                     {\r
222                         HandleGroupIM(e);\r
223                     }\r
224                     else if (e.IM.BinaryBucket.Length > 1)\r
225                     { // conference\r
226                         HandleConferenceIM(e);\r
227                     }\r
228                     else\r
229                     {\r
230                         HandleIM(e);\r
231                     }\r
232                     break;\r
233 \r
234                 case InstantMessageDialog.MessageFromObject:\r
235                     HandleIMFromObject(e);\r
236                     break;\r
237 \r
238                 case InstantMessageDialog.StartTyping:\r
239                     if (TabExists(e.IM.FromAgentName))\r
240                     {\r
241                         RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];\r
242                         if (!tab.Highlighted) tab.PartialHighlight();\r
243                     }\r
244 \r
245                     break;\r
246 \r
247                 case InstantMessageDialog.StopTyping:\r
248                     if (TabExists(e.IM.FromAgentName))\r
249                     {\r
250                         RadegastTab tab = tabs[e.IM.FromAgentName.ToLower()];\r
251                         if (!tab.Highlighted) tab.Unhighlight();\r
252                     }\r
253 \r
254                     break;\r
255 \r
256                 case InstantMessageDialog.MessageBox:\r
257                     instance.MainForm.AddNotification(new ntfGeneric(instance, e.IM.Message));\r
258                     break;\r
259 \r
260                 case InstantMessageDialog.RequestTeleport:\r
261                     instance.MainForm.AddNotification(new ntfTeleport(instance, e.IM));\r
262                     break;\r
263 \r
264                 case InstantMessageDialog.GroupInvitation:\r
265                     instance.MainForm.AddNotification(new ntfGroupInvitation(instance, e.IM));\r
266                     break;\r
267 \r
268                 case InstantMessageDialog.FriendshipOffered:\r
269                     instance.MainForm.AddNotification(new ntfFriendshipOffer(instance, e.IM));\r
270                     break;\r
271 \r
272                 case InstantMessageDialog.InventoryAccepted:\r
273                     DisplayNotificationInChat(e.IM.FromAgentName + " accepted your inventory offer.");\r
274                     break;\r
275 \r
276                 case InstantMessageDialog.GroupNotice:\r
277                     instance.MainForm.AddNotification(new ntfGroupNotice(instance, e.IM));\r
278                     break;\r
279 \r
280                 case InstantMessageDialog.InventoryOffered:\r
281                 case InstantMessageDialog.TaskInventoryOffered:\r
282                     instance.MainForm.AddNotification(new ntfInventoryOffer(instance, e.IM));\r
283                     break;\r
284             }\r
285         }\r
286 \r
287         /// <summary>\r
288         /// Displays notification in the main chat tab\r
289         /// </summary>\r
290         /// <param name="msg">Message to be printed in the chat tab</param>\r
291         public void DisplayNotificationInChat(string msg)\r
292         {\r
293             DisplayNotificationInChat(msg, ChatBufferTextStyle.ObjectChat);\r
294         }\r
295 \r
296         /// <summary>\r
297         /// Displays notification in the main chat tab\r
298         /// </summary>\r
299         /// <param name="msg">Message to be printed in the chat tab</param>\r
300         /// <param name="style">Style of the message to be printed, normal, object, etc.</param>\r
301         public void DisplayNotificationInChat(string msg, ChatBufferTextStyle style)\r
302         {\r
303             if (InvokeRequired)\r
304             {\r
305                 BeginInvoke(new MethodInvoker(delegate()\r
306                     {\r
307                         DisplayNotificationInChat(msg, style);\r
308                     }));\r
309                 return;\r
310             }\r
311 \r
312             ChatBufferItem line = new ChatBufferItem(\r
313                 DateTime.Now,\r
314                 msg,\r
315                 style\r
316             );\r
317             try\r
318             {\r
319                 mainChatManger.ProcessBufferItem(line, true);\r
320                 tabs["chat"].Highlight();\r
321             }\r
322             catch (Exception) { }\r
323         }\r
324 \r
325         private void HandleIMFromObject(InstantMessageEventArgs e)\r
326         {\r
327             DisplayNotificationInChat(e.IM.FromAgentName + ": " + e.IM.Message);\r
328         }\r
329 \r
330         private void HandleIM(InstantMessageEventArgs e)\r
331         {\r
332             if (TabExists(e.IM.IMSessionID.ToString()))\r
333             {\r
334                 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
335                 if (!tab.Selected) tab.Highlight();\r
336                 return;\r
337             }\r
338 \r
339             IMTabWindow imTab = AddIMTab(e);\r
340             tabs[e.IM.IMSessionID.ToString()].Highlight();\r
341         }\r
342 \r
343         private void HandleConferenceIM(InstantMessageEventArgs e)\r
344         {\r
345             if (TabExists(e.IM.IMSessionID.ToString()))\r
346             {\r
347                 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
348                 if (!tab.Selected) tab.Highlight();\r
349                 return;\r
350             }\r
351 \r
352             ConferenceIMTabWindow imTab = AddConferenceIMTab(e);\r
353             tabs[e.IM.IMSessionID.ToString()].Highlight();\r
354         }\r
355 \r
356         private void HandleGroupIM(InstantMessageEventArgs e)\r
357         {\r
358             if (TabExists(e.IM.IMSessionID.ToString()))\r
359             {\r
360                 RadegastTab tab = tabs[e.IM.IMSessionID.ToString()];\r
361                 if (!tab.Selected) tab.Highlight();\r
362                 return;\r
363             }\r
364 \r
365             GroupIMTabWindow imTab = AddGroupIMTab(e);\r
366             tabs[e.IM.IMSessionID.ToString()].Highlight();\r
367         }\r
368 \r
369         private void InitializeMainTab()\r
370         {\r
371             MainConsole mainConsole = new MainConsole(instance);\r
372 \r
373             RadegastTab tab = AddTab("login", "Login", mainConsole);\r
374             tab.AllowClose = false;\r
375             tab.AllowDetach = false;\r
376             tab.AllowMerge = false;\r
377 \r
378             mainConsole.RegisterTab(tab);\r
379         }\r
380 \r
381         private void InitializeChatTab()\r
382         {\r
383             chatConsole = new ChatConsole(instance);\r
384             mainChatManger = chatConsole.ChatManager;\r
385 \r
386             RadegastTab tab = AddTab("chat", "Chat", chatConsole);\r
387             tab.AllowClose = false;\r
388             tab.AllowDetach = false;\r
389             tab.AllowHide = false;\r
390         }\r
391 \r
392 \r
393         /// <summary>\r
394         /// Create Tabs that only make sense when connected\r
395         /// </summary>\r
396         private void InitializeOnlineTabs()\r
397         {\r
398             RadegastTab tab = AddTab("friends", "Friends", new FriendsConsole(instance));\r
399             tab.AllowClose = false;\r
400             tab.AllowDetach = true;\r
401             tab.Visible = false;\r
402 \r
403             tab = AddTab("groups", "Groups", new GroupsConsole(instance));\r
404             tab.AllowClose = false;\r
405             tab.AllowDetach = true;\r
406             tab.Visible = false;\r
407 \r
408             tab = AddTab("inventory", "Inventory", new InventoryConsole(instance));\r
409             tab.AllowClose = false;\r
410             tab.AllowDetach = true;\r
411             tab.Visible = false;\r
412 \r
413             tab = AddTab("search", "Search", new SearchConsole(instance));\r
414             tab.AllowClose = false;\r
415             tab.AllowDetach = false;\r
416             tab.Visible = false;\r
417 \r
418             tab = AddTab("map", "Map", new MapConsole(instance));\r
419             tab.AllowClose = false;\r
420             tab.AllowDetach = true;\r
421             tab.Visible = false;\r
422 \r
423         }\r
424 \r
425         /// <summary>\r
426         /// Close tabs that make no sense when not connected\r
427         /// </summary>\r
428         private void DisposeOnlineTabs()\r
429         {\r
430             ForceCloseTab("map");\r
431             ForceCloseTab("search");\r
432             ForceCloseTab("inventory");\r
433             ForceCloseTab("groups");\r
434             ForceCloseTab("friends");\r
435         }\r
436 \r
437         private void ForceCloseTab(string name)\r
438         {\r
439             if (!TabExists(name)) return;\r
440 \r
441             RadegastTab tab = tabs[name];\r
442             if (tab.Merged) SplitTab(tab);\r
443 \r
444             tab.AllowClose = true;\r
445             tab.Close();\r
446             tab = null;\r
447         }\r
448 \r
449 \r
450         public void AddContextMenu(Type libomvType, String label, EventHandler handler)\r
451         {\r
452             instance.ContextActionManager.AddContextMenu(libomvType, label, handler);\r
453         }\r
454 \r
455         public void AddContextMenu(ContextAction handler)\r
456         {\r
457             instance.ContextActionManager.AddContextMenu(handler);\r
458         }\r
459 \r
460         public void AddTab(RadegastTab tab)\r
461         {\r
462             ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(tab.Label);\r
463             button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;\r
464             button.Image = null;\r
465             button.AutoToolTip = false;\r
466             button.Tag = tab.Name;\r
467             button.Click += new EventHandler(TabButtonClick);\r
468             tab.Button = button;\r
469             tabs.Add(tab.Name, tab);\r
470 \r
471             if (OnTabAdded != null)\r
472             {\r
473                 try { OnTabAdded(this, new TabEventArgs(tab)); }\r
474                 catch (Exception) { }\r
475             }\r
476         }\r
477 \r
478         public RadegastTab AddTab(string name, string label, Control control)\r
479         {\r
480             // WORKAROUND: one should never add tab that alrady exists\r
481             // but under some weird conditions disconnect/connect\r
482             // fire in the wrong order\r
483             if (TabExists(name))\r
484             {\r
485                 Logger.Log("Force closing tab '" + name + "'", Helpers.LogLevel.Warning, client);\r
486                 ForceCloseTab(name);\r
487             }\r
488 \r
489             toolStripContainer1.ContentPanel.Controls.Add(control);\r
490             control.Visible = false;\r
491             control.Dock = DockStyle.Fill;\r
492 \r
493             ToolStripButton button = (ToolStripButton)tstTabs.Items.Add(label);\r
494             button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;\r
495             button.Image = null;\r
496             button.AutoToolTip = false;\r
497             button.Tag = name.ToLower();\r
498             button.Click += new EventHandler(TabButtonClick);\r
499 \r
500             RadegastTab tab = new RadegastTab(instance, button, control, name.ToLower(), label);\r
501             tab.TabAttached += new EventHandler(tab_TabAttached);\r
502             tab.TabDetached += new EventHandler(tab_TabDetached);\r
503             tab.TabSelected += new EventHandler(tab_TabSelected);\r
504             tab.TabClosed += new EventHandler(tab_TabClosed);\r
505             tab.TabHidden += new EventHandler(tab_TabHidden);\r
506             tabs.Add(name.ToLower(), tab);\r
507 \r
508             if (OnTabAdded != null)\r
509             {\r
510                 try { OnTabAdded(this, new TabEventArgs(tab)); }\r
511                 catch (Exception) { }\r
512             }\r
513 \r
514             return tab;\r
515         }\r
516 \r
517         private void tab_TabAttached(object sender, EventArgs e)\r
518         {\r
519             RadegastTab tab = (RadegastTab)sender;\r
520             tab.Select();\r
521         }\r
522 \r
523         private void tab_TabDetached(object sender, EventArgs e)\r
524         {\r
525             RadegastTab tab = (RadegastTab)sender;\r
526             frmDetachedTab form = (frmDetachedTab)tab.Owner;\r
527 \r
528             form.ReattachStrip = tstTabs;\r
529             form.ReattachContainer = toolStripContainer1.ContentPanel;\r
530         }\r
531 \r
532         private void tab_TabSelected(object sender, EventArgs e)\r
533         {\r
534             RadegastTab tab = (RadegastTab)sender;\r
535 \r
536             if (selectedTab != null &&\r
537                 selectedTab != tab)\r
538             { selectedTab.Deselect(); }\r
539 \r
540             selectedTab = tab;\r
541 \r
542             tbtnCloseTab.Enabled = tab.AllowClose || tab.AllowHide;\r
543             owner.AcceptButton = tab.DefaultControlButton;\r
544 \r
545             if (OnTabSelected != null)\r
546             {\r
547                 try { OnTabSelected(this, new TabEventArgs(selectedTab)); }\r
548                 catch (Exception) { }\r
549             }\r
550         }\r
551 \r
552         void tab_TabHidden(object sender, EventArgs e)\r
553         {\r
554             RadegastTab tab = (RadegastTab)sender;\r
555 \r
556             if (selectedTab != null && selectedTab == tab)\r
557             {\r
558                 tab.Deselect();\r
559                 tabs["chat"].Select();\r
560             }\r
561         }\r
562 \r
563         private void tab_TabClosed(object sender, EventArgs e)\r
564         {\r
565             RadegastTab tab = (RadegastTab)sender;\r
566 \r
567             if (selectedTab != null && selectedTab == tab)\r
568             {\r
569                 tab.Deselect();\r
570                 tabs["chat"].Select();\r
571             }\r
572 \r
573             tabs.Remove(tab.Name);\r
574 \r
575             if (OnTabRemoved != null)\r
576             {\r
577                 try { OnTabRemoved(this, new TabEventArgs(tab)); }\r
578                 catch (Exception) { }\r
579             }\r
580 \r
581             tab = null;\r
582         }\r
583 \r
584         private void TabButtonClick(object sender, EventArgs e)\r
585         {\r
586             ToolStripButton button = (ToolStripButton)sender;\r
587 \r
588             RadegastTab tab = tabs[button.Tag.ToString()];\r
589             tab.Select();\r
590         }\r
591 \r
592         public void RemoveTabEntry(RadegastTab tab)\r
593         {\r
594             if (tstTabs.Items.Contains(tab.Button))\r
595             {\r
596                 tstTabs.Items.Remove(tab.Button);\r
597             }\r
598 \r
599             tab.Button.Dispose();\r
600             tabs.Remove(tab.Name);\r
601         }\r
602 \r
603         public void RemoveTab(string name)\r
604         {\r
605             if (tabs.ContainsKey(name))\r
606             {\r
607                 tabs.Remove(name);\r
608             }\r
609         }\r
610 \r
611         //Used for outside classes that have a reference to TabsConsole\r
612         public void SelectTab(string name)\r
613         {\r
614             tabs[name.ToLower()].Select();\r
615         }\r
616 \r
617         public bool TabExists(string name)\r
618         {\r
619             return tabs.ContainsKey(name.ToLower());\r
620         }\r
621 \r
622         public RadegastTab GetTab(string name)\r
623         {\r
624             return tabs[name.ToLower()];\r
625         }\r
626 \r
627         public List<RadegastTab> GetOtherTabs()\r
628         {\r
629             List<RadegastTab> otherTabs = new List<RadegastTab>();\r
630 \r
631             foreach (ToolStripItem item in tstTabs.Items)\r
632             {\r
633                 if (item.Tag == null) continue;\r
634                 if ((ToolStripItem)item == selectedTab.Button) continue;\r
635 \r
636                 RadegastTab tab = tabs[item.Tag.ToString()];\r
637                 if (!tab.AllowMerge) continue;\r
638                 if (tab.Merged) continue;\r
639 \r
640                 otherTabs.Add(tab);\r
641             }\r
642 \r
643             return otherTabs;\r
644         }\r
645 \r
646         /// <summary>\r
647         /// Activates the next tab\r
648         /// </summary>\r
649         public void SelectNextTab()\r
650         {\r
651             List<ToolStripItem> buttons = new List<ToolStripItem>();\r
652 \r
653             foreach (ToolStripItem item in tstTabs.Items)\r
654             {\r
655                 if (item.Tag == null || !item.Visible) continue;\r
656 \r
657                 buttons.Add(item);\r
658             }\r
659 \r
660             int current = 0;\r
661 \r
662             for (int i = 0; i < buttons.Count; i++)\r
663             {\r
664                 if (buttons[i] == selectedTab.Button)\r
665                 {\r
666                     current = i;\r
667                     break;\r
668                 }\r
669             }\r
670 \r
671             current++;\r
672 \r
673             if (current == buttons.Count)\r
674                 current = 0;\r
675 \r
676             SelectTab(tabs[buttons[current].Tag.ToString()].Name);\r
677         }\r
678 \r
679         /// <summary>\r
680         /// Activates the previous tab\r
681         /// </summary>\r
682         public void SelectPreviousTab()\r
683         {\r
684             List<ToolStripItem> buttons = new List<ToolStripItem>();\r
685 \r
686             foreach (ToolStripItem item in tstTabs.Items)\r
687             {\r
688                 if (item.Tag == null || !item.Visible) continue;\r
689 \r
690                 buttons.Add(item);\r
691             }\r
692 \r
693             int current = 0;\r
694 \r
695             for (int i = 0; i < buttons.Count; i++)\r
696             {\r
697                 if (buttons[i] == selectedTab.Button)\r
698                 {\r
699                     current = i;\r
700                     break;\r
701                 }\r
702             }\r
703 \r
704             current--;\r
705 \r
706             if (current == -1)\r
707                 current = buttons.Count - 1;\r
708 \r
709             SelectTab(tabs[buttons[current].Tag.ToString()].Name);\r
710         }\r
711 \r
712 \r
713         public IMTabWindow AddIMTab(UUID target, UUID session, string targetName)\r
714         {\r
715             IMTabWindow imTab = new IMTabWindow(instance, target, session, targetName);\r
716 \r
717             RadegastTab tab = AddTab(session.ToString(), "IM: " + targetName, imTab);\r
718             imTab.SelectIMInput();\r
719             tab.Highlight();\r
720 \r
721             return imTab;\r
722         }\r
723 \r
724         public ConferenceIMTabWindow AddConferenceIMTab(UUID session, string name)\r
725         {\r
726             ConferenceIMTabWindow imTab = new ConferenceIMTabWindow(instance, session, name);\r
727 \r
728             RadegastTab tab = AddTab(session.ToString(), name, imTab);\r
729             imTab.SelectIMInput();\r
730 \r
731             return imTab;\r
732         }\r
733 \r
734 \r
735         public ConferenceIMTabWindow AddConferenceIMTab(InstantMessageEventArgs e)\r
736         {\r
737             ConferenceIMTabWindow imTab = AddConferenceIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));\r
738             imTab.TextManager.ProcessIM(e);\r
739             return imTab;\r
740         }\r
741 \r
742         public GroupIMTabWindow AddGroupIMTab(UUID session, string name)\r
743         {\r
744             GroupIMTabWindow imTab = new GroupIMTabWindow(instance, session, name);\r
745 \r
746             RadegastTab tab = AddTab(session.ToString(), name, imTab);\r
747             imTab.SelectIMInput();\r
748 \r
749             return imTab;\r
750         }\r
751 \r
752         public GroupIMTabWindow AddGroupIMTab(InstantMessageEventArgs e)\r
753         {\r
754             GroupIMTabWindow imTab = AddGroupIMTab(e.IM.IMSessionID, Utils.BytesToString(e.IM.BinaryBucket));\r
755             imTab.TextManager.ProcessIM(e);\r
756             return imTab;\r
757         }\r
758 \r
759         public IMTabWindow AddIMTab(InstantMessageEventArgs e)\r
760         {\r
761             IMTabWindow imTab = AddIMTab(e.IM.FromAgentID, e.IM.IMSessionID, e.IM.FromAgentName);\r
762             imTab.TextManager.ProcessIM(e);\r
763             return imTab;\r
764         }\r
765 \r
766         public OutfitTextures AddOTTab(Avatar avatar)\r
767         {\r
768             OutfitTextures otTab = new OutfitTextures(instance, avatar);\r
769 \r
770             RadegastTab tab = AddTab("OT: " + avatar.Name, "OT: " + avatar.Name, otTab);\r
771             otTab.GetTextures();\r
772             return otTab;\r
773         }\r
774 \r
775         public MasterTab AddMSTab(Avatar avatar)\r
776         {\r
777             MasterTab msTab = new MasterTab(instance, avatar);\r
778 \r
779             RadegastTab tab = AddTab("MS: " + avatar.Name, "MS: " + avatar.Name, msTab);\r
780             return msTab;\r
781         }\r
782 \r
783         public AttachmentTab AddATTab(Avatar avatar)\r
784         {\r
785             AttachmentTab atTab = new AttachmentTab(instance, avatar);\r
786 \r
787             RadegastTab tab = AddTab("AT: " + avatar.Name, "AT: " + avatar.Name, atTab);\r
788             return atTab;\r
789         }\r
790 \r
791         public AnimTab AddAnimTab(Avatar avatar)\r
792         {\r
793             AnimTab animTab = new AnimTab(instance, avatar);\r
794 \r
795             RadegastTab tab = AddTab("Anim: " + avatar.Name, "Anim: " + avatar.Name, animTab);\r
796             return animTab;\r
797         }\r
798 \r
799         private void tbtnTabOptions_Click(object sender, EventArgs e)\r
800         {\r
801             tmnuMergeWith.Enabled = selectedTab.AllowMerge;\r
802             tmnuDetachTab.Enabled = selectedTab.AllowDetach;\r
803 \r
804             tmnuMergeWith.DropDown.Items.Clear();\r
805 \r
806             if (!selectedTab.AllowMerge) return;\r
807             if (!selectedTab.Merged)\r
808             {\r
809                 tmnuMergeWith.Text = "Merge With";\r
810 \r
811                 List<RadegastTab> otherTabs = GetOtherTabs();\r
812 \r
813                 tmnuMergeWith.Enabled = (otherTabs.Count > 0);\r
814                 if (!tmnuMergeWith.Enabled) return;\r
815 \r
816                 foreach (RadegastTab tab in otherTabs)\r
817                 {\r
818                     ToolStripItem item = tmnuMergeWith.DropDown.Items.Add(tab.Label);\r
819                     item.Tag = tab.Name;\r
820                     item.Click += new EventHandler(MergeItemClick);\r
821                 }\r
822             }\r
823             else\r
824             {\r
825                 tmnuMergeWith.Text = "Split";\r
826                 tmnuMergeWith.Click += new EventHandler(SplitClick);\r
827             }\r
828         }\r
829 \r
830         private void MergeItemClick(object sender, EventArgs e)\r
831         {\r
832             ToolStripItem item = (ToolStripItem)sender;\r
833             RadegastTab tab = tabs[item.Tag.ToString()];\r
834 \r
835             selectedTab.MergeWith(tab);\r
836 \r
837             SplitContainer container = (SplitContainer)selectedTab.Control;\r
838             toolStripContainer1.ContentPanel.Controls.Add(container);\r
839 \r
840             selectedTab.Select();\r
841             RemoveTabEntry(tab);\r
842 \r
843             tabs.Add(tab.Name, selectedTab);\r
844         }\r
845 \r
846         private void SplitClick(object sender, EventArgs e)\r
847         {\r
848             SplitTab(selectedTab);\r
849             selectedTab.Select();\r
850         }\r
851 \r
852         public void SplitTab(RadegastTab tab)\r
853         {\r
854             RadegastTab otherTab = tab.Split();\r
855             if (otherTab == null) return;\r
856 \r
857             toolStripContainer1.ContentPanel.Controls.Add(tab.Control);\r
858             toolStripContainer1.ContentPanel.Controls.Add(otherTab.Control);\r
859 \r
860             tabs.Remove(otherTab.Name);\r
861             AddTab(otherTab);\r
862         }\r
863 \r
864         private void tmnuDetachTab_Click(object sender, EventArgs e)\r
865         {\r
866             if (!selectedTab.AllowDetach) return;\r
867             RadegastTab tab = selectedTab;\r
868             tabs["chat"].Select();\r
869             tab.Detach(instance);\r
870         }\r
871 \r
872         private void tbtnCloseTab_Click(object sender, EventArgs e)\r
873         {\r
874             RadegastTab tab = selectedTab;\r
875             if (tab.AllowHide)\r
876                 tab.Hide();\r
877             else if (tab.AllowClose)\r
878                 tab.Close();\r
879         }\r
880 \r
881         private void TabsConsole_Load(object sender, EventArgs e)\r
882         {\r
883             owner = this.FindForm();\r
884         }\r
885 \r
886         private void ctxTabs_Opening(object sender, CancelEventArgs e)\r
887         {\r
888             Point pt = this.PointToClient(Cursor.Position);\r
889             ToolStripItem stripItem = tstTabs.GetItemAt(pt);\r
890 \r
891             if (stripItem == null)\r
892             {\r
893                 e.Cancel = true;\r
894             }\r
895             else\r
896             {\r
897                 tabs[stripItem.Tag.ToString()].Select();\r
898 \r
899                 ctxBtnClose.Enabled = selectedTab.AllowClose || selectedTab.AllowHide;\r
900                 ctxBtnDetach.Enabled = selectedTab.AllowDetach;\r
901                 ctxBtnMerge.Enabled = selectedTab.AllowMerge;\r
902                 ctxBtnMerge.DropDown.Items.Clear();\r
903 \r
904                 if (!ctxBtnClose.Enabled && !ctxBtnDetach.Enabled && !ctxBtnMerge.Enabled)\r
905                 {\r
906                     e.Cancel = true;\r
907                     return;\r
908                 }\r
909 \r
910                 if (!selectedTab.AllowMerge) return;\r
911                 if (!selectedTab.Merged)\r
912                 {\r
913                     ctxBtnMerge.Text = "Merge With";\r
914 \r
915                     List<RadegastTab> otherTabs = GetOtherTabs();\r
916 \r
917                     ctxBtnMerge.Enabled = (otherTabs.Count > 0);\r
918                     if (!ctxBtnMerge.Enabled) return;\r
919 \r
920                     foreach (RadegastTab tab in otherTabs)\r
921                     {\r
922                         ToolStripItem item = ctxBtnMerge.DropDown.Items.Add(tab.Label);\r
923                         item.Tag = tab.Name;\r
924                         item.Click += new EventHandler(MergeItemClick);\r
925                     }\r
926                 }\r
927                 else\r
928                 {\r
929                     ctxBtnMerge.Text = "Split";\r
930                     ctxBtnMerge.Click += new EventHandler(SplitClick);\r
931                 }\r
932 \r
933             }\r
934         }\r
935 \r
936     }\r
937 \r
938     /// <summary>\r
939     /// Arguments for tab events\r
940     /// </summary>\r
941     public class TabEventArgs : EventArgs\r
942     {\r
943         /// <summary>\r
944         /// Tab that was manipulated in the event\r
945         /// </summary>\r
946         public RadegastTab Tab;\r
947 \r
948         public TabEventArgs()\r
949             : base()\r
950         {\r
951         }\r
952 \r
953         public TabEventArgs(RadegastTab tab)\r
954             : base()\r
955         {\r
956             Tab = tab;\r
957         }\r
958     }\r
959 }\r