2005-08-25 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / Style.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) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Dennis Bartok     (pbartok@novell.com)
24 //
25 //
26
27 using System;
28 using System.ComponentModel;
29 using System.Drawing;
30
31 namespace System.Web.UI.WebControls 
32 {
33         [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
34         [ToolboxItem("")]
35         public class Style : System.ComponentModel.Component, System.Web.UI.IStateManager 
36         {
37                 [Flags]
38                 internal enum Styles 
39                 {
40                         None            = 0,
41                         BackColor       = 0x00000001,
42                         BorderColor     = 0x00000002,
43                         BorderStyle     = 0x00000004,
44                         BorderWidth     = 0x00000008,
45                         CssClass        = 0x00000010,
46                         Font            = 0x00000020,
47                         ForeColor       = 0x00000040,
48                         Height          = 0x00000080,
49                         Width           = 0x00000100,
50
51                         // from TableStyle (which doesn't override IsEmpty)
52                         BackImageUrl    = 0x00000200,
53                         CellPadding     = 0x00000400,
54                         CellSpacing     = 0x00000800,
55                         GridLines       = 0x00001000,
56                         HorizontalAlign = 0x00002000,
57
58                         // from TableItemStyle (which doesn't override IsEmpty neither)
59                         VerticalAlign   = 0x00004000,
60                         Wrap            = 0x00008000,
61
62                         // from DataGridPagerStyle (and, once again, no IsEmpty override)
63                         Mode            = 0x00010000,
64                         NextPageText    = 0x00020000,
65                         PageButtonCount = 0x00040000,
66                         Position        = 0x00080000,
67                         PrevPageText    = 0x00100000,
68                         Visible         = 0x00200000
69                         
70                 }
71
72                 #region Fields
73                 internal Styles         styles;
74                 internal StateBag       viewstate;
75                 private FontInfo        fontinfo;
76                 private bool            tracking;
77 #if NET_2_0
78                 private string          registered_class;
79 #endif
80                 #endregion      // Fields
81
82                 #region Public Constructors
83                 public Style() : this(new StateBag()) 
84                 {
85                 }
86
87                 public Style(System.Web.UI.StateBag bag) 
88                 {
89                         if (bag != null) {
90                                 viewstate = bag;
91                         } else {
92                                 viewstate = new StateBag();
93                         }
94                         tracking = false;
95                 }
96                 #endregion      // Public Constructors
97
98                 #region Public Instance Properties
99                 [Bindable(true)]
100                 [DefaultValue("Color [Empty]")]
101                 [NotifyParentProperty(true)]
102                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
103                 public Color BackColor 
104                 {
105                         get 
106                         {
107                                 if ((styles & Styles.BackColor) == 0) 
108                                 {
109                                         return Color.Empty;
110                                 }
111
112                                 return (Color)viewstate["BackColor"];
113                         }
114
115                         set 
116                         {
117                                 viewstate["BackColor"] = value;
118                                 styles |= Styles.BackColor;
119                         }
120                 }
121
122                 [Bindable(true)]
123                 [DefaultValue("Color [Empty]")]
124                 [NotifyParentProperty(true)]
125                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
126                 public Color BorderColor 
127                 {
128                         get 
129                         {
130                                 if ((styles & Styles.BorderColor) == 0) 
131                                 {
132                                         return Color.Empty;
133                                 }
134
135                                 return (Color)viewstate["BorderColor"];
136                         }
137
138                         set 
139                         {
140                                 viewstate["BorderColor"] = value;
141                                 styles |= Styles.BorderColor;
142                         }
143                 }
144
145                 [Bindable(true)]
146                 [DefaultValue(BorderStyle.NotSet)]
147                 [NotifyParentProperty(true)]
148                 public BorderStyle BorderStyle 
149                 {
150                         get 
151                         {
152                                 if ((styles & Styles.BorderStyle) == 0) 
153                                 {
154                                         return BorderStyle.NotSet;
155                                 }
156
157                                 return (BorderStyle)viewstate["BorderStyle"];
158                         }
159
160                         set 
161                         {
162                                 viewstate["BorderStyle"] = value;
163                                 styles |= Styles.BorderStyle;
164                         }
165                 }
166
167                 [Bindable(true)]
168                 [DefaultValue("")]
169                 [NotifyParentProperty(true)]
170                 public Unit BorderWidth 
171                 {
172                         get 
173                         {
174                                 if ((styles & Styles.BorderWidth) == 0) 
175                                 {
176                                         return Unit.Empty;
177                                 }
178
179                                 return (Unit)viewstate["BorderWidth"];
180                         }
181
182                         set 
183                         {
184                                 if (value.Value < 0) 
185                                 {
186                                         throw new ArgumentOutOfRangeException("Value", value.Value, "BorderWidth must not be negative");
187                                 }
188
189                                 viewstate["BorderWidth"] = value;
190                                 styles |= Styles.BorderWidth;
191                         }
192                 }
193
194                 [DefaultValue("")]
195                 [NotifyParentProperty(true)]
196                 public string CssClass 
197                 {
198                         get 
199                         {
200                                 if ((styles & Styles.CssClass) == 0) 
201                                 {
202                                         return string.Empty;
203                                 }
204
205                                 return (string)viewstate["CssClass"];
206                         }
207
208                         set 
209                         {
210                                 viewstate["CssClass"] = value;
211                                 styles |= Styles.CssClass;
212                         }
213                 }
214
215                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
216                 [NotifyParentProperty(true)]
217                 public FontInfo Font 
218                 {
219                         get 
220                         {
221                                 if (fontinfo == null) 
222                                 {
223                                         fontinfo = new FontInfo(this);
224                                 }
225                                 return fontinfo;
226                         }
227                 }
228
229                 [Bindable(true)]
230                 [DefaultValue("Color [Empty]")]
231                 [NotifyParentProperty(true)]
232                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
233                 public Color ForeColor 
234                 {
235                         get 
236                         {
237                                 if ((styles & Styles.ForeColor) == 0) 
238                                 {
239                                         return Color.Empty;
240                                 }
241
242                                 return (Color)viewstate["ForeColor"];
243                         }
244
245                         set 
246                         {
247                                 viewstate["ForeColor"] = value;
248                                 styles |= Styles.ForeColor;
249                         }
250                 }
251
252                 [Bindable(true)]
253                 [DefaultValue("")]
254                 [NotifyParentProperty(true)]
255                 public Unit Height 
256                 {
257                         get 
258                         {
259                                 if ((styles & Styles.Height) == 0) 
260                                 {
261                                         return Unit.Empty;
262                                 }
263
264                                 return (Unit)viewstate["Height"];
265                         }
266
267                         set 
268                         {
269                                 if (value.Value < 0) 
270                                 {
271                                         throw new ArgumentOutOfRangeException("Value", value.Value, "Height must not be negative");
272                                 }
273
274                                 viewstate["Height"] = value;
275                                 styles |= Styles.Height;
276                         }
277                 }
278
279                 [Bindable(true)]
280                 [DefaultValue("")]
281                 [NotifyParentProperty(true)]
282                 public Unit Width 
283                 {
284                         get 
285                         {
286                                 if ((styles & Styles.Width) == 0) 
287                                 {
288                                         return Unit.Empty;
289                                 }
290
291                                 return (Unit)viewstate["Width"];
292                         }
293
294                         set 
295                         {
296                                 if (value.Value < 0) 
297                                 {
298                                         throw new ArgumentOutOfRangeException("Value", value.Value, "Width must not be negative");
299                                 }
300
301                                 viewstate["Width"] = value;
302                                 styles |= Styles.Width;
303                         }
304                 }
305                 #endregion      // Public Instance Properties
306
307                 #region Protected Instance Properties
308                 protected internal virtual bool IsEmpty 
309                 {
310                         get 
311                         {
312                                 return (styles == 0);
313                         }
314                 }
315
316                 protected bool IsTrackingViewState 
317                 {
318                         get 
319                         {
320                                 return tracking;
321                         }
322                 }
323
324                 [Browsable(false)]
325                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
326                 protected internal StateBag ViewState 
327                 {
328                         get 
329                         {
330                                 return viewstate;
331                         }
332                 }
333                 #endregion      // Protected Instance Properties
334
335                 #region Public Instance Methods
336                 public void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer) 
337                 {
338                         AddAttributesToRender(writer, null);
339                 }
340
341                 public virtual void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer, WebControl owner)
342                 {
343                         if ((styles & Styles.CssClass) != 0) 
344                         {
345                                 string s = (string)viewstate["CssClass"];
346                                 if (s != string.Empty)
347                                         writer.AddAttribute (HtmlTextWriterAttribute.Class, s);
348                         }
349
350                         CssStyleCollection attributes = new CssStyleCollection ();
351                         FillStyleAttributes (attributes);
352                         foreach (string attr in attributes.Keys)
353                                 writer.AddStyleAttribute (attr, attributes [attr]);
354                 }
355                  
356                 void FillStyleAttributes (CssStyleCollection attributes) 
357                 {
358                         string          s;
359                         Color           color;
360                         BorderStyle     bs;
361                         Unit            u;
362
363                         if ((styles & Styles.BackColor) != 0)
364                         {
365                                 color = (Color)viewstate["BackColor"];
366                                 if (!color.IsEmpty)
367                                         attributes.Add (HtmlTextWriterStyle.BackgroundColor, ColorTranslator.ToHtml(color));
368                         }
369
370                         if ((styles & Styles.BorderColor) != 0) 
371                         {
372                                 color = (Color)viewstate["BorderColor"];
373                                 if (!color.IsEmpty)
374                                         attributes.Add (HtmlTextWriterStyle.BorderColor, ColorTranslator.ToHtml(color));
375                         }
376
377                         if ((styles & Styles.BorderStyle) != 0) 
378                         {
379                                 bs = (BorderStyle)viewstate["BorderStyle"];
380                                 if (bs != BorderStyle.NotSet) 
381                                         attributes.Add (HtmlTextWriterStyle.BorderStyle, bs.ToString());
382                         }
383
384                         if ((styles & Styles.BorderWidth) != 0) 
385                         {
386                                 u = (Unit)viewstate["BorderWidth"];
387                                 if (!u.IsEmpty)
388                                         attributes.Add (HtmlTextWriterStyle.BorderWidth, u.ToString());
389                         }
390
391                         if ((styles & Styles.ForeColor) != 0) 
392                         {
393                                 color = (Color)viewstate["ForeColor"];
394                                 if (!color.IsEmpty)
395                                         attributes.Add (HtmlTextWriterStyle.Color, ColorTranslator.ToHtml(color));
396                         }
397
398                         if ((styles & Styles.Height) != 0) 
399                         {
400                                 u = (Unit)viewstate["Height"];
401                                 if (!u.IsEmpty)
402                                         attributes.Add (HtmlTextWriterStyle.Height, u.ToString());
403                         }
404
405                         if ((styles & Styles.Width) != 0) 
406                         {
407                                 u = (Unit)viewstate["Width"];
408                                 if (!u.IsEmpty)
409                                         attributes.Add (HtmlTextWriterStyle.Width, u.ToString());
410                         }
411
412                         if (fontinfo != null) {
413                                 // Fonts are a bit weird
414                                 if (fontinfo.Name != string.Empty) 
415                                 {
416                                         s = fontinfo.Names[0];
417                                         for (int i = 1; i < fontinfo.Names.Length; i++) 
418                                         {
419                                                 s += "," + fontinfo.Names[i];
420                                         }
421                                         attributes.Add (HtmlTextWriterStyle.FontFamily, s);
422                                 }
423
424                                 if (fontinfo.Bold) 
425                                 {
426                                         attributes.Add (HtmlTextWriterStyle.FontWeight, "bold");
427                                 }
428
429                                 if (fontinfo.Italic) 
430                                 {
431                                         attributes.Add (HtmlTextWriterStyle.FontStyle, "italic");
432                                 }
433
434                                 if (!fontinfo.Size.IsEmpty) 
435                                 {
436                                         attributes.Add (HtmlTextWriterStyle.FontSize, fontinfo.Size.ToString());
437                                 }
438
439                                 // These styles are munged into a attribute decoration
440                                 s = string.Empty;
441
442                                 if (fontinfo.Overline) 
443                                 {
444                                         s += "overline ";
445                                 }
446
447                                 if (fontinfo.Strikeout) 
448                                 {
449                                         s += "line-through ";
450                                 }
451
452                                 if (fontinfo.Underline) 
453                                 {
454                                         s += "underline ";
455                                 }
456
457                                 if (s != string.Empty) 
458                                 {
459                                         attributes.Add (HtmlTextWriterStyle.TextDecoration, s);
460                                 }
461                         }
462                 }
463
464                 public virtual void CopyFrom(Style s) 
465                 {
466                         if ((s == null) || s.IsEmpty) 
467                         {
468                                 return;
469                         }
470
471                         if (s.fontinfo != null) 
472                         {
473                                 Font.CopyFrom(s.fontinfo);
474                         }
475
476                         if (((s.styles & Styles.BackColor) != 0) && (s.BackColor != Color.Empty))
477                         {
478                                 this.BackColor = s.BackColor;
479                         }
480                         if (((s.styles & Styles.BorderColor) != 0) && (s.BorderColor != Color.Empty))
481                         {
482                                 this.BorderColor = s.BorderColor;
483                         }
484                         if (((s.styles & Styles.BorderStyle) != 0) && (s.BorderStyle != BorderStyle.NotSet))
485                         {
486                                 this.BorderStyle = s.BorderStyle;
487                         }
488                         if (((s.styles & Styles.BorderWidth) != 0) && (s.BorderWidth != Unit.Empty))
489                         {
490                                 this.BorderWidth = s.BorderWidth;
491                         }
492                         if (((s.styles & Styles.CssClass) != 0) && (s.CssClass != string.Empty))
493                         {
494                                 this.CssClass = s.CssClass;
495                         }
496                         if (((s.styles & Styles.ForeColor) != 0) && (s.ForeColor != Color.Empty))
497                         {
498                                 this.ForeColor = s.ForeColor;
499                         }
500                         if (((s.styles & Styles.Height) != 0) && (s.Height != Unit.Empty))
501                         {
502                                 this.Height = s.Height;
503                         }
504                         if (((s.styles & Styles.Width) != 0) && (s.Width != Unit.Empty))
505                         {
506                                 this.Width = s.Width;
507                         }
508                 }
509
510                 public virtual void MergeWith(Style s) 
511                 {
512                         if ((s == null) || (s.IsEmpty))
513                         {
514                                 return;
515                         }
516
517                         if (s.fontinfo != null) 
518                         {
519                                 Font.MergeWith(s.fontinfo);
520                         }
521
522                         if (((styles & Styles.BackColor) == 0) && ((s.styles & Styles.BackColor) != 0) && (s.BackColor != Color.Empty))
523                         {
524                                 this.BackColor = s.BackColor;
525                         }
526                         if (((styles & Styles.BorderColor) == 0) && ((s.styles & Styles.BorderColor) != 0) && (s.BorderColor != Color.Empty)) 
527                         {
528                                 this.BorderColor = s.BorderColor;
529                         }
530                         if (((styles & Styles.BorderStyle) == 0) && ((s.styles & Styles.BorderStyle) != 0) && (s.BorderStyle != BorderStyle.NotSet)) 
531                         {
532                                 this.BorderStyle = s.BorderStyle;
533                         }
534                         if (((styles & Styles.BorderWidth) == 0) && ((s.styles & Styles.BorderWidth) != 0) && (s.BorderWidth != Unit.Empty)) 
535                         {
536                                 this.BorderWidth = s.BorderWidth;
537                         }
538                         if (((styles & Styles.CssClass) == 0) && ((s.styles & Styles.CssClass) != 0) && (s.CssClass != string.Empty)) 
539                         {
540                                 this.CssClass = s.CssClass;
541                         }
542                         if (((styles & Styles.ForeColor) == 0) && ((s.styles & Styles.ForeColor) != 0) && (s.ForeColor != Color.Empty)) 
543                         {
544                                 this.ForeColor = s.ForeColor;
545                         }
546                         if (((styles & Styles.Height) == 0) && ((s.styles & Styles.Height) != 0) && (s.Height != Unit.Empty)) 
547                         {
548                                 this.Height = s.Height;
549                         }
550                         if (((styles & Styles.Width) == 0) && ((s.styles & Styles.Width) != 0) && (s.Width != Unit.Empty)) 
551                         {
552                                 this.Width = s.Width;
553                         }
554                 }
555
556                 public virtual void Reset() 
557                 {
558                         viewstate.Remove("BackColor");
559                         viewstate.Remove("BorderColor");
560                         viewstate.Remove("BorderStyle");
561                         viewstate.Remove("BorderWidth");
562                         viewstate.Remove("CssClass");
563                         viewstate.Remove("ForeColor");
564                         viewstate.Remove("Height");
565                         viewstate.Remove("Width");
566                         if (fontinfo != null) 
567                         {
568                                 fontinfo.Reset();
569                         }
570                         styles = Styles.None;
571                 }
572
573                 public override string ToString() 
574                 {
575                         return string.Empty;
576                 }
577                 #endregion      // Public Instance Methods
578
579                 #region Protected Instance Methods
580                 protected internal void LoadViewState(object state) 
581                 {
582                         viewstate.LoadViewState(state);
583
584                         // Update our style
585                         this.styles = Styles.None;
586
587                         if (viewstate["BackColor"] != null) 
588                         {
589                                 styles |= Styles.BackColor;
590                         }
591                         if (viewstate["BorderColor"] != null) 
592                         {
593                                 styles |= Styles.BorderColor;
594                         }
595                         if (viewstate["BorderStyle"] != null) 
596                         {
597                                 styles |= Styles.BorderStyle;
598                         }
599                         if (viewstate["BorderWidth"] != null) 
600                         {
601                                 styles |= Styles.BorderWidth;
602                         }
603                         if (viewstate["CssClass"] != null) 
604                         {
605                                 styles |= Styles.CssClass;
606                         }
607                         if (viewstate["ForeColor"] != null) 
608                         {
609                                 styles |= Styles.ForeColor;
610                         }
611                         if (viewstate["Height"] != null) 
612                         {
613                                 styles |= Styles.Height;
614                         }
615                         if (viewstate["Width"] != null) 
616                         {
617                                 styles |= Styles.Width;
618                         }
619                         if (fontinfo != null) {
620                                 fontinfo.LoadViewState();
621                         }
622
623                         LoadViewStateInternal();
624                 }
625
626                 internal virtual void LoadViewStateInternal()
627                 {
628                         // Override me
629                 }
630
631                 protected internal virtual object SaveViewState () 
632                 {
633                         if (styles != Styles.None) 
634                         {
635                                 return viewstate.SaveViewState();
636                         }
637                         return null;
638                 }
639
640                 [MonoTODO]
641                 protected internal virtual void SetBit( int bit ) 
642                 {
643                         throw new NotImplementedException();
644                 }
645
646                 protected internal virtual void TrackViewState() 
647                 {
648                         tracking = true;
649                         viewstate.TrackViewState();
650                 }
651                 #endregion      // Protected Instance Methods
652
653                 #region IStateManager Properties & Methods
654                 void IStateManager.LoadViewState(object state) 
655                 {
656                         LoadViewState(state);
657                 }
658
659                 object IStateManager.SaveViewState() 
660                 {
661                         return SaveViewState();
662                 }
663
664                 void IStateManager.TrackViewState() 
665                 {
666                         TrackViewState();
667                 }
668
669                 bool IStateManager.IsTrackingViewState 
670                 {
671                         get 
672                         {
673                                 return this.IsTrackingViewState;
674                         }
675                 }
676                 #endregion      // IStateManager Properties & Methods
677
678                 #region REMOVE ME
679                 internal static int BORDERWIDTH = 0xeadbeef;
680                 internal static int FORECOLOR   = 0xeadbeef;
681
682                 [Obsolete ("This method will be removed in Fresh")]
683                 internal bool IsSet(int blah) 
684                 {
685                         if (blah == BORDERWIDTH)
686                                 return ((styles & Styles.BorderWidth) != 0);
687
688                         if (blah == FORECOLOR)
689                                 return ((styles & Styles.ForeColor) != 0);
690
691                         return false;
692                 }
693
694                 [Obsolete ("This method will be removed in Fresh")]
695                 internal void Set(int blah) 
696                 {
697                 }
698                 #endregion      // REMOVE ME
699
700 #if NET_2_0
701                 protected virtual void FillStyleAttributes (CssStyleCollection attributes, IUrlResolutionService urlResolver)
702                 {
703                         FillStyleAttributes (attributes);
704                 }
705
706                 internal void SetRegisteredCssClass (string name)
707                 {
708                         registered_class = name;
709                 }
710
711                 public CssStyleCollection GetStyleAttributes (IUrlResolutionService resolver)
712                 {
713                         CssStyleCollection col = new CssStyleCollection ();
714                         FillStyleAttributes (col, resolver);
715                         return col;
716                 }
717
718                 [MonoTODO]
719                 public string RegisteredCssClass {
720                         get {
721                                 return registered_class;
722                         }
723                 }
724
725                 internal virtual void CopyTextStylesFrom (Style source)
726                 {
727                         // Need to ask lluis if we need fonts, too
728                         if ((styles & Styles.ForeColor) != 0) {
729                                 ForeColor = source.ForeColor;
730                         }
731                         if ((styles & Styles.BackColor) != 0) {
732                                 BackColor = source.BackColor;
733                         }
734                 }
735
736                 public void SetDirty ()
737                 {
738                         if (viewstate != null)
739                                 viewstate.SetDirty ();
740                 }
741
742                 public static bool IsStyleEmpty (Style s)
743                 {
744                         if (s == null)
745                                 return true;
746                         return s.IsEmpty;
747                 }
748
749 #endif
750         }
751 }