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