/*******************************************************}
{                                                       }
{               Borland DB Web                          }
{           Data aware Web controls                     }
{  Copyright (c) 2003 Borland Software Corporation      }
{                                                       }
{*******************************************************/

using System;
using System.Data;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Drawing.Design;
using System.Text;


namespace Borland.Data.Web
{

	public enum NavigatorButtonType
   {
   	ButtonText,
      ButtonSymbols,
      ButtonIcons
   }

   public interface INavigatorDesignAccess
   {
      string GetDefaultImagesVirtualPath();
      string GetButtonFileName();
   }

	#region DBWebNavigator
	/// <summary>
	/// Data Navigator control
   /// responsible for sending scrolling, undo, apply, refresh
   /// requests to DBWebNavigator
	/// </summary>

	[Designer("Borland.Data.Web.DBWebControlDesigner"),
   ToolboxBitmap(typeof(Borland.Data.Web.DBWebNavigator),
   "Borland.Data.Web.DBWebNavigator.bmp"),
	ToolboxData("<{0}:DBWebNavigator runat=server></{0}:DBWebNavigator>")]
   public class DBWebNavigator : WebControl, IDBWebDataLink, IPostBackDataHandler, INavigatorDesignAccess
   {  // button resources
      //
      protected const string FDefaultRefreshJpg = "NavBtnRefresh.gif";
      protected const string FDefaultInsertJpg = "NavBtnInsert.gif";
      protected const string FDefaultDeleteJpg = "NavBtnDelete.gif";
      protected const string FDefaultFirstJpg = "NavBtnFirst.gif";
      protected const string FDefaultLastJpg = "NavBtnLast.gif";
      protected const string FDefaultNextJpg = "NavBtnNext.gif";
      protected const string FDefaultPrevJpg = "NavBtnPrev.gif";
      protected const string FDefaultUndoJpg = "NavBtnUndo.gif";
      protected const string FDefaultUndoAllJpg = "NavBtnUndoAll.gif";
      protected const string FDefaultApplyJpg = "NavBtnApply.gif";
      protected const string FDefaultDisabledRefreshJpg = "NavBtnDisabledRefresh.gif";
      protected const string FDefaultDisabledInsertJpg = "NavBtnDisabledInsert.gif";
      protected const string FDefaultDisabledDeleteJpg = "NavBtnDisabledDelete.gif";
      protected const string FDefaultDisabledFirstJpg = "NavBtnDisabledFirst.gif";
      protected const string FDefaultDisabledLastJpg = "NavBtnDisabledLast.gif";
      protected const string FDefaultDisabledNextJpg = "NavBtnDisabledNext.gif";
      protected const string FDefaultDisabledPrevJpg = "NavBtnDisabledPrev.gif";
      protected const string FDefaultDisabledUndoJpg = "NavBtnDisabledUndo.gif";
      protected const string FDefaultDisabledUndoAllJpg = "NavBtnDisabledUndoAll.gif";
      protected const string FDefaultDisabledApplyJpg = "NavBtnDisabledApply.gif";
      protected const string FDefaultImageVirtualPath = "BorlandImages";
      protected const int MinWidth = 15*8;
      protected const int MinHeight = 8;
      protected const int maxGap = 4;
		protected ArrayList NavButtons;
      protected ArrayList IconNavButtons;
      private NavigatorButtonType FButtonType;
      private System.Web.UI.WebControls.Panel FPanel;
      private DBWebDataLink FDataLink;
      private IDBWebDataLink IDataLink;

      private string FFirstButtonIcon;
      private string FLastButtonIcon;
      private string FNextButtonIcon;
      private string FPreviousButtonIcon;
      private string FInsertButtonIcon;
      private string FDeleteButtonIcon;
      private string FRefreshButtonIcon;
      private string FApplyButtonIcon;
      private string FUndoButtonIcon;
      private string FUndoAllButtonIcon;

      private string FImagesVirtualPath;

   	public DBWebNavigator(): base()
      {
			NavButtons = new ArrayList();
			IconNavButtons = new ArrayList();
         FPanel = new System.Web.UI.WebControls.Panel();
         FPanel.Wrap = false;
         FPanel.Width = MinWidth*3;
         this.Width = FPanel.Width;
         this.Height = FPanel.Height;
         FButtonType = NavigatorButtonType.ButtonSymbols;
         FDataLink = new DBWebDataLink(this);
         IDataLink = (FDataLink as IDBWebDataLink);
		 FRefreshButtonIcon = FDefaultRefreshJpg;
		 FInsertButtonIcon = FDefaultInsertJpg;
		 FDeleteButtonIcon = FDefaultDeleteJpg;
		 FFirstButtonIcon = FDefaultFirstJpg;
		 FLastButtonIcon = FDefaultLastJpg;
		 FNextButtonIcon = FDefaultNextJpg;
		 FPreviousButtonIcon = FDefaultPrevJpg;
		 FUndoButtonIcon = FDefaultUndoJpg;
		 FUndoAllButtonIcon = FDefaultUndoAllJpg;
      	 FApplyButtonIcon = FDefaultApplyJpg;
         FImagesVirtualPath = FDefaultImageVirtualPath;
      }

		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);
			if( Page != null )
				Page.RegisterRequiresPostBack(this);
      }


      public event DBWebNavigatorEvent Click;

      #region IPostBackDataHandler
      // RaisePostDataChangedEvent is called prior to DataBind()
      // DataSet and related properties are NOT available here
      // Child controls are not available
		bool IPostBackDataHandler.LoadPostData(string postDataKey,
			NameValueCollection postCollection)
      {
         if( this.Visible )
	      	FDataLink.LoadPostData(postDataKey, postCollection);
         return false;
      }

	   void IPostBackDataHandler.RaisePostDataChangedEvent()
   	{
	   }
      #endregion

      #region IDBWebDataLink
      string IDBWebDataLink.TableName
      {
      	get
         {
         	return IDataLink.TableName;
         }
         set
         {
         	IDataLink.TableName = value;
         }
      }
      IDBDataSource IDBWebDataLink.DBDataSource
      {
      	get
         {
         	return IDataLink.DBDataSource;
         }
         set
         {
         	IDataLink.DBDataSource = value;
         }
      }
      #endregion

      [Editor(typeof(Borland.Data.Web.TableNamePropEditor), typeof(UITypeEditor)),
		LocalizableCategoryAttribute("DBWebControl"),
		DefaultValue("")]
      public string TableName
      {
      	get
         {
	      	return IDataLink.TableName;
         }
      	set
         {
	      	IDataLink.TableName = value;
         }
      }
		[LocalizableCategoryAttribute("DBWebControl"),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
		DefaultValue(null)]
		
      public IDBDataSource DBDataSource
      {
      	get
         {
         	return IDataLink.DBDataSource;
         }
         set
         {
         	IDataLink.DBDataSource = value;
         }
      }

		[LocalizableCategoryAttribute("DBWebControl"),
		DefaultValue(FDefaultImageVirtualPath)]
      public string ImagesVirtualPath
      {
      	get
         {
         	return FImagesVirtualPath;
         }
         set
         {
         	FImagesVirtualPath = value;
         }
      }

      protected bool HasRecords()
      {
         if( FDataLink == null || ClassUtils.IsDesignTime(Page) )
         	return true;
      	if( !FDataLink.IsDataBound )
         	return true;
         return IDataLink.DBDataSource.GetDisplayRowCount(Page, TableName) > 0;
      }

      protected bool HasDetailRecords()
      {
         if( FDataLink == null || ClassUtils.IsDesignTime(Page) )
         	return false;
      	if( !FDataLink.IsDataBound )
         	return false;
         return IDataLink.DBDataSource.HasDetailRecords(Page, TableName);
      }

      protected bool DataSourceHasApplyEvent()
      {
         if( ClassUtils.IsDesignTime(Page) )
         	return true;
      	else if( FDataLink == null )
         	return false;
         else if( !FDataLink.IsDataBound )
         	return false;
         else if( Click != null )
         	return true;
         return (IDataLink.DBDataSource as IDBPostStateManager).HasApplyEvent();
      }

      #region INavigatorDesignAccess
      string INavigatorDesignAccess.GetDefaultImagesVirtualPath()
      {
      	return FDefaultImageVirtualPath;
      }

      string INavigatorDesignAccess.GetButtonFileName()
      {
      	return FDefaultFirstJpg;
      }
      #endregion INavigatorDesignAccess;

      #region Layout
		[LocalizableCategoryAttribute("Layout")]
      public override Unit Width
      {
      	get
         {
         	return base.Width;
         }
         set
         {
         	if( value.Value >= MinWidth )
            {
	         	base.Width = value;
   	         FPanel.Width = value;
            }
         }
      }


		[LocalizableCategoryAttribute("Layout")]
      public override Unit Height
      {
      	get
         {
         	return base.Height;
         }
         set
         {
         	if( value.Value >= MinHeight )
            {
	         	base.Height = value;
   	         FPanel.Height = value;
            }
         }
      }


      #endregion

      #region AddButtons
		protected void AddButtons()
		{
      	NavButtons.Clear();
         IconNavButtons.Clear();
         if( HasRecords() )
         {
			AddButton(DBWebConst.sFirstText, true);
			AddButton(DBWebConst.sPrevText, true);
			AddButton(DBWebConst.sNextText, true);
			AddButton(DBWebConst.sLastText, true);
		 }
		 else
		 {
			AddButton(DBWebConst.sFirstText, false);
			AddButton(DBWebConst.sPrevText, false);
			AddButton(DBWebConst.sNextText, false);
			AddButton(DBWebConst.sLastText, false);
         }
         AddButton(DBWebConst.sInsertText, true);
         if( HasRecords() && !HasDetailRecords() )
	         AddButton(DBWebConst.sDeleteText, true);
         else
	         AddButton(DBWebConst.sDeleteText, false);
         if( DataSourceHasApplyEvent() )
	         AddButton(DBWebConst.sApplyText, true);
         else
	         AddButton(DBWebConst.sApplyText, false);
         if( !FDataLink.DataSourceHasDelta(Page) )
         {
         	AddButton(DBWebConst.sRefreshText, true);
         	AddButton(DBWebConst.sUndoText, false);
            AddButton(DBWebConst.sUndoAllText, false);
         }
         else
			{
         	AddButton(DBWebConst.sRefreshText, false);
         	AddButton(DBWebConst.sUndoText, true);
            AddButton(DBWebConst.sUndoAllText, true);
         }
		}

      private void AddButton(string Text, bool enabled)
		{
      	if( FButtonType == NavigatorButtonType.ButtonIcons )
         {
            AddIconButton(Text, enabled);
            return;
         }
         string sText = BdwResources.GetString(Text);
			Button tempButton = new Button();
			tempButton.ID = IDataLink.TableName + DBWebConst.Splitter + Text;
         tempButton.Enabled = enabled;
         if( FButtonType == NavigatorButtonType.ButtonSymbols )
         {
         	tempButton.Text  = GetSymbolForText(Text);
            tempButton.Font.Bold = true;
            tempButton.ToolTip = sText;
         }
         else
         {
				tempButton.Text = sText;
            tempButton.ToolTip = sText;
         }
         tempButton.CommandName = Text;
			tempButton.Page = this.Page;
         ClassUtils.SetInnerAppearanceProperties( tempButton, this );
         if( this.Height.Value > MinHeight )
         	tempButton.Height = Unit.Parse(Convert.ToString(this.Height.Value) + "px");
			NavButtons.Add(tempButton);
		}

      private string GetImageUrlForButton(string text, bool Enabled)
      {
      	string sImageUrl = "";
      	if( text == DBWebConst.sNextText )
         {
         	if( !Enabled && FNextButtonIcon == FDefaultNextJpg )
	         	sImageUrl = FDefaultDisabledNextJpg;
            else
	         	sImageUrl = FNextButtonIcon;
         }
      	else if( text == DBWebConst.sPrevText )
         {
         	if( !Enabled && FPreviousButtonIcon == FDefaultPrevJpg )
	         	sImageUrl = FDefaultDisabledPrevJpg;
            else
	         	sImageUrl = FPreviousButtonIcon;
         }
      	else if( text == DBWebConst.sFirstText )
         {
         	if( !Enabled && FFirstButtonIcon == FDefaultFirstJpg )
	         	sImageUrl = FDefaultDisabledFirstJpg;
            else
		      	sImageUrl = FFirstButtonIcon;
         }
      	else if( text == DBWebConst.sLastText )
         {
         	if( !Enabled && FLastButtonIcon == FDefaultLastJpg )
	         	sImageUrl = FDefaultDisabledLastJpg;
            else
	         	sImageUrl = FLastButtonIcon;
         }
      	else if( text == DBWebConst.sApplyText )
         {
         	if( !Enabled && FApplyButtonIcon == FDefaultApplyJpg )
            	sImageUrl = FDefaultDisabledApplyJpg;
            else
         		sImageUrl = FApplyButtonIcon;
         }
      	else if( text == DBWebConst.sRefreshText )
         {
         	if( !Enabled && FRefreshButtonIcon == FDefaultRefreshJpg )
            	sImageUrl = FDefaultDisabledRefreshJpg;
            else
	         	sImageUrl = FRefreshButtonIcon;
         }
      	else if( text == DBWebConst.sDeleteText )
         {
         	if( !Enabled && FDeleteButtonIcon == FDefaultDeleteJpg )
            	sImageUrl = FDefaultDisabledDeleteJpg;
            else
	         	sImageUrl = FDeleteButtonIcon;
         }
      	else if( text == DBWebConst.sInsertText )
         {
         	if( !Enabled && FInsertButtonIcon == FDefaultInsertJpg )
            	sImageUrl = FDefaultDisabledInsertJpg;
            else
	         	sImageUrl = FInsertButtonIcon;
         }
      	else if( text == DBWebConst.sUndoText )
         {
         	if( !Enabled && FUndoButtonIcon == FDefaultUndoJpg )
            	sImageUrl = FDefaultDisabledUndoJpg;
            else
	         	sImageUrl = FUndoButtonIcon;
         }
      	else if( text == DBWebConst.sUndoAllText )
         {
         	if( !Enabled && FUndoAllButtonIcon == FDefaultUndoAllJpg )
            	sImageUrl = FDefaultDisabledUndoAllJpg;
            else
	         	sImageUrl = FUndoAllButtonIcon;
         }
      	else
         	return null;
         return ClassUtils.GetFullVirtualDirectory(FImagesVirtualPath) + sImageUrl;
      }

      private void AddIconButton(string Text, bool enabled)
      {
         ImageButton tempButton = new ImageButton();
         tempButton.ID = IDataLink.TableName + DBWebConst.Splitter + Text;
         tempButton.Enabled = enabled;
         tempButton.Page = this.Page;
         ClassUtils.SetInnerAppearanceProperties( tempButton, this );
         tempButton.ImageUrl = GetImageUrlForButton(Text, enabled);
         tempButton.ToolTip = BdwResources.GetString(Text);
         tempButton.CommandName = Text;
         if( this.Height.Value > MinHeight )
         	tempButton.Height = Unit.Parse(Convert.ToString(this.Height.Value) + "px");
         IconNavButtons.Add(tempButton);
      }

      private string GetSymbolForText(string Text)
      {
      	if( Text == DBWebConst.sFirstText )
         	return "|<";
      	else if( Text == DBWebConst.sLastText )
         	return ">|";
      	else if( Text == DBWebConst.sNextText )
         	return ">>";
      	else if( Text == DBWebConst.sPrevText )
         	return "<<";
      	else if( Text == DBWebConst.sInsertText )
         	return "+";
      	else if( Text == DBWebConst.sDeleteText )
         	return "_";
      	else if( Text == DBWebConst.sRefreshText )
         	return "[<]";
      	else if( Text == DBWebConst.sApplyText )
         	return "[>]";
      	else if( Text == DBWebConst.sUndoText )
         	return "X";
      	else if( Text == DBWebConst.sUndoAllText )
         	return "XX";
         return "";
      }


      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string NextButtonIcon
      {
      	get
         {
         	return FNextButtonIcon;
         }
         set
         {
         	FNextButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string PreviousButtonIcon
      {
      	get
         {
         	return FPreviousButtonIcon;
         }
         set
         {
         	FPreviousButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string FirstButtonIcon
      {
      	get
         {
         	return FFirstButtonIcon;
         }
         set
         {
         	FFirstButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string LastButtonIcon
      {
      	get
         {
         	return FLastButtonIcon;
         }
         set
         {
         	FLastButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string InsertButtonIcon
      {
      	get
         {
         	return FInsertButtonIcon;
         }
         set
         {
         	FInsertButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string DeleteButtonIcon
      {
      	get
         {
         	return FDeleteButtonIcon;
         }
         set
         {
         	FDeleteButtonIcon = value;
         }
      }


      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string ApplyButtonIcon
      {
      	get
         {
         	return FApplyButtonIcon;
         }
         set
         {
         	FApplyButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string RefreshButtonIcon
      {
      	get
         {
         	return FRefreshButtonIcon;
         }
         set
         {
         	FRefreshButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string UndoButtonIcon
      {
      	get
         {
         	return FUndoButtonIcon;
         }
         set
         {
         	FUndoButtonIcon = value;
         }
      }

      [Editor(typeof(Borland.Data.Web.DBWebSelectJpg), typeof(UITypeEditor)),
      LocalizableCategoryAttribute("ButtonIcon"),
      DefaultValue(null)]
      public string UndoAllButtonIcon
      {
      	get
         {
         	return FUndoAllButtonIcon;
         }
         set
         {
         	FUndoAllButtonIcon = value;
         }
      }



	  [LocalizableCategoryAttribute("DBWebControl"),
     DefaultValue(NavigatorButtonType.ButtonSymbols)]
	  public NavigatorButtonType ButtonType
	  {
		get
		{
         	return FButtonType;
         }
         set
         {
            if( FButtonType != value )
         		FButtonType = value;
         }
      }

      #endregion

      #region RenderHtml
      // writes html out at runtime
		protected override void Render(HtmlTextWriter output)
		{
      	bool error = ClassUtils.OutputErrors(Page, output, IDataLink);
         if( !error || (IDataLink.DBDataSource as DBWebDataSource).ErrorOption != ErrorHtmlOption.logOnErrorPage )
         	output.Write(Text);
         else  // if going to a separate error hmtl page, output "OK" button.
         {
         	ClassUtils.OutputOKButton(output);
            Page.Response.End();
         }
		}

      private void AdjustButtonsWidth()
      {

      }

      private void SetButtonsWidth()
      {
			string sWidth;
         int count;
         if( ButtonType == NavigatorButtonType.ButtonIcons )
         	count = IconNavButtons.Count;
         else
         	count = NavButtons.Count;
         double PanelBorder =  ((FPanel.BorderWidth.Value * 2) / count) + 1;
         double dWidth = (FPanel.Width.Value / count) - PanelBorder;
         int iWidth = Convert.ToInt32(dWidth);
			sWidth = iWidth.ToString( ) + "px";
         if( ButtonType == NavigatorButtonType.ButtonIcons )
         {
         	ImageButton ib = null;
				for( int i = 0; i < IconNavButtons.Count; i++ )
				{
					ib = (IconNavButtons[i] as ImageButton);
					ib.Width = Unit.Parse(sWidth);
				}
         }
         else
         {
         	Button b = null;
				for( int i = 0; i < NavButtons.Count; i++ )
				{
					b = (NavButtons[i] as Button);
					b.Width = Unit.Parse(sWidth);
				}
         }
         double iButtonsWidth = iWidth * NavButtons.Count;
         double iExtraPanelPixels = (FPanel.Width.Value - (FPanel.BorderWidth.Value * 2 )) - (2 + iButtonsWidth);
      }
      #endregion

		public override void DataBind()
      {
      	try
         {
	         base.DataBind();
   	      if( !ClassUtils.IsDesignTime(Page) )
      	   {
	      	   if( Click != null )
   	      	{
            		object buttonObj = Page.Session[IDataLink.TableName + DBWebConst.sLastButtonSelected];
	               if( buttonObj != null )
   	            {
   		        		string sButton = buttonObj.ToString();
	      	         Object o = null;
      	   	      if( FDataLink.IsDataBound )
            		      o = IDataLink.DBDataSource.GetTableOrView(Page, IDataLink.TableName);
	            		DBWebButtonClickArgs e = new DBWebButtonClickArgs(sButton, o);
	   	      	   Click(this as object, e);
   	            }
			      }
         	}
	         ClassUtils.SetOuterAppearanceProperties( FPanel, this );
   	      if( this.Width.Value > MinWidth )
      	   	ClassUtils.SetSizeProperties( FPanel, this );
	      }
         catch(Exception ex)
         {
         	if( !ClassUtils.IsDesignTime(Page) )
            {
	            Page.Response.Write(ClassUtils.GetInternalError(Page, IDataLink, ex, this.ID));
            }
            else
            	throw new Exception(ex.Message);
         }
      }


		protected string Text
		{
			get
			{
            if( !ClassUtils.IsDesignTime(Page) )
            {
					string s = Page.Request.QueryString[DBWebConst.sBorlandImageID];
   	      	if( s != null )
      	   		return "";
            }
         	StringWriter sw = new StringWriter();
				HtmlTextWriter tw = new HtmlTextWriter(sw);
            DataBind();
            AddButtons();
            SetButtonsWidth();
            ClassUtils.AddStyleToPanel(FPanel, this.Style);
            FPanel.RenderBeginTag(tw);
            tw.Write("<table><tr>");
            if( ButtonType == NavigatorButtonType.ButtonIcons )
            {
					for( int i = 0; i < IconNavButtons.Count; i++ )
					{
               	tw.Write("<td>");
						ImageButton b = (IconNavButtons[i] as ImageButton);
						b.RenderControl(tw);
               	tw.Write("</td>");
					}
            }
            else
            {
					for( int i = 0; i < NavButtons.Count; i++ )
					{
               	tw.Write("<td>");
						Button b = (NavButtons[i] as Button);
						b.RenderControl(tw);
               	tw.Write("</td>");
					}
            }
            tw.Write("</tr></table>");
            FPanel.RenderEndTag(tw);
            return sw.ToString();
			}
		}
   }
   #endregion

}
