// AMenu.cs
using System;
using System.Text;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
using System.Drawing;
using System.Security.Permissions;
namespace mtweb
{
//////////////////////////////////////////////////////////////////////////
[ParseChildren(false)]
[PersistChildren(true)]
[DefaultEvent("ItemClick")]
[ToolboxData("<{0}:AMenu runat=server></{0}:AMenu>")]
public class AMenu : WebControl, INamingContainer
{
// Constants
public const string DEF_WIDTH = "190px";
public const string DEF_HEIGHT = "10em";
public const string DEF_FONTSIZE = "12px";
public const string DEF_FONTNAME = "Arial";
public const bool DEF_FONTBOLD = false;
public const string DEF_FORECOLOR = "#336666";
public const string DEF_BACKCOLOR = "#f7f7f7";
public const string DEF_BORDERCOLOR = "#c6c6cc";
public const string DEF_FOREHOVER = "#0000ff";
public const string DEF_BACKHOVER = "#dae0e4";
public const string DEF_MARGIN = "2px";
public const string DEF_INDENT = "38px";
public const bool DEF_BORDER = false;
public const string DEF_ARROWIMAGE = "";
public const string DEF_ICONIMAGE = "";
public const string DEF_SUBWIDTH = "190px";
public const string DEF_SUBMARGIN = "2px";
public const string DEF_SUBINDENT = "16px";
//
public const string CLASS_AMENU = "amenu";
public const string CLASS_TOP = "top";
public const string CLASS_SUB = "sub";
public const string CLASS_VPADDING_TOP = "vpadding_top";
public const string CLASS_VPADDING_BOTTOM = "vpadding_bottom";
public const string CLASS_ARROW = "arrow";
// Fields
private ArrayList m_Items = new ArrayList();
private event CommandEventHandler m_ItemClick;
///////////////////////////////////////////////
// Constructor
public AMenu() : base(HtmlTextWriterTag.Div)
{
}
///////////////////////////////////////////////
// Events
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
///////////////////////////////////////////////
// Properties
// Hide inherited:
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override Unit BorderWidth
{
get { return Unit.Empty; }
set {}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override BorderStyle BorderStyle
{
get { return BorderStyle.NotSet; }
set {}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override Boolean Enabled
{
get { return true; }
set {}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override String SkinID
{
get { return string.Empty; }
set {}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override Boolean EnableTheming
{
get { return false; }
set {}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override String ToolTip
{
get { return string.Empty; }
set {}
}
// Top menu:
// Child controls
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ArrayList Items
{
get { return m_Items; }
set { m_Items = value;}
}
// Top menu width.
// Note: Unit.Empty will reset to def. value
[Category("Layout")]
[DefaultValue(DEF_WIDTH)]
[Bindable(true)]
public override Unit Width
{
get {
object o = ViewState["TopWidth"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return new Unit(DEF_WIDTH);
}
set {
ViewState["TopWidth"] = value;
}
}
// Top menu height.
// Note: Unit.Empty will reset to def. value
[Category("Layout")]
[DefaultValue(DEF_HEIGHT)]
[Bindable(true)]
public override Unit Height
{
get {
object o = ViewState["TopHeight"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return Unit.Parse(DEF_HEIGHT);
}
set {
ViewState["TopHeight"] = value;
}
}
// Menu font size.
// Note: Unit.Empty will reset to def. value.
// Note: In Properties window use Font-Size,
// in code use this.FontSize.
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(typeof(Unit),DEF_FONTSIZE)]
[TypeConverter(typeof(UnitConverter))]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Unit FontSize
{
get {
Unit u = base.Font.Size.Unit;
if (!u.IsEmpty) return u;
return Unit.Parse(DEF_FONTSIZE);
}
set {
base.Font.Size = FontUnit.Parse(value.ToString());
}
}
// Menu font name.
// Note: NULL will reset to def. value.
// Note: In Properties window use Font-Names, in code
// use this.FontNames to set/get the font name(s)
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(DEF_FONTNAME)]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual string[] FontNames
{
get {
string[] s = base.Font.Names;
if (s.Length != 0) return s;
return new string[1]{DEF_FONTNAME};
}
set {
if (value == null) base.Font.Names = new string[0]{};
else base.Font.Names = value;
}
}
// Menu font bold [true|false]
// Note: In Properties window use Font-Bold, in code
// use this.FontBold to set/get the property
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(DEF_FONTBOLD)]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual bool FontBold
{
get {
return base.Font.Bold;
}
set {
base.Font.Bold = value;
}
}
// Menu font color.
// Note: Color.Empty will reset to def. value.
[Category("Appearance")]
[DefaultValue(typeof(Color),DEF_FORECOLOR)]
[TypeConverter(typeof(WebColorConverter))]
[Bindable(true)]
public override Color ForeColor
{
get {
Color c = base.ForeColor;
if (!c.IsEmpty) return c;
return ColorTranslator.FromHtml(DEF_FORECOLOR);
}
set {
base.ForeColor = value;
}
}
// Menu background color.
// Note: Color.Empty will reset to def. value.
[Category("Appearance")]
[DefaultValue(typeof(Color),DEF_BACKCOLOR)]
[TypeConverter(typeof(WebColorConverter))]
[Bindable(true)]
public override Color BackColor
{
get {
Color c = base.BackColor;
if (!c.IsEmpty) return c;
return ColorTranslator.FromHtml(DEF_BACKCOLOR);
}
set {
base.BackColor = value;
}
}
// Menu border color.
// Note: Color.Empty will reset to def. value.
[Category("Appearance")]
[DefaultValue(typeof(Color),DEF_BORDERCOLOR)]
[TypeConverter(typeof(WebColorConverter))]
[Bindable(true)]
public override Color BorderColor
{
get {
Color c = base.BorderColor;
if (!c.IsEmpty) return c;
return ColorTranslator.FromHtml(DEF_BORDERCOLOR);
}
set {
base.BorderColor = value;
}
}
// Menu hover color.
// Note: Color.Empty will reset to def. value.
[Category("Appearance")]
[DefaultValue(typeof(Color),DEF_FOREHOVER)]
[TypeConverter(typeof(WebColorConverter))]
[Bindable(true)]
public virtual Color ForeHover
{
get {
object o = ViewState["ForeHover"];
if (o != null && ((Color)o) != Color.Empty) return (Color)o;
return ColorTranslator.FromHtml(DEF_FOREHOVER);
}
set {
ViewState["ForeHover"] = value;
}
}
// Menu hover background.
// Note: Color.Empty will reset to def. value.
[Category("Appearance")]
[DefaultValue(typeof(Color),DEF_BACKHOVER)]
[TypeConverter(typeof(WebColorConverter))]
[Bindable(true)]
public virtual Color BackHover
{
get {
object o = ViewState["BackHover"];
if (o != null && ((Color)o) != Color.Empty) return (Color)o;
return ColorTranslator.FromHtml(DEF_BACKHOVER);
}
set {
ViewState["BackHover"] = value;
}
}
// Top menu left and right margins.
// Note: Unit.Empty will reset to def. value
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(typeof(Unit),DEF_MARGIN)]
[TypeConverter(typeof(UnitConverter))]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Unit Margin
{
get {
object o = ViewState["TopMargin"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return new Unit(DEF_MARGIN);
}
set {
ViewState["TopMargin"] = value;
}
}
// Top menu left padding.
// Note: Unit.Empty will reset to def. value
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(typeof(Unit),DEF_INDENT)]
[TypeConverter(typeof(UnitConverter))]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Unit Indent
{
get {
object o = ViewState["TopIndent"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return new Unit(DEF_INDENT);
}
set {
ViewState["TopIndent"] = value;
}
}
// Top menu border [true|false]
[Category("Layout")]
[DefaultValue(DEF_BORDER)]
[Bindable(true)]
public virtual bool Border
{
get {
object o = ViewState["TopBorder"];
return (o == null) ? DEF_BORDER : (bool)o;
}
set {
ViewState["TopBorder"] = value;
}
}
// Arrow image for links with sub-menus
[Category("Appearance")]
[UrlProperty()]
[DefaultValue(DEF_ARROWIMAGE)]
[Bindable(true)]
public virtual string ArrowImage
{
get {
String s = (String)ViewState["ArrowImage"];
if (s == null) s = DEF_ARROWIMAGE;
return ToAbsolute(s);
}
set {
ViewState["ArrowImage"] = value;
}
}
// --------------
// Sub menu
// Default width of all sub menus.
// Can be overwritten for each sub menu.
// Note: Unit.Empty will reset to def. value
[Category("Layout")]
[DefaultValue(typeof(Unit),DEF_SUBWIDTH)]
[TypeConverter(typeof(UnitConverter))]
[Bindable(true)]
public virtual Unit SubWidth
{
get {
object o = ViewState["SubWidth"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return Unit.Parse(DEF_SUBWIDTH);
}
set {
ViewState["SubWidth"] = value;
}
}
// Sub menu left and right margins.
// Note: Unit.Empty will reset to def. value
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(typeof(Unit),DEF_SUBMARGIN)]
[TypeConverter(typeof(UnitConverter))]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Unit SubMargin
{
get {
object o = ViewState["SubMargin"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return Unit.Parse(DEF_SUBMARGIN);
}
set {
ViewState["SubMargin"] = value;
}
}
// Sub menu left padding.
// Note: Unit.Empty will reset to def. value
[ReadOnly(true)]
[Browsable(false)]
[DefaultValue(typeof(Unit),DEF_SUBINDENT)]
[TypeConverter(typeof(UnitConverter))]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Unit SubIndent
{
get {
object o = ViewState["SubIndent"];
if (o != null && ((Unit)o) != Unit.Empty) return (Unit)o;
return Unit.Parse(DEF_SUBINDENT);
}
set {
ViewState["SubIndent"] = value;
}
}
// Click handler (server)
[Category("Action")]
public event CommandEventHandler ItemClick
{
add { m_ItemClick += value; }
remove { m_ItemClick -= value; }
}
///////////////////////////////////////////////
// Rendering
public override void RenderBeginTag(HtmlTextWriter writer)
{
// Call base: <div>
base.RenderBeginTag(writer);
// Render UL for this top-menu:
// ID ... not needed
//writer.AddAttribute("id", "root");
// Class
writer.AddAttribute("class", AMenu.CLASS_TOP);
// Width
if (Width != Unit.Empty) {
if (!AMenu.IsDefault(Width.ToString(), AMenu.DEF_WIDTH)) {
writer.AddStyleAttribute("width", Width.ToString());
}
}
// Background color
if (!BackColor.IsEmpty) {
string bc = ColorTranslator.ToHtml(BackColor);
if (!AMenu.IsDefault(bc, AMenu.DEF_BACKCOLOR)) {
writer.AddStyleAttribute("background-color", bc);
}
}
// Open the UL tag
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
// Render LI for top padding:
// Class
writer.AddAttribute("class", AMenu.CLASS_VPADDING_TOP);
// Width
if (Width != Unit.Empty) {
if (!AMenu.IsDefault(Width.ToString(), AMenu.DEF_WIDTH)) {
writer.AddStyleAttribute("width", Width.ToString());
}
}
// Border (left/right/bottom) color
if (!BorderColor.IsEmpty) {
string bc = ColorTranslator.ToHtml(BorderColor);
if (!AMenu.IsDefault(bc, AMenu.DEF_BORDERCOLOR)) {
writer.AddStyleAttribute("border-color", bc);
}
}
// Remove borders, if needed
if (!Border) {
writer.AddStyleAttribute("border", "none");
writer.AddStyleAttribute("height", "0");
}
// Open/close the LI tag
writer.RenderBeginTag(HtmlTextWriterTag.Li);
writer.Write(" ");
writer.RenderEndTag();
}
// Note: don't call base, set attributes manually
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
// ID
writer.AddAttribute("id", this.ID);
// Class
writer.AddAttribute("class", AMenu.CLASS_AMENU);
// Height
if (Height != Unit.Empty) {
writer.AddStyleAttribute("height", Height.ToString());
}
// Font size
if (FontSize != Unit.Empty) {
if (!AMenu.IsDefault(FontSize.ToString(), AMenu.DEF_FONTSIZE)) {
writer.AddStyleAttribute("font-size", FontSize.ToString());
}
}
// Font family
if (FontNames.Length > 0) {
string fnames = string.Join(",", FontNames);
if (!AMenu.IsDefault(fnames, AMenu.DEF_FONTNAME)) {
writer.AddStyleAttribute("font-family", fnames);
}
}
// Font weight
if (FontBold != AMenu.DEF_FONTBOLD) {
writer.AddStyleAttribute("font-weight", "bold");
}
}
public override void RenderEndTag(HtmlTextWriter writer)
{
// Render LI for bottom padding:
// Class
writer.AddAttribute("class", AMenu.CLASS_VPADDING_BOTTOM);
// Width
if (Width != Unit.Empty) {
if (!AMenu.IsDefault(Width.ToString(), AMenu.DEF_WIDTH)) {
writer.AddStyleAttribute("width", Width.ToString());
}
}
// Border (left/right/top) color
if (!BorderColor.IsEmpty) {
string bc = ColorTranslator.ToHtml(BorderColor);
if (!AMenu.IsDefault(bc, AMenu.DEF_BORDERCOLOR)) {
writer.AddStyleAttribute("border-color", bc);
}
}
// Remove borders, if needed
if (!Border) {
writer.AddStyleAttribute("border", "none");
writer.AddStyleAttribute("height", "0");
}
// Open/close the LI tag
writer.RenderBeginTag(HtmlTextWriterTag.Li);
writer.Write(" ");
writer.RenderEndTag();
// Close the UL tag
writer.RenderEndTag();
// Call base: </div>
base.RenderEndTag(writer);
}
///////////////////////////////////////////////
// Methods
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected override void AddParsedSubObject(Object obj)
{
m_Items.Add(obj);
}
protected override void CreateChildControls()
{
foreach (Control c in m_Items) {
this.Controls.Add(c);
}
}
// Return TRUE if event should not be bubbled
protected override bool OnBubbleEvent(object sender, EventArgs e)
{
// If not a command arg, or not from MenuLink, ignore
if (!(e is CommandEventArgs) || !(sender is MenuLink))
{
return false;
}
// Call the handler if we got one
if (m_ItemClick != null) {
m_ItemClick(sender, (CommandEventArgs)e);
return true;
}
// Event not handled
return false;
}
///////////////////////////////////////////////
// Utility
public static double RoundUp(double d)
{
return Math.Floor(d + 0.5);
}
public static double RoundDown(double d)
{
double floor = Math.Floor(d);
if ((d - floor) > 0.5) return (floor + 1);
else return (floor);
}
public static bool IsDefault(string val, string defval)
{
string s1 = val.Trim().Replace("'","").ToUpper();
string s2 = defval.Trim().Replace("'","").ToUpper();
return s1 == s2;
}
public static string ToAbsolute(string path)
{
path = path.Trim();
if (string.IsNullOrEmpty(path)) return string.Empty;
return VirtualPathUtility.ToAbsolute(path);
}
} // class
} // namespace