void InitTagTable() { table = new Gtk.TextTagTable(); table.Add(new Gtk.TextTag("bold") { Weight = Pango.Weight.Bold }); table.Add(new Gtk.TextTag("italic") { Style = Pango.Style.Italic }); table.Add(new Gtk.TextTag("tt") { Family = "Monospace" }); table.Add(new Gtk.TextTag("li") { LeftMargin = 14 }); table.Add(new Gtk.TextTag("h1") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.XXLarge }); table.Add(new Gtk.TextTag("h2") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.XLarge }); table.Add(new Gtk.TextTag("h3") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.Large }); table.Add(new Gtk.TextTag("h4") { Scale = Pango.Scale.Large }); table.Add(new Gtk.TextTag("pre") { Family = "Monospace", Indent = 14, WrapMode = Gtk.WrapMode.None }); table.Add(new Gtk.TextTag("p") { SizePoints = Math.Max(LineSpacing, ParagraphSpacing), }); }
void AddEmoji(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, ImageMessagePartModel imgPart, string shortName, Gtk.TextMark emojiMark, string imagePath) { int width, height; int descent; using (var layout = CreatePangoLayout(null)) { layout.GetPixelSize(out width, out height); descent = layout.Context.GetMetrics(layout.FontDescription, null).Descent; } Gdk.Pixbuf emojiPixBuf; try { emojiPixBuf = new Gdk.Pixbuf(imagePath, -1, height); } catch (Exception ex) { #if LOG4NET _Logger.ErrorFormat( "AddEmoji(): error loading " + "image file: '{0}' " + "emoji: '{1}' into Gdk.Pixbuf(), " + "Exception: {2}", imagePath, shortName, ex ); #endif // delete the broken image file, maybe after the // next download this will be a valid image File.Delete(imagePath); // show alternative text as fallback instead buffer.DeleteMark(emojiMark); AddAlternativeText(buffer, ref iter, imgPart); return; } buffer.InsertPixbuf(ref iter, emojiPixBuf); var beforeIter = buffer.GetIterAtMark(emojiMark); var emojiTag = new EmojiTag(emojiMark, imagePath) { Rise = -descent }; _MessageTextTagTable.Add(emojiTag); buffer.ApplyTag(emojiTag, beforeIter, iter); }
static API_Contract() { // Tags boldTag = new Gtk.TextTag("bold") { Weight = Pango.Weight.Bold }; italicTag = new Gtk.TextTag("italic") { Style = Pango.Style.Italic }; // GC seems to kill @tagTable, is it's not static TagTable.Add(API_Contract.boldTag); TagTable.Add(API_Contract.italicTag); // Colors invalidColor.Red = invalidColor.Alpha = 1; invalidColor.Blue = invalidColor.Green = 0; validColor.Blue = validColor.Green = validColor.Red = validColor.Alpha = 1; }
/* * Helper methods */ private Gtk.TextTagTable BuildTagTable() { // TextTags Gtk.TextTagTable ttt = new Gtk.TextTagTable(); Gtk.TextTag tt; Pango.FontDescription fd; tt = new Gtk.TextTag("bold"); fd = new Pango.FontDescription(); fd.Weight = Pango.Weight.Bold; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("italic"); fd = new Pango.FontDescription(); fd.Style = Pango.Style.Italic; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("underline"); tt.Underline = Pango.Underline.Single; ttt.Add(tt); tt = new Gtk.TextTag("link"); tt.Underline = Pango.Underline.Single; tt.Foreground = "darkblue"; fd = new Pango.FontDescription(); tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("event"); tt.Foreground = "darkgray"; ttt.Add(tt); return(ttt); }
/* * Helper methods */ private Gtk.TextTagTable BuildTagTable() { // TextTags Gtk.TextTagTable ttt = new Gtk.TextTagTable(); Gtk.TextTag tt; Pango.FontDescription fd; // WARNING: the insertion order of tags MATTERS! // The attributes of the text tags are applied in the order of // insertion to the text table, and not in which order the tags // applied in the buffer. This is sick IMHO. tt = new Gtk.TextTag("bold"); fd = new Pango.FontDescription(); fd.Weight = Pango.Weight.Bold; tt.FontDesc = fd; BoldTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("italic"); fd = new Pango.FontDescription(); fd.Style = Pango.Style.Italic; tt.FontDesc = fd; ItalicTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("underline"); tt.Underline = Pango.Underline.Single; UnderlineTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("event"); tt.Foreground = "darkgray"; EventTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("link"); tt.Underline = Pango.Underline.Single; tt.Foreground = "darkblue"; LinkTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("person"); PersonTag = tt; ttt.Add(tt); return(ttt); }
void InitTagTable () { table = new Gtk.TextTagTable (); table.Add (new Gtk.TextTag ("bold") { Weight = Pango.Weight.Bold }); table.Add (new Gtk.TextTag ("italic") { Style = Pango.Style.Italic }); table.Add (new Gtk.TextTag ("tt") { Family = "Monospace" }); table.Add (new Gtk.TextTag ("li") { LeftMargin = 14 }); table.Add (new Gtk.TextTag ("h1") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.XXLarge }); table.Add (new Gtk.TextTag ("h2") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.XLarge }); table.Add (new Gtk.TextTag ("h3") { Weight = Pango.Weight.Bold, Scale = Pango.Scale.Large }); table.Add (new Gtk.TextTag ("h4") { Scale = Pango.Scale.Large }); table.Add (new Gtk.TextTag ("pre") { Family = "Monospace", Indent = 14, WrapMode = Gtk.WrapMode.None }); }
/* * Helper methods */ private Gtk.TextTagTable BuildTagTable() { // TextTags Gtk.TextTagTable ttt = new Gtk.TextTagTable(); Gtk.TextTag tt; Pango.FontDescription fd; // WARNING: the insertion order of tags MATTERS! // The attributes of the text tags are applied in the order of // insertion to the text table, and not in which order the tags // applied in the buffer. This is sick IMHO. tt = new Gtk.TextTag("bold"); fd = new Pango.FontDescription(); fd.Weight = Pango.Weight.Bold; tt.FontDesc = fd; BoldTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("italic"); fd = new Pango.FontDescription(); fd.Style = Pango.Style.Italic; tt.FontDesc = fd; ItalicTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("underline"); tt.Underline = Pango.Underline.Single; UnderlineTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("event"); tt.Foreground = "darkgray"; EventTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("link"); tt.Underline = Pango.Underline.Single; tt.Foreground = "darkblue"; LinkTag = tt; ttt.Add(tt); tt = new Gtk.TextTag("person"); PersonTag = tt; ttt.Add(tt); return ttt; }
public void AddMessage(MessageModel msg, bool addLinebreak) { Trace.Call(msg, addLinebreak); if (msg == null) { throw new ArgumentNullException("msg"); } var buffer = Buffer; var iter = buffer.EndIter; Gdk.Color bgColor = DefaultAttributes.Appearance.BgColor; if (_ThemeSettings.BackgroundColor != null) { bgColor = _ThemeSettings.BackgroundColor.Value; } TextColor bgTextColor = ColorConverter.GetTextColor(bgColor); if (_ShowTimestamps) { var msgTimeStamp = msg.TimeStamp.ToLocalTime(); if (_LastMessage != null) { var lastMsgTimeStamp = _LastMessage.TimeStamp.ToLocalTime(); var span = msgTimeStamp.Date - lastMsgTimeStamp.Date; string dayLine = null; if (span.Days > 1) { dayLine = String.Format( "-!- " + _("Day changed from {0} to {1}"), lastMsgTimeStamp.ToShortDateString(), msgTimeStamp.ToShortDateString() ); } else if (span.Days > 0) { dayLine = String.Format( "-!- " + _("Day changed to {0}"), msgTimeStamp.ToLongDateString() ); } if (dayLine != null) { buffer.Insert(ref iter, dayLine + "\n"); } } string timestamp = null; try { string format = (string)Frontend.UserConfig["Interface/Notebook/TimestampFormat"]; if (!String.IsNullOrEmpty(format)) { timestamp = msgTimeStamp.ToString(format); } } catch (FormatException e) { timestamp = "Timestamp Format ERROR: " + e.Message; } if (timestamp != null) { timestamp = String.Format("{0} ", timestamp); if (msg.MessageType == MessageType.Event) { // get best contrast for the event font color Gtk.TextTag eventTag = _MessageTextTagTable.Lookup("event"); Gdk.Color eventColor = eventTag.ForegroundGdk; TextColor eventTextColor = TextColorTools.GetBestTextColor( ColorConverter.GetTextColor(eventColor), bgTextColor, TextColorContrast.High ); eventTag.ForegroundGdk = ColorConverter.GetGdkColor( eventTextColor ); buffer.InsertWithTagsByName(ref iter, timestamp, "event"); } else { buffer.Insert(ref iter, timestamp); } } } bool hasHighlight = false; foreach (MessagePartModel msgPart in msg.MessageParts) { // supposed to be used only in a ChatView if (msgPart.IsHighlight) { hasHighlight = true; } // TODO: implement all types if (msgPart is UrlMessagePartModel) { var urlPart = (UrlMessagePartModel)msgPart; // HACK: the engine should set a color for us! var linkStyleTag = _MessageTextTagTable.Lookup("link"); var linkColor = ColorConverter.GetTextColor( linkStyleTag.ForegroundGdk ); linkColor = TextColorTools.GetBestTextColor( linkColor, bgTextColor ); var linkText = urlPart.Text ?? urlPart.Url; var url = urlPart.Url; // HACK: assume http if no protocol/scheme was specified if (urlPart.Protocol == UrlProtocol.None || !Regex.IsMatch(url, @"^[a-zA-Z0-9\-]+:")) { url = String.Format("http://{0}", url); } Uri uri; try { uri = new Uri(url); } catch (UriFormatException ex) { #if LOG4NET _Logger.Error("AddMessage(): Invalid URL: " + url, ex); #endif buffer.Insert(ref iter, linkText); continue; } var linkTag = new LinkTag(uri); linkTag.ForegroundGdk = ColorConverter.GetGdkColor(linkColor); linkTag.TextEvent += OnLinkTagTextEvent; _MessageTextTagTable.Add(linkTag); buffer.InsertWithTags(ref iter, linkText, linkStyleTag, linkTag); } else if (msgPart is TextMessagePartModel) { TextMessagePartModel fmsgti = (TextMessagePartModel)msgPart; List <string> tags = new List <string>(); if (fmsgti.ForegroundColor != TextColor.None) { var bg = bgTextColor; if (fmsgti.BackgroundColor != TextColor.None) { bg = fmsgti.BackgroundColor; } TextColor color = TextColorTools.GetBestTextColor( fmsgti.ForegroundColor, bg ); //Console.WriteLine("GetBestTextColor({0}, {1}): {2}", fmsgti.ForegroundColor, bgTextColor, color); string tagname = GetTextTagName(color, null); //string tagname = _GetTextTagName(fmsgti.ForegroundColor, null); tags.Add(tagname); } if (fmsgti.BackgroundColor != TextColor.None) { // TODO: get this from ChatView string tagname = GetTextTagName(null, fmsgti.BackgroundColor); tags.Add(tagname); } if (fmsgti.Underline) { #if LOG4NET _Logger.Debug("AddMessage(): fmsgti.Underline is true"); #endif tags.Add("underline"); } if (fmsgti.Bold) { #if LOG4NET _Logger.Debug("AddMessage(): fmsgti.Bold is true"); #endif tags.Add("bold"); } if (fmsgti.Italic) { #if LOG4NET _Logger.Debug("AddMessage(): fmsgti.Italic is true"); #endif tags.Add("italic"); } if (msg.MessageType == MessageType.Event && fmsgti.ForegroundColor == TextColor.None) { // only mark parts that don't have a color set tags.Add("event"); } if (tags.Count > 0) { buffer.InsertWithTagsByName(ref iter, fmsgti.Text, tags.ToArray()); } else { buffer.Insert(ref iter, fmsgti.Text); } } } if (addLinebreak) { buffer.Insert(ref iter, "\n"); } CheckBufferSize(); // HACK: force a redraw of the widget, as for some reason // GTK+ 2.17.6 is not redrawing some lines we add here, especially // for local messages. See: // http://projects.qnetp.net/issues/show/185 QueueDraw(); if (MessageAdded != null) { MessageAdded(this, new MessageTextViewMessageAddedEventArgs(msg)); } if (hasHighlight) { if (MessageHighlighted != null) { MessageHighlighted(this, new MessageTextViewMessageHighlightedEventArgs(msg)); } } _LastMessage = msg; }
/* * Helper methods */ private Gtk.TextTagTable BuildTagTable() { // TextTags Gtk.TextTagTable ttt = new Gtk.TextTagTable(); Gtk.TextTag tt; Pango.FontDescription fd; tt = new Gtk.TextTag("bold"); fd = new Pango.FontDescription(); fd.Weight = Pango.Weight.Bold; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("italic"); fd = new Pango.FontDescription(); fd.Style = Pango.Style.Italic; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("underline"); tt.Underline = Pango.Underline.Single; ttt.Add(tt); tt = new Gtk.TextTag("url"); tt.Underline = Pango.Underline.Single; tt.Foreground = "darkblue"; tt.TextEvent += OnTextTagUrlTextEvent; fd = new Pango.FontDescription(); tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("event"); tt.Foreground = "darkgray"; ttt.Add(tt); return ttt; }
public void AddMessage(MessageModel msg, bool addLinebreak, bool showTimestamps) { #if MSG_DEBUG Trace.Call(msg, addLinebreak); #endif if (msg == null) { throw new ArgumentNullException("msg"); } var buffer = Buffer; var iter = buffer.EndIter; var startMark = new Gtk.TextMark(null, true); buffer.AddMark(startMark, iter); var senderPrefixWidth = GetSenderPrefixWidth(msg); Gtk.TextTag indentTag = null; if (senderPrefixWidth != 0) { // TODO: re-use text tags that have the same indent width indentTag = new Gtk.TextTag(null) { Indent = -senderPrefixWidth }; _MessageTextTagTable.Add(indentTag); } if (showTimestamps) { var msgTimeStamp = msg.TimeStamp.ToLocalTime(); if (_LastMessage != null) { var lastMsgTimeStamp = _LastMessage.TimeStamp.ToLocalTime(); var span = msgTimeStamp.Date - lastMsgTimeStamp.Date; if (span.Days > 0) { var dayLine = new MessageBuilder(). AppendEventPrefix(); if (span.Days > 1) { dayLine.AppendText(_("Day changed from {0} to {1}"), lastMsgTimeStamp.ToShortDateString(), msgTimeStamp.ToShortDateString()); } else { dayLine.AppendText(_("Day changed to {0}"), msgTimeStamp.ToLongDateString()); } dayLine.AppendText("\n"); var dayLineMsg = dayLine.ToMessage().ToString(); Buffer.InsertWithTags(ref iter, dayLineMsg, EventTag); } } string timestamp = null; try { string format = (string)Frontend.UserConfig["Interface/Notebook/TimestampFormat"]; if (!String.IsNullOrEmpty(format)) { timestamp = msgTimeStamp.ToString(format); } } catch (FormatException e) { timestamp = "Timestamp Format ERROR: " + e.Message; } if (timestamp != null) { timestamp = String.Format("{0} ", timestamp); buffer.Insert(ref iter, timestamp); // apply timestamp width to indent tag if (indentTag != null) { indentTag.Indent -= GetPangoWidth(timestamp); } } } var msgStartMark = new Gtk.TextMark(null, true); buffer.AddMark(msgStartMark, iter); bool hasHighlight = false; foreach (MessagePartModel msgPart in msg.MessageParts) { // supposed to be used only in a ChatView if (msgPart.IsHighlight) { hasHighlight = true; } // TODO: implement all types if (msgPart is UrlMessagePartModel) { var urlPart = (UrlMessagePartModel)msgPart; var linkText = urlPart.Text ?? urlPart.Url; Uri uri; try { uri = new Uri(urlPart.Url); } catch (UriFormatException ex) { #if LOG4NET _Logger.Error("AddMessage(): Invalid URL: " + urlPart.Url, ex); #endif buffer.Insert(ref iter, linkText); continue; } var tags = new List <Gtk.TextTag>(); // link URI tag var linkTag = new LinkTag(uri); linkTag.TextEvent += OnLinkTagTextEvent; _MessageTextTagTable.Add(linkTag); tags.Add(linkTag); // link style tag tags.Add(LinkTag); buffer.InsertWithTags(ref iter, linkText, tags.ToArray()); } else if (msgPart is TextMessagePartModel) { var tags = new List <Gtk.TextTag>(); TextMessagePartModel fmsgti = (TextMessagePartModel)msgPart; if (fmsgti.ForegroundColor != TextColor.None) { var bg = ColorConverter.GetTextColor(BackgroundColor); if (fmsgti.BackgroundColor != TextColor.None) { bg = fmsgti.BackgroundColor; } TextColor color = TextColorTools.GetBestTextColor( fmsgti.ForegroundColor, bg ); string tagname = GetTextTagName(color, null); var tag = _MessageTextTagTable.Lookup(tagname); tags.Add(tag); } if (fmsgti.BackgroundColor != TextColor.None) { // TODO: get this from ChatView string tagname = GetTextTagName(null, fmsgti.BackgroundColor); var tag = _MessageTextTagTable.Lookup(tagname); tags.Add(tag); } if (fmsgti.Underline) { #if LOG4NET && MSG_DEBUG _Logger.Debug("AddMessage(): fmsgti.Underline is true"); #endif tags.Add(UnderlineTag); } if (fmsgti.Bold) { #if LOG4NET && MSG_DEBUG _Logger.Debug("AddMessage(): fmsgti.Bold is true"); #endif tags.Add(BoldTag); } if (fmsgti.Italic) { #if LOG4NET && MSG_DEBUG _Logger.Debug("AddMessage(): fmsgti.Italic is true"); #endif tags.Add(ItalicTag); } if (tags.Count > 0) { buffer.InsertWithTags(ref iter, fmsgti.Text, tags.ToArray()); } else { buffer.Insert(ref iter, fmsgti.Text); } } } var startIter = buffer.GetIterAtMark(startMark); if (msg.MessageType == MessageType.Event) { buffer.ApplyTag(EventTag, startIter, iter); } if (indentTag != null) { buffer.ApplyTag(indentTag, startIter, iter); } var nick = msg.GetNick(); if (nick != null) { // TODO: re-use the same person tag for the same nick var personTag = new PersonTag(nick, nick); personTag.TextEvent += OnPersonTagTextEvent; _MessageTextTagTable.Add(personTag); var msgStartIter = buffer.GetIterAtMark(msgStartMark); var nickEndIter = msgStartIter; nickEndIter.ForwardChars(nick.Length + 2); buffer.ApplyTag(PersonTag, msgStartIter, nickEndIter); buffer.ApplyTag(personTag, msgStartIter, nickEndIter); } buffer.DeleteMark(startMark); buffer.DeleteMark(msgStartMark); if (addLinebreak) { buffer.Insert(ref iter, "\n"); } CheckBufferSize(); if (IsGtk2_17) { // HACK: force a redraw of the widget, as for some reason // GTK+ 2.17.6 is not redrawing some lines we add here, especially // for local messages. See: // http://projects.qnetp.net/issues/show/185 QueueDraw(); } if (Frontend.IsWindows && _LastMessage == null) { // HACK: workaround rendering issue on Windows where the // first inserted text is not showing up until the next insert QueueDraw(); } if (MessageAdded != null) { MessageAdded(this, new MessageTextViewMessageAddedEventArgs(msg)); } if (hasHighlight) { if (MessageHighlighted != null) { MessageHighlighted(this, new MessageTextViewMessageHighlightedEventArgs(msg)); } } _LastMessage = msg; }
void AddEmoji(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, ImageMessagePartModel imgPart, string shortName) { var unicode = Emojione.ShortnameToUnicode(shortName); if (unicode == null) { AddAlternativeText(buffer, ref iter, imgPart); return; } int width, height; int descent; using (var layout = CreatePangoLayout(null)) { layout.GetPixelSize(out width, out height); descent = layout.Context.GetMetrics(layout.FontDescription, null).Descent; } // A mark here serves two pusposes. One is to allow us to apply the // tag across the pixbuf. It also lets us know later where to put // the pixbuf if we need to load it from the network var mark = new Gtk.TextMark(null, true); buffer.AddMark(mark, iter); var emojiName = unicode + ".png"; string emojiPath; if (EmojiCache.TryGetIcon("emojione", emojiName, out emojiPath)) { var emojiFile = new FileInfo(emojiPath); if (emojiFile.Exists && emojiFile.Length > 0) { var pix = new Gdk.Pixbuf(emojiPath, -1, height); buffer.InsertPixbuf(ref iter, pix); var beforeIter = buffer.GetIterAtMark(mark); var imgTag = new EmojiTag(mark, emojiFile.FullName); imgTag.Rise = -descent; _MessageTextTagTable.Add(imgTag); buffer.ApplyTag(imgTag, beforeIter, iter); } else { AddAlternativeText(buffer, ref iter, imgPart); } return; } var emojiUrl = Emojione.UnicodeToUrl(unicode); EmojiCache.BeginDownloadFile("emojione", emojiName, emojiUrl, (path) => { GLib.Idle.Add(delegate { var afterIter = buffer.GetIterAtMark(mark); buffer.InsertPixbuf(ref afterIter, new Gdk.Pixbuf(path, -1, height)); var beforeIter = buffer.GetIterAtMark(mark); var emojiTag = new EmojiTag(mark, path); _MessageTextTagTable.Add(emojiTag); emojiTag.Rise = -descent; buffer.ApplyTag(emojiTag, beforeIter, afterIter); return(false); }); }, (ex) => { GLib.Idle.Add(delegate { var markIter = buffer.GetIterAtMark(mark); buffer.DeleteMark(mark); AddAlternativeText(buffer, ref markIter, imgPart); return(false); }); } ); }
public ChatView(ChatModel chat) { Trace.Call(chat); _ChatModel = chat; _Name = _ChatModel.Name; Name = _Name; // TextTags Gtk.TextTagTable ttt = new Gtk.TextTagTable(); _OutputTextTagTable = ttt; Gtk.TextTag tt; Pango.FontDescription fd; tt = new Gtk.TextTag("bold"); fd = new Pango.FontDescription(); fd.Weight = Pango.Weight.Bold; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("italic"); fd = new Pango.FontDescription(); fd.Style = Pango.Style.Italic; tt.FontDesc = fd; ttt.Add(tt); tt = new Gtk.TextTag("underline"); tt.Underline = Pango.Underline.Single; ttt.Add(tt); tt = new Gtk.TextTag("url"); tt.Underline = Pango.Underline.Single; tt.Foreground = "darkblue"; tt.TextEvent += new Gtk.TextEventHandler(_OnTextTagUrlTextEvent); fd = new Pango.FontDescription(); tt.FontDesc = fd; ttt.Add(tt); Gtk.TextView tv = new Gtk.TextView(); tv.Buffer = new Gtk.TextBuffer(ttt); _EndMark = tv.Buffer.CreateMark("end", tv.Buffer.EndIter, false); tv.Editable = false; //tv.CursorVisible = false; tv.CursorVisible = true; tv.WrapMode = Gtk.WrapMode.Char; tv.Buffer.Changed += new EventHandler(_OnTextBufferChanged); tv.MotionNotifyEvent += new Gtk.MotionNotifyEventHandler(_OnMotionNotifyEvent); _OutputTextView = tv; Gtk.ScrolledWindow sw = new Gtk.ScrolledWindow(); //sw.HscrollbarPolicy = Gtk.PolicyType.Never; sw.HscrollbarPolicy = Gtk.PolicyType.Automatic; sw.VscrollbarPolicy = Gtk.PolicyType.Always; sw.ShadowType = Gtk.ShadowType.In; sw.Add(_OutputTextView); _OutputScrolledWindow = sw; // popup menu _TabMenu = new Gtk.Menu(); Gtk.ImageMenuItem close_item = new Gtk.ImageMenuItem(Gtk.Stock.Close, null); close_item.Activated += new EventHandler(OnTabMenuCloseActivated); _TabMenu.Append(close_item); //FocusChild = _OutputTextView; //CanFocus = false; _TabLabel = new Gtk.Label(); _TabLabel.Text = _Name; _TabHBox = new Gtk.HBox(); _TabHBox.PackEnd(new Gtk.Fixed(), true, true, 0); _TabHBox.PackEnd(_TabLabel, false, false, 0); _TabHBox.ShowAll(); _TabEventBox = new Gtk.EventBox(); _TabEventBox.VisibleWindow = false; _TabEventBox.ButtonPressEvent += new Gtk.ButtonPressEventHandler(OnTabButtonPress); _TabEventBox.Add(_TabHBox); _TabEventBox.ShowAll(); }