Fix bug #395
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ColumnHeader.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 Novell, Inc. (http://www.novell.com)
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //
25
26
27 // COMPLETE
28
29
30 using System.ComponentModel;
31 using System.Drawing;
32
33 namespace System.Windows.Forms
34 {
35         [DefaultProperty ("Text")]
36         [DesignTimeVisible (false)]
37         [ToolboxItem (false)]
38         [TypeConverter (typeof (ColumnHeaderConverter))]
39         public class ColumnHeader : Component, ICloneable
40         {
41                 #region Instance Variables
42                 private StringFormat format = new StringFormat ();
43                 private string text = "ColumnHeader";
44                 private HorizontalAlignment text_alignment = HorizontalAlignment.Left;
45                 private int width = ThemeEngine.Current.ListViewDefaultColumnWidth;
46                 private int image_index = -1;
47                 private string image_key = String.Empty;
48                 private string name = String.Empty;
49                 private object tag;
50                 private int display_index = -1;
51
52                 // internal variables
53                 Rectangle column_rect = Rectangle.Empty;
54                 bool pressed = false;
55                 ListView owner;
56                 #endregion      // Instance Variables
57
58                 #region Internal Constructor
59                 internal ColumnHeader (ListView owner, string text,
60                                        HorizontalAlignment alignment, int width)
61                 {
62                         this.owner = owner;
63                         this.text = text;
64                         this.width = width;
65                         this.text_alignment = alignment;
66                         CalcColumnHeader ();
67                 }
68
69                 internal ColumnHeader (string key, string text, int width, HorizontalAlignment textAlign)
70                 {
71                         Name = key;
72                         Text = text;
73                         this.width = width;
74                         this.text_alignment = textAlign;
75                         CalcColumnHeader ();
76                 }
77                 #endregion      // Internal Constructor
78
79                 #region Public Constructors
80                 public ColumnHeader () { }
81
82                 public ColumnHeader (int imageIndex)
83                 {
84                         ImageIndex = imageIndex;
85                 }
86
87                 public ColumnHeader (string imageKey)
88                 {
89                         ImageKey = imageKey;
90                 }
91                 #endregion      // Public Constructors
92
93                 #region Private Internal Methods Properties
94                 internal bool Pressed {
95                         get { return pressed; }
96                         set { pressed = value; }
97                 }
98
99                 internal int X {
100                         get { return column_rect.X; }
101                         set { column_rect.X = value; }
102                 }
103
104                 internal int Y {
105                         get { return column_rect.Y; }
106                         set { column_rect.Y = value; }
107                 }
108
109                 internal int Wd {
110                         get { return column_rect.Width; }
111                         set { column_rect.Width = value; }
112                 }
113
114                 internal int Ht {
115                         get { return column_rect.Height; }
116                         set { column_rect.Height = value; }
117                 }
118
119                 internal Rectangle Rect {
120                         get { return column_rect; }
121                         set { column_rect = value; }
122                 }
123
124                 internal StringFormat Format {
125                         get { return format; }
126                 }
127
128                 internal int InternalDisplayIndex {
129                         get { return display_index; }
130                         set { display_index = value; }
131                 }
132
133                 internal void CalcColumnHeader ()
134                 {
135                         if (text_alignment == HorizontalAlignment.Center)
136                                 format.Alignment = StringAlignment.Center;
137                         else if (text_alignment == HorizontalAlignment.Right)
138                                 format.Alignment = StringAlignment.Far;
139                         else
140                                 format.Alignment = StringAlignment.Near;
141                         format.LineAlignment = StringAlignment.Center;
142                         format.Trimming = StringTrimming.EllipsisCharacter;
143                         // text is wrappable only in LargeIcon and SmallIcon views
144                         format.FormatFlags = StringFormatFlags.NoWrap;
145
146                         if (owner != null)
147                                 column_rect.Height = ThemeEngine.Current.ListViewGetHeaderHeight (owner, owner.Font);
148                         else
149                                 column_rect.Height = ThemeEngine.Current.ListViewGetHeaderHeight (null, ThemeEngine.Current.DefaultFont);
150
151                         column_rect.Width = 0;
152
153                         if (width >= 0) // manual width
154                                 column_rect.Width = width;
155                         else if (Index != -1) { // automatic width, either -1 or -2
156                                 // try to expand if we are the last column
157                                 bool expand_to_right = Index == owner.Columns.Count - 1 && width == -2;
158                                 Rectangle visible_area = owner.ClientRectangle;
159
160                                 column_rect.Width = owner.GetChildColumnSize (Index).Width;
161                                 width = column_rect.Width;
162
163                                 // expand only if we have free space to the right
164                                 if (expand_to_right && column_rect.X + column_rect.Width < visible_area.Width) {
165                                         width = visible_area.Width - column_rect.X;
166                                         if (owner.v_scroll.Visible)
167                                                 width -= owner.v_scroll.Width;
168
169                                         column_rect.Width = width;
170                                 }
171                         }
172                 }
173
174                 internal void SetListView (ListView list_view)
175                 {
176                         owner = list_view;
177                 }
178
179                 #endregion      // Private Internal Methods Properties
180
181                 #region Public Instance Properties
182
183                 [Localizable (true)]
184                 [RefreshProperties (RefreshProperties.Repaint)]
185                 public int DisplayIndex {
186                         get {
187                                 if (owner == null)
188                                         return display_index;
189                                         
190                                 return owner.GetReorderedColumnIndex (this);
191                         }
192                         set {
193                                 if (owner == null) {
194                                         display_index = value;
195                                         return;
196                                 }
197                                 if (value < 0 || value >= owner.Columns.Count)
198                                         throw new ArgumentOutOfRangeException ("DisplayIndex");
199
200                                 owner.ReorderColumn (this, value, false);
201                         }
202                 }
203
204                 [DefaultValue (-1)]
205                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
206                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
207                          "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
208                 [RefreshProperties (RefreshProperties.Repaint)]
209                 [TypeConverter (typeof (ImageIndexConverter))]
210                 public int ImageIndex {
211                         get {
212                                 return image_index;
213                         }
214                         set {
215                                 if (value < -1)
216                                         throw new ArgumentOutOfRangeException ("ImageIndex");
217
218                                 image_index = value;
219                                 image_key = String.Empty;
220
221                                 if (owner != null)
222                                         owner.header_control.Invalidate ();
223                         }
224                 }
225
226                 [DefaultValue ("")]
227                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
228                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
229                          "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
230                 [RefreshProperties (RefreshProperties.Repaint)]
231                 [TypeConverter (typeof (ImageKeyConverter))]
232                 public string ImageKey {
233                         get {
234                                 return image_key;
235                         }
236                         set {
237                                 image_key = value == null ? String.Empty : value;
238                                 image_index = -1;
239
240                                 if (owner != null)
241                                         owner.header_control.Invalidate ();
242                         }
243                 }
244
245                 [Browsable (false)]
246                 public ImageList ImageList {
247                         get {
248                                 if (owner == null)
249                                         return null;
250
251                                 return owner.SmallImageList;
252                         }
253                 }
254
255                 [Browsable (false)]
256                 public int Index {
257                         get {
258                                 if (owner != null)
259                                         return owner.Columns.IndexOf (this);
260
261                                 return -1;
262                         }
263                 }
264
265                 [Browsable (false)]
266                 public ListView ListView {
267                         get { return owner; }
268                 }
269
270                 [Browsable (false)]
271                 public string Name {
272                         get {
273                                 return name;
274                         }
275                         set {
276                                 name = value == null ? String.Empty : value;
277                         }
278                 }
279
280                 [DefaultValue (null)]
281                 [BindableAttribute (true)]
282                 [LocalizableAttribute (false)]
283                 [TypeConverter (typeof (StringConverter))]
284                 public object Tag {
285                         get {
286                                 return tag;
287                         }
288                         set {
289                                 tag = value;
290                         }
291                 }
292
293                 [Localizable (true)]
294                 public string Text {
295                         get { return text; }
296                         set {
297                                 if (text != value) {
298                                         text = value;
299                                         if (owner != null)
300                                                 owner.Redraw (true);
301
302                                         // UIA Framework: Raising Value changed event
303                                         OnUIATextChanged ();
304                                 }
305                         }
306                 }
307
308                 [DefaultValue (HorizontalAlignment.Left)]
309                 [Localizable (true)]
310                 public HorizontalAlignment TextAlign {
311                         get { return text_alignment; }
312                         set {
313                                 text_alignment = value;
314                                 if (owner != null)
315                                         owner.Redraw (true);
316                         }
317                 }
318
319                 [DefaultValue (60)]
320                 [Localizable (true)]
321                 public int Width {
322                         get { return width; }
323                         set {
324                                 if (width != value) {
325                                         width = value;
326                                         if (owner != null) {
327                                                 owner.Redraw (true);
328                                                 owner.RaiseColumnWidthChanged (this);
329                                         }
330                                 }
331                         }
332                 }
333                 #endregion // Public Instance Properties
334
335                 #region Public Methods
336                 public void AutoResize (ColumnHeaderAutoResizeStyle headerAutoResize)
337                 {
338                         switch (headerAutoResize) {
339                                 case ColumnHeaderAutoResizeStyle.None:
340                                         break;
341                                 case ColumnHeaderAutoResizeStyle.ColumnContent:
342                                         Width = -1;
343                                         break;
344                                 case ColumnHeaderAutoResizeStyle.HeaderSize:
345                                         Width = -2;
346                                         break;
347                                 default:
348                                         throw new InvalidEnumArgumentException ("headerAutoResize", (int) headerAutoResize,
349                                                         typeof (ColumnHeaderAutoResizeStyle));
350                         }
351                 }
352
353                 public object Clone ()
354                 {
355                         ColumnHeader columnHeader = new ColumnHeader ();
356                         columnHeader.text = text;
357                         columnHeader.text_alignment = text_alignment;
358                         columnHeader.width = width;
359                         columnHeader.owner = owner;
360                         columnHeader.format = (StringFormat) Format.Clone ();
361                         columnHeader.column_rect = Rectangle.Empty;
362                         return columnHeader;
363                 }
364
365                 public override string ToString ()
366                 {
367                         return string.Format ("ColumnHeader: Text: {0}", text);
368                 }
369                 #endregion // Public Methods
370
371                 #region Protected Methods
372                 protected override void Dispose (bool disposing)
373                 {
374                         base.Dispose (disposing);
375                 }
376                 #endregion // Protected Methods
377
378                 
379                 #region UIA Framework: Methods, Properties and Events
380
381                 static object UIATextChangedEvent = new object ();
382
383                 internal event EventHandler UIATextChanged {
384                         add { Events.AddHandler (UIATextChangedEvent, value); }
385                         remove { Events.RemoveHandler (UIATextChangedEvent, value); }
386                 }
387
388                 private void OnUIATextChanged ()
389                 {
390                         EventHandler eh = (EventHandler) Events [UIATextChangedEvent];
391                         if (eh != null)
392                                 eh (this, EventArgs.Empty);
393                 }
394
395                 #endregion
396         }
397 }