using System; using Cairo; using Pango; using Gtk; using Gdk; public class TextInputEventArgs : EventArgs { public string Value; public TextInputEventArgs(string s) { Value = s; } } public class TextInput : DrawingArea, IKeyPress { public string Value; protected int cursor; private string killring = null; Pango.FontDescription font; public delegate void SelectHandler(object o, TextInputEventArgs s); public event SelectHandler Selected; public TextInput() : this("") { } public TextInput(string Value) { this.Value = Value; cursor = Value.Length; font = Pango.FontDescription.FromString("Courier 12"); SetSizeRequest(-1, 12); ModifyBg(StateType.Normal, new Gdk.Color(0xFF, 0xFF, 0xFF)); } protected virtual void draw (Cairo.Context gr, int width, int height) { gr.SetSourceRGB(0,0,0); gr.NewPath(); gr.Rectangle(new Cairo.Rectangle(0, 0, width, height)); gr.Stroke(); Pango.Layout layout = new Pango.Layout(this.PangoContext); layout.Width = Pango.Units.FromPixels(width); layout.Alignment = Pango.Alignment.Left; layout.FontDescription = font; layout.SetText(Value); Pango.CairoHelper.ShowLayout(gr, layout); gr.NewPath(); int h = Pango.Units.ToPixels(layout.FontDescription.Size) + 1; gr.Rectangle(cursor*8, 0, 7, h); gr.Fill(); } protected override bool OnExposeEvent (Gdk.EventExpose args) { Gdk.Window win = args.Window; Cairo.Context g = Gdk.CairoHelper.Create (args.Window); int x, y, w, h, d; win.GetGeometry(out x, out y, out w, out h, out d); draw(g, w, h); ((IDisposable) g.Target).Dispose(); ((IDisposable) g).Dispose(); return true; } [GLib.ConnectBefore ()] public virtual void KeyPress(object o, KeyPressEventArgs args) { if ((args.Event.State & ModifierType.ControlMask) != 0) { switch(args.Event.Key) { case Gdk.Key.u: killring = Value.Substring(0, cursor); Value = Value.Substring(cursor); cursor = 0; break; case Gdk.Key.k: killring = Value.Substring(cursor); Value = Value.Substring(0, cursor); break; case Gdk.Key.w: int ws = Value.LastIndexOfAny(" ".ToCharArray()); if (ws == -1) { killring = Value; Value = ""; } else { killring = Value.Substring(ws + 1); Value = Value.Substring(0, ws); } cursor = Value.Length; break; case Gdk.Key.y: if (killring == null) return; Value = Value.Insert(cursor, killring); cursor += killring.Length; break; } } else { switch(args.Event.Key) { case Gdk.Key.BackSpace: if (cursor == 0) return; cursor--; Value = Value.Remove(cursor, 1); break; case Gdk.Key.Return: if (Selected != null) { TextInputEventArgs t = new TextInputEventArgs(Value); Selected(this, t); Selected = null; } break; case Gdk.Key.Left: if (cursor > 0) cursor--; break; case Gdk.Key.Right: if (cursor < Value.Length) cursor++; break; case Gdk.Key.Escape: if (Selected != null) { TextInputEventArgs t = new TextInputEventArgs(null); Selected(this, t); Selected = null; } break; default: if (args.Event.KeyValue > 128) return; Value = Value.Insert(cursor, new String((char)args.Event.KeyValue, 1)); cursor++; break; } } QueueDraw(); } }