2008-06-27 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PropertyGridTextBox.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Jonathan Chambers (jonathan.chambers@ansys.com)
24 //
25
26 // COMPLETE
27
28 using System;
29 using System.Drawing;
30 using System.ComponentModel;
31
32 namespace System.Windows.Forms.PropertyGridInternal 
33 {
34         internal class PGTextBox : TextBox 
35         {
36                 private bool _focusing = false;
37
38                 public void FocusAt (Point location)
39                 {
40                         _focusing = true;
41                         Point pnt = PointToClient (location);
42                         XplatUI.SendMessage (Handle, Msg.WM_LBUTTONDOWN, new IntPtr ((int)MsgButtons.MK_LBUTTON), Control.MakeParam (pnt.X, pnt.Y));
43                 }
44
45                 protected override bool IsInputKey (Keys keyData)
46                 {
47                         // To be handled by the PropertyGridView
48                         if ((keyData & Keys.Alt) != 0 && 
49                             (keyData & Keys.KeyCode) == Keys.Down)
50                                 return true;
51                         return base.IsInputKey (keyData);
52                 }
53
54                 protected override void WndProc (ref Message m)
55                 {
56                         // Swallow the first MOUSEMOVE after the focusing WM_LBUTTONDOWN
57                         if (_focusing && m.Msg == (int)Msg.WM_MOUSEMOVE) {
58                                 _focusing = false;
59                                 return;
60                         }
61                         base.WndProc (ref m);
62                 }
63         }
64         
65         internal class PropertyGridTextBox : System.Windows.Forms.UserControl, IMessageFilter
66         {
67                 #region Private Members
68
69                 private PGTextBox textbox;
70                 private Button dialog_button;
71                 private Button dropdown_button;
72                 private bool validating = false;
73                 private bool filtering = false;
74
75                 #endregion Private Members
76
77                 #region Contructors
78                 public PropertyGridTextBox() {
79                         dialog_button = new Button();
80                         dropdown_button = new Button();
81                         textbox = new PGTextBox ();
82
83                         SuspendLayout();
84
85                         dialog_button.Dock = DockStyle.Right;
86                         dialog_button.BackColor = SystemColors.Control;
87                         dialog_button.Size = new Size(16, 16);
88                         dialog_button.TabIndex = 1;
89                         dialog_button.Visible = false;
90                         dialog_button.Click += new System.EventHandler(dialog_button_Click);
91
92                         dropdown_button.Dock = DockStyle.Right;
93                         dropdown_button.BackColor = SystemColors.Control;
94                         dropdown_button.Size = new Size(16, 16);
95                         dropdown_button.TabIndex = 2;
96                         dropdown_button.Visible = false;
97                         dropdown_button.Click += new System.EventHandler(dropdown_button_Click);
98
99                         textbox.AutoSize = false;
100                         textbox.BorderStyle = BorderStyle.None;
101                         textbox.Dock = DockStyle.Fill;
102                         textbox.TabIndex = 3;
103
104                         Controls.Add(textbox);
105                         Controls.Add(dropdown_button);
106                         Controls.Add(dialog_button);
107
108                         SetStyle (ControlStyles.Selectable, true);
109
110                         ResumeLayout(false);
111
112                         dropdown_button.Paint+=new PaintEventHandler(dropdown_button_Paint);
113                         dialog_button.Paint+=new PaintEventHandler(dialog_button_Paint);
114                         textbox.DoubleClick+=new EventHandler(textbox_DoubleClick);
115                         textbox.KeyDown+=new KeyEventHandler(textbox_KeyDown);
116                         textbox.GotFocus+=new EventHandler(textbox_GotFocus);
117                 }
118
119                 
120                 #endregion Contructors
121
122                 #region Protected Instance Properties
123
124                 protected override void OnGotFocus (EventArgs args)
125                 {
126                         base.OnGotFocus (args);
127                         // force-disable selection
128                         textbox.has_been_focused = true;
129                         textbox.Focus ();
130                         textbox.SelectionLength = 0;
131                 }
132
133                 #endregion
134
135                 #region Public Instance Properties
136
137                 public bool DialogButtonVisible {
138                         get{
139                                 return dialog_button.Visible;
140                         }
141                         set {
142                                 dialog_button.Visible = value;
143                         }
144                 }
145                 public bool DropDownButtonVisible {
146                         get{
147                                 return dropdown_button.Visible;
148                         }
149                         set {
150                                 dropdown_button.Visible = value;
151                         }
152                 }
153
154                 public new Color ForeColor {
155                         get {
156                                 return base.ForeColor;
157                         }
158                         set {
159                                 textbox.ForeColor = value;
160                                 dropdown_button.ForeColor = value;
161                                 dialog_button.ForeColor = value;
162                                 base.ForeColor = value;
163                         }
164                 }
165
166                 public new Color BackColor {
167                         get {
168                                 return base.BackColor;
169                         }
170                         set {
171                                 textbox.BackColor = value;
172                                 base.BackColor = value;
173                         }
174                 }
175                 public bool ReadOnly {
176                         get {
177                                 return textbox.ReadOnly;
178                         }
179                         set {
180                                 textbox.ReadOnly = value;
181                         }
182                 }
183
184                 public new string Text {
185                         get {
186                                 return textbox.Text;
187                         }
188                         set {
189                                 textbox.Text = value;
190                         }
191                 }
192
193                 public char PasswordChar {
194                         set { textbox.PasswordChar = value; }
195                 }
196
197                 #endregion Public Instance Properties
198                 
199                 #region Events
200                 static object DropDownButtonClickedEvent = new object ();
201                 static object DialogButtonClickedEvent = new object ();
202                 static object ToggleValueEvent = new object ();
203                 static object KeyDownEvent = new object ();
204                 static object ValidateEvent = new object ();
205
206                 public event EventHandler DropDownButtonClicked {
207                         add { Events.AddHandler (DropDownButtonClickedEvent, value); }
208                         remove { Events.RemoveHandler (DropDownButtonClickedEvent, value); }
209                 }
210
211                 public event EventHandler DialogButtonClicked {
212                         add { Events.AddHandler (DialogButtonClickedEvent, value); }
213                         remove { Events.RemoveHandler (DialogButtonClickedEvent, value); }
214                 }
215
216                 public event EventHandler ToggleValue {
217                         add { Events.AddHandler (ToggleValueEvent, value); }
218                         remove { Events.RemoveHandler (ToggleValueEvent, value); }
219                 }
220
221                 public new event KeyEventHandler KeyDown {
222                         add { Events.AddHandler (KeyDownEvent, value); }
223                         remove { Events.RemoveHandler (KeyDownEvent, value); }
224                 }
225                 
226                 public new event CancelEventHandler Validate {
227                         add { Events.AddHandler (ValidateEvent, value); }
228                         remove { Events.RemoveHandler (ValidateEvent, value); }
229                 }
230                 #endregion Events
231                 
232                 #region Private Helper Methods
233
234                 private void dropdown_button_Paint(object sender, PaintEventArgs e)
235                 {
236                         ThemeEngine.Current.CPDrawComboButton(e.Graphics, dropdown_button.ClientRectangle, dropdown_button.ButtonState);
237                 }
238
239                 private void dialog_button_Paint(object sender, PaintEventArgs e) {
240                         // best way to draw the ellipse?
241                         e.Graphics.DrawString("...", new Font(Font,FontStyle.Bold), Brushes.Black, 0,0);
242                 }
243
244                 private void dropdown_button_Click(object sender, EventArgs e) {
245                         EventHandler eh = (EventHandler)(Events [DropDownButtonClickedEvent]);
246                         if (eh != null)
247                                 eh (this, e);
248                 }
249
250                 private void dialog_button_Click(object sender, EventArgs e) {
251                         EventHandler eh = (EventHandler)(Events [DialogButtonClickedEvent]);
252                         if (eh != null)
253                                 eh (this, e);
254                 }
255
256                 #endregion Private Helper Methods
257
258                 internal void SendMouseDown (Point screenLocation)
259                 {
260                         Point clientLocation = PointToClient (screenLocation);
261                         XplatUI.SendMessage (Handle, Msg.WM_LBUTTONDOWN, new IntPtr ((int) MsgButtons.MK_LBUTTON), Control.MakeParam (clientLocation.X, clientLocation.Y));
262                         textbox.FocusAt (screenLocation);
263                 }       
264
265                 private void textbox_DoubleClick(object sender, EventArgs e) {
266                         EventHandler eh = (EventHandler)(Events [ToggleValueEvent]);
267                         if (eh != null)
268                                 eh (this, e);
269                 }
270
271                 private void textbox_KeyDown(object sender, KeyEventArgs e) {
272                         KeyEventHandler eh = (KeyEventHandler)(Events [KeyDownEvent]);
273                         if (eh != null)
274                                 eh (this, e);
275                 }
276
277                 private void textbox_GotFocus(object sender, EventArgs e) {
278                         if (!filtering) {
279                                 filtering = true;
280                                 Application.AddMessageFilter ((IMessageFilter)this);
281                         }
282                 }
283
284                 bool IMessageFilter.PreFilterMessage(ref Message m)
285                 {
286                         // validating check is to allow whatever UI code to execute
287                         // without filtering messages (i.e. error dialogs, etc)
288                         //
289                         if (!validating && m.HWnd != textbox.Handle &&
290                             m.Msg == (int)Msg.WM_LBUTTONDOWN || 
291                             m.Msg == (int)Msg.WM_MBUTTONDOWN ||
292                             m.Msg == (int)Msg.WM_RBUTTONDOWN ||
293                             m.Msg == (int)Msg.WM_NCLBUTTONDOWN ||
294                             m.Msg == (int)Msg.WM_NCMBUTTONDOWN ||
295                             m.Msg == (int)Msg.WM_NCRBUTTONDOWN) {
296                                 CancelEventHandler validateHandler = (CancelEventHandler)(Events [ValidateEvent]);
297                                 if (validateHandler != null) {
298                                         CancelEventArgs args = new CancelEventArgs ();
299                                         validating = true;
300                                         validateHandler (this, args);
301                                         validating = false;
302                                         if (!args.Cancel) {
303                                                 Application.RemoveMessageFilter ((IMessageFilter)this);
304                                                 filtering = false;
305                                         }
306                                         return args.Cancel;
307                                 }
308                         }
309                         return false;
310                 }
311         }
312 }