2010-03-02 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Web / System.Web.UI.WebControls / MenuItem.cs
blobfe3c03955cb0aabb29ed8fbd94b0f82bbfba7087
1 //
2 // System.Web.UI.WebControls.MenuItem.cs
3 //
4 // Authors:
5 // Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
31 #if NET_2_0
33 using System;
34 using System.Collections;
35 using System.Text;
36 using System.ComponentModel;
37 using System.Web.UI;
39 namespace System.Web.UI.WebControls
41 [ParseChildrenAttribute (true, "ChildItems")]
42 public sealed class MenuItem: IStateManager, ICloneable
44 StateBag ViewState = new StateBag ();
45 MenuItemCollection items;
46 bool marked;
47 Menu menu;
48 MenuItem parent;
49 int index;
50 string path;
51 int depth = -1;
53 object dataItem;
54 IHierarchyData hierarchyData;
56 bool gotBinding;
57 MenuItemBinding binding;
58 PropertyDescriptorCollection boundProperties;
60 public MenuItem ()
64 public MenuItem (string text)
66 Text = text;
69 public MenuItem (string text, string value)
71 Text = text;
72 Value = value;
75 public MenuItem (string text, string value, string imageUrl)
77 Text = text;
78 Value = value;
79 ImageUrl = imageUrl;
82 public MenuItem (string text, string value, string imageUrl, string navigateUrl)
84 Text = text;
85 Value = value;
86 ImageUrl = imageUrl;
87 NavigateUrl = navigateUrl;
90 public MenuItem (string text, string value, string imageUrl, string navigateUrl, string target)
92 Text = text;
93 Value = value;
94 ImageUrl = imageUrl;
95 NavigateUrl = navigateUrl;
96 Target = target;
99 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
100 [Browsable (false)]
101 public int Depth {
102 get {
103 if (depth != -1) return depth;
104 if (Parent == null) depth = 0;
105 else depth = Parent.Depth + 1;
106 return depth;
110 void ResetPathData ()
112 path = null;
113 depth = -1;
114 gotBinding = false;
117 internal Menu Menu {
118 get { return menu; }
119 set {
120 menu = value;
121 if (items != null)
122 items.SetMenu (menu);
123 ResetPathData ();
127 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
128 [DefaultValue (false)]
129 [Browsable (false)]
130 public bool DataBound {
131 get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
132 private set { ViewState ["DataBound"] = value; }
135 [DefaultValue (null)]
136 [Browsable (false)]
137 public object DataItem {
138 get {
139 if (!DataBound) throw new InvalidOperationException ("MenuItem is not data bound.");
140 return dataItem;
144 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
145 [DefaultValue ("")]
146 [Browsable (false)]
147 public string DataPath {
148 get {
149 return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"];
151 private set {
152 ViewState ["DataPath"] = value;
156 [MergableProperty (false)]
157 [Browsable (false)]
158 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
159 public MenuItemCollection ChildItems {
160 get {
161 if (items == null) {
162 items = new MenuItemCollection (this);
164 if (((IStateManager)this).IsTrackingViewState)
165 ((IStateManager)items).TrackViewState();
167 return items;
171 [DefaultValue ("")]
172 [UrlProperty]
173 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
174 public string ImageUrl {
175 get {
176 return ViewState ["ImageUrl"] == null ? String.Empty : (String) ViewState ["ImageUrl"];
178 set {
179 ViewState ["ImageUrl"] = value;
183 [DefaultValue ("")]
184 [UrlProperty]
185 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
186 public string NavigateUrl {
187 get {
188 return ViewState ["NavigateUrl"] == null ? String.Empty : (String) ViewState ["NavigateUrl"];
190 set {
191 ViewState ["NavigateUrl"] = value;
195 [DefaultValue ("")]
196 [UrlProperty]
197 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
198 public string PopOutImageUrl {
199 get {
200 return ViewState ["PopOutImageUrl"] == null ? String.Empty : (String) ViewState ["PopOutImageUrl"];
202 set {
203 ViewState ["PopOutImageUrl"] = value;
207 [DefaultValue ("")]
208 public string Target {
209 get {
210 return ViewState ["Target"] == null ? String.Empty : (String) ViewState ["Target"];
212 set {
213 ViewState ["Target"] = value;
217 [Localizable (true)]
218 [DefaultValue ("")]
219 public string Text {
220 get {
221 object o = ViewState ["Text"];
222 if (o == null)
223 o = ViewState ["Value"];
224 if (o != null)
225 return (string) o;
226 return String.Empty;
228 set {
229 ViewState ["Text"] = value;
233 [Localizable (true)]
234 [DefaultValue ("")]
235 public string ToolTip {
236 get {
237 return ViewState ["ToolTip"] == null ? String.Empty : (String) ViewState ["ToolTip"];
239 set {
240 ViewState ["ToolTip"] = value;
244 [Localizable (true)]
245 [DefaultValue ("")]
246 public string Value {
247 get {
248 object o = ViewState ["Value"];
249 if (o == null)
250 o = ViewState ["Text"];
251 if (o != null)
252 return (string) o;
253 return String.Empty;
255 set {
256 ViewState ["Value"] = value;
260 [DefaultValue ("")]
261 [UrlProperty]
262 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
263 public string SeparatorImageUrl {
264 get {
265 return ViewState ["SeparatorImageUrl"] == null ? String.Empty : (String) ViewState ["SeparatorImageUrl"];
267 set {
268 ViewState ["SeparatorImageUrl"] = value;
272 [BrowsableAttribute (true)]
273 [DefaultValueAttribute (true)]
274 public bool Selectable {
275 get {
276 return ViewState ["Selectable"] == null ? true : (bool) ViewState ["Selectable"];
278 set {
279 ViewState ["Selectable"] = value;
283 [BrowsableAttribute (true)]
284 [DefaultValueAttribute (true)]
285 public bool Enabled {
286 get {
287 return ViewState ["Enabled"] == null ? true : (bool) ViewState ["Enabled"];
289 set {
290 ViewState ["Enabled"] = value;
294 internal bool BranchEnabled {
295 get { return Enabled && (parent == null || parent.BranchEnabled); }
298 [DefaultValue (false)]
299 [Browsable (true)]
300 public bool Selected {
301 get {
302 if (menu != null)
303 return menu.SelectedItem == this;
304 else
305 return false;
307 set {
308 if (menu != null) {
309 if (!value && menu.SelectedItem == this)
310 menu.SetSelectedItem (null);
311 else if (value)
312 menu.SetSelectedItem (this);
317 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
318 [Browsable (false)]
319 public MenuItem Parent {
320 get { return parent; }
323 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
324 [Browsable (false)]
325 public string ValuePath {
326 get {
327 if (menu == null) return Value;
329 StringBuilder sb = new StringBuilder (Value);
330 MenuItem item = parent;
331 while (item != null) {
332 sb.Insert (0, menu.PathSeparator);
333 sb.Insert (0, item.Value);
334 item = item.Parent;
336 return sb.ToString ();
340 internal int Index {
341 get { return index; }
342 set { index = value; ResetPathData (); }
345 internal void SetParent (MenuItem item) {
346 parent = item;
347 ResetPathData ();
350 internal string Path {
351 get {
352 if (path != null) return path;
353 StringBuilder sb = new StringBuilder (index.ToString());
354 MenuItem item = parent;
355 while (item != null) {
356 sb.Insert (0, '_');
357 sb.Insert (0, item.Index.ToString ());
358 item = item.Parent;
360 path = sb.ToString ();
361 return path;
365 internal bool HasChildData {
366 get { return items != null; }
369 void IStateManager.LoadViewState (object savedState)
371 if (savedState == null)
372 return;
374 object[] states = (object[]) savedState;
375 ViewState.LoadViewState (states [0]);
377 if (states [1] != null)
378 ((IStateManager)ChildItems).LoadViewState (states [1]);
381 object IStateManager.SaveViewState ()
383 object[] states = new object[2];
384 states[0] = ViewState.SaveViewState();
385 states[1] = (items == null ? null : ((IStateManager)items).SaveViewState());
387 for (int i = 0; i < states.Length; i++) {
388 if (states [i] != null)
389 return states;
391 return null;
394 void IStateManager.TrackViewState ()
396 if (marked) return;
397 marked = true;
398 ViewState.TrackViewState();
400 if (items != null)
401 ((IStateManager)items).TrackViewState ();
404 bool IStateManager.IsTrackingViewState
406 get { return marked; }
409 internal void SetDirty ()
411 ViewState.SetDirty (true);
412 if (items != null)
413 items.SetDirty ();
416 object ICloneable.Clone ()
418 MenuItem nod = new MenuItem ();
419 foreach (DictionaryEntry e in ViewState)
420 nod.ViewState [(string)e.Key] = e.Value;
422 foreach (ICloneable c in ChildItems)
423 nod.ChildItems.Add ((MenuItem)c.Clone ());
425 return nod;
428 internal void Bind (IHierarchyData hierarchyData)
430 this.hierarchyData = hierarchyData;
431 DataBound = true;
432 DataPath = hierarchyData.Path;
433 dataItem = hierarchyData.Item;
435 MenuItemBinding bin = GetBinding ();
436 if (bin != null) {
438 // Bind Enabled property
440 if (bin.EnabledField != "")
441 try { Enabled = Convert.ToBoolean (GetBoundPropertyValue (bin.EnabledField)); }
442 catch { Enabled = bin.Enabled; }
443 else
444 Enabled = bin.Enabled;
446 // Bind ImageUrl property
448 if (bin.ImageUrlField.Length > 0) {
449 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
450 if (ImageUrl.Length == 0)
451 ImageUrl = bin.ImageUrl;
453 else if (bin.ImageUrl.Length > 0)
454 ImageUrl = bin.ImageUrl;
456 // Bind NavigateUrl property
458 if (bin.NavigateUrlField.Length > 0) {
459 NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
460 if (NavigateUrl.Length == 0)
461 NavigateUrl = bin.NavigateUrl;
463 else if (bin.NavigateUrl.Length > 0)
464 NavigateUrl = bin.NavigateUrl;
466 // Bind PopOutImageUrl property
468 if (bin.PopOutImageUrlField.Length > 0) {
469 PopOutImageUrl = Convert.ToString (GetBoundPropertyValue (bin.PopOutImageUrlField));
470 if (PopOutImageUrl.Length == 0)
471 PopOutImageUrl = bin.PopOutImageUrl;
473 else if (bin.PopOutImageUrl.Length > 0)
474 PopOutImageUrl = bin.PopOutImageUrl;
476 // Bind Selectable property
478 if (bin.SelectableField != "")
479 try { Selectable = Convert.ToBoolean (GetBoundPropertyValue (bin.SelectableField)); }
480 catch { Selectable = bin.Selectable; }
481 else
482 Selectable = bin.Selectable;
484 // Bind SeparatorImageUrl property
486 if (bin.SeparatorImageUrlField.Length > 0) {
487 SeparatorImageUrl = Convert.ToString (GetBoundPropertyValue (bin.SeparatorImageUrlField));
488 if (SeparatorImageUrl.Length == 0)
489 SeparatorImageUrl = bin.SeparatorImageUrl;
491 else if (bin.SeparatorImageUrl.Length > 0)
492 SeparatorImageUrl = bin.SeparatorImageUrl;
494 // Bind Target property
496 if (bin.TargetField.Length > 0) {
497 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
498 if (Target.Length == 0)
499 Target = bin.Target;
501 else if (bin.Target.Length > 0)
502 Target = bin.Target;
504 // Bind ToolTip property
506 if (bin.ToolTipField.Length > 0) {
507 ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
508 if (ToolTip.Length == 0)
509 ToolTip = bin.ToolTip;
511 else if (bin.ToolTip.Length > 0)
512 ToolTip = bin.ToolTip;
514 // Bind Value property
515 string value = null;
516 if (bin.ValueField.Length > 0) {
517 value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
519 if (String.IsNullOrEmpty (value)) {
520 if (bin.Value.Length > 0)
521 value = bin.Value;
522 else if (bin.Text.Length > 0)
523 value = bin.Text;
524 else
525 value = String.Empty;
527 Value = value;
529 // Bind Text property
530 string text = null;
531 if (bin.TextField.Length > 0) {
532 text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
533 if (bin.FormatString.Length > 0)
534 text = string.Format (bin.FormatString, text);
536 if (String.IsNullOrEmpty (text)) {
537 if (bin.Text.Length > 0)
538 text = bin.Text;
539 else if (bin.Value.Length > 0)
540 text = bin.Value;
541 else
542 text = String.Empty;
544 Text = text;
547 else {
548 Text = Value = GetDefaultBoundText ();
551 INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
552 if (navigateUIData != null) {
553 ToolTip = navigateUIData.Description;
554 Text = navigateUIData.ToString ();
555 NavigateUrl = navigateUIData.NavigateUrl;
559 internal void SetDataItem (object item)
561 dataItem = item;
564 internal void SetDataPath (string path)
566 DataPath = path;
569 internal void SetDataBound (bool bound)
571 DataBound = bound;
574 string GetDefaultBoundText ()
576 if (hierarchyData != null) return hierarchyData.ToString ();
577 else if (dataItem != null) return dataItem.ToString ();
578 else return string.Empty;
581 string GetDataItemType ()
583 if (hierarchyData != null) return hierarchyData.Type;
584 else if (dataItem != null) return dataItem.GetType().ToString ();
585 else return string.Empty;
588 MenuItemBinding GetBinding ()
590 if (menu == null) return null;
591 if (gotBinding) return binding;
592 binding = menu.FindBindingForItem (GetDataItemType (), Depth);
593 gotBinding = true;
594 return binding;
597 object GetBoundPropertyValue (string name)
599 if (boundProperties == null) {
600 if (hierarchyData != null)
601 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
602 else
603 boundProperties = TypeDescriptor.GetProperties (dataItem);
606 PropertyDescriptor prop = boundProperties.Find (name, true);
607 if (prop == null)
608 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
610 if (hierarchyData != null)
611 return prop.GetValue (hierarchyData);
612 else
613 return prop.GetValue (dataItem);
618 #endif