2005-02-02 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / Menu.cs
1 //
2 // System.Web.UI.WebControls.Menu.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 #if NET_2_0
32
33 using System;
34 using System.Collections;
35 using System.Text;
36 using System.ComponentModel;
37 using System.Web.UI;
38 using System.Web.Handlers;
39 using System.Collections.Specialized;
40 using System.IO;
41
42 namespace System.Web.UI.WebControls
43 {
44         [DefaultEvent ("MenuItemClick")]
45         [ControlValueProperty ("SelectedValue")]
46         [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, System.Design, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.IDesigner")]
47         public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
48         {
49                 MenuItemStyle dynamicMenuItemStyle;
50                 SubMenuStyle dynamicMenuStyle;
51                 MenuItemStyle dynamicSelectedStyle;
52                 MenuItemStyle staticMenuItemStyle;
53                 SubMenuStyle staticMenuStyle;
54                 MenuItemStyle staticSelectedStyle;
55                 Style staticHoverStyle;
56                 Style dynamicHoverStyle;
57
58                 MenuItemStyleCollection levelMenuItemStyles;
59                 MenuItemStyleCollection levelSelectedStyles;
60                 ITemplate staticItemTemplate;
61                 ITemplate dynamicItemTemplate;
62                 
63                 MenuItemCollection items;
64                 MenuItemBindingCollection dataBindings;
65                 MenuItem selectedItem;
66                 string selectedItemPath;
67                 Hashtable bindings;
68                 ArrayList dynamicMenus;
69                 
70                 private static readonly object MenuItemClickEvent = new object();
71                 
72                 public event MenuEventHandler MenuItemClick {
73                         add { Events.AddHandler (MenuItemClickEvent, value); }
74                         remove { Events.RemoveHandler (MenuItemClickEvent, value); }
75                 }
76                 
77                 protected virtual void OnMenuItemClick (MenuEventArgs e)
78                 {
79                         if (Events != null) {
80                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
81                                 if (eh != null) eh (this, e);
82                         }
83                 }
84
85                 [PersistenceMode (PersistenceMode.InnerProperty)]
86                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
87                 [Editor ("System.Web.UI.Design.MenuItemBindingsEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
88                 public virtual MenuItemBindingCollection DataBindings {
89                         get {
90                                 if (dataBindings == null) {
91                                         dataBindings = new MenuItemBindingCollection ();
92                                         if (IsTrackingViewState)
93                                                 ((IStateManager)dataBindings).TrackViewState();
94                                 }
95                                 return dataBindings;
96                         }
97                 }
98
99                 [DefaultValue (500)]
100                 [ThemeableAttribute (false)]
101                 public virtual int DisappearAfter {
102                         get {
103                                 object o = ViewState ["DisappearAfter"];
104                                 if (o != null) return (int)o;
105                                 return 500;
106                         }
107                         set {
108                                 ViewState["DisappearAfter"] = value;
109                         }
110                 }
111
112                 [ThemeableAttribute (false)]
113                 [DefaultValue ("")]
114                 [UrlProperty]
115                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
116                 public virtual string DynamicBottomSeparatorImageUrl {
117                         get {
118                                 object o = ViewState ["dbsiu"];
119                                 if (o != null) return (string)o;
120                                 return "";
121                         }
122                         set {
123                                 ViewState["dbsiu"] = value;
124                         }
125                 }
126
127                 [DefaultValue ("")]
128                 [UrlProperty]
129                 [WebCategory ("Appearance")]
130                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
131                 public virtual string DynamicTopSeparatorImageUrl {
132                         get {
133                                 object o = ViewState ["dtsiu"];
134                                 if (o != null) return (string)o;
135                                 return "";
136                         }
137                         set {
138                                 ViewState["dtsiu"] = value;
139                         }
140                 }
141
142                 [DefaultValue ("")]
143                 [UrlProperty]
144                 [WebCategory ("Appearance")]
145                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
146                 public virtual string StaticBottomSeparatorImageUrl {
147                         get {
148                                 object o = ViewState ["sbsiu"];
149                                 if (o != null) return (string)o;
150                                 return "";
151                         }
152                         set {
153                                 ViewState["sbsiu"] = value;
154                         }
155                 }
156
157                 [DefaultValue ("")]
158                 [UrlProperty]
159                 [WebCategory ("Appearance")]
160                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
161                 public virtual string StaticTopSeparatorImageUrl {
162                         get {
163                                 object o = ViewState ["stsiu"];
164                                 if (o != null) return (string)o;
165                                 return "";
166                         }
167                         set {
168                                 ViewState["stsiu"] = value;
169                         }
170                 }
171
172                 [DefaultValue (Orientation.Vertical)]
173                 public virtual Orientation Orientation {
174                         get {
175                                 object o = ViewState ["Orientation"];
176                                 if (o != null) return (Orientation) o;
177                                 return Orientation.Vertical;
178                         }
179                         set {
180                                 ViewState["Orientation"] = value;
181                         }
182                 }
183
184                 [DefaultValue (1)]
185                 [ThemeableAttribute (false)]
186                 public virtual int StaticDisplayLevels {
187                         get {
188                                 object o = ViewState ["StaticDisplayLevels"];
189                                 if (o != null) return (int)o;
190                                 return 1;
191                         }
192                         set {
193                                 if (value < 1) throw new ArgumentOutOfRangeException ();
194                                 ViewState["StaticDisplayLevels"] = value;
195                         }
196                 }
197
198                 [DefaultValue ("16px")]
199                 [ThemeableAttribute (false)]
200                 public Unit StaticSubMenuIndent {
201                         get {
202                                 object o = ViewState ["StaticSubMenuIndent"];
203                                 if (o != null) return (Unit)o;
204                                 return new Unit (16);
205                         }
206                         set {
207                                 ViewState["StaticSubMenuIndent"] = value;
208                         }
209                 }
210
211                 [ThemeableAttribute (false)]
212                 [DefaultValue (3)]
213                 public virtual int MaximumDynamicDisplayLevels {
214                         get {
215                                 object o = ViewState ["MaximumDynamicDisplayLevels"];
216                                 if (o != null) return (int)o;
217                                 return 3;
218                         }
219                         set {
220                                 if (value < 0) throw new ArgumentOutOfRangeException ();
221                                 ViewState["MaximumDynamicDisplayLevels"] = value;
222                         }
223                 }
224
225                 [DefaultValue (0)]
226                 public virtual int DynamicVerticalOffset {
227                         get {
228                                 object o = ViewState ["DynamicVerticalOffset"];
229                                 if (o != null) return (int)o;
230                                 return 0;
231                         }
232                         set {
233                                 ViewState["DynamicVerticalOffset"] = value;
234                         }
235                 }
236
237                 [DefaultValue (0)]
238                 public virtual int DynamicHorizontalOffset {
239                         get {
240                                 object o = ViewState ["DynamicHorizontalOffset"];
241                                 if (o != null) return (int)o;
242                                 return 0;
243                         }
244                         set {
245                                 ViewState["DynamicHorizontalOffset"] = value;
246                         }
247                 }
248
249                 [DefaultValue (true)]
250                 public virtual bool DynamicEnableDefaultPopOutImage {
251                         get {
252                                 object o = ViewState ["dedpoi"];
253                                 if (o != null) return (bool)o;
254                                 return true;
255                         }
256                         set {
257                                 ViewState["dedpoi"] = value;
258                         }
259                 }
260
261                 [DefaultValue (true)]
262                 public virtual bool StaticEnableDefaultPopOutImage {
263                         get {
264                                 object o = ViewState ["sedpoi"];
265                                 if (o != null) return (bool)o;
266                                 return true;
267                         }
268                         set {
269                                 ViewState["sedpoi"] = value;
270                         }
271                 }
272
273                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
274                 [PersistenceMode (PersistenceMode.InnerProperty)]
275                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
276                 public virtual MenuItemCollection Items {
277                         get {
278                                 if (items == null) {
279                                         items = new MenuItemCollection (this);
280                                         if (IsTrackingViewState)
281                                                 ((IStateManager)items).TrackViewState();
282                                 }
283                                 return items;
284                         }
285                 }
286
287                 [DefaultValue ('/')]
288                 public virtual char PathSeparator {
289                         get {
290                                 object o = ViewState ["PathSeparator"];
291                                 if(o != null) return (char)o;
292                                 return '/';
293                         }
294                         set {
295                                 ViewState ["PathSeparator"] = value;
296                         }
297                 }
298
299                 [DefaultValue (false)]
300                 public virtual bool ItemWrap {
301                         get {
302                                 object o = ViewState ["ItemWrap"];
303                                 if(o != null) return (bool)o;
304                                 return false;
305                         }
306                         set {
307                                 ViewState ["ItemWrap"] = value;
308                         }
309                 }
310
311                 [PersistenceMode (PersistenceMode.InnerProperty)]
312                 [NotifyParentProperty (true)]
313                 [DefaultValue (null)]
314                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
315                 public virtual MenuItemStyle DynamicMenuItemStyle {
316                         get {
317                                 if (dynamicMenuItemStyle == null) {
318                                         dynamicMenuItemStyle = new MenuItemStyle ();
319                                         if (IsTrackingViewState)
320                                                 dynamicMenuItemStyle.TrackViewState();
321                                 }
322                                 return dynamicMenuItemStyle;
323                         }
324                 }
325                 
326                 [PersistenceMode (PersistenceMode.InnerProperty)]
327                 [NotifyParentProperty (true)]
328                 [DefaultValue (null)]
329                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
330                 public virtual MenuItemStyle DynamicSelectedStyle {
331                         get {
332                                 if (dynamicSelectedStyle == null) {
333                                         dynamicSelectedStyle = new MenuItemStyle ();
334                                         if (IsTrackingViewState)
335                                                 dynamicSelectedStyle.TrackViewState();
336                                 }
337                                 return dynamicSelectedStyle;
338                         }
339                 }
340                 
341                 [PersistenceMode (PersistenceMode.InnerProperty)]
342                 [NotifyParentProperty (true)]
343                 [DefaultValue (null)]
344                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
345                 public virtual SubMenuStyle DynamicMenuStyle {
346                         get {
347                                 if (dynamicMenuStyle == null) {
348                                         dynamicMenuStyle = new SubMenuStyle ();
349                                         if (IsTrackingViewState)
350                                                 dynamicMenuStyle.TrackViewState();
351                                 }
352                                 return dynamicMenuStyle;
353                         }
354                 }
355                 
356                 [PersistenceMode (PersistenceMode.InnerProperty)]
357                 [NotifyParentProperty (true)]
358                 [DefaultValue (null)]
359                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
360                 public virtual MenuItemStyle StaticMenuItemStyle {
361                         get {
362                                 if (staticMenuItemStyle == null) {
363                                         staticMenuItemStyle = new MenuItemStyle ();
364                                         if (IsTrackingViewState)
365                                                 staticMenuItemStyle.TrackViewState();
366                                 }
367                                 return staticMenuItemStyle;
368                         }
369                 }
370                 
371                 [PersistenceMode (PersistenceMode.InnerProperty)]
372                 [NotifyParentProperty (true)]
373                 [DefaultValue (null)]
374                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
375                 public virtual MenuItemStyle StaticSelectedStyle {
376                         get {
377                                 if (staticSelectedStyle == null) {
378                                         staticSelectedStyle = new MenuItemStyle ();
379                                         if (IsTrackingViewState)
380                                                 staticSelectedStyle.TrackViewState();
381                                 }
382                                 return staticSelectedStyle;
383                         }
384                 }
385                 
386                 [PersistenceMode (PersistenceMode.InnerProperty)]
387                 [NotifyParentProperty (true)]
388                 [DefaultValue (null)]
389                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
390                 public virtual SubMenuStyle StaticMenuStyle {
391                         get {
392                                 if (staticMenuStyle == null) {
393                                         staticMenuStyle = new SubMenuStyle ();
394                                         if (IsTrackingViewState)
395                                                 staticMenuStyle.TrackViewState();
396                                 }
397                                 return staticMenuStyle;
398                         }
399                 }
400
401                 [PersistenceMode (PersistenceMode.InnerProperty)]
402                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
403             [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor,System.Design, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
404                 public virtual MenuItemStyleCollection LevelMenuItemStyles {
405                         get {
406                                 if (levelMenuItemStyles == null) {
407                                         levelMenuItemStyles = new MenuItemStyleCollection ();
408                                         if (IsTrackingViewState)
409                                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
410                                 }
411                                 return levelMenuItemStyles;
412                         }
413                 }
414
415                 [PersistenceMode (PersistenceMode.InnerProperty)]
416                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
417                 public virtual MenuItemStyleCollection LevelSelectedStyles {
418                         get {
419                                 if (levelSelectedStyles == null) {
420                                         levelSelectedStyles = new MenuItemStyleCollection ();
421                                         if (IsTrackingViewState)
422                                                 ((IStateManager)levelSelectedStyles).TrackViewState();
423                                 }
424                                 return levelSelectedStyles;
425                         }
426                 }
427
428                 [PersistenceMode (PersistenceMode.InnerProperty)]
429                 [NotifyParentProperty (true)]
430                 [DefaultValue (null)]
431                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
432                 public virtual Style DynamicHoverStyle {
433                         get {
434                                 if (dynamicHoverStyle == null) {
435                                         dynamicHoverStyle = new Style ();
436                                         if (IsTrackingViewState)
437                                                 dynamicHoverStyle.TrackViewState();
438                                 }
439                                 return dynamicHoverStyle;
440                         }
441                 }
442                 
443                 [PersistenceMode (PersistenceMode.InnerProperty)]
444                 [NotifyParentProperty (true)]
445                 [DefaultValue (null)]
446                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
447                 public virtual Style StaticHoverStyle {
448                         get {
449                                 if (staticHoverStyle == null) {
450                                         staticHoverStyle = new Style ();
451                                         if (IsTrackingViewState)
452                                                 staticHoverStyle.TrackViewState();
453                                 }
454                                 return staticHoverStyle;
455                         }
456                 }
457                 
458                 [DefaultValue ("")]
459                 [UrlProperty]
460                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
461                 public virtual string ScrollDownImageUrl {
462                         get {
463                                 object o = ViewState ["sdiu"];
464                                 if (o != null) return (string)o;
465                                 return "";
466                         }
467                         set {
468                                 ViewState["sdiu"] = value;
469                         }
470                 }
471
472                 [DefaultValue ("")]
473                 [UrlProperty]
474                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
475                 public virtual string ScrollUpImageUrl {
476                         get {
477                                 object o = ViewState ["suiu"];
478                                 if (o != null) return (string)o;
479                                 return "";
480                         }
481                         set {
482                                 ViewState["suiu"] = value;
483                         }
484                 }
485
486                 [Localizable (true)]
487                 public virtual string ScrollDownText {
488                         get {
489                                 object o = ViewState ["ScrollDownText"];
490                                 if (o != null) return (string) o;
491                                 return "";
492                         }
493                         set {
494                                 ViewState["ScrollDownText"] = value;
495                         }
496                 }
497
498                 [Localizable (true)]
499                 public virtual string ScrollUpText {
500                         get {
501                                 object o = ViewState ["ScrollUpText"];
502                                 if (o != null) return (string) o;
503                                 return "";
504                         }
505                         set {
506                                 ViewState["ScrollUpText"] = value;
507                         }
508                 }
509
510                 [DefaultValue ("")]
511                 [UrlProperty]
512                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
513                 public virtual string DynamicPopOutImageUrl {
514                         get {
515                                 object o = ViewState ["dpoiu"];
516                                 if (o != null) return (string)o;
517                                 return "";
518                         }
519                         set {
520                                 ViewState["dpoiu"] = value;
521                         }
522                 }
523
524                 [DefaultValue ("")]
525                 [UrlProperty]
526                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
527                 public virtual string StaticPopOutImageUrl {
528                         get {
529                                 object o = ViewState ["spoiu"];
530                                 if (o != null) return (string)o;
531                                 return "";
532                         }
533                         set {
534                                 ViewState["spoiu"] = value;
535                         }
536                 }
537
538                 [DefaultValue ("")]
539                 public virtual string Target {
540                         get {
541                                 object o = ViewState ["Target"];
542                                 if (o != null) return (string) o;
543                                 return "";
544                         }
545                         set {
546                                 ViewState["Target"] = value;
547                         }
548                 }
549
550                 [DefaultValue (null)]
551                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
552                 [PersistenceMode (PersistenceMode.InnerProperty)]
553             [Browsable (false)]
554                 public ITemplate StaticItemTemplate {
555                         get { return staticItemTemplate; }
556                         set { staticItemTemplate = value; }
557                 }
558                 
559                 [DefaultValue (null)]
560                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
561                 [PersistenceMode (PersistenceMode.InnerProperty)]
562             [Browsable (false)]
563                 public ITemplate DynamicItemTemplate {
564                         get { return dynamicItemTemplate; }
565                         set { dynamicItemTemplate = value; }
566                 }
567                 
568                 [Browsable (false)]
569                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
570                 public MenuItem SelectedItem {
571                         get {
572                                 if (selectedItem == null && selectedItemPath != null) {
573                                         selectedItem = FindItemByPos (selectedItemPath);
574                                 }
575                                 
576                                 return selectedItem;
577                         }
578                 }
579
580                 [Browsable (false)]
581                 [DefaultValue ("")]
582                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
583                 public string SelectedValue {
584                         get { return selectedItem != null ? selectedItem.Value : null; }
585                 }
586
587                 internal void SetSelectedItem (MenuItem item)
588                 {
589                         if (selectedItem == item) return;
590                         selectedItem = item;
591                         selectedItemPath = item.Path;
592                 }
593                 
594                 public MenuItem FindItem (string valuePath)
595                 {
596                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
597                         string[] path = valuePath.Split (PathSeparator);
598                         int n = 0;
599                         MenuItemCollection col = Items;
600                         bool foundBranch = true;
601                         while (col.Count > 0 && foundBranch) {
602                                 foundBranch = false;
603                                 foreach (MenuItem item in col) {
604                                         if (item.Value == path [n]) {
605                                                 if (++n == path.Length) return item;
606                                                 col = item.ChildItems;
607                                                 foundBranch = true;
608                                                 break;
609                                         }
610                                 }
611                         }
612                         return null;
613                 }
614                 
615                 string GetBindingKey (string dataMember, int depth)
616                 {
617                         return dataMember + " " + depth;
618                 }
619                 
620                 internal MenuItemBinding FindBindingForItem (string type, int depth)
621                 {
622                         if (bindings == null) return null;
623
624                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
625                         if (bin != null) return bin;
626                         
627                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
628                         if (bin != null) return bin;
629                         
630                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
631                         if (bin != null) return bin;
632                         
633                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
634                         return bin;
635                 }
636                 
637                 protected internal override void PerformDataBinding ()
638                 {
639                         base.PerformDataBinding ();
640                         HierarchicalDataSourceView data = GetData ("");
641                         IHierarchicalEnumerable e = data.Select ();
642                         foreach (object obj in e) {
643                                 IHierarchyData hdata = e.GetHierarchyData (obj);
644                                 MenuItem item = new MenuItem ();
645                                 item.Bind (hdata);
646                                 Items.Add (item);
647                         }
648                 }
649                 
650                 public void RaisePostBackEvent (string eventArgument)
651                 {
652                         MenuItem item = FindItemByPos (eventArgument);
653                         if (item == null) return;
654                         item.Selected = true;
655                         OnMenuItemClick (new MenuEventArgs (item));
656                 }
657                 
658                 MenuItem FindItemByPos (string path)
659                 {
660                         string[] indexes = path.Split ('_');
661                         MenuItem item = null;
662                         
663                         foreach (string index in indexes) {
664                                 int i = int.Parse (index);
665                                 if (item == null) {
666                                         if (i >= Items.Count) return null;
667                                         item = Items [i];
668                                 } else {
669                                         if (i >= item.ChildItems.Count) return null;
670                                         item = item.ChildItems [i];
671                                 }
672                         }
673                         return item;
674                 }
675                 
676                 protected override HtmlTextWriterTag TagKey {
677                         get { return HtmlTextWriterTag.Table; }
678                 }
679                 
680                 protected override void TrackViewState()
681                 {
682                         EnsureDataBound ();
683                         
684                         base.TrackViewState();
685                         if (dataBindings != null) {
686                                 ((IStateManager)dataBindings).TrackViewState ();
687                         }
688                         if (items != null) {
689                                 ((IStateManager)items).TrackViewState();
690                         }
691                         if (dynamicMenuItemStyle != null)
692                                 dynamicMenuItemStyle.TrackViewState ();
693                         if (dynamicMenuStyle != null)
694                                 dynamicMenuStyle.TrackViewState ();
695                         if (levelMenuItemStyles != null)
696                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
697                         if (levelSelectedStyles != null)
698                                 ((IStateManager)levelSelectedStyles).TrackViewState();
699                         if (dynamicSelectedStyle != null)
700                                 dynamicSelectedStyle.TrackViewState();
701                         if (staticMenuItemStyle != null)
702                                 staticMenuItemStyle.TrackViewState ();
703                         if (staticMenuStyle != null)
704                                 staticMenuStyle.TrackViewState ();
705                         if (staticSelectedStyle != null)
706                                 staticSelectedStyle.TrackViewState();
707                         if (staticHoverStyle != null)
708                                 staticHoverStyle.TrackViewState();
709                         if (dynamicHoverStyle != null)
710                                 dynamicHoverStyle.TrackViewState();
711                 }
712
713                 protected override object SaveViewState()
714                 {
715                         object[] states = new object [13];
716                         states[0] = base.SaveViewState ();
717                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
718                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
719                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
720                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
721                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
722                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
723                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
724                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
725                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
726                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
727                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
728                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
729
730                         for (int i = states.Length - 1; i >= 0; i--) {
731                                 if (states [i] != null)
732                                         return states;
733                         }
734
735                         return null;
736                 }
737
738                 protected override void LoadViewState (object savedState)
739                 {
740                         if (savedState == null)
741                                 return;
742
743                         object [] states = (object []) savedState;
744                         base.LoadViewState (states[0]);
745                         
746                         if (states[1] != null)
747                                 ((IStateManager)dataBindings).LoadViewState(states[1]);
748                         if (states[2] != null)
749                                 ((IStateManager)Items).LoadViewState(states[2]);
750                         if (states[3] != null)
751                                 dynamicMenuItemStyle.LoadViewState (states[3]);
752                         if (states[4] != null)
753                                 dynamicMenuStyle.LoadViewState (states[4]);
754                         if (states[5] != null)
755                                 ((IStateManager)levelMenuItemStyles).LoadViewState(states[5]);
756                         if (states[6] != null)
757                                 ((IStateManager)levelSelectedStyles).LoadViewState(states[6]);
758                         if (states[7] != null)
759                                 dynamicSelectedStyle.LoadViewState (states[7]);
760                         if (states[8] != null)
761                                 staticMenuItemStyle.LoadViewState (states[8]);
762                         if (states[9] != null)
763                                 staticMenuStyle.LoadViewState (states[9]);
764                         if (states[10] != null)
765                                 staticSelectedStyle.LoadViewState (states[10]);
766                         if (states[11] != null)
767                                 staticHoverStyle.LoadViewState (states[11]);
768                         if (states[12] != null)
769                                 dynamicHoverStyle.LoadViewState (states[12]);
770                 }
771                 
772                 protected override void OnInit (EventArgs e)
773                 {
774                         Page.RegisterRequiresControlState (this);
775                         base.OnInit (e);
776                 }
777                 
778                 protected internal override void LoadControlState (object ob)
779                 {
780                         if (ob == null) return;
781                         object[] state = (object[]) ob;
782                         base.LoadControlState (state[0]);
783                         selectedItemPath = state[1] as string;
784                 }
785                 
786                 protected internal override object SaveControlState ()
787                 {
788                         object bstate = base.SaveControlState ();
789                         object mstate = selectedItemPath;
790                         
791                         if (bstate != null && mstate != null)
792                                 return new object[] { bstate, mstate };
793                         else
794                                 return null;
795                 }
796                 
797                 [MonoTODO]
798                 protected override void CreateChildControls ()
799                 {
800                         base.CreateChildControls ();
801                 }
802                 
803                 
804                 protected override void OnPreRender (EventArgs e)
805                 {
806                         base.OnPreRender (e);
807                         
808                         if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
809                                 string url = Page.GetWebResourceUrl (typeof(Menu), "Menu.js");
810                                 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
811                         }
812                         
813                         string cmenu = ClientID + "_data";
814                         string script = string.Format ("var {0} = new Object ();\n", cmenu);
815                         script += string.Format ("{0}.disappearAfter = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DisappearAfter));
816                         script += string.Format ("{0}.vertical = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
817                         if (DynamicHorizontalOffset != 0)
818                                 script += string.Format ("{0}.dho = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset));
819                         if (DynamicVerticalOffset != 0)
820                                 script += string.Format ("{0}.dvo = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset));
821                                 
822                         // The order in which styles are defined matters when more than one class
823                         // is assigned to an element
824                         
825                         if (dynamicMenuStyle != null)
826                                 RegisterItemStyle (dynamicMenuStyle);
827                         if (staticMenuStyle != null)
828                                 RegisterItemStyle (staticMenuStyle);
829                 
830                         if (staticMenuItemStyle != null)
831                                 RegisterItemStyle (staticMenuItemStyle);
832                         if (staticSelectedStyle != null)
833                                 RegisterItemStyle (staticSelectedStyle);
834
835                         if (dynamicMenuItemStyle != null)
836                                 RegisterItemStyle (dynamicMenuItemStyle);
837                         if (dynamicSelectedStyle != null)
838                                 RegisterItemStyle (dynamicSelectedStyle);
839
840                         if (levelMenuItemStyles != null)
841                                 foreach (Style style in levelMenuItemStyles)
842                                         RegisterItemStyle (style);
843
844                         if (levelSelectedStyles != null)
845                                 foreach (Style style in levelSelectedStyles)
846                                         RegisterItemStyle (style);
847                         
848                         if (dynamicHoverStyle != null)
849                                 RegisterItemStyle (dynamicHoverStyle);
850                         if (staticHoverStyle != null)
851                                 RegisterItemStyle (staticHoverStyle);
852
853                         if (staticHoverStyle != null)
854                                 script += string.Format ("{0}.staticHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass));
855                         if (dynamicHoverStyle != null)
856                                 script += string.Format ("{0}.dynamicHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass));
857                         
858                         Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
859
860                         if (dataBindings != null && dataBindings.Count > 0) {
861                                 bindings = new Hashtable ();
862                                 foreach (TreeNodeBinding bin in dataBindings) {
863                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
864                                         bindings [key] = bin;
865                                 }
866                         }
867                         else
868                                 bindings = null;
869                 }
870                 
871                 void RegisterItemStyle (Style baseStyle)
872                 {
873                         Page.Header.StyleSheet.RegisterStyle (baseStyle, this);
874                         Style ts = new Style ();
875                         ts.CopyTextStylesFrom (baseStyle);
876                         Page.Header.StyleSheet.CreateStyleRule (ts, "." + baseStyle.RegisteredCssClass + " A", this);
877                 }
878                 
879                 protected override void Render (HtmlTextWriter writer)
880                 {
881                         base.Render (writer);
882                 }
883                 
884                 protected override void AddAttributesToRender (HtmlTextWriter writer)
885                 {
886                         RenderMenuBeginTagAttributes (writer, false);
887                 }
888                 
889                 public override void RenderBeginTag (HtmlTextWriter writer)
890                 {
891                         base.RenderBeginTag (writer);
892                 }
893                 
894                 public override void RenderEndTag (HtmlTextWriter writer)
895                 {
896                         base.RenderEndTag (writer);
897                         
898                         // Render dynamic menus outside the main control tag
899                         for (int n=0; n<dynamicMenus.Count; n++) {
900                                 MenuItem item = (MenuItem) dynamicMenus [n];
901                                 RenderDynamicMenu (writer, item);
902                         }
903                         dynamicMenus = null;
904                 }
905                 
906                 protected override void RenderContents (HtmlTextWriter writer)
907                 {
908                         dynamicMenus = new ArrayList ();
909                         RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false);
910                 }
911                 
912                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
913                 {
914                         if (dynamicMenuStyle != null)
915                                 writer.AddAttribute ("class", dynamicMenuStyle.RegisteredCssClass);
916                         
917                         writer.AddStyleAttribute ("visibility", "hidden");
918                         writer.AddStyleAttribute ("position", "absolute");
919                         writer.AddStyleAttribute ("left", "0px");
920                         writer.AddStyleAttribute ("top", "0px");
921                         writer.AddAttribute ("id", GetItemClientId (item, "s"));
922                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
923
924                         // Up button
925                         writer.AddAttribute ("id", GetItemClientId (item, "cu"));
926                         writer.AddStyleAttribute ("display", "block");
927                         writer.AddStyleAttribute ("text-align", "center");
928                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
929                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
930                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
931                         
932                         string src = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.GetWebResourceUrl (typeof(Menu), "arrow_up.gif");
933                         writer.AddAttribute ("src", src);
934                         writer.AddAttribute ("alt", ScrollUpText);
935                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
936                         writer.RenderEndTag (); // IMG
937                         
938                         writer.RenderEndTag (); // DIV scroll button
939                 
940                         writer.AddAttribute ("id", GetItemClientId (item, "cb"));       // Scroll container
941                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
942                         writer.AddAttribute ("id", GetItemClientId (item, "cc"));       // Content
943                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
944                         
945                         RenderMenu (writer, item.ChildItems, true, true);
946                         
947                         writer.RenderEndTag (); // DIV Content
948                         writer.RenderEndTag (); // DIV Scroll container
949
950                         // Down button
951                         writer.AddAttribute ("id", GetItemClientId (item, "cd"));
952                         writer.AddStyleAttribute ("display", "block");
953                         writer.AddStyleAttribute ("text-align", "center");
954                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
955                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
956                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
957                         
958                         src = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.GetWebResourceUrl (typeof(Menu), "arrow_down.gif");
959                         writer.AddAttribute ("src", src);
960                         writer.AddAttribute ("alt", ScrollDownText);
961                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
962                         writer.RenderEndTag (); // IMG
963                         
964                         writer.RenderEndTag (); // DIV scroll button
965                         
966                         writer.RenderEndTag (); // DIV menu
967                 }
968                 
969                 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic)
970                 {
971                         writer.AddAttribute ("cellpadding", "0");
972                         writer.AddAttribute ("cellspacing", "0");
973
974                         if (!dynamic && staticMenuStyle != null)
975                                 writer.AddAttribute ("class", staticMenuStyle.RegisteredCssClass);
976                 }
977                 
978                 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
979                 {
980                         RenderMenuBeginTag (writer, dynamic);
981                         RenderMenuBody (writer, items, vertical, dynamic);
982                         RenderMenuEndTag (writer);
983                 }
984                 
985                 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic)
986                 {
987                         RenderMenuBeginTagAttributes (writer, dynamic);
988                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
989                 }
990                 
991                 void RenderMenuEndTag (HtmlTextWriter writer)
992                 {
993                         writer.RenderEndTag ();
994                 }
995                 
996                 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
997                 {
998                         if (!vertical) writer.RenderBeginTag (HtmlTextWriterTag.Tr);
999                         
1000                         for (int n=0; n<items.Count; n++) {
1001                                 MenuItem item = items [n];
1002                                 if (n > 0) {
1003                                         int itemSpacing = GetItemSpacing (item, dynamic);
1004                                         if (itemSpacing != 0) {
1005                                                 if (vertical) {
1006                                                         writer.AddAttribute ("height", itemSpacing + "px");
1007                                                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1008                                                         writer.RenderEndTag ();
1009                                                 } else {
1010                                                         writer.AddAttribute ("width", itemSpacing + "px");
1011                                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1012                                                         writer.RenderEndTag ();
1013                                                 }
1014                                         }
1015                                 }
1016                                 RenderMenuItem (writer, item);
1017                         }
1018                         
1019                         if (!vertical) writer.RenderEndTag ();  // TR
1020                 }
1021                 
1022                 void RenderMenuItem (HtmlTextWriter writer, MenuItem item)
1023                 {
1024                         bool displayChildren = (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels);
1025                         bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels) && item.ChildItems.Count > 0;
1026                         bool isDynamicItem = item.Depth + 1 > StaticDisplayLevels;
1027                         bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1028
1029                         if (vertical)
1030                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1031                         
1032                         Style itemStyle = null;
1033                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count)
1034                                 itemStyle = levelMenuItemStyles [item.Depth];
1035                         else if (isDynamicItem) {
1036                                 if (dynamicMenuItemStyle != null)
1037                                         itemStyle = dynamicMenuItemStyle;
1038                         } else {
1039                                 if (staticMenuItemStyle != null)
1040                                         itemStyle = staticMenuItemStyle;
1041                         }
1042                         
1043                         Style selectedStyle = null;
1044                         if (item == SelectedItem) {
1045                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count)
1046                                         selectedStyle = levelSelectedStyles [item.Depth];
1047                                 else if (isDynamicItem) {
1048                                         if (dynamicSelectedStyle != null)
1049                                                 selectedStyle = dynamicSelectedStyle;
1050                                 } else {
1051                                         if (staticSelectedStyle != null)
1052                                                 selectedStyle = staticSelectedStyle;
1053                                 }
1054                         }
1055                         
1056                         string cls = "";
1057                         if (itemStyle != null) cls += itemStyle.RegisteredCssClass + " ";
1058                         if (selectedStyle != null) cls += selectedStyle.RegisteredCssClass + " ";
1059                         if (cls != "")
1060                                 writer.AddAttribute ("class", cls);
1061                         
1062                         string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1063                         if (dynamicChildren) {
1064                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1065                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1066                         } else if (isDynamicItem) {
1067                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverDynamicLeafItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1068                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1069                         } else {
1070                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverStaticLeafItem ('{0}','{1}')", ClientID, item.Path));
1071                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1072                         }
1073                         
1074                         writer.AddAttribute ("id", GetItemClientId (item, "i"));
1075                         
1076                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1077
1078                         // Top separator image
1079
1080                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1081                                 writer.AddAttribute ("src", DynamicTopSeparatorImageUrl);
1082                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1083                                 writer.RenderEndTag (); // IMG
1084                         } else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1085                                 writer.AddAttribute ("src", StaticTopSeparatorImageUrl);
1086                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1087                                 writer.RenderEndTag (); // IMG
1088                         }
1089                         
1090                         // Menu item box
1091                         
1092                         writer.AddAttribute ("cellpadding", "0");
1093                         writer.AddAttribute ("cellspacing", "0");
1094                         writer.AddAttribute ("width", "100%");
1095                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1096                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1097                         
1098                         if (item.Depth > 0 && !isDynamicItem) {
1099                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1100                                 writer.AddStyleAttribute ("width", StaticSubMenuIndent.ToString ());
1101                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1102                                 writer.RenderEndTag (); // DIV
1103                                 writer.RenderEndTag (); // TD
1104                         }
1105                         
1106                         if (item.ImageUrl != "") {
1107                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1108                                 RenderItemHref (writer, item);
1109                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1110                                 writer.AddAttribute ("src", item.ImageUrl);
1111                                 writer.AddAttribute ("border", "0");
1112                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1113                                 writer.RenderEndTag (); // IMG
1114                                 writer.RenderEndTag (); // A
1115                                 writer.RenderEndTag (); // TD
1116                         }
1117                         
1118                         // Menu item text
1119                         
1120                         writer.AddAttribute ("width", "100%");
1121                         if (!ItemWrap)
1122                                 writer.AddAttribute ("nowrap", "nowrap");
1123                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1124                         
1125                         RenderItemHref (writer, item);
1126                         writer.AddStyleAttribute ("text-decoration", "none");
1127                         writer.RenderBeginTag (HtmlTextWriterTag.A);
1128                         RenderItemContent (writer, item, isDynamicItem);
1129                         writer.RenderEndTag (); // A
1130                         
1131                         writer.RenderEndTag (); // TD
1132                         
1133                         // Popup image
1134                         
1135                         if (dynamicChildren) {
1136                                 string popOutImage = GetPopOutImage (item, isDynamicItem);
1137                                 if (popOutImage != null)
1138                                 {
1139                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1140                                         writer.AddAttribute ("src", popOutImage);
1141                                         writer.AddAttribute ("border", "0");
1142                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1143                                         writer.RenderEndTag (); // IMG
1144                                         writer.RenderEndTag (); // TD
1145                                 }
1146                         }
1147                         
1148                         writer.RenderEndTag (); // TR
1149                         writer.RenderEndTag (); // TABLE
1150                         
1151                         // Bottom separator image
1152                                 
1153                         string separatorImg = item.SeparatorImageUrl;
1154                         if (separatorImg.Length == 0) { 
1155                                 if (isDynamicItem) separatorImg = DynamicBottomSeparatorImageUrl;
1156                                 else separatorImg = StaticBottomSeparatorImageUrl;
1157                         }
1158                         if (separatorImg.Length > 0) {
1159                                 writer.AddAttribute ("src", separatorImg);
1160                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1161                                 writer.RenderEndTag (); // IMG
1162                         }
1163                                 
1164                         // Submenu
1165                                 
1166                         if (vertical) {
1167                                 if (displayChildren) {
1168                                         if (dynamicChildren) dynamicMenus.Add (item);
1169                                         else {
1170                                                 writer.AddAttribute ("width", "100%");
1171                                                 RenderMenu (writer, item.ChildItems, true, false);
1172                                         }
1173                                 }
1174                                 
1175                                 writer.RenderEndTag (); // TD
1176                                 writer.RenderEndTag (); // TR
1177                         } else {
1178                                 writer.RenderEndTag (); // TD
1179                                 
1180                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1181                                 if (displayChildren) {
1182                                         if (dynamicChildren) dynamicMenus.Add (item);
1183                                         else RenderMenu (writer, item.ChildItems, false, false);
1184                                 }
1185                                 writer.RenderEndTag (); // TD
1186                         }
1187                 }
1188                 
1189                 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem)
1190                 {
1191                         if (isDynamicItem && dynamicItemTemplate != null) {
1192                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1193                                 dynamicItemTemplate.InstantiateIn (cter);
1194                                 cter.Render (writer);
1195                         } else if (!isDynamicItem && staticItemTemplate != null) {
1196                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1197                                 staticItemTemplate.InstantiateIn (cter);
1198                                 cter.Render (writer);
1199                         } else {
1200                                 writer.Write (item.Text);
1201                         }
1202                 }
1203                         
1204                 int GetItemSpacing (MenuItem item, bool dynamic)
1205                 {
1206                         int itemSpacing;
1207                         
1208                         if (item.Selected) {
1209                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1210                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1211                                         if (itemSpacing != 0) return itemSpacing;
1212                                 }
1213                                 
1214                                 if (dynamic) itemSpacing = DynamicSelectedStyle.ItemSpacing;
1215                                 else itemSpacing = StaticSelectedStyle.ItemSpacing;
1216                                 if (itemSpacing != 0) return itemSpacing;
1217                         }
1218                         
1219                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1220                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1221                                 if (itemSpacing != 0) return itemSpacing;
1222                         }
1223                         
1224                         if (dynamic) return DynamicMenuItemStyle.ItemSpacing;
1225                         else return StaticMenuItemStyle.ItemSpacing;
1226                 }
1227                 
1228                 
1229                 string GetItemSeparatorImage (MenuItem item, bool isDynamicItem)
1230                 {
1231                         if (item.SeparatorImageUrl != "") return item.SeparatorImageUrl;
1232                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "")
1233                                 return DynamicTopSeparatorImageUrl;
1234                         else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "")
1235                                 return StaticTopSeparatorImageUrl;
1236                         return null;
1237                 }
1238                         
1239                 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1240                 {
1241                         if (item.PopOutImageUrl != "")
1242                                 return item.PopOutImageUrl;
1243
1244                         if (isDynamicItem) {
1245                                 if (DynamicPopOutImageUrl != "")
1246                                         return DynamicPopOutImageUrl;
1247                                 if (DynamicEnableDefaultPopOutImage)
1248                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1249                         } else {
1250                                 if (StaticPopOutImageUrl != "")
1251                                         return StaticPopOutImageUrl;
1252                                 if (StaticEnableDefaultPopOutImage)
1253                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1254                         }
1255                         return null;
1256                 }
1257                         
1258                 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1259                 {
1260                         if (item.NavigateUrl != "") {
1261                                 writer.AddAttribute ("href", item.NavigateUrl);
1262                                 if (item.Target != "")
1263                                         writer.AddAttribute ("target", item.Target);
1264                                 else if (Target != "")
1265                                         writer.AddAttribute ("target", Target);
1266                         }
1267                         else {
1268                                 writer.AddAttribute ("href", GetClientEvent (item));
1269                         }
1270                 }
1271                 
1272                 string GetItemClientId (MenuItem item, string sufix)
1273                 {
1274                         return ClientID + "_" + item.Path + sufix;
1275                 }
1276                                                         
1277                 string GetClientEvent (MenuItem item)
1278                 {
1279                         return Page.GetPostBackClientHyperlink (this, item.Path);
1280                 }
1281         }
1282 }
1283
1284 #endif