System.Drawing: added email to icon and test file headers
[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-2010 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.UI.HtmlControls;
40 using System.Web.Handlers;
41 using System.Collections.Specialized;
42 using System.IO;
43 using System.Drawing;
44 using System.Collections.Generic;
45
46 namespace System.Web.UI.WebControls
47 {
48         [DefaultEvent ("MenuItemClick")]
49         [ControlValueProperty ("SelectedValue")]
50         [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51         [SupportsEventValidation]
52         public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
53         {
54                 IMenuRenderer renderer;
55                 
56                 MenuItemStyle dynamicMenuItemStyle;
57                 SubMenuStyle dynamicMenuStyle;
58                 MenuItemStyle dynamicSelectedStyle;
59                 MenuItemStyle staticMenuItemStyle;
60                 SubMenuStyle staticMenuStyle;
61                 MenuItemStyle staticSelectedStyle;
62                 Style staticHoverStyle;
63                 Style dynamicHoverStyle;
64
65                 MenuItemStyleCollection levelMenuItemStyles;
66                 MenuItemStyleCollection levelSelectedStyles;
67                 SubMenuStyleCollection levelSubMenuStyles;
68                 ITemplate staticItemTemplate;
69                 ITemplate dynamicItemTemplate;
70                 
71                 MenuItemCollection items;
72                 MenuItemBindingCollection dataBindings;
73                 MenuItem selectedItem;
74                 string selectedItemPath;
75                 Hashtable bindings;
76
77                 Hashtable _menuItemControls;
78                 bool _requiresChildControlsDataBinding;
79                 SiteMapNode _currSiteMapNode;
80                 List<Style> levelSelectedLinkStyles;
81                 List<Style> levelMenuItemLinkStyles;
82                 Style popOutBoxStyle;
83                 Style controlLinkStyle;
84                 Style dynamicMenuItemLinkStyle;
85                 Style staticMenuItemLinkStyle;
86                 Style dynamicSelectedLinkStyle;
87                 Style staticSelectedLinkStyle;
88                 Style dynamicHoverLinkStyle;
89                 Style staticHoverLinkStyle;
90 #if NET_4_0
91                 bool? renderList;
92                 bool includeStyleBlock = true;
93                 MenuRenderingMode renderingMode = MenuRenderingMode.Default;
94 #endif
95                 static readonly object MenuItemClickEvent = new object();
96                 static readonly object MenuItemDataBoundEvent = new object();
97                 
98                 public static readonly string MenuItemClickCommandName = "Click";
99                 
100                 public event MenuEventHandler MenuItemClick {
101                         add { Events.AddHandler (MenuItemClickEvent, value); }
102                         remove { Events.RemoveHandler (MenuItemClickEvent, value); }
103                 }
104                 
105                 public event MenuEventHandler MenuItemDataBound {
106                         add { Events.AddHandler (MenuItemDataBoundEvent, value); }
107                         remove { Events.RemoveHandler (MenuItemDataBoundEvent, value); }
108                 }
109                 
110                 protected virtual void OnMenuItemClick (MenuEventArgs e)
111                 {
112                         if (Events != null) {
113                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
114                                 if (eh != null) eh (this, e);
115                         }
116                 }
117                 
118                 protected virtual void OnMenuItemDataBound (MenuEventArgs e)
119                 {
120                         if (Events != null) {
121                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemDataBoundEvent];
122                                 if (eh != null) eh (this, e);
123                         }
124                 }
125
126                 IMenuRenderer Renderer {
127                         get {
128                                 if (renderer == null)
129                                         renderer = CreateRenderer (null);
130                                 
131                                 return renderer;
132                         }
133                 }
134 #if NET_4_0
135                 bool RenderList {
136                         get {
137                                 if (renderList == null) {
138                                         switch (RenderingMode) {
139                                                 case MenuRenderingMode.List:
140                                                         renderList = true;
141                                                         break;
142
143                                                 case MenuRenderingMode.Table:
144                                                         renderList = false;
145                                                         break;
146
147                                                 default:
148                                                         if (RenderingCompatibilityLessThan40)
149                                                                 renderList = false;
150                                                         else
151                                                                 renderList = true;
152                                                         break;
153                                         }
154                                 }
155
156                                 return renderList.Value;
157                         }
158                 }
159                 
160                 [DefaultValue (true)]
161                 [Description ("Determines whether or not to render the inline style block (only used in standards compliance mode)")]
162                 public bool IncludeStyleBlock {
163                         get { return includeStyleBlock; }
164                         set { includeStyleBlock = value; }
165                 }
166
167                 [DefaultValue (MenuRenderingMode.Default)]
168                 public MenuRenderingMode RenderingMode {
169                         get { return renderingMode; }
170                         set {
171                                 if (value < MenuRenderingMode.Default || value > MenuRenderingMode.List)
172                                         throw new ArgumentOutOfRangeException ("value");
173
174                                 renderingMode = value;
175                                 renderer = CreateRenderer (renderer);
176                         }
177                 }
178 #endif
179                 [DefaultValueAttribute (null)]
180                 [PersistenceMode (PersistenceMode.InnerProperty)]
181                 [EditorAttribute ("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
182                 [MergablePropertyAttribute (false)]
183                 public MenuItemBindingCollection DataBindings {
184                         get {
185                                 if (dataBindings == null) {
186                                         dataBindings = new MenuItemBindingCollection ();
187                                         if (IsTrackingViewState)
188                                                 ((IStateManager)dataBindings).TrackViewState();
189                                 }
190                                 return dataBindings;
191                         }
192                 }
193
194                 [DefaultValue (500)]
195                 [ThemeableAttribute (false)]
196                 public int DisappearAfter {
197                         get {
198                                 object o = ViewState ["DisappearAfter"];
199                                 if (o != null) return (int)o;
200                                 return 500;
201                         }
202                         set {
203                                 ViewState["DisappearAfter"] = value;
204                         }
205                 }
206
207                 [ThemeableAttribute (true)]
208                 [DefaultValue ("")]
209                 [UrlProperty]
210                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
211                 public string DynamicBottomSeparatorImageUrl {
212                         get {
213                                 object o = ViewState ["dbsiu"];
214                                 if (o != null)
215                                         return (string)o;
216                                 return String.Empty;
217                         }
218                         set {
219                                 ViewState["dbsiu"] = value;
220                         }
221                 }
222
223                 [DefaultValueAttribute ("")]
224                 public string DynamicItemFormatString {
225                         get {
226                                 object o = ViewState ["DynamicItemFormatString"];
227                                 if (o != null) return (string)o;
228                                 return "";
229                         }
230                         set {
231                                 ViewState["DynamicItemFormatString"] = value;
232                         }
233                 }
234
235                 [DefaultValue ("")]
236                 [UrlProperty]
237                 [WebCategory ("Appearance")]
238                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
239                 public string DynamicTopSeparatorImageUrl {
240                         get {
241                                 object o = ViewState ["dtsiu"];
242                                 if (o != null) return (string)o;
243                                 return "";
244                         }
245                         set {
246                                 ViewState["dtsiu"] = value;
247                         }
248                 }
249
250                 [DefaultValue ("")]
251                 [UrlProperty]
252                 [WebCategory ("Appearance")]
253                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
254                 public string StaticBottomSeparatorImageUrl {
255                         get {
256                                 object o = ViewState ["sbsiu"];
257                                 if (o != null) return (string)o;
258                                 return "";
259                         }
260                         set {
261                                 ViewState["sbsiu"] = value;
262                         }
263                 }
264
265                 [DefaultValue ("")]
266                 [UrlProperty]
267                 [WebCategory ("Appearance")]
268                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
269                 public string StaticTopSeparatorImageUrl {
270                         get {
271                                 object o = ViewState ["stsiu"];
272                                 if (o != null) return (string)o;
273                                 return "";
274                         }
275                         set {
276                                 ViewState["stsiu"] = value;
277                         }
278                 }
279
280                 [DefaultValue (Orientation.Vertical)]
281                 public Orientation Orientation {
282                         get {
283                                 object o = ViewState ["Orientation"];
284                                 if (o != null) return (Orientation) o;
285                                 return Orientation.Vertical;
286                         }
287                         set {
288                                 ViewState["Orientation"] = value;
289                         }
290                 }
291
292                 [DefaultValue (1)]
293                 [ThemeableAttribute (true)]
294                 public int StaticDisplayLevels {
295                         get {
296                                 object o = ViewState ["StaticDisplayLevels"];
297                                 if (o != null) return (int)o;
298                                 return 1;
299                         }
300                         set {
301                                 if (value < 1) throw new ArgumentOutOfRangeException ();
302                                 ViewState["StaticDisplayLevels"] = value;
303                         }
304                 }
305
306                 [DefaultValueAttribute ("")]
307                 public string StaticItemFormatString {
308                         get {
309                                 object o = ViewState ["StaticItemFormatString"];
310                                 if (o != null) return (string)o;
311                                 return "";
312                         }
313                         set {
314                                 ViewState["StaticItemFormatString"] = value;
315                         }
316                 }
317
318                 [DefaultValue (typeof (Unit), "16px")]
319                 [ThemeableAttribute (true)]
320                 public Unit StaticSubMenuIndent {
321                         get {
322                                 object o = ViewState ["StaticSubMenuIndent"];
323                                 if (o != null)
324                                         return (Unit)o;
325                                 // LAMESPEC: on 4.0 it returns Unit.Empty and on 3.5 16px
326 #if NET_4_0
327                                 return Unit.Empty;
328 #else
329                                 return new Unit (16);
330 #endif
331                         }
332                         set {
333                                 ViewState["StaticSubMenuIndent"] = value;
334                         }
335                 }
336
337                 [ThemeableAttribute (true)]
338                 [DefaultValue (3)]
339                 public int MaximumDynamicDisplayLevels {
340                         get {
341                                 object o = ViewState ["MaximumDynamicDisplayLevels"];
342                                 if (o != null) return (int)o;
343                                 return 3;
344                         }
345                         set {
346                                 if (value < 0) throw new ArgumentOutOfRangeException ();
347                                 ViewState["MaximumDynamicDisplayLevels"] = value;
348                         }
349                 }
350
351                 [DefaultValue (0)]
352                 public int DynamicVerticalOffset {
353                         get {
354                                 object o = ViewState ["DynamicVerticalOffset"];
355                                 if (o != null) return (int)o;
356                                 return 0;
357                         }
358                         set {
359                                 ViewState["DynamicVerticalOffset"] = value;
360                         }
361                 }
362
363                 [DefaultValue (0)]
364                 public int DynamicHorizontalOffset {
365                         get {
366                                 object o = ViewState ["DynamicHorizontalOffset"];
367                                 if (o != null) return (int)o;
368                                 return 0;
369                         }
370                         set {
371                                 ViewState["DynamicHorizontalOffset"] = value;
372                         }
373                 }
374
375                 [DefaultValue (true)]
376                 public bool DynamicEnableDefaultPopOutImage {
377                         get {
378                                 object o = ViewState ["dedpoi"];
379                                 if (o != null) return (bool)o;
380                                 return true;
381                         }
382                         set {
383                                 ViewState["dedpoi"] = value;
384                         }
385                 }
386
387                 [DefaultValue (true)]
388                 public bool StaticEnableDefaultPopOutImage {
389                         get {
390                                 object o = ViewState ["sedpoi"];
391                                 if (o != null) return (bool)o;
392                                 return true;
393                         }
394                         set {
395                                 ViewState["sedpoi"] = value;
396                         }
397                 }
398
399                 [DefaultValueAttribute (null)]
400                 [PersistenceMode (PersistenceMode.InnerProperty)]
401                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
402                 [MergablePropertyAttribute (false)]
403                 public MenuItemCollection Items {
404                         get {
405                                 if (items == null) {
406                                         items = new MenuItemCollection (this);
407                                         if (IsTrackingViewState)
408                                                 ((IStateManager)items).TrackViewState();
409                                 }
410                                 return items;
411                         }
412                 }
413
414                 [DefaultValue ('/')]
415                 public char PathSeparator {
416                         get {
417                                 object o = ViewState ["PathSeparator"];
418                                 if(o != null) return (char)o;
419                                 return '/';
420                         }
421                         set {
422                                 ViewState ["PathSeparator"] = value;
423                         }
424                 }
425
426                 [DefaultValue (false)]
427                 public bool ItemWrap {
428                         get {
429                                 object o = ViewState ["ItemWrap"];
430                                 if(o != null) return (bool)o;
431                                 return false;
432                         }
433                         set {
434                                 ViewState ["ItemWrap"] = value;
435                         }
436                 }
437
438                 internal Style PopOutBoxStyle {
439                         get {
440                                 if (popOutBoxStyle == null) {
441                                         popOutBoxStyle = new Style ();
442                                         popOutBoxStyle.BackColor = Color.White;
443                                 }
444                                 return popOutBoxStyle;
445                         }
446                 }
447
448                 internal Style ControlLinkStyle {
449                         get {
450                                 if (controlLinkStyle == null) {
451                                         controlLinkStyle = new Style ();
452                                         controlLinkStyle.AlwaysRenderTextDecoration = true;
453                                 }
454                                 return controlLinkStyle;
455                         }
456                 }
457
458                 internal Style DynamicMenuItemLinkStyle {
459                         get {
460                                 if (dynamicMenuItemLinkStyle == null) {
461                                         dynamicMenuItemLinkStyle = new Style ();
462                                 }
463                                 return dynamicMenuItemLinkStyle;
464                         }
465                 }
466
467                 internal Style StaticMenuItemLinkStyle {
468                         get {
469                                 if (staticMenuItemLinkStyle == null) {
470                                         staticMenuItemLinkStyle = new Style ();
471                                 }
472                                 return staticMenuItemLinkStyle;
473                         }
474                 }
475
476                 internal Style DynamicSelectedLinkStyle {
477                         get {
478                                 if (dynamicSelectedLinkStyle == null) {
479                                         dynamicSelectedLinkStyle = new Style ();
480                                 }
481                                 return dynamicSelectedLinkStyle;
482                         }
483                 }
484
485                 internal Style StaticSelectedLinkStyle {
486                         get {
487                                 if (staticSelectedLinkStyle == null) {
488                                         staticSelectedLinkStyle = new Style ();
489                                 }
490                                 return staticSelectedLinkStyle;
491                         }
492                 }
493
494                 internal Style DynamicHoverLinkStyle {
495                         get {
496                                 if (dynamicHoverLinkStyle == null) {
497                                         dynamicHoverLinkStyle = new Style ();
498                                 }
499                                 return dynamicHoverLinkStyle;
500                         }
501                 }
502
503                 internal Style StaticHoverLinkStyle {
504                         get {
505                                 if (staticHoverLinkStyle == null) {
506                                         staticHoverLinkStyle = new Style ();
507                                 }
508                                 return staticHoverLinkStyle;
509                         }
510                 }
511
512                 internal MenuItemStyle StaticMenuItemStyleInternal {
513                         get { return staticMenuItemStyle; }
514                 }
515
516                 internal SubMenuStyle StaticMenuStyleInternal {
517                         get { return staticMenuStyle; }
518                 }
519
520                 internal MenuItemStyle DynamicMenuItemStyleInternal {
521                         get { return dynamicMenuItemStyle; }
522                 }
523
524                 internal SubMenuStyle DynamicMenuStyleInternal {
525                         get { return dynamicMenuStyle; }
526                 }
527
528                 internal MenuItemStyleCollection LevelMenuItemStylesInternal {
529                         get { return levelMenuItemStyles; }
530                 }
531
532                 internal List<Style> LevelMenuItemLinkStyles {
533                         get { return levelMenuItemLinkStyles; }
534                 }
535
536                 internal SubMenuStyleCollection LevelSubMenuStylesInternal {
537                         get { return levelSubMenuStyles; }
538                 }
539
540                 internal MenuItemStyle StaticSelectedStyleInternal {
541                         get { return staticSelectedStyle; }
542                 }
543
544                 internal MenuItemStyle DynamicSelectedStyleInternal {
545                         get { return dynamicSelectedStyle; }
546                 }
547
548                 internal MenuItemStyleCollection LevelSelectedStylesInternal {
549                         get { return levelSelectedStyles; }
550                 }
551
552                 internal List<Style> LevelSelectedLinkStyles {
553                         get { return levelSelectedLinkStyles; }
554                 }
555
556                 internal Style StaticHoverStyleInternal {
557                         get { return staticHoverStyle; }
558                 }
559
560                 internal Style DynamicHoverStyleInternal {
561                         get { return dynamicHoverStyle; }
562                 }
563                 
564                 [PersistenceMode (PersistenceMode.InnerProperty)]
565                 [NotifyParentProperty (true)]
566                 [DefaultValue (null)]
567                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
568                 public MenuItemStyle DynamicMenuItemStyle {
569                         get {
570                                 if (dynamicMenuItemStyle == null) {
571                                         dynamicMenuItemStyle = new MenuItemStyle ();
572                                         if (IsTrackingViewState)
573                                                 dynamicMenuItemStyle.TrackViewState();
574                                 }
575                                 return dynamicMenuItemStyle;
576                         }
577                 }
578                 
579                 [PersistenceMode (PersistenceMode.InnerProperty)]
580                 [NotifyParentProperty (true)]
581                 [DefaultValue (null)]
582                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
583                 public MenuItemStyle DynamicSelectedStyle {
584                         get {
585                                 if (dynamicSelectedStyle == null) {
586                                         dynamicSelectedStyle = new MenuItemStyle ();
587                                         if (IsTrackingViewState)
588                                                 dynamicSelectedStyle.TrackViewState();
589                                 }
590                                 return dynamicSelectedStyle;
591                         }
592                 }
593                 
594                 [PersistenceMode (PersistenceMode.InnerProperty)]
595                 [NotifyParentProperty (true)]
596                 [DefaultValue (null)]
597                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
598                 public SubMenuStyle DynamicMenuStyle {
599                         get {
600                                 if (dynamicMenuStyle == null) {
601                                         dynamicMenuStyle = new SubMenuStyle ();
602                                         if (IsTrackingViewState)
603                                                 dynamicMenuStyle.TrackViewState();
604                                 }
605                                 return dynamicMenuStyle;
606                         }
607                 }
608                 
609                 [PersistenceMode (PersistenceMode.InnerProperty)]
610                 [NotifyParentProperty (true)]
611                 [DefaultValue (null)]
612                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
613                 public MenuItemStyle StaticMenuItemStyle {
614                         get {
615                                 if (staticMenuItemStyle == null) {
616                                         staticMenuItemStyle = new MenuItemStyle ();
617                                         if (IsTrackingViewState)
618                                                 staticMenuItemStyle.TrackViewState();
619                                 }
620                                 return staticMenuItemStyle;
621                         }
622                 }
623                 
624                 [PersistenceMode (PersistenceMode.InnerProperty)]
625                 [NotifyParentProperty (true)]
626                 [DefaultValue (null)]
627                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
628                 public MenuItemStyle StaticSelectedStyle {
629                         get {
630                                 if (staticSelectedStyle == null) {
631                                         staticSelectedStyle = new MenuItemStyle ();
632                                         if (IsTrackingViewState)
633                                                 staticSelectedStyle.TrackViewState();
634                                 }
635                                 return staticSelectedStyle;
636                         }
637                 }
638                 
639                 [PersistenceMode (PersistenceMode.InnerProperty)]
640                 [NotifyParentProperty (true)]
641                 [DefaultValue (null)]
642                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
643                 public SubMenuStyle StaticMenuStyle {
644                         get {
645                                 if (staticMenuStyle == null) {
646                                         staticMenuStyle = new SubMenuStyle ();
647                                         if (IsTrackingViewState)
648                                                 staticMenuStyle.TrackViewState();
649                                 }
650                                 return staticMenuStyle;
651                         }
652                 }
653
654                 [DefaultValue (null)]
655                 [PersistenceMode (PersistenceMode.InnerProperty)]
656                 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
657                 public MenuItemStyleCollection LevelMenuItemStyles {
658                         get {
659                                 if (levelMenuItemStyles == null) {
660                                         levelMenuItemStyles = new MenuItemStyleCollection ();
661                                         if (IsTrackingViewState)
662                                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
663                                 }
664                                 return levelMenuItemStyles;
665                         }
666                 }
667
668                 [DefaultValue (null)]
669                 [PersistenceMode (PersistenceMode.InnerProperty)]
670                 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
671                 public MenuItemStyleCollection LevelSelectedStyles {
672                         get {
673                                 if (levelSelectedStyles == null) {
674                                         levelSelectedStyles = new MenuItemStyleCollection ();
675                                         if (IsTrackingViewState)
676                                                 ((IStateManager)levelSelectedStyles).TrackViewState();
677                                 }
678                                 return levelSelectedStyles;
679                         }
680                 }
681
682                 [DefaultValue (null)]
683                 [PersistenceMode (PersistenceMode.InnerProperty)]
684                 [Editor ("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
685                 public SubMenuStyleCollection LevelSubMenuStyles {
686                         get {
687                                 if (levelSubMenuStyles == null) {
688                                         levelSubMenuStyles = new SubMenuStyleCollection ();
689                                         if (IsTrackingViewState)
690                                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
691                                 }
692                                 return levelSubMenuStyles;
693                         }
694                 }
695
696                 [PersistenceMode (PersistenceMode.InnerProperty)]
697                 [NotifyParentProperty (true)]
698                 [DefaultValue (null)]
699                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
700                 public Style DynamicHoverStyle {
701                         get {
702                                 if (dynamicHoverStyle == null) {
703                                         dynamicHoverStyle = new Style ();
704                                         if (IsTrackingViewState)
705                                                 dynamicHoverStyle.TrackViewState();
706                                 }
707                                 return dynamicHoverStyle;
708                         }
709                 }
710                 
711                 [PersistenceMode (PersistenceMode.InnerProperty)]
712                 [NotifyParentProperty (true)]
713                 [DefaultValue (null)]
714                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
715                 public Style StaticHoverStyle {
716                         get {
717                                 if (staticHoverStyle == null) {
718                                         staticHoverStyle = new Style ();
719                                         if (IsTrackingViewState)
720                                                 staticHoverStyle.TrackViewState();
721                                 }
722                                 return staticHoverStyle;
723                         }
724                 }
725                 
726                 [DefaultValue ("")]
727                 [UrlProperty]
728                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
729                 public string ScrollDownImageUrl {
730                         get {
731                                 object o = ViewState ["sdiu"];
732                                 if (o != null) return (string)o;
733                                 return "";
734                         }
735                         set {
736                                 ViewState["sdiu"] = value;
737                         }
738                 }
739
740                 [DefaultValue ("")]
741                 [UrlProperty]
742                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
743                 public string ScrollUpImageUrl {
744                         get {
745                                 object o = ViewState ["suiu"];
746                                 if (o != null) return (string)o;
747                                 return "";
748                         }
749                         set {
750                                 ViewState["suiu"] = value;
751                         }
752                 }
753
754                 [Localizable (true)]
755                 public string ScrollDownText {
756                         get {
757                                 object o = ViewState ["ScrollDownText"];
758                                 if (o != null) return (string) o;
759                                 return Locale.GetText ("Scroll down");
760                         }
761                         set {
762                                 ViewState["ScrollDownText"] = value;
763                         }
764                 }
765
766                 [Localizable (true)]
767                 public string ScrollUpText {
768                         get {
769                                 object o = ViewState ["ScrollUpText"];
770                                 if (o != null) return (string) o;
771                                 return Locale.GetText ("Scroll up");
772                         }
773                         set {
774                                 ViewState["ScrollUpText"] = value;
775                         }
776                 }
777
778                 public string DynamicPopOutImageTextFormatString 
779                 {
780                         get
781                         {
782                                 object o = ViewState ["dpoitf"];
783                                 if (o != null) return (string) o;
784                                 return Locale.GetText ("Expand {0}");
785                         }
786                         set
787                         {
788                                 ViewState ["dpoitf"] = value;
789                         }
790                 }
791                 
792
793                 [DefaultValue ("")]
794                 [UrlProperty]
795                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
796                 public string DynamicPopOutImageUrl {
797                         get {
798                                 object o = ViewState ["dpoiu"];
799                                 if (o != null) return (string)o;
800                                 return "";
801                         }
802                         set {
803                                 ViewState["dpoiu"] = value;
804                         }
805                 }
806
807                 public string StaticPopOutImageTextFormatString
808                 {
809                         get
810                         {
811                                 object o = ViewState ["spoitf"];
812                                 if (o != null) return (string) o;
813                                 return Locale.GetText ("Expand {0}");
814                         }
815                         set
816                         {
817                                 ViewState ["spoitf"] = value;
818                         }
819                 }
820
821
822                 [DefaultValue ("")]
823                 [UrlProperty]
824                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
825                 public string StaticPopOutImageUrl {
826                         get {
827                                 object o = ViewState ["spoiu"];
828                                 if (o != null) return (string)o;
829                                 return "";
830                         }
831                         set {
832                                 ViewState["spoiu"] = value;
833                         }
834                 }
835
836                 [DefaultValue ("")]
837                 public string Target {
838                         get {
839                                 object o = ViewState ["Target"];
840                                 if (o != null) return (string) o;
841                                 return "";
842                         }
843                         set {
844                                 ViewState["Target"] = value;
845                         }
846                 }
847
848                 [DefaultValue (null)]
849                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
850                 [PersistenceMode (PersistenceMode.InnerProperty)]
851                 [Browsable (false)]
852                 public ITemplate StaticItemTemplate {
853                         get { return staticItemTemplate; }
854                         set { staticItemTemplate = value; }
855                 }
856                 
857                 [DefaultValue (null)]
858                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
859                 [PersistenceMode (PersistenceMode.InnerProperty)]
860                 [Browsable (false)]
861                 public ITemplate DynamicItemTemplate {
862                         get { return dynamicItemTemplate; }
863                         set { dynamicItemTemplate = value; }
864                 }
865                 
866                 [Browsable (false)]
867                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
868                 public MenuItem SelectedItem {
869                         get {
870                                 if (selectedItem == null && selectedItemPath != null) {
871                                         selectedItem = FindItemByPos (selectedItemPath);
872                                 }
873                                 
874                                 return selectedItem;
875                         }
876                 }
877
878                 [Browsable (false)]
879                 [DefaultValue ("")]
880                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
881                 public string SelectedValue {
882                         get { return selectedItem != null ? selectedItem.Value : ""; }
883                 }
884
885                 [Localizable (true)]
886                 public string SkipLinkText 
887                 {
888                         get {
889                                 object o = ViewState ["SkipLinkText"];
890                                 if (o != null)
891                                         return (string) o;
892                                 return "Skip Navigation Links";
893                         }
894                         set {
895                                 ViewState ["SkipLinkText"] = value;
896                         }
897                 }
898                 
899                 IMenuRenderer CreateRenderer (IMenuRenderer current)
900                 {
901 #if NET_4_0
902                         Type newType = null;
903                         
904                         switch (RenderingMode) {
905                                 case MenuRenderingMode.Default:
906                                         if (RenderingCompatibilityLessThan40)
907                                                 newType = typeof (MenuTableRenderer);
908                                         else
909                                                 newType = typeof (MenuListRenderer);
910                                         break;
911                                         
912                                 case MenuRenderingMode.Table:
913                                         newType = typeof (MenuTableRenderer);
914                                         break;
915
916                                 case MenuRenderingMode.List:
917                                         newType = typeof (MenuListRenderer);
918                                         break;
919                         }
920
921                         if (newType == null)
922                                 return null;
923
924                         if (current == null || current.GetType () != newType)
925                                 return Activator.CreateInstance (newType, this) as IMenuRenderer;
926 #else
927                         if (current == null)
928                                 return new MenuTableRenderer (this);
929 #endif
930                         return current;
931                 }
932                 
933                 internal void SetSelectedItem (MenuItem item)
934                 {
935                         if (selectedItem == item) return;
936                         selectedItem = item;
937                         selectedItemPath = item.Path;
938                 }
939                 
940                 public MenuItem FindItem (string valuePath)
941                 {
942                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
943                         string[] path = valuePath.Split (PathSeparator);
944                         int n = 0;
945                         MenuItemCollection col = Items;
946                         bool foundBranch = true;
947                         while (col.Count > 0 && foundBranch) {
948                                 foundBranch = false;
949                                 foreach (MenuItem item in col) {
950                                         if (item.Value == path [n]) {
951                                                 if (++n == path.Length) return item;
952                                                 col = item.ChildItems;
953                                                 foundBranch = true;
954                                                 break;
955                                         }
956                                 }
957                         }
958                         return null;
959                 }
960                 
961                 string GetBindingKey (string dataMember, int depth)
962                 {
963                         return dataMember + " " + depth;
964                 }
965                 
966                 internal MenuItemBinding FindBindingForItem (string type, int depth)
967                 {
968                         if (bindings == null) return null;
969
970                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
971                         if (bin != null) return bin;
972                         
973                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
974                         if (bin != null) return bin;
975                         
976                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
977                         if (bin != null) return bin;
978                         
979                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
980                         return bin;
981                 }
982                 
983                 protected internal override void PerformDataBinding ()
984                 {
985                         base.PerformDataBinding ();
986
987                         // Do not attempt to bind data if there is no
988                         // data source set.
989                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
990                                 EnsureChildControlsDataBound ();
991                                 return;
992                         }
993
994                         InitializeDataBindings ();
995
996                         HierarchicalDataSourceView data = GetData ("");
997
998                         if (data == null) {
999                                 throw new InvalidOperationException ("No view returned by data source control.");
1000                         }
1001                         Items.Clear ();
1002                         IHierarchicalEnumerable e = data.Select ();
1003                         FillBoundChildrenRecursive (e, Items);
1004
1005                         CreateChildControlsForItems ();
1006                         ChildControlsCreated = true;
1007
1008                         EnsureChildControlsDataBound ();
1009                 }
1010
1011                 void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, MenuItemCollection itemCollection)
1012                 {
1013                         if (hEnumerable == null)
1014                                 return;
1015                         foreach (object obj in hEnumerable) {
1016                                 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
1017                                 MenuItem item = new MenuItem ();
1018                                 itemCollection.Add (item);
1019                                 item.Bind (hdata);
1020
1021                                 SiteMapNode siteMapNode = hdata as SiteMapNode;
1022                                 if (siteMapNode != null) {
1023                                         if (_currSiteMapNode == null)
1024                                                 _currSiteMapNode = siteMapNode.Provider.CurrentNode;
1025                                         if (siteMapNode == _currSiteMapNode)
1026                                                 item.Selected = true;
1027                                 }
1028                                 
1029                                 OnMenuItemDataBound (new MenuEventArgs (item));
1030
1031                                 if (hdata == null || !hdata.HasChildren)
1032                                         continue;
1033
1034                                 IHierarchicalEnumerable e = hdata.GetChildren ();
1035                                 FillBoundChildrenRecursive (e, item.ChildItems);
1036                         }
1037                 }
1038                 
1039                 protected void SetItemDataBound (MenuItem node, bool dataBound)
1040                 {
1041                         node.SetDataBound (dataBound);
1042                 }
1043                 
1044                 protected void SetItemDataPath (MenuItem node, string dataPath)
1045                 {
1046                         node.SetDataPath (dataPath);
1047                 }
1048                 
1049                 protected void SetItemDataItem (MenuItem node, object dataItem)
1050                 {
1051                         node.SetDataItem (dataItem);
1052                 }
1053                 
1054                 protected internal virtual void RaisePostBackEvent (string eventArgument)
1055                 {
1056                         ValidateEvent (UniqueID, eventArgument);
1057                         if (!IsEnabled)
1058                                 return;
1059
1060                         EnsureChildControls();
1061                         MenuItem item = FindItemByPos (eventArgument);
1062                         if (item == null) return;
1063                         item.Selected = true;
1064                         OnMenuItemClick (new MenuEventArgs (item));
1065                 }
1066
1067                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
1068                 {
1069                         RaisePostBackEvent (eventArgument);
1070                 }
1071                 
1072                 MenuItem FindItemByPos (string path)
1073                 {
1074                         string[] indexes = path.Split ('_');
1075                         MenuItem item = null;
1076                         
1077                         foreach (string index in indexes) {
1078                                 int i = int.Parse (index);
1079                                 if (item == null) {
1080                                         if (i >= Items.Count) return null;
1081                                         item = Items [i];
1082                                 } else {
1083                                         if (i >= item.ChildItems.Count) return null;
1084                                         item = item.ChildItems [i];
1085                                 }
1086                         }
1087                         return item;
1088                 }
1089                 
1090                 protected override HtmlTextWriterTag TagKey {
1091                         get { return Renderer.Tag; }
1092                 }
1093                 
1094                 protected override void TrackViewState()
1095                 {
1096                         EnsureDataBound ();
1097                         
1098                         base.TrackViewState();
1099                         if (dataBindings != null) {
1100                                 ((IStateManager)dataBindings).TrackViewState ();
1101                         }
1102                         if (items != null) {
1103                                 ((IStateManager)items).TrackViewState();
1104                         }
1105                         if (dynamicMenuItemStyle != null)
1106                                 dynamicMenuItemStyle.TrackViewState ();
1107                         if (dynamicMenuStyle != null)
1108                                 dynamicMenuStyle.TrackViewState ();
1109                         if (levelMenuItemStyles != null && levelMenuItemStyles.Count > 0)
1110                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
1111                         if (levelSelectedStyles != null && levelMenuItemStyles.Count > 0)
1112                                 ((IStateManager)levelSelectedStyles).TrackViewState();
1113                         if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0)
1114                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
1115                         if (dynamicSelectedStyle != null)
1116                                 dynamicSelectedStyle.TrackViewState();
1117                         if (staticMenuItemStyle != null)
1118                                 staticMenuItemStyle.TrackViewState ();
1119                         if (staticMenuStyle != null)
1120                                 staticMenuStyle.TrackViewState ();
1121                         if (staticSelectedStyle != null)
1122                                 staticSelectedStyle.TrackViewState();
1123                         if (staticHoverStyle != null)
1124                                 staticHoverStyle.TrackViewState();
1125                         if (dynamicHoverStyle != null)
1126                                 dynamicHoverStyle.TrackViewState();
1127                 }
1128
1129                 protected override object SaveViewState()
1130                 {
1131                         object[] states = new object [14];
1132                         states[0] = base.SaveViewState ();
1133                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
1134                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
1135                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
1136                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
1137                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
1138                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
1139                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
1140                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
1141                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
1142                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
1143                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
1144                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
1145                         states[13] = levelSubMenuStyles == null ? null : ((IStateManager)levelSubMenuStyles).SaveViewState();
1146
1147                         for (int i = states.Length - 1; i >= 0; i--) {
1148                                 if (states [i] != null)
1149                                         return states;
1150                         }
1151
1152                         return null;
1153                 }
1154
1155                 protected override void LoadViewState (object savedState)
1156                 {
1157                         if (savedState == null)
1158                                 return;
1159
1160                         object [] states = (object []) savedState;
1161                         base.LoadViewState (states[0]);
1162                         
1163                         if (states[1] != null)
1164                                 ((IStateManager)DataBindings).LoadViewState(states[1]);
1165                         if (states[2] != null)
1166                                 ((IStateManager)Items).LoadViewState(states[2]);
1167                         if (states[3] != null)
1168                                 DynamicMenuItemStyle.LoadViewState (states[3]);
1169                         if (states[4] != null)
1170                                 DynamicMenuStyle.LoadViewState (states[4]);
1171                         if (states[5] != null)
1172                                 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
1173                         if (states[6] != null)
1174                                 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
1175                         if (states[7] != null)
1176                                 DynamicSelectedStyle.LoadViewState (states[7]);
1177                         if (states[8] != null)
1178                                 StaticMenuItemStyle.LoadViewState (states[8]);
1179                         if (states[9] != null)
1180                                 StaticMenuStyle.LoadViewState (states[9]);
1181                         if (states[10] != null)
1182                                 StaticSelectedStyle.LoadViewState (states[10]);
1183                         if (states[11] != null)
1184                                 StaticHoverStyle.LoadViewState (states[11]);
1185                         if (states[12] != null)
1186                                 DynamicHoverStyle.LoadViewState (states[12]);
1187                         if (states[13] != null)
1188                                 ((IStateManager)LevelSubMenuStyles).LoadViewState(states[13]);
1189                 }
1190                 
1191                 protected internal override void OnInit (EventArgs e)
1192                 {
1193                         Page.RegisterRequiresControlState (this);
1194                         base.OnInit (e);
1195                 }
1196                 
1197                 protected internal override void LoadControlState (object ob)
1198                 {
1199                         if (ob == null) return;
1200                         object[] state = (object[]) ob;
1201                         base.LoadControlState (state[0]);
1202                         selectedItemPath = state[1] as string;
1203                 }
1204                 
1205                 protected internal override object SaveControlState ()
1206                 {
1207                         object bstate = base.SaveControlState ();
1208                         object mstate = selectedItemPath;
1209                         
1210                         if (bstate != null || mstate != null)
1211                                 return new object[] { bstate, mstate };
1212                         else
1213                                 return null;
1214                 }
1215                 
1216                 protected internal override void CreateChildControls ()
1217                 {
1218                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
1219                                 CreateChildControlsForItems ();
1220                         }
1221                         else {
1222                                 EnsureDataBound ();
1223                         }
1224                 }
1225
1226                 void CreateChildControlsForItems () {
1227                         Controls.Clear ();
1228                         // Check for HasChildViewState to avoid unnecessary calls to ClearChildViewState.
1229                         if (HasChildViewState)
1230                                 ClearChildViewState ();
1231                         _menuItemControls = new Hashtable ();
1232                         CreateChildControlsForItems (Items);
1233                         _requiresChildControlsDataBinding = true;
1234                 }
1235
1236                 void CreateChildControlsForItems (MenuItemCollection items )
1237                 {
1238                         IMenuRenderer renderer = Renderer;
1239                         foreach (MenuItem item in items) {
1240                                 bool isDynamicItem = renderer.IsDynamicItem (this, item);
1241                                 if (isDynamicItem && dynamicItemTemplate != null) {
1242                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1243                                         dynamicItemTemplate.InstantiateIn (cter);
1244                                         _menuItemControls [item] = cter;
1245                                         Controls.Add (cter);
1246                                 }
1247                                 else if (!isDynamicItem && staticItemTemplate != null) {
1248                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1249                                         staticItemTemplate.InstantiateIn (cter);
1250                                         _menuItemControls [item] = cter;
1251                                         Controls.Add (cter);
1252                                 }
1253                                 if (item.HasChildData)
1254                                         CreateChildControlsForItems (item.ChildItems);
1255                         }
1256                 }
1257
1258                 protected override void EnsureDataBound ()
1259                 {
1260                         base.EnsureDataBound ();
1261                         
1262                         EnsureChildControlsDataBound ();
1263                 }
1264
1265                 void EnsureChildControlsDataBound () {
1266                         if (!_requiresChildControlsDataBinding)
1267                                 return;
1268                         DataBindChildren ();
1269                         _requiresChildControlsDataBinding = false;
1270                 }
1271
1272                 [MonoTODO ("Not implemented")]
1273                 protected override IDictionary GetDesignModeState ()
1274                 {
1275                         throw new NotImplementedException ();
1276                 }
1277
1278                 [MonoTODO ("Not implemented")]
1279                 protected override void SetDesignModeState (IDictionary data)
1280                 {
1281                         throw new NotImplementedException ();
1282                 }
1283                                 
1284                 public override ControlCollection Controls {
1285                         get { return base.Controls; }
1286                 }
1287                 
1288                 public sealed override void DataBind ()
1289                 {
1290                         base.DataBind ();
1291                 }
1292                 
1293                 protected override bool OnBubbleEvent (object source, EventArgs args)
1294                 {
1295                         if (!(args is CommandEventArgs))
1296                                 return false;
1297
1298                         MenuEventArgs menuArgs = args as MenuEventArgs;
1299                         if (menuArgs != null && string.Equals (menuArgs.CommandName, MenuItemClickCommandName))
1300                                 OnMenuItemClick (menuArgs);
1301                         return true;
1302                 }
1303
1304                 protected override void OnDataBinding (EventArgs e)
1305                 {
1306                         EnsureChildControls ();
1307                         base.OnDataBinding (e);
1308                 }
1309                 
1310                 protected internal override void OnPreRender (EventArgs e)
1311                 {
1312                         base.OnPreRender (e);
1313
1314                         string cmenu = ClientID + "_data";
1315                         StringBuilder script = new StringBuilder ();
1316                         Page page = Page;
1317                         HtmlHead header;
1318                         ClientScriptManager csm;
1319
1320                         if (page != null) {
1321                                 header = page.Header;
1322                                 csm = page.ClientScript;
1323                         } else {
1324                                 header = null;
1325                                 csm = null;
1326                         }
1327                         
1328                         Renderer.PreRender (page, header, csm, cmenu, script);
1329
1330                         if (csm != null) {
1331                                 csm.RegisterWebFormClientScript ();
1332                                 csm.RegisterStartupScript (typeof(Menu), ClientID, script.ToString (), true);
1333                         }
1334                 }
1335
1336                 void InitializeDataBindings () {
1337                         if (dataBindings != null && dataBindings.Count > 0) {
1338                                 bindings = new Hashtable ();
1339                                 foreach (MenuItemBinding bin in dataBindings) {
1340                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
1341                                         bindings [key] = bin;
1342                                 }
1343                         }
1344                         else
1345                                 bindings = null;
1346                 }
1347                 
1348                 protected internal override void Render (HtmlTextWriter writer)
1349                 {
1350                         if (Items.Count > 0)
1351                                 base.Render (writer);
1352                 }
1353                 
1354                 protected override void AddAttributesToRender (HtmlTextWriter writer)
1355                 {
1356                         Renderer.AddAttributesToRender (writer);
1357                         base.AddAttributesToRender (writer);
1358                 }
1359                 
1360                 public override void RenderBeginTag (HtmlTextWriter writer)
1361                 {
1362                         string skipLinkText = SkipLinkText;
1363                         if (!String.IsNullOrEmpty (skipLinkText))
1364                                 Renderer.RenderBeginTag (writer, skipLinkText);
1365                         base.RenderBeginTag (writer);
1366                 }
1367                 
1368                 public override void RenderEndTag (HtmlTextWriter writer)
1369                 {
1370                         base.RenderEndTag (writer);
1371
1372                         Renderer.RenderEndTag (writer);
1373                         
1374                         string skipLinkText = SkipLinkText;
1375                         if (!String.IsNullOrEmpty (skipLinkText)) {
1376                                 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_SkipLink");
1377                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1378                                 writer.RenderEndTag ();
1379                         }
1380                 }
1381                 
1382                 protected internal override void RenderContents (HtmlTextWriter writer)
1383                 {
1384                         Renderer.RenderContents (writer);
1385                 }
1386
1387                 internal void RenderDynamicMenu (HtmlTextWriter writer, MenuItemCollection items)
1388                 {
1389                         for (int n = 0; n < items.Count; n++) {
1390                                 if (DisplayChildren (items [n])) {
1391                                         RenderDynamicMenu (writer, items [n]);
1392                                         RenderDynamicMenu (writer, items [n].ChildItems);
1393                                 }
1394                         }
1395                 }
1396                 
1397                 MenuRenderHtmlTemplate _dynamicTemplate;
1398                 MenuRenderHtmlTemplate GetDynamicMenuTemplate (MenuItem item)
1399                 {
1400                         if (_dynamicTemplate != null) 
1401                                 return _dynamicTemplate;
1402
1403                         _dynamicTemplate = new MenuRenderHtmlTemplate ();
1404                         HtmlTextWriter writer = _dynamicTemplate.GetMenuTemplateWriter ();
1405
1406                         if (Page.Header != null) {
1407                                 writer.AddAttribute (HtmlTextWriterAttribute.Class, MenuRenderHtmlTemplate.GetMarker (0));
1408                         }
1409                         else {
1410                                 writer.AddAttribute (HtmlTextWriterAttribute.Style, MenuRenderHtmlTemplate.GetMarker (0));
1411                         }
1412
1413                         writer.AddStyleAttribute ("visibility", "hidden");
1414                         writer.AddStyleAttribute ("position", "absolute");
1415                         writer.AddStyleAttribute ("z-index", "1");
1416                         writer.AddStyleAttribute ("left", "0px");
1417                         writer.AddStyleAttribute ("top", "0px");
1418                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (1));
1419                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1420
1421                         // Up button
1422                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (2));
1423                         writer.AddStyleAttribute ("display", "block");
1424                         writer.AddStyleAttribute ("text-align", "center");
1425                         writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (3), "','u')"));
1426                         writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (4), "','u')")); 
1427                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1428                         
1429                         writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (5)); //src
1430                         writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (6)); //ScrollUpText
1431                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1432                         writer.RenderEndTag (); // IMG
1433                         
1434                         writer.RenderEndTag (); // DIV scroll button
1435                 
1436                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (7));
1437                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1438                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (8));
1439                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1440                         
1441                         // call of RenderMenu
1442                         writer.Write (MenuRenderHtmlTemplate.GetMarker (9));
1443                         
1444                         writer.RenderEndTag (); // DIV Content
1445                         writer.RenderEndTag (); // DIV Scroll container
1446
1447                         // Down button
1448                         writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (0));
1449                         writer.AddStyleAttribute ("display", "block");
1450                         writer.AddStyleAttribute ("text-align", "center");
1451                         writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (1), "','d')"));
1452                         writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (2), "','d')")); 
1453                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1454                         
1455                         writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (3)); //src
1456                         writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (4)); //ScrollDownText
1457                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1458                         writer.RenderEndTag (); // IMG
1459                         
1460                         writer.RenderEndTag (); // DIV scroll button
1461                         
1462                         writer.RenderEndTag (); // DIV menu
1463
1464                         _dynamicTemplate.Parse ();
1465                         return _dynamicTemplate;
1466                 }
1467
1468                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
1469                 {
1470                         _dynamicTemplate = GetDynamicMenuTemplate (item);
1471
1472                         string idPrefix = ClientID + "_" + item.Path;
1473                         string [] param = new string [9];
1474                         param [0] = GetCssMenuStyle (true, item.Depth + 1);
1475                         param [1] = idPrefix + "s";
1476                         param [2] = idPrefix + "cu";
1477                         param [3] = item.Path;
1478                         param [4] = item.Path;
1479                         param [5] = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_up.gif");
1480                         param [6] = ScrollUpText;
1481                         param [7] = idPrefix + "cb";
1482                         param [8] = idPrefix + "cc";
1483
1484                         _dynamicTemplate.RenderTemplate (writer, param, 0, param.Length);
1485
1486                         RenderMenu (writer, item.ChildItems, true, true, item.Depth + 1, false);
1487
1488                         string [] param2 = new string [5];
1489                         param2 [0] = idPrefix + "cd";
1490                         param2 [1] = item.Path;
1491                         param2 [2] = item.Path;
1492                         param2 [3] = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_down.gif");
1493                         param2 [4] = ScrollDownText;
1494
1495                         _dynamicTemplate.RenderTemplate (writer, param2, param.Length + 1, param2.Length);
1496
1497                 }
1498
1499                 string GetCssMenuStyle (bool dynamic, int menuLevel)
1500                 {
1501                         if (Page.Header != null) {
1502                                 // styles are registered
1503                                 StringBuilder sb = new StringBuilder ();
1504
1505                                 if (!dynamic && staticMenuStyle != null) {
1506                                         sb.Append (staticMenuStyle.CssClass);
1507                                         sb.Append (' ');
1508                                         sb.Append (staticMenuStyle.RegisteredCssClass);
1509                                 }
1510                                 if (dynamic && dynamicMenuStyle != null) {
1511                                         sb.Append (PopOutBoxStyle.RegisteredCssClass);
1512                                         sb.Append (' ');
1513                                         sb.Append (dynamicMenuStyle.CssClass);
1514                                         sb.Append (' ');
1515                                         sb.Append (dynamicMenuStyle.RegisteredCssClass);
1516                                 }
1517                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1518                                         sb.Append (levelSubMenuStyles [menuLevel].CssClass);
1519                                         sb.Append (' ');
1520                                         sb.Append (levelSubMenuStyles [menuLevel].RegisteredCssClass); 
1521                                 }
1522                                 return sb.ToString ();
1523                         }
1524                         else {
1525                                 // styles are not registered
1526                                 SubMenuStyle style = new SubMenuStyle ();
1527
1528                                 if (!dynamic && staticMenuStyle != null) {
1529                                         style.CopyFrom (staticMenuStyle);
1530                                 }
1531                                 if (dynamic && dynamicMenuStyle != null) {
1532                                         style.CopyFrom (PopOutBoxStyle);
1533                                         style.CopyFrom (dynamicMenuStyle);
1534                                 }
1535                                 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1536                                         style.CopyFrom (levelSubMenuStyles [menuLevel]);
1537                                 }
1538                                 return style.GetStyleAttributes (null).Value;
1539                         }
1540                 }
1541
1542                 internal void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, int menuLevel, bool notLast)
1543                 {
1544                         IMenuRenderer renderer = Renderer;
1545                         
1546                         renderer.RenderMenuBeginTag (writer, dynamic, menuLevel);
1547                         renderer.RenderMenuBody (writer, items, vertical, dynamic, notLast);
1548                         renderer.RenderMenuEndTag (writer, dynamic, menuLevel);
1549                 }
1550
1551                 internal bool DisplayChildren (MenuItem item)
1552                 {
1553                         return (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels) && item.ChildItems.Count > 0;
1554                 }
1555                 
1556                 internal void RenderItem (HtmlTextWriter writer, MenuItem item, int position)
1557                 {
1558                         // notLast should be true if item or any of its ancestors is not a
1559                         // last child.
1560                         bool notLast = false;
1561                         MenuItem parent;
1562                         MenuItem child = item;                  
1563                         while (null != (parent = child.Parent)) {
1564                                 if (child.Index != parent.ChildItems.Count - 1) {
1565                                         notLast = true;
1566                                         break;
1567                                 }
1568                                 child = parent;
1569                         }
1570                         Renderer.RenderMenuItem (writer, item, notLast, position == 0);
1571                 }
1572
1573                 internal void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem)
1574                 {
1575                         if (_menuItemControls!=null && _menuItemControls [item] != null)
1576                                 ((Control) _menuItemControls [item]).Render (writer);
1577
1578                         Renderer.RenderItemContent (writer, item, isDynamicItem);
1579                 }
1580                         
1581                 internal Unit GetItemSpacing (MenuItem item, bool dynamic)
1582                 {
1583                         Unit itemSpacing = Unit.Empty;
1584                         
1585                         if (item.Selected) {
1586                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1587                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1588                                         if (itemSpacing != Unit.Empty) return itemSpacing;
1589                                 }
1590
1591                                 if (dynamic && dynamicSelectedStyle != null)
1592                                         itemSpacing = dynamicSelectedStyle.ItemSpacing;
1593                                 else if (!dynamic && staticSelectedStyle != null)
1594                                         itemSpacing = staticSelectedStyle.ItemSpacing;
1595                                 if (itemSpacing != Unit.Empty)
1596                                         return itemSpacing;
1597                         }
1598                         
1599                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1600                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1601                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1602                         }
1603
1604                         if (dynamic && dynamicMenuItemStyle != null)
1605                                 return dynamicMenuItemStyle.ItemSpacing;
1606                         else if (!dynamic && staticMenuItemStyle != null)
1607                                 return staticMenuItemStyle.ItemSpacing;
1608                         else
1609                                 return Unit.Empty;
1610                 }
1611
1612                 class MenuTemplateWriter : TextWriter
1613                 {
1614                         char [] _buffer;
1615                         int _ptr = 0;
1616                         
1617                         public MenuTemplateWriter (char [] buffer)
1618                         {
1619                                 _buffer = buffer;
1620                         }
1621
1622                         public override Encoding Encoding
1623                         {
1624                                 get { return Encoding.Unicode; }
1625                         }
1626
1627                         public override void Write (char value)
1628                         {
1629                                 if (_ptr == _buffer.Length)
1630                                         EnsureCapacity ();
1631                                 
1632                                 _buffer [_ptr++] = value;
1633                         }
1634
1635                         public override void Write (string value)
1636                         {
1637                                 if (value == null)
1638                                         return;
1639
1640                                 if (_ptr + value.Length >= _buffer.Length)
1641                                         EnsureCapacity ();
1642
1643                                 for (int i = 0; i < value.Length; i++)
1644                                         _buffer [_ptr++] = value [i];
1645                         }
1646
1647                         void EnsureCapacity ()
1648                         {
1649                                 char [] tmpBuffer = new char [_buffer.Length * 2];
1650                                 Array.Copy (_buffer, tmpBuffer, _buffer.Length);
1651
1652                                 _buffer = tmpBuffer;
1653                         }
1654                 }
1655
1656                 class MenuRenderHtmlTemplate
1657                 {
1658                         public const string Marker = "\u093a\u093b\u0971";
1659                         char [] _templateHtml;
1660
1661                         MenuTemplateWriter _templateWriter;
1662                         ArrayList idxs = new ArrayList (32);
1663
1664                         public MenuRenderHtmlTemplate ()
1665                         {
1666                                 _templateHtml = new char [1024];
1667                                 _templateWriter = new MenuTemplateWriter (_templateHtml);
1668                         }
1669
1670                         public static string GetMarker (int num)
1671                         {
1672                                 char charNum = (char) ((int) '\u0971' + num);
1673                                 return string.Concat (Marker, charNum);
1674                         }
1675
1676                         public HtmlTextWriter GetMenuTemplateWriter()
1677                         {
1678                                 return new HtmlTextWriter (_templateWriter);
1679                         }
1680
1681                         public void Parse ()
1682                         {
1683                                 int mpos = 0;
1684                                 for (int i = 0; i < _templateHtml.Length; i++) {
1685                                         if (_templateHtml [i] == '\0') {
1686                                                 idxs.Add (i);
1687                                                 break;
1688                                         }
1689
1690                                         if (_templateHtml [i] != Marker [mpos]) {
1691                                                 mpos = 0;
1692                                                 continue;
1693                                         }
1694
1695                                         mpos++;
1696                                         if (mpos == Marker.Length) {
1697                                                 mpos = 0;
1698                                                 idxs.Add (i - Marker.Length + 1);
1699                                         }
1700                                 }
1701                         }
1702
1703                         public void RenderTemplate (HtmlTextWriter writer, string [] dynamicParts, int start, int count)
1704                         {
1705                                 if (idxs.Count == 0)
1706                                         return;
1707
1708                                 int partStart = 0;
1709                                 int partEnd = (start == 0) ? -Marker.Length - 1 : (int) idxs [start - 1];
1710                                 int di = 0;
1711
1712                                 int i = start;
1713                                 int total = start + count;
1714                                 for (; i < total; i++) {
1715
1716                                         partStart = partEnd + Marker.Length + 1;
1717                                         partEnd = (int) idxs [i];
1718                                         
1719                                         // write static part
1720                                         writer.Write (_templateHtml, partStart, partEnd - partStart);
1721
1722                                         // write synamic part
1723                                         di = (int) _templateHtml [partEnd + Marker.Length] - 0x971;
1724                                         writer.Write (dynamicParts [di]);
1725                                 }
1726
1727                                 partStart = partEnd + Marker.Length + 1;
1728                                 partEnd = (int) idxs [i];
1729
1730                                 writer.Write (_templateHtml, partStart, partEnd - partStart);
1731                         }
1732                 
1733                 }
1734         }
1735 }
1736
1737 #endif