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