OSDN Git Service

Started adding infrastructure that will enable disconnect/reconnect RAD-58
[radegast/radegast.git] / Radegast / GUI / Consoles / GroupIMTabWindow.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.Drawing;\r
33 using System.Collections.Generic;\r
34 using System.Windows.Forms;\r
35 using System.Threading;\r
36 using Radegast.Netcom;\r
37 using OpenMetaverse;\r
38 \r
39 namespace Radegast\r
40 {\r
41     public partial class GroupIMTabWindow : UserControl\r
42     {\r
43         private RadegastInstance instance;\r
44         private GridClient client { get { return instance.Client; } }\r
45         private RadegastNetcom netcom { get { return instance.Netcom; } }\r
46         private UUID session;\r
47         private IMTextManager textManager;\r
48         private object AvatarListSyncRoot = new object();\r
49 \r
50         ManualResetEvent WaitForSessionStart = new ManualResetEvent(false);\r
51 \r
52         public GroupIMTabWindow(RadegastInstance instance, UUID session, string sessionName)\r
53         {\r
54             InitializeComponent();\r
55             Disposed += new EventHandler(IMTabWindow_Disposed);\r
56 \r
57             this.instance = instance;\r
58             this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
59             this.session = session;\r
60 \r
61             textManager = new IMTextManager(this.instance, new RichTextBoxPrinter(rtbIMText), this.session, sessionName);\r
62 \r
63             btnShow.Text = "Show";\r
64             chatSplit.Panel2Collapsed = true;\r
65 \r
66             // Callbacks\r
67             RegisterClientEvents(client);\r
68             client.Self.RequestJoinGroupChat(session);\r
69         }\r
70 \r
71         private void RegisterClientEvents(GridClient client)\r
72         {\r
73             client.Self.GroupChatJoined += new EventHandler<GroupChatJoinedEventArgs>(Self_GroupChatJoined);\r
74             client.Self.ChatSessionMemberAdded += new EventHandler<ChatSessionMemberAddedEventArgs>(Self_ChatSessionMemberAdded);\r
75             client.Self.ChatSessionMemberLeft += new EventHandler<ChatSessionMemberLeftEventArgs>(Self_ChatSessionMemberLeft);\r
76             client.Avatars.UUIDNameReply += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
77             client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);\r
78             client.Network.OnDisconnected += new NetworkManager.DisconnectedCallback(Network_OnDisconnected);\r
79         }\r
80 \r
81         private void UnregisterClientEvents(GridClient client)\r
82         {\r
83             client.Self.GroupChatJoined -= new EventHandler<GroupChatJoinedEventArgs>(Self_GroupChatJoined);\r
84             client.Self.ChatSessionMemberAdded -= new EventHandler<ChatSessionMemberAddedEventArgs>(Self_ChatSessionMemberAdded);\r
85             client.Self.ChatSessionMemberLeft -= new EventHandler<ChatSessionMemberLeftEventArgs>(Self_ChatSessionMemberLeft);\r
86             client.Avatars.UUIDNameReply -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
87             client.Network.OnConnected -= new NetworkManager.ConnectedCallback(Network_OnConnected);\r
88             client.Network.OnDisconnected -= new NetworkManager.DisconnectedCallback(Network_OnDisconnected);\r
89         }\r
90 \r
91         void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
92         {\r
93             UnregisterClientEvents(e.OldClient);\r
94             RegisterClientEvents(client);\r
95         }\r
96 \r
97         private void IMTabWindow_Disposed(object sender, EventArgs e)\r
98         {\r
99             client.Self.RequestLeaveGroupChat(session);\r
100             UnregisterClientEvents(client);\r
101             CleanUp();\r
102         }\r
103 \r
104         void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)\r
105         {\r
106             RefreshControls();\r
107         }\r
108 \r
109         void Network_OnConnected(object sender)\r
110         {\r
111             client.Self.RequestJoinGroupChat(session);\r
112             RefreshControls();\r
113         }\r
114 \r
115         void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)\r
116         {\r
117             if (InvokeRequired)\r
118             {\r
119                 BeginInvoke(new MethodInvoker(() => Avatars_UUIDNameReply(sender, e)));\r
120                 return;\r
121             }\r
122 \r
123             lock (AvatarListSyncRoot)\r
124             {\r
125 \r
126                 Participants.BeginUpdate();\r
127 \r
128                 foreach (KeyValuePair<UUID, string> kvp in e.Names)\r
129                 {\r
130                     if (Participants.Items.ContainsKey(kvp.Key.ToString()))\r
131                         Participants.Items[kvp.Key.ToString()].Text = kvp.Value;\r
132                 }\r
133 \r
134                 Participants.Sort();\r
135                 Participants.EndUpdate();\r
136             }\r
137         }\r
138 \r
139         void Self_ChatSessionMemberLeft(object sender, ChatSessionMemberLeftEventArgs e)\r
140         {\r
141             if (e.SessionID == session)\r
142                 UpdateParticipantList();\r
143         }\r
144 \r
145         void Self_ChatSessionMemberAdded(object sender, ChatSessionMemberAddedEventArgs e)\r
146         {\r
147             if (e.SessionID == session)\r
148                 UpdateParticipantList();\r
149         }\r
150 \r
151         void UpdateParticipantList()\r
152         {\r
153             if (InvokeRequired)\r
154             {\r
155                 BeginInvoke(new MethodInvoker(UpdateParticipantList));\r
156                 return;\r
157             }\r
158 \r
159             try\r
160             {\r
161                 lock (AvatarListSyncRoot)\r
162                 {\r
163                     Participants.BeginUpdate();\r
164                     Participants.Items.Clear();\r
165 \r
166                     List<ChatSessionMember> participants;\r
167                     List<UUID> nameLookup = new List<UUID>();\r
168 \r
169                     if (client.Self.GroupChatSessions.TryGetValue(session, out participants))\r
170                     {\r
171                         ChatSessionMember[] members = participants.ToArray();\r
172                         for (int i = 0; i < members.Length; i++)\r
173                         {\r
174                             ChatSessionMember participant = members[i];\r
175                             ListViewItem item = new ListViewItem();\r
176                             item.Name = participant.AvatarKey.ToString();\r
177                             if (instance.nameCache.ContainsKey(participant.AvatarKey))\r
178                             {\r
179                                 item.Text = instance.nameCache[participant.AvatarKey];\r
180                             }\r
181                             else\r
182                             {\r
183                                 item.Text = RadegastInstance.INCOMPLETE_NAME;\r
184                                 nameLookup.Add(participant.AvatarKey);\r
185                             }\r
186                             if (participant.IsModerator)\r
187                                 item.Font = new Font(item.Font, FontStyle.Bold);\r
188                             Participants.Items.Add(item);\r
189                         }\r
190 \r
191                         if (nameLookup.Count > 0)\r
192                             client.Avatars.RequestAvatarNames(nameLookup);\r
193                     }\r
194 \r
195                     Participants.Sort();\r
196                     Participants.EndUpdate();\r
197                 }\r
198             }\r
199             catch (Exception)\r
200             {\r
201                 Participants.EndUpdate();\r
202             }\r
203         }\r
204 \r
205         void Self_GroupChatJoined(object sender, GroupChatJoinedEventArgs e)\r
206         {\r
207             if (e.SessionID != session && e.TmpSessionID != session)\r
208             {\r
209                 return;\r
210             }\r
211 \r
212             if (InvokeRequired)\r
213             {\r
214                 Invoke(new MethodInvoker(() => Self_GroupChatJoined(sender, e)));\r
215                 return;\r
216             }\r
217 \r
218             if (e.Success)\r
219             {\r
220                 textManager.TextPrinter.PrintTextLine("Join Group Chat Success!", Color.Green);\r
221                 WaitForSessionStart.Set();\r
222             }\r
223             else\r
224             {\r
225                 textManager.TextPrinter.PrintTextLine("Join Group Chat failed.", Color.Red);\r
226             }\r
227         }\r
228 \r
229         public void CleanUp()\r
230         {\r
231             textManager.CleanUp();\r
232             textManager = null;\r
233         }\r
234 \r
235         private void btnSend_Click(object sender, EventArgs e)\r
236         {\r
237             SendMsg();\r
238             this.ClearIMInput();\r
239         }\r
240 \r
241         private void btnShow_Click(object sender, EventArgs e)\r
242         {\r
243             if (chatSplit.Panel2Collapsed)\r
244             {\r
245                 chatSplit.Panel2Collapsed = false;\r
246                 btnShow.Text = "Hide";\r
247             }\r
248             else\r
249             {\r
250                 chatSplit.Panel2Collapsed = true;\r
251                 btnShow.Text = "Show";\r
252             }\r
253         }\r
254 \r
255         private void cbxInput_TextChanged(object sender, EventArgs e)\r
256         {\r
257             RefreshControls();\r
258         }\r
259 \r
260         private void RefreshControls()\r
261         {\r
262             if (InvokeRequired)\r
263             {\r
264                 BeginInvoke(new MethodInvoker(RefreshControls));\r
265                 return;\r
266             }\r
267 \r
268             if (!netcom.IsLoggedIn)\r
269             {\r
270                 cbxInput.Enabled = false;\r
271                 btnSend.Enabled = false;\r
272                 btnShow.Enabled = false;\r
273                 btnShow.Text = "Show";\r
274                 chatSplit.Panel2Collapsed = true;\r
275                 return;\r
276             }\r
277 \r
278             cbxInput.Enabled = true;\r
279             btnShow.Enabled = true;\r
280            \r
281             if (cbxInput.Text.Length > 0)\r
282             {\r
283                 btnSend.Enabled = true;\r
284             }\r
285             else\r
286             {\r
287                 btnSend.Enabled = false;\r
288             }\r
289         }\r
290 \r
291         private void cbxInput_KeyUp(object sender, KeyEventArgs e)\r
292         {\r
293             if (e.KeyCode != Keys.Enter) return;\r
294             e.SuppressKeyPress = true;\r
295 \r
296             SendMsg();\r
297         }\r
298 \r
299         private void SendMsg()\r
300         {\r
301             if (cbxInput.Text.Length == 0) return;\r
302 \r
303             string message = cbxInput.Text;\r
304             if (message.Length > 1023) message = message.Remove(1023);\r
305 \r
306             if (!client.Self.GroupChatSessions.ContainsKey(session))\r
307             {\r
308                 WaitForSessionStart.Reset();\r
309                 client.Self.RequestJoinGroupChat(session);\r
310             }\r
311             else\r
312             {\r
313                 WaitForSessionStart.Set();\r
314             }\r
315 \r
316             if (WaitForSessionStart.WaitOne(10000, false))\r
317             {\r
318                 client.Self.InstantMessageGroup(session, message);\r
319             }\r
320             else\r
321             {\r
322                 textManager.TextPrinter.PrintTextLine("Cannot send group IM.", Color.Red);\r
323             }\r
324             this.ClearIMInput();\r
325         }\r
326 \r
327         private void ClearIMInput()\r
328         {\r
329             cbxInput.Items.Add(cbxInput.Text);\r
330             cbxInput.Text = string.Empty;\r
331         }\r
332 \r
333         public void SelectIMInput()\r
334         {\r
335             cbxInput.Select();\r
336         }\r
337 \r
338         private void rtbIMText_LinkClicked(object sender, LinkClickedEventArgs e)\r
339         {\r
340             instance.MainForm.ProcessLink(e.LinkText);\r
341         }\r
342 \r
343         private void cbxInput_KeyDown(object sender, KeyEventArgs e)\r
344         {\r
345             if (e.KeyCode == Keys.Enter) e.SuppressKeyPress = true;\r
346         }\r
347 \r
348         public UUID SessionId\r
349         {\r
350             get { return session; }\r
351             set { session = value; }\r
352         }\r
353 \r
354         public IMTextManager TextManager\r
355         {\r
356             get { return textManager; }\r
357             set { textManager = value; }\r
358         }\r
359 \r
360         private void Participants_MouseDoubleClick(object sender, MouseEventArgs e)\r
361         {\r
362             ListViewItem item = Participants.GetItemAt(e.X, e.Y);\r
363             if (item != null)\r
364             {\r
365                 try\r
366                 {\r
367                     instance.MainForm.ShowAgentProfile(item.Text, new UUID(item.Name));\r
368                 }\r
369                 catch (Exception) { }\r
370             }\r
371         }\r
372 \r
373     }\r
374 }\r