Initial commit
[Nebula.git] / TextInput.cs
1 using System;
2 using Cairo;
3 using Pango;
4 using Gtk;
5 using Gdk;
6
7 public class TextInputEventArgs : EventArgs {
8         public string Value;
9
10         public TextInputEventArgs(string s) {
11                 Value = s;
12         }
13 }
14
15
16 public class TextInput : DrawingArea, IKeyPress {
17         public string Value;
18         protected int cursor;
19         private string killring = null;
20         Pango.FontDescription font;
21
22         public delegate void SelectHandler(object o, TextInputEventArgs s);
23         public event SelectHandler Selected;
24
25         public TextInput() : this("") { }
26
27         public TextInput(string Value) {
28                 this.Value = Value;
29                 cursor = Value.Length;
30                 font = Pango.FontDescription.FromString("Courier 12");
31                 SetSizeRequest(-1, 12);
32                 ModifyBg(StateType.Normal, new Gdk.Color(0xFF, 0xFF, 0xFF));
33         }
34
35         protected virtual void draw (Cairo.Context gr, int width, int height) {
36                 gr.SetSourceRGB(0,0,0);
37                 gr.NewPath();
38                 gr.Rectangle(new Cairo.Rectangle(0, 0, width, height));
39                 gr.Stroke();
40
41                 Pango.Layout layout = new Pango.Layout(this.PangoContext);
42                 layout.Width = Pango.Units.FromPixels(width);
43                 layout.Alignment = Pango.Alignment.Left;
44                 layout.FontDescription = font;
45                 layout.SetText(Value);
46                 Pango.CairoHelper.ShowLayout(gr, layout);
47
48                 gr.NewPath();
49                 int h = Pango.Units.ToPixels(layout.FontDescription.Size) + 1;
50                 gr.Rectangle(new Cairo.Rectangle(cursor*8, 0, 7, h));
51                 gr.Fill();
52         }
53
54         protected override bool OnExposeEvent (Gdk.EventExpose args) {
55                 Gdk.Window win = args.Window;                
56                 Cairo.Context g = Gdk.CairoHelper.Create (args.Window);
57
58                 int x, y, w, h, d;
59                 win.GetGeometry(out x, out y, out w, out h, out d);
60
61                 draw(g, w, h);
62
63                 ((IDisposable) g.Target).Dispose();
64                 ((IDisposable) g).Dispose();
65                 return true;
66         }
67
68         [GLib.ConnectBefore ()]
69         public virtual void KeyPress(object o, KeyPressEventArgs args) {
70                 if ((args.Event.State & ModifierType.ControlMask) != 0) {
71                         switch(args.Event.Key) {
72                         case Gdk.Key.u:
73                                 killring = Value.Substring(0, cursor);
74                                 Value = Value.Substring(cursor);
75                                 cursor = 0;
76                                 break;
77                         case Gdk.Key.k:
78                                 killring = Value.Substring(cursor);
79                                 Value = Value.Substring(0, cursor);
80                                 break;
81                         case Gdk.Key.w:
82                                 int ws = Value.LastIndexOfAny(" ".ToCharArray());
83                                 if (ws == -1) {
84                                         killring = Value;
85                                         Value = "";
86                                 } else {
87                                         killring = Value.Substring(ws + 1);
88                                         Value = Value.Substring(0, ws);
89                                 }
90                                 cursor = Value.Length;
91                                 break;
92                         case Gdk.Key.y:
93                                 if (killring == null) return;
94                                 Value = Value.Insert(cursor, killring);
95                                 cursor += killring.Length;
96                                 break;
97                         }
98                 } else {
99                         switch(args.Event.Key) {
100                         case Gdk.Key.BackSpace:
101                                 if (cursor == 0) return;
102                                 cursor--;
103                                 Value = Value.Remove(cursor, 1);
104                                 break;
105                         case Gdk.Key.Return:
106                                 if (Selected != null) {
107                                         TextInputEventArgs t = new TextInputEventArgs(Value);
108                                         Selected(this, t);
109                                         Selected = null;
110                                 }
111                                 break;
112                         case Gdk.Key.Left:
113                                 if (cursor > 0) cursor--;
114                                 break;
115                         case Gdk.Key.Right:
116                                 if (cursor < Value.Length) cursor++;
117                                 break;
118                         case Gdk.Key.Escape:
119                                 if (Selected != null) {
120                                         TextInputEventArgs t = new TextInputEventArgs(null);
121                                         Selected(this, t);
122                                         Selected = null;
123                                 }
124                                 break;
125                         default:
126                                 if (args.Event.KeyValue > 128) return;
127                                 Value = Value.Insert(cursor, new String((char)args.Event.KeyValue, 1));
128                                 cursor++;
129                                 break;
130                         }
131                 }
132                 QueueDraw();
133         }
134 }