Logo Search packages:      
Sourcecode: galaxium version File versions  Download package

GtkActivityUtility.cs

/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2008 Philippe Durand <draekz@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;

using Gtk;

using Mono.Addins;

using Galaxium.Client;
using Galaxium.Core;
using Galaxium.Gui.GtkGui;
using Galaxium.Protocol;

using Anculus.Core;
using Anculus.Gui;

namespace Galaxium.Client.GtkGui
{
      public static class GtkActivityUtility
      {
            public static event EventHandler ActivityQueued;
            
            const string _preProcessorPath = "/Galaxium/Activities/PreProcessors";
            const string _processorPath    = "/Galaxium/Activities/Processors";
            
            static Dictionary<IContact, Queue<IActivity>> _queues;
            static IConfigurationSection _config = Configuration.Conversation.Section;
            
            /// <value>
            /// True if any activities are currently queued
            /// </value>
            public static bool Pending
            {
                  get
                  {
                        lock (_queues)
                              return _queues.Count > 0;
                  }
            }
            
            static List<KeyValuePair<Type, MethodInfo>> _preProcessors;
            static List<KeyValuePair<Type, MethodInfo>> _processors;
            
            /// <summary>
            /// Initialize GtkActivityUtility. Must be called before use
            /// </summary>
            public static void Initialize ()
            {
                  Log.Debug ("Initializing gtk activity utility...");
                  
                  _preProcessors = new List<KeyValuePair<Type, MethodInfo>> ();
                  _processors = new List<KeyValuePair<Type, MethodInfo>> ();
                  
                  _queues = new Dictionary<IContact, Queue<IActivity>> ();
                  
                  LoadProcessors (ref _preProcessors, _preProcessorPath);
                  LoadProcessors (ref _processors, _processorPath);
                  
                  AddinManager.ExtensionChanged += OnExtensionChanged;
            }
            
            /// <summary>
            /// Load all processors at the given extension point into the given list
            /// </summary>
            /// <param name="list">
            /// A <see cref="List`1"/> which will contain the processors
            /// </param>
            /// <param name="extensionPoint">
            /// A <see cref="System.String"/> containing the extension point to load from
            /// </param>
            static void LoadProcessors (ref List<KeyValuePair<Type, MethodInfo>> list, string extensionPoint)
            {
                  list.Clear ();
                  
                  //Log.Debug ("Loading processors from {0}", extensionPoint);
                  
                  foreach (ActivityProcessorExtension node in AddinUtility.GetExtensionNodes (extensionPoint))
                        list.Add (new KeyValuePair<Type, MethodInfo> (node.ActivityType, node.CallMethod));
            }
            
            static void OnExtensionChanged (object o, ExtensionEventArgs args)
            {
                  if (args.PathChanged (_preProcessorPath))
                        LoadProcessors (ref _preProcessors, _preProcessorPath);
                  
                  if (args.PathChanged (_processorPath))
                        LoadProcessors (ref _processors, _processorPath);
            }
            
            /// <summary>
            /// Called by the main ActivityUtility when an activity is emitted
            /// </summary>
            /// <param name="sender">
            /// The <see cref="System.Object"/> which generated the activity
            /// </param>
            /// <param name="activity">
            /// The emmitted <see cref="IActivity"/>
            /// </param>
            public static void OnActivity (object sender, IActivity activity)
            {
                  Process (activity, _preProcessors);
                  
                  if (activity.Handled)
                  {
                        Log.Debug ("Activity {0} handled by a preprocessor, dropping it", activity);
                        return;
                  }
                  
                  if (activity.CanQueue && (activity.Entity != null))
                  {
                        IConversation conv = activity.Session.Conversations.GetConversation (activity.Entity as IContact);
                        
                        if (conv != null && WindowUtility<Widget>.GetWindow (conv) != null)
                        {
                              Process (activity, _processors);
                        }
                        else
                        {
                              if (_config.GetBool (Configuration.Conversation.QueueAlways.Name, Configuration.Conversation.QueueAlways.Default))
                                    QueueActivity (activity);
                              else if (_config.GetBool (Configuration.Conversation.QueueWhenAway.Name, Configuration.Conversation.QueueWhenAway.Default) && activity.Session.Account.Presence.BasePresence == BasePresence.Away)
                                    QueueActivity (activity);
                              else
                                    Process (activity, _processors);
                        }
                  }
                  else
                        Process (activity, _processors);
            }
            
            /// <summary>
            /// Get the first activity from the first queue without removing or processing it
            /// </summary>
            /// <returns>
            /// The first <see cref="IActivity"/> from the first queue
            /// </returns>
            public static IActivity PeekQueueItem ()
            {
                  lock (_queues)
                  {
                        foreach (IContact contact in _queues.Keys)
                              return _queues[contact].Peek ();
                  }
                  
                  return null;
            }
            
            /// <summary>
            /// Enqueue an activity for later processing
            /// </summary>
            /// <param name="activity">
            /// The <see cref="IActivity"/> to enqueue
            /// </param>
            static void QueueActivity (IActivity activity)
            {
                  ThrowUtility.ThrowIfFalse ("entity not an IContact", activity.Entity is IContact);
                  
                  lock (_queues)
                  {
                        if (!_queues.ContainsKey (activity.Entity as IContact))
                              _queues.Add (activity.Entity as IContact, new Queue<IActivity> ());
                        
                        _queues[activity.Entity as IContact].Enqueue (activity);
                  }
                  
                  if (ActivityQueued != null)
                        ActivityQueued (activity, new EventArgs ());
            }
            
            /// <summary>
            /// Process one queue (all queued activities for one contact)
            /// </summary>
            public static void ProcessQueue ()
            {
                  lock (_queues)
                  {
                        if (_queues.Count == 0)
                              return;
                        
                        foreach (IContact contact in _queues.Keys)
                        {
                              Queue<IActivity> queue = _queues[contact];
                              
                              while (queue.Count > 0)
                                    Process (queue.Dequeue (), _processors);
                              
                              _queues.Remove (contact);
                              
                              // We only want to process one queue here
                              break;
                        }
                  }
            }
            
            /// <summary>
            /// Invoke the appropriate processors from a given set, for the activity provided
            /// </summary>
            /// <param name="activity">
            /// The <see cref="IActivity"/> to process
            /// </param>
            /// <param name="processors">
            /// A set of processors to invoke if they accept the given activity's type
            /// </param>
            static void Process (IActivity activity, IEnumerable<KeyValuePair<Type, MethodInfo>> processors)
            {
                  ThrowUtility.ThrowIfNull ("activity", activity);
                  ThrowUtility.ThrowIfNull ("processors", processors);
                  
                  foreach (KeyValuePair<Type, MethodInfo> processor in processors)
                  {
                        // Execute the processor method if it handles the activities type, an
                        // ancestor of the activities type or an interface implemented by the
                        // activities type
                        
                        if ((processor.Key == activity.GetType ()) || activity.GetType ().IsSubclassOf (processor.Key) ||
                            (processor.Key.IsInterface && (activity.GetType ().GetInterface (processor.Key.Name) != null)))
                        {
                              if (processor.Value != null)
                                    processor.Value.Invoke (null, new object[] { null, activity });
                              else
                                    Log.Error ("Method information not found! Are you sure the addin specifies the proper method?");
                        }
                  }
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index