OSDN Git Service

a6dd17f5ee399b7caa1676df3964c86aba61ac3d
[radegast/radegast.git] / Radegast / GUI / Notifications / Notification.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, Radegast Development Team
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 
9 //     * Redistributions of source code must retain the above copyright notice,
10 //       this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //     * Neither the name of the application "Radegast", nor the names of its
15 //       contributors may be used to endorse or promote products derived from
16 //       this software without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // $Id: FriendshipOfferNotification.cs 118 2009-07-20 00:39:00Z latifer $
30 //
31 using System;
32 using System.Collections.Generic;
33 #if (COGBOT_LIBOMV || USE_STHREADS)
34 using ThreadPoolUtil;
35 using Thread = ThreadPoolUtil.Thread;
36 using ThreadPool = ThreadPoolUtil.ThreadPool;
37 using Monitor = ThreadPoolUtil.Monitor;
38 #endif
39 using OpenMetaverse;
40
41 using System.Windows.Forms;
42
43 namespace Radegast
44 {
45
46     /// <summary>
47     /// Base class for all notificatiosn (blue dialogs)
48     /// </summary>
49     public class Notification : UserControl
50     {
51         /// <summary>
52         /// Notification type
53         /// </summary>
54         public NotificationType Type;
55
56         /// <summary>
57         /// Callback when blue dialog notification is displayed or closed
58         /// </summary>
59         /// <param name="sender">Notification dialog</param>
60         /// <param name="e">Notification parameters</param>
61         public delegate void NotificationCallback(object sender, NotificationEventArgs e);
62
63         /// <summary>
64         /// Callback when blue dialog notification button is clicked
65         /// </summary>
66         /// <param name="sender">Notification dialog</param>
67         /// <param name="e">Notification parameters</param>
68         public delegate void NotificationClickedCallback(object sender, EventArgs e, NotificationEventArgs notice);
69
70         /// <summary>
71         /// Fired when a notification is displayed
72         /// </summary>
73         public static event NotificationCallback OnNotificationDisplayed;
74
75         public Notification()
76         {
77             Type = NotificationType.Generic;
78         }
79
80         public Notification(NotificationType type)
81         {
82             Type = type;
83         }
84
85         protected void FireNotificationCallback(NotificationEventArgs e)
86         {
87             if (OnNotificationDisplayed == null) return;
88             try
89             {
90                 e.Type = this.Type;
91                 WorkPool.QueueUserWorkItem((object o) => Notificaton_Displayed(this, e));
92             }
93             catch (Exception ex)
94             {
95                 Console.WriteLine("" + ex);
96                 OpenMetaverse.Logger.Log("Error executing notification callback", OpenMetaverse.Helpers.LogLevel.Warning, ex);
97             }
98         }
99
100         private void Notificaton_Displayed(Notification notification, NotificationEventArgs e)
101         {
102             try
103             {
104                 e.HookNotification(this);
105                 if (OnNotificationDisplayed != null)
106                     OnNotificationDisplayed(notification, e);
107             }
108             catch (Exception ex)
109             {
110                 Console.WriteLine("" + ex);
111                 OpenMetaverse.Logger.Log("Error executing notification displayed", OpenMetaverse.Helpers.LogLevel.Warning, ex);
112             }
113         }
114     }
115     /// <summary>
116     /// What kind of notification this is (blue dialog)
117     /// </summary>
118     public enum NotificationType
119     {
120         Generic,
121         FriendshipOffer,
122         GroupInvitation,
123         GroupNotice,
124         PermissionsRequest,
125         ScriptDialog,
126         Teleport,
127         InventoryOffer,
128         RequestLure,
129         SendLureRequest,
130         SendLureOffer
131     }
132
133     /// <summary>
134     /// Fired when blue dialog notification is displayed
135     /// </summary>
136     public class NotificationEventArgs : EventArgs, IDisposable
137     {
138         public event Notification.NotificationCallback OnNotificationClosed;
139
140         public event Notification.NotificationClickedCallback OnNotificationClicked;
141
142         /// <summary>
143         /// The Notfication form itself
144         /// </summary>
145         public Notification Notice;
146
147         /// <summary>
148         /// Type of notfication
149         /// </summary>
150         public NotificationType Type;
151
152         /// <summary>
153         /// Instance of Radegast where the event occured
154         /// </summary>
155         public RadegastInstance Instance;
156
157         /// <summary>
158         /// Notification text
159         /// </summary>
160         public string Text = string.Empty;
161
162         /// <summary>
163         /// Buttons displayed on the notification window
164         /// </summary>
165         public List<Button> Buttons = new List<Button>();
166
167         /// <summary>
168         /// When set true the Dialog Can send the Close Event
169         /// </summary>
170         public bool CanClose = false;
171
172         /// <summary>
173         /// The button has been pushed once
174         /// </summary>        
175         public bool ButtonSelected = false;
176
177         /// <summary>
178         /// Create new event args object
179         /// </summary>
180         /// <param name="instance">Instance of Radegast notification is coming from</param>
181         public NotificationEventArgs(RadegastInstance instance)
182         {
183             Instance = instance;
184         }
185
186         private void Notification_Closing(object sender, EventArgs e)
187         {
188             Notification_Close();
189         }
190
191         /// <summary>
192         /// Triggers the OnNotificationClosing event.
193         /// </summary>
194         internal void Notification_Close()
195         {
196             if (ButtonSelected)
197             {
198                 try
199                 {
200                     if (OnNotificationClosed != null)
201                         OnNotificationClosed(this, this);
202                 }
203                 catch (Exception ex)
204                 {
205                     OpenMetaverse.Logger.Log("Error executing OnNotificationClosed " + Text,
206                                              OpenMetaverse.Helpers.LogLevel.Warning, ex);
207                 }
208                 if (!CanClose) Dispose();
209             }
210             CanClose = true;
211         }
212
213         /// <summary>
214         /// Triggers the OnNotificationClicked event.
215         /// </summary>
216         internal void Notification_Click(object sender, EventArgs e)
217         {
218             if (ButtonSelected) throw new InvalidOperationException("Clicked twice " + Text + " item: " + sender);
219             ButtonSelected = true;
220             try
221             {
222                 if (OnNotificationClicked != null)
223                     OnNotificationClicked(sender, e, this);
224             }
225             catch (Exception ex)
226             {
227                 OpenMetaverse.Logger.Log("Error executing OnNotificationClicked", OpenMetaverse.Helpers.LogLevel.Warning, ex);
228             }
229             if (CanClose)
230             {
231                 Notification_Close();
232             }
233         }
234
235         public void HookNotification(Notification notification)
236         {
237             Notice = notification;
238             int hooked = 0;
239             lock (notification)
240             {
241                 notification.HandleDestroyed += Notification_Closing;
242                 lock (Buttons)
243                     foreach (var button in Buttons)
244                     {
245                         button.Click += Notification_Click;
246                         hooked++;
247                     }
248             }
249             if (hooked == 0)
250                 throw new InvalidOperationException("No buttons found on Dialog " + Text);
251
252         }
253
254         public void Dispose()
255         {
256             if (!CanClose)
257             {
258                 CanClose = true;
259                 ButtonSelected = true;
260                 Notification_Close();
261             }
262             lock (Notice)
263             {
264                 Notice.HandleDestroyed -= Notification_Closing;
265                 lock (Buttons)
266                     foreach (var button in Buttons)
267                         button.Click -= Notification_Click;
268             }
269         }
270     }
271 }