[bcl] Enable tests for the monodroid profile.
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / SiteMapPath.cs
1 //
2 // System.Web.UI.WebControls.SiteMapPath.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
29 //
30
31
32 using System;
33 using System.Collections;
34 using System.ComponentModel;
35 using System.Web.UI.HtmlControls;
36
37 namespace System.Web.UI.WebControls
38 {
39         [Designer ("System.Web.UI.Design.WebControls.SiteMapPathDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
40         public class SiteMapPath: CompositeControl
41         {
42                 SiteMapProvider provider;
43                 
44                 Style currentNodeStyle;
45                 Style nodeStyle;
46                 Style pathSeparatorStyle;
47                 Style rootNodeStyle;
48                 
49                 ITemplate currentNodeTemplate;
50                 ITemplate nodeTemplate;
51                 ITemplate pathSeparatorTemplate;
52                 ITemplate rootNodeTemplate;
53
54                 static readonly object ItemCreatedEvent = new object();
55                 static readonly object ItemDataBoundEvent = new object();
56                 
57                 public event SiteMapNodeItemEventHandler ItemCreated {
58                         add { Events.AddHandler (ItemCreatedEvent, value); }
59                         remove { Events.RemoveHandler (ItemCreatedEvent, value); }
60                 }
61                 
62                 public event SiteMapNodeItemEventHandler ItemDataBound {
63                         add { Events.AddHandler (ItemDataBoundEvent, value); }
64                         remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
65                 }
66                 
67                 protected virtual void OnItemCreated (SiteMapNodeItemEventArgs e)
68                 {
69                         if (Events != null) {
70                                 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemCreatedEvent];
71                                 if (eh != null) eh (this, e);
72                         }
73                 }
74                 
75                 protected virtual void OnItemDataBound (SiteMapNodeItemEventArgs e)
76                 {
77                         if (Events != null) {
78                                 SiteMapNodeItemEventHandler eh = (SiteMapNodeItemEventHandler) Events [ItemDataBoundEvent];
79                                 if (eh != null) eh (this, e);
80                         }
81                 }
82                 
83                 [DefaultValueAttribute (null)]
84                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
85                 [NotifyParentPropertyAttribute (true)]
86                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
87                 public Style CurrentNodeStyle {
88                         get {
89                                 if (currentNodeStyle == null) {
90                                         currentNodeStyle = new Style ();
91                                         if (IsTrackingViewState)
92                                                 ((IStateManager)currentNodeStyle).TrackViewState ();
93                                 }
94                                 return currentNodeStyle;
95                         }
96                 }
97         
98                 [DefaultValue (null)]
99                 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
100                 [PersistenceMode (PersistenceMode.InnerProperty)]
101                 [Browsable (false)]
102                 public virtual ITemplate CurrentNodeTemplate {
103                         get { return currentNodeTemplate; }
104                         set { currentNodeTemplate = value; UpdateControls (); }
105                 }
106                 
107                 [DefaultValueAttribute (null)]
108                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
109                 [NotifyParentPropertyAttribute (true)]
110                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
111                 public Style NodeStyle {
112                         get {
113                                 if (nodeStyle == null) {
114                                         nodeStyle = new Style ();
115                                         if (IsTrackingViewState)
116                                                 ((IStateManager)nodeStyle).TrackViewState ();
117                                 }
118                                 return nodeStyle;
119                         }
120                 }
121         
122                 [DefaultValue (null)]
123                 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
124                 [PersistenceMode (PersistenceMode.InnerProperty)]
125                 [Browsable (false)]
126                 public virtual ITemplate NodeTemplate {
127                         get { return nodeTemplate; }
128                         set { nodeTemplate = value; UpdateControls (); }
129                 }
130                 
131                 [DefaultValueAttribute (-1)]
132                 [ThemeableAttribute (false)]
133                 public virtual int ParentLevelsDisplayed {
134                         get { return ViewState.GetInt ("ParentLevelsDisplayed", -1); }
135                         set {
136                                 if (value < -1) throw new ArgumentOutOfRangeException ("value");
137                                 ViewState ["ParentLevelsDisplayed"] = value;
138                                 UpdateControls ();
139                         }
140                 }
141                 
142                 [DefaultValueAttribute (PathDirection.RootToCurrent)]
143                 public virtual PathDirection PathDirection {
144                         get { return (PathDirection)ViewState.GetInt ("PathDirection", (int)PathDirection.RootToCurrent); }
145                         set {
146                                 if (value != PathDirection.RootToCurrent && value != PathDirection.CurrentToRoot)
147                                         throw new ArgumentOutOfRangeException ("value");
148                                 ViewState ["PathDirection"] = value;
149                                 UpdateControls ();
150                         }
151                 }
152                 
153                 [DefaultValueAttribute (" > ")]
154                 [LocalizableAttribute (true)]
155                 public virtual string PathSeparator {
156                         get { return ViewState.GetString ("PathSeparator", " > "); }
157                         set {
158                                 ViewState ["PathSeparator"] = value;
159                                 UpdateControls ();
160                         }
161                 }
162                 
163                 [DefaultValueAttribute (null)]
164                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
165                 [NotifyParentPropertyAttribute (true)]
166                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
167                 public Style PathSeparatorStyle {
168                         get {
169                                 if (pathSeparatorStyle == null) {
170                                         pathSeparatorStyle = new Style ();
171                                         if (IsTrackingViewState)
172                                                 ((IStateManager)pathSeparatorStyle).TrackViewState ();
173                                 }
174                                 return pathSeparatorStyle;
175                         }
176                 }
177         
178                 [DefaultValue (null)]
179                 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
180                 [PersistenceMode (PersistenceMode.InnerProperty)]
181                 [Browsable (false)]
182                 public virtual ITemplate PathSeparatorTemplate {
183                         get { return pathSeparatorTemplate; }
184                         set { pathSeparatorTemplate = value; UpdateControls (); }
185                 }
186                 
187                 [BrowsableAttribute (false)]
188                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
189                 public SiteMapProvider Provider {
190                         get {
191                                 if (provider == null) {
192                                         if (this.SiteMapProvider.Length == 0) {
193                                                 provider = SiteMap.Provider;
194                                                 if (provider == null)
195                                                         throw new HttpException ("There is no default provider configured for the site.");
196                                         } else {
197                                                 provider = SiteMap.Providers [this.SiteMapProvider];
198                                                 if (provider == null)
199                                                         throw new HttpException ("SiteMap provider '" + this.SiteMapProvider + "' not found.");
200                                         }
201                                 }
202                                 return provider;
203                         }
204                         set {
205                                 provider = value;
206                                 UpdateControls ();
207                         }
208                 }
209                 
210                 [DefaultValueAttribute (false)]
211                 public virtual bool RenderCurrentNodeAsLink {
212                         get { return ViewState.GetBool ("RenderCurrentNodeAsLink", false); }
213                         set {
214                                 ViewState ["RenderCurrentNodeAsLink"] = value;
215                                 UpdateControls ();
216                         }
217                 }
218                 
219                 [DefaultValueAttribute (null)]
220                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
221                 [NotifyParentPropertyAttribute (true)]
222                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
223                 public Style RootNodeStyle {
224                         get {
225                                 if (rootNodeStyle == null) {
226                                         rootNodeStyle = new Style ();
227                                         if (IsTrackingViewState)
228                                                 ((IStateManager)rootNodeStyle).TrackViewState ();
229                                 }
230                                 return rootNodeStyle;
231                         }
232                 }
233         
234                 [DefaultValue (null)]
235                 [TemplateContainer (typeof(SiteMapNodeItem), BindingDirection.OneWay)]
236                 [PersistenceMode (PersistenceMode.InnerProperty)]
237                 [Browsable (false)]
238                 public virtual ITemplate RootNodeTemplate {
239                         get { return rootNodeTemplate; }
240                         set { rootNodeTemplate = value; UpdateControls (); }
241                 }
242                 
243                 [DefaultValueAttribute (true)]
244                 [ThemeableAttribute (false)]
245                 public virtual bool ShowToolTips {
246                         get { return ViewState.GetBool ("ShowToolTips", true); }
247                         set {
248                                 ViewState ["ShowToolTips"] = value;
249                                 UpdateControls ();
250                         }
251                 }
252                 
253                 [DefaultValueAttribute ("")]
254                 [ThemeableAttribute (false)]
255                 public virtual string SiteMapProvider {
256                         get { return ViewState.GetString ("SiteMapProvider", ""); }
257                         set {
258                                 ViewState ["SiteMapProvider"] = value;
259                                 UpdateControls ();
260                         }
261                 }
262
263                 [Localizable (true)]
264                 public virtual string SkipLinkText 
265                 {
266                         get { return ViewState.GetString ("SkipLinkText", "Skip Navigation Links"); }
267                         set { ViewState["SkipLinkText"] = value; }
268                 }
269                 
270                 
271                 void UpdateControls ()
272                 {
273                         ChildControlsCreated = false;
274                 }
275
276                 public override void DataBind ()
277                 {
278                         base.DataBind ();
279
280                         /* the child controls get bound in
281                          * base.DataBind */
282                         foreach (Control c in Controls) {
283                                 if (c is SiteMapNodeItem) {
284                                         SiteMapNodeItem it = (SiteMapNodeItem)c;
285                                         OnItemDataBound (new SiteMapNodeItemEventArgs (it));
286                                 }
287                         }
288                 }
289                 
290                 protected internal override void CreateChildControls ()
291                 {
292                         Controls.Clear ();
293                         CreateControlHierarchy ();
294                         DataBind ();
295                 }
296
297                 protected virtual void CreateControlHierarchy ()
298                 {
299                         ArrayList nodes = new ArrayList ();
300                         SiteMapNode node = Provider.CurrentNode;
301                         if (node == null) return;
302                         
303                         int levels = ParentLevelsDisplayed != -1 ? ParentLevelsDisplayed + 1 : int.MaxValue;
304                         
305                         while (node != null && levels > 0) {
306                                 if (nodes.Count > 0) {
307                                         SiteMapNodeItem sep = new SiteMapNodeItem (nodes.Count, SiteMapNodeItemType.PathSeparator);
308                                         InitializeItem (sep);
309                                         SiteMapNodeItemEventArgs sargs = new SiteMapNodeItemEventArgs (sep);
310                                         OnItemCreated (sargs);
311                                         nodes.Add (sep);
312                                 }
313
314                                 SiteMapNodeItemType nt;
315                                 if (nodes.Count == 0)
316                                         nt = SiteMapNodeItemType.Current;
317                                 else if (node.ParentNode == null)
318                                         nt = SiteMapNodeItemType.Root;
319                                 else
320                                         nt = SiteMapNodeItemType.Parent;
321                                         
322                                 SiteMapNodeItem it = new SiteMapNodeItem (nodes.Count, nt);
323                                 it.SiteMapNode = node;
324                                 InitializeItem (it);
325                                 
326                                 SiteMapNodeItemEventArgs args = new SiteMapNodeItemEventArgs (it);
327                                 OnItemCreated (args);
328                                 
329                                 nodes.Add (it);
330                                 node = node.ParentNode;
331                                 levels--;
332                         }
333                         
334                         if (PathDirection == PathDirection.RootToCurrent) {
335                                 for (int n=nodes.Count - 1; n>=0; n--)
336                                         Controls.Add ((Control)nodes[n]);
337                         } else {
338                                 for (int n=0; n<nodes.Count; n++)
339                                         Controls.Add ((Control)nodes[n]);
340                         }
341                 }
342                 
343                 protected virtual void InitializeItem (SiteMapNodeItem item)
344                 {
345                         switch (item.ItemType) {
346                                 case SiteMapNodeItemType.Root:
347                                         if (RootNodeTemplate != null) {
348                                                 item.ApplyStyle (NodeStyle);
349                                                 item.ApplyStyle (RootNodeStyle);
350                                                 RootNodeTemplate.InstantiateIn (item);
351                                         }
352                                         else if (NodeTemplate != null) {
353                                                 item.ApplyStyle (NodeStyle);
354                                                 item.ApplyStyle (RootNodeStyle);
355                                                 NodeTemplate.InstantiateIn (item);
356                                         }
357                                         else {
358                                                 WebControl c = CreateHyperLink (item);
359                                                 c.ApplyStyle (NodeStyle);
360                                                 c.ApplyStyle (RootNodeStyle);
361                                                 item.Controls.Add (c);
362                                         }
363                                         break;
364
365                                 case SiteMapNodeItemType.Current:
366                                         if (CurrentNodeTemplate != null) {
367                                                 item.ApplyStyle (NodeStyle);
368                                                 item.ApplyStyle (CurrentNodeStyle);
369                                                 CurrentNodeTemplate.InstantiateIn (item);
370                                         }
371                                         else if (NodeTemplate != null) {
372                                                 item.ApplyStyle (NodeStyle);
373                                                 item.ApplyStyle (CurrentNodeStyle);
374                                                 NodeTemplate.InstantiateIn (item);
375                                         } else if (RenderCurrentNodeAsLink) {
376                                                 HyperLink c = CreateHyperLink (item);
377                                                 c.ApplyStyle (NodeStyle);
378                                                 c.ApplyStyle (CurrentNodeStyle);
379                                                 item.Controls.Add (c);
380                                         } else {
381                                                 Literal c = CreateLiteral (item);
382                                                 item.ApplyStyle (NodeStyle);
383                                                 item.ApplyStyle (CurrentNodeStyle);
384                                                 item.Controls.Add (c);
385                                         }
386                                         break;
387                                         
388                                 case SiteMapNodeItemType.Parent:
389                                         if (NodeTemplate != null) {
390                                                 item.ApplyStyle (NodeStyle);
391                                                 NodeTemplate.InstantiateIn (item);
392                                         }
393                                         else {
394                                                 WebControl c = CreateHyperLink (item);
395                                                 c.ApplyStyle (NodeStyle);
396                                                 item.Controls.Add (c);
397                                         }
398                                         break;
399                                         
400                                 case SiteMapNodeItemType.PathSeparator:
401                                         if (PathSeparatorTemplate != null) {
402                                                 item.ApplyStyle (PathSeparatorStyle);
403                                                 PathSeparatorTemplate.InstantiateIn (item);
404                                         } else {
405                                                 Literal h = new Literal ();
406                                                 h.Text = HttpUtility.HtmlEncode (PathSeparator);
407                                                 item.ApplyStyle (PathSeparatorStyle);
408                                                 item.Controls.Add (h);
409                                         }
410                                         break;
411                         }
412                 }
413                 
414                 HyperLink CreateHyperLink (SiteMapNodeItem item)
415                 {
416                         HyperLink h = new HyperLink ();
417                         h.Text = item.SiteMapNode.Title;
418                         h.NavigateUrl = item.SiteMapNode.Url;
419                         if (ShowToolTips)
420                                 h.ToolTip = item.SiteMapNode.Description;
421                         return h;
422                 }
423
424                 Literal CreateLiteral (SiteMapNodeItem item)
425                 {
426                         Literal h = new Literal ();
427                         h.Text = item.SiteMapNode.Title;
428                         return h;
429                 }
430                 
431                 protected override void LoadViewState (object savedState)
432                 {
433                         if (savedState == null) {
434                                 base.LoadViewState (null);
435                                 return;
436                         }
437                         
438                         object[] states = (object[]) savedState;
439                         base.LoadViewState (states [0]);
440                         
441                         if (states[1] != null) ((IStateManager)CurrentNodeStyle).LoadViewState (states[1]);
442                         if (states[2] != null) ((IStateManager)NodeStyle).LoadViewState (states[2]);
443                         if (states[3] != null) ((IStateManager)PathSeparatorStyle).LoadViewState (states[3]);
444                         if (states[4] != null) ((IStateManager)RootNodeStyle).LoadViewState (states[4]);
445                 }
446
447                 [MonoTODO ("why override?")]
448                 protected override void OnDataBinding (EventArgs e)
449                 {
450                         base.OnDataBinding (e);
451                 }
452                 
453                 [MonoTODO ("why override?")]
454                 protected internal override void Render (HtmlTextWriter w)
455                 {
456                         base.Render (w);
457                 }
458
459                 protected internal override void RenderContents (HtmlTextWriter w)
460                 {
461                         string skip_id = ClientID + "_SkipLink";
462                         string altText = SkipLinkText;
463                         bool needAnchor = !String.IsNullOrEmpty (altText);
464                         
465                         if (needAnchor) {
466                                 // Anchor start
467                                 w.AddAttribute (HtmlTextWriterAttribute.Href, "#" + skip_id);
468                                 w.RenderBeginTag (HtmlTextWriterTag.A);
469
470                                 // Image
471                                 w.AddAttribute (HtmlTextWriterAttribute.Alt, altText);
472                                 w.AddAttribute (HtmlTextWriterAttribute.Height, "0");
473                                 w.AddAttribute (HtmlTextWriterAttribute.Width, "0");
474                                 w.AddAttribute (HtmlTextWriterAttribute.Src, Page.ClientScript.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif"));
475                                 w.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0px");
476                                 w.RenderBeginTag (HtmlTextWriterTag.Img);
477                                 w.RenderEndTag ();
478
479                                 w.RenderEndTag ();
480                         }
481
482                         base.RenderContents (w);
483
484                         if (needAnchor) {
485                                  w.AddAttribute(HtmlTextWriterAttribute.Id, skip_id);
486                                  w.RenderBeginTag(HtmlTextWriterTag.A);
487                                  w.RenderEndTag();
488                         }
489                 }
490                 
491                 protected override object SaveViewState ()
492                 {
493                         object[] state = new object [5];
494                         state [0] = base.SaveViewState ();
495                         
496                         if (currentNodeStyle != null) state [1] = ((IStateManager)currentNodeStyle).SaveViewState ();
497                         if (nodeStyle != null) state [2] = ((IStateManager)nodeStyle).SaveViewState ();
498                         if (pathSeparatorStyle != null) state [3] = ((IStateManager)pathSeparatorStyle).SaveViewState ();
499                         if (rootNodeStyle != null) state [4] = ((IStateManager)rootNodeStyle).SaveViewState ();
500                         
501                         for (int n=0; n<state.Length; n++)
502                                 if (state [n] != null) return state;
503                         return null;
504                 }
505                 
506                 protected override void TrackViewState ()
507                 {
508                         base.TrackViewState();
509                         if (currentNodeStyle != null) ((IStateManager)currentNodeStyle).TrackViewState();
510                         if (nodeStyle != null) ((IStateManager)nodeStyle).TrackViewState();
511                         if (pathSeparatorStyle != null) ((IStateManager)pathSeparatorStyle).TrackViewState();
512                         if (rootNodeStyle != null) ((IStateManager)rootNodeStyle).TrackViewState();
513                 }
514         }
515 }
516