// // GtkExtensions.cs // // Author: // Vsevolod Kukol // // Copyright (c) 2014 Vsevolod Kukol // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using Gdk; namespace Xwt.GtkBackend { public static class Gtk2Extensions { public static void SetHasWindow (this Gtk.Widget widget, bool value) { if (value) widget.WidgetFlags &= ~Gtk.WidgetFlags.NoWindow; else widget.WidgetFlags |= Gtk.WidgetFlags.NoWindow; } public static bool GetHasWindow (this Gtk.Widget widget) { return !widget.IsNoWindow; } public static void SetAppPaintable (this Gtk.Widget widget, bool value) { if (value) widget.WidgetFlags |= Gtk.WidgetFlags.AppPaintable; else widget.WidgetFlags &= ~Gtk.WidgetFlags.AppPaintable; } public static void SetStateActive(this Gtk.Widget widget) { widget.State = Gtk.StateType.Active; } public static void SetStateNormal(this Gtk.Widget widget) { widget.State = Gtk.StateType.Normal; } public static void AddSignalHandler (this Gtk.Widget widget, string name, Delegate handler, Type args_type) { var signal = GLib.Signal.Lookup (widget, name, args_type); signal.AddDelegate (handler); } public static void RemoveSignalHandler (this Gtk.Widget widget, string name, Delegate handler) { var signal = GLib.Signal.Lookup (widget, name); signal.RemoveDelegate (handler); } public static Gdk.Pixbuf ToPixbuf (this Gdk.Window window, int src_x, int src_y, int width, int height) { return Gdk.Pixbuf.FromDrawable (window, Gdk.Colormap.System, src_x, src_y, 0, 0, width, height); } public static Gtk.CellRenderer[] GetCellRenderers (this Gtk.TreeViewColumn column) { return column.CellRenderers; } public static Gdk.DragAction GetSelectedAction (this Gdk.DragContext context) { return context.Action; } public static Gdk.Atom[] ListTargets (this Gdk.DragContext context) { return context.Targets; } public static void AddContent (this Gtk.Dialog dialog, Gtk.Widget widget, bool expand = true, bool fill = true, uint padding = 0) { dialog.VBox.PackStart (widget, expand, fill, padding); } public static void AddContent (this Gtk.MessageDialog dialog, Gtk.Widget widget, bool expand = true, bool fill = true, uint padding = 0) { var messageArea = dialog.GetMessageArea () ?? dialog.VBox; messageArea.PackStart (widget, expand, fill, padding); } public static void SetContentSpacing (this Gtk.Dialog dialog, int spacing) { dialog.VBox.Spacing = spacing; } public static void SetTextColumn (this Gtk.ComboBox comboBox, int column) { ((Gtk.ComboBoxEntry)comboBox).TextColumn = column; } public static void FixContainerLeak (this Gtk.Container c) { GtkWorkarounds.FixContainerLeak (c); } public static Xwt.Drawing.Color GetBackgroundColor (this Gtk.Widget widget) { return widget.GetBackgroundColor (Gtk.StateType.Normal); } public static Xwt.Drawing.Color GetBackgroundColor (this Gtk.Widget widget, Gtk.StateType state) { return widget.Style.Background (state).ToXwtValue (); } public static void SetBackgroundColor (this Gtk.Widget widget, Xwt.Drawing.Color color) { widget.SetBackgroundColor (Gtk.StateType.Normal, color); } public static void SetBackgroundColor (this Gtk.Widget widget, Gtk.StateType state, Xwt.Drawing.Color color) { widget.ModifyBg (state, color.ToGtkValue ()); } public static void SetChildBackgroundColor (this Gtk.Container container, Xwt.Drawing.Color color) { foreach (var widget in container.Children) widget.ModifyBg (Gtk.StateType.Normal, color.ToGtkValue ()); } public static Xwt.Drawing.Color GetForegroundColor (this Gtk.Widget widget) { return widget.GetForegroundColor (Gtk.StateType.Normal); } public static Xwt.Drawing.Color GetForegroundColor (this Gtk.Widget widget, Gtk.StateType state) { return widget.Style.Foreground (state).ToXwtValue (); } public static void SetForegroundColor (this Gtk.Widget widget, Xwt.Drawing.Color color) { widget.SetForegroundColor (Gtk.StateType.Normal, color); } public static void SetForegroundColor (this Gtk.Widget widget, Gtk.StateType state, Xwt.Drawing.Color color) { widget.ModifyFg (state, color.ToGtkValue ()); } public static Xwt.Drawing.Color GetTextColor (this Gtk.Widget widget) { return widget.GetTextColor (Gtk.StateType.Normal); } public static Xwt.Drawing.Color GetTextColor (this Gtk.Widget widget, Gtk.StateType state) { return widget.Style.Text (state).ToXwtValue (); } public static void SetTextColor (this Gtk.Widget widget, Xwt.Drawing.Color color) { widget.SetTextColor (Gtk.StateType.Normal, color); } public static void SetTextColor (this Gtk.Widget widget, Gtk.StateType state, Xwt.Drawing.Color color) { widget.ModifyText (state, color.ToGtkValue ()); } public static string GetText (this Gtk.TextInsertedArgs args) { return args.Text; } public static void RenderPlaceholderText (this Gtk.Entry entry, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout) { // The Entry's GdkWindow is the top level window onto which // the frame is drawn; the actual text entry is drawn into a // separate window, so we can ensure that for themes that don't // respect HasFrame, we never ever allow the base frame drawing // to happen if (args.Event.Window == entry.GdkWindow) return; if (entry.Text.Length > 0) return; RenderPlaceholderText_internal (entry, args, placeHolderText, ref layout, entry.Xalign, 0.5f, 1, 0); } static void RenderPlaceholderText_internal (Gtk.Widget widget, Gtk.ExposeEventArgs args, string placeHolderText, ref Pango.Layout layout, float xalign, float yalign, int xpad, int ypad) { if (layout == null) { layout = new Pango.Layout (widget.PangoContext); layout.FontDescription = widget.PangoContext.FontDescription.Copy (); } int wh, ww; args.Event.Window.GetSize (out ww, out wh); int width, height; layout.SetText (placeHolderText); layout.GetPixelSize (out width, out height); int x = xpad + (int)((ww - width) * xalign); int y = ypad + (int)((wh - height) * yalign); using (var gc = new Gdk.GC (args.Event.Window)) { gc.Copy (widget.Style.TextGC (Gtk.StateType.Normal)); Xwt.Drawing.Color color_a = widget.Style.Base (Gtk.StateType.Normal).ToXwtValue (); Xwt.Drawing.Color color_b = widget.Style.Text (Gtk.StateType.Normal).ToXwtValue (); gc.RgbFgColor = color_b.BlendWith (color_a, 0.5).ToGtkValue (); args.Event.Window.DrawLayout (gc, x, y, layout); } } public static double GetSliderPosition (this Gtk.Scale scale) { Gtk.Orientation orientation; if (scale is Gtk.HScale) orientation = Gtk.Orientation.Horizontal; else if (scale is Gtk.VScale) orientation = Gtk.Orientation.Vertical; else throw new InvalidOperationException ("Can not obtain slider position from " + scale.GetType ()); var padding = (int)scale.StyleGetProperty ("focus-padding"); var slwidth = Convert.ToDouble (scale.StyleGetProperty ("slider-width")); int orientationSize; if (orientation == Gtk.Orientation.Horizontal) orientationSize = scale.Allocation.Width - (2 * padding); else orientationSize = scale.Allocation.Height - (2 * padding); double prct = 0; if (scale.Adjustment.Lower >= 0) { prct = (scale.Value / (scale.Adjustment.Upper - scale.Adjustment.Lower)); } else if (scale.Adjustment.Upper <= 0) { prct = (Math.Abs (scale.Value) / Math.Abs (scale.Adjustment.Lower - scale.Adjustment.Upper)); } else if (scale.Adjustment.Lower < 0) { if (scale.Value >= 0) prct = 0.5 + ((scale.Value / 2) / scale.Adjustment.Upper); else prct = 0.5 - Math.Abs ((scale.Value / 2) / scale.Adjustment.Lower); } if (orientation == Gtk.Orientation.Vertical || scale.Inverted) prct = 1 - prct; return (int)(((orientationSize - (slwidth)) * prct) + (slwidth / 2)); } } }