merge from trunk revisions 58933, 58935, 58936
[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, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]\r
105             [MergablePropertyAttribute (false)]\r
106                 public 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 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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
134                 public 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 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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
161                 public 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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
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 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 (true)]
216                 public 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 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 (typeof (Unit), "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 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 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 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 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 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)]
316                 [PersistenceMode (PersistenceMode.InnerProperty)]
317                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
318                 [MergablePropertyAttribute (false)]
319                 public 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 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 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 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 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 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 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 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 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," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
447                 public 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," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
461                 public 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.SubMenuStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
475                 public 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 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 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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
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, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
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 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 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                 [MonoTODO]
569                 public string DynamicPopOutImageTextFormatString 
570                 {
571                         get {
572                                 throw new NotImplementedException ();
573                         }
574                         set {
575                                 throw new NotImplementedException ();
576                         }
577                 }
578                 
579
580                 [DefaultValue ("")]
581                 [UrlProperty]
582                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
583                 public string DynamicPopOutImageUrl {
584                         get {
585                                 object o = ViewState ["dpoiu"];
586                                 if (o != null) return (string)o;
587                                 return "";
588                         }
589                         set {
590                                 ViewState["dpoiu"] = value;
591                         }
592                 }
593
594                 [MonoTODO]
595                 public string StaticPopOutImageTextFormatString
596                 {
597                         get {
598                                 throw new NotImplementedException ();
599                         }
600                         set {
601                                 throw new NotImplementedException ();
602                         }
603                 }
604                 
605
606                 [DefaultValue ("")]
607                 [UrlProperty]
608                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
609                 public string StaticPopOutImageUrl {
610                         get {
611                                 object o = ViewState ["spoiu"];
612                                 if (o != null) return (string)o;
613                                 return "";
614                         }
615                         set {
616                                 ViewState["spoiu"] = value;
617                         }
618                 }
619
620                 [DefaultValue ("")]
621                 public string Target {
622                         get {
623                                 object o = ViewState ["Target"];
624                                 if (o != null) return (string) o;
625                                 return "";
626                         }
627                         set {
628                                 ViewState["Target"] = value;
629                         }
630                 }
631
632                 [DefaultValue (null)]
633                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
634                 [PersistenceMode (PersistenceMode.InnerProperty)]
635             [Browsable (false)]
636                 public ITemplate StaticItemTemplate {
637                         get { return staticItemTemplate; }
638                         set { staticItemTemplate = value; }
639                 }
640                 
641                 [DefaultValue (null)]
642                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
643                 [PersistenceMode (PersistenceMode.InnerProperty)]
644             [Browsable (false)]
645                 public ITemplate DynamicItemTemplate {
646                         get { return dynamicItemTemplate; }
647                         set { dynamicItemTemplate = value; }
648                 }
649                 
650                 [Browsable (false)]
651                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
652                 public MenuItem SelectedItem {
653                         get {
654                                 if (selectedItem == null && selectedItemPath != null) {
655                                         selectedItem = FindItemByPos (selectedItemPath);
656                                 }
657                                 
658                                 return selectedItem;
659                         }
660                 }
661
662                 [Browsable (false)]
663                 [DefaultValue ("")]
664                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
665                 public string SelectedValue {
666                         get { return selectedItem != null ? selectedItem.Value : null; }
667                 }
668
669                 [MonoTODO]
670                 [Localizable (true)]
671                 public string SkipLinkText 
672                 {
673                         get {
674                                 throw new NotImplementedException ();
675                         }
676                         set {
677                                 throw new NotImplementedException ();
678                         }
679                 }
680                 
681
682                 internal void SetSelectedItem (MenuItem item)
683                 {
684                         if (selectedItem == item) return;
685                         selectedItem = item;
686                         selectedItemPath = item.Path;
687                 }
688                 
689                 public MenuItem FindItem (string valuePath)
690                 {
691                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
692                         string[] path = valuePath.Split (PathSeparator);
693                         int n = 0;
694                         MenuItemCollection col = Items;
695                         bool foundBranch = true;
696                         while (col.Count > 0 && foundBranch) {
697                                 foundBranch = false;
698                                 foreach (MenuItem item in col) {
699                                         if (item.Value == path [n]) {
700                                                 if (++n == path.Length) return item;
701                                                 col = item.ChildItems;
702                                                 foundBranch = true;
703                                                 break;
704                                         }
705                                 }
706                         }
707                         return null;
708                 }
709                 
710                 string GetBindingKey (string dataMember, int depth)
711                 {
712                         return dataMember + " " + depth;
713                 }
714                 
715                 internal MenuItemBinding FindBindingForItem (string type, int depth)
716                 {
717                         if (bindings == null) return null;
718
719                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
720                         if (bin != null) return bin;
721                         
722                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
723                         if (bin != null) return bin;
724                         
725                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
726                         if (bin != null) return bin;
727                         
728                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
729                         return bin;
730                 }
731                 
732                 protected internal override void PerformDataBinding ()
733                 {
734                         base.PerformDataBinding ();
735                         HierarchicalDataSourceView data = GetData ("");
736                         IHierarchicalEnumerable e = data.Select ();
737                         foreach (object obj in e) {
738                                 IHierarchyData hdata = e.GetHierarchyData (obj);
739                                 MenuItem item = new MenuItem ();
740                                 item.Bind (hdata);
741                                 Items.Add (item);
742                                 OnMenuItemDataBound (new MenuEventArgs (item));
743                         }
744                 }
745                 
746                 protected void SetItemDataBound (MenuItem node, bool dataBound)
747                 {
748                         node.SetDataBound (dataBound);
749                 }
750                 
751                 protected void SetItemDataPath (MenuItem node, string dataPath)
752                 {
753                         node.SetDataPath (dataPath);
754                 }
755                 
756                 protected void SetItemDataItem (MenuItem node, object dataItem)
757                 {
758                         node.SetDataItem (dataItem);
759                 }
760                 
761                 protected internal virtual void RaisePostBackEvent (string eventArgument)
762                 {
763                         MenuItem item = FindItemByPos (eventArgument);
764                         if (item == null) return;
765                         item.Selected = true;
766                         OnMenuItemClick (new MenuEventArgs (item));
767                 }
768
769                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
770                 {
771                         RaisePostBackEvent (eventArgument);
772                 }
773                 
774                 MenuItem FindItemByPos (string path)
775                 {
776                         string[] indexes = path.Split ('_');
777                         MenuItem item = null;
778                         
779                         foreach (string index in indexes) {
780                                 int i = int.Parse (index);
781                                 if (item == null) {
782                                         if (i >= Items.Count) return null;
783                                         item = Items [i];
784                                 } else {
785                                         if (i >= item.ChildItems.Count) return null;
786                                         item = item.ChildItems [i];
787                                 }
788                         }
789                         return item;
790                 }
791                 
792                 protected override HtmlTextWriterTag TagKey {
793                         get { return HtmlTextWriterTag.Table; }
794                 }
795                 
796                 protected override void TrackViewState()
797                 {
798                         EnsureDataBound ();
799                         
800                         base.TrackViewState();
801                         if (dataBindings != null) {
802                                 ((IStateManager)dataBindings).TrackViewState ();
803                         }
804                         if (items != null) {
805                                 ((IStateManager)items).TrackViewState();
806                         }
807                         if (dynamicMenuItemStyle != null)
808                                 dynamicMenuItemStyle.TrackViewState ();
809                         if (dynamicMenuStyle != null)
810                                 dynamicMenuStyle.TrackViewState ();
811                         if (levelMenuItemStyles != null)
812                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
813                         if (levelSelectedStyles != null)
814                                 ((IStateManager)levelSelectedStyles).TrackViewState();
815                         if (levelSubMenuStyles != null)
816                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
817                         if (dynamicSelectedStyle != null)
818                                 dynamicSelectedStyle.TrackViewState();
819                         if (staticMenuItemStyle != null)
820                                 staticMenuItemStyle.TrackViewState ();
821                         if (staticMenuStyle != null)
822                                 staticMenuStyle.TrackViewState ();
823                         if (staticSelectedStyle != null)
824                                 staticSelectedStyle.TrackViewState();
825                         if (staticHoverStyle != null)
826                                 staticHoverStyle.TrackViewState();
827                         if (dynamicHoverStyle != null)
828                                 dynamicHoverStyle.TrackViewState();
829                 }
830
831                 protected override object SaveViewState()
832                 {
833                         object[] states = new object [14];
834                         states[0] = base.SaveViewState ();
835                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
836                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
837                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
838                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
839                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
840                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
841                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
842                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
843                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
844                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
845                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
846                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
847                         states[13] = levelSubMenuStyles == null ? null : ((IStateManager)levelSubMenuStyles).SaveViewState();
848
849                         for (int i = states.Length - 1; i >= 0; i--) {
850                                 if (states [i] != null)
851                                         return states;
852                         }
853
854                         return null;
855                 }
856
857                 protected override void LoadViewState (object savedState)
858                 {
859                         if (savedState == null)
860                                 return;
861
862                         object [] states = (object []) savedState;
863                         base.LoadViewState (states[0]);
864                         
865                         if (states[1] != null)
866                                 ((IStateManager)DataBindings).LoadViewState(states[1]);
867                         if (states[2] != null)
868                                 ((IStateManager)Items).LoadViewState(states[2]);
869                         if (states[3] != null)
870                                 DynamicMenuItemStyle.LoadViewState (states[3]);
871                         if (states[4] != null)
872                                 DynamicMenuStyle.LoadViewState (states[4]);
873                         if (states[5] != null)
874                                 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
875                         if (states[6] != null)
876                                 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
877                         if (states[7] != null)
878                                 DynamicSelectedStyle.LoadViewState (states[7]);
879                         if (states[8] != null)
880                                 StaticMenuItemStyle.LoadViewState (states[8]);
881                         if (states[9] != null)
882                                 StaticMenuStyle.LoadViewState (states[9]);
883                         if (states[10] != null)
884                                 StaticSelectedStyle.LoadViewState (states[10]);
885                         if (states[11] != null)
886                                 StaticHoverStyle.LoadViewState (states[11]);
887                         if (states[12] != null)
888                                 DynamicHoverStyle.LoadViewState (states[12]);
889                         if (states[13] != null)
890                                 ((IStateManager)LevelSubMenuStyles).LoadViewState(states[13]);
891                 }
892                 
893                 protected internal override void OnInit (EventArgs e)
894                 {
895                         Page.RegisterRequiresControlState (this);
896                         base.OnInit (e);
897                 }
898                 
899                 protected internal override void LoadControlState (object ob)
900                 {
901                         if (ob == null) return;
902                         object[] state = (object[]) ob;
903                         base.LoadControlState (state[0]);
904                         selectedItemPath = state[1] as string;
905                 }
906                 
907                 protected internal override object SaveControlState ()
908                 {
909                         object bstate = base.SaveControlState ();
910                         object mstate = selectedItemPath;
911                         
912                         if (bstate != null || mstate != null)
913                                 return new object[] { bstate, mstate };
914                         else
915                                 return null;
916                 }
917                 
918                 protected internal override void CreateChildControls ()
919                 {
920                         base.CreateChildControls ();
921                 }
922                 
923                 protected override void EnsureDataBound ()
924                 {
925                         base.EnsureDataBound ();
926                 }
927
928                 [MonoTODO]
929                 protected override IDictionary GetDesignModeState ()
930                 {
931                         throw new NotImplementedException ();
932                 }
933
934                 [MonoTODO]
935                 protected override void SetDesignModeState (IDictionary data)
936                 {
937                         throw new NotImplementedException ();
938                 }
939                                 
940                 public override ControlCollection Controls {
941                         get { return base.Controls; }
942                 }
943                 
944                 public sealed override void DataBind ()
945                 {
946                         base.DataBind ();
947                 }
948                 
949                 [MonoTODO]
950                 protected override bool OnBubbleEvent (object source, EventArgs e)
951                 {
952                         throw new NotImplementedException ();
953                 }
954
955                 [MonoTODO]
956                 protected override void OnDataBinding (EventArgs e)
957                 {
958                         throw new NotImplementedException ();
959                 }
960                 
961                 protected internal override void OnPreRender (EventArgs e)
962                 {
963                         base.OnPreRender (e);
964                         
965                         if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
966                                 string url = Page.ClientScript.GetWebResourceUrl (typeof(Menu), "Menu.js");
967                                 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
968                         }
969                         
970                         string cmenu = ClientID + "_data";
971                         string script = string.Format ("var {0} = new Object ();\n", cmenu);
972                         script += string.Format ("{0}.disappearAfter = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DisappearAfter));
973                         script += string.Format ("{0}.vertical = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
974                         if (DynamicHorizontalOffset != 0)
975                                 script += string.Format ("{0}.dho = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset));
976                         if (DynamicVerticalOffset != 0)
977                                 script += string.Format ("{0}.dvo = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset));
978                                 
979                         // The order in which styles are defined matters when more than one class
980                         // is assigned to an element
981                         
982                         if (dynamicMenuStyle != null)
983                                 RegisterItemStyle (dynamicMenuStyle);
984                         if (staticMenuStyle != null)
985                                 RegisterItemStyle (staticMenuStyle);
986                 
987                         if (staticMenuItemStyle != null)
988                                 RegisterItemStyle (staticMenuItemStyle);
989
990                         if (dynamicMenuItemStyle != null)
991                                 RegisterItemStyle (dynamicMenuItemStyle);
992
993                         if (levelSubMenuStyles != null)
994                                 foreach (Style style in levelSubMenuStyles)
995                                         RegisterItemStyle (style);
996
997                         if (levelMenuItemStyles != null)
998                                 foreach (Style style in levelMenuItemStyles)
999                                         RegisterItemStyle (style);
1000
1001                         if (staticSelectedStyle != null)
1002                                 RegisterItemStyle (staticSelectedStyle);
1003                         if (dynamicSelectedStyle != null)
1004                                 RegisterItemStyle (dynamicSelectedStyle);
1005                                 
1006                         if (levelSelectedStyles != null)
1007                                 foreach (Style style in levelSelectedStyles)
1008                                         RegisterItemStyle (style);
1009                         
1010                         if (dynamicHoverStyle != null)
1011                                 RegisterItemStyle (dynamicHoverStyle);
1012                         if (staticHoverStyle != null)
1013                                 RegisterItemStyle (staticHoverStyle);
1014
1015                         if (staticHoverStyle != null)
1016                                 script += string.Format ("{0}.staticHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass));
1017                         if (dynamicHoverStyle != null)
1018                                 script += string.Format ("{0}.dynamicHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass));
1019                         
1020                         Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
1021
1022                         if (dataBindings != null && dataBindings.Count > 0) {
1023                                 bindings = new Hashtable ();
1024                                 foreach (TreeNodeBinding bin in dataBindings) {
1025                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
1026                                         bindings [key] = bin;
1027                                 }
1028                         }
1029                         else
1030                                 bindings = null;
1031                 }
1032                 
1033                 void RegisterItemStyle (Style baseStyle)
1034                 {
1035                         Page.Header.StyleSheet.RegisterStyle (baseStyle, this);
1036                         Style ts = new Style ();
1037                         ts.CopyTextStylesFrom (baseStyle);
1038                         Page.Header.StyleSheet.CreateStyleRule (ts, this, "." + baseStyle.RegisteredCssClass + " A");
1039                 }
1040                 
1041                 protected internal override void Render (HtmlTextWriter writer)
1042                 {
1043                         base.Render (writer);
1044                 }
1045                 
1046                 protected override void AddAttributesToRender (HtmlTextWriter writer)
1047                 {
1048                         RenderMenuBeginTagAttributes (writer, false, 0);
1049                 }
1050                 
1051                 public override void RenderBeginTag (HtmlTextWriter writer)
1052                 {
1053                         base.RenderBeginTag (writer);
1054                 }
1055                 
1056                 public override void RenderEndTag (HtmlTextWriter writer)
1057                 {
1058                         base.RenderEndTag (writer);
1059                         
1060                         // Render dynamic menus outside the main control tag
1061                         for (int n=0; n<dynamicMenus.Count; n++) {
1062                                 MenuItem item = (MenuItem) dynamicMenus [n];
1063                                 RenderDynamicMenu (writer, item);
1064                         }
1065                         dynamicMenus = null;
1066                 }
1067                 
1068                 protected internal override void RenderContents (HtmlTextWriter writer)
1069                 {
1070                         dynamicMenus = new ArrayList ();
1071                         RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false);
1072                 }
1073                 
1074                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
1075                 {
1076                         if (dynamicMenuStyle != null)
1077                                 writer.AddAttribute ("class", dynamicMenuStyle.RegisteredCssClass);
1078                         
1079                         writer.AddStyleAttribute ("visibility", "hidden");
1080                         writer.AddStyleAttribute ("position", "absolute");
1081                         writer.AddStyleAttribute ("left", "0px");
1082                         writer.AddStyleAttribute ("top", "0px");
1083                         writer.AddAttribute ("id", GetItemClientId (item, "s"));
1084                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1085
1086                         // Up button
1087                         writer.AddAttribute ("id", GetItemClientId (item, "cu"));
1088                         writer.AddStyleAttribute ("display", "block");
1089                         writer.AddStyleAttribute ("text-align", "center");
1090                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
1091                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
1092                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1093                         
1094                         string src = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_up.gif");
1095                         writer.AddAttribute ("src", src);
1096                         writer.AddAttribute ("alt", ScrollUpText);
1097                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1098                         writer.RenderEndTag (); // IMG
1099                         
1100                         writer.RenderEndTag (); // DIV scroll button
1101                 
1102                         writer.AddAttribute ("id", GetItemClientId (item, "cb"));       // Scroll container
1103                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1104                         writer.AddAttribute ("id", GetItemClientId (item, "cc"));       // Content
1105                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1106                         
1107                         RenderMenu (writer, item.ChildItems, true, true, item.Depth + 1);
1108                         
1109                         writer.RenderEndTag (); // DIV Content
1110                         writer.RenderEndTag (); // DIV Scroll container
1111
1112                         // Down button
1113                         writer.AddAttribute ("id", GetItemClientId (item, "cd"));
1114                         writer.AddStyleAttribute ("display", "block");
1115                         writer.AddStyleAttribute ("text-align", "center");
1116                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
1117                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
1118                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1119                         
1120                         src = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_down.gif");
1121                         writer.AddAttribute ("src", src);
1122                         writer.AddAttribute ("alt", ScrollDownText);
1123                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1124                         writer.RenderEndTag (); // IMG
1125                         
1126                         writer.RenderEndTag (); // DIV scroll button
1127                         
1128                         writer.RenderEndTag (); // DIV menu
1129                 }
1130                 
1131                 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic, int menuLevel)
1132                 {
1133                         writer.AddAttribute ("cellpadding", "0");
1134                         writer.AddAttribute ("cellspacing", "0");
1135
1136                         string cls = string.Empty;
1137                         
1138                         if (!dynamic && staticMenuStyle != null)
1139                                 cls += staticMenuStyle.RegisteredCssClass + " ";
1140                                 
1141                         if (levelSubMenuStyles != null && menuLevel < levelSubMenuStyles.Count)
1142                                 cls += levelSubMenuStyles [menuLevel].RegisteredCssClass;
1143                         
1144                         if (cls.Length != 0)
1145                                 writer.AddAttribute ("class", cls);
1146                 }
1147                 
1148                 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, int menuLevel)
1149                 {
1150                         RenderMenuBeginTag (writer, dynamic, menuLevel);
1151                         RenderMenuBody (writer, items, vertical, dynamic);
1152                         RenderMenuEndTag (writer);
1153                 }
1154                 
1155                 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic, int menuLevel)
1156                 {
1157                         RenderMenuBeginTagAttributes (writer, dynamic, menuLevel);
1158                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1159                 }
1160                 
1161                 void RenderMenuEndTag (HtmlTextWriter writer)
1162                 {
1163                         writer.RenderEndTag ();
1164                 }
1165                 
1166                 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
1167                 {
1168                         if (!vertical) writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1169                         
1170                         for (int n=0; n<items.Count; n++) {
1171                                 MenuItem item = items [n];
1172                                 if (n > 0) {
1173                                         Unit itemSpacing = GetItemSpacing (item, dynamic);
1174                                         if (itemSpacing != Unit.Empty) {
1175                                                 if (vertical) {
1176                                                         writer.AddAttribute ("height", itemSpacing.ToString());
1177                                                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1178                                                         writer.RenderEndTag ();
1179                                                 } else {
1180                                                         writer.AddAttribute ("width", itemSpacing.ToString());
1181                                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1182                                                         writer.RenderEndTag ();
1183                                                 }
1184                                         }
1185                                 }
1186                                 RenderMenuItem (writer, item);
1187                         }
1188                         
1189                         if (!vertical) writer.RenderEndTag ();  // TR
1190                 }
1191                 
1192                 void RenderMenuItem (HtmlTextWriter writer, MenuItem item)
1193                 {
1194                         bool displayChildren = (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels);
1195                         bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels) && item.ChildItems.Count > 0;
1196                         bool isDynamicItem = item.Depth + 1 > StaticDisplayLevels;
1197                         bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1198
1199                         if (vertical)
1200                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1201                         
1202                         Style itemStyle = null;
1203                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count)
1204                                 itemStyle = levelMenuItemStyles [item.Depth];
1205                         else if (isDynamicItem) {
1206                                 if (dynamicMenuItemStyle != null)
1207                                         itemStyle = dynamicMenuItemStyle;
1208                         } else {
1209                                 if (staticMenuItemStyle != null)
1210                                         itemStyle = staticMenuItemStyle;
1211                         }
1212                         
1213                         Style selectedStyle = null;
1214                         if (item == SelectedItem) {
1215                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count)
1216                                         selectedStyle = levelSelectedStyles [item.Depth];
1217                                 else if (isDynamicItem) {
1218                                         if (dynamicSelectedStyle != null)
1219                                                 selectedStyle = dynamicSelectedStyle;
1220                                 } else {
1221                                         if (staticSelectedStyle != null)
1222                                                 selectedStyle = staticSelectedStyle;
1223                                 }
1224                         }
1225                         
1226                         string cls = "";
1227                         if (itemStyle != null) cls += itemStyle.RegisteredCssClass + " ";
1228                         if (selectedStyle != null) cls += selectedStyle.RegisteredCssClass + " ";
1229                         if (cls != "")
1230                                 writer.AddAttribute ("class", cls);
1231                         
1232                         string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1233                         if (dynamicChildren) {
1234                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1235                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1236                         } else if (isDynamicItem) {
1237                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverDynamicLeafItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1238                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1239                         } else {
1240                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverStaticLeafItem ('{0}','{1}')", ClientID, item.Path));
1241                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1242                         }
1243                         
1244                         writer.AddAttribute ("id", GetItemClientId (item, "i"));
1245                         
1246                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1247
1248                         // Top separator image
1249
1250                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1251                                 writer.AddAttribute ("src", DynamicTopSeparatorImageUrl);
1252                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1253                                 writer.RenderEndTag (); // IMG
1254                         } else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1255                                 writer.AddAttribute ("src", StaticTopSeparatorImageUrl);
1256                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1257                                 writer.RenderEndTag (); // IMG
1258                         }
1259                         
1260                         // Menu item box
1261                         
1262                         writer.AddAttribute ("cellpadding", "0");
1263                         writer.AddAttribute ("cellspacing", "0");
1264                         writer.AddAttribute ("width", "100%");
1265                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1266                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1267                         
1268                         if (item.Depth > 0 && !isDynamicItem) {
1269                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1270                                 writer.AddStyleAttribute ("width", StaticSubMenuIndent.ToString ());
1271                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1272                                 writer.RenderEndTag (); // DIV
1273                                 writer.RenderEndTag (); // TD
1274                         }
1275                         
1276                         if (item.ImageUrl != "") {
1277                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1278                                 RenderItemHref (writer, item);
1279                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1280                                 writer.AddAttribute ("src", item.ImageUrl);
1281                                 writer.AddAttribute ("border", "0");
1282                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1283                                 writer.RenderEndTag (); // IMG
1284                                 writer.RenderEndTag (); // A
1285                                 writer.RenderEndTag (); // TD
1286                         }
1287                         
1288                         // Menu item text
1289                         
1290                         writer.AddAttribute ("width", "100%");
1291                         if (!ItemWrap)
1292                                 writer.AddAttribute ("nowrap", "nowrap");
1293                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1294                         
1295                         RenderItemHref (writer, item);
1296                         writer.AddStyleAttribute ("text-decoration", "none");
1297                         writer.RenderBeginTag (HtmlTextWriterTag.A);
1298                         RenderItemContent (writer, item, isDynamicItem);
1299                         writer.RenderEndTag (); // A
1300                         
1301                         writer.RenderEndTag (); // TD
1302                         
1303                         // Popup image
1304                         
1305                         if (dynamicChildren) {
1306                                 string popOutImage = GetPopOutImage (item, isDynamicItem);
1307                                 if (popOutImage != null)
1308                                 {
1309                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1310                                         writer.AddAttribute ("src", popOutImage);
1311                                         writer.AddAttribute ("border", "0");
1312                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1313                                         writer.RenderEndTag (); // IMG
1314                                         writer.RenderEndTag (); // TD
1315                                 }
1316                         }
1317                         
1318                         writer.RenderEndTag (); // TR
1319                         writer.RenderEndTag (); // TABLE
1320                         
1321                         // Bottom separator image
1322                                 
1323                         string separatorImg = item.SeparatorImageUrl;
1324                         if (separatorImg.Length == 0) { 
1325                                 if (isDynamicItem) separatorImg = DynamicBottomSeparatorImageUrl;
1326                                 else separatorImg = StaticBottomSeparatorImageUrl;
1327                         }
1328                         if (separatorImg.Length > 0) {
1329                                 writer.AddAttribute ("src", separatorImg);
1330                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1331                                 writer.RenderEndTag (); // IMG
1332                         }
1333                                 
1334                         // Submenu
1335                                 
1336                         if (vertical) {
1337                                 if (displayChildren) {
1338                                         if (dynamicChildren) dynamicMenus.Add (item);
1339                                         else {
1340                                                 writer.AddAttribute ("width", "100%");
1341                                                 RenderMenu (writer, item.ChildItems, true, false, item.Depth + 1);
1342                                         }
1343                                 }
1344                                 
1345                                 writer.RenderEndTag (); // TD
1346                                 writer.RenderEndTag (); // TR
1347                         } else {
1348                                 writer.RenderEndTag (); // TD
1349                                 
1350                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1351                                 if (displayChildren) {
1352                                         if (dynamicChildren) dynamicMenus.Add (item);
1353                                         else RenderMenu (writer, item.ChildItems, false, false, item.Depth + 1);
1354                                 }
1355                                 writer.RenderEndTag (); // TD
1356                         }
1357                 }
1358                 
1359                 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem)
1360                 {
1361                         if (isDynamicItem && dynamicItemTemplate != null) {
1362                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1363                                 dynamicItemTemplate.InstantiateIn (cter);
1364                                 cter.Render (writer);
1365                         } else if (!isDynamicItem && staticItemTemplate != null) {
1366                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1367                                 staticItemTemplate.InstantiateIn (cter);
1368                                 cter.Render (writer);
1369                         } else if (isDynamicItem && DynamicItemFormatString.Length > 0) {
1370                                 writer.Write (string.Format (DynamicItemFormatString, item.Text));
1371                         } else if (!isDynamicItem && StaticItemFormatString.Length > 0) {
1372                                 writer.Write (string.Format (StaticItemFormatString, item.Text));
1373                         } else {
1374                                 writer.Write (item.Text);
1375                         }
1376                         
1377                 }
1378                         
1379                 Unit GetItemSpacing (MenuItem item, bool dynamic)
1380                 {
1381                         Unit itemSpacing;
1382                         
1383                         if (item.Selected) {
1384                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1385                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1386                                         if (itemSpacing != Unit.Empty) return itemSpacing;
1387                                 }
1388                                 
1389                                 if (dynamic) itemSpacing = DynamicSelectedStyle.ItemSpacing;
1390                                 else itemSpacing = StaticSelectedStyle.ItemSpacing;
1391                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1392                         }
1393                         
1394                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1395                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1396                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1397                         }
1398                         
1399                         if (dynamic) return DynamicMenuItemStyle.ItemSpacing;
1400                         else return StaticMenuItemStyle.ItemSpacing;
1401                 }
1402                 
1403                 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1404                 {
1405                         if (item.PopOutImageUrl != "")
1406                                 return item.PopOutImageUrl;
1407
1408                         if (isDynamicItem) {
1409                                 if (DynamicPopOutImageUrl != "")
1410                                         return DynamicPopOutImageUrl;
1411                                 if (DynamicEnableDefaultPopOutImage)
1412                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1413                         } else {
1414                                 if (StaticPopOutImageUrl != "")
1415                                         return StaticPopOutImageUrl;
1416                                 if (StaticEnableDefaultPopOutImage)
1417                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1418                         }
1419                         return null;
1420                 }
1421                         
1422                 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1423                 {
1424                         if (!item.BranchEnabled) {
1425                                 writer.AddAttribute ("disabled", "true");
1426                         }
1427                         else if (!item.Selectable) {
1428                                 writer.AddAttribute ("href", "#");
1429                                 writer.AddStyleAttribute ("cursor", "text");
1430                         }
1431                         else if (item.NavigateUrl != "") {
1432                                 writer.AddAttribute ("href", item.NavigateUrl);
1433                                 if (item.Target != "")
1434                                         writer.AddAttribute ("target", item.Target);
1435                                 else if (Target != "")
1436                                         writer.AddAttribute ("target", Target);
1437                         }
1438                         else {
1439                                 writer.AddAttribute ("href", GetClientEvent (item));
1440                         }
1441
1442                 }
1443                 
1444                 string GetItemClientId (MenuItem item, string sufix)
1445                 {
1446                         return ClientID + "_" + item.Path + sufix;
1447                 }
1448                                                         
1449                 string GetClientEvent (MenuItem item)
1450                 {
1451                         return Page.ClientScript.GetPostBackClientHyperlink (this, item.Path);
1452                 }
1453         }
1454 }
1455
1456 #endif