OSDN Git Service

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