OSDN Git Service

Implemented group muting.
[radegast/radegast.git] / Radegast / GUI / Dialogs / MainForm.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2011, 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.Collections.Generic;
33 using System.Drawing;
34 using System.Text;
35 using System.Text.RegularExpressions;
36 using System.Timers;
37 using System.Threading;
38 using System.Windows.Forms;
39 using System.Resources;
40 using System.IO;
41 using System.Web;
42 using Radegast.Netcom;
43 using OpenMetaverse;
44 using OpenMetaverse.StructuredData;
45 using OpenMetaverse.Assets;
46
47 namespace Radegast
48 {
49     public partial class frmMain : RadegastForm
50     {
51         #region Public members
52         public static ImageList ResourceImages = new ImageList();
53         public static List<string> ImageNames = new List<string>();
54         public bool PreventParcelUpdate = false;
55         public delegate void ProfileHandlerDelegate(string agentName, UUID agentID);
56         public ProfileHandlerDelegate ShowAgentProfile;
57
58         public TabsConsole TabConsole
59         {
60             get { return tabsConsole; }
61         }
62
63         public MapConsole WorldMap
64         {
65             get
66             {
67                 if (MapTab != null)
68                 {
69                     return (MapConsole)MapTab.Control;
70                 }
71                 return null;
72             }
73         }
74
75         public RadegastTab MapTab
76         {
77             get
78             {
79                 if (tabsConsole.TabExists("map"))
80                 {
81                     return tabsConsole.Tabs["map"];
82                 }
83                 else
84                 {
85                     return null;
86                 }
87             }
88         }
89
90         public MediaConsole MediaConsole { get { return mediaConsole; } }
91
92         /// <summary>
93         /// Drop down that contains the tools menu
94         /// </summary>
95         public ToolStripDropDownButton ToolsMenu
96         {
97             get { return tbnTools; }
98         }
99
100         /// <summary>
101         /// Dropdown that contains the heelp menu
102         /// </summary>
103         public ToolStripDropDownButton HelpMenu
104         {
105             get { return tbtnHelp; }
106         }
107
108         /// <summary>
109         /// Drop down that contants the plugins menu. Make sure to set it Visible if
110         /// you add items to this menu, it's hidden by default
111         /// </summary>
112         public ToolStripDropDownButton PluginsMenu
113         {
114             get { return tbnPlugins; }
115         }
116
117         #endregion
118
119         #region Private members
120         private RadegastInstance instance;
121         private GridClient client { get { return instance.Client; } }
122         private RadegastNetcom netcom { get { return instance.Netcom; } }
123         private TabsConsole tabsConsole;
124         private System.Timers.Timer statusTimer;
125         private AutoPilot ap;
126         private bool AutoPilotActive = false;
127         private TransparentButton btnDialogNextControl;
128         private MediaConsole mediaConsole;
129         #endregion
130
131         #region Constructor and disposal
132         public frmMain(RadegastInstance instance)
133             : base(instance)
134         {
135             InitializeComponent();
136             Disposed += new EventHandler(frmMain_Disposed);
137
138             this.instance = instance;
139             this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
140             netcom.NetcomSync = this;
141             ShowAgentProfile = ShowAgentProfileInternal;
142
143             pnlDialog.Visible = false;
144             btnDialogNextControl = new TransparentButton();
145             pnlDialog.Controls.Add(btnDialogNextControl);
146             pnlDialog.Top = 0;
147
148             btnDialogNextControl.Size = new Size(35, 20);
149             btnDialogNextControl.BackColor = Color.Transparent;
150             btnDialogNextControl.ForeColor = Color.Gold;
151             btnDialogNextControl.FlatAppearance.BorderSize = 0;
152             btnDialogNextControl.FlatStyle = FlatStyle.Flat;
153             btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
154             btnDialogNextControl.Text = ">>";
155             btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);
156             btnDialogNextControl.Margin = new Padding(0);
157             btnDialogNextControl.Padding = new Padding(0);
158             btnDialogNextControl.UseVisualStyleBackColor = false;
159             btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
160             btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
161             btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);
162
163             if (instance.MonoRuntime)
164             {
165                 statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;
166             }
167
168             // Config options
169             if (instance.GlobalSettings["transaction_notification_chat"].Type == OSDType.Unknown)
170                 instance.GlobalSettings["transaction_notification_chat"] = OSD.FromBoolean(true);
171
172             if (instance.GlobalSettings["transaction_notification_dialog"].Type == OSDType.Unknown)
173                 instance.GlobalSettings["transaction_notification_dialog"] = OSD.FromBoolean(true);
174
175             if (!instance.GlobalSettings.ContainsKey("minimize_to_tray"))
176                 instance.GlobalSettings["minimize_to_tray"] = OSD.FromBoolean(false);
177
178             // Callbacks
179             netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
180             netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
181             netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
182             instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
183             RegisterClientEvents(client);
184
185             InitializeStatusTimer();
186             RefreshWindowTitle();
187         }
188
189         private void RegisterClientEvents(GridClient client)
190         {
191             client.Parcels.ParcelProperties += new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
192             client.Self.MoneyBalanceReply += new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
193             client.Self.MoneyBalance += new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
194         }
195
196         private void UnregisterClientEvents(GridClient client)
197         {
198             client.Parcels.ParcelProperties -= new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
199             client.Self.MoneyBalanceReply -= new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
200             client.Self.MoneyBalance -= new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
201         }
202
203         void instance_ClientChanged(object sender, ClientChangedEventArgs e)
204         {
205             UnregisterClientEvents(e.OldClient);
206             RegisterClientEvents(client);
207         }
208
209         void frmMain_Disposed(object sender, EventArgs e)
210         {
211             if (netcom != null)
212             {
213                 netcom.NetcomSync = null;
214                 netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
215                 netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
216                 netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
217             }
218             
219             if (client != null)
220             {
221                 UnregisterClientEvents(client);
222             }
223
224             if (instance != null && instance.Names != null)
225             {
226                 instance.Names.NameUpdated -= new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
227             }
228
229             this.instance.CleanUp();
230         }
231         #endregion
232
233         #region Event handlers
234         bool firstMoneyNotification = true;
235         void Self_MoneyBalance(object sender, BalanceEventArgs e)
236         {
237             int oldBalance = 0;
238             int.TryParse(tlblMoneyBalance.Text, out oldBalance);
239             int delta = Math.Abs(oldBalance - e.Balance);
240
241             if (firstMoneyNotification)
242             {
243                 firstMoneyNotification = false;
244             }
245             else
246             {
247                 if (delta > 50)
248                 {
249                     if (oldBalance > e.Balance)
250                     {
251                         instance.MediaManager.PlayUISound(UISounds.MoneyIn);
252                     }
253                     else
254                     {
255                         instance.MediaManager.PlayUISound(UISounds.MoneyOut);
256                     }
257                 }
258             }
259         }
260
261         void Names_NameUpdated(object sender, UUIDNameReplyEventArgs e)
262         {
263             if (!e.Names.ContainsKey(client.Self.AgentID)) return;
264
265             if (InvokeRequired)
266             {
267                 if (IsHandleCreated || !instance.MonoRuntime)
268                 {
269                     BeginInvoke(new MethodInvoker(() => Names_NameUpdated(sender, e)));
270                 }
271                 return;
272             }
273
274             RefreshWindowTitle();
275             RefreshStatusBar();
276         }
277
278         void Self_MoneyBalanceReply(object sender, MoneyBalanceReplyEventArgs e)
279         {
280             if (!String.IsNullOrEmpty(e.Description))
281             {
282                 if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())
283                     AddNotification(new ntfGeneric(instance, e.Description));
284                 if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())
285                     TabConsole.DisplayNotificationInChat(e.Description);
286             }
287         }
288
289         public void InitializeControls()
290         {
291             InitializeTabsConsole();
292
293             if (instance.MediaManager.SoundSystemAvailable)
294             {
295                 mediaConsole = new MediaConsole(instance);
296                 tbtnMedia.Visible = true;
297             }
298         }
299
300         public bool InAutoReconnect { get; set; }
301
302         private void DisplayAutoReconnectForm()
303         {
304             if (IsDisposed) return;
305
306             if (InvokeRequired)
307             {
308                 BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));
309                 return;
310             }
311
312             InAutoReconnect = true;
313             frmReconnect dialog = new frmReconnect(instance, 120);
314             dialog.ShowDialog(this);
315             dialog.Dispose();
316             dialog = null;
317         }
318
319         public void BeginAutoReconnect()
320         {
321             // Sleep for 3 seconds on a separate thread while things unwind on
322             // disconnect, since ShowDialog() blocks GUI thread
323             (new Thread(new ThreadStart(() =>
324                 {
325                     System.Threading.Thread.Sleep(3000);
326                     DisplayAutoReconnectForm();
327                 }
328                 ))
329                 {
330                     Name = "Reconnect Delay Thread",
331                     IsBackground = true
332                 }
333             ).Start();
334         }
335
336         private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)
337         {
338             if (e.Status == LoginStatus.Failed)
339             {
340                 if (InAutoReconnect)
341                 {
342                     if (instance.GlobalSettings["auto_reconnect"].AsBoolean())
343                         BeginAutoReconnect();
344                     else
345                         InAutoReconnect = false;
346                 }
347             }
348             else if (e.Status == LoginStatus.Success)
349             {
350                 InAutoReconnect = false;
351                 tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
352                 tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
353                     tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = true;
354
355                 statusTimer.Start();
356                 RefreshWindowTitle();
357             }
358         }
359
360         private void netcom_ClientLoggedOut(object sender, EventArgs e)
361         {
362             tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
363             tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
364                 tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = false;
365
366             reconnectToolStripMenuItem.Enabled = true;
367             InAutoReconnect = false;
368
369             if (statusTimer != null)
370                 statusTimer.Stop();
371
372             RefreshStatusBar();
373             RefreshWindowTitle();
374         }
375
376         private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
377         {
378             if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;
379             netcom_ClientLoggedOut(sender, EventArgs.Empty);
380
381             if (instance.GlobalSettings["auto_reconnect"].AsBoolean())
382             {
383                 BeginAutoReconnect();
384             }
385         }
386
387         private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
388         {
389             if (statusTimer != null)
390             {
391                 statusTimer.Stop();
392                 statusTimer.Dispose();
393                 statusTimer = null;
394             }
395
396             if (mediaConsole != null)
397             {
398                 if (tabsConsole.TabExists("media"))
399                 {
400                     tabsConsole.Tabs["media"].AllowClose = true;
401                     tabsConsole.Tabs["media"].Close();
402                 }
403                 else
404                 {
405                     mediaConsole.Dispose();
406                 }
407                 mediaConsole = null;
408             }
409
410             if (netcom.IsLoggedIn)
411             {
412                 Thread saveInvToDisk = new Thread(new ThreadStart(
413                     delegate()
414                     {
415                         client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);
416                     }));
417                 saveInvToDisk.Name = "Save inventory to disk";
418                 saveInvToDisk.Start();
419
420                 netcom.Logout();
421             }
422         }
423         #endregion
424
425         # region Update status
426
427         void Parcels_ParcelProperties(object sender, ParcelPropertiesEventArgs e)
428         {
429             if (PreventParcelUpdate || e.Result != ParcelResult.Single) return;
430             if (InvokeRequired)
431             {
432                 BeginInvoke(new MethodInvoker(() => Parcels_ParcelProperties(sender, e)));
433                 return;
434             }
435
436             Parcel parcel = instance.State.Parcel = e.Parcel;
437
438             tlblParcel.Text = parcel.Name;
439             tlblParcel.ToolTipText = parcel.Desc;
440
441             if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)
442                 icoNoFly.Visible = true;
443             else
444                 icoNoFly.Visible = false;
445
446             if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)
447                 icoNoBuild.Visible = true;
448             else
449                 icoNoBuild.Visible = false;
450
451             if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)
452                 icoNoScript.Visible = true;
453             else
454                 icoNoScript.Visible = false;
455
456             if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)
457                 icoNoPush.Visible = true;
458             else
459                 icoNoPush.Visible = false;
460
461             if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)
462                 icoHealth.Visible = true;
463             else
464                 icoHealth.Visible = false;
465
466             if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)
467                 icoNoVoice.Visible = true;
468             else
469                 icoNoVoice.Visible = false;
470         }
471
472         private void RefreshStatusBar()
473         {
474             if (netcom.IsLoggedIn)
475             {
476                 tlblLoginName.Text = instance.Names.Get(client.Self.AgentID, client.Self.Name);
477                 tlblMoneyBalance.Text = client.Self.Balance.ToString();
478                 icoHealth.Text = client.Self.Health.ToString() + "%";
479
480                 tlblRegionInfo.Text =
481                     client.Network.CurrentSim.Name +
482                     " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +
483                     Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +
484                     Math.Floor(client.Self.SimPosition.Z).ToString() + ")";
485             }
486             else
487             {
488                 tlblLoginName.Text = "Offline";
489                 tlblMoneyBalance.Text = "0";
490                 icoHealth.Text = "0%";
491                 tlblRegionInfo.Text = "No Region";
492                 tlblParcel.Text = "No Parcel";
493
494                 icoHealth.Visible = false;
495                 icoNoBuild.Visible = false;
496                 icoNoFly.Visible = false;
497                 icoNoPush.Visible = false;
498                 icoNoScript.Visible = false;
499                 icoNoVoice.Visible = false;
500             }
501         }
502
503         private void RefreshWindowTitle()
504         {
505             string name = instance.Names.Get(client.Self.AgentID, client.Self.Name);
506             StringBuilder sb = new StringBuilder();
507             sb.Append("Radegast - ");
508
509             if (netcom.IsLoggedIn)
510             {
511                 sb.Append("[" + name + "]");
512
513                 if (instance.State.IsAway)
514                 {
515                     sb.Append(" - Away");
516                     if (instance.State.IsBusy) sb.Append(", Busy");
517                 }
518                 else if (instance.State.IsBusy)
519                 {
520                     sb.Append(" - Busy");
521                 }
522
523                 if (instance.State.IsFollowing)
524                 {
525                     sb.Append(" - Following ");
526                     sb.Append(instance.State.FollowName);
527                 }
528             }
529             else
530             {
531                 sb.Append("Logged Out");
532             }
533
534             this.Text = sb.ToString();
535
536             // When minimized to tray, update tray tool tip also
537             if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"])
538             {
539                 trayIcon.Text = sb.ToString();
540                 ctxTrayMenuLabel.Text = sb.ToString();
541             }
542
543             sb = null;
544         }
545
546         private void InitializeStatusTimer()
547         {
548             statusTimer = new System.Timers.Timer(250);
549             statusTimer.SynchronizingObject = this;
550             statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);
551         }
552
553         private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)
554         {
555             // Mono sometimes fires timer after is's disposed
556             try
557             {
558                 RefreshWindowTitle();
559                 RefreshStatusBar();
560             }
561             catch { }
562         }
563         #endregion
564
565         #region Initialization, configuration, and key shortcuts
566         private void InitializeTabsConsole()
567         {
568             tabsConsole = new TabsConsole(instance);
569             tabsConsole.Dock = DockStyle.Fill;
570             toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);
571         }
572
573         private void frmMain_KeyDown(object sender, KeyEventArgs e)
574         {
575             // Ctrl-Shift-1 (sim/parcel info)
576             if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.D1)
577             {
578                 e.Handled = e.SuppressKeyPress = true;
579                 DisplayRegionParcelConsole();
580                 return;
581             }
582
583             // Ctrl-W: Close tab
584             if (e.Modifiers == Keys.Control && e.KeyCode == Keys.W)
585             {
586                 e.Handled = e.SuppressKeyPress = true;
587                 RadegastTab tab = tabsConsole.SelectedTab;
588
589                 if (tab.AllowClose)
590                 {
591                     tab.Close();
592                 }
593                 else if (tab.AllowHide)
594                 {
595                     tab.Hide();
596                 }
597
598                 return;
599             }
600
601             // Ctl-Shift-H: Teleport Home
602             if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.H)
603             {
604                 e.Handled = e.SuppressKeyPress = true;
605                 tmnuTeleportHome.PerformClick();
606                 return;
607             }
608
609             // Alt-Ctrl-D Open debug console
610             if (e.Modifiers == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.D)
611             {
612                 e.Handled = e.SuppressKeyPress = true;
613                 debugConsoleToolStripMenuItem.PerformClick();
614                 return;
615             }
616
617             // Alt 1-8: Toggle various tabs
618             if (e.Modifiers == Keys.Alt)
619             {
620                 switch (e.KeyCode)
621                 {
622                     case Keys.D1:
623                         e.Handled = e.SuppressKeyPress = true;
624                         tabsConsole.Tabs["chat"].Select();
625                         return;
626
627                     case Keys.D2:
628                         e.Handled = e.SuppressKeyPress = true;
629                         tbtnFriends.PerformClick();
630                         return;
631
632                     case Keys.D3:
633                         e.Handled = e.SuppressKeyPress = true;
634                         tbtnGroups.PerformClick();
635                         return;
636
637                     case Keys.D4:
638                         e.Handled = e.SuppressKeyPress = true;
639                         tbtnInventory.PerformClick();
640                         return;
641
642                     case Keys.D5:
643                         e.Handled = e.SuppressKeyPress = true;
644                         tbtnSearch.PerformClick();
645                         return;
646
647                     case Keys.D6:
648                         e.Handled = e.SuppressKeyPress = true;
649                         tbtnMap.PerformClick();
650                         return;
651
652                     case Keys.D7:
653                         e.Handled = e.SuppressKeyPress = true;
654                         tbnObjects.PerformClick();
655                         return;
656
657                     case Keys.D8:
658                         e.Handled = e.SuppressKeyPress = true;
659                         tbtnMedia.PerformClick();
660                         return;
661
662                     case Keys.D9:
663                         e.Handled = e.SuppressKeyPress = true;
664                         tbtnVoice.PerformClick();
665                         return;
666                 }
667             }
668
669             // ctrl-g, goto slurl
670             if (e.Control && e.KeyCode == Keys.G)
671             {
672                 if (!ProcessLink(Clipboard.GetText(), true))
673                     MapToCurrentLocation();
674
675                 e.Handled = e.SuppressKeyPress = true;
676                 return;
677             }
678
679             // ctrl-(shift)-tab for next/previous tab
680             if (e.Control && e.KeyCode == Keys.Tab)
681             {
682                 if (e.Shift)
683                 {
684                     TabConsole.SelectPreviousTab();
685                 }
686                 else
687                 {
688                     TabConsole.SelectNextTab();
689                 }
690                 e.Handled = e.SuppressKeyPress = true;
691                 return;
692             }
693         }
694
695         bool firstLoad = true;
696
697         private void frmMain_Load(object sender, EventArgs e)
698         {
699             if (firstLoad)
700             {
701                 firstLoad = false;
702                 tabsConsole.SelectTab("login");
703                 ResourceManager rm = Properties.Resources.ResourceManager;
704                 ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
705                 System.Collections.IDictionaryEnumerator de = set.GetEnumerator();
706                 while (de.MoveNext() == true)
707                 {
708                     if (de.Entry.Value is Image)
709                     {
710                         Bitmap bitMap = de.Entry.Value as Bitmap;
711                         ResourceImages.Images.Add(bitMap);
712                         ImageNames.Add(de.Entry.Key.ToString());
713                     }
714                 }
715                 StartUpdateCheck(false);
716
717                 if (instance.PlainColors)
718                 {
719                     pnlDialog.BackColor = System.Drawing.Color.FromArgb(120, 220, 255);
720                 }
721
722             }
723         }
724         #endregion
725
726         #region Public methods
727
728         private Dictionary<UUID, frmProfile> shownProfiles = new Dictionary<UUID, frmProfile>();
729
730         void ShowAgentProfileInternal(string name, UUID agentID)
731         {
732             lock (shownProfiles)
733             {
734                 frmProfile profile = null;
735                 if (shownProfiles.TryGetValue(agentID, out profile))
736                 {
737                     profile.WindowState = FormWindowState.Normal;
738                     profile.Focus();
739                 }
740                 else
741                 {
742                     profile = new frmProfile(instance, name, agentID);
743
744                     profile.Disposed += (object sender, EventArgs e) =>
745                         {
746                             lock (shownProfiles)
747                             {
748                                 frmProfile agentProfile = (frmProfile)sender;
749                                 if (shownProfiles.ContainsKey(agentProfile.AgentID))
750                                     shownProfiles.Remove(agentProfile.AgentID);
751                             }
752                         };
753
754                     profile.Show();
755                     profile.Focus();
756                     shownProfiles.Add(agentID, profile);
757                 }
758             }
759         }
760
761         private Dictionary<UUID, frmGroupInfo> shownGroupProfiles = new Dictionary<UUID, frmGroupInfo>();
762
763         public void ShowGroupProfile(AvatarGroup group)
764         {
765             ShowGroupProfile(new OpenMetaverse.Group()
766             {
767                 ID = group.GroupID,
768                 InsigniaID = group.GroupInsigniaID,
769                 Name = group.GroupName
770             }
771             );
772         }
773
774         public void ShowGroupProfile(OpenMetaverse.Group group)
775         {
776             lock (shownGroupProfiles)
777             {
778                 frmGroupInfo profile = null;
779                 if (shownGroupProfiles.TryGetValue(group.ID, out profile))
780                 {
781                     profile.WindowState = FormWindowState.Normal;
782                     profile.Focus();
783                 }
784                 else
785                 {
786                     profile = new frmGroupInfo(instance, group);
787
788                     profile.Disposed += (object sender, EventArgs e) =>
789                         {
790                             lock (shownGroupProfiles)
791                             {
792                                 frmGroupInfo groupProfile = (frmGroupInfo)sender;
793                                 if (shownGroupProfiles.ContainsKey(groupProfile.Group.ID))
794                                     shownGroupProfiles.Remove(groupProfile.Group.ID);
795                             }
796                         };
797
798                     profile.Show();
799                     profile.Focus();
800                     shownGroupProfiles.Add(group.ID, profile);
801                 }
802             }
803         }
804
805         public void ProcessLink(string link)
806         {
807             ProcessLink(link, false);
808         }
809
810         public bool ProcessLink(string link, bool onlyMap)
811         {
812             if (!link.Contains("://"))
813             {
814                 link = "http://" + link;
815             }
816
817             Regex r = new Regex(@"^(http://(slurl\.com|maps\.secondlife\.com)/secondlife/|secondlife://)(?<region>[^/]+)/(?<x>\d+)/(?<y>\d+)(/(?<z>\d+))?",
818                 RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase
819                 );
820             Match m = r.Match(link);
821
822             if (m.Success)
823             {
824                 string region = HttpUtility.UrlDecode(m.Groups["region"].Value);
825                 int x = int.Parse(m.Groups["x"].Value);
826                 int y = int.Parse(m.Groups["y"].Value);
827                 int z = 0;
828
829                 if (!string.IsNullOrEmpty(m.Groups["z"].Value))
830                 {
831                     z = int.Parse(m.Groups["z"].Value);
832                 }
833
834                 MapTab.Select();
835                 WorldMap.DisplayLocation(region, x, y, z);
836                 return true;
837             }
838             else if (!onlyMap)
839             {
840                 System.Diagnostics.Process.Start(link);
841             }
842             return false;
843         }
844         #endregion
845
846         #region Notifications
847         CircularList<Control> notifications = new CircularList<Control>();
848
849         public Color NotificationBackground
850         {
851             get { return pnlDialog.BackColor; }
852         }
853
854         void ResizeNotificationByControl(Control active)
855         {
856             int Width = active.Size.Width + 6;
857             int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;
858             pnlDialog.Size = new Size(Width, Height);
859             pnlDialog.Top = 0;
860             pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;
861
862             btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
863             btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
864
865             btnDialogNextControl.BringToFront();
866         }
867
868         public void AddNotification(Control control)
869         {
870             if (InvokeRequired)
871             {
872                 BeginInvoke(new MethodInvoker(delegate()
873                 {
874                     AddNotification(control);
875                 }
876                 ));
877                 return;
878             }
879
880             FormFlash.StartFlash(this);
881             pnlDialog.Visible = true;
882             pnlDialog.BringToFront();
883
884             foreach (Control existing in notifications)
885             {
886                 existing.Visible = false;
887             }
888
889             notifications.Add(control);
890             control.Visible = true;
891             control.Anchor = AnchorStyles.Top | AnchorStyles.Left;
892             control.Top = 3;
893             control.Left = 3;
894             pnlDialog.Controls.Add(control);
895             ResizeNotificationByControl(control);
896
897             btnDialogNextControl.Visible = notifications.Count > 1;
898         }
899
900         public void RemoveNotification(Control control)
901         {
902             pnlDialog.Controls.Remove(control);
903             notifications.Remove(control);
904             control.Dispose();
905
906             if (notifications.HasNext)
907             {
908                 pnlDialog.Visible = true;
909                 Control active = notifications.Next;
910                 active.Visible = true;
911                 ResizeNotificationByControl(active);
912             }
913             else
914             {
915                 pnlDialog.Visible = false;
916             }
917
918             btnDialogNextControl.Visible = notifications.Count > 1;
919         }
920
921         private void btnDialogNextControl_Click(object sender, EventArgs e)
922         {
923             foreach (Control existing in notifications)
924             {
925                 existing.Visible = false;
926             }
927
928             if (notifications.HasNext)
929             {
930                 pnlDialog.Visible = true;
931                 Control active = notifications.Next;
932                 active.Visible = true;
933                 ResizeNotificationByControl(active);
934             }
935             else
936             {
937                 pnlDialog.Visible = false;
938             }
939
940         }
941         #endregion Notifications
942
943         #region Menu click handlers
944
945         private void tmnuStatusAway_Click(object sender, EventArgs e)
946         {
947             instance.State.SetAway(tmnuStatusAway.Checked);
948         }
949
950         private void tmnuHelpReadme_Click(object sender, EventArgs e)
951         {
952             System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");
953         }
954
955         private void tmnuStatusBusy_Click(object sender, EventArgs e)
956         {
957             instance.State.SetBusy(tmnuStatusBusy.Checked);
958         }
959
960         private void tmnuControlFly_Click(object sender, EventArgs e)
961         {
962             instance.State.SetFlying(tmnuControlFly.Checked);
963         }
964
965         private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)
966         {
967             instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);
968         }
969
970         private void tmnuPrefs_Click(object sender, EventArgs e)
971         {
972             (new frmSettings(instance)).ShowDialog();
973         }
974
975         private void tbtnAppearance_Click(object sender, EventArgs e)
976         {
977             client.Appearance.RequestSetAppearance(false);
978         }
979
980         private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)
981         {
982             PrimDeserializer.ImportFromFile(client);
983         }
984
985         private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)
986         {
987             if (ap == null)
988             {
989                 ap = new AutoPilot(client);
990                 /*
991                 ap.InsertWaypoint(new Vector3(66, 163, 21));
992                 ap.InsertWaypoint(new Vector3(66, 98, 21));
993
994                 ap.InsertWaypoint(new Vector3(101, 98, 21));
995                 ap.InsertWaypoint(new Vector3(101, 45, 21));
996                 ap.InsertWaypoint(new Vector3(93, 27, 21));
997                 ap.InsertWaypoint(new Vector3(106, 12, 21));
998                 ap.InsertWaypoint(new Vector3(123, 24, 21));
999                 ap.InsertWaypoint(new Vector3(114, 45, 21));
1000                 ap.InsertWaypoint(new Vector3(114, 98, 21));
1001
1002                 ap.InsertWaypoint(new Vector3(130, 98, 21));
1003                 ap.InsertWaypoint(new Vector3(130, 163, 21));
1004                  **/
1005                 ap.InsertWaypoint(new Vector3(64, 68, 21));
1006                 ap.InsertWaypoint(new Vector3(65, 20, 21));
1007                 ap.InsertWaypoint(new Vector3(33, 23, 21));
1008                 ap.InsertWaypoint(new Vector3(17, 39, 21));
1009                 ap.InsertWaypoint(new Vector3(17, 62, 21));
1010
1011
1012             }
1013             if (AutoPilotActive)
1014             {
1015                 AutoPilotActive = false;
1016                 ap.Stop();
1017             }
1018             else
1019             {
1020                 AutoPilotActive = true;
1021                 ap.Start();
1022             }
1023
1024         }
1025
1026         private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)
1027         {
1028             client.Assets.Cache.Clear();
1029         }
1030
1031         private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)
1032         {
1033             client.Appearance.RequestSetAppearance(true);
1034         }
1035
1036         public void MapToCurrentLocation()
1037         {
1038             if (MapTab != null && client.Network.Connected)
1039             {
1040                 MapTab.Select();
1041                 WorldMap.DisplayLocation(client.Network.CurrentSim.Name,
1042                     (int)client.Self.SimPosition.X,
1043                     (int)client.Self.SimPosition.Y,
1044                     (int)client.Self.SimPosition.Z);
1045             }
1046         }
1047
1048         private void standToolStripMenuItem_Click(object sender, EventArgs e)
1049         {
1050             instance.State.SetSitting(false, UUID.Zero);
1051         }
1052
1053         private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)
1054         {
1055             client.Self.SitOnGround();
1056         }
1057
1058         private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)
1059         {
1060             try { System.Diagnostics.Process.Start(Application.ExecutablePath); }
1061             catch (Exception) { }
1062         }
1063
1064         private void tmnuExit_Click(object sender, EventArgs e)
1065         {
1066             Close();
1067         }
1068
1069         private void tlblRegionInfo_Click(object sender, EventArgs e)
1070         {
1071             if (WorldMap != null && client.Network.Connected)
1072             {
1073                 MapTab.Select();
1074             }
1075         }
1076
1077         private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)
1078         {
1079             ScriptEditor se = new ScriptEditor(instance);
1080             se.Dock = DockStyle.Fill;
1081             se.ShowDetached();
1082         }
1083
1084         private void tmnuSetHome_Click(object sender, EventArgs e)
1085         {
1086             client.Self.SetHome();
1087         }
1088
1089         private void tmnuCreateLandmark_Click(object sender, EventArgs e)
1090         {
1091             string location = string.Format(", {0} ({1}, {2}, {3})",
1092                 client.Network.CurrentSim.Name,
1093                 (int)client.Self.SimPosition.X,
1094                 (int)client.Self.SimPosition.Y,
1095                 (int)client.Self.SimPosition.Z
1096                 );
1097
1098             string name = tlblParcel.Text;
1099             int maxLen = 63 - location.Length;
1100
1101             if (name.Length > maxLen)
1102                 name = name.Substring(0, maxLen);
1103
1104             name += location;
1105
1106             client.Inventory.RequestCreateItem(
1107                 client.Inventory.FindFolderForType(AssetType.Landmark),
1108                 name,
1109                 tlblParcel.ToolTipText,
1110                 AssetType.Landmark,
1111                 UUID.Random(),
1112                 InventoryType.Landmark,
1113                 PermissionMask.All,
1114                 (bool success, InventoryItem item) =>
1115                 {
1116                     if (success)
1117                     {
1118                         BeginInvoke(new MethodInvoker(() =>
1119                             {
1120                                 Landmark ln = new Landmark(instance, (InventoryLandmark)item);
1121                                 ln.Dock = DockStyle.Fill;
1122                                 ln.Detached = true;
1123                             }));
1124                     }
1125                 }
1126             );
1127         }
1128
1129
1130         private void timerWorldClock_Tick(object sender, EventArgs e)
1131         {
1132             lblTime.Text = instance.GetWorldTime().ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);
1133         }
1134
1135         private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)
1136         {
1137             ProcessLink("http://jira.openmetaverse.org/browse/RAD");
1138         }
1139
1140         private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)
1141         {
1142             (new frmAbout(instance)).ShowDialog();
1143         }
1144
1145         #region Update Checking
1146         private UpdateChecker updateChecker = null;
1147         private bool ManualUpdateCheck = false;
1148
1149         public void StartUpdateCheck(bool userInitiated)
1150         {
1151             ManualUpdateCheck = userInitiated;
1152
1153             if (updateChecker != null)
1154             {
1155                 if (ManualUpdateCheck)
1156                     tabsConsole.DisplayNotificationInChat("Update check already in progress.");
1157                 return;
1158             }
1159
1160             if (ManualUpdateCheck)
1161                 tabsConsole.DisplayNotificationInChat("Checking for updates...", ChatBufferTextStyle.StatusBlue);
1162             updateChecker = new UpdateChecker();
1163             updateChecker.OnUpdateInfoReceived += new UpdateChecker.UpdateInfoCallback(OnUpdateInfoReceived);
1164             updateChecker.StartCheck();
1165         }
1166
1167         private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
1168         {
1169             tabsConsole.SelectTab("chat");
1170             StartUpdateCheck(true);
1171         }
1172
1173         void OnUpdateInfoReceived(object sender, UpdateCheckerArgs e)
1174         {
1175             if (InvokeRequired)
1176             {
1177                 BeginInvoke(new MethodInvoker(() => OnUpdateInfoReceived(sender, e)));
1178                 return;
1179             }
1180
1181             if (!e.Success)
1182             {
1183                 if (ManualUpdateCheck)
1184                     tabsConsole.DisplayNotificationInChat("Error: Failed connecting to the update site.", ChatBufferTextStyle.StatusBlue);
1185             }
1186             else
1187             {
1188                 if (!ManualUpdateCheck && e.Info.DisplayMOTD)
1189                 {
1190                     tabsConsole.DisplayNotificationInChat(e.Info.MOTD, ChatBufferTextStyle.StatusBlue);
1191                 }
1192
1193                 if (e.Info.UpdateAvailable)
1194                 {
1195                     tabsConsole.DisplayNotificationInChat("New version available at " + e.Info.DownloadSite, ChatBufferTextStyle.Alert);
1196                 }
1197                 else
1198                 {
1199                     if (ManualUpdateCheck)
1200                         tabsConsole.DisplayNotificationInChat("Your version is up to date.", ChatBufferTextStyle.StatusBlue);
1201                 }
1202             }
1203
1204             updateChecker.Dispose();
1205             updateChecker = null;
1206         }
1207         #endregion
1208
1209         private void ToggleHidden(string tabName)
1210         {
1211             if (!tabsConsole.TabExists(tabName)) return;
1212
1213             RadegastTab tab = tabsConsole.Tabs[tabName];
1214
1215             if (tab.Hidden)
1216             {
1217                 tab.Show();
1218             }
1219             else
1220             {
1221                 if (!tab.Selected)
1222                 {
1223                     tab.Select();
1224                 }
1225                 else
1226                 {
1227                     tab.Hide();
1228                 }
1229             }
1230         }
1231
1232         private void tbtnFriends_Click(object sender, EventArgs e)
1233         {
1234             ToggleHidden("friends");
1235         }
1236
1237         private void tbtnInventory_Click(object sender, EventArgs e)
1238         {
1239             ToggleHidden("inventory");
1240         }
1241
1242         private void tbtnSearch_Click(object sender, EventArgs e)
1243         {
1244             ToggleHidden("search");
1245         }
1246
1247         private void tbtnGroups_Click(object sender, EventArgs e)
1248         {
1249             ToggleHidden("groups");
1250         }
1251
1252         private void tbtnVoice_Click(object sender, EventArgs e)
1253         {
1254             ToggleHidden("voice");
1255         }
1256
1257         private void tbtnMedia_Click(object sender, EventArgs e)
1258         {
1259             if (tabsConsole.TabExists("media"))
1260             {
1261                 ToggleHidden("media");
1262             }
1263             else
1264             {
1265                 RadegastTab tab = tabsConsole.AddTab("media", "Media", mediaConsole);
1266                 tab.AllowClose = false;
1267                 tab.AllowHide = true;
1268                 tab.Select();
1269             }
1270         }
1271
1272         private void debugConsoleToolStripMenuItem_Click(object sender, EventArgs e)
1273         {
1274             if (tabsConsole.TabExists("debug"))
1275             {
1276                 ToggleHidden("debug");
1277             }
1278             else
1279             {
1280                 RadegastTab tab = tabsConsole.AddTab("debug", "Debug", new DebugConsole(instance));
1281                 tab.AllowClose = false;
1282                 tab.AllowHide = true;
1283                 tab.Select();
1284             }
1285         }
1286
1287         private void tbnObjects_Click(object sender, EventArgs e)
1288         {
1289             if (tabsConsole.TabExists("objects"))
1290             {
1291                 RadegastTab tab = tabsConsole.Tabs["objects"];
1292                 if (!tab.Selected)
1293                 {
1294                     tab.Select();
1295                     ((ObjectsConsole)tab.Control).RefreshObjectList();
1296                 }
1297                 else
1298                 {
1299                     tab.Close();
1300                 }
1301             }
1302             else
1303             {
1304                 RadegastTab tab = tabsConsole.AddTab("objects", "Objects", new ObjectsConsole(instance));
1305                 tab.AllowClose = true;
1306                 tab.AllowDetach = true;
1307                 tab.Visible = true;
1308                 tab.AllowHide = false;
1309                 tab.Select();
1310                 ((ObjectsConsole)tab.Control).RefreshObjectList();
1311             }
1312         }
1313
1314         private void tbtnMap_Click(object sender, EventArgs e)
1315         {
1316             ToggleHidden("map");
1317             if (!MapTab.Hidden)
1318                 MapToCurrentLocation();
1319         }
1320
1321         private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
1322         {
1323             if (client.Network.Connected)
1324                 client.Network.RequestLogout();
1325         }
1326
1327         private void reconnectToolStripMenuItem_Click(object sender, EventArgs e)
1328         {
1329             instance.Reconnect();
1330         }
1331
1332         private frmKeyboardShortcuts keyboardShortcutsForm = null;
1333         private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)
1334         {
1335             if (keyboardShortcutsForm != null)
1336             {
1337                 keyboardShortcutsForm.Focus();
1338             }
1339             else
1340             {
1341                 keyboardShortcutsForm = new frmKeyboardShortcuts(instance);
1342
1343                 keyboardShortcutsForm.Disposed += (object senderx, EventArgs ex) =>
1344                     {
1345                         if (components != null)
1346                         {
1347                             components.Remove(keyboardShortcutsForm);
1348                         }
1349                         keyboardShortcutsForm = null;
1350                     };
1351
1352                 keyboardShortcutsForm.Show(this);
1353                 keyboardShortcutsForm.Top = Top + 100;
1354                 keyboardShortcutsForm.Left = Left + 100;
1355
1356                 if (components != null)
1357                 {
1358                     components.Add(keyboardShortcutsForm);
1359                 }
1360             }
1361         }
1362
1363         // Menu item for testing out stuff
1364         private void testToolStripMenuItem_Click(object sender, EventArgs e)
1365         {
1366             //instance.MediaManager.PlayUISound(UISounds.IM);
1367             //Random r = new Random();
1368             //client.Self.RequestMuteList((uint)r.Next());
1369         }
1370
1371         private void reloadInventoryToolStripMenuItem_Click(object sender, EventArgs e)
1372         {
1373             if (tabsConsole.TabExists("inventory"))
1374             {
1375                 ((InventoryConsole)tabsConsole.Tabs["inventory"].Control).ReloadInventory();
1376                 tabsConsole.Tabs["inventory"].Select();
1377             }
1378         }
1379
1380         private void btnLoadScript_Click(object sender, EventArgs e)
1381         {
1382             if (!TabConsole.TabExists("plugin_manager"))
1383             {
1384                 TabConsole.AddTab("plugin_manager", "Plugins", new PluginsTab(instance));
1385             }
1386             TabConsole.Tabs["plugin_manager"].Select();
1387         }
1388
1389         private void frmMain_Resize(object sender, EventArgs e)
1390         {
1391             if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"].AsBoolean())
1392             {
1393                 ShowInTaskbar = false;
1394                 trayIcon.Visible = true;
1395                 FormBorderStyle = FormBorderStyle.SizableToolWindow;
1396             }
1397         }
1398
1399         private void treyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
1400         {
1401             WindowState = FormWindowState.Normal;
1402             ShowInTaskbar = true;
1403             trayIcon.Visible = false;
1404             FormBorderStyle = FormBorderStyle.Sizable;
1405         }
1406
1407         private void ctxTreyRestore_Click(object sender, EventArgs e)
1408         {
1409             treyIcon_MouseDoubleClick(this, null);
1410         }
1411
1412         private void ctxTreyExit_Click(object sender, EventArgs e)
1413         {
1414             tmnuExit_Click(this, EventArgs.Empty);
1415         }
1416
1417         private void tmnuTeleportHome_Click(object sender, EventArgs e)
1418         {
1419             TabConsole.DisplayNotificationInChat("Teleporting home...");
1420             client.Self.RequestTeleport(UUID.Zero);
1421         }
1422  
1423         private void stopAllAnimationsToolStripMenuItem_Click(object sender, EventArgs e)
1424         {
1425             instance.State.StopAllAnimations();
1426         }
1427
1428         public void DisplayRegionParcelConsole()
1429         {
1430             if (tabsConsole.TabExists("current region info"))
1431             {
1432                 tabsConsole.Tabs["current region info"].Select();
1433                 (tabsConsole.Tabs["current region info"].Control as RegionInfo).UpdateDisplay();
1434             }
1435             else
1436             {
1437                 tabsConsole.AddTab("current region info", "Region info", new RegionInfo(instance));
1438                 tabsConsole.Tabs["current region info"].Select();
1439             }
1440         }
1441
1442         private void regionParcelToolStripMenuItem_Click(object sender, EventArgs e)
1443         {
1444             DisplayRegionParcelConsole();
1445         }
1446
1447         private void tlblParcel_Click(object sender, EventArgs e)
1448         {
1449             DisplayRegionParcelConsole();
1450         }
1451
1452         private void changeMyDisplayNameToolStripMenuItem_Click(object sender, EventArgs e)
1453         {
1454             if (!client.Avatars.DisplayNamesAvailable())
1455             {
1456                 tabsConsole.DisplayNotificationInChat("This grid does not support display names.", ChatBufferTextStyle.Error);
1457                 return;
1458             }
1459
1460             var dlg = new DisplayNameChange(instance);
1461             dlg.ShowDialog();
1462         }
1463
1464         private void muteListToolStripMenuItem_Click(object sender, EventArgs e)
1465         {
1466             if (!tabsConsole.TabExists("mute list console"))
1467             {
1468                 tabsConsole.AddTab("mute list console", "Mute List", new MuteList(instance));
1469             }
1470             tabsConsole.Tabs["mute list console"].Select();
1471         }
1472         #endregion
1473
1474     }
1475 }