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