OSDN Git Service

De-register setting event hooks.
[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.session = session;\r
59 \r
60             textManager = new IMTextManager(this.instance, new RichTextBoxPrinter(rtbIMText), IMTextManagerType.Group, this.session, sessionName);\r
61 \r
62             btnShow.Text = "Show";\r
63             chatSplit.Panel2Collapsed = true;\r
64 \r
65             // Callbacks\r
66             RegisterClientEvents(client);\r
67             client.Self.RequestJoinGroupChat(session);\r
68 \r
69             UpdateFontSize();\r
70         }\r
71 \r
72         private void RegisterClientEvents(GridClient client)\r
73         {\r
74             client.Self.GroupChatJoined += new EventHandler<GroupChatJoinedEventArgs>(Self_GroupChatJoined);\r
75             client.Self.ChatSessionMemberAdded += new EventHandler<ChatSessionMemberAddedEventArgs>(Self_ChatSessionMemberAdded);\r
76             client.Self.ChatSessionMemberLeft += new EventHandler<ChatSessionMemberLeftEventArgs>(Self_ChatSessionMemberLeft);\r
77             client.Avatars.UUIDNameReply += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
78             instance.Netcom.ClientConnected += new EventHandler<EventArgs>(Netcom_Connected);\r
79             instance.Netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(Netcom_Disconnected);\r
80             instance.GlobalSettings.OnSettingChanged += new Settings.SettingChangedCallback(GlobalSettings_OnSettingChanged);\r
81             instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
82         }\r
83 \r
84         private void UnregisterClientEvents(GridClient client)\r
85         {\r
86             client.Self.GroupChatJoined -= new EventHandler<GroupChatJoinedEventArgs>(Self_GroupChatJoined);\r
87             client.Self.ChatSessionMemberAdded -= new EventHandler<ChatSessionMemberAddedEventArgs>(Self_ChatSessionMemberAdded);\r
88             client.Self.ChatSessionMemberLeft -= new EventHandler<ChatSessionMemberLeftEventArgs>(Self_ChatSessionMemberLeft);\r
89             client.Avatars.UUIDNameReply -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
90             instance.Netcom.ClientConnected -= new EventHandler<EventArgs>(Netcom_Connected);\r
91             instance.Netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_Disconnected);\r
92             instance.GlobalSettings.OnSettingChanged -= new Settings.SettingChangedCallback(GlobalSettings_OnSettingChanged);\r
93             instance.ClientChanged -= new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
94         }\r
95 \r
96         void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
97         {\r
98             UnregisterClientEvents(e.OldClient);\r
99             RegisterClientEvents(client);\r
100         }\r
101 \r
102         private void IMTabWindow_Disposed(object sender, EventArgs e)\r
103         {\r
104             if (instance.Netcom.IsLoggedIn)\r
105             {\r
106                 client.Self.RequestLeaveGroupChat(session);\r
107             }\r
108 \r
109             UnregisterClientEvents(client);\r
110             CleanUp();\r
111         }\r
112 \r
113         void UpdateFontSize()\r
114         {\r
115             float size = (float)instance.GlobalSettings["chat_font_size"].AsReal();\r
116             cbxInput.Font = ChatConsole.ChangeFontSize(cbxInput.Font, size);\r
117             rtbIMText.Font = ChatConsole.ChangeFontSize(rtbIMText.Font, size);\r
118             textManager.ReprintAllText();\r
119         }\r
120 \r
121         void GlobalSettings_OnSettingChanged(object sender, SettingsEventArgs e)\r
122         {\r
123             if (e.Key == "chat_font_size")\r
124                 UpdateFontSize();\r
125         }\r
126 \r
127         void Netcom_Disconnected(object sender, DisconnectedEventArgs e)\r
128         {\r
129             RefreshControls();\r
130         }\r
131 \r
132         void Netcom_Connected(object sender, EventArgs e)\r
133         {\r
134             client.Self.RequestJoinGroupChat(session);\r
135             RefreshControls();\r
136         }\r
137 \r
138         void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)\r
139         {\r
140             if (InvokeRequired)\r
141             {\r
142                 BeginInvoke(new MethodInvoker(() => Avatars_UUIDNameReply(sender, e)));\r
143                 return;\r
144             }\r
145 \r
146             lock (AvatarListSyncRoot)\r
147             {\r
148 \r
149                 Participants.BeginUpdate();\r
150 \r
151                 foreach (KeyValuePair<UUID, string> kvp in e.Names)\r
152                 {\r
153                     if (Participants.Items.ContainsKey(kvp.Key.ToString()))\r
154                         Participants.Items[kvp.Key.ToString()].Text = kvp.Value;\r
155                 }\r
156 \r
157                 Participants.Sort();\r
158                 Participants.EndUpdate();\r
159             }\r
160         }\r
161 \r
162         void Self_ChatSessionMemberLeft(object sender, ChatSessionMemberLeftEventArgs e)\r
163         {\r
164             if (e.SessionID == session)\r
165                 UpdateParticipantList();\r
166         }\r
167 \r
168         void Self_ChatSessionMemberAdded(object sender, ChatSessionMemberAddedEventArgs e)\r
169         {\r
170             if (e.SessionID == session)\r
171                 UpdateParticipantList();\r
172         }\r
173 \r
174         void UpdateParticipantList()\r
175         {\r
176             if (InvokeRequired)\r
177             {\r
178                 BeginInvoke(new MethodInvoker(UpdateParticipantList));\r
179                 return;\r
180             }\r
181 \r
182             try\r
183             {\r
184                 lock (AvatarListSyncRoot)\r
185                 {\r
186                     Participants.BeginUpdate();\r
187                     Participants.Items.Clear();\r
188 \r
189                     List<ChatSessionMember> participants;\r
190                     List<UUID> nameLookup = new List<UUID>();\r
191 \r
192                     if (client.Self.GroupChatSessions.TryGetValue(session, out participants))\r
193                     {\r
194                         ChatSessionMember[] members = participants.ToArray();\r
195                         for (int i = 0; i < members.Length; i++)\r
196                         {\r
197                             ChatSessionMember participant = members[i];\r
198                             ListViewItem item = new ListViewItem();\r
199                             item.Name = participant.AvatarKey.ToString();\r
200                             if (instance.nameCache.ContainsKey(participant.AvatarKey))\r
201                             {\r
202                                 item.Text = instance.nameCache[participant.AvatarKey];\r
203                             }\r
204                             else\r
205                             {\r
206                                 item.Text = RadegastInstance.INCOMPLETE_NAME;\r
207                                 nameLookup.Add(participant.AvatarKey);\r
208                             }\r
209                             if (participant.IsModerator)\r
210                                 item.Font = new Font(item.Font, FontStyle.Bold);\r
211                             Participants.Items.Add(item);\r
212                         }\r
213 \r
214                         if (nameLookup.Count > 0)\r
215                             client.Avatars.RequestAvatarNames(nameLookup);\r
216                     }\r
217 \r
218                     Participants.Sort();\r
219                     Participants.EndUpdate();\r
220                 }\r
221             }\r
222             catch (Exception)\r
223             {\r
224                 Participants.EndUpdate();\r
225             }\r
226         }\r
227 \r
228         void Self_GroupChatJoined(object sender, GroupChatJoinedEventArgs e)\r
229         {\r
230             if (e.SessionID != session && e.TmpSessionID != session)\r
231             {\r
232                 return;\r
233             }\r
234 \r
235             if (InvokeRequired)\r
236             {\r
237                 Invoke(new MethodInvoker(() => Self_GroupChatJoined(sender, e)));\r
238                 return;\r
239             }\r
240 \r
241             if (e.Success)\r
242             {\r
243                 textManager.TextPrinter.PrintTextLine("Join Group Chat Success!", Color.Green);\r
244                 WaitForSessionStart.Set();\r
245             }\r
246             else\r
247             {\r
248                 textManager.TextPrinter.PrintTextLine("Join Group Chat failed.", Color.Red);\r
249             }\r
250         }\r
251 \r
252         public void CleanUp()\r
253         {\r
254             textManager.CleanUp();\r
255             textManager = null;\r
256         }\r
257 \r
258         private void btnSend_Click(object sender, EventArgs e)\r
259         {\r
260             SendMsg();\r
261             this.ClearIMInput();\r
262         }\r
263 \r
264         private void btnShow_Click(object sender, EventArgs e)\r
265         {\r
266             if (chatSplit.Panel2Collapsed)\r
267             {\r
268                 chatSplit.Panel2Collapsed = false;\r
269                 btnShow.Text = "Hide";\r
270             }\r
271             else\r
272             {\r
273                 chatSplit.Panel2Collapsed = true;\r
274                 btnShow.Text = "Show";\r
275             }\r
276         }\r
277 \r
278         private void cbxInput_TextChanged(object sender, EventArgs e)\r
279         {\r
280             RefreshControls();\r
281         }\r
282 \r
283         private void RefreshControls()\r
284         {\r
285             if (InvokeRequired)\r
286             {\r
287                 BeginInvoke(new MethodInvoker(RefreshControls));\r
288                 return;\r
289             }\r
290 \r
291             if (!netcom.IsLoggedIn)\r
292             {\r
293                 cbxInput.Enabled = false;\r
294                 btnSend.Enabled = false;\r
295                 btnShow.Enabled = false;\r
296                 btnShow.Text = "Show";\r
297                 chatSplit.Panel2Collapsed = true;\r
298                 return;\r
299             }\r
300 \r
301             cbxInput.Enabled = true;\r
302             btnShow.Enabled = true;\r
303 \r
304             if (cbxInput.Text.Length > 0)\r
305             {\r
306                 btnSend.Enabled = true;\r
307             }\r
308             else\r
309             {\r
310                 btnSend.Enabled = false;\r
311             }\r
312         }\r
313 \r
314         private void cbxInput_KeyUp(object sender, KeyEventArgs e)\r
315         {\r
316             if (e.KeyCode != Keys.Enter) return;\r
317             e.SuppressKeyPress = true;\r
318 \r
319             SendMsg();\r
320         }\r
321 \r
322         private void SendMsg()\r
323         {\r
324             if (cbxInput.Text.Length == 0) return;\r
325 \r
326             string message = cbxInput.Text.Replace(ChatInputBox.NewlineMarker, "\n");\r
327 \r
328             if (instance.GlobalSettings["mu_emotes"].AsBoolean() && message.StartsWith(":"))\r
329             {\r
330                 message = "/me " + message.Substring(1);\r
331             }\r
332 \r
333             this.ClearIMInput();\r
334 \r
335             if (instance.RLV.RestictionActive("sendim")) return;\r
336 \r
337             if (message.Length > 1023) message = message.Remove(1023);\r
338 \r
339             if (!client.Self.GroupChatSessions.ContainsKey(session))\r
340             {\r
341                 WaitForSessionStart.Reset();\r
342                 client.Self.RequestJoinGroupChat(session);\r
343             }\r
344             else\r
345             {\r
346                 WaitForSessionStart.Set();\r
347             }\r
348 \r
349             if (WaitForSessionStart.WaitOne(10000, false))\r
350             {\r
351                 client.Self.InstantMessageGroup(session, message);\r
352             }\r
353             else\r
354             {\r
355                 textManager.TextPrinter.PrintTextLine("Cannot send group IM.", Color.Red);\r
356             }\r
357         }\r
358 \r
359         private void ClearIMInput()\r
360         {\r
361             cbxInput.Text = string.Empty;\r
362         }\r
363 \r
364         public void SelectIMInput()\r
365         {\r
366             cbxInput.Select();\r
367         }\r
368 \r
369         private void rtbIMText_LinkClicked(object sender, LinkClickedEventArgs e)\r
370         {\r
371             instance.MainForm.ProcessLink(e.LinkText);\r
372         }\r
373 \r
374         private void cbxInput_KeyDown(object sender, KeyEventArgs e)\r
375         {\r
376             if (e.KeyCode == Keys.Enter) e.SuppressKeyPress = true;\r
377         }\r
378 \r
379         public UUID SessionId\r
380         {\r
381             get { return session; }\r
382             set { session = value; }\r
383         }\r
384 \r
385         public IMTextManager TextManager\r
386         {\r
387             get { return textManager; }\r
388             set { textManager = value; }\r
389         }\r
390 \r
391         private void Participants_MouseDoubleClick(object sender, MouseEventArgs e)\r
392         {\r
393             ListViewItem item = Participants.GetItemAt(e.X, e.Y);\r
394             if (item != null)\r
395             {\r
396                 try\r
397                 {\r
398                     instance.MainForm.ShowAgentProfile(item.Text, new UUID(item.Name));\r
399                 }\r
400                 catch (Exception) { }\r
401             }\r
402         }\r
403 \r
404         private void cbxInput_VisibleChanged(object sender, EventArgs e)\r
405         {\r
406             if (Visible) cbxInput.Focus();\r
407         }\r
408 \r
409         private void cbxInput_SizeChanged(object sender, EventArgs e)\r
410         {\r
411             pnlChatInput.Height = cbxInput.Height + 7;\r
412         }\r
413     }\r
414 }\r