OSDN Git Service

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