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

ContactTreeView.cs

/*
 * Galaxium Messenger
 * Copyright (C) 2008 Paul Burton <paulburton89@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 Gdk;
using Gtk;

using Anculus.Core;
using Anculus.Gui;

using Galaxium.Core;
using Galaxium.Protocol;

namespace Galaxium.Gui.GtkGui
{
      public partial class ContactTreeView : GalaxiumTreeView
      {
            ISession _session;
            IContactTreeManager _manager;
            
            Dictionary<IGroup, ContactTreeGroup> _groups = new Dictionary<IGroup, ContactTreeGroup> ();
            ContactTreeGroup _onlineGroup;
            ContactTreeGroup _offlineGroup;
            int _building;
            
            public IContactTreeManager Manager
            {
                  get { return _manager; }
                  set
                  {
                        _manager = value;
                        _manager.Init (this, _session);
                  }
            }
            
            public ContactTreeView (ISession session)
            {
                  _session = session;
                  
                  _session.GroupAdded += SessionGroupAdded;
                  _session.GroupRemoved += SessionGroupRemoved;
                  _session.GroupRenamed += SessionGroupChanged;
                  _session.ContactAdded += SessionContactAdded;
                  _session.ContactRemoved += SessionContactRemoved;
                  _session.ContactChanged += SessionContactChanged;
                  _session.Account.DisplaySettingsChange += AccountDisplaySettingsChange;
                  _session.ContactDisplayImageChanged += ContactDisplayImageChanged;
                  
                  HeadersVisible = false;
                  RulesHint = false;
                  Reorderable = false;
                  
                  InitColumns ();
                  
                  Rebuild ();
            }
            
            protected virtual void InitColumns ()
            {
                  TreeViewColumn col = new TreeViewColumn ();
                  col.Sizing = TreeViewColumnSizing.Autosize;
                  
                  CellRenderer renderer = new CellRendererPixbuf ();
                  col.PackStart (renderer, false);
                  col.SetCellDataFunc (renderer, new TreeCellDataFunc (RenderLeftImage));
                  
                  renderer = new CellRendererContact (_session.Account.Protocol);
                  col.PackStart (renderer, true);
                  col.SetCellDataFunc (renderer, new TreeCellDataFunc (RenderText));
                  
                  renderer = new CellRendererPixbuf ();
                  col.PackStart (renderer, false);
                  col.SetCellDataFunc (renderer, new TreeCellDataFunc (RenderRightImage));
                  
                  AppendColumn (col);
                  
                  col = new TreeViewColumn ();
                  col.PackStart (new ExpanderCellRenderer (), true);
                  col.MaxWidth = 16;
                  InsertColumn (col, 0);
                  ExpanderColumn = col;
            }
            
            public void Rebuild ()
            {
                  bool origSort = Sort;
                  Sort = false;
                  _building++;
                  
                  if (_onlineGroup != null)
                  {
                        _onlineGroup.ContactAdded -= TreeGroupContactAdded;
                        _onlineGroup.ContactRemoved -= TreeGroupContactRemoved;
                        _onlineGroup = null;
                  }
                  
                  if (_offlineGroup != null)
                  {
                        _offlineGroup.ContactAdded -= TreeGroupContactAdded;
                        _offlineGroup.ContactRemoved -= TreeGroupContactRemoved;
                        _offlineGroup = null;
                  }
                  
                  Store.Clear ();
                  _groups.Clear ();
                  
                  bool viewByGroup = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.ViewByGroup.Name, Configuration.ContactList.ViewByGroup.Default) : _session.Account.ViewByGroup;
                  bool showEmptyGroups = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.ShowEmptyGroups.Name, Configuration.ContactList.ShowEmptyGroups.Default) : _session.Account.ShowEmptyGroups;
                  bool showOfflineContacts = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.ShowOfflineContacts.Name, Configuration.ContactList.ShowOfflineContacts.Default) : _session.Account.ShowOfflineContacts;
                  bool groupOfflineContacts = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.GroupOfflineContacts.Name, Configuration.ContactList.GroupOfflineContacts.Default) : _session.Account.GroupOfflineContacts;
                  
                  if (!viewByGroup)
                  {
                        _onlineGroup = new ContactTreeOnlineVirtualGroup ();
                        _onlineGroup.ContactAdded += TreeGroupContactAdded;
                        _onlineGroup.ContactRemoved += TreeGroupContactRemoved;
                        _onlineGroup.ContactChanged += TreeGroupContactChanged;
                        
                        if (showEmptyGroups || (_onlineGroup.Count > 0))
                              _onlineGroup._ref = AddRow (_onlineGroup);
                  }
                  
                  if ((showOfflineContacts && groupOfflineContacts) || (!viewByGroup))
                  {
                        _offlineGroup = new ContactTreeOfflineVirtualGroup ();
                        _offlineGroup.ContactAdded += TreeGroupContactAdded;
                        _offlineGroup.ContactRemoved += TreeGroupContactRemoved;
                        _offlineGroup.ContactChanged += TreeGroupContactChanged;
                        
                        if (showEmptyGroups || (_offlineGroup.Count > 0))
                              _offlineGroup._ref = AddRow (_offlineGroup);
                  }
                  
                  if (viewByGroup)
                  {
                        foreach (IGroup group in _session.GroupCollection)
                              AddGroup (group);
                  }
                  
                  UpdateContacts ();
                  
                  _building--;
                  Sort = origSort;
                  
                  foreach (ContactTreeGroup treeGroup in _groups.Values)
                        AutoExpandGroup (treeGroup);
                  
                  if (_onlineGroup != null)
                        AutoExpandGroup (_onlineGroup);
                  
                  if (_offlineGroup != null)
                        AutoExpandGroup (_offlineGroup);
            }
            
            void UpdateContacts ()
            {
                  UpdateContacts (_session.ContactCollection);
            }
            
            void UpdateContacts (params IContact[] contacts)
            {
                  UpdateContacts ((IEnumerable<IContact>)contacts);
            }
            
            void UpdateContacts (IEnumerable<IContact> contacts)
            {
                  if (_onlineGroup != null)
                        _onlineGroup.UpdateContacts (contacts);
                  
                  if (_offlineGroup != null)
                        _offlineGroup.UpdateContacts (contacts);
                  
                  foreach (ContactTreeGroup treeGroup in _groups.Values)
                        treeGroup.UpdateContacts (contacts);
            }
            
            void SessionGroupAdded (object sender, GroupEventArgs args)
            {
                  AddGroup (args.Group);
            }
            
            void SessionGroupRemoved (object sender, GroupEventArgs args)
            {
                  if (!_groups.ContainsKey (args.Group))
                        return;
                  
                  ContactTreeGroup treeGroup = _groups[args.Group];
                  
                  treeGroup.ContactAdded -= TreeGroupContactAdded;
                  treeGroup.ContactRemoved -= TreeGroupContactRemoved;
                  treeGroup.ContactChanged -= TreeGroupContactChanged;
                  
                  _groups.Remove (args.Group);
                  RemoveRow (treeGroup._ref);
            }
            
            void SessionGroupChanged (object sender, GroupEventArgs args)
            {
                  if (!_groups.ContainsKey (args.Group))
                        return;
                  
                  RowChanged (_groups[args.Group]._ref);
            }
            
            void SessionContactAdded (object sender, ContactListEventArgs args)
            {
                  UpdateContacts (args.Contact);
            }
            
            void SessionContactRemoved (object sender, ContactListEventArgs args)
            {
                  UpdateContacts (args.Contact);
            }
            
            void ContactDisplayImageChanged (object sender, EntityChangeEventArgs<IDisplayImage> args)
            {
                  UpdateContacts (args.Entity as IContact);
            }
            
            void SessionContactChanged (object sender, ContactEventArgs args)
            {
                  UpdateContacts (args.Contact);
            }
            
            void AccountDisplaySettingsChange (object sender, PropertyEventArgs args)
            {
                  switch (args.Property)
                  {
                  case "ViewByGroup":
                  case "ShowEmptyGroups":
                  case "GroupOfflineContacts":
                        Rebuild ();
                        break;
                  case "ShowOfflineContacts":
                        UpdateContacts ();
                        Rebuild ();
                        break;
                  case "SortAlphabetic":
                        Resort ();
                        break;
                  case "SortAscending":
                        if ((sender as IAccount).UseDefaultListView)
                              SortOrder = Configuration.ContactList.Section.GetBool (Configuration.ContactList.SortAscending.Name, Configuration.ContactList.SortAscending.Default) ? SortOrder.Ascending : SortOrder.Descending;
                        else
                              SortOrder = (sender as IAccount).SortAscending ? SortOrder.Ascending : SortOrder.Descending;
                        break;
                  default:
                        AllRowsChanged ();
                        break;
                  }
            }
            
            void TreeGroupContactAdded (object sender, ContactEventArgs args)
            {
                  ContactTreeGroup treeGroup = sender as ContactTreeGroup;
                  
                  if (treeGroup._ref == null)
                  {
                        // The group wasn't being displayed, add it to the tree
                        
                        _building++;
                        treeGroup._ref = AddRow (treeGroup);
                        _building--;
                  }
                  
                  treeGroup.SetContactRef (args.Contact, AddRow (treeGroup._ref, args.Contact));
                  
                  Resort ();
                  Refilter ();
                  AutoExpandGroup (treeGroup);
            }
            
            void TreeGroupContactRemoved (object sender, ContactEventArgs args)
            {
                  ContactTreeGroup treeGroup = sender as ContactTreeGroup;
                  RemoveRow (treeGroup.GetContactRef (args.Contact));
                  
                  bool showEmptyGroups = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.ShowEmptyGroups.Name, Configuration.ContactList.ShowEmptyGroups.Default) : _session.Account.ShowEmptyGroups;
                  
                  // The count property still includes the group currently being removed
                  if ((treeGroup.Count <= 1) && (!showEmptyGroups))
                  {
                        // Remove the group from the tree
                        _building++;
                        RemoveRow (treeGroup._ref);
                        treeGroup._ref = null;
                        _building--;
                  }
            }
            
            void TreeGroupContactChanged (object sender, ContactEventArgs args)
            {
                  ContactTreeGroup treeGroup = sender as ContactTreeGroup;
                  RowChanged (treeGroup.GetContactRef (args.Contact));
            }
            
            void AddGroup (IGroup group)
            {
                  ContactTreeGroup treeGroup = new ContactTreeRealGroup (group);
                  
                  if (treeGroup == null)
                        return;
                  
                  treeGroup.ContactAdded += TreeGroupContactAdded;
                  treeGroup.ContactRemoved += TreeGroupContactRemoved;
                  treeGroup.ContactChanged += TreeGroupContactChanged;
                  
                  _groups.Add (group, treeGroup);
                  
                  bool showEmptyGroups = _session.Account.UseDefaultListView ? Configuration.ContactList.Section.GetBool (Configuration.ContactList.ShowEmptyGroups.Name, Configuration.ContactList.ShowEmptyGroups.Default) : _session.Account.ShowEmptyGroups;
                  
                  if (showEmptyGroups || (treeGroup.Count > 0))
                        treeGroup._ref = AddRow (treeGroup);
                  
                  Resort ();
                  Refilter ();
            }
            
            void AutoExpandGroup (ContactTreeGroup treeGroup)
            {
                  if (treeGroup._ref == null)
                        return;
                  
                  bool expanded = Configuration.Account.Section[_session.Account.Protocol.Name][_session.Account.UniqueIdentifier]["Groups"][treeGroup.Name].GetBool ("Expanded", true);
                  
                  if (expanded)
                        ExpandRow (GetModelPath (treeGroup._ref.Path), true);
                  else
                        CollapseRow (GetModelPath (treeGroup._ref.Path));
            }
            
            void StoreExpanded (ContactTreeGroup treeGroup)
            {
                  bool expanded = GetRowExpanded (GetModelPath (treeGroup._ref.Path));
                  //Log.Debug ("{0} expanded={1} building={2}", treeGroup.Name, expanded, _building);
                  Configuration.Account.Section[_session.Account.Protocol.Name][_session.Account.UniqueIdentifier]["Groups"][treeGroup.Name].SetBool ("Expanded", expanded);
            }
            
            protected override void OnRowExpanded (TreeIter iter, TreePath path)
            {
                  base.OnRowExpanded (iter, path);
                  
                  if (_building > 0)
                        return;
                  
                  ContactTreeGroup treeGroup = GetModelData (path) as ContactTreeGroup;
                  
                  if (treeGroup != null)
                        StoreExpanded (treeGroup);
            }
            
            protected override void OnRowCollapsed (TreeIter iter, TreePath path)
            {
                  base.OnRowCollapsed (iter, path);
                  
                  if (_building > 0)
                        return;
                  
                  ContactTreeGroup treeGroup = GetModelData (path) as ContactTreeGroup;
                  
                  if (treeGroup != null)
                        StoreExpanded (treeGroup);
            }
            
            public override void Refilter ()
            {
                  base.Refilter ();
                  
                  // Re-expand the appropriate groups
                  
                  if (_onlineGroup != null)
                        AutoExpandGroup (_onlineGroup);
                  
                  if (_offlineGroup != null)
                        AutoExpandGroup (_offlineGroup);
                  
                  foreach (ContactTreeGroup treeGroup in _groups.Values)
                        AutoExpandGroup (treeGroup);
            }
            
#region Rendering
            void RenderText (TreeViewColumn col, CellRenderer cell, TreeModel model, TreeIter iter)
            {
                  _manager.RenderText (GetModelData (iter), cell as CellRendererContact);
            }
            
            void RenderLeftImage (TreeViewColumn col, CellRenderer cell, TreeModel model, TreeIter iter)
            {
                  _manager.RenderLeftImage (GetModelData (iter), cell as CellRendererPixbuf);
            }
            
            void RenderRightImage (TreeViewColumn col, CellRenderer cell, TreeModel model, TreeIter iter)
            {
                  _manager.RenderRightImage (GetModelData (iter), cell as CellRendererPixbuf);
            }
#endregion
            
#region Sorting
            protected override int Compare (object obj1, object obj2)
            {
                  if (_manager == null)
                        return 0;
                  
                  return _manager.Compare (obj1, obj2);
            }
#endregion
            
#region Filtering
            protected override bool FilterShouldDisplay (object data)
            {
                  if (_manager == null)
                        return true;
                  
                  return _manager.Visible (data, Filter, FilterCaseSensitive);
            }
#endregion
            
#region Interaction
            protected override InfoTooltip CreateTooltip (TreePath treePath, object data)
            {
                  return _manager.GetTooltip (data);
            }
            
            protected override Menu CreateContextMenu (TreePath treePath, object data)
            {
                  string menuPath = _manager.GetMenuExtensionPoint (data);
                  
                  if (string.IsNullOrEmpty (menuPath))
                        return null;
                  
                  if (data is ContactTreeRealGroup)
                        data = (data as ContactTreeRealGroup).Group;
                  
                  ContactTreeContext context = new ContactTreeContext (this, treePath, data);
                  return MenuUtility.CreateContextMenu (menuPath, new DefaultExtensionContext (context));
            }
#endregion
            
            public IGroup GetContactGroup (TreePath contactPath)
            {
                  TreePath groupPath = contactPath.Copy ();
                  
                  if (!groupPath.Up ())
                        return null;
                  
                  ContactTreeRealGroup treeGroup = GetModelData (groupPath) as ContactTreeRealGroup;
                  
                  if (treeGroup != null)
                        return treeGroup.Group;
                  
                  return null;
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index