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