Merge branch 'master' of github.com:mono/mono
[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 //      Igor Zelmanovich (igorz@mainsoft.com)
7 //
8 // (C) 2004 Novell, Inc (http://www.novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if NET_2_0
33
34 using System;
35 using System.Collections;
36 using System.Text;
37 using System.ComponentModel;
38 using System.Web.UI;
39 using System.Web.Handlers;
40 using System.Collections.Specialized;
41 using System.IO;
42 using System.Drawing;
43 using System.Collections.Generic;
44
45 namespace System.Web.UI.WebControls
46 {
47         [DefaultEvent ("MenuItemClick")]
48         [ControlValueProperty ("SelectedValue")]
49         [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
50         [SupportsEventValidation]
51         public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
52         {
53                 MenuItemStyle dynamicMenuItemStyle;
54                 SubMenuStyle dynamicMenuStyle;
55                 MenuItemStyle dynamicSelectedStyle;
56                 MenuItemStyle staticMenuItemStyle;
57                 SubMenuStyle staticMenuStyle;
58                 MenuItemStyle staticSelectedStyle;
59                 Style staticHoverStyle;
60                 Style dynamicHoverStyle;
61
62                 MenuItemStyleCollection levelMenuItemStyles;
63                 MenuItemStyleCollection levelSelectedStyles;
64                 SubMenuStyleCollection levelSubMenuStyles;
65                 ITemplate staticItemTemplate;
66                 ITemplate dynamicItemTemplate;
67                 
68                 MenuItemCollection items;
69                 MenuItemBindingCollection dataBindings;
70                 MenuItem selectedItem;
71                 string selectedItemPath;
72                 Hashtable bindings;
73
74                 Hashtable _menuItemControls;
75                 bool _requiresChildControlsDataBinding;
76                 SiteMapNode _currSiteMapNode;
77                 int registeredStylesCounter = -1;
78                 List<Style> levelSelectedLinkStyles;
79                 List<Style> levelMenuItemLinkStyles;
80                 Style popOutBoxStyle;
81                 Style controlLinkStyle;
82                 Style dynamicMenuItemLinkStyle;
83                 Style staticMenuItemLinkStyle;
84                 Style dynamicSelectedLinkStyle;
85                 Style staticSelectedLinkStyle;
86                 Style dynamicHoverLinkStyle;
87                 Style staticHoverLinkStyle;
88 #if NET_4_0
89                 bool includeStyleBlock = true;
90                 MenuRenderingMode renderingMode = MenuRenderingMode.Default;
91 #endif
92                 static readonly object MenuItemClickEvent = new object();
93                 static readonly object MenuItemDataBoundEvent = new object();
94                 
95                 public static readonly string MenuItemClickCommandName = "Click";
96                 
97                 public event MenuEventHandler MenuItemClick {
98                         add { Events.AddHandler (MenuItemClickEvent, value); }
99                         remove { Events.RemoveHandler (MenuItemClickEvent, value); }
100                 }
101                 
102                 public event MenuEventHandler MenuItemDataBound {
103                         add { Events.AddHandler (MenuItemDataBoundEvent, value); }
104                         remove { Events.RemoveHandler (MenuItemDataBoundEvent, value); }
105                 }
106                 
107                 protected virtual void OnMenuItemClick (MenuEventArgs e)
108                 {
109                         if (Events != null) {
110                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
111                                 if (eh != null) eh (this, e);
112                         }
113                 }
114                 
115                 protected virtual void OnMenuItemDataBound (MenuEventArgs e)
116                 {
117                         if (Events != null) {
118                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemDataBoundEvent];
119                                 if (eh != null) eh (this, e);
120                         }
121                 }
122 #if NET_4_0
123                 [DefaultValue (true)]
124                 [Description ("Determines whether or not to render the inline style block (only used in standards compliance mode)")]
125                 public bool IncludeStyleBlock {
126                         get { return includeStyleBlock; }
127                         set { includeStyleBlock = value; }
128                 }
129
130                 [DefaultValue (MenuRenderingMode.Default)]
131                 public MenuRenderingMode RenderingMode {
132                         get { return renderingMode; }
133                         set {
134                                 if (value < MenuRenderingMode.Default || value > MenuRenderingMode.List)
135                                         throw new ArgumentOutOfRangeException ("value");
136
137                                 renderingMode = value;
138                         }
139                 }
140 #endif
141                 [DefaultValueAttribute (null)]
142                 [PersistenceMode (PersistenceMode.InnerProperty)]
143                 [EditorAttribute ("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
144                 [MergablePropertyAttribute (false)]
145                 public MenuItemBindingCollection DataBindings {
146                         get {
147                                 if (dataBindings == null) {
148                                         dataBindings = new MenuItemBindingCollection ();
149                                         if (IsTrackingViewState)
150                                                 ((IStateManager)dataBindings).TrackViewState();
151                                 }
152                                 return dataBindings;
153                         }
154                 }
155
156                 [DefaultValue (500)]
157                 [ThemeableAttribute (false)]
158                 public int DisappearAfter {
159                         get {
160                                 object o = ViewState ["DisappearAfter"];
161                                 if (o != null) return (int)o;
162                                 return 500;
163                         }
164                         set {
165                                 ViewState["DisappearAfter"] = value;
166                         }
167                 }
168
169                 [ThemeableAttribute (true)]
170                 [DefaultValue ("")]
171                 [UrlProperty]
172                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
173                 public string DynamicBottomSeparatorImageUrl {
174                         get {
175                                 object o = ViewState ["dbsiu"];
176                                 if (o != null) return (string)o;
177                                 return "";
178                         }
179                         set {
180                                 ViewState["dbsiu"] = value;
181                         }
182                 }
183
184                 [DefaultValueAttribute ("")]
185                 public string DynamicItemFormatString {
186                         get {
187                                 object o = ViewState ["DynamicItemFormatString"];
188                                 if (o != null) return (string)o;
189                                 return "";
190                         }
191                         set {
192                                 ViewState["DynamicItemFormatString"] = value;
193                         }
194                 }
195
196                 [DefaultValue ("")]
197                 [UrlProperty]
198                 [WebCategory ("Appearance")]
199                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
200                 public string DynamicTopSeparatorImageUrl {
201                         get {
202                                 object o = ViewState ["dtsiu"];
203                                 if (o != null) return (string)o;
204                                 return "";
205                         }
206                         set {
207                                 ViewState["dtsiu"] = value;
208                         }
209                 }
210
211                 [DefaultValue ("")]
212                 [UrlProperty]
213                 [WebCategory ("Appearance")]
214                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
215                 public string StaticBottomSeparatorImageUrl {
216                         get {
217                                 object o = ViewState ["sbsiu"];
218                                 if (o != null) return (string)o;
219                                 return "";
220                         }
221                         set {
222                                 ViewState["sbsiu"] = value;
223                         }
224                 }
225
226                 [DefaultValue ("")]
227                 [UrlProperty]
228                 [WebCategory ("Appearance")]
229                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
230                 public string StaticTopSeparatorImageUrl {
231                         get {
232                                 object o = ViewState ["stsiu"];
233                                 if (o != null) return (string)o;
234                                 return "";
235                         }
236                         set {
237                                 ViewState["stsiu"] = value;
238                         }
239                 }
240
241                 [DefaultValue (Orientation.Vertical)]
242                 public Orientation Orientation {
243                         get {
244                                 object o = ViewState ["Orientation"];
245                                 if (o != null) return (Orientation) o;
246                                 return Orientation.Vertical;
247                         }
248                         set {
249                                 ViewState["Orientation"] = value;
250                         }
251                 }
252
253                 [DefaultValue (1)]
254                 [ThemeableAttribute (true)]
255                 public int StaticDisplayLevels {
256                         get {
257                                 object o = ViewState ["StaticDisplayLevels"];
258                                 if (o != null) return (int)o;
259                                 return 1;
260                         }
261                         set {
262                                 if (value < 1) throw new ArgumentOutOfRangeException ();
263                                 ViewState["StaticDisplayLevels"] = value;
264                         }
265                 }
266
267                 [DefaultValueAttribute ("")]
268                 public string StaticItemFormatString {
269                         get {
270                                 object o = ViewState ["StaticItemFormatString"];
271                                 if (o != null) return (string)o;
272                                 return "";
273                         }
274                         set {
275                                 ViewState["StaticItemFormatString"] = value;
276                         }
277                 }
278
279                 [DefaultValue (typeof (Unit), "16px")]
280                 [ThemeableAttribute (true)]
281                 public Unit StaticSubMenuIndent {
282                         get {
283                                 object o = ViewState ["StaticSubMenuIndent"];
284                                 if (o != null)
285                                         return (Unit)o;
286                                 // LAMESPEC: on 4.0 it returns Unit.Empty and on 3.5 16px
287 #if NET_4_0
288                                 return Unit.Empty;
289 #else
290                                 return new Unit (16);
291 #endif
292                         }
293                         set {
294                                 ViewState["StaticSubMenuIndent"] = value;
295                         }
296                 }
297
298                 [ThemeableAttribute (true)]
299                 [DefaultValue (3)]
300                 public int MaximumDynamicDisplayLevels {
301                         get {
302                                 object o = ViewState ["MaximumDynamicDisplayLevels"];
303                                 if (o != null) return (int)o;
304                                 return 3;
305                         }
306                         set {
307                                 if (value < 0) throw new ArgumentOutOfRangeException ();
308                                 ViewState["MaximumDynamicDisplayLevels"] = value;
309                         }
310                 }
311
312                 [DefaultValue (0)]
313                 public int DynamicVerticalOffset {
314                         get {
315                                 object o = ViewState ["DynamicVerticalOffset"];
316                                 if (o != null) return (int)o;
317                                 return 0;
318                         }
319                         set {
320                                 ViewState["DynamicVerticalOffset"] = value;
321                         }
322                 }
323
324                 [DefaultValue (0)]
325                 public int DynamicHorizontalOffset {
326                         get {
327                                 object o = ViewState ["DynamicHorizontalOffset"];
328                                 if (o != null) return (int)o;
329                                 return 0;
330                         }
331                         set {
332                                 ViewState["DynamicHorizontalOffset"] = value;
333                         }
334                 }
335
336                 [DefaultValue (true)]
337                 public bool DynamicEnableDefaultPopOutImage {
338                         get {
339                                 object o = ViewState ["dedpoi"];
340                                 if (o != null) return (bool)o;
341                                 return true;
342                         }
343                         set {
344                                 ViewState["dedpoi"] = value;
345                         }
346                 }
347
348                 [DefaultValue (true)]
349                 public bool StaticEnableDefaultPopOutImage {
350                         get {
351                                 object o = ViewState ["sedpoi"];
352                                 if (o != null) return (bool)o;
353                                 return true;
354                         }
355                         set {
356                                 ViewState["sedpoi"] = value;
357                         }
358                 }
359
360                 [DefaultValueAttribute (null)]
361                 [PersistenceMode (PersistenceMode.InnerProperty)]
362                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
363                 [MergablePropertyAttribute (false)]
364                 public MenuItemCollection Items {
365                         get {
366                                 if (items == null) {
367                                         items = new MenuItemCollection (this);
368                                         if (IsTrackingViewState)
369                                                 ((IStateManager)items).TrackViewState();
370                                 }
371                                 return items;
372                         }
373                 }
374
375                 [DefaultValue ('/')]
376                 public char PathSeparator {
377                         get {
378                                 object o = ViewState ["PathSeparator"];
379                                 if(o != null) return (char)o;
380                                 return '/';
381                         }
382                         set {
383                                 ViewState ["PathSeparator"] = value;
384                         }
385                 }
386
387                 [DefaultValue (false)]
388                 public bool ItemWrap {
389                         get {
390                                 object o = ViewState ["ItemWrap"];
391                                 if(o != null) return (bool)o;
392                                 return false;
393                         }
394                         set {
395                                 ViewState ["ItemWrap"] = value;
396                         }
397                 }
398
399                 Style PopOutBoxStyle {
400                         get {
401                                 if (popOutBoxStyle == null) {
402                                         popOutBoxStyle = new Style ();
403                                         popOutBoxStyle.BackColor = Color.White;
404                                 }
405                                 return popOutBoxStyle;
406                         }
407                 }
408
409                 Style ControlLinkStyle {
410                         get {
411                                 if (controlLinkStyle == null) {
412                                         controlLinkStyle = new Style ();
413                                         controlLinkStyle.AlwaysRenderTextDecoration = true;
414                                 }
415                                 return controlLinkStyle;
416                         }
417                 }
418
419                 Style DynamicMenuItemLinkStyle {
420                         get {
421                                 if (dynamicMenuItemLinkStyle == null) {
422                                         dynamicMenuItemLinkStyle = new Style ();
423                                 }
424                                 return dynamicMenuItemLinkStyle;
425                         }
426                 }
427
428                 Style StaticMenuItemLinkStyle {
429                         get {
430                                 if (staticMenuItemLinkStyle == null) {
431                                         staticMenuItemLinkStyle = new Style ();
432                                 }
433                                 return staticMenuItemLinkStyle;
434                         }
435                 }
436
437                 Style DynamicSelectedLinkStyle {
438                         get {
439                                 if (dynamicSelectedLinkStyle == null) {
440                                         dynamicSelectedLinkStyle = new Style ();
441                                 }
442                                 return dynamicSelectedLinkStyle;
443                         }
444                 }
445
446                 Style StaticSelectedLinkStyle {
447                         get {
448                                 if (staticSelectedLinkStyle == null) {
449                                         staticSelectedLinkStyle = new Style ();
450                                 }
451                                 return staticSelectedLinkStyle;
452                         }
453                 }
454
455                 Style DynamicHoverLinkStyle {
456                         get {
457                                 if (dynamicHoverLinkStyle == null) {
458                                         dynamicHoverLinkStyle = new Style ();
459                                 }
460                                 return dynamicHoverLinkStyle;
461                         }
462                 }
463
464                 Style StaticHoverLinkStyle {
465                         get {
466                                 if (staticHoverLinkStyle == null) {
467                                         staticHoverLinkStyle = new Style ();
468                                 }
469                                 return staticHoverLinkStyle;
470                         }
471                 }
472
473                 [PersistenceMode (PersistenceMode.InnerProperty)]
474                 [NotifyParentProperty (true)]
475                 [DefaultValue (null)]
476                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
477                 public MenuItemStyle DynamicMenuItemStyle {
478                         get {
479                                 if (dynamicMenuItemStyle == null) {
480                                         dynamicMenuItemStyle = new MenuItemStyle ();
481                                         if (IsTrackingViewState)
482                                                 dynamicMenuItemStyle.TrackViewState();
483                                 }
484                                 return dynamicMenuItemStyle;
485                         }
486                 }
487                 
488                 [PersistenceMode (PersistenceMode.InnerProperty)]
489                 [NotifyParentProperty (true)]
490                 [DefaultValue (null)]
491                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
492                 public MenuItemStyle DynamicSelectedStyle {
493                         get {
494                                 if (dynamicSelectedStyle == null) {
495                                         dynamicSelectedStyle = new MenuItemStyle ();
496                                         if (IsTrackingViewState)
497                                                 dynamicSelectedStyle.TrackViewState();
498                                 }
499                                 return dynamicSelectedStyle;
500                         }
501                 }
502                 
503                 [PersistenceMode (PersistenceMode.InnerProperty)]
504                 [NotifyParentProperty (true)]
505                 [DefaultValue (null)]
506                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
507                 public SubMenuStyle DynamicMenuStyle {
508                         get {
509                                 if (dynamicMenuStyle == null) {
510                                         dynamicMenuStyle = new SubMenuStyle ();
511                                         if (IsTrackingViewState)
512                                                 dynamicMenuStyle.TrackViewState();
513                                 }
514                                 return dynamicMenuStyle;
515                         }
516                 }
517                 
518                 [PersistenceMode (PersistenceMode.InnerProperty)]
519                 [NotifyParentProperty (true)]
520                 [DefaultValue (null)]
521                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
522                 public MenuItemStyle StaticMenuItemStyle {
523                         get {
524                                 if (staticMenuItemStyle == null) {
525                                         staticMenuItemStyle = new MenuItemStyle ();
526                                         if (IsTrackingViewState)
527                                                 staticMenuItemStyle.TrackViewState();
528                                 }
529                                 return staticMenuItemStyle;
530                         }
531                 }
532                 
533                 [PersistenceMode (PersistenceMode.InnerProperty)]
534                 [NotifyParentProperty (true)]
535                 [DefaultValue (null)]
536                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
537                 public MenuItemStyle StaticSelectedStyle {
538                         get {
539                                 if (staticSelectedStyle == null) {
540                                         staticSelectedStyle = new MenuItemStyle ();
541                                         if (IsTrackingViewState)
542                                                 staticSelectedStyle.TrackViewState();
543                                 }
544                                 return staticSelectedStyle;
545                         }
546                 }
547                 
548                 [PersistenceMode (PersistenceMode.InnerProperty)]
549                 [NotifyParentProperty (true)]
550                 [DefaultValue (null)]
551                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
552                 public SubMenuStyle StaticMenuStyle {
553                         get {
554                                 if (staticMenuStyle == null) {
555                                         staticMenuStyle = new SubMenuStyle ();
556                                         if (IsTrackingViewState)
557                                                 staticMenuStyle.TrackViewState();
558                                 }
559                                 return staticMenuStyle;
560                         }
561                 }
562
563                 [DefaultValue (null)]
564                 [PersistenceMode (PersistenceMode.InnerProperty)]
565                 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
566                 public MenuItemStyleCollection LevelMenuItemStyles {
567                         get {
568                                 if (levelMenuItemStyles == null) {
569                                         levelMenuItemStyles = new MenuItemStyleCollection ();
570                                         if (IsTrackingViewState)
571                                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
572                                 }
573                                 return levelMenuItemStyles;
574                         }
575                 }
576
577                 [DefaultValue (null)]
578                 [PersistenceMode (PersistenceMode.InnerProperty)]
579                 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
580                 public MenuItemStyleCollection LevelSelectedStyles {
581                         get {
582                                 if (levelSelectedStyles == null) {
583                                         levelSelectedStyles = new MenuItemStyleCollection ();
584                                         if (IsTrackingViewState)
585                                                 ((IStateManager)levelSelectedStyles).TrackViewState();
586                                 }
587                                 return levelSelectedStyles;
588                         }
589                 }
590
591                 [DefaultValue (null)]
592                 [PersistenceMode (PersistenceMode.InnerProperty)]
593                 [Editor ("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
594                 public SubMenuStyleCollection LevelSubMenuStyles {
595                         get {
596                                 if (levelSubMenuStyles == null) {
597                                         levelSubMenuStyles = new SubMenuStyleCollection ();
598                                         if (IsTrackingViewState)
599                                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
600                                 }
601                                 return levelSubMenuStyles;
602                         }
603                 }
604
605                 [PersistenceMode (PersistenceMode.InnerProperty)]
606                 [NotifyParentProperty (true)]
607                 [DefaultValue (null)]
608                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
609                 public Style DynamicHoverStyle {
610                         get {
611                                 if (dynamicHoverStyle == null) {
612                                         dynamicHoverStyle = new Style ();
613                                         if (IsTrackingViewState)
614                                                 dynamicHoverStyle.TrackViewState();
615                                 }
616                                 return dynamicHoverStyle;
617                         }
618                 }
619                 
620                 [PersistenceMode (PersistenceMode.InnerProperty)]
621                 [NotifyParentProperty (true)]
622                 [DefaultValue (null)]
623                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
624                 public Style StaticHoverStyle {
625                         get {
626                                 if (staticHoverStyle == null) {
627                                         staticHoverStyle = new Style ();
628                                         if (IsTrackingViewState)
629                                                 staticHoverStyle.TrackViewState();
630                                 }
631                                 return staticHoverStyle;
632                         }
633                 }
634                 
635                 [DefaultValue ("")]
636                 [UrlProperty]
637                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
638                 public string ScrollDownImageUrl {
639                         get {
640                                 object o = ViewState ["sdiu"];
641                                 if (o != null) return (string)o;
642                                 return "";
643                         }
644                         set {
645                                 ViewState["sdiu"] = value;
646                         }
647                 }
648
649                 [DefaultValue ("")]
650                 [UrlProperty]
651                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
652                 public string ScrollUpImageUrl {
653                         get {
654                                 object o = ViewState ["suiu"];
655                                 if (o != null) return (string)o;
656                                 return "";
657                         }
658                         set {
659                                 ViewState["suiu"] = value;
660                         }
661                 }
662
663                 [Localizable (true)]
664                 public string ScrollDownText {
665                         get {
666                                 object o = ViewState ["ScrollDownText"];
667                                 if (o != null) return (string) o;
668                                 return Locale.GetText ("Scroll down");
669                         }
670                         set {
671                                 ViewState["ScrollDownText"] = value;
672                         }
673                 }
674
675                 [Localizable (true)]
676                 public string ScrollUpText {
677                         get {
678                                 object o = ViewState ["ScrollUpText"];
679                                 if (o != null) return (string) o;
680                                 return Locale.GetText ("Scroll up");
681                         }
682                         set {
683                                 ViewState["ScrollUpText"] = value;
684                         }
685                 }
686
687                 public string DynamicPopOutImageTextFormatString 
688                 {
689                         get
690                         {
691                                 object o = ViewState ["dpoitf"];
692                                 if (o != null) return (string) o;
693                                 return Locale.GetText ("Expand {0}");
694                         }
695                         set
696                         {
697                                 ViewState ["dpoitf"] = value;
698                         }
699                 }
700                 
701
702                 [DefaultValue ("")]
703                 [UrlProperty]
704                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
705                 public string DynamicPopOutImageUrl {
706                         get {
707                                 object o = ViewState ["dpoiu"];
708                                 if (o != null) return (string)o;
709                                 return "";
710                         }
711                         set {
712                                 ViewState["dpoiu"] = value;
713                         }
714                 }
715
716                 public string StaticPopOutImageTextFormatString
717                 {
718                         get
719                         {
720                                 object o = ViewState ["spoitf"];
721                                 if (o != null) return (string) o;
722                                 return Locale.GetText ("Expand {0}");
723                         }
724                         set
725                         {
726                                 ViewState ["spoitf"] = value;
727                         }
728                 }
729
730
731                 [DefaultValue ("")]
732                 [UrlProperty]
733                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
734                 public string StaticPopOutImageUrl {
735                         get {
736                                 object o = ViewState ["spoiu"];
737                                 if (o != null) return (string)o;
738                                 return "";
739                         }
740                         set {
741                                 ViewState["spoiu"] = value;
742                         }
743                 }
744
745                 [DefaultValue ("")]
746                 public string Target {
747                         get {
748                                 object o = ViewState ["Target"];
749                                 if (o != null) return (string) o;
750                                 return "";
751                         }
752                         set {
753                                 ViewState["Target"] = value;
754                         }
755                 }
756
757                 [DefaultValue (null)]
758                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
759                 [PersistenceMode (PersistenceMode.InnerProperty)]
760                 [Browsable (false)]
761                 public ITemplate StaticItemTemplate {
762                         get { return staticItemTemplate; }
763                         set { staticItemTemplate = value; }
764                 }
765                 
766                 [DefaultValue (null)]
767                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
768                 [PersistenceMode (PersistenceMode.InnerProperty)]
769                 [Browsable (false)]
770                 public ITemplate DynamicItemTemplate {
771                         get { return dynamicItemTemplate; }
772                         set { dynamicItemTemplate = value; }
773                 }
774                 
775                 [Browsable (false)]
776                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
777                 public MenuItem SelectedItem {
778                         get {
779                                 if (selectedItem == null && selectedItemPath != null) {
780                                         selectedItem = FindItemByPos (selectedItemPath);
781                                 }
782                                 
783                                 return selectedItem;
784                         }
785                 }
786
787                 [Browsable (false)]
788                 [DefaultValue ("")]
789                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
790                 public string SelectedValue {
791                         get { return selectedItem != null ? selectedItem.Value : ""; }
792                 }
793
794                 [Localizable (true)]
795                 public string SkipLinkText 
796                 {
797                         get {
798                                 object o = ViewState ["SkipLinkText"];
799                                 if (o != null)
800                                         return (string) o;
801                                 return "Skip Navigation Links";
802                         }
803                         set {
804                                 ViewState ["SkipLinkText"] = value;
805                         }
806                 }
807                 
808
809                 internal void SetSelectedItem (MenuItem item)
810                 {
811                         if (selectedItem == item) return;
812                         selectedItem = item;
813                         selectedItemPath = item.Path;
814                 }
815                 
816                 public MenuItem FindItem (string valuePath)
817                 {
818                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
819                         string[] path = valuePath.Split (PathSeparator);
820                         int n = 0;
821                         MenuItemCollection col = Items;
822                         bool foundBranch = true;
823                         while (col.Count > 0 && foundBranch) {
824                                 foundBranch = false;
825                                 foreach (MenuItem item in col) {
826                                         if (item.Value == path [n]) {
827                                                 if (++n == path.Length) return item;
828                                                 col = item.ChildItems;
829                                                 foundBranch = true;
830                                                 break;
831                                         }
832                                 }
833                         }
834                         return null;
835                 }
836                 
837                 string GetBindingKey (string dataMember, int depth)
838                 {
839                         return dataMember + " " + depth;
840                 }
841                 
842                 internal MenuItemBinding FindBindingForItem (string type, int depth)
843                 {
844                         if (bindings == null) return null;
845
846                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
847                         if (bin != null) return bin;
848                         
849                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
850                         if (bin != null) return bin;
851                         
852                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
853                         if (bin != null) return bin;
854                         
855                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
856                         return bin;
857                 }
858                 
859                 protected internal override void PerformDataBinding ()
860                 {
861                         base.PerformDataBinding ();
862
863                         // Do not attempt to bind data if there is no
864                         // data source set.
865                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
866                                 EnsureChildControlsDataBound ();
867                                 return;
868                         }
869
870                         InitializeDataBindings ();
871
872                         HierarchicalDataSourceView data = GetData ("");
873
874                         if (data == null) {
875                                 throw new InvalidOperationException ("No view returned by data source control.");
876                         }
877                         Items.Clear ();
878                         IHierarchicalEnumerable e = data.Select ();
879                         FillBoundChildrenRecursive (e, Items);
880
881                         CreateChildControlsForItems ();
882                         ChildControlsCreated = true;
883
884                         EnsureChildControlsDataBound ();
885                 }
886
887                 void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, MenuItemCollection itemCollection)
888                 {
889                         if (hEnumerable == null)
890                                 return;
891                         foreach (object obj in hEnumerable) {
892                                 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
893                                 MenuItem item = new MenuItem ();
894                                 itemCollection.Add (item);
895                                 item.Bind (hdata);
896
897                                 SiteMapNode siteMapNode = hdata as SiteMapNode;
898                                 if (siteMapNode != null) {
899                                         if (_currSiteMapNode == null)
900                                                 _currSiteMapNode = siteMapNode.Provider.CurrentNode;
901                                         if (siteMapNode == _currSiteMapNode)
902                                                 item.Selected = true;
903                                 }
904                                 
905                                 OnMenuItemDataBound (new MenuEventArgs (item));
906
907                                 if (hdata == null || !hdata.HasChildren)
908                                         continue;
909
910                                 IHierarchicalEnumerable e = hdata.GetChildren ();
911                                 FillBoundChildrenRecursive (e, item.ChildItems);
912                         }
913                 }
914                 
915                 protected void SetItemDataBound (MenuItem node, bool dataBound)
916                 {
917                         node.SetDataBound (dataBound);
918                 }
919                 
920                 protected void SetItemDataPath (MenuItem node, string dataPath)
921                 {
922                         node.SetDataPath (dataPath);
923                 }
924                 
925                 protected void SetItemDataItem (MenuItem node, object dataItem)
926                 {
927                         node.SetDataItem (dataItem);
928                 }
929                 
930                 protected internal virtual void RaisePostBackEvent (string eventArgument)
931                 {
932                         ValidateEvent (UniqueID, eventArgument);
933                         if (!IsEnabled)
934                                 return;
935
936                         EnsureChildControls();
937                         MenuItem item = FindItemByPos (eventArgument);
938                         if (item == null) return;
939                         item.Selected = true;
940                         OnMenuItemClick (new MenuEventArgs (item));
941                 }
942
943                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
944                 {
945                         RaisePostBackEvent (eventArgument);
946                 }
947                 
948                 MenuItem FindItemByPos (string path)
949                 {
950                         string[] indexes = path.Split ('_');
951                         MenuItem item = null;
952                         
953                         foreach (string index in indexes) {
954                                 int i = int.Parse (index);
955                                 if (item == null) {
956                                         if (i >= Items.Count) return null;
957                                         item = Items [i];
958                                 } else {
959                                         if (i >= item.ChildItems.Count) return null;
960                                         item = item.ChildItems [i];
961                                 }
962                         }
963                         return item;
964                 }
965                 
966                 protected override HtmlTextWriterTag TagKey {
967                         get { return HtmlTextWriterTag.Table; }
968                 }
969                 
970                 protected override void TrackViewState()
971                 {
972                         EnsureDataBound ();
973                         
974                         base.TrackViewState();
975                         if (dataBindings != null) {
976                                 ((IStateManager)dataBindings).TrackViewState ();
977                         }
978                         if (items != null) {
979                                 ((IStateManager)items).TrackViewState();
980                         }
981                         if (dynamicMenuItemStyle != null)
982                                 dynamicMenuItemStyle.TrackViewState ();
983                         if (dynamicMenuStyle != null)
984                                 dynamicMenuStyle.TrackViewState ();
985                         if (levelMenuItemStyles != null && levelMenuItemStyles.Count > 0)
986                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
987                         if (levelSelectedStyles != null && levelMenuItemStyles.Count > 0)
988                                 ((IStateManager)levelSelectedStyles).TrackViewState();
989                         if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0)
990                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
991                         if (dynamicSelectedStyle != null)
992                                 dynamicSelectedStyle.TrackViewState();
993                         if (staticMenuItemStyle != null)
994                                 staticMenuItemStyle.TrackViewState ();
995                         if (staticMenuStyle != null)
996                                 staticMenuStyle.TrackViewState ();
997                         if (staticSelectedStyle != null)
998                                 staticSelectedStyle.TrackViewState();
999                         if (staticHoverStyle != null)
1000                                 staticHoverStyle.TrackViewState();
1001                         if (dynamicHoverStyle != null)
1002                                 dynamicHoverStyle.TrackViewState();
1003                 }
1004
1005                 protected override object SaveViewState()
1006                 {
1007                         object[] states = new object [14];
1008                         states[0] = base.SaveViewState ();
1009                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
1010                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
1011                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
1012                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
1013                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
1014                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
1015                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
1016                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
1017                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
1018                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
1019                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
1020                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
1021                         states[13] = levelSubMenuStyles == null ? null : ((IStateManager)levelSubMenuStyles).SaveViewState();
1022
1023                         for (int i = states.Length - 1; i >= 0; i--) {
1024                                 if (states [i] != null)
1025                                         return states;
1026                         }
1027
1028                         return null;
1029                 }
1030
1031                 protected override void LoadViewState (object savedState)
1032                 {
1033                         if (savedState == null)
1034                                 return;
1035
1036                         object [] states = (object []) savedState;
1037                         base.LoadViewState (states[0]);
1038                         
1039                         if (states[1] != null)
1040                                 ((IStateManager)DataBindings).LoadViewState(states[1]);
1041                         if (states[2] != null)
1042                                 ((IStateManager)Items).LoadViewState(states[2]);
1043                         if (states[3] != null)
1044                                 DynamicMenuItemStyle.LoadViewState (states[3]);
1045                         if (states[4] != null)
1046                                 DynamicMenuStyle.LoadViewState (states[4]);
1047                         if (states[5] != null)
1048                                 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
1049                         if (states[6] != null)
1050                                 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
1051                         if (states[7] != null)
1052                                 DynamicSelectedStyle.LoadViewState (states[7]);
1053                         if (states[8] != null)
1054                                 StaticMenuItemStyle.LoadViewState (states[8]);
1055                         if (states[9] != null)
1056                                 StaticMenuStyle.LoadViewState (states[9]);
1057                         if (states[10] != null)
1058                                 StaticSelectedStyle.LoadViewState (states[10]);
1059                         if (states[11] != null)
1060                                 StaticHoverStyle.LoadViewState (states[11]);
1061                         if (states[12] != null)
1062                                 DynamicHoverStyle.LoadViewState (states[12]);
1063                         if (states[13] != null)
1064                                 ((IStateManager)LevelSubMenuStyles).LoadViewState(states[13]);
1065                 }
1066                 
1067                 protected internal override void OnInit (EventArgs e)
1068                 {
1069                         Page.RegisterRequiresControlState (this);
1070                         base.OnInit (e);
1071                 }
1072                 
1073                 protected internal override void LoadControlState (object ob)
1074                 {
1075                         if (ob == null) return;
1076                         object[] state = (object[]) ob;
1077                         base.LoadControlState (state[0]);
1078                         selectedItemPath = state[1] as string;
1079                 }
1080                 
1081                 protected internal override object SaveControlState ()
1082                 {
1083                         object bstate = base.SaveControlState ();
1084                         object mstate = selectedItemPath;
1085                         
1086                         if (bstate != null || mstate != null)
1087                                 return new object[] { bstate, mstate };
1088                         else
1089                                 return null;
1090                 }
1091                 
1092                 protected internal override void CreateChildControls ()
1093                 {
1094                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
1095                                 CreateChildControlsForItems ();
1096                         }
1097                         else {
1098                                 EnsureDataBound ();
1099                         }
1100                 }
1101
1102                 void CreateChildControlsForItems () {
1103                         Controls.Clear ();
1104                         // Check for HasChildViewState to avoid unnecessary calls to ClearChildViewState.
1105                         if (HasChildViewState)
1106                                 ClearChildViewState ();
1107                         _menuItemControls = new Hashtable ();
1108                         CreateChildControlsForItems (Items);
1109                         _requiresChildControlsDataBinding = true;
1110                 }
1111
1112                 void CreateChildControlsForItems (MenuItemCollection items ) {
1113                         foreach (MenuItem item in items) {
1114                                 bool isDynamicItem = IsDynamicItem (item);
1115                                 if (isDynamicItem && dynamicItemTemplate != null) {
1116                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1117                                         dynamicItemTemplate.InstantiateIn (cter);
1118                                         _menuItemControls [item] = cter;
1119                                         Controls.Add (cter);
1120                                 }
1121                                 else if (!isDynamicItem && staticItemTemplate != null) {
1122                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1123                                         staticItemTemplate.InstantiateIn (cter);
1124                                         _menuItemControls [item] = cter;
1125                                         Controls.Add (cter);
1126                                 }
1127                                 if (item.HasChildData)
1128                                         CreateChildControlsForItems (item.ChildItems);
1129                         }
1130                 }
1131
1132                 protected override void EnsureDataBound ()
1133                 {
1134                         base.EnsureDataBound ();
1135                         
1136                         EnsureChildControlsDataBound ();
1137                 }
1138
1139                 void EnsureChildControlsDataBound () {
1140                         if (!_requiresChildControlsDataBinding)
1141                                 return;
1142                         DataBindChildren ();
1143                         _requiresChildControlsDataBinding = false;
1144                 }
1145
1146                 [MonoTODO ("Not implemented")]
1147                 protected override IDictionary GetDesignModeState ()
1148                 {
1149                         throw new NotImplementedException ();
1150                 }
1151
1152                 [MonoTODO ("Not implemented")]
1153                 protected override void SetDesignModeState (IDictionary data)
1154                 {
1155                         throw new NotImplementedException ();
1156                 }
1157                                 
1158                 public override ControlCollection Controls {
1159                         get { return base.Controls; }
1160                 }
1161                 
1162                 public sealed override void DataBind ()
1163                 {
1164                         base.DataBind ();
1165                 }
1166                 
1167                 protected override bool OnBubbleEvent (object source, EventArgs args)
1168                 {
1169                         if (!(args is CommandEventArgs))
1170                                 return false;
1171
1172                         MenuEventArgs menuArgs = args as MenuEventArgs;
1173                         if (menuArgs != null && string.Equals (menuArgs.CommandName, MenuItemClickCommandName))
1174                                 OnMenuItemClick (menuArgs);
1175                         return true;
1176                 }
1177
1178                 protected override void OnDataBinding (EventArgs e)
1179                 {
1180                         EnsureChildControls ();
1181                         base.OnDataBinding (e);
1182                 }
1183
1184                 const string onPreRenderScript = "var {0} = new Object ();\n{0}.webForm = {1};\n{0}.disappearAfter = {2};\n{0}.vertical = {3};";
1185                 
1186                 protected internal override void OnPreRender (EventArgs e)
1187                 {
1188                         base.OnPreRender (e);
1189                         
1190                         if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
1191                                 string url = Page.ClientScript.GetWebResourceUrl (typeof(Menu), "Menu.js");
1192                                 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
1193                         }
1194                         
1195                         string cmenu = ClientID + "_data";
1196                         string script = String.Format (onPreRenderScript,
1197                                                        cmenu,
1198                                                        Page.IsMultiForm ? Page.theForm : "window",
1199                                                        ClientScriptManager.GetScriptLiteral (DisappearAfter),
1200                                                        ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));                     
1201
1202                         if (DynamicHorizontalOffset != 0)
1203                                 script += String.Concat (cmenu, ".dho = ", ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset), ";\n");
1204                         if (DynamicVerticalOffset != 0)
1205                                 script += String.Concat (cmenu, ".dvo = ", ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset), ";\n");
1206                         
1207                         // The order in which styles are defined matters when more than one class
1208                         // is assigned to an element
1209                         RegisterStyle (PopOutBoxStyle);
1210                         RegisterStyle (ControlStyle, ControlLinkStyle);
1211                         
1212                         if (staticMenuItemStyle != null)
1213                                 RegisterStyle (StaticMenuItemStyle, StaticMenuItemLinkStyle);
1214
1215                         if (staticMenuStyle != null)
1216                                 RegisterStyle (StaticMenuStyle);
1217                         
1218                         if (dynamicMenuItemStyle != null)
1219                                 RegisterStyle (DynamicMenuItemStyle, DynamicMenuItemLinkStyle);
1220
1221                         if (dynamicMenuStyle != null)
1222                                 RegisterStyle (DynamicMenuStyle);
1223
1224                         if (levelMenuItemStyles != null && levelMenuItemStyles.Count > 0) {
1225                                 levelMenuItemLinkStyles = new List<Style> (levelMenuItemStyles.Count);
1226                                 foreach (Style style in levelMenuItemStyles) {
1227                                         Style linkStyle = new Style ();
1228                                         levelMenuItemLinkStyles.Add (linkStyle);
1229                                         RegisterStyle (style, linkStyle);
1230                                 }
1231                         }
1232                 
1233                         if (levelSubMenuStyles != null)
1234                                 foreach (Style style in levelSubMenuStyles)
1235                                         RegisterStyle (style);
1236
1237                         if (staticSelectedStyle != null)
1238                                 RegisterStyle (staticSelectedStyle, StaticSelectedLinkStyle);
1239                         
1240                         if (dynamicSelectedStyle != null)
1241                                 RegisterStyle (dynamicSelectedStyle, DynamicSelectedLinkStyle);
1242
1243                         if (levelSelectedStyles != null && levelSelectedStyles.Count > 0) {
1244                                 levelSelectedLinkStyles = new List<Style> (levelSelectedStyles.Count);
1245                                 foreach (Style style in levelSelectedStyles) {
1246                                         Style linkStyle = new Style ();
1247                                         levelSelectedLinkStyles.Add (linkStyle);
1248                                         RegisterStyle (style, linkStyle);
1249                                 }
1250                         }
1251                         
1252                         if (staticHoverStyle != null) {
1253                                 if (Page.Header == null)
1254                                         throw new InvalidOperationException ("Using Menu.StaticHoverStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1255                                 RegisterStyle (staticHoverStyle, StaticHoverLinkStyle);
1256                                 script += string.Concat (cmenu, ".staticHover = ", ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass), ";\n");
1257                                 script += string.Concat (cmenu, ".staticLinkHover = ", ClientScriptManager.GetScriptLiteral (StaticHoverLinkStyle.RegisteredCssClass), ";\n");
1258                         }
1259                         
1260                         if (dynamicHoverStyle != null) {
1261                                 if (Page.Header == null)
1262                                         throw new InvalidOperationException ("Using Menu.DynamicHoverStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1263                                 RegisterStyle (dynamicHoverStyle, DynamicHoverLinkStyle);
1264                                 script += string.Concat (cmenu, ".dynamicHover = ", ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass), ";\n");
1265                                 script += string.Concat (cmenu, ".dynamicLinkHover = ", ClientScriptManager.GetScriptLiteral (DynamicHoverLinkStyle.RegisteredCssClass), ";\n");
1266                         }
1267
1268                         Page.ClientScript.RegisterWebFormClientScript ();
1269                         Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
1270
1271                 }
1272
1273                 void InitializeDataBindings () {
1274                         if (dataBindings != null && dataBindings.Count > 0) {
1275                                 bindings = new Hashtable ();
1276                                 foreach (MenuItemBinding bin in dataBindings) {
1277                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
1278                                         bindings [key] = bin;
1279                                 }
1280                         }
1281                         else
1282                                 bindings = null;
1283                 }
1284
1285                 string IncrementStyleClassName () {
1286                         registeredStylesCounter++;
1287                         return ClientID + "_" + registeredStylesCounter;
1288                 }
1289
1290                 void RegisterStyle (Style baseStyle, Style linkStyle) {
1291                         linkStyle.CopyTextStylesFrom (baseStyle);
1292                         linkStyle.BorderStyle = BorderStyle.None;
1293                         RegisterStyle (linkStyle);
1294                         RegisterStyle (baseStyle);
1295                 }
1296
1297                 void RegisterStyle (Style baseStyle)
1298                 {
1299                         if (Page.Header == null)
1300                                 return;
1301                         string className = IncrementStyleClassName ();
1302                         baseStyle.SetRegisteredCssClass (className);
1303                         Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
1304                 }
1305                 
1306                 protected internal override void Render (HtmlTextWriter writer)
1307                 {
1308                         if (Items.Count > 0)
1309                                 base.Render (writer);
1310                 }
1311                 
1312                 protected override void AddAttributesToRender (HtmlTextWriter writer)
1313                 {
1314                         writer.AddAttribute ("cellpadding", "0", false);
1315                         writer.AddAttribute ("cellspacing", "0", false);
1316                         writer.AddAttribute ("border", "0", false);
1317                         if (Page.Header != null) {
1318                                 // styles are registered
1319                                 if (staticMenuStyle != null) {
1320                                         AddCssClass (ControlStyle, staticMenuStyle.CssClass);
1321                                         AddCssClass (ControlStyle, staticMenuStyle.RegisteredCssClass);
1322                                 }
1323                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0) {
1324                                         AddCssClass (ControlStyle, levelSubMenuStyles [0].CssClass);
1325                                         AddCssClass (ControlStyle, levelSubMenuStyles [0].RegisteredCssClass);
1326                                 }
1327                         }
1328                         else {
1329                                 // styles are not registered
1330                                 if (staticMenuStyle != null){
1331                                         ControlStyle.CopyFrom (staticMenuStyle);
1332                                 }
1333                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0) {
1334                                         ControlStyle.CopyFrom (levelSubMenuStyles [0]);
1335                                 }
1336                         }
1337                         base.AddAttributesToRender (writer);
1338                 }
1339
1340                 void AddCssClass (Style style, string cssClass) {
1341                         style.AddCssClass (cssClass);
1342                 }
1343                 
1344                 public override void RenderBeginTag (HtmlTextWriter writer)
1345                 {
1346                         string skipLinkText = SkipLinkText;
1347                         if (!String.IsNullOrEmpty (skipLinkText)) {
1348                                 // <a href="#ID_SkipLink">
1349                                 writer.AddAttribute (HtmlTextWriterAttribute.Href, "#" + ClientID + "_SkipLink");
1350                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1351                                 
1352                                 // <img alt="" height="0" width="0" src="" style="border-width:0px;"/>
1353                                 writer.AddAttribute (HtmlTextWriterAttribute.Alt, skipLinkText);
1354                                 writer.AddAttribute (HtmlTextWriterAttribute.Height, "0");
1355                                 writer.AddAttribute (HtmlTextWriterAttribute.Width, "0");
1356                                 
1357                                 Page page = Page;
1358                                 ClientScriptManager csm;
1359                                 
1360                                 if (page != null)
1361                                         csm = page.ClientScript;
1362                                 else
1363                                         csm = new ClientScriptManager (null);
1364                                 writer.AddAttribute (HtmlTextWriterAttribute.Src, csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif"));
1365                                 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0px");
1366                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1367                                 writer.RenderEndTag ();
1368                                 
1369                                 writer.RenderEndTag (); // </a>
1370                         }
1371                         base.RenderBeginTag (writer);
1372                 }
1373                 
1374                 public override void RenderEndTag (HtmlTextWriter writer)
1375                 {
1376                         base.RenderEndTag (writer);
1377
1378                         if (StaticDisplayLevels == 1 && MaximumDynamicDisplayLevels > 0)
1379                                 RenderDynamicMenu (writer, Items);
1380
1381                         string skipLinkText = SkipLinkText;
1382                         if (!String.IsNullOrEmpty (skipLinkText)) {
1383                                 writer.AddAttribute (HtmlTextWriterAttribute.Id, "SkipLink");
1384                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1385                                 writer.RenderEndTag ();
1386                         }
1387                 }
1388                 
1389                 protected internal override void RenderContents (HtmlTextWriter writer)
1390                 {
1391                         RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false, false);
1392                 }
1393
1394                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItemCollection items) {
1395                         for (int n = 0; n < items.Count; n++) {
1396                                 if (DisplayChildren (items [n])) {
1397                                         RenderDynamicMenu (writer, items [n]);
1398                                         RenderDynamicMenu (writer, items [n].ChildItems);
1399                                 }
1400                         }
1401                 }
1402                 
1403                 MenuRenderHtmlTemplate _dynamicTemplate;
1404                 MenuRenderHtmlTemplate GetDynamicMenuTemplate (MenuItem item)
1405                 {
1406                         if (_dynamicTemplate != null) 
1407                                 return _dynamicTemplate;
1408
1409                         _dynamicTemplate = new MenuRenderHtmlTemplate ();
1410                         HtmlTextWriter writer = _dynamicTemplate.GetMenuTemplateWriter ();
1411
1412                         if (Page.Header != null) {
1413                                 writer.AddAttribute (HtmlTextWriterAttribute.Class, MenuRenderHtmlTemplate.GetMarker (0));
1414                         }
1415                         else {
1416                                 writer.AddAttribute (HtmlTextWriterAttribute.Style, MenuRenderHtmlTemplate.GetMarker (0));
1417                         }
1418
1419                         writer.AddStyleAttribute ("visibility", "hidden");
1420                         writer.AddStyleAttribute ("position", "absolute");
1421                         writer.AddStyleAttribute ("z-index", "1");
1422                         writer.AddStyleAttribute ("left", "0px");
1423                         writer.AddStyleAttribute ("top", "0px");
1424                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (1));
1425                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1426
1427                         // Up button
1428                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (2));
1429                         writer.AddStyleAttribute ("display", "block");
1430                         writer.AddStyleAttribute ("text-align", "center");
1431                         writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (3), "','u')"));
1432                         writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (4), "','u')")); 
1433                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1434                         
1435                         writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (5)); //src
1436                         writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (6)); //ScrollUpText
1437                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1438                         writer.RenderEndTag (); // IMG
1439                         
1440                         writer.RenderEndTag (); // DIV scroll button
1441                 
1442                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (7));
1443                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1444                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (8));
1445                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1446                         
1447                         // call of RenderMenu
1448                         writer.Write (MenuRenderHtmlTemplate.GetMarker (9));
1449                         
1450                         writer.RenderEndTag (); // DIV Content
1451                         writer.RenderEndTag (); // DIV Scroll container
1452
1453                         // Down button
1454                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (0));
1455                         writer.AddStyleAttribute ("display", "block");
1456                         writer.AddStyleAttribute ("text-align", "center");
1457                         writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (1), "','d')"));
1458                         writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (2), "','d')")); 
1459                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1460                         
1461                         writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (3)); //src
1462                         writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (4)); //ScrollDownText
1463                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1464                         writer.RenderEndTag (); // IMG
1465                         
1466                         writer.RenderEndTag (); // DIV scroll button
1467                         
1468                         writer.RenderEndTag (); // DIV menu
1469
1470                         _dynamicTemplate.Parse ();
1471                         return _dynamicTemplate;
1472                 }
1473
1474                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
1475                 {
1476                         _dynamicTemplate = GetDynamicMenuTemplate (item);
1477
1478                         string idPrefix = ClientID + "_" + item.Path;
1479                         string [] param = new string [9];
1480                         param [0] = GetCssMenuStyle (true, item.Depth + 1);
1481                         param [1] = idPrefix + "s";
1482                         param [2] = idPrefix + "cu";
1483                         param [3] = item.Path;
1484                         param [4] = item.Path;
1485                         param [5] = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_up.gif");
1486                         param [6] = ScrollUpText;
1487                         param [7] = idPrefix + "cb";
1488                         param [8] = idPrefix + "cc";
1489
1490                         _dynamicTemplate.RenderTemplate (writer, param, 0, param.Length);
1491
1492                         RenderMenu (writer, item.ChildItems, true, true, item.Depth + 1, false);
1493
1494                         string [] param2 = new string [5];
1495                         param2 [0] = idPrefix + "cd";
1496                         param2 [1] = item.Path;
1497                         param2 [2] = item.Path;
1498                         param2 [3] = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_down.gif");
1499                         param2 [4] = ScrollDownText;
1500
1501                         _dynamicTemplate.RenderTemplate (writer, param2, param.Length + 1, param2.Length);
1502
1503                 }
1504
1505                 string GetCssMenuStyle (bool dynamic, int menuLevel)
1506                 {
1507                         if (Page.Header != null) {
1508                                 // styles are registered
1509                                 StringBuilder sb = new StringBuilder ();
1510
1511                                 if (!dynamic && staticMenuStyle != null) {
1512                                         sb.Append (staticMenuStyle.CssClass);
1513                                         sb.Append (' ');
1514                                         sb.Append (staticMenuStyle.RegisteredCssClass);
1515                                 }
1516                                 if (dynamic && dynamicMenuStyle != null) {
1517                                         sb.Append (PopOutBoxStyle.RegisteredCssClass);
1518                                         sb.Append (' ');
1519                                         sb.Append (dynamicMenuStyle.CssClass);
1520                                         sb.Append (' ');
1521                                         sb.Append (dynamicMenuStyle.RegisteredCssClass);
1522                                 }
1523                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1524                                         sb.Append (levelSubMenuStyles [menuLevel].CssClass);
1525                                         sb.Append (' ');
1526                                         sb.Append (levelSubMenuStyles [menuLevel].RegisteredCssClass); 
1527                                 }
1528                                 return sb.ToString ();
1529                         }
1530                         else {
1531                                 // styles are not registered
1532                                 SubMenuStyle style = new SubMenuStyle ();
1533
1534                                 if (!dynamic && staticMenuStyle != null) {
1535                                         style.CopyFrom (staticMenuStyle);
1536                                 }
1537                                 if (dynamic && dynamicMenuStyle != null) {
1538                                         style.CopyFrom (PopOutBoxStyle);
1539                                         style.CopyFrom (dynamicMenuStyle);
1540                                 }
1541                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1542                                         style.CopyFrom (levelSubMenuStyles [menuLevel]);
1543                                 }
1544                                 return style.GetStyleAttributes (null).Value;
1545                         }
1546                 }
1547
1548                 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic, int menuLevel) {
1549                         writer.AddAttribute ("cellpadding", "0", false);
1550                         writer.AddAttribute ("cellspacing", "0", false);
1551                         writer.AddAttribute ("border", "0", false);
1552
1553                         if (!dynamic) {
1554                                 SubMenuStyle style = new SubMenuStyle ();
1555                                 FillMenuStyle (dynamic, menuLevel, style);
1556                                 style.AddAttributesToRender (writer);
1557                         }
1558                 }
1559
1560                 void FillMenuStyle (bool dynamic, int menuLevel, SubMenuStyle style) {
1561                         if (Page.Header != null) {
1562                                 // styles are registered
1563                                 if (!dynamic && staticMenuStyle != null) {
1564                                         AddCssClass (style, staticMenuStyle.CssClass);
1565                                         AddCssClass (style, staticMenuStyle.RegisteredCssClass);
1566                                 }
1567                                 if (dynamic && dynamicMenuStyle != null) {
1568                                         AddCssClass (style, dynamicMenuStyle.CssClass);
1569                                         AddCssClass (style, dynamicMenuStyle.RegisteredCssClass);
1570                                 }
1571                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1572                                         AddCssClass (style, levelSubMenuStyles [menuLevel].CssClass);
1573                                         AddCssClass (style, levelSubMenuStyles [menuLevel].RegisteredCssClass);
1574                                 }
1575                         }
1576                         else {
1577                                 // styles are not registered
1578                                 if (!dynamic && staticMenuStyle != null) {
1579                                         style.CopyFrom (staticMenuStyle);
1580                                 }
1581                                 if (dynamic && dynamicMenuStyle != null) {
1582                                         style.CopyFrom (dynamicMenuStyle);
1583                                 }
1584                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1585                                         style.CopyFrom (levelSubMenuStyles [menuLevel]);
1586                                 }
1587                         }
1588                 }
1589
1590                 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, int menuLevel, bool notLast)
1591                 {
1592                         RenderMenuBeginTag (writer, dynamic, menuLevel);
1593                         RenderMenuBody (writer, items, vertical, dynamic, notLast);
1594                         RenderMenuEndTag (writer);
1595                 }
1596                 
1597                 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic, int menuLevel)
1598                 {
1599                         RenderMenuBeginTagAttributes (writer, dynamic, menuLevel);
1600                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1601                 }
1602                 
1603                 void RenderMenuEndTag (HtmlTextWriter writer)
1604                 {
1605                         writer.RenderEndTag ();
1606                 }
1607
1608                 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, bool notLast) {
1609                         if (!vertical)
1610                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1611
1612                         int count = items.Count;
1613                         for (int n = 0; n < count; n++) {
1614                                 MenuItem item = items [n];
1615                                 Adapters.MenuAdapter adapter = Adapter as Adapters.MenuAdapter;
1616                                 if (adapter != null)
1617                                         adapter.RenderItem (writer, item, n);
1618                                 else
1619                                         RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
1620                         }
1621
1622                         if (!vertical)
1623                                 writer.RenderEndTag (); // TR
1624                 }
1625
1626                 void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing, bool vertical) {
1627                         if (vertical) {
1628                                 writer.AddStyleAttribute ("height", itemSpacing.ToString ());
1629                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1630                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1631                                 writer.RenderEndTag ();
1632                                 writer.RenderEndTag ();
1633                         }
1634                         else {
1635                                 writer.AddStyleAttribute ("width", itemSpacing.ToString ());
1636                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1637                                 writer.RenderEndTag ();
1638                         }
1639                 }
1640                 
1641                 bool IsDynamicItem (MenuItem item) {
1642                         return item.Depth + 1 > StaticDisplayLevels;
1643                 }
1644
1645                 bool DisplayChildren (MenuItem item) {
1646                         return (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels) && item.ChildItems.Count > 0;
1647                 }
1648                 
1649                 internal void RenderItem (HtmlTextWriter writer, MenuItem item, int position) {
1650                         // notLast should be true if item or any of its ancestors is not a
1651                         // last child.
1652                         bool notLast = false;
1653                         MenuItem parent;
1654                         MenuItem child = item;                  
1655                         while (null != (parent = child.Parent)) {
1656                                 if (child.Index != parent.ChildItems.Count - 1) {
1657                                         notLast = true;
1658                                         break;
1659                                 }
1660                                 child = parent;
1661                         }
1662                         
1663                         RenderMenuItem (writer, item, notLast, position == 0);
1664                 }
1665                 
1666                 void RenderMenuItem (HtmlTextWriter writer, MenuItem item, bool notLast, bool isFirst) {
1667                         bool displayChildren = DisplayChildren (item);
1668                         bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels);
1669                         bool isDynamicItem = IsDynamicItem (item);
1670                         bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1671                         
1672                         Unit itemSpacing = GetItemSpacing (item, isDynamicItem);
1673
1674                         if (itemSpacing != Unit.Empty && (item.Depth > 0 || !isFirst))
1675                                 RenderMenuItemSpacing (writer, itemSpacing, vertical);
1676
1677                         if(!String.IsNullOrEmpty(item.ToolTip))
1678                                 writer.AddAttribute (HtmlTextWriterAttribute.Title, item.ToolTip);
1679                         if (vertical)
1680                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1681
1682                         string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1683                         if (dynamicChildren) {
1684                                 writer.AddAttribute ("onmouseover",
1685                                                      "javascript:Menu_OverItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1686                                 writer.AddAttribute ("onmouseout",
1687                                                      "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "')");
1688                         } else if (isDynamicItem) {
1689                                 writer.AddAttribute ("onmouseover",
1690                                                      "javascript:Menu_OverDynamicLeafItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1691                                 writer.AddAttribute ("onmouseout",
1692                                                      "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1693                         } else {
1694                                 writer.AddAttribute ("onmouseover",
1695                                                      "javascript:Menu_OverStaticLeafItem ('" + ClientID + "','" + item.Path + "')");
1696                                 writer.AddAttribute ("onmouseout",
1697                                                      "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "')");
1698                         }
1699
1700                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1701
1702                         // Top separator image
1703
1704                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1705                                 writer.AddAttribute ("src", ResolveClientUrl (DynamicTopSeparatorImageUrl));
1706                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1707                                 writer.RenderEndTag (); // IMG
1708                         }
1709                         else if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1710                                 writer.AddAttribute ("src", ResolveClientUrl (StaticTopSeparatorImageUrl));
1711                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1712                                 writer.RenderEndTag (); // IMG
1713                         }
1714
1715                         // Menu item box
1716                         
1717                         MenuItemStyle style = new MenuItemStyle ();
1718                         if (Page.Header != null) {
1719                                 // styles are registered
1720                                 if (!isDynamicItem && staticMenuItemStyle != null) {
1721                                         AddCssClass (style, staticMenuItemStyle.CssClass);
1722                                         AddCssClass (style, staticMenuItemStyle.RegisteredCssClass);
1723                                 }
1724                                 if (isDynamicItem && dynamicMenuItemStyle != null) {
1725                                         AddCssClass (style, dynamicMenuItemStyle.CssClass);
1726                                         AddCssClass (style, dynamicMenuItemStyle.RegisteredCssClass);
1727                                 }
1728                                 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1729                                         AddCssClass (style, levelMenuItemStyles [item.Depth].CssClass);
1730                                         AddCssClass (style, levelMenuItemStyles [item.Depth].RegisteredCssClass);
1731                                 }
1732                                 if (item == SelectedItem) {
1733                                         if (!isDynamicItem && staticSelectedStyle != null) {
1734                                                 AddCssClass (style, staticSelectedStyle.CssClass);
1735                                                 AddCssClass (style, staticSelectedStyle.RegisteredCssClass);
1736                                         }
1737                                         if (isDynamicItem && dynamicSelectedStyle != null) {
1738                                                 AddCssClass (style, dynamicSelectedStyle.CssClass);
1739                                                 AddCssClass (style, dynamicSelectedStyle.RegisteredCssClass);
1740                                         }
1741                                         if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1742                                                 AddCssClass (style, levelSelectedStyles [item.Depth].CssClass);
1743                                                 AddCssClass (style, levelSelectedStyles [item.Depth].RegisteredCssClass);
1744                                         }
1745                                 }
1746                         }
1747                         else {
1748                                 // styles are not registered
1749                                 if (!isDynamicItem && staticMenuItemStyle != null) {
1750                                         style.CopyFrom (staticMenuItemStyle);
1751                                 }
1752                                 if (isDynamicItem && dynamicMenuItemStyle != null) {
1753                                         style.CopyFrom (dynamicMenuItemStyle);
1754                                 }
1755                                 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1756                                         style.CopyFrom (levelMenuItemStyles [item.Depth]);
1757                                 }
1758                                 if (item == SelectedItem) {
1759                                         if (!isDynamicItem && staticSelectedStyle != null) {
1760                                                 style.CopyFrom (staticSelectedStyle);
1761                                         }
1762                                         if (isDynamicItem && dynamicSelectedStyle != null) {
1763                                                 style.CopyFrom (dynamicSelectedStyle);
1764                                         }
1765                                         if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1766                                                 style.CopyFrom (levelSelectedStyles [item.Depth]);
1767                                         }
1768                                 }
1769                         }
1770                         style.AddAttributesToRender (writer);
1771
1772                         writer.AddAttribute ("id", GetItemClientId (item, "i"));
1773
1774                         writer.AddAttribute ("cellpadding", "0", false);
1775                         writer.AddAttribute ("cellspacing", "0", false);
1776                         writer.AddAttribute ("border", "0", false);
1777                         writer.AddAttribute ("width", "100%", false);
1778                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1779                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1780
1781                         // Menu item text
1782
1783                         if (vertical)
1784                                 writer.AddStyleAttribute (HtmlTextWriterStyle.Width, "100%");
1785                         if (!ItemWrap)
1786                                 writer.AddStyleAttribute ("white-space", "nowrap");
1787                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1788
1789                         RenderItemHref (writer, item);
1790                         
1791                         Style linkStyle = new Style ();
1792                         if (Page.Header != null) {
1793                                 // styles are registered
1794                                 AddCssClass (linkStyle, ControlLinkStyle.RegisteredCssClass);
1795
1796                                 if (!isDynamicItem && staticMenuItemStyle != null) {
1797                                         AddCssClass (linkStyle, staticMenuItemStyle.CssClass);
1798                                         AddCssClass (linkStyle, staticMenuItemLinkStyle.RegisteredCssClass);
1799                                 }
1800                                 if (isDynamicItem && dynamicMenuItemStyle != null) {
1801                                         AddCssClass (linkStyle, dynamicMenuItemStyle.CssClass);
1802                                         AddCssClass (linkStyle, dynamicMenuItemLinkStyle.RegisteredCssClass);
1803                                 }
1804                                 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1805                                         AddCssClass (linkStyle, levelMenuItemStyles [item.Depth].CssClass);
1806                                         AddCssClass (linkStyle, levelMenuItemLinkStyles [item.Depth].RegisteredCssClass);
1807                                 }
1808                                 if (item == SelectedItem) {
1809                                         if (!isDynamicItem && staticSelectedStyle != null) {
1810                                                 AddCssClass (linkStyle, staticSelectedStyle.CssClass);
1811                                                 AddCssClass (linkStyle, staticSelectedLinkStyle.RegisteredCssClass);
1812                                         }
1813                                         if (isDynamicItem && dynamicSelectedStyle != null) {
1814                                                 AddCssClass (linkStyle, dynamicSelectedStyle.CssClass);
1815                                                 AddCssClass (linkStyle, dynamicSelectedLinkStyle.RegisteredCssClass);
1816                                         }
1817                                         if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1818                                                 AddCssClass (linkStyle, levelSelectedStyles [item.Depth].CssClass);
1819                                                 AddCssClass (linkStyle, levelSelectedLinkStyles [item.Depth].RegisteredCssClass);
1820                                         }
1821                                 }
1822                         }
1823                         else {
1824                                 // styles are not registered
1825                                 linkStyle.CopyFrom (ControlLinkStyle);
1826
1827                                 if (!isDynamicItem && staticMenuItemStyle != null) {
1828                                         linkStyle.CopyFrom (staticMenuItemLinkStyle);
1829                                 }
1830                                 if (isDynamicItem && dynamicMenuItemStyle != null) {
1831                                         linkStyle.CopyFrom (dynamicMenuItemLinkStyle);
1832                                 }
1833                                 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1834                                         linkStyle.CopyFrom (levelMenuItemLinkStyles [item.Depth]);
1835                                 }
1836                                 if (item == SelectedItem) {
1837                                         if (!isDynamicItem && staticSelectedStyle != null) {
1838                                                 linkStyle.CopyFrom (staticSelectedLinkStyle);
1839                                         }
1840                                         if (isDynamicItem && dynamicSelectedStyle != null) {
1841                                                 linkStyle.CopyFrom (dynamicSelectedLinkStyle);
1842                                         }
1843                                         if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1844                                                 linkStyle.CopyFrom (levelSelectedLinkStyles [item.Depth]);
1845                                         }
1846                                 }
1847
1848                                 linkStyle.AlwaysRenderTextDecoration = true;
1849                         }
1850                         linkStyle.AddAttributesToRender (writer);
1851
1852                         writer.AddAttribute ("id", GetItemClientId (item, "l"));
1853                         
1854                         if (item.Depth > 0 && !isDynamicItem) {
1855                                 double value;
1856 #if NET_4_0
1857                                 Unit unit = StaticSubMenuIndent;
1858                                 if (unit == Unit.Empty)
1859                                         value = 16;
1860                                 else
1861                                         value = unit.Value;
1862 #else
1863                                 value = StaticSubMenuIndent.Value;
1864 #endif
1865                                 Unit indent = new Unit (value * item.Depth, StaticSubMenuIndent.Type);
1866                                 writer.AddStyleAttribute (HtmlTextWriterStyle.MarginLeft, indent.ToString ());
1867                         }
1868                         writer.RenderBeginTag (HtmlTextWriterTag.A);
1869                         RenderItemContent (writer, item, isDynamicItem);
1870                         writer.RenderEndTag (); // A
1871
1872                         writer.RenderEndTag (); // TD
1873
1874                         // Popup image
1875
1876                         if (dynamicChildren) {
1877                                 string popOutImage = GetPopOutImage (item, isDynamicItem);
1878                                 if (popOutImage != null) {
1879                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1880                                         writer.AddAttribute ("src", ResolveClientUrl (popOutImage));
1881                                         writer.AddAttribute ("border", "0");
1882                                         string toolTip = String.Format (isDynamicItem ? DynamicPopOutImageTextFormatString : StaticPopOutImageTextFormatString, item.Text);
1883                                         writer.AddAttribute (HtmlTextWriterAttribute.Alt, toolTip);
1884                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1885                                         writer.RenderEndTag (); // IMG
1886                                         writer.RenderEndTag (); // TD
1887                                 }
1888                         }
1889
1890                         writer.RenderEndTag (); // TR
1891                         writer.RenderEndTag (); // TABLE
1892                         
1893                         writer.RenderEndTag (); // TD
1894
1895                         if (!vertical && itemSpacing == Unit.Empty && (notLast || (displayChildren && !dynamicChildren))) {
1896                                 writer.AddStyleAttribute ("width", "3px");
1897                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1898                                 writer.RenderEndTag ();
1899                         }
1900                         
1901                         // Bottom separator image
1902                         string separatorImg = item.SeparatorImageUrl;
1903                         if (separatorImg.Length == 0) {
1904                                 if (isDynamicItem)
1905                                         separatorImg = DynamicBottomSeparatorImageUrl;
1906                                 else
1907                                         separatorImg = StaticBottomSeparatorImageUrl;
1908                         }
1909                         if (separatorImg.Length > 0) {
1910                                 if (!vertical)
1911                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1912                                 writer.AddAttribute ("src", ResolveClientUrl (separatorImg));
1913                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1914                                 writer.RenderEndTag (); // IMG
1915                                 if (!vertical)
1916                                         writer.RenderEndTag (); // TD
1917                         }
1918
1919                         if (vertical)
1920                                 writer.RenderEndTag (); // TR
1921
1922                         if (itemSpacing != Unit.Empty)
1923                                 RenderMenuItemSpacing (writer, itemSpacing, vertical);
1924
1925                         // Submenu
1926
1927                         if (displayChildren && !dynamicChildren) {
1928                                 if (vertical)
1929                                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1930                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1931                                 writer.AddAttribute ("width", "100%");
1932                                 RenderMenu (writer, item.ChildItems, Orientation == Orientation.Vertical, false, item.Depth + 1, notLast);
1933                                 if (item.Depth + 2 == StaticDisplayLevels)
1934                                         RenderDynamicMenu (writer, item.ChildItems);
1935                                 writer.RenderEndTag (); // TD
1936                                 if (vertical)
1937                                         writer.RenderEndTag (); // TR
1938                         }
1939
1940                 }
1941
1942                 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem) {
1943                         if (_menuItemControls!=null && _menuItemControls [item] != null) {
1944                                 ((Control) _menuItemControls [item]).Render (writer);
1945                         }
1946                         else {
1947
1948                                 if (!String.IsNullOrEmpty (item.ImageUrl)) {
1949                                         writer.AddAttribute (HtmlTextWriterAttribute.Src, ResolveClientUrl (item.ImageUrl));
1950                                         writer.AddAttribute (HtmlTextWriterAttribute.Alt, item.ToolTip);
1951                                         writer.AddStyleAttribute (HtmlTextWriterStyle.BorderStyle, "none");
1952                                         writer.AddStyleAttribute (HtmlTextWriterStyle.VerticalAlign, "middle");
1953                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1954                                         writer.RenderEndTag (); // IMG
1955                                 }
1956
1957                                 if (isDynamicItem && DynamicItemFormatString.Length > 0) {
1958                                         writer.Write (String.Format (DynamicItemFormatString, item.Text));
1959                                 }
1960                                 else if (!isDynamicItem && StaticItemFormatString.Length > 0) {
1961                                         writer.Write (String.Format (StaticItemFormatString, item.Text));
1962                                 }
1963                                 else {
1964                                         writer.Write (item.Text);
1965                                 }
1966                         }
1967                 }
1968                         
1969                 Unit GetItemSpacing (MenuItem item, bool dynamic)
1970                 {
1971                         Unit itemSpacing = Unit.Empty;
1972                         
1973                         if (item.Selected) {
1974                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1975                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1976                                         if (itemSpacing != Unit.Empty) return itemSpacing;
1977                                 }
1978
1979                                 if (dynamic && dynamicSelectedStyle != null)
1980                                         itemSpacing = dynamicSelectedStyle.ItemSpacing;
1981                                 else if (!dynamic && staticSelectedStyle != null)
1982                                         itemSpacing = staticSelectedStyle.ItemSpacing;
1983                                 if (itemSpacing != Unit.Empty)
1984                                         return itemSpacing;
1985                         }
1986                         
1987                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1988                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1989                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1990                         }
1991
1992                         if (dynamic && dynamicMenuItemStyle != null)
1993                                 return dynamicMenuItemStyle.ItemSpacing;
1994                         else if (!dynamic && staticMenuItemStyle != null)
1995                                 return staticMenuItemStyle.ItemSpacing;
1996                         else
1997                                 return Unit.Empty;
1998                 }
1999                 
2000                 string GetPopOutImage (MenuItem item, bool isDynamicItem)
2001                 {
2002                         if (item.PopOutImageUrl != "")
2003                                 return item.PopOutImageUrl;
2004
2005                         if (isDynamicItem) {
2006                                 if (DynamicPopOutImageUrl != "")
2007                                         return DynamicPopOutImageUrl;
2008                                 if (DynamicEnableDefaultPopOutImage)
2009                                         return Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_plus.gif");
2010                         } else {
2011                                 if (StaticPopOutImageUrl != "")
2012                                         return StaticPopOutImageUrl;
2013                                 if (StaticEnableDefaultPopOutImage)
2014                                         return Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_plus.gif");
2015                         }
2016                         return null;
2017                 }
2018                         
2019                 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
2020                 {
2021                         if (!item.BranchEnabled) {
2022                                 writer.AddAttribute ("disabled", "true", false);
2023                         }
2024                         else if (!item.Selectable) {
2025                                 writer.AddAttribute ("href", "#", false);
2026                                 writer.AddStyleAttribute ("cursor", "text");
2027                         }
2028                         else if (item.NavigateUrl != "") {
2029                                 string target = item.Target != "" ? item.Target : Target;
2030 #if TARGET_J2EE
2031                                 string navUrl = ResolveClientUrl (item.NavigateUrl, String.Compare (target, "_blank", StringComparison.InvariantCultureIgnoreCase) != 0);
2032 #else
2033                                 string navUrl = ResolveClientUrl (item.NavigateUrl);
2034 #endif
2035                                 writer.AddAttribute ("href", navUrl);
2036                                 if (target != "")
2037                                         writer.AddAttribute ("target", target);
2038                         }
2039                         else {
2040                                 writer.AddAttribute ("href", GetClientEvent (item));
2041                         }
2042
2043                 }
2044                 
2045                 string GetItemClientId (MenuItem item, string sufix)
2046                 {
2047                         return ClientID + "_" + item.Path + sufix;
2048                 }
2049                 
2050                 string GetClientEvent (MenuItem item)
2051                 {
2052                         return Page.ClientScript.GetPostBackClientHyperlink (this, item.Path, true);
2053                 }
2054
2055                 class MenuTemplateWriter : TextWriter
2056                 {
2057                         char [] _buffer;
2058                         int _ptr = 0;
2059                         
2060                         public MenuTemplateWriter (char [] buffer)
2061                         {
2062                                 _buffer = buffer;
2063                         }
2064
2065                         public override Encoding Encoding
2066                         {
2067                                 get { return Encoding.Unicode; }
2068                         }
2069
2070                         public override void Write (char value)
2071                         {
2072                                 if (_ptr == _buffer.Length)
2073                                         EnsureCapacity ();
2074                                 
2075                                 _buffer [_ptr++] = value;
2076                         }
2077
2078                         public override void Write (string value)
2079                         {
2080                                 if (value == null)
2081                                         return;
2082
2083                                 if (_ptr + value.Length >= _buffer.Length)
2084                                         EnsureCapacity ();
2085
2086                                 for (int i = 0; i < value.Length; i++)
2087                                         _buffer [_ptr++] = value [i];
2088                         }
2089
2090                         void EnsureCapacity ()
2091                         {
2092                                 char [] tmpBuffer = new char [_buffer.Length * 2];
2093                                 Array.Copy (_buffer, tmpBuffer, _buffer.Length);
2094
2095                                 _buffer = tmpBuffer;
2096                         }
2097                 }
2098
2099                 class MenuRenderHtmlTemplate
2100                 {
2101                         public const string Marker = "\u093a\u093b\u0971";
2102                         char [] _templateHtml;
2103
2104                         MenuTemplateWriter _templateWriter;
2105                         ArrayList idxs = new ArrayList (32);
2106
2107                         public MenuRenderHtmlTemplate ()
2108                         {
2109                                 _templateHtml = new char [1024];
2110                                 _templateWriter = new MenuTemplateWriter (_templateHtml);
2111                         }
2112
2113                         public static string GetMarker (int num)
2114                         {
2115                                 char charNum = (char) ((int) '\u0971' + num);
2116                                 return string.Concat (Marker, charNum);
2117                         }
2118
2119                         public HtmlTextWriter GetMenuTemplateWriter()
2120                         {
2121                                 return new HtmlTextWriter (_templateWriter);
2122                         }
2123
2124                         public void Parse ()
2125                         {
2126                                 int mpos = 0;
2127                                 for (int i = 0; i < _templateHtml.Length; i++) {
2128                                         if (_templateHtml [i] == '\0') {
2129                                                 idxs.Add (i);
2130                                                 break;
2131                                         }
2132
2133                                         if (_templateHtml [i] != Marker [mpos]) {
2134                                                 mpos = 0;
2135                                                 continue;
2136                                         }
2137
2138                                         mpos++;
2139                                         if (mpos == Marker.Length) {
2140                                                 mpos = 0;
2141                                                 idxs.Add (i - Marker.Length + 1);
2142                                         }
2143                                 }
2144                         }
2145
2146                         public void RenderTemplate (HtmlTextWriter writer, string [] dynamicParts, int start, int count)
2147                         {
2148                                 if (idxs.Count == 0)
2149                                         return;
2150
2151                                 int partStart = 0;
2152                                 int partEnd = (start == 0) ? -Marker.Length - 1 : (int) idxs [start - 1];
2153                                 int di = 0;
2154
2155                                 int i = start;
2156                                 int total = start + count;
2157                                 for (; i < total; i++) {
2158
2159                                         partStart = partEnd + Marker.Length + 1;
2160                                         partEnd = (int) idxs [i];
2161                                         
2162                                         // write static part
2163                                         writer.Write (_templateHtml, partStart, partEnd - partStart);
2164
2165                                         // write synamic part
2166                                         di = (int) _templateHtml [partEnd + Marker.Length] - 0x971;
2167                                         writer.Write (dynamicParts [di]);
2168                                 }
2169
2170                                 partStart = partEnd + Marker.Length + 1;
2171                                 partEnd = (int) idxs [i];
2172
2173                                 writer.Write (_templateHtml, partStart, partEnd - partStart);
2174                         }
2175                 
2176                 }
2177         }
2178 }
2179
2180 #endif