OSDN Git Service

RAD-497 minimize to tray
[radegast/radegast.git] / Radegast / GUI / Dialogs / MainForm.cs
index bf2e8fc..d4be299 100644 (file)
-// \r
-// Radegast Metaverse Client\r
-// Copyright (c) 2009, Radegast Development Team\r
-// All rights reserved.\r
-// \r
-// Redistribution and use in source and binary forms, with or without\r
-// modification, are permitted provided that the following conditions are met:\r
-// \r
-//     * Redistributions of source code must retain the above copyright notice,\r
-//       this list of conditions and the following disclaimer.\r
-//     * Redistributions in binary form must reproduce the above copyright\r
-//       notice, this list of conditions and the following disclaimer in the\r
-//       documentation and/or other materials provided with the distribution.\r
-//     * Neither the name of the application "Radegast", nor the names of its\r
-//       contributors may be used to endorse or promote products derived from\r
-//       this software without specific prior written permission.\r
-// \r
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-//\r
-// $Id$\r
-//\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Drawing;\r
-using System.Text;\r
-using System.Text.RegularExpressions;\r
-using System.Timers;\r
-using System.Threading;\r
-using System.Windows.Forms;\r
-using System.Resources;\r
-using System.IO;\r
-using System.Web;\r
-using Radegast.Netcom;\r
-using OpenMetaverse;\r
-using OpenMetaverse.StructuredData;\r
-\r
-namespace Radegast\r
-{\r
-    public partial class frmMain : RadegastForm\r
-    {\r
-        #region Public members\r
-        public static ImageList ResourceImages = new ImageList();\r
-        public static List<string> ImageNames = new List<string>();\r
-\r
-        public TabsConsole TabConsole\r
-        {\r
-            get { return tabsConsole; }\r
-        }\r
-\r
-        public MapConsole WorldMap\r
-        {\r
-            get\r
-            {\r
-                if (MapTab != null)\r
-                {\r
-                    return (MapConsole)MapTab.Control;\r
-                }\r
-                return null;\r
-            }\r
-        }\r
-\r
-        public RadegastTab MapTab\r
-        {\r
-            get\r
-            {\r
-                if (tabsConsole.TabExists("map"))\r
-                {\r
-                    return tabsConsole.Tabs["map"];\r
-                }\r
-                else\r
-                {\r
-                    return null;\r
-                }\r
-            }\r
-        }\r
-\r
-        public MediaConsole MediaConsole { get { return mediaConsole; } }\r
-\r
-        /// <summary>\r
-        /// Drop down that contains the tools menu\r
-        /// </summary>\r
-        public ToolStripDropDownButton ToolsMenu\r
-        {\r
-            get { return tbnTools; }\r
-        }\r
-\r
-        /// <summary>\r
-        /// Dropdown that contains the heelp menu\r
-        /// </summary>\r
-        public ToolStripDropDownButton HelpMenu\r
-        {\r
-            get { return tbtnHelp; }\r
-        }\r
-\r
-        /// <summary>\r
-        /// Drop down that contants the plugins menu. Make sure to set it Visible if\r
-        /// you add items to this menu, it's hidden by default\r
-        /// </summary>\r
-        public ToolStripDropDownButton PluginsMenu\r
-        {\r
-            get { return tbnPlugins; }\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region Private members\r
-        private RadegastInstance instance;\r
-        private GridClient client { get { return instance.Client; } }\r
-        private RadegastNetcom netcom { get { return instance.Netcom; } }\r
-        private TabsConsole tabsConsole;\r
-        private System.Timers.Timer statusTimer;\r
-        private AutoPilot ap;\r
-        private bool AutoPilotActive = false;\r
-        private TransparentButton btnDialogNextControl;\r
-        private MediaConsole mediaConsole;\r
-        #endregion\r
-\r
-        #region Constructor and disposal\r
-        public frmMain(RadegastInstance instance)\r
-            : base(instance)\r
-        {\r
-            GetSLTimeZone();\r
-            InitializeComponent();\r
-            Disposed += new EventHandler(frmMain_Disposed);\r
-\r
-            this.instance = instance;\r
-            this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
-            netcom.NetcomSync = this;\r
-\r
-            pnlDialog.Visible = false;\r
-            btnDialogNextControl = new TransparentButton();\r
-            pnlDialog.Controls.Add(btnDialogNextControl);\r
-            pnlDialog.Top = 0;\r
-\r
-            btnDialogNextControl.Size = new Size(35, 20);\r
-            btnDialogNextControl.BackColor = Color.Transparent;\r
-            btnDialogNextControl.ForeColor = Color.Gold;\r
-            btnDialogNextControl.FlatAppearance.BorderSize = 0;\r
-            btnDialogNextControl.FlatStyle = FlatStyle.Flat;\r
-            btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;\r
-            btnDialogNextControl.Text = ">>";\r
-            btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);\r
-            btnDialogNextControl.Margin = new Padding(0);\r
-            btnDialogNextControl.Padding = new Padding(0);\r
-            btnDialogNextControl.UseVisualStyleBackColor = false;\r
-            btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
-            btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
-            btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);\r
-\r
-            if (instance.MonoRuntime)\r
-            {\r
-                statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;\r
-            }\r
-\r
-            // Config options\r
-            if (instance.GlobalSettings["transaction_notification_chat"].Type == OSDType.Unknown)\r
-                instance.GlobalSettings["transaction_notification_chat"] = OSD.FromBoolean(true);\r
-\r
-            if (instance.GlobalSettings["transaction_notification_dialog"].Type == OSDType.Unknown)\r
-                instance.GlobalSettings["transaction_notification_dialog"] = OSD.FromBoolean(true);\r
-\r
-            // Callbacks\r
-            netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
-            netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);\r
-            netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
-            RegisterClientEvents(client);\r
-\r
-            InitializeStatusTimer();\r
-            RefreshWindowTitle();\r
-        }\r
-\r
-        private void RegisterClientEvents(GridClient client)\r
-        {\r
-            client.Parcels.ParcelProperties += new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);\r
-            client.Self.MoneyBalanceReply += new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);\r
-        }\r
-\r
-        private void UnregisterClientEvents(GridClient client)\r
-        {\r
-            client.Parcels.ParcelProperties -= new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);\r
-            client.Self.MoneyBalanceReply -= new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);\r
-        }\r
-\r
-        void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
-        {\r
-            UnregisterClientEvents(e.OldClient);\r
-            RegisterClientEvents(client);\r
-        }\r
-\r
-        void frmMain_Disposed(object sender, EventArgs e)\r
-        {\r
-            netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
-            netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);\r
-            netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
-            UnregisterClientEvents(client);\r
-            this.instance.CleanUp();\r
-        }\r
-        #endregion\r
-\r
-        #region Event handlers\r
-        void Self_MoneyBalanceReply(object sender, MoneyBalanceReplyEventArgs e)\r
-        {\r
-            if (!String.IsNullOrEmpty(e.Description))\r
-            {\r
-                if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())\r
-                    AddNotification(new ntfGeneric(instance, e.Description));\r
-                if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())\r
-                    TabConsole.DisplayNotificationInChat(e.Description);\r
-            }\r
-        }\r
-\r
-        public void InitializeControls()\r
-        {\r
-            InitializeTabsConsole();\r
-\r
-            if (instance.MediaManager.SoundSystemAvailable)\r
-            {\r
-                mediaConsole = new MediaConsole(instance);\r
-                tbtnMedia.Visible = true;\r
-            }\r
-        }\r
-\r
-        public bool InAutoReconnect { get; set; }\r
-\r
-        private void DisplayAutoReconnectForm()\r
-        {\r
-            if (InvokeRequired)\r
-            {\r
-                BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));\r
-                return;\r
-            }\r
-\r
-            InAutoReconnect = true;\r
-            frmReconnect dialog = new frmReconnect(instance, 120);\r
-            dialog.ShowDialog(this);\r
-            dialog.Dispose();\r
-            dialog = null;\r
-        }\r
-\r
-        public void BeginAutoReconnect()\r
-        {\r
-            // Sleep for 3 seconds on a separate thread while things unwind on\r
-            // disconnect, since ShowDialog() blocks GUI thread\r
-            (new Thread(new ThreadStart(() =>\r
-                {\r
-                    System.Threading.Thread.Sleep(3000);\r
-                    DisplayAutoReconnectForm();\r
-                }\r
-                ))\r
-                {\r
-                    Name = "Reconnect Delay Thread",\r
-                    IsBackground = false\r
-                }\r
-            ).Start();\r
-        }\r
-\r
-        private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)\r
-        {\r
-            if (e.Status == LoginStatus.Failed)\r
-            {\r
-                if (InAutoReconnect)\r
-                {\r
-                    if (instance.GlobalSettings["auto_reconnect"].AsBoolean())\r
-                        BeginAutoReconnect();\r
-                    else\r
-                        InAutoReconnect = false;\r
-                }\r
-            }\r
-            else if (e.Status == LoginStatus.Success)\r
-            {\r
-                InAutoReconnect = false;\r
-                disconnectToolStripMenuItem.Enabled =\r
-                tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =\r
-                    tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = true;\r
-\r
-                statusTimer.Start();\r
-                RefreshWindowTitle();\r
-            }\r
-        }\r
-\r
-        private void netcom_ClientLoggedOut(object sender, EventArgs e)\r
-        {\r
-            disconnectToolStripMenuItem.Enabled =\r
-            tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =\r
-                tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = false;\r
-\r
-            reconnectToolStripMenuItem.Enabled = true;\r
-            InAutoReconnect = false;\r
-\r
-            statusTimer.Stop();\r
-\r
-            RefreshStatusBar();\r
-            RefreshWindowTitle();\r
-        }\r
-\r
-        private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)\r
-        {\r
-            if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;\r
-            netcom_ClientLoggedOut(sender, EventArgs.Empty);\r
-\r
-            if (instance.GlobalSettings["auto_reconnect"].AsBoolean())\r
-            {\r
-                BeginAutoReconnect();\r
-            }\r
-        }\r
-\r
-        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)\r
-        {\r
-            if (statusTimer != null)\r
-            {\r
-                statusTimer.Stop();\r
-                statusTimer.Dispose();\r
-                statusTimer = null;\r
-            }\r
-\r
-            if (mediaConsole != null)\r
-            {\r
-                if (tabsConsole.TabExists("media"))\r
-                {\r
-                    tabsConsole.Tabs["media"].AllowClose = true;\r
-                    tabsConsole.Tabs["media"].Close();\r
-                }\r
-                else\r
-                {\r
-                    mediaConsole.Dispose();\r
-                }\r
-                mediaConsole = null;\r
-            }\r
-\r
-            if (netcom.IsLoggedIn)\r
-            {\r
-                Thread saveInvToDisk = new Thread(new ThreadStart(\r
-                    delegate()\r
-                    {\r
-                        client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);\r
-                    }));\r
-                saveInvToDisk.Name = "Save inventory to disk";\r
-                saveInvToDisk.Start();\r
-\r
-                netcom.Logout();\r
-            }\r
-        }\r
-        #endregion\r
-\r
-        # region Update status\r
-\r
-        void Parcels_ParcelProperties(object sender, ParcelPropertiesEventArgs e)\r
-        {\r
-            if (e.Result != ParcelResult.Single) return;\r
-            if (InvokeRequired)\r
-            {\r
-                BeginInvoke(new MethodInvoker(() => Parcels_ParcelProperties(sender, e)));\r
-                return;\r
-            }\r
-\r
-            Parcel parcel = e.Parcel;\r
-\r
-            tlblParcel.Text = parcel.Name;\r
-            tlblParcel.ToolTipText = parcel.Desc;\r
-\r
-            if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)\r
-                icoNoFly.Visible = true;\r
-            else\r
-                icoNoFly.Visible = false;\r
-\r
-            if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)\r
-                icoNoBuild.Visible = true;\r
-            else\r
-                icoNoBuild.Visible = false;\r
-\r
-            if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)\r
-                icoNoScript.Visible = true;\r
-            else\r
-                icoNoScript.Visible = false;\r
-\r
-            if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)\r
-                icoNoPush.Visible = true;\r
-            else\r
-                icoNoPush.Visible = false;\r
-\r
-            if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)\r
-                icoHealth.Visible = true;\r
-            else\r
-                icoHealth.Visible = false;\r
-\r
-            if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)\r
-                icoNoVoice.Visible = true;\r
-            else\r
-                icoNoVoice.Visible = false;\r
-        }\r
-\r
-        private void RefreshStatusBar()\r
-        {\r
-            if (netcom.IsLoggedIn)\r
-            {\r
-                tlblLoginName.Text = netcom.LoginOptions.FullName;\r
-                tlblMoneyBalance.Text = client.Self.Balance.ToString();\r
-                icoHealth.Text = client.Self.Health.ToString() + "%";\r
-\r
-                tlblRegionInfo.Text =\r
-                    client.Network.CurrentSim.Name +\r
-                    " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +\r
-                    Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +\r
-                    Math.Floor(client.Self.SimPosition.Z).ToString() + ")";\r
-            }\r
-            else\r
-            {\r
-                tlblLoginName.Text = "Offline";\r
-                tlblMoneyBalance.Text = "0";\r
-                icoHealth.Text = "0%";\r
-                tlblRegionInfo.Text = "No Region";\r
-                tlblParcel.Text = "No Parcel";\r
-\r
-                icoHealth.Visible = false;\r
-                icoNoBuild.Visible = false;\r
-                icoNoFly.Visible = false;\r
-                icoNoPush.Visible = false;\r
-                icoNoScript.Visible = false;\r
-                icoNoVoice.Visible = false;\r
-            }\r
-        }\r
-\r
-        private void RefreshWindowTitle()\r
-        {\r
-            StringBuilder sb = new StringBuilder();\r
-            sb.Append("Radegast - ");\r
-\r
-            if (netcom.IsLoggedIn)\r
-            {\r
-                sb.Append("[" + netcom.LoginOptions.FullName + "]");\r
-\r
-                if (instance.State.IsAway)\r
-                {\r
-                    sb.Append(" - Away");\r
-                    if (instance.State.IsBusy) sb.Append(", Busy");\r
-                }\r
-                else if (instance.State.IsBusy)\r
-                {\r
-                    sb.Append(" - Busy");\r
-                }\r
-\r
-                if (instance.State.IsFollowing)\r
-                {\r
-                    sb.Append(" - Following ");\r
-                    sb.Append(instance.State.FollowName);\r
-                }\r
-            }\r
-            else\r
-            {\r
-                sb.Append("Logged Out");\r
-            }\r
-\r
-            this.Text = sb.ToString();\r
-            sb = null;\r
-        }\r
-\r
-        private void InitializeStatusTimer()\r
-        {\r
-            statusTimer = new System.Timers.Timer(250);\r
-            statusTimer.SynchronizingObject = this;\r
-            statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);\r
-        }\r
-\r
-        private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)\r
-        {\r
-            // Mono sometimes fires timer after is's disposed\r
-            try\r
-            {\r
-                RefreshWindowTitle();\r
-                RefreshStatusBar();\r
-            }\r
-            catch { }\r
-        }\r
-        #endregion\r
-\r
-        #region Initialization, configuration, and key shortcuts\r
-        private void InitializeTabsConsole()\r
-        {\r
-            tabsConsole = new TabsConsole(instance);\r
-            tabsConsole.Dock = DockStyle.Fill;\r
-            toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);\r
-        }\r
-\r
-        private void frmMain_KeyDown(object sender, KeyEventArgs e)\r
-        {\r
-            // Ctl-Shift-H: Teleport Home\r
-            if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.H)\r
-            {\r
-                e.Handled = e.SuppressKeyPress = true;\r
-                tmnuTeleportHome.PerformClick();\r
-                return;\r
-            }\r
-\r
-            // Alt 1-8: Toggle various tabs\r
-            if (e.Modifiers == Keys.Alt)\r
-            {\r
-                switch (e.KeyCode)\r
-                {\r
-                    case Keys.D1:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tabsConsole.Tabs["chat"].Select();\r
-                        break;\r
-\r
-                    case Keys.D2:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnFriends.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D3:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnGroups.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D4:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnInventory.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D5:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnSearch.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D6:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnMap.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D7:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbnObjects.PerformClick();\r
-                        break;\r
-\r
-                    case Keys.D8:\r
-                        e.Handled = e.SuppressKeyPress = true;\r
-                        tbtnMedia.PerformClick();\r
-                        break;\r
-                }\r
-            }\r
-\r
-            // ctrl-g, goto slurl\r
-            if (e.Control && e.KeyCode == Keys.G)\r
-            {\r
-                if (!ProcessLink(Clipboard.GetText(), true))\r
-                    MapToCurrentLocation();\r
-\r
-                e.Handled = e.SuppressKeyPress = true;\r
-                return;\r
-            }\r
-\r
-            // ctrl-(shift)-tab for next/previous tab\r
-            if (e.Control && e.KeyCode == Keys.Tab)\r
-            {\r
-                if (e.Shift)\r
-                {\r
-                    TabConsole.SelectPreviousTab();\r
-                }\r
-                else\r
-                {\r
-                    TabConsole.SelectNextTab();\r
-                }\r
-                e.Handled = e.SuppressKeyPress = true;\r
-                return;\r
-            }\r
-        }\r
-\r
-        private void frmMain_KeyUp(object sender, KeyEventArgs e)\r
-        {\r
-        }\r
-\r
-        private void frmMain_Load(object sender, EventArgs e)\r
-        {\r
-            tabsConsole.SelectTab("login");\r
-            ResourceManager rm = Properties.Resources.ResourceManager;\r
-            ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);\r
-            System.Collections.IDictionaryEnumerator de = set.GetEnumerator();\r
-            while (de.MoveNext() == true)\r
-            {\r
-                if (de.Entry.Value is Image)\r
-                {\r
-                    Bitmap bitMap = de.Entry.Value as Bitmap;\r
-                    ResourceImages.Images.Add(bitMap);\r
-                    ImageNames.Add(de.Entry.Key.ToString());\r
-                }\r
-            }\r
-            StartUpdateCheck(false);\r
-        }\r
-        #endregion\r
-\r
-        #region Public methods\r
-\r
-        private Dictionary<UUID, frmProfile> shownProfiles = new Dictionary<UUID, frmProfile>();\r
-\r
-        public void ShowAgentProfile(string name, UUID agentID)\r
-        {\r
-            lock (shownProfiles)\r
-            {\r
-                frmProfile profile = null;\r
-                if (shownProfiles.TryGetValue(agentID, out profile))\r
-                {\r
-                    profile.WindowState = FormWindowState.Normal;\r
-                    profile.Focus();\r
-                }\r
-                else\r
-                {\r
-                    profile = new frmProfile(instance, name, agentID);\r
-\r
-                    profile.Disposed += (object sender, EventArgs e) =>\r
-                        {\r
-                            lock (shownProfiles)\r
-                            {\r
-                                frmProfile agentProfile = (frmProfile)sender;\r
-                                if (shownProfiles.ContainsKey(agentProfile.AgentID))\r
-                                    shownProfiles.Remove(agentProfile.AgentID);\r
-                            }\r
-                        };\r
-\r
-                    profile.Show();\r
-                    profile.Focus();\r
-                    shownProfiles.Add(agentID, profile);\r
-                }\r
-            }\r
-        }\r
-\r
-        private Dictionary<UUID, frmGroupInfo> shownGroupProfiles = new Dictionary<UUID, frmGroupInfo>();\r
-\r
-        public void ShowGroupProfile(OpenMetaverse.Group group)\r
-        {\r
-            lock (shownGroupProfiles)\r
-            {\r
-                frmGroupInfo profile = null;\r
-                if (shownGroupProfiles.TryGetValue(group.ID, out profile))\r
-                {\r
-                    profile.WindowState = FormWindowState.Normal;\r
-                    profile.Focus();\r
-                }\r
-                else\r
-                {\r
-                    profile = new frmGroupInfo(instance, group);\r
-\r
-                    profile.Disposed += (object sender, EventArgs e) =>\r
-                        {\r
-                            lock (shownGroupProfiles)\r
-                            {\r
-                                frmGroupInfo groupProfile = (frmGroupInfo)sender;\r
-                                if (shownGroupProfiles.ContainsKey(groupProfile.Group.ID))\r
-                                    shownGroupProfiles.Remove(groupProfile.Group.ID);\r
-                            }\r
-                        };\r
-\r
-                    profile.Show();\r
-                    profile.Focus();\r
-                    shownGroupProfiles.Add(group.ID, profile);\r
-                }\r
-            }\r
-        }\r
-\r
-        public void ProcessLink(string link)\r
-        {\r
-            ProcessLink(link, false);\r
-        }\r
-\r
-        public bool ProcessLink(string link, bool onlyMap)\r
-        {\r
-            if (!link.Contains("://"))\r
-            {\r
-                link = "http://" + link;\r
-            }\r
-\r
-            Regex r = new Regex(@"^(http://slurl.com/secondlife/|secondlife://)([^/]+)/(\d+)/(\d+)(/(\d+))?");\r
-            Match m = r.Match(link);\r
-\r
-            if (m.Success)\r
-            {\r
-                string region = HttpUtility.UrlDecode(m.Groups[2].Value);\r
-                int x = int.Parse(m.Groups[3].Value);\r
-                int y = int.Parse(m.Groups[4].Value);\r
-                int z = 0;\r
-\r
-                if (m.Groups.Count > 5 && m.Groups[6].Value != String.Empty)\r
-                {\r
-                    z = int.Parse(m.Groups[6].Value);\r
-                }\r
-\r
-                MapTab.Select();\r
-                WorldMap.DisplayLocation(region, x, y, z);\r
-                return true;\r
-            }\r
-            else if (!onlyMap)\r
-            {\r
-                System.Diagnostics.Process.Start(link);\r
-            }\r
-            return false;\r
-        }\r
-        #endregion\r
-\r
-        #region Notifications\r
-        CircularList<Control> notifications = new CircularList<Control>();\r
-\r
-        public Color NotificationBackground\r
-        {\r
-            get { return pnlDialog.BackColor; }\r
-        }\r
-\r
-        void ResizeNotificationByControl(Control active)\r
-        {\r
-            int Width = active.Size.Width + 6;\r
-            int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;\r
-            pnlDialog.Size = new Size(Width, Height);\r
-            pnlDialog.Top = 0;\r
-            pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;\r
-\r
-            btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
-            btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
-\r
-            btnDialogNextControl.BringToFront();\r
-        }\r
-\r
-        public void AddNotification(Control control)\r
-        {\r
-            if (InvokeRequired)\r
-            {\r
-                BeginInvoke(new MethodInvoker(delegate()\r
-                {\r
-                    AddNotification(control);\r
-                }\r
-                ));\r
-                return;\r
-            }\r
-\r
-            FormFlash.StartFlash(this);\r
-            pnlDialog.Visible = true;\r
-            pnlDialog.BringToFront();\r
-\r
-            foreach (Control existing in notifications)\r
-            {\r
-                existing.Visible = false;\r
-            }\r
-\r
-            notifications.Add(control);\r
-            control.Visible = true;\r
-            control.Anchor = AnchorStyles.Top | AnchorStyles.Left;\r
-            control.Top = 3;\r
-            control.Left = 3;\r
-            pnlDialog.Controls.Add(control);\r
-            ResizeNotificationByControl(control);\r
-\r
-            btnDialogNextControl.Visible = notifications.Count > 1;\r
-        }\r
-\r
-        public void RemoveNotification(Control control)\r
-        {\r
-            pnlDialog.Controls.Remove(control);\r
-            notifications.Remove(control);\r
-            control.Dispose();\r
-\r
-            if (notifications.HasNext)\r
-            {\r
-                pnlDialog.Visible = true;\r
-                Control active = notifications.Next;\r
-                active.Visible = true;\r
-                ResizeNotificationByControl(active);\r
-            }\r
-            else\r
-            {\r
-                pnlDialog.Visible = false;\r
-            }\r
-\r
-            btnDialogNextControl.Visible = notifications.Count > 1;\r
-        }\r
-\r
-        private void btnDialogNextControl_Click(object sender, EventArgs e)\r
-        {\r
-            foreach (Control existing in notifications)\r
-            {\r
-                existing.Visible = false;\r
-            }\r
-\r
-            if (notifications.HasNext)\r
-            {\r
-                pnlDialog.Visible = true;\r
-                Control active = notifications.Next;\r
-                active.Visible = true;\r
-                ResizeNotificationByControl(active);\r
-            }\r
-            else\r
-            {\r
-                pnlDialog.Visible = false;\r
-            }\r
-\r
-        }\r
-        #endregion Notifications\r
-\r
-        #region Menu click handlers\r
-\r
-        private void tbtnTeleport_Click(object sender, EventArgs e)\r
-        {\r
-            (new frmTeleport(instance)).ShowDialog();\r
-        }\r
-\r
-        private void tmnuStatusAway_Click(object sender, EventArgs e)\r
-        {\r
-            instance.State.SetAway(tmnuStatusAway.Checked);\r
-        }\r
-\r
-        private void tmnuHelpReadme_Click(object sender, EventArgs e)\r
-        {\r
-            System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");\r
-        }\r
-\r
-        private void tmnuStatusBusy_Click(object sender, EventArgs e)\r
-        {\r
-            instance.State.SetBusy(tmnuStatusBusy.Checked);\r
-        }\r
-\r
-        private void tmnuControlFly_Click(object sender, EventArgs e)\r
-        {\r
-            instance.State.SetFlying(tmnuControlFly.Checked);\r
-        }\r
-\r
-        private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)\r
-        {\r
-            instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);\r
-        }\r
-\r
-        private void tmnuPrefs_Click(object sender, EventArgs e)\r
-        {\r
-            (new frmSettings(instance)).ShowDialog();\r
-        }\r
-\r
-        private void tbtnAppearance_Click(object sender, EventArgs e)\r
-        {\r
-            client.Appearance.RequestSetAppearance(false);\r
-        }\r
-\r
-        private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            PrimDeserializer.ImportFromFile(client);\r
-        }\r
-\r
-        private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            if (ap == null)\r
-            {\r
-                ap = new AutoPilot(client);\r
-                /*\r
-                ap.InsertWaypoint(new Vector3(66, 163, 21));\r
-                ap.InsertWaypoint(new Vector3(66, 98, 21));\r
-\r
-                ap.InsertWaypoint(new Vector3(101, 98, 21));\r
-                ap.InsertWaypoint(new Vector3(101, 45, 21));\r
-                ap.InsertWaypoint(new Vector3(93, 27, 21));\r
-                ap.InsertWaypoint(new Vector3(106, 12, 21));\r
-                ap.InsertWaypoint(new Vector3(123, 24, 21));\r
-                ap.InsertWaypoint(new Vector3(114, 45, 21));\r
-                ap.InsertWaypoint(new Vector3(114, 98, 21));\r
-\r
-                ap.InsertWaypoint(new Vector3(130, 98, 21));\r
-                ap.InsertWaypoint(new Vector3(130, 163, 21));\r
-                 **/\r
-                ap.InsertWaypoint(new Vector3(64, 68, 21));\r
-                ap.InsertWaypoint(new Vector3(65, 20, 21));\r
-                ap.InsertWaypoint(new Vector3(33, 23, 21));\r
-                ap.InsertWaypoint(new Vector3(17, 39, 21));\r
-                ap.InsertWaypoint(new Vector3(17, 62, 21));\r
-\r
-\r
-            }\r
-            if (AutoPilotActive)\r
-            {\r
-                AutoPilotActive = false;\r
-                ap.Stop();\r
-            }\r
-            else\r
-            {\r
-                AutoPilotActive = true;\r
-                ap.Start();\r
-            }\r
-\r
-        }\r
-\r
-        private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            client.Assets.Cache.Clear();\r
-            DirectoryInfo di = new DirectoryInfo(instance.AnimCacheDir);\r
-            FileInfo[] files = di.GetFiles();\r
-\r
-            int num = 0;\r
-            foreach (FileInfo file in files)\r
-            {\r
-                file.Delete();\r
-                ++num;\r
-            }\r
-\r
-            Logger.Log("Wiped out " + num + " files from the anim cache directory.", Helpers.LogLevel.Debug);\r
-\r
-        }\r
-\r
-        private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            client.Appearance.RequestSetAppearance(true);\r
-        }\r
-\r
-        public void MapToCurrentLocation()\r
-        {\r
-            if (MapTab != null && client.Network.Connected)\r
-            {\r
-                MapTab.Select();\r
-                WorldMap.DisplayLocation(client.Network.CurrentSim.Name,\r
-                    (int)client.Self.SimPosition.X,\r
-                    (int)client.Self.SimPosition.Y,\r
-                    (int)client.Self.SimPosition.Z);\r
-            }\r
-        }\r
-\r
-        private void standToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            client.Self.Stand();\r
-        }\r
-\r
-        private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            client.Self.SitOnGround();\r
-        }\r
-\r
-        private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            try { System.Diagnostics.Process.Start(Application.ExecutablePath); }\r
-            catch (Exception) { }\r
-        }\r
-\r
-        private void tmnuExit_Click(object sender, EventArgs e)\r
-        {\r
-            Close();\r
-        }\r
-\r
-        private void tlblRegionInfo_Click(object sender, EventArgs e)\r
-        {\r
-            if (WorldMap != null && client.Network.Connected)\r
-            {\r
-                MapTab.Select();\r
-            }\r
-        }\r
-\r
-        private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            ScriptEditor se = new ScriptEditor(instance);\r
-            se.Dock = DockStyle.Fill;\r
-            se.ShowDetached();\r
-        }\r
-\r
-        private void tmnuSetHome_Click(object sender, EventArgs e)\r
-        {\r
-            client.Self.SetHome();\r
-        }\r
-\r
-        private void tmnuCreateLandmark_Click(object sender, EventArgs e)\r
-        {\r
-            string location = string.Format(", {0} ({1}, {2}, {3})",\r
-                client.Network.CurrentSim.Name,\r
-                (int)client.Self.SimPosition.X,\r
-                (int)client.Self.SimPosition.Y,\r
-                (int)client.Self.SimPosition.Z\r
-                );\r
-\r
-            string name = tlblParcel.Text;\r
-            int maxLen = 63 - location.Length;\r
-\r
-            if (name.Length > maxLen)\r
-                name = name.Substring(0, maxLen);\r
-\r
-            name += location;\r
-\r
-            client.Inventory.RequestCreateItem(\r
-                client.Inventory.FindFolderForType(AssetType.Landmark),\r
-                name,\r
-                tlblParcel.ToolTipText,\r
-                AssetType.Landmark,\r
-                UUID.Random(),\r
-                InventoryType.Landmark,\r
-                PermissionMask.All,\r
-                (bool success, InventoryItem item) =>\r
-                {\r
-                    if (success)\r
-                    {\r
-                        BeginInvoke(new MethodInvoker(() =>\r
-                            {\r
-                                Landmark ln = new Landmark(instance, (InventoryLandmark)item);\r
-                                ln.Dock = DockStyle.Fill;\r
-                                ln.Detached = true;\r
-                            }));\r
-                    }\r
-                }\r
-            );\r
-        }\r
-\r
-        private void tmnuTeleportHome_Click(object sender, EventArgs e)\r
-        {\r
-            if (WorldMap != null)\r
-            {\r
-                WorldMap.GoHome();\r
-            }\r
-        }\r
-\r
-        private TimeZoneInfo SLTime;\r
-\r
-        private void GetSLTimeZone()\r
-        {\r
-            try\r
-            {\r
-                foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())\r
-                {\r
-                    if (tz.Id == "Pacific Standard Time" || tz.Id == "America/Los_Angeles")\r
-                    {\r
-                        SLTime = tz;\r
-                        break;\r
-                    }\r
-                }\r
-            }\r
-            catch (Exception) { }\r
-        }\r
-\r
-        private void timerWorldClock_Tick(object sender, EventArgs e)\r
-        {\r
-            DateTime now;\r
-            try\r
-            {\r
-                if (SLTime != null)\r
-                    now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, SLTime);\r
-                else\r
-                    now = DateTime.UtcNow.AddHours(-7);\r
-            }\r
-            catch (Exception)\r
-            {\r
-                now = DateTime.UtcNow.AddHours(-7);\r
-            }\r
-            lblTime.Text = now.ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);\r
-        }\r
-\r
-        private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            ProcessLink("http://jira.openmetaverse.org/browse/RAD");\r
-        }\r
-\r
-        private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            (new frmAbout(instance)).ShowDialog();\r
-        }\r
-\r
-        #region Update Checking\r
-        private UpdateChecker updateChecker = null;\r
-        private bool ManualUpdateCheck = false;\r
-\r
-        public void StartUpdateCheck(bool userInitiated)\r
-        {\r
-            ManualUpdateCheck = userInitiated;\r
-\r
-            if (updateChecker != null)\r
-            {\r
-                if (ManualUpdateCheck)\r
-                    tabsConsole.DisplayNotificationInChat("Update check already in progress.");\r
-                return;\r
-            }\r
-\r
-            if (ManualUpdateCheck)\r
-                tabsConsole.DisplayNotificationInChat("Checking for updates...", ChatBufferTextStyle.StatusBlue);\r
-            updateChecker = new UpdateChecker();\r
-            updateChecker.OnUpdateInfoReceived += new UpdateChecker.UpdateInfoCallback(OnUpdateInfoReceived);\r
-            updateChecker.StartCheck();\r
-        }\r
-\r
-        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            tabsConsole.SelectTab("chat");\r
-            StartUpdateCheck(true);\r
-        }\r
-\r
-        void OnUpdateInfoReceived(object sender, UpdateCheckerArgs e)\r
-        {\r
-            if (InvokeRequired)\r
-            {\r
-                BeginInvoke(new MethodInvoker(() => OnUpdateInfoReceived(sender, e)));\r
-                return;\r
-            }\r
-\r
-            if (!e.Success)\r
-            {\r
-                if (ManualUpdateCheck)\r
-                    tabsConsole.DisplayNotificationInChat("Error: Failed connecting to the update site.", ChatBufferTextStyle.StatusBlue);\r
-            }\r
-            else\r
-            {\r
-                if (!ManualUpdateCheck && e.Info.DisplayMOTD)\r
-                {\r
-                    tabsConsole.DisplayNotificationInChat(e.Info.MOTD, ChatBufferTextStyle.StatusBlue);\r
-                }\r
-\r
-                if (e.Info.UpdateAvailable)\r
-                {\r
-                    tabsConsole.DisplayNotificationInChat("New version available at " + e.Info.DownloadSite, ChatBufferTextStyle.Alert);\r
-                }\r
-                else\r
-                {\r
-                    if (ManualUpdateCheck)\r
-                        tabsConsole.DisplayNotificationInChat("Your version is up to date.", ChatBufferTextStyle.StatusBlue);\r
-                }\r
-            }\r
-\r
-            updateChecker.Dispose();\r
-            updateChecker = null;\r
-        }\r
-        #endregion\r
-\r
-        private void ToggleHidden(string tabName)\r
-        {\r
-            if (!tabsConsole.TabExists(tabName)) return;\r
-\r
-            RadegastTab tab = tabsConsole.Tabs[tabName];\r
-\r
-            if (tab.Hidden)\r
-            {\r
-                tab.Show();\r
-            }\r
-            else\r
-            {\r
-                if (!tab.Selected)\r
-                {\r
-                    tab.Select();\r
-                }\r
-                else\r
-                {\r
-                    tab.Hide();\r
-                }\r
-            }\r
-        }\r
-\r
-        private void tbtnFriends_Click(object sender, EventArgs e)\r
-        {\r
-            ToggleHidden("friends");\r
-        }\r
-\r
-        private void tbtnInventory_Click(object sender, EventArgs e)\r
-        {\r
-            ToggleHidden("inventory");\r
-        }\r
-\r
-        private void tbtnSearch_Click(object sender, EventArgs e)\r
-        {\r
-            ToggleHidden("search");\r
-        }\r
-\r
-        private void tbtnGroups_Click(object sender, EventArgs e)\r
-        {\r
-            ToggleHidden("groups");\r
-        }\r
-\r
-        private void tbtnMedia_Click(object sender, EventArgs e)\r
-        {\r
-            if (tabsConsole.TabExists("media"))\r
-            {\r
-                ToggleHidden("media");\r
-            }\r
-            else\r
-            {\r
-                RadegastTab tab = tabsConsole.AddTab("media", "Media", mediaConsole);\r
-                tab.AllowClose = false;\r
-                tab.AllowHide = true;\r
-                tab.Select();\r
-            }\r
-        }\r
-\r
-        private void tbnObjects_Click(object sender, EventArgs e)\r
-        {\r
-            if (tabsConsole.TabExists("objects"))\r
-            {\r
-                RadegastTab tab = tabsConsole.Tabs["objects"];\r
-                if (!tab.Selected)\r
-                {\r
-                    tab.Select();\r
-                    ((ObjectsConsole)tab.Control).RefreshObjectList();\r
-                }\r
-                else\r
-                {\r
-                    tab.Close();\r
-                }\r
-            }\r
-            else\r
-            {\r
-                RadegastTab tab = tabsConsole.AddTab("objects", "Objects", new ObjectsConsole(instance));\r
-                tab.AllowClose = true;\r
-                tab.AllowDetach = true;\r
-                tab.Visible = true;\r
-                tab.AllowHide = false;\r
-                tab.Select();\r
-                ((ObjectsConsole)tab.Control).RefreshObjectList();\r
-            }\r
-        }\r
-\r
-        private void tbtnMap_Click(object sender, EventArgs e)\r
-        {\r
-            ToggleHidden("map");\r
-            if (!MapTab.Hidden)\r
-                MapToCurrentLocation();\r
-        }\r
-\r
-        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            if (client.Network.Connected)\r
-                client.Network.RequestLogout();\r
-        }\r
-\r
-        private void reconnectToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            instance.Reconnect();\r
-        }\r
-\r
-        private frmKeyboardShortcuts keyboardShortcutsForm = null;\r
-        private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)\r
-        {\r
-            if (keyboardShortcutsForm != null)\r
-            {\r
-                keyboardShortcutsForm.Focus();\r
-            }\r
-            else\r
-            {\r
-                keyboardShortcutsForm = new frmKeyboardShortcuts(instance);\r
-\r
-                keyboardShortcutsForm.Disposed += (object senderx, EventArgs ex) =>\r
-                    {\r
-                        if (components != null)\r
-                        {\r
-                            components.Remove(keyboardShortcutsForm);\r
-                        }\r
-                        keyboardShortcutsForm = null;\r
-                    };\r
-\r
-                keyboardShortcutsForm.Show(this);\r
-                keyboardShortcutsForm.Top = Top + 100;\r
-                keyboardShortcutsForm.Left = Left + 100;\r
-\r
-                if (components != null)\r
-                {\r
-                    components.Add(keyboardShortcutsForm);\r
-                }\r
-            }\r
-        }\r
-        #endregion\r
-\r
-    }\r
+// 
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//     * Redistributions of source code must retain the above copyright notice,
+//       this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the application "Radegast", nor the names of its
+//       contributors may be used to endorse or promote products derived from
+//       this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Timers;
+#if (COGBOT_LIBOMV || USE_STHREADS)
+using ThreadPoolUtil;
+using Thread = ThreadPoolUtil.Thread;
+using ThreadPool = ThreadPoolUtil.ThreadPool;
+using Monitor = ThreadPoolUtil.Monitor;
+#endif
+using System.Threading;
+
+using System.Windows.Forms;
+using System.Resources;
+using System.IO;
+using System.Web;
+using Radegast.Netcom;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenMetaverse.Assets;
+
+namespace Radegast
+{
+    public partial class frmMain : RadegastForm
+    {
+        #region Public members
+        public static ImageList ResourceImages = new ImageList();
+        public static List<string> ImageNames = new List<string>();
+        public bool PreventParcelUpdate = false;
+        public delegate void ProfileHandlerDelegate(string agentName, UUID agentID);
+        public ProfileHandlerDelegate ShowAgentProfile;
+
+        public TabsConsole TabConsole
+        {
+            get { return tabsConsole; }
+        }
+
+        public MapConsole WorldMap
+        {
+            get
+            {
+                if (MapTab != null)
+                {
+                    return (MapConsole)MapTab.Control;
+                }
+                return null;
+            }
+        }
+
+        public RadegastTab MapTab
+        {
+            get
+            {
+                if (tabsConsole.TabExists("map"))
+                {
+                    return tabsConsole.Tabs["map"];
+                }
+                else
+                {
+                    return null;
+                }
+            }
+        }
+
+        public MediaConsole MediaConsole { get { return mediaConsole; } }
+
+        /// <summary>
+        /// Drop down that contains the tools menu
+        /// </summary>
+        public ToolStripDropDownButton ToolsMenu
+        {
+            get { return tbnTools; }
+        }
+
+        /// <summary>
+        /// Dropdown that contains the heelp menu
+        /// </summary>
+        public ToolStripDropDownButton HelpMenu
+        {
+            get { return tbtnHelp; }
+        }
+
+        /// <summary>
+        /// Drop down that contants the plugins menu. Make sure to set it Visible if
+        /// you add items to this menu, it's hidden by default
+        /// </summary>
+        public ToolStripDropDownButton PluginsMenu
+        {
+            get { return tbnPlugins; }
+        }
+
+        #endregion
+
+        #region Private members
+        private RadegastInstance instance;
+        private GridClient client { get { return instance.Client; } }
+        private RadegastNetcom netcom { get { return instance.Netcom; } }
+        private TabsConsole tabsConsole;
+        private System.Timers.Timer statusTimer;
+        private AutoPilot ap;
+        private bool AutoPilotActive = false;
+        private TransparentButton btnDialogNextControl;
+        private MediaConsole mediaConsole;
+        private SlUriParser uriParser;
+        #endregion
+
+        #region Constructor and disposal
+        public frmMain(RadegastInstance instance)
+            : base(instance)
+        {
+            InitializeComponent();
+            Disposed += new EventHandler(frmMain_Disposed);
+
+            this.instance = instance;
+            this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
+            netcom.NetcomSync = this;
+            ShowAgentProfile = ShowAgentProfileInternal;
+
+            pnlDialog.Visible = false;
+            btnDialogNextControl = new TransparentButton();
+            pnlDialog.Controls.Add(btnDialogNextControl);
+            pnlDialog.Top = 0;
+
+            btnDialogNextControl.Size = new Size(35, 20);
+            btnDialogNextControl.BackColor = Color.Transparent;
+            btnDialogNextControl.ForeColor = Color.Gold;
+            btnDialogNextControl.FlatAppearance.BorderSize = 0;
+            btnDialogNextControl.FlatStyle = FlatStyle.Flat;
+            btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+            btnDialogNextControl.Text = ">>";
+            btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);
+            btnDialogNextControl.Margin = new Padding(0);
+            btnDialogNextControl.Padding = new Padding(0);
+            btnDialogNextControl.UseVisualStyleBackColor = false;
+            btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
+            btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
+            btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);
+
+            if (instance.MonoRuntime)
+            {
+                statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;
+            }
+
+            // Callbacks
+            netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+            netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
+            netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+            instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
+            RegisterClientEvents(client);
+
+            InitializeStatusTimer();
+            RefreshWindowTitle();
+        }
+
+        private void RegisterClientEvents(GridClient client)
+        {
+            client.Parcels.ParcelProperties += new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
+            client.Self.MoneyBalanceReply += new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
+            client.Self.MoneyBalance += new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
+        }
+
+        private void UnregisterClientEvents(GridClient client)
+        {
+            client.Parcels.ParcelProperties -= new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
+            client.Self.MoneyBalanceReply -= new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
+            client.Self.MoneyBalance -= new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
+        }
+
+        void instance_ClientChanged(object sender, ClientChangedEventArgs e)
+        {
+            UnregisterClientEvents(e.OldClient);
+            RegisterClientEvents(client);
+        }
+
+        void frmMain_Disposed(object sender, EventArgs e)
+        {
+            if (netcom != null)
+            {
+                netcom.NetcomSync = null;
+                netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+                netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
+                netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+            }
+
+            if (client != null)
+            {
+                UnregisterClientEvents(client);
+            }
+
+            if (instance != null && instance.Names != null)
+            {
+                instance.Names.NameUpdated -= new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
+            }
+
+            this.instance.CleanUp();
+        }
+        #endregion
+
+        #region Event handlers
+        bool firstMoneyNotification = true;
+        void Self_MoneyBalance(object sender, BalanceEventArgs e)
+        {
+            int oldBalance = 0;
+            int.TryParse(tlblMoneyBalance.Text, out oldBalance);
+            int delta = Math.Abs(oldBalance - e.Balance);
+
+            if (firstMoneyNotification)
+            {
+                firstMoneyNotification = false;
+            }
+            else
+            {
+                if (delta > 50)
+                {
+                    if (oldBalance > e.Balance)
+                    {
+                        instance.MediaManager.PlayUISound(UISounds.MoneyIn);
+                    }
+                    else
+                    {
+                        instance.MediaManager.PlayUISound(UISounds.MoneyOut);
+                    }
+                }
+            }
+        }
+
+        void Names_NameUpdated(object sender, UUIDNameReplyEventArgs e)
+        {
+            if (!e.Names.ContainsKey(client.Self.AgentID)) return;
+
+            if (InvokeRequired)
+            {
+                if (IsHandleCreated || !instance.MonoRuntime)
+                {
+                    BeginInvoke(new MethodInvoker(() => Names_NameUpdated(sender, e)));
+                }
+                return;
+            }
+
+            RefreshWindowTitle();
+            RefreshStatusBar();
+        }
+
+        void Self_MoneyBalanceReply(object sender, MoneyBalanceReplyEventArgs e)
+        {
+            if (!String.IsNullOrEmpty(e.Description))
+            {
+                if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())
+                    AddNotification(new ntfGeneric(instance, e.Description));
+                if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())
+                    TabConsole.DisplayNotificationInChat(e.Description);
+            }
+        }
+
+        public void InitializeControls()
+        {
+            InitializeTabsConsole();
+            uriParser = new SlUriParser();
+
+            if (instance.MediaManager.SoundSystemAvailable)
+            {
+                mediaConsole = new MediaConsole(instance);
+                tbtnMedia.Visible = true;
+            }
+        }
+
+        public bool InAutoReconnect { get; set; }
+
+        private void DisplayAutoReconnectForm()
+        {
+            if (IsDisposed) return;
+
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));
+                return;
+            }
+
+            InAutoReconnect = true;
+            frmReconnect dialog = new frmReconnect(instance, instance.GlobalSettings["reconnect_time"]);
+            dialog.ShowDialog(this);
+            dialog.Dispose();
+            dialog = null;
+        }
+
+        public void BeginAutoReconnect()
+        {
+            // Sleep for 3 seconds on a separate thread while things unwind on
+            // disconnect, since ShowDialog() blocks GUI thread
+            (new Thread(new ThreadStart(() =>
+                {
+                    System.Threading.Thread.Sleep(3000);
+                    DisplayAutoReconnectForm();
+                }
+                ))
+                {
+                    Name = "Reconnect Delay Thread",
+                    IsBackground = true
+                }
+            ).Start();
+        }
+
+        private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)
+        {
+            if (e.Status == LoginStatus.Failed)
+            {
+                if (InAutoReconnect)
+                {
+                    if (instance.GlobalSettings["auto_reconnect"].AsBoolean() && e.FailReason != "tos")
+                        BeginAutoReconnect();
+                    else
+                        InAutoReconnect = false;
+                }
+            }
+            else if (e.Status == LoginStatus.Success)
+            {
+                InAutoReconnect = false;
+                reconnectToolStripMenuItem.Enabled = false;
+                loginToolStripMenuItem.Enabled = false;
+                tsb3D.Enabled = tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
+                tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
+                    tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = true;
+
+                statusTimer.Start();
+                RefreshWindowTitle();
+            }
+        }
+
+        private void netcom_ClientLoggedOut(object sender, EventArgs e)
+        {
+            tsb3D.Enabled = tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
+            tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
+                tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = false;
+
+            reconnectToolStripMenuItem.Enabled = true;
+            loginToolStripMenuItem.Enabled = true;
+            InAutoReconnect = false;
+
+            if (statusTimer != null)
+                statusTimer.Stop();
+
+            RefreshStatusBar();
+            RefreshWindowTitle();
+        }
+
+        private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
+        {
+            firstMoneyNotification = true;
+
+            if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;
+            netcom_ClientLoggedOut(sender, EventArgs.Empty);
+
+            if (instance.GlobalSettings["auto_reconnect"].AsBoolean())
+            {
+                BeginAutoReconnect();
+            }
+        }
+
+        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (statusTimer != null)
+            {
+                statusTimer.Stop();
+                statusTimer.Dispose();
+                statusTimer = null;
+            }
+
+            if (mediaConsole != null)
+            {
+                if (tabsConsole.TabExists("media"))
+                {
+                    tabsConsole.Tabs["media"].AllowClose = true;
+                    tabsConsole.Tabs["media"].Close();
+                }
+                else
+                {
+                    mediaConsole.Dispose();
+                }
+                mediaConsole = null;
+            }
+
+            if (netcom.IsLoggedIn)
+            {
+                Thread saveInvToDisk = new Thread(new ThreadStart(
+                    delegate()
+                    {
+                        client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);
+                    }));
+                saveInvToDisk.Name = "Save inventory to disk";
+                saveInvToDisk.Start();
+
+                netcom.Logout();
+            }
+        }
+        #endregion
+
+        # region Update status
+
+        void Parcels_ParcelProperties(object sender, ParcelPropertiesEventArgs e)
+        {
+            if (PreventParcelUpdate || e.Result != ParcelResult.Single) return;
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(() => Parcels_ParcelProperties(sender, e)));
+                return;
+            }
+
+            Parcel parcel = instance.State.Parcel = e.Parcel;
+
+            tlblParcel.Text = parcel.Name;
+            tlblParcel.ToolTipText = parcel.Desc;
+
+            if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)
+                icoNoFly.Visible = true;
+            else
+                icoNoFly.Visible = false;
+
+            if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)
+                icoNoBuild.Visible = true;
+            else
+                icoNoBuild.Visible = false;
+
+            if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)
+                icoNoScript.Visible = true;
+            else
+                icoNoScript.Visible = false;
+
+            if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)
+                icoNoPush.Visible = true;
+            else
+                icoNoPush.Visible = false;
+
+            if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)
+                icoHealth.Visible = true;
+            else
+                icoHealth.Visible = false;
+
+            if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)
+                icoNoVoice.Visible = true;
+            else
+                icoNoVoice.Visible = false;
+        }
+
+        private void RefreshStatusBar()
+        {
+            if (netcom.IsLoggedIn)
+            {
+                tlblLoginName.Text = instance.Names.Get(client.Self.AgentID, client.Self.Name);
+                tlblMoneyBalance.Text = client.Self.Balance.ToString();
+                icoHealth.Text = client.Self.Health.ToString() + "%";
+
+                var cs = client.Network.CurrentSim;
+                tlblRegionInfo.Text =
+                    (cs == null ? "No region" : cs.Name) +
+                    " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +
+                    Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +
+                    Math.Floor(client.Self.SimPosition.Z).ToString() + ")";
+            }
+            else
+            {
+                tlblLoginName.Text = "Offline";
+                tlblMoneyBalance.Text = "0";
+                icoHealth.Text = "0%";
+                tlblRegionInfo.Text = "No Region";
+                tlblParcel.Text = "No Parcel";
+
+                icoHealth.Visible = false;
+                icoNoBuild.Visible = false;
+                icoNoFly.Visible = false;
+                icoNoPush.Visible = false;
+                icoNoScript.Visible = false;
+                icoNoVoice.Visible = false;
+            }
+        }
+
+        private void RefreshWindowTitle()
+        {
+            string name = instance.Names.Get(client.Self.AgentID, client.Self.Name);
+            StringBuilder sb = new StringBuilder();
+            sb.Append("Radegast - ");
+
+            if (netcom.IsLoggedIn)
+            {
+                sb.Append("[" + name + "]");
+
+                if (instance.State.IsAway)
+                {
+                    sb.Append(" - Away");
+                    if (instance.State.IsBusy) sb.Append(", Busy");
+                }
+                else if (instance.State.IsBusy)
+                {
+                    sb.Append(" - Busy");
+                }
+
+                if (instance.State.IsFollowing)
+                {
+                    sb.Append(" - Following ");
+                    sb.Append(instance.State.FollowName);
+                }
+            }
+            else
+            {
+                sb.Append("Logged Out");
+            }
+
+            this.Text = sb.ToString();
+
+            // When minimized to tray, update tray tool tip also
+            if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"])
+            {
+                trayIcon.Text = sb.ToString();
+                ctxTrayMenuLabel.Text = sb.ToString();
+            }
+
+            sb = null;
+        }
+
+        private void InitializeStatusTimer()
+        {
+            statusTimer = new System.Timers.Timer(250);
+            statusTimer.SynchronizingObject = this;
+            statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);
+        }
+
+        private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)
+        {
+            // Mono sometimes fires timer after is's disposed
+            try
+            {
+                RefreshWindowTitle();
+                RefreshStatusBar();
+            }
+            catch { }
+        }
+        #endregion
+
+        #region Initialization, configuration, and key shortcuts
+        private void InitializeTabsConsole()
+        {
+            tabsConsole = new TabsConsole(instance);
+            tabsConsole.Dock = DockStyle.Fill;
+            toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);
+        }
+
+        private void frmMain_KeyDown(object sender, KeyEventArgs e)
+        {
+            // Ctrl-Alt-Shift-H Say "Hippos!" in chat
+            if (e.Modifiers == (Keys.Control | Keys.Shift | Keys.Alt) && e.KeyCode == Keys.H)
+            {
+                e.Handled = e.SuppressKeyPress = true;
+                netcom.ChatOut("Hippos!", ChatType.Normal, 0);
+                return;
+            }
+
+            // Ctrl-Shift-1 (sim/parcel info)
+            if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.D1)
+            {
+                e.Handled = e.SuppressKeyPress = true;
+                DisplayRegionParcelConsole();
+                return;
+            }
+
+            // Ctrl-W: Close tab
+            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.W)
+            {
+                e.Handled = e.SuppressKeyPress = true;
+                RadegastTab tab = tabsConsole.SelectedTab;
+
+                if (tab.AllowClose)
+                {
+                    tab.Close();
+                }
+                else if (tab.AllowHide)
+                {
+                    tab.Hide();
+                }
+
+                return;
+            }
+
+            // Ctl-Shift-H: Teleport Home
+            if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.H)
+            {
+                e.Handled = e.SuppressKeyPress = true;
+                tmnuTeleportHome.PerformClick();
+                return;
+            }
+
+            // Alt-Ctrl-D Open debug console
+            if (e.Modifiers == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.D)
+            {
+                e.Handled = e.SuppressKeyPress = true;
+                debugConsoleToolStripMenuItem.PerformClick();
+                return;
+            }
+
+            // Alt 1-8: Toggle various tabs
+            if (e.Modifiers == Keys.Alt)
+            {
+                switch (e.KeyCode)
+                {
+                    case Keys.D1:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tabsConsole.Tabs["chat"].Select();
+                        return;
+
+                    case Keys.D2:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnFriends.PerformClick();
+                        return;
+
+                    case Keys.D3:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnGroups.PerformClick();
+                        return;
+
+                    case Keys.D4:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnInventory.PerformClick();
+                        return;
+
+                    case Keys.D5:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnSearch.PerformClick();
+                        return;
+
+                    case Keys.D6:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnMap.PerformClick();
+                        return;
+
+                    case Keys.D7:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbnObjects.PerformClick();
+                        return;
+
+                    case Keys.D8:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnMedia.PerformClick();
+                        return;
+
+                    case Keys.D9:
+                        e.Handled = e.SuppressKeyPress = true;
+                        tbtnVoice.PerformClick();
+                        return;
+                }
+            }
+
+            // ctrl-g, goto slurl
+            if (e.Control && e.KeyCode == Keys.G)
+            {
+                if (!ProcessLink(Clipboard.GetText(), true))
+                    MapToCurrentLocation();
+
+                e.Handled = e.SuppressKeyPress = true;
+                return;
+            }
+
+            // ctrl-(shift)-tab for next/previous tab
+            if (e.Control && e.KeyCode == Keys.Tab)
+            {
+                if (e.Shift)
+                {
+                    TabConsole.SelectPreviousTab();
+                }
+                else
+                {
+                    TabConsole.SelectNextTab();
+                }
+                e.Handled = e.SuppressKeyPress = true;
+                return;
+            }
+        }
+
+        bool firstLoad = true;
+
+        private void frmMain_Load(object sender, EventArgs e)
+        {
+            if (firstLoad)
+            {
+                firstLoad = false;
+                tabsConsole.SelectTab("login");
+                ResourceManager rm = Properties.Resources.ResourceManager;
+                ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
+                System.Collections.IDictionaryEnumerator de = set.GetEnumerator();
+                while (de.MoveNext() == true)
+                {
+                    if (de.Entry.Value is Image)
+                    {
+                        Bitmap bitMap = de.Entry.Value as Bitmap;
+                        ResourceImages.Images.Add(bitMap);
+                        ImageNames.Add(de.Entry.Key.ToString());
+                    }
+                }
+                StartUpdateCheck(false);
+
+                if (instance.PlainColors)
+                {
+                    pnlDialog.BackColor = System.Drawing.Color.FromArgb(120, 220, 255);
+                }
+
+            }
+        }
+        #endregion
+
+        #region Public methods
+
+        private Dictionary<UUID, frmProfile> shownProfiles = new Dictionary<UUID, frmProfile>();
+
+        void ShowAgentProfileInternal(string name, UUID agentID)
+        {
+            lock (shownProfiles)
+            {
+                frmProfile profile = null;
+                if (shownProfiles.TryGetValue(agentID, out profile))
+                {
+                    profile.WindowState = FormWindowState.Normal;
+                    profile.Focus();
+                }
+                else
+                {
+                    profile = new frmProfile(instance, name, agentID);
+
+                    profile.Disposed += (object sender, EventArgs e) =>
+                        {
+                            lock (shownProfiles)
+                            {
+                                frmProfile agentProfile = (frmProfile)sender;
+                                if (shownProfiles.ContainsKey(agentProfile.AgentID))
+                                    shownProfiles.Remove(agentProfile.AgentID);
+                            }
+                        };
+
+                    profile.Show();
+                    profile.Focus();
+                    shownProfiles.Add(agentID, profile);
+                }
+            }
+        }
+
+        private Dictionary<UUID, frmGroupInfo> shownGroupProfiles = new Dictionary<UUID, frmGroupInfo>();
+
+        public void ShowGroupProfile(UUID id)
+        {
+            ShowGroupProfile(new OpenMetaverse.Group()
+            {
+                ID = id,
+            });
+        }
+
+        public void ShowGroupProfile(AvatarGroup group)
+        {
+            ShowGroupProfile(new OpenMetaverse.Group()
+            {
+                ID = group.GroupID,
+                InsigniaID = group.GroupInsigniaID,
+                Name = group.GroupName
+            }
+            );
+        }
+
+        public void ShowGroupProfile(OpenMetaverse.Group group)
+        {
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(() => ShowGroupProfile(group)));
+                return;
+            }
+
+            lock (shownGroupProfiles)
+            {
+                frmGroupInfo profile = null;
+                if (shownGroupProfiles.TryGetValue(group.ID, out profile))
+                {
+                    profile.WindowState = FormWindowState.Normal;
+                    profile.Focus();
+                }
+                else
+                {
+                    profile = new frmGroupInfo(instance, group);
+
+                    profile.Disposed += (object sender, EventArgs e) =>
+                        {
+                            lock (shownGroupProfiles)
+                            {
+                                frmGroupInfo groupProfile = (frmGroupInfo)sender;
+                                if (shownGroupProfiles.ContainsKey(groupProfile.Group.ID))
+                                    shownGroupProfiles.Remove(groupProfile.Group.ID);
+                            }
+                        };
+
+                    profile.Show();
+                    profile.Focus();
+                    shownGroupProfiles.Add(group.ID, profile);
+                }
+            }
+        }
+
+        public bool ProcessSecondlifeURI(string link)
+        {
+            uriParser.ExecuteLink(link);
+            return true;
+        }
+
+        public void ProcessLink(string link)
+        {
+            ProcessLink(link, false);
+        }
+
+        public bool ProcessLink(string link, bool onlyMap)
+        {
+            var pos = link.IndexOf(RRichTextBox.LinkSeparator);
+            if (pos > 0)
+            {
+                link = link.Substring(pos + 1);
+            }
+
+            if (link.StartsWith("secondlife://") || link.StartsWith("[secondlife://"))
+            {
+                return ProcessSecondlifeURI(link);
+            }
+
+            if (!link.Contains("://"))
+            {
+                link = "http://" + link;
+            }
+
+            Regex r = new Regex(@"^(http://(slurl\.com|maps\.secondlife\.com)/secondlife/|secondlife://)(?<region>[^/]+)/(?<x>\d+)/(?<y>\d+)(/(?<z>\d+))?",
+                RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase
+                );
+            Match m = r.Match(link);
+
+            if (m.Success)
+            {
+                string region = HttpUtility.UrlDecode(m.Groups["region"].Value);
+                int x = int.Parse(m.Groups["x"].Value);
+                int y = int.Parse(m.Groups["y"].Value);
+                int z = 0;
+
+                if (!string.IsNullOrEmpty(m.Groups["z"].Value))
+                {
+                    z = int.Parse(m.Groups["z"].Value);
+                }
+
+                MapTab.Select();
+                WorldMap.DisplayLocation(region, x, y, z);
+                return true;
+            }
+            else if (!onlyMap)
+            {
+                System.Diagnostics.Process.Start(link);
+            }
+            return false;
+        }
+        #endregion
+
+        #region Notifications
+        CircularList<Control> notifications = new CircularList<Control>();
+
+        public Color NotificationBackground
+        {
+            get { return pnlDialog.BackColor; }
+        }
+
+        void ResizeNotificationByControl(Control active)
+        {
+            int Width = active.Size.Width + 6;
+            int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;
+            pnlDialog.Size = new Size(Width, Height);
+            pnlDialog.Top = 0;
+            pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;
+
+            btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
+            btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
+
+            btnDialogNextControl.BringToFront();
+        }
+
+        public void AddNotification(Control control)
+        {
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(delegate()
+                {
+                    AddNotification(control);
+                }
+                ));
+                return;
+            }
+
+            Control active = TabsConsole.FindFocusedControl(this);
+
+            FormFlash.StartFlash(this);
+            pnlDialog.Visible = true;
+            pnlDialog.BringToFront();
+
+            foreach (Control existing in notifications)
+            {
+                existing.Visible = false;
+            }
+
+            notifications.Add(control);
+            control.Visible = true;
+            control.Anchor = AnchorStyles.Top | AnchorStyles.Left;
+            control.Top = 3;
+            control.Left = 3;
+            pnlDialog.Controls.Add(control);
+            ResizeNotificationByControl(control);
+
+            btnDialogNextControl.Visible = notifications.Count > 1;
+
+            if (active != null)
+            {
+                active.Focus();
+            }
+        }
+
+        public void RemoveNotification(Control control)
+        {
+            pnlDialog.Controls.Remove(control);
+            notifications.Remove(control);
+            control.Dispose();
+
+            if (notifications.HasNext)
+            {
+                pnlDialog.Visible = true;
+                Control active = notifications.Next;
+                active.Visible = true;
+                ResizeNotificationByControl(active);
+            }
+            else
+            {
+                pnlDialog.Visible = false;
+            }
+
+            btnDialogNextControl.Visible = notifications.Count > 1;
+        }
+
+        private void btnDialogNextControl_Click(object sender, EventArgs e)
+        {
+            foreach (Control existing in notifications)
+            {
+                existing.Visible = false;
+            }
+
+            if (notifications.HasNext)
+            {
+                pnlDialog.Visible = true;
+                Control active = notifications.Next;
+                active.Visible = true;
+                ResizeNotificationByControl(active);
+            }
+            else
+            {
+                pnlDialog.Visible = false;
+            }
+
+        }
+        #endregion Notifications
+
+        #region Menu click handlers
+
+        private void tmnuStatusAway_Click(object sender, EventArgs e)
+        {
+            instance.State.SetAway(tmnuStatusAway.Checked);
+        }
+
+        private void tmnuHelpReadme_Click(object sender, EventArgs e)
+        {
+            System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");
+        }
+
+        private void tmnuStatusBusy_Click(object sender, EventArgs e)
+        {
+            instance.State.SetBusy(tmnuStatusBusy.Checked);
+        }
+
+        private void tmnuControlFly_Click(object sender, EventArgs e)
+        {
+            instance.State.SetFlying(tmnuControlFly.Checked);
+        }
+
+        private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)
+        {
+            instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);
+        }
+
+        private void tmnuPrefs_Click(object sender, EventArgs e)
+        {
+            (new frmSettings(instance)).ShowDialog();
+        }
+
+        private void tbtnAppearance_Click(object sender, EventArgs e)
+        {
+            client.Appearance.RequestSetAppearance(false);
+        }
+
+        private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            //PrimDeserializer.ImportFromFile(client);
+            DisplayImportConsole();
+        }
+
+        private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (ap == null)
+            {
+                ap = new AutoPilot(client);
+                /*
+                ap.InsertWaypoint(new Vector3(66, 163, 21));
+                ap.InsertWaypoint(new Vector3(66, 98, 21));
+
+                ap.InsertWaypoint(new Vector3(101, 98, 21));
+                ap.InsertWaypoint(new Vector3(101, 45, 21));
+                ap.InsertWaypoint(new Vector3(93, 27, 21));
+                ap.InsertWaypoint(new Vector3(106, 12, 21));
+                ap.InsertWaypoint(new Vector3(123, 24, 21));
+                ap.InsertWaypoint(new Vector3(114, 45, 21));
+                ap.InsertWaypoint(new Vector3(114, 98, 21));
+
+                ap.InsertWaypoint(new Vector3(130, 98, 21));
+                ap.InsertWaypoint(new Vector3(130, 163, 21));
+                 **/
+                ap.InsertWaypoint(new Vector3(64, 68, 21));
+                ap.InsertWaypoint(new Vector3(65, 20, 21));
+                ap.InsertWaypoint(new Vector3(33, 23, 21));
+                ap.InsertWaypoint(new Vector3(17, 39, 21));
+                ap.InsertWaypoint(new Vector3(17, 62, 21));
+
+
+            }
+            if (AutoPilotActive)
+            {
+                AutoPilotActive = false;
+                ap.Stop();
+            }
+            else
+            {
+                AutoPilotActive = true;
+                ap.Start();
+            }
+
+        }
+
+        int filesDeleted;
+
+        private void deleteFolder(DirectoryInfo dir)
+        {
+            foreach (var file in dir.GetFiles())
+            {
+                try 
+                {
+                    file.Delete();
+                    filesDeleted++;
+                }
+                catch { }
+            }
+
+            foreach (var subDir in dir.GetDirectories())
+            {
+                deleteFolder(subDir);
+            }
+
+            try { dir.Delete(); }
+            catch { }
+        }
+
+        private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            WorkPool.QueueUserWorkItem(sync =>
+            {
+                filesDeleted = 0;
+                try { deleteFolder(new DirectoryInfo(client.Settings.ASSET_CACHE_DIR)); }
+                catch { }
+                Logger.DebugLog("Wiped out " + filesDeleted + " files from the cache directory.");
+            });
+            instance.Names.CleanCache();
+        }
+
+        private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            instance.COF.RebakeTextures();
+        }
+
+        public void MapToCurrentLocation()
+        {
+            if (MapTab != null && client.Network.Connected)
+            {
+                MapTab.Select();
+                WorldMap.DisplayLocation(client.Network.CurrentSim.Name,
+                    (int)client.Self.SimPosition.X,
+                    (int)client.Self.SimPosition.Y,
+                    (int)client.Self.SimPosition.Z);
+            }
+        }
+
+        private void standToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            instance.State.SetSitting(false, UUID.Zero);
+        }
+
+        private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            client.Self.SitOnGround();
+        }
+
+        private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            try { System.Diagnostics.Process.Start(Application.ExecutablePath); }
+            catch (Exception) { }
+        }
+
+        private void tmnuExit_Click(object sender, EventArgs e)
+        {
+            Close();
+        }
+
+        private void tlblRegionInfo_Click(object sender, EventArgs e)
+        {
+            if (WorldMap != null && client.Network.Connected)
+            {
+                MapTab.Select();
+            }
+        }
+
+        private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ScriptEditor se = new ScriptEditor(instance);
+            se.Dock = DockStyle.Fill;
+            se.ShowDetached();
+        }
+
+        private void tmnuSetHome_Click(object sender, EventArgs e)
+        {
+            client.Self.SetHome();
+        }
+
+        private void tmnuCreateLandmark_Click(object sender, EventArgs e)
+        {
+            string location = string.Format(", {0} ({1}, {2}, {3})",
+                client.Network.CurrentSim.Name,
+                (int)client.Self.SimPosition.X,
+                (int)client.Self.SimPosition.Y,
+                (int)client.Self.SimPosition.Z
+                );
+
+            string name = tlblParcel.Text;
+            int maxLen = 63 - location.Length;
+
+            if (name.Length > maxLen)
+                name = name.Substring(0, maxLen);
+
+            name += location;
+
+            client.Inventory.RequestCreateItem(
+                client.Inventory.FindFolderForType(AssetType.Landmark),
+                name,
+                tlblParcel.ToolTipText,
+                AssetType.Landmark,
+                UUID.Random(),
+                InventoryType.Landmark,
+                PermissionMask.All,
+                (bool success, InventoryItem item) =>
+                {
+                    if (success)
+                    {
+                        BeginInvoke(new MethodInvoker(() =>
+                            {
+                                Landmark ln = new Landmark(instance, (InventoryLandmark)item);
+                                ln.Dock = DockStyle.Fill;
+                                ln.Detached = true;
+                            }));
+                    }
+                }
+            );
+        }
+
+
+        private void timerWorldClock_Tick(object sender, EventArgs e)
+        {
+            lblTime.Text = instance.GetWorldTime().ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);
+        }
+
+        private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ProcessLink("http://jira.openmetaverse.org/browse/RAD");
+        }
+
+        private void accessibilityGuideToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ProcessLink("http://radegast.org/wiki/Accessibility_Guide");
+        }
+
+        private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            (new frmAbout(instance)).ShowDialog();
+        }
+
+        #region Update Checking
+        private UpdateChecker updateChecker = null;
+        private bool ManualUpdateCheck = false;
+
+        public void StartUpdateCheck(bool userInitiated)
+        {
+            ManualUpdateCheck = userInitiated;
+
+            if (updateChecker != null)
+            {
+                if (ManualUpdateCheck)
+                    tabsConsole.DisplayNotificationInChat("Update check already in progress.");
+                return;
+            }
+
+            if (ManualUpdateCheck)
+                tabsConsole.DisplayNotificationInChat("Checking for updates...", ChatBufferTextStyle.StatusBlue);
+            updateChecker = new UpdateChecker();
+            updateChecker.OnUpdateInfoReceived += new UpdateChecker.UpdateInfoCallback(OnUpdateInfoReceived);
+            updateChecker.StartCheck();
+        }
+
+        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            tabsConsole.SelectTab("chat");
+            StartUpdateCheck(true);
+        }
+
+        void OnUpdateInfoReceived(object sender, UpdateCheckerArgs e)
+        {
+            if (InvokeRequired)
+            {
+                BeginInvoke(new MethodInvoker(() => OnUpdateInfoReceived(sender, e)));
+                return;
+            }
+
+            if (!e.Success)
+            {
+                if (ManualUpdateCheck)
+                    tabsConsole.DisplayNotificationInChat("Error: Failed connecting to the update site.", ChatBufferTextStyle.StatusBlue);
+            }
+            else
+            {
+                if (!ManualUpdateCheck && e.Info.DisplayMOTD)
+                {
+                    tabsConsole.DisplayNotificationInChat(e.Info.MOTD, ChatBufferTextStyle.StatusBlue);
+                }
+
+                if (e.Info.UpdateAvailable)
+                {
+                    tabsConsole.DisplayNotificationInChat("New version available at " + e.Info.DownloadSite, ChatBufferTextStyle.Alert);
+                }
+                else
+                {
+                    if (ManualUpdateCheck)
+                        tabsConsole.DisplayNotificationInChat("Your version is up to date.", ChatBufferTextStyle.StatusBlue);
+                }
+            }
+
+            updateChecker.Dispose();
+            updateChecker = null;
+        }
+        #endregion
+
+        private void ToggleHidden(string tabName)
+        {
+            if (!tabsConsole.TabExists(tabName)) return;
+
+            RadegastTab tab = tabsConsole.Tabs[tabName];
+
+            if (tab.Hidden)
+            {
+                tab.Show();
+            }
+            else
+            {
+                if (!tab.Selected)
+                {
+                    tab.Select();
+                }
+                else
+                {
+                    tab.Hide();
+                }
+            }
+        }
+
+        private void tbtnFriends_Click(object sender, EventArgs e)
+        {
+            ToggleHidden("friends");
+        }
+
+        private void tbtnInventory_Click(object sender, EventArgs e)
+        {
+            ToggleHidden("inventory");
+        }
+
+        private void tbtnSearch_Click(object sender, EventArgs e)
+        {
+            ToggleHidden("search");
+        }
+
+        private void tbtnGroups_Click(object sender, EventArgs e)
+        {
+            ToggleHidden("groups");
+        }
+
+        private void tbtnVoice_Click(object sender, EventArgs e)
+        {
+            ToggleHidden("voice");
+        }
+
+        private void tbtnMedia_Click(object sender, EventArgs e)
+        {
+            if (tabsConsole.TabExists("media"))
+            {
+                ToggleHidden("media");
+            }
+            else
+            {
+                RadegastTab tab = tabsConsole.AddTab("media", "Media", mediaConsole);
+                tab.AllowClose = false;
+                tab.AllowHide = true;
+                tab.Select();
+            }
+        }
+
+        private void debugConsoleToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (tabsConsole.TabExists("debug"))
+            {
+                ToggleHidden("debug");
+            }
+            else
+            {
+                RadegastTab tab = tabsConsole.AddTab("debug", "Debug", new DebugConsole(instance));
+                tab.AllowClose = false;
+                tab.AllowHide = true;
+                tab.Select();
+            }
+        }
+
+        private void tbnObjects_Click(object sender, EventArgs e)
+        {
+            if (tabsConsole.TabExists("objects"))
+            {
+                RadegastTab tab = tabsConsole.Tabs["objects"];
+                if (!tab.Selected)
+                {
+                    tab.Select();
+                    ((ObjectsConsole)tab.Control).RefreshObjectList();
+                }
+                else
+                {
+                    tab.Close();
+                }
+            }
+            else
+            {
+                RadegastTab tab = tabsConsole.AddTab("objects", "Objects", new ObjectsConsole(instance));
+                tab.AllowClose = true;
+                tab.AllowDetach = true;
+                tab.Visible = true;
+                tab.AllowHide = false;
+                tab.Select();
+                ((ObjectsConsole)tab.Control).RefreshObjectList();
+            }
+        }
+
+        private void tbtnMap_Click(object sender, EventArgs e)
+        {
+            if (MapTab == null) return; // too soon!
+
+            ToggleHidden("map");
+            if (!MapTab.Hidden)
+                MapToCurrentLocation();
+        }
+
+        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (client.Network.Connected)
+                client.Network.RequestLogout();
+        }
+
+        private void reconnectToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (!client.Network.Connected)
+            {
+                instance.Reconnect();
+            }
+        }
+
+        private frmKeyboardShortcuts keyboardShortcutsForm = null;
+        private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (keyboardShortcutsForm != null)
+            {
+                keyboardShortcutsForm.Focus();
+            }
+            else
+            {
+                keyboardShortcutsForm = new frmKeyboardShortcuts(instance);
+
+                keyboardShortcutsForm.Disposed += (object senderx, EventArgs ex) =>
+                    {
+                        if (components != null)
+                        {
+                            components.Remove(keyboardShortcutsForm);
+                        }
+                        keyboardShortcutsForm = null;
+                    };
+
+                keyboardShortcutsForm.Show(this);
+                keyboardShortcutsForm.Top = Top + 100;
+                keyboardShortcutsForm.Left = Left + 100;
+
+                if (components != null)
+                {
+                    components.Add(keyboardShortcutsForm);
+                }
+            }
+        }
+
+        // Menu item for testing out stuff
+        private void testToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+        }
+
+        private void reloadInventoryToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (tabsConsole.TabExists("inventory"))
+            {
+                ((InventoryConsole)tabsConsole.Tabs["inventory"].Control).ReloadInventory();
+                tabsConsole.Tabs["inventory"].Select();
+            }
+        }
+
+        private void btnLoadScript_Click(object sender, EventArgs e)
+        {
+            if (!TabConsole.TabExists("plugin_manager"))
+            {
+                TabConsole.AddTab("plugin_manager", "Plugins", new PluginsTab(instance));
+            }
+            TabConsole.Tabs["plugin_manager"].Select();
+        }
+
+        private void frmMain_Resize(object sender, EventArgs e)
+        {
+            if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"].AsBoolean())
+            {
+                if (TabConsole.TabExists("scene_window") && !TabConsole.Tabs["scene_window"].Detached)
+                {
+                    TabConsole.Tabs["scene_window"].Close();
+                }
+                ShowInTaskbar = false;
+                trayIcon.Visible = true;
+                trayIcon.BalloonTipText = "Radegast is runnig in the background";
+                trayIcon.ShowBalloonTip(2000);
+            }
+        }
+
+        private void treyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            WindowState = FormWindowState.Normal;
+            ShowInTaskbar = true;
+            trayIcon.Visible = false;
+        }
+
+        private void ctxTreyRestore_Click(object sender, EventArgs e)
+        {
+            treyIcon_MouseDoubleClick(this, null);
+        }
+
+        private void ctxTreyExit_Click(object sender, EventArgs e)
+        {
+            tmnuExit_Click(this, EventArgs.Empty);
+        }
+
+        private void tmnuTeleportHome_Click(object sender, EventArgs e)
+        {
+            TabConsole.DisplayNotificationInChat("Teleporting home...");
+            client.Self.RequestTeleport(UUID.Zero);
+        }
+
+        private void stopAllAnimationsToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            instance.State.StopAllAnimations();
+        }
+
+        public void DisplayRegionParcelConsole()
+        {
+            if (tabsConsole.TabExists("current region info"))
+            {
+                tabsConsole.Tabs["current region info"].Select();
+                (tabsConsole.Tabs["current region info"].Control as RegionInfo).UpdateDisplay();
+            }
+            else
+            {
+                tabsConsole.AddTab("current region info", "Region info", new RegionInfo(instance));
+                tabsConsole.Tabs["current region info"].Select();
+            }
+        }
+
+        public void DisplayExportConsole(uint localID)
+        {
+            if (InvokeRequired)
+            {
+                if (IsHandleCreated || !instance.MonoRuntime)
+                    BeginInvoke(new MethodInvoker(() => DisplayExportConsole(localID)));
+                return;
+            }
+
+            if (tabsConsole.TabExists("export console"))
+            {
+                tabsConsole.Tabs["export console"].Close();
+            }
+            RadegastTab tab = tabsConsole.AddTab("export console", "Export Object", new ExportConsole(client, localID));
+            tab.Select();
+        }
+
+        public void DisplayImportConsole()
+        {
+            if (TabConsole.TabExists("import console"))
+            {
+                TabConsole.Tabs["import console"].Select();
+            }
+            else
+            {
+                RadegastTab tab = tabsConsole.AddTab("import console", "Import Object", new ImportConsole(client));
+                tab.AllowClose = false;
+                tab.AllowHide = true;
+                tab.Select();
+            }
+        }
+
+        public void DisplayColladaConsole(Primitive prim)
+        {
+            if (InvokeRequired)
+            {
+                if (IsHandleCreated || !instance.MonoRuntime)
+                    BeginInvoke(new MethodInvoker(() => DisplayColladaConsole(prim)));
+                return;
+            }
+
+            if (tabsConsole.TabExists("collada console"))
+            {
+                tabsConsole.Tabs["collada console"].Close();
+            }
+            RadegastTab tab = tabsConsole.AddTab("collada console", "Export Collada", new ExportCollada(instance, prim));
+            tab.Select();
+        }
+
+        private void regionParcelToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            DisplayRegionParcelConsole();
+        }
+
+        private void tlblParcel_Click(object sender, EventArgs e)
+        {
+            if (!client.Network.Connected) return;
+            DisplayRegionParcelConsole();
+        }
+
+        private void changeMyDisplayNameToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (!client.Avatars.DisplayNamesAvailable())
+            {
+                tabsConsole.DisplayNotificationInChat("This grid does not support display names.", ChatBufferTextStyle.Error);
+                return;
+            }
+
+            var dlg = new DisplayNameChange(instance);
+            dlg.ShowDialog();
+        }
+
+        private void muteListToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (!tabsConsole.TabExists("mute list console"))
+            {
+                tabsConsole.AddTab("mute list console", "Mute list", new MuteList(instance));
+            }
+            tabsConsole.Tabs["mute list console"].Select();
+        }
+
+        private void uploadImageToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (!tabsConsole.TabExists("image upload console"))
+            {
+                tabsConsole.AddTab("image upload console", "Upload image", new ImageUploadConsole(instance));
+            }
+            tabsConsole.Tabs["image upload console"].Select();
+        }
+        #endregion
+
+        private void myAttachmentsToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            Avatar av = client.Network.CurrentSim.ObjectsAvatars.Find((Avatar a) => { return a.ID == client.Self.AgentID; });
+
+            if (av == null)
+            {
+                tabsConsole.DisplayNotificationInChat("Unable to find my avatar!", ChatBufferTextStyle.Error);
+                return;
+            }
+
+            if (!instance.TabConsole.TabExists("AT: " + av.ID.ToString()))
+            {
+                instance.TabConsole.AddTab("AT: " + av.ID.ToString(), "My Attachments", new AttachmentTab(instance, av));
+            }
+            instance.TabConsole.SelectTab("AT: " + av.ID.ToString());
+
+        }
+
+        private void tsb3D_Click(object sender, EventArgs e)
+        {
+            if (instance.TabConsole.TabExists("scene_window"))
+            {
+                instance.TabConsole.Tabs["scene_window"].Select();
+            }
+            else
+            {
+                var control = new Rendering.SceneWindow(instance);
+                control.Dock = DockStyle.Fill;
+                instance.TabConsole.AddTab("scene_window", "Scene Viewer", control);
+                instance.TabConsole.Tabs["scene_window"].Floater = false;
+                instance.TabConsole.Tabs["scene_window"].CloseOnDetachedClose = true;
+                control.RegisterTabEvents();
+
+                if (instance.GlobalSettings["scene_window_docked"])
+                {
+                    instance.TabConsole.Tabs["scene_window"].Select();
+                }
+                else
+                {
+                    instance.TabConsole.Tabs["scene_window"].Detach(instance);
+                }
+            }
+        }
+
+        private void loginToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            // We are logging in without exiting the client
+            // Mark last run as successful
+            instance.MarkEndExecution();
+            TabConsole.InitializeMainTab();
+            TabConsole.Tabs["login"].Select();
+        }
+
+        private void setMaturityLevel(string level)
+        {
+            client.Self.SetAgentAccess(level, res =>
+            {
+                if (res.Success)
+                {
+                    tabsConsole.DisplayNotificationInChat("Successfully changed maturity access level to " + res.NewLevel);
+                }
+                else
+                {
+                    tabsConsole.DisplayNotificationInChat("Failed to change maturity access level.", ChatBufferTextStyle.Error);
+                }
+            });
+        }
+
+        private void pGToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            setMaturityLevel("PG");
+        }
+
+        private void matureToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            setMaturityLevel("M");
+        }
+
+        private void adultToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            setMaturityLevel("A");
+        }
+
+        private void uploadmeshToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (!tabsConsole.TabExists("mesh upload console"))
+            {
+                tabsConsole.AddTab("mesh upload console", "Upload mesh", new MeshUploadConsole(instance));
+            }
+            tabsConsole.Tabs["mesh upload console"].Select();
+        }
+
+    }
 }
\ No newline at end of file