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

MessageEntryWidget.cs

/*
 * Galaxium Messenger
 * Copyright (C) 2007 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.Text.RegularExpressions;
using System.Collections.Generic;
using System.IO;

using Gdk;
using Gtk;
using G=Gtk;
using Pango;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Protocol;

namespace Galaxium.Gui.GtkGui
{
      public class MessageEntryWidget: G.TextView
      {
            public event EventHandler<DragReceivedEventArgs> DragReceived;
            
            bool _showURLs = true;
            bool _showEmoticons = true;
            IConversation _conversation = null;
            
            OrderedDictionary<string, IEmoticon> _emoticons = new OrderedDictionary<string, IEmoticon> ();
            
            Dictionary<G.Image, string> _imageEquivalents = new Dictionary<G.Image, string> ();
            
            bool _bold;
            bool _italic;
            bool _underline;
            bool _strikethrough;
            
            TextTag _tagBase = new TextTag ("base");
            TextTag _tagBold = new TextTag ("bold");
            TextTag _tagItalic = new TextTag ("italic");
            TextTag _tagUnderline = new TextTag ("underline");
            TextTag _tagStrikethrough = new TextTag ("strikethrough");
            TextTag _tagUri = new G.TextTag ("uri");
            
            public string Family
            {
                  get { return _tagBase.Family; }
                  set
                  {
                        _tagBase.Family = value;
                        ApplyTags ();
                  }
            }
            
            public double Size
            {
                  get { return _tagBase.SizePoints; }
                  set
                  {
                        if ((value < 1) || (value > 36))
                              return;
                        
                        _tagBase.SizePoints = value;
                        ApplyTags ();
                  }
            }
            
            public bool Bold
            {
                  get { return _bold; }
                  set
                  {
                        _bold = value;
                        ApplyTags ();
                  }
            }
            
            public bool Italic
            {
                  get { return _italic; }
                  set
                  {
                        _italic = value;
                        ApplyTags ();
                  }
            }
            
            public bool Underline
            {
                  get { return _underline; }
                  set
                  {
                        _underline = value;
                        ApplyTags ();
                  }
            }
            
            public bool Strikethrough
            {
                  get { return _strikethrough; }
                  set
                  {
                        _strikethrough = value;
                        ApplyTags ();
                  }
            }
            
            public bool ShowURLs
            {
                  get { return _showURLs; }
                  set
                  {
                        _showURLs = value;
                  }
            }
            
            public bool ShowEmoticons
            {
                  get { return _showEmoticons; }
                  set
                  {
                        _showEmoticons = value;
                        RebuildEmoticonList ();
                  }
            }
            
            public IConversation Conversation
            {
                  get { return _conversation; }
                  set
                  {
                        _conversation = value;
                        RebuildEmoticonList ();
                  }
            }
            
            public string Text
            {
                  get
                  {
                        string text = string.Empty;
                        TextIter iter = Buffer.StartIter;
                        
                        do
                        {
                              if (iter.ChildAnchor != null)
                              {
                                    text += _imageEquivalents[(G.Image)iter.ChildAnchor.Widgets[0]];
                                    continue;
                              }
                              
                              text += iter.Char;
                        }
                        while (iter.ForwardChar());
                        
                        return text;
                  }
            }
            
            public Gdk.Color Color
            {
                  get { return _tagBase.ForegroundGdk; }
                  set
                  {
                        _tagBase.ForegroundGdk = value;
                        ApplyTags ();
                  }
            }
            
            public int ColorInt
            {
                  get
                  {
                        byte r = (byte)(Color.Red >> 8);
                        byte g = (byte)(Color.Green >> 8);
                        byte b = (byte)(Color.Blue >> 8);
                        
                        return (r << 16) + (g << 8) + b;
                  }
                  set
                  {
                        byte r = (byte)((value & 0xFF0000) >> 16);
                        byte g = (byte)((value & 0xFF00) >> 8);
                        byte b = (byte)(value & 0xFF);
                        
                        Color = new Gdk.Color (r, g, b);
                  }
            }
            
            public MessageEntryWidget (IConversation conversation)
            {
                  // Targets
                  TargetEntry entryTarget = new TargetEntry ();
                  entryTarget.Flags = TargetFlags.Widget;
                  entryTarget.Target = "text/uri-list";
                  
                  G.Drag.DestSetTargetList (this, new TargetList (new TargetEntry[] {entryTarget}));
                  
                  AcceptsTab = true;
                  BorderWidth = 0;
                  CursorVisible = true;
                  Editable = true;
                  WrapMode = G.WrapMode.Word;
                  
                  Buffer.TagTable.Add (_tagBase);
                  
                  _tagBold.Weight = Weight.Bold;
                  Buffer.TagTable.Add (_tagBold);

                  _tagItalic.Style = Pango.Style.Italic;
                  Buffer.TagTable.Add (_tagItalic);
                  
                  _tagUnderline.Underline = Pango.Underline.Single;
                  Buffer.TagTable.Add (_tagUnderline);
                  
                  _tagStrikethrough.Strikethrough = true;
                  Buffer.TagTable.Add (_tagStrikethrough);
                  
                  //TODO: can this be gotten from the gtk theme?
                  _tagUri.ForegroundGdk = new Gdk.Color (0, 0, 255);
                  _tagUri.Underline = Pango.Underline.Single;
                  Buffer.TagTable.Add (_tagUri);
                  
                  ResetFont ();
                  
                  Conversation = conversation;
            }
            
            public void Clear ()
            {
                  Buffer.Clear ();
                  _imageEquivalents.Clear ();
            }
            
            protected override void OnDragDataReceived (Gdk.DragContext context, int x, int y, SelectionData selection, uint info, uint time)
            {
                  if (selection != null && selection.Text != null)
                  {
                        string uristring = selection.Text;
                        List<string> uris = new List<string> ();
                        
                        while (uristring.IndexOf("\r\n") >= 0)
                        {
                              uris.Add(uristring.Substring(0, uristring.IndexOf("\r\n")));
                              uristring = uristring.Substring (uristring.IndexOf("\r\n")+2);
                        }
                        
                        if (DragReceived != null)
                              DragReceived (this, new DragReceivedEventArgs (uris.ToArray()));
                        
                        G.Drag.Finish(context, true, false, time);
                  }
            }
            
            TextIter GetCurrentWordStartIter ()
            {
                  TextIter iter = Buffer.GetIterAtOffset (Buffer.CursorPosition);
                  
                  while (!iter.IsStart)
                  {
                        iter.BackwardChar ();
                        
                        if ((!string.IsNullOrEmpty (iter.Char)) && char.IsWhiteSpace (iter.Char, 0))
                              break;
                  }
                  if (!iter.IsStart)
                        iter.ForwardChar ();
                  
                  return iter;
            }
            
            TextIter GetCurrentWordEndIter ()
            {
                  TextIter iter = Buffer.GetIterAtOffset (Buffer.CursorPosition);
                  while (!iter.IsEnd)
                  {
                        if ((!string.IsNullOrEmpty (iter.Char)) && char.IsWhiteSpace (iter.Char, 0))
                              break;
                        
                        iter.ForwardChar ();
                  }
                  
                  return iter;
            }
            
            bool IsUrl (string str)
            {
                  foreach (string urlStart in MessageUtility.UriStarts)
                        if (str.StartsWith (urlStart, StringComparison.InvariantCultureIgnoreCase))
                              return true;
                  
                  return false;
            }
            
            [GLib.ConnectBefore]
            protected override bool OnKeyPressEvent (EventKey evnt)
            {
                  bool ret = base.OnKeyPressEvent (evnt);
                  
                  TextIter iterWordStart = GetCurrentWordStartIter ();
                  TextIter iterWordEnd = GetCurrentWordEndIter ();
                  
                  string word = iterWordStart.GetText (iterWordEnd);
                  
                  if (!string.IsNullOrEmpty (word))
                  {
                        //Log.Debug ("Current word = '{0}'", word);
                        
                        if (_emoticons.ContainsKey (word))
                        {
                              // This is an emoticon, try to load the image
                              G.Image img = TextMessageDisplay.LoadEmoticon (_emoticons[word]);
                              
                              if (img != null)
                              {
                                    // Delete the emoticons text
                                    Buffer.Delete (ref iterWordStart, ref iterWordEnd);
                                    
                                    // Add the emoticons image
                                    TextChildAnchor anchor = Buffer.CreateChildAnchor (ref iterWordEnd);
                                    AddChildAtAnchor (img, anchor);
                                    _imageEquivalents.Add (img, word);
                              }
                        }
                        else if (IsUrl (word))
                              Buffer.ApplyTag (_tagUri, iterWordStart, iterWordEnd);
                        else
                              Buffer.RemoveTag (_tagUri, iterWordStart, iterWordEnd);
                  }
                  
                  ApplyTags ();
                  
                  return ret;
            }
            
            public void InsertEmoticon (IEmoticon emoticon, int index)
            {
                  string txt = Buffer.GetSlice(Buffer.StartIter, Buffer.EndIter, true);
                  
                  G.Image img = TextMessageDisplay.LoadEmoticon (emoticon);
                  
                  if (img == null)
                        return;
                  
                  TextIter iter = Buffer.GetIterAtOffset(index);
                  
                  G.TextChildAnchor anchor = Buffer.CreateChildAnchor (ref iter);
                  
                  AddChildAtAnchor (img, anchor);
                  
                  _imageEquivalents.Add (img, emoticon.Equivalents[0]);
            }
            
            void RebuildEmoticonList ()
            {
                  _emoticons = null;
                  
                  if ((!_showEmoticons) || (_conversation == null))
                        return;
                  
                  _emoticons = EmoticonUtility.GetEmoticonDict (_conversation.Session.Account, null, null, true);
            }
            
            void ApplyTags ()
            {
                  Buffer.RemoveTag (_tagBase, Buffer.StartIter, Buffer.EndIter);
                  Buffer.RemoveTag (_tagBold, Buffer.StartIter, Buffer.EndIter);
                  Buffer.RemoveTag (_tagItalic, Buffer.StartIter, Buffer.EndIter);
                  Buffer.RemoveTag (_tagStrikethrough, Buffer.StartIter, Buffer.EndIter);
                  Buffer.RemoveTag (_tagUnderline, Buffer.StartIter, Buffer.EndIter);
                  
                  Buffer.ApplyTag (_tagBase, Buffer.StartIter, Buffer.EndIter);
                  
                  if (_bold)
                        Buffer.ApplyTag (_tagBold, Buffer.StartIter, Buffer.EndIter);
                  if (_italic)
                        Buffer.ApplyTag (_tagItalic, Buffer.StartIter, Buffer.EndIter);
                  if (_underline)
                        Buffer.ApplyTag (_tagUnderline, Buffer.StartIter, Buffer.EndIter);
                  if (_strikethrough)
                        Buffer.ApplyTag (_tagStrikethrough, Buffer.StartIter, Buffer.EndIter);
            }
            
            public void ResetFont ()
            {
                  Bold = false;
                  Italic = false;
                  Underline = false;
                  Strikethrough = false;
                  Family = string.Empty;
                  Size = 10;
                  ColorInt = 0;
                  
                  ApplyTags ();
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index