OSDN Git Service

- Added Help menu and About box
[radegast/radegast.git] / Radegast / GUI / Dialogs / MainForm.cs
1 // \r
2 // Radegast Metaverse Client\r
3 // Copyright (c) 2009, Radegast Development Team\r
4 // All rights reserved.\r
5 // \r
6 // Redistribution and use in source and binary forms, with or without\r
7 // modification, are permitted provided that the following conditions are met:\r
8 // \r
9 //     * Redistributions of source code must retain the above copyright notice,\r
10 //       this list of conditions and the following disclaimer.\r
11 //     * Redistributions in binary form must reproduce the above copyright\r
12 //       notice, this list of conditions and the following disclaimer in the\r
13 //       documentation and/or other materials provided with the distribution.\r
14 //     * Neither the name of the application "Radegast", nor the names of its\r
15 //       contributors may be used to endorse or promote products derived from\r
16 //       this software without specific prior written permission.\r
17 // \r
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 //\r
29 // $Id$\r
30 //\r
31 using System;\r
32 using System.Collections.Generic;\r
33 using System.Drawing;\r
34 using System.Text;\r
35 using System.Text.RegularExpressions;\r
36 using System.Timers;\r
37 using System.Threading;\r
38 using System.Windows.Forms;\r
39 using System.Resources;\r
40 using System.IO;\r
41 using System.Web;\r
42 using Radegast.Netcom;\r
43 using OpenMetaverse;\r
44 using OpenMetaverse.StructuredData;\r
45 \r
46 namespace Radegast\r
47 {\r
48     public partial class frmMain : RadegastForm\r
49     {\r
50         #region Public members\r
51         public static ImageList ResourceImages = new ImageList();\r
52         public static List<string> ImageNames = new List<string>();\r
53         public frmMap WorldMap { get { return worldMap; } }\r
54         private frmMap worldMap;\r
55         public TabsConsole TabConsole\r
56         {\r
57             get { return tabsConsole; }\r
58         }\r
59 \r
60         public MediaConsole MediaConsole { get { return mediaConsole; } }\r
61 \r
62         /// <summary>\r
63         /// Drop down that contains the tools menu\r
64         /// </summary>\r
65         public ToolStripDropDownButton ToolsMenu\r
66         {\r
67             get { return tbnTools; }\r
68         }\r
69 \r
70         /// <summary>\r
71         /// Dropdown that contains the heelp menu\r
72         /// </summary>\r
73         public ToolStripDropDownButton HelpMenu\r
74         {\r
75             get { return tbtnHelp; }\r
76         }\r
77 \r
78         /// <summary>\r
79         /// Drop down that contants the plugins menu. Make sure to set it Visible if\r
80         /// you add items to this menu, it's hidden by default\r
81         /// </summary>\r
82         public ToolStripDropDownButton PluginsMenu\r
83         {\r
84             get { return tbnPlugins; }\r
85         }\r
86 \r
87         #endregion\r
88 \r
89         #region Private members\r
90         private RadegastInstance instance;\r
91         private RadegastNetcom netcom;\r
92         private GridClient client;\r
93         private TabsConsole tabsConsole;\r
94         private frmDebugLog debugLogForm;\r
95         private System.Timers.Timer statusTimer;\r
96         private AutoPilot ap;\r
97         private bool AutoPilotActive = false;\r
98         private TransparentButton btnDialogNextControl;\r
99         private MediaConsole mediaConsole;\r
100         #endregion\r
101 \r
102         #region Constructor and disposal\r
103         public frmMain(RadegastInstance instance)\r
104             : base(instance)\r
105         {\r
106             GetSLTimeZone();\r
107             InitializeComponent();\r
108             Disposed += new EventHandler(frmMain_Disposed);\r
109 \r
110             this.instance = instance;\r
111             client = this.instance.Client;\r
112             netcom = this.instance.Netcom;\r
113             netcom.NetcomSync = this;\r
114 \r
115             pnlDialog.Visible = false;\r
116             btnDialogNextControl = new TransparentButton();\r
117             pnlDialog.Controls.Add(btnDialogNextControl);\r
118             pnlDialog.Top = 0;\r
119 \r
120             btnDialogNextControl.Size = new Size(35, 20);\r
121             btnDialogNextControl.BackColor = Color.Transparent;\r
122             btnDialogNextControl.ForeColor = Color.Gold;\r
123             btnDialogNextControl.FlatAppearance.BorderSize = 0;\r
124             btnDialogNextControl.FlatStyle = FlatStyle.Flat;\r
125             btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;\r
126             btnDialogNextControl.Text = ">>";\r
127             btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);\r
128             btnDialogNextControl.Margin = new Padding(0);\r
129             btnDialogNextControl.Padding = new Padding(0);\r
130             btnDialogNextControl.UseVisualStyleBackColor = false;\r
131             btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
132             btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
133             btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);\r
134 \r
135             if (instance.MonoRuntime)\r
136             {\r
137                 statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;\r
138             }\r
139 \r
140             // Config options\r
141             if (instance.GlobalSettings["transaction_notification_chat"].Type == OSDType.Unknown)\r
142                 instance.GlobalSettings["transaction_notification_chat"] = OSD.FromBoolean(true);\r
143 \r
144             if (instance.GlobalSettings["transaction_notification_dialog"].Type == OSDType.Unknown)\r
145                 instance.GlobalSettings["transaction_notification_dialog"] = OSD.FromBoolean(true);\r
146 \r
147             // Callbacks\r
148             netcom.ClientLoginStatus += new EventHandler<ClientLoginEventArgs>(netcom_ClientLoginStatus);\r
149             netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);\r
150             netcom.ClientDisconnected += new EventHandler<ClientDisconnectEventArgs>(netcom_ClientDisconnected);\r
151             client.Parcels.OnParcelProperties += new ParcelManager.ParcelPropertiesCallback(Parcels_OnParcelProperties);\r
152             client.Self.OnMoneyBalanceReplyReceived += new AgentManager.MoneyBalanceReplyCallback(Self_OnMoneyBalanceReplyReceived);\r
153 \r
154             InitializeStatusTimer();\r
155             RefreshWindowTitle();\r
156         }\r
157 \r
158         void frmMain_Disposed(object sender, EventArgs e)\r
159         {\r
160             netcom.ClientLoginStatus -= new EventHandler<ClientLoginEventArgs>(netcom_ClientLoginStatus);\r
161             netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);\r
162             netcom.ClientDisconnected -= new EventHandler<ClientDisconnectEventArgs>(netcom_ClientDisconnected);\r
163             client.Parcels.OnParcelProperties -= new ParcelManager.ParcelPropertiesCallback(Parcels_OnParcelProperties);\r
164             client.Self.OnMoneyBalanceReplyReceived -= new AgentManager.MoneyBalanceReplyCallback(Self_OnMoneyBalanceReplyReceived);\r
165             this.instance.CleanUp();\r
166         }\r
167         #endregion\r
168 \r
169         #region Event handlers\r
170         void Self_OnMoneyBalanceReplyReceived(UUID transactionID, bool transactionSuccess, int balance, int metersCredit, int metersCommitted, string description)\r
171         {\r
172             if (!String.IsNullOrEmpty(description))\r
173             {\r
174                 if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())\r
175                     AddNotification(new ntfGeneric(instance, description));\r
176                 if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())\r
177                     TabConsole.DisplayNotificationInChat(description);\r
178             }\r
179         }\r
180 \r
181         public void InitializeControls()\r
182         {\r
183             InitializeTabsConsole();\r
184             InitializeDebugLogForm();\r
185             if (instance.MediaManager.SoundSystemAvailable)\r
186             {\r
187                 mediaConsole = new MediaConsole(instance);\r
188                 tbtnMedia.Visible = true;\r
189             }\r
190         }\r
191 \r
192         private void netcom_ClientLoginStatus(object sender, ClientLoginEventArgs e)\r
193         {\r
194             if (e.Status != LoginStatus.Success) return;\r
195 \r
196             tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled = true;\r
197             statusTimer.Start();\r
198             RefreshWindowTitle();\r
199         }\r
200 \r
201         private void netcom_ClientLoggedOut(object sender, EventArgs e)\r
202         {\r
203             tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled = false;\r
204 \r
205             statusTimer.Stop();\r
206 \r
207             RefreshStatusBar();\r
208             RefreshWindowTitle();\r
209         }\r
210 \r
211         private void netcom_ClientDisconnected(object sender, ClientDisconnectEventArgs e)\r
212         {\r
213             if (e.Type == NetworkManager.DisconnectType.ClientInitiated) return;\r
214 \r
215             tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = false;\r
216 \r
217             statusTimer.Stop();\r
218 \r
219             RefreshStatusBar();\r
220             RefreshWindowTitle();\r
221         }\r
222 \r
223         private void frmMain_FormClosing(object sender, FormClosingEventArgs e)\r
224         {\r
225             if (mediaConsole != null)\r
226             {\r
227                 mediaConsole.Dispose();\r
228                 mediaConsole = null;\r
229             }\r
230 \r
231             if (debugLogForm != null)\r
232             {\r
233                 debugLogForm.Close();\r
234                 debugLogForm.Dispose();\r
235                 debugLogForm = null;\r
236             }\r
237 \r
238             if (worldMap != null)\r
239             {\r
240                 worldMap.Close();\r
241                 worldMap.Dispose();\r
242                 worldMap = null;\r
243             }\r
244 \r
245             if (netcom.IsLoggedIn)\r
246             {\r
247                 Thread saveInvToDisk = new Thread(new ThreadStart(\r
248                     delegate()\r
249                     {\r
250                         client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);\r
251                     }));\r
252                 saveInvToDisk.Name = "Save inventory to disk";\r
253                 saveInvToDisk.Start();\r
254 \r
255                 netcom.Logout();\r
256             }\r
257         }\r
258         #endregion\r
259 \r
260         # region Update status\r
261 \r
262         private void Parcels_OnParcelProperties(Simulator simulator, Parcel parcel, ParcelResult result, int selectedPrims,\r
263     int sequenceID, bool snapSelection)\r
264         {\r
265             if (result != ParcelResult.Single) return;\r
266             if (InvokeRequired)\r
267             {\r
268                 BeginInvoke(new MethodInvoker(delegate()\r
269                 {\r
270                     Parcels_OnParcelProperties(simulator, parcel, result, selectedPrims, sequenceID, snapSelection);\r
271                 }\r
272                 ));\r
273                 return;\r
274             }\r
275 \r
276             tlblParcel.Text = parcel.Name;\r
277             tlblParcel.ToolTipText = parcel.Desc;\r
278 \r
279             if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)\r
280                 icoNoFly.Visible = true;\r
281             else\r
282                 icoNoFly.Visible = false;\r
283 \r
284             if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)\r
285                 icoNoBuild.Visible = true;\r
286             else\r
287                 icoNoBuild.Visible = false;\r
288 \r
289             if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)\r
290                 icoNoScript.Visible = true;\r
291             else\r
292                 icoNoScript.Visible = false;\r
293 \r
294             if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)\r
295                 icoNoPush.Visible = true;\r
296             else\r
297                 icoNoPush.Visible = false;\r
298 \r
299             if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)\r
300                 icoHealth.Visible = true;\r
301             else\r
302                 icoHealth.Visible = false;\r
303 \r
304             if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)\r
305                 icoNoVoice.Visible = true;\r
306             else\r
307                 icoNoVoice.Visible = false;\r
308         }\r
309 \r
310         private void RefreshStatusBar()\r
311         {\r
312             if (netcom.IsLoggedIn)\r
313             {\r
314                 tlblLoginName.Text = netcom.LoginOptions.FullName;\r
315                 tlblMoneyBalance.Text = client.Self.Balance.ToString();\r
316                 icoHealth.Text = client.Self.Health.ToString() + "%";\r
317 \r
318                 tlblRegionInfo.Text =\r
319                     client.Network.CurrentSim.Name +\r
320                     " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +\r
321                     Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +\r
322                     Math.Floor(client.Self.SimPosition.Z).ToString() + ")";\r
323             }\r
324             else\r
325             {\r
326                 tlblLoginName.Text = "Offline";\r
327                 tlblMoneyBalance.Text = "0";\r
328                 icoHealth.Text = "0%";\r
329                 tlblRegionInfo.Text = "No Region";\r
330                 tlblParcel.Text = "No Parcel";\r
331 \r
332                 icoHealth.Visible = false;\r
333                 icoNoBuild.Visible = false;\r
334                 icoNoFly.Visible = false;\r
335                 icoNoPush.Visible = false;\r
336                 icoNoScript.Visible = false;\r
337                 icoNoVoice.Visible = false;\r
338             }\r
339         }\r
340 \r
341         private void RefreshWindowTitle()\r
342         {\r
343             StringBuilder sb = new StringBuilder();\r
344             sb.Append("Radegast - ");\r
345 \r
346             if (netcom.IsLoggedIn)\r
347             {\r
348                 sb.Append("[" + netcom.LoginOptions.FullName + "]");\r
349 \r
350                 if (instance.State.IsAway)\r
351                 {\r
352                     sb.Append(" - Away");\r
353                     if (instance.State.IsBusy) sb.Append(", Busy");\r
354                 }\r
355                 else if (instance.State.IsBusy)\r
356                 {\r
357                     sb.Append(" - Busy");\r
358                 }\r
359 \r
360                 if (instance.State.IsFollowing)\r
361                 {\r
362                     sb.Append(" - Following ");\r
363                     sb.Append(instance.State.FollowName);\r
364                 }\r
365             }\r
366             else\r
367             {\r
368                 sb.Append("Logged Out");\r
369             }\r
370 \r
371             this.Text = sb.ToString();\r
372             sb = null;\r
373         }\r
374 \r
375         private void InitializeStatusTimer()\r
376         {\r
377             statusTimer = new System.Timers.Timer(250);\r
378             statusTimer.SynchronizingObject = this;\r
379             statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);\r
380         }\r
381 \r
382         private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)\r
383         {\r
384             RefreshWindowTitle();\r
385             RefreshStatusBar();\r
386         }\r
387         #endregion\r
388 \r
389         #region Initialization, configuration, and key shortcuts\r
390         private void InitializeTabsConsole()\r
391         {\r
392             tabsConsole = new TabsConsole(instance);\r
393             tabsConsole.Dock = DockStyle.Fill;\r
394             toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);\r
395         }\r
396 \r
397         private void InitializeDebugLogForm()\r
398         {\r
399             debugLogForm = new frmDebugLog(instance);\r
400         }\r
401 \r
402         private void frmMain_KeyDown(object sender, KeyEventArgs e)\r
403         {\r
404             if (e.Control && e.Alt && e.KeyCode == Keys.D)\r
405             {\r
406                 e.Handled = e.SuppressKeyPress = true;\r
407             }\r
408 \r
409             if (e.Control && e.KeyCode == Keys.O && client.Network.Connected)\r
410             {\r
411                 e.Handled = e.SuppressKeyPress = true;\r
412             }\r
413 \r
414             if (e.Control && e.KeyCode == Keys.G)\r
415             {\r
416                 e.Handled = e.SuppressKeyPress = true;\r
417             }\r
418 \r
419             if (e.Control && e.KeyCode == Keys.M && Clipboard.ContainsText() && client.Network.Connected)\r
420             {\r
421                 e.Handled = e.SuppressKeyPress = true;\r
422             }\r
423 \r
424             if (e.Control && e.KeyCode == Keys.Right)\r
425             {\r
426                 e.Handled = e.SuppressKeyPress = true;\r
427             }\r
428 \r
429             if (e.Control && e.KeyCode == Keys.Left)\r
430             {\r
431                 e.Handled = e.SuppressKeyPress = true;\r
432             }\r
433         }\r
434 \r
435 \r
436         private void frmMain_KeyUp(object sender, KeyEventArgs e)\r
437         {\r
438             // alt-ctrl-d activate debug menu\r
439             if (e.Control && e.Alt && e.KeyCode == Keys.D)\r
440             {\r
441                 tbtnDebug.Visible = !tbtnDebug.Visible;\r
442                 e.Handled = e.SuppressKeyPress = true;\r
443             }\r
444 \r
445             // ctrl-o, open objects finder\r
446             if (e.Control && e.KeyCode == Keys.O && client.Network.Connected)\r
447             {\r
448                 (new frmObjects(instance)).Show();\r
449                 e.Handled = e.SuppressKeyPress = true;\r
450             }\r
451 \r
452             // ctrl-g, goto slurl\r
453             if (e.Control && e.KeyCode == Keys.G && Clipboard.ContainsText() && client.Network.Connected)\r
454             {\r
455                 if (!ProcessLink(Clipboard.GetText(), true))\r
456                     MapToCurrentLocation();\r
457                 e.Handled = e.SuppressKeyPress = true;\r
458             }\r
459 \r
460             // ctrl-m, open map\r
461             if (e.Control && e.KeyCode == Keys.M && Clipboard.ContainsText() && client.Network.Connected)\r
462             {\r
463                 MapToCurrentLocation();\r
464                 e.Handled = e.SuppressKeyPress = true;\r
465             }\r
466 \r
467             // ctrl-right_arrow, select next tab\r
468             if (e.Control && e.KeyCode == Keys.Right)\r
469             {\r
470                 TabConsole.SelectNextTab();\r
471                 e.Handled = e.SuppressKeyPress = true;\r
472             }\r
473 \r
474             // ctrl-right_arrow, select previous tab\r
475             if (e.Control && e.KeyCode == Keys.Left)\r
476             {\r
477                 TabConsole.SelectPreviousTab();\r
478                 e.Handled = e.SuppressKeyPress = true;\r
479             }\r
480         }\r
481 \r
482 \r
483         private void frmMain_Load(object sender, EventArgs e)\r
484         {\r
485             worldMap = new frmMap(instance);\r
486             tabsConsole.SelectTab("login");\r
487             ResourceManager rm = Properties.Resources.ResourceManager;\r
488             ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);\r
489             System.Collections.IDictionaryEnumerator de = set.GetEnumerator();\r
490             while (de.MoveNext() == true)\r
491             {\r
492                 if (de.Entry.Value is Image)\r
493                 {\r
494                     Bitmap bitMap = de.Entry.Value as Bitmap;\r
495                     ResourceImages.Images.Add(bitMap);\r
496                     ImageNames.Add(de.Entry.Key.ToString());\r
497                 }\r
498             }\r
499         }\r
500         #endregion\r
501 \r
502         #region Public methods\r
503 \r
504         public void AddLogMessage(string msg, log4net.Core.Level level)\r
505         {\r
506             if (debugLogForm != null && !debugLogForm.IsDisposed)\r
507             {            \r
508                 // Log form handlles the InvokeNeeded                                      \r
509                 debugLogForm.AddLogMessage(msg, level);\r
510             }\r
511         }\r
512 \r
513         public void ProcessLink(string link)\r
514         {\r
515             ProcessLink(link, false);\r
516         }\r
517 \r
518         public bool ProcessLink(string link, bool onlyMap)\r
519         {\r
520             if (!link.Contains("://"))\r
521             {\r
522                 link = "http://" + link;\r
523             }\r
524 \r
525             Regex r = new Regex(@"^(http://slurl.com/secondlife/|secondlife://)([^/]+)/(\d+)/(\d+)(/(\d+))?");\r
526             Match m = r.Match(link);\r
527 \r
528             if (m.Success)\r
529             {\r
530                 string region = HttpUtility.UrlDecode(m.Groups[2].Value);\r
531                 int x = int.Parse(m.Groups[3].Value);\r
532                 int y = int.Parse(m.Groups[4].Value);\r
533                 int z = 0;\r
534 \r
535                 if (m.Groups.Count > 5 && m.Groups[6].Value != String.Empty)\r
536                 {\r
537                     z = int.Parse(m.Groups[6].Value);\r
538                 }\r
539 \r
540                 worldMap.Show();\r
541                 worldMap.Focus();\r
542                 worldMap.DisplayLocation(region, x, y, z);\r
543                 return true;\r
544             }\r
545             else if (!onlyMap)\r
546             {\r
547                 System.Diagnostics.Process.Start(link);\r
548             }\r
549             return false;\r
550         }\r
551         #endregion\r
552 \r
553         #region Notifications\r
554         CircularList<Control> notifications = new CircularList<Control>();\r
555 \r
556         public Color NotificationBackground\r
557         {\r
558             get { return pnlDialog.BackColor; }\r
559         }\r
560 \r
561         void ResizeNotificationByControl(Control active)\r
562         {\r
563             int Width = active.Size.Width + 6;\r
564             int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;\r
565             pnlDialog.Size = new Size(Width, Height);\r
566             pnlDialog.Top = 0;\r
567             pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;\r
568 \r
569             btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
570             btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
571 \r
572             btnDialogNextControl.BringToFront();\r
573         }\r
574 \r
575         public void AddNotification(Control control)\r
576         {\r
577             if (InvokeRequired)\r
578             {\r
579                 BeginInvoke(new MethodInvoker(delegate()\r
580                 {\r
581                     AddNotification(control);\r
582                 }\r
583                 ));\r
584                 return;\r
585             }\r
586 \r
587             FormFlash.StartFlash(this);\r
588             pnlDialog.Visible = true;\r
589             pnlDialog.BringToFront();\r
590 \r
591             foreach (Control existing in notifications)\r
592             {\r
593                 existing.Visible = false;\r
594             }\r
595 \r
596             notifications.Add(control);\r
597             control.Visible = true;\r
598             control.Anchor = AnchorStyles.Top | AnchorStyles.Left;\r
599             control.Top = 3;\r
600             control.Left = 3;\r
601             pnlDialog.Controls.Add(control);\r
602             ResizeNotificationByControl(control);\r
603 \r
604             btnDialogNextControl.Visible = notifications.Count > 1;\r
605         }\r
606 \r
607         public void RemoveNotification(Control control)\r
608         {\r
609             pnlDialog.Controls.Remove(control);\r
610             notifications.Remove(control);\r
611             control.Dispose();\r
612 \r
613             if (notifications.HasNext)\r
614             {\r
615                 pnlDialog.Visible = true;\r
616                 Control active = notifications.Next;\r
617                 active.Visible = true;\r
618                 ResizeNotificationByControl(active);\r
619             }\r
620             else\r
621             {\r
622                 pnlDialog.Visible = false;\r
623             }\r
624 \r
625             btnDialogNextControl.Visible = notifications.Count > 1;\r
626         }\r
627 \r
628         private void btnDialogNextControl_Click(object sender, EventArgs e)\r
629         {\r
630             foreach (Control existing in notifications)\r
631             {\r
632                 existing.Visible = false;\r
633             }\r
634 \r
635             if (notifications.HasNext)\r
636             {\r
637                 pnlDialog.Visible = true;\r
638                 Control active = notifications.Next;\r
639                 active.Visible = true;\r
640                 ResizeNotificationByControl(active);\r
641             }\r
642             else\r
643             {\r
644                 pnlDialog.Visible = false;\r
645             }\r
646 \r
647         }\r
648         #endregion Notifications\r
649 \r
650         #region Menu click handlers\r
651 \r
652         private void tbtnTeleport_Click(object sender, EventArgs e)\r
653         {\r
654             (new frmTeleport(instance)).ShowDialog();\r
655         }\r
656 \r
657         private void tmnuStatusAway_Click(object sender, EventArgs e)\r
658         {\r
659             instance.State.SetAway(tmnuStatusAway.Checked);\r
660         }\r
661 \r
662         private void tmnuHelpReadme_Click(object sender, EventArgs e)\r
663         {\r
664             System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");\r
665         }\r
666 \r
667         private void tmnuStatusBusy_Click(object sender, EventArgs e)\r
668         {\r
669             instance.State.SetBusy(tmnuStatusBusy.Checked);\r
670         }\r
671 \r
672         private void tmnuControlFly_Click(object sender, EventArgs e)\r
673         {\r
674             instance.State.SetFlying(tmnuControlFly.Checked);\r
675         }\r
676 \r
677         private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)\r
678         {\r
679             instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);\r
680         }\r
681 \r
682         private void tmnuDebugLog_Click(object sender, EventArgs e)\r
683         {\r
684             debugLogForm.Show();\r
685         }\r
686 \r
687         private void tmnuPrefs_Click(object sender, EventArgs e)\r
688         {\r
689             (new frmSettings(instance)).ShowDialog();\r
690         }\r
691 \r
692         private void tbtnObjects_Click(object sender, EventArgs e)\r
693         {\r
694             (new frmObjects(instance)).Show();\r
695         }\r
696 \r
697         private void tbtnAppearance_Click(object sender, EventArgs e)\r
698         {\r
699             client.Appearance.RequestSetAppearance(false);\r
700         }\r
701 \r
702         private void groupsToolStripMenuItem_Click(object sender, EventArgs e)\r
703         {\r
704             (new GroupsDialog(instance)).Show();\r
705         }\r
706 \r
707         private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)\r
708         {\r
709             PrimDeserializer.ImportFromFile(client);\r
710         }\r
711 \r
712         private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)\r
713         {\r
714             if (ap == null)\r
715             {\r
716                 ap = new AutoPilot(client);\r
717                 /*\r
718                 ap.InsertWaypoint(new Vector3(66, 163, 21));\r
719                 ap.InsertWaypoint(new Vector3(66, 98, 21));\r
720 \r
721                 ap.InsertWaypoint(new Vector3(101, 98, 21));\r
722                 ap.InsertWaypoint(new Vector3(101, 45, 21));\r
723                 ap.InsertWaypoint(new Vector3(93, 27, 21));\r
724                 ap.InsertWaypoint(new Vector3(106, 12, 21));\r
725                 ap.InsertWaypoint(new Vector3(123, 24, 21));\r
726                 ap.InsertWaypoint(new Vector3(114, 45, 21));\r
727                 ap.InsertWaypoint(new Vector3(114, 98, 21));\r
728 \r
729                 ap.InsertWaypoint(new Vector3(130, 98, 21));\r
730                 ap.InsertWaypoint(new Vector3(130, 163, 21));\r
731                  **/\r
732                 ap.InsertWaypoint(new Vector3(64, 68, 21));\r
733                 ap.InsertWaypoint(new Vector3(65, 20, 21));\r
734                 ap.InsertWaypoint(new Vector3(33, 23, 21));\r
735                 ap.InsertWaypoint(new Vector3(17, 39, 21));\r
736                 ap.InsertWaypoint(new Vector3(17, 62, 21));\r
737 \r
738 \r
739             }\r
740             if (AutoPilotActive)\r
741             {\r
742                 AutoPilotActive = false;\r
743                 ap.Stop();\r
744             }\r
745             else\r
746             {\r
747                 AutoPilotActive = true;\r
748                 ap.Start();\r
749             }\r
750 \r
751         }\r
752 \r
753         private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)\r
754         {\r
755             client.Assets.Cache.Clear();\r
756             DirectoryInfo di = new DirectoryInfo(instance.AnimCacheDir);\r
757             FileInfo[] files = di.GetFiles();\r
758 \r
759             int num = 0;\r
760             foreach (FileInfo file in files)\r
761             {\r
762                 file.Delete();\r
763                 ++num;\r
764             }\r
765 \r
766             Logger.Log("Wiped out " + num + " files from the anim cache directory.", Helpers.LogLevel.Debug);\r
767 \r
768         }\r
769 \r
770         private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)\r
771         {\r
772             client.Appearance.RequestSetAppearance(true);\r
773         }\r
774 \r
775         public void MapToCurrentLocation()\r
776         {\r
777             if (worldMap != null && client.Network.Connected)\r
778             {\r
779                 worldMap.Show();\r
780                 worldMap.Focus();\r
781                 worldMap.DisplayLocation(client.Network.CurrentSim.Name,\r
782                     (int)client.Self.SimPosition.X,\r
783                     (int)client.Self.SimPosition.Y,\r
784                     (int)client.Self.SimPosition.Z);\r
785             }\r
786         }\r
787 \r
788         private void mapToolStripMenuItem_Click(object sender, EventArgs e)\r
789         {\r
790             MapToCurrentLocation();\r
791         }\r
792 \r
793         private void standToolStripMenuItem_Click(object sender, EventArgs e)\r
794         {\r
795             client.Self.Stand();\r
796         }\r
797 \r
798         private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)\r
799         {\r
800             client.Self.SitOnGround();\r
801         }\r
802 \r
803         private frmObjects objectWindow;\r
804 \r
805         private void tbnObjects_Click(object sender, EventArgs e)\r
806         {\r
807             if (objectWindow == null)\r
808             {\r
809                 objectWindow = new frmObjects(instance);\r
810                 objectWindow.Disposed += new EventHandler(objectWindow_Disposed);\r
811                 objectWindow.Show();\r
812             }\r
813             objectWindow.Focus();\r
814         }\r
815 \r
816         void objectWindow_Disposed(object sender, EventArgs e)\r
817         {\r
818             objectWindow = null;\r
819         }\r
820 \r
821         private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)\r
822         {\r
823             try { System.Diagnostics.Process.Start(Application.ExecutablePath); }\r
824             catch (Exception) { }\r
825         }\r
826 \r
827         private void tmnuExit_Click(object sender, EventArgs e)\r
828         {\r
829             Close();\r
830         }\r
831 \r
832         private void tlblRegionInfo_Click(object sender, EventArgs e)\r
833         {\r
834             if (worldMap != null && client.Network.Connected)\r
835             {\r
836                 worldMap.Show();\r
837             }\r
838         }\r
839 \r
840         private void tbtnGroups_Click(object sender, EventArgs e)\r
841         {\r
842             (new GroupsDialog(instance)).Show();\r
843         }\r
844 \r
845         private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)\r
846         {\r
847             ScriptEditor se = new ScriptEditor(instance);\r
848             se.Dock = DockStyle.Fill;\r
849             se.ShowDetached();\r
850         }\r
851 \r
852         private void tmnuSetHome_Click(object sender, EventArgs e)\r
853         {\r
854             client.Self.SetHome();\r
855         }\r
856 \r
857         private void tmnuCreateLandmark_Click(object sender, EventArgs e)\r
858         {\r
859             string location = string.Format(", {0} ({1}, {2}, {3})",\r
860                 client.Network.CurrentSim.Name,\r
861                 (int)client.Self.SimPosition.X,\r
862                 (int)client.Self.SimPosition.Y,\r
863                 (int)client.Self.SimPosition.Z\r
864                 );\r
865 \r
866             string name = tlblParcel.Text;\r
867             int maxLen = 63 - location.Length;\r
868 \r
869             if (name.Length > maxLen)\r
870                 name = name.Substring(0, maxLen);\r
871 \r
872             name += location;\r
873 \r
874             client.Inventory.RequestCreateItem(\r
875                 client.Inventory.FindFolderForType(AssetType.Landmark),\r
876                 name,\r
877                 tlblParcel.ToolTipText,\r
878                 AssetType.Landmark,\r
879                 UUID.Random(),\r
880                 InventoryType.Landmark,\r
881                 PermissionMask.All,\r
882                 (bool success, InventoryItem item) =>\r
883                 {\r
884                     if (success)\r
885                     {\r
886                         BeginInvoke(new MethodInvoker(() =>\r
887                             {\r
888                                 Landmark ln = new Landmark(instance, (InventoryLandmark)item);\r
889                                 ln.Dock = DockStyle.Fill;\r
890                                 ln.Detached = true;\r
891                             }));\r
892                     }\r
893                 }\r
894             );\r
895         }\r
896 \r
897         private void tmnuTeleportHome_Click(object sender, EventArgs e)\r
898         {\r
899             worldMap.GoHome();\r
900         }\r
901 \r
902         private TimeZoneInfo SLTime;\r
903 \r
904         private void GetSLTimeZone()\r
905         {\r
906             try\r
907             {\r
908                 foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())\r
909                 {\r
910                     if (tz.Id == "Pacific Standard Time" || tz.Id == "America/Los_Angeles")\r
911                     {\r
912                         SLTime = tz;\r
913                         break;\r
914                     }\r
915                 }\r
916             }\r
917             catch (Exception) { }\r
918         }\r
919 \r
920         private void timerWorldClock_Tick(object sender, EventArgs e)\r
921         {\r
922             DateTime now;\r
923             try\r
924             {\r
925                 if (SLTime != null)\r
926                     now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, SLTime);\r
927                 else\r
928                     now = DateTime.UtcNow.AddHours(-7);\r
929             }\r
930             catch (Exception)\r
931             {\r
932                 now = DateTime.UtcNow.AddHours(-7);\r
933             }\r
934             lblTime.Text = now.ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);\r
935         }\r
936 \r
937         private void tbtnMedia_Click(object sender, EventArgs e)\r
938         {\r
939             if (!mediaConsole.Detached)\r
940                 mediaConsole.Detached = true;\r
941             else\r
942                 mediaConsole.Focus();\r
943         }\r
944 \r
945         private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)\r
946         {\r
947             ProcessLink("http://jira.openmetaverse.org/browse/RAD");\r
948         }\r
949 \r
950         private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)\r
951         {\r
952             (new frmAbout(instance)).ShowDialog();\r
953         }\r
954 \r
955         #endregion\r
956     }\r
957 }