OSDN Git Service

9838e6de06f76b3a41ba99cf02b0fcc21ac5de68
[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     }
131
132     /// <summary>
133     /// Fired when blue dialog notification is displayed
134     /// </summary>
135     public class NotificationEventArgs : EventArgs, IDisposable
136     {
137         public event Notification.NotificationCallback OnNotificationClosed;
138
139         public event Notification.NotificationClickedCallback OnNotificationClicked;
140
141         /// <summary>
142         /// The Notfication form itself
143         /// </summary>
144         public Notification Notice;
145
146         /// <summary>
147         /// Type of notfication
148         /// </summary>
149         public NotificationType Type;
150
151         /// <summary>
152         /// Instance of Radegast where the event occured
153         /// </summary>
154         public RadegastInstance Instance;
155
156         /// <summary>
157         /// Notification text
158         /// </summary>
159         public string Text = string.Empty;
160
161         /// <summary>
162         /// Buttons displayed on the notification window
163         /// </summary>
164         public List<Button> Buttons = new List<Button>();
165
166         /// <summary>
167         /// When set true the Dialog Can send the Close Event
168         /// </summary>
169         public bool CanClose = false;
170
171         /// <summary>
172         /// The button has been pushed once
173         /// </summary>        
174         public bool ButtonSelected = false;
175
176         /// <summary>
177         /// Create new event args object
178         /// </summary>
179         /// <param name="instance">Instance of Radegast notification is coming from</param>
180         public NotificationEventArgs(RadegastInstance instance)
181         {
182             Instance = instance;
183         }
184
185         private void Notification_Closing(object sender, EventArgs e)
186         {
187             Notification_Close();
188         }
189
190         /// <summary>
191         /// Triggers the OnNotificationClosing event.
192         /// </summary>
193         internal void Notification_Close()
194         {
195             if (ButtonSelected)
196             {
197                 try
198                 {
199                     if (OnNotificationClosed != null)
200                         OnNotificationClosed(this, this);
201                 }
202                 catch (Exception ex)
203                 {
204                     OpenMetaverse.Logger.Log("Error executing OnNotificationClosed " + Text,
205                                              OpenMetaverse.Helpers.LogLevel.Warning, ex);
206                 }
207                 if (!CanClose) Dispose();
208             }
209             CanClose = true;
210         }
211
212         /// <summary>
213         /// Triggers the OnNotificationClicked event.
214         /// </summary>
215         internal void Notification_Click(object sender, EventArgs e)
216         {
217             if (ButtonSelected) throw new InvalidOperationException("Clicked twice " + Text + " item: " + sender);
218             ButtonSelected = true;
219             try
220             {
221                 if (OnNotificationClicked != null)
222                     OnNotificationClicked(sender, e, this);
223             }
224             catch (Exception ex)
225             {
226                 OpenMetaverse.Logger.Log("Error executing OnNotificationClicked", OpenMetaverse.Helpers.LogLevel.Warning, ex);
227             }
228             if (CanClose)
229             {
230                 Notification_Close();
231             }
232         }
233
234         public void HookNotification(Notification notification)
235         {
236             Notice = notification;
237             int hooked = 0;
238             lock (notification)
239             {
240                 notification.HandleDestroyed += Notification_Closing;
241                 lock (Buttons)
242                     foreach (var button in Buttons)
243                     {
244                         button.Click += Notification_Click;
245                         hooked++;
246                     }
247             }
248             if (hooked == 0)
249                 throw new InvalidOperationException("No buttons found on Dialog " + Text);
250
251         }
252
253         public void Dispose()
254         {
255             if (!CanClose)
256             {
257                 CanClose = true;
258                 ButtonSelected = true;
259                 Notification_Close();
260             }
261             lock (Notice)
262             {
263                 Notice.HandleDestroyed -= Notification_Closing;
264                 lock (Buttons)
265                     foreach (var button in Buttons)
266                         button.Click -= Notification_Click;
267             }
268         }
269     }
270 }