{***************************************************************************}
{ TMS IntraWeb Component Pack Pro                                           }
{ for Delphi & C++Builder                                                   }
{                                                                           }
{ written by TMS Software                                                   }
{            copyright © 2002 - 2009                                        }
{            Email : info@tmssoftware.com                                   }
{            Web : http://www.tmssoftware.com                               }
{                                                                           }
{ The source code is given as is. The author is not responsible             }
{ for any possible damage done due to the use of this code.                 }
{ The component can be freely used in any application. The complete         }
{ source code remains property of the author and may not be distributed,    }
{ published, given or sold in any form as such. No parts of the source      }
{ code can be included in any other component or application without        }
{ written authorization of the author.                                      }
{***************************************************************************}

unit IWSideNavBar;
                             
interface
                                                                         
{$R TMSIWSIDENAVBAR.RES}                                
                                                      
{$I TMSDEFS.INC}

uses
  Classes, SysUtils,  ExtCtrls, Windows, Math, Graphics, Controls,
  IWTMSImg, IWControl, IWExtCtrls, IWTypes, IWHTMLTag, IWTMSBase, IWImageList
  {$IFDEF TMSIW6}
  , IWRenderContext
  {$ENDIF}
  , IWColor, IWFont
  {$IFDEF TMSIW9}
  , IWXMLTag
  {$ENDIF}
  ;

type
  TIWGradientDirection = (gdHorizontal, gdVertical);                         

  TTIWSideNavBar = class;
  TSideNavBarPanel = class;
  TSideNavBarPanels = class;
  TSideNavBarItem = class;
  TSideNavBarItems = class;

  TTIWPicture = class(TPersistent)
  private
    FFileName: string;
    FImageIndex: integer;
  public
    constructor Create;
    procedure Assign(Source: TPersistent); override;
    function ImageRef(Control: TIWControl; Images: TIWImageList): string;
  published
     property FileName: string read FFileName write FFileName;
     property ImageIndex: integer read FImageIndex write FImageIndex default -1;
  end;

  TSideNavBarButton = class(TPersistent)
  private
    FActiveColor: TIWColor;
    FActiveColorTo: TIWColor;
    FActiveForeColor: TIWColor;
    FActiveHoverColor: TIWColor;
    FActiveHoverColorTo: TIWColor;
    FBackColor: TIWColor;
    FBackColorTo: TIWColor;
    FCollapsedImage: TTIWPicture;
    FExpandedImage: TTIWPicture;
    FFont: TIWFont;
    FForeColor: TIWColor;
    FGradientDirection: TIWGradientDirection;
    FHeight: integer;
    FHoverColor: TIWColor;
    FHoverColorTo: TIWColor;
    FHoverForeColor: TIWColor;
    FTextAlign: TAlignment;
    procedure SetFont(const Value: TIWFont);
  public
    constructor Create;
    destructor Destroy; override;
  published
    property ActiveColor: TIWColor read FActiveColor write FActiveColor default $C7581E;
    property ActiveColorTo: TIWColor read FActiveColorTo write FActiveColorTo default $C7581E;
    property ActiveForeColor: TIWColor read FActiveForeColor write FActiveForeColor default $FFFFFF;
    property ActiveHoverColor: TIWColor read FActiveHoverColor write FActiveHoverColor default $C7581E;
    property ActiveHoverColorTo: TIWColor read FActiveHoverColorTo write FActiveHoverColorTo default $C7581E;
    property BackColor: TIWColor read FBackColor write FBackColor default $FFFFFF;
    property BackColorTo: TIWColor read FBackColorTo write FBackColorTo default $F7DFD6;
    property CollapsedImage: TTIWPicture read FCollapsedImage write FCollapsedImage;
    property ExpandedImage: TTIWPicture read FExpandedImage write FCollapsedImage;
    property Font: TIWFont read FFont write SetFont;
    property ForeColor: TIWColor read FForeColor write FForeColor default $C7581E;
    property GradientDirection: TIWGradientDirection read FGradientDirection write FGradientDirection default gdHorizontal;
    property Height: integer read FHeight write FHeight default 30;
    property HoverColor: TIWColor read FHoverColor write FHoverColor default clNone;
    property HoverColorTo: TIWColor read FHoverColorTo write FHoverColorTo default clNone;
    property HoverForeColor: TIWColor read FHoverForeColor write FHoverForeColor default $FF8E42;
    property TextAlign: TAlignment read FTextAlign write FTextAlign default taLeftJustify;
  end;

  TSideNavBarClientEvents = class(TPersistent)
  private
    FItemClick: TStringList;
    FItemCollapse: TStringList;
    FItemExpand: TStringList;
    FPanelChange: TStringList;
    FPanelClose: TStringList;
    FPanelMove: TStringList;
    FPanelOpen: TStringList;
    FPanelUpdate: TStringList;

    procedure SetItemClick(const Value: TStringList);
    procedure SetItemCollapse(const Value: TStringList);
    procedure SetItemExpand(const Value: TStringList);
    procedure SetPanelChange(const Value: TStringList);
    procedure SetPanelClose(const Value: TStringList);
    procedure SetPanelMove(const Value: TStringList);
    procedure SetPanelOpen(const Value: TStringList);
    procedure SetPanelUpdate(const Value: TStringList);
  protected
  public
    constructor Create;
    destructor Destroy; override;
    function GetJSFunction(PropName: string): string;
  published
    property ItemClick: TStringList read FItemClick write SetItemClick;
    property ItemCollapse: TStringList read FItemCollapse write SetItemCollapse;
    property ItemExpand: TStringList read FItemExpand write SetItemExpand;
    property PanelChange: TStringList read FPanelChange write SetPanelChange;
    property PanelClose: TStringList read FPanelClose write SetPanelClose;
    property PanelMove: TStringList read FPanelMove write SetPanelMove;
    property PanelOpen: TStringList read FPanelOpen write SetPanelOpen;
    property PanelUpdate: TStringList read FPanelUpdate write SetPanelUpdate;
  end;

  TSideNavBarDivider = class(TPersistent)
  private
    FBackColor: TIWColor;
    FBackColorTo: TIWColor;
    FForeColor: TIWColor;    
    FGradientDirection: TIWGradientDirection;
  public
    constructor Create;
  published
    property BackColor: TIWColor read FBackColor write FBackColor default clWebWHITESMOKE;
    property BackColorTo: TIWColor read FBackColorTo write FBackColorTo default clSilver;
    property ForeColor: TIWColor read FForeColor write FForeColor default $00C7581E;
    property GradientDirection: TIWGradientDirection read FGradientDirection write FGradientDirection default gdVertical;
  end;

  TSideNavBarItemImageMargin = class(TPersistent)
  private
    Ftop: integer;
    FRight: integer;
    FBottom: integer;
    FLeft: integer;
  public
    constructor Create;
  published
    property Top: integer read FTop write FTop default 2;
    property Right: integer read FRight write FRight default 2;
    property Bottom: integer read FBottom write FBottom default 2;
    property Left: integer read FLeft write FLeft default 2;
  end;

  TSideNavBarItemImageSize = class(TPersistent)
  private
    FHeight: integer;
    FWidth: integer;
  public
    constructor Create;
  published
    property Height: integer read FHeight write FHeight default 16;
    property Width: integer read FWidth write FWidth default 16;
  end;


  TSideNavBarItemDisplay = class(TPersistent)
  private
    FAlign: TAlignment;
    FCollapsedImage: TTIWPicture;
    FExpandedImage: TTIWPicture;
    FHoverBackColor: TIWColor;
    FHoverForeColor: TIWColor;
    FImageMargin: TSideNavBarItemImageMargin;
    FImageSize: TSideNavBarItemImageSize;
    FSelectBackColor: TIWColor;
    FSelectForeColor: TIWColor;
    FSpacing: integer;
  public
    constructor Create;
    destructor Destroy; override;
  published
    property Align: TAlignment read FAlign write FAlign default taLeftJustify;
    property CollapsedImage: TTIWPicture read FCollapsedImage write FCollapsedImage;
    property ExpandedImage: TTIWPicture read FExpandedImage write FExpandedImage;
    property HoverBackColor: TIWColor read FHoverBackColor write FHoverBackColor default clNone;
    property HoverForeColor: TIWColor read FHoverForeColor write FHoverForeColor default $FF8E42;
    property ImageMargin: TSideNavBarItemImageMargin read FImageMargin write FImageMargin;
    property ImageSize: TSideNavBarItemImageSize read FImageSize write FImageSize;
    property SelectBackColor: TIWColor read FSelectBackColor write FSelectBackColor default clNone;
    property SelectForeColor: TIWColor read FSelectForeColor write FSelectForeColor default $FF8E42;
    property Spacing: integer read FSpacing write FSpacing default 0;
  end;

  TSideNavBarItem = class(TCollectionItem)
  private
    FOwner: TSideNavBarItems;
    FCaption: string;
    FGlyph: TTIWPicture;
    FHint: string;
    FIsDivider: boolean;
    FIsExpanded: boolean;
    FLevel: integer;
    FName: string;
    FLink: string;
    FScript: string;
    FTag: integer;
    FTarget: string;
  public
    constructor Create(Collection: TCollection);  override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function GetOwner: TPersistent; override;    
  protected
    function GetDisplayName: string; override;
  published
    property Caption: string read FCaption write FCaption;
    property Glyph: TTIWPicture read FGlyph write FGlyph;
    property Hint: string read FHint write FHint;
    property IsDivider: boolean read FIsDivider write FIsDivider default false;
    property IsExpanded: boolean read FIsExpanded write FIsExpanded default true;
    property Level: integer read FLevel write FLevel default 0;
    property Name: string read FName write FName;
    property Link: string read FLink write FLink;
    property Script: string read FScript write FScript;
    property Tag: integer read FTag write FTag default 0;
    property Target: string read FTarget write FTarget;
  end;

  TSideNavBarItems = class(TCollection)
  private
    FOwner: TSideNavBarPanel;
    function GetItems(Index: Integer): TSideNavBarItem;
    procedure SetItems(Index: Integer; const Value: TSideNavBarItem);
  protected
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(AOwner: TSideNavBarPanel);
    function GetOwner: TPersistent; override;
    function Add: TSideNavBarItem;
    function Insert(Index: Integer):TSideNavBarItem;
    property Items[Index: Integer]: TSideNavBarItem read GetItems write SetItems; default;
  end;

  TSideNavBarPanel = class(TCollectionItem)
  private
    FOwner: TSideNavBarPanels;
    FBackColor: TIWColor;
    FBackColorTo: TIWColor;
    FBackColorGradientDirection: TIWGradientDirection;
    FBackgroundImage: TTIWPicture;
    FBorderColor: TIWColor;
    FCaption: string;
    {$IFDEF TMSIW7}
    FControl: TIWCustomControl;
    {$ELSE}
    FControl: TIWControl;    
    {$ENDIF}
    FGlyph: TTIWPicture;
    FHeight: integer;
    FIsExpanded: boolean;
    FItems: TSideNavBarItems;
    FName: string;
    FPosition: integer;
    FScript: string;
    FTag: integer;
  protected
    function GetDisplayName: String; override;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function GetOwner: TPersistent; override;
  published
    property BackColor: TIWColor read FBackColor write FBackColor default $F7DFD6;
    property BackColorTo: TIWColor read FBackColorTo write FBackColorTo default $F7DFD6;
    property BackColorGradientDirection: TIWGradientDirection read FBackColorGradientDirection write FBackColorGradientDirection default gdHorizontal;
    property BackgroundImage: TTIWPicture read FBackgroundImage write FBackgroundImage;
    property BorderColor: TIWColor read FBorderColor write FBorderColor default $FFFFFF;
    property Caption: string read FCaption write FCaption;
    {$IFDEF TMSIW7}
    property Control: TIWCustomControl read FControl write FControl;
    {$ELSE}
    property Control: TIWControl read FControl write FControl;    
    {$ENDIF}
    property Glyph: TTIWPicture read FGlyph write FGlyph;
    property Height: integer read FHeight write FHeight default 120;
    property IsExpanded: boolean read FIsExpanded write FIsExpanded default true;
    property Items: TSideNavBarItems read FItems write FItems;
    property Name: string read FName write FName;
    property Script: string read FScript write FScript;
    property Tag: integer read FTag write FTag default 0;
  end;

  TSideNavBarPanels = class(TCollection)
  private
    FOwner: TTIWSideNavBar;
    function GetItem(Index: Integer): TSideNavBarPanel;
    procedure SetItem(Index: Integer; const Value: TSideNavBarPanel);
  protected
    procedure Update(Item: TCollectionItem); override;  
  public
    destructor Destroy; override;
    //procedure Assign(Source: TPersistent); override;
    constructor Create(AOwner: TTIWSideNavBar);
    function Add: TSideNavBarPanel;
    function GetOwner: TPersistent; override;
    property Items[Index: Integer]: TSideNavBarPanel read GetItem write SetItem; default;
  end;

  TItemEvent = procedure(Sender: TComponent; PanelIndex, ItemIndex: Integer) of object;
  TPanelEvent = procedure(Sender: TComponent; FromPosition, ToPosition: Integer) of object;

  {$IFDEF TMSIW9}
  TIWAsyncItemEvent = procedure (Sender: TObject; EventParams: TStringList; PanelIndex, ItemIndex: Integer) of object;
  TIWAsyncPanelEvent = procedure (Sender: TObject; EventParams: TStringList; FromPosition, ToPosition: Integer) of object;
  {$ENDIF}

  TTIWSideNavBar = class(TIWControl)
  private
    FActivePanel: integer;
    FPanelClicked: integer;
    FPrevPanelClicked: integer;
    FAllowMove: bool;
    FBackColor: TIWColor;
    FBackColorTo: TIWColor;
    FBackColorGradientDirection: TIWGradientDirection;
    FBackgroundImage: TTIWPicture;
    FBorderColor: TIWColor;
    FBorderWidth: integer;
    FForeColor: TIWColor;
    FMarginVertical: integer;
    FMarginHorizontal: integer;
    FSelectedItem: integer;
    FButton: TSideNavBarButton;
    FItem: TSideNavBarItemDisplay;
    FPanels: TSideNavBarPanels;
    FClientEvents: TSideNavBarClientEvents;
    FDivider: TSideNavBarDivider;
    FImages: TIWImageList;
    FOnItemClick: TItemEvent;
    FOnPanelChange: TPanelEvent;
//    FSinglePanelOpen: bool;

    {$IFDEF TMSIW9}
    FOnAsyncItemClick: TIWAsyncItemEvent;
    FOnAsyncPanelChange: TIWAsyncPanelEvent;
    procedure DoAsyncPanelChange(AParams: TStringList);
    procedure DoAsyncItemClick(AParams: TStringList);
    {$ENDIF}

    procedure SetActivePanel(const Value: integer);
    procedure SetSelectedItem(const Value: integer);
  protected
    procedure SetValue(const AValue: string); override;
    procedure Submit(const AValue: string); override;
    {$IFDEF TMSIW6}
    function ImageHTML(const ASrc,BSrc,IMap: string; AContext: TIWBaseComponentContext): string;
    {$ELSE}
    function ImageHTML(const ASrc,BSrc,IMap: string): string;
    {$ENDIF}
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure DrawGradient(Canvas: TCanvas; FromColor, ToColor: TIWColor; Steps: Integer; r:TRect; Direction: Boolean);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    {$IFDEF TMSIW6}
    procedure IWPaint; override;
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    procedure Invalidate; override;
    {$ELSE}
    procedure Paint; override;
    function RenderHTML: TIWHTMLTag; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    {$ENDIF}
  published
    property ActivePanel: integer read FActivePanel write SetActivePanel default 0;
    property AllowMove: bool read FAllowMove write FAllowMove default true;
    property BackColor: TIWColor read FBackColor write FBackColor default $E7A27B;
    property BackColorTo: TIWColor read FBackColorTo write FBackColorTo default $C88C69;
    property BackColorGradientDirection: TIWGradientDirection read FBackColorGradientDirection write FBackColorGradientDirection default gdVertical;
    property BackgroundImage: TTIWPicture read FBackgroundImage write FBackgroundImage;
    property BorderColor: TIWColor read FBorderColor write FBorderColor default clNone;
    property BorderWidth: integer read FBorderWidth write FBorderWidth default 0;
    property ForeColor: TIWColor read FForeColor write FForeColor default $C7581E;
    property Images: TIWImageList read FImages write FImages;
    property MarginVertical: integer read FMarginVertical write FMarginVertical default 14;
    property MarginHorizontal: integer read FMarginHorizontal write FMarginHorizontal default 14;
    property SelectedItem: integer read FSelectedItem write SetSelectedItem default -1;
//    property SinglePanelOpen: bool read FSinglePanelOpen write FSinglePanelOpen default false;

    property OnItemClick: TItemEvent read FOnItemClick write FOnItemClick;
    property OnPanelChange: TPanelEvent read FOnPanelChange write FOnPanelChange;

    {$IFDEF TMSIW9}
    property OnAsyncPanelChange: TIWAsyncPanelEvent read FOnAsyncPanelChange write FOnAsyncPanelChange;
    property OnAsyncItemClick: TIWAsyncItemEvent read FOnAsyncItemClick write FOnAsyncItemClick;
    {$ENDIF}

    property Button: TSideNavBarButton read FButton write FButton;
    property Font;
    property Item: TSideNavBarItemDisplay read FItem write FItem;
    property Panels: TSideNavBarPanels read FPanels write FPanels;
    property ClientEvents: TSideNavBarClientEvents read FClientEvents write FClientEvents;
    property Divider: TSideNavBarDivider read FDivider write FDivider;
  end;


//============================================================ IMPLEMENTATION ==
implementation

uses
  IWLineLibrary, IWAppForm, IWForm, IWServerControllerBase, SWSystem, SWStrings, IWServer
  {$IFDEF TMSIW7}
  , IWBaseHTMLControl
  , IWVCLBaseControl, IWGlobal
  {$ENDIF}
  ;


{ TSideNavBarPanels }

//------------------------------------------------------------------------------
function TSideNavBarPanels.Add: TSideNavBarPanel;
begin
  Result := TSideNavBarPanel(inherited Add);
end;

//------------------------------------------------------------------------------
{
procedure TSideNavBarPanels.Assign(Source: TPersistent);
var
  i: Integer;
  S: TSideNavBarPanels;
begin
  inherited;
  S := TSideNavBarPanels(Source);
  Clear;
  for i := 0 to S.Count-1 do
    Add.Assign(S[i]);
end;
}

//------------------------------------------------------------------------------
constructor TSideNavBarPanels.Create(AOwner: TTIWSideNavBar);
begin
  inherited Create(TSideNavBarPanel);
  FOwner := AOwner;
end;

//------------------------------------------------------------------------------
destructor TSideNavBarPanels.Destroy;
begin
  inherited;
end;

//------------------------------------------------------------------------------
procedure TSideNavBarPanels.Update(Item: TCollectionItem);
begin
  inherited;
  FOwner.Invalidate;
end;

//------------------------------------------------------------------------------
function TSideNavBarPanels.GetItem(Index: Integer): TSideNavBarPanel;
begin
  Result := TSideNavBarPanel(inherited GetItem(Index));
end;

//------------------------------------------------------------------------------
function TSideNavBarPanels.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

//------------------------------------------------------------------------------
procedure TSideNavBarPanels.SetItem(Index: Integer; const Value: TSideNavBarPanel);
begin
  inherited SetItem(Index, Value);
end;

{ TSideNavBarPanel }

//------------------------------------------------------------------------------
function TSideNavBarPanel.GetDisplayName: String;
begin
  if Caption <> '' then
    Result := Caption
  else
    Result := 'Panel' + IntToStr(Index);
end;

//------------------------------------------------------------------------------
procedure TSideNavBarPanel.Assign(Source: TPersistent);
begin
  if Source is TSideNavBarPanel then
  begin
    FBackColor := (Source as TSideNavBarPanel).BackColor;
    FBackgroundImage.Assign((Source as TSideNavBarPanel).BackgroundImage);
    FBorderColor := (Source as TSideNavBarPanel).BorderColor;
    FCaption := (Source as TSideNavBarPanel).Caption;
    FControl := (Source as TSideNavBarPanel).Control;
    FGlyph.Assign((Source as TSideNavBarPanel).Glyph);
    FHeight := (Source as TSideNavBarPanel).Height;
    FIsExpanded := (Source as TSideNavBarPanel).IsExpanded;
    FItems.Assign((Source as TSideNavBarPanel).Items);
    FName := (Source as TSideNavBarPanel).Name;
    FScript := (Source as TSideNavBarPanel).Script;
    FTag := (Source as TSideNavBarPanel).Tag;
  end;
end;

//------------------------------------------------------------------------------
constructor TSideNavBarPanel.Create(Collection: TCollection);
begin
  inherited;

  if Collection is TSideNavBarPanels then
  begin
    FOwner := Collection as TSideNavBarPanels;
  end;

  FItems := TSideNavBarItems.Create(self);
  FBackgroundImage := TTIWPicture.Create;
  FCaption := 'Panel ' + IntToStr(Collection.Count - 1);
  FGlyph := TTIWPicture.Create;
  FHeight := 120;

  FBackColor := $F7DFD6;
  FBackColorTo := $F7DFD6;
  FBackColorGradientDirection := gdHorizontal;
  FBorderColor := $FFFFFF;
  FControl := nil;
  FIsExpanded := true;
  FName := EmptyStr;
  FScript := EmptyStr;
  FTag := 0;

end;

//------------------------------------------------------------------------------
destructor TSideNavBarPanel.Destroy;
begin
  FItems.Free;
  FBackgroundImage.Free;
  FGlyph.Free;
  inherited;
end;


function TSideNavBarPanel.GetOwner: TPersistent;
begin
  Result := FOwner;
end;


{ TTIWSideNavBar }
{$IFDEF TMSIW9}
procedure TTIWSideNavBar.DoAsyncPanelChange(AParams: TStringList);
begin
  if Assigned(OnAsyncPanelChange) then
    OnAsyncPanelChange(Self, AParams, FPrevPanelClicked, FPanelClicked);
end;

procedure TTIWSideNavBar.DoAsyncItemClick(AParams: TStringList);
begin
  if Assigned(OnAsyncItemClick) then
    OnAsyncItemClick(Self, AParams, ActivePanel, SelectedItem);
end;

function TTIWSideNavBar.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
begin
  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWSIDENAVBAR');
    RenderAsyncCommonProperties( AContext, Result );
  except
    FreeAndNil(Result);
  end;
end;
{$ENDIF}

constructor TTIWSideNavBar.Create(AOwner: TComponent);
var
  p,i: integer;
begin
  inherited;
  {$IFDEF TMSIW6}
  {TODO}
  {$ELSE}
  FSupportsSubmit := True;
  FSupportedScriptEvents := 'OnAbort,OnError,OnKeyDown,OnKeyPress,OnKeyUp,OnLoad';
  {$ENDIF}
  FPanels := TSideNavBarPanels.Create(Self);
  FButton := TSideNavBarButton.Create;
  FItem := TSideNavBarItemDisplay.Create;
  FClientEvents := TSideNavBarClientEvents.Create;
  FDivider := TSideNavBarDivider.Create;
  FBackgroundImage := TTIWPicture.Create;

  FActivePanel := 0;
  FAllowMove := true;
  FBackColor := $E7A27B;
  FBackColorTo := $C88C69;
  FBackColorGradientDirection := gdVertical;
  FBorderColor := clNone;
  FBorderWidth := 0;
  FForeColor := $C7581E;
  FMarginVertical := 14;
  FMarginHorizontal := 14;
  FSelectedItem := -1;
//  FSinglePanelOpen := false;

  Width := 220;
  Height := 360;

   if not (csDesigning in Componentstate) then
  begin
    {$IFDEF TMSIW51}
    TIWServer.AddInternalFile('IW_JS_TMSIWSIDENAVBAR','/js/TMSIWSIDENAVBAR.js');
    {$ELSE}
    GIWServer.AddInternalFile('IW_JS_TMSIWSIDENAVBAR');
    {$ENDIF}
  end;

  if (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  begin
    for p:=0 to 2 do
    begin
      with Panels.Add do
      begin
        Caption := 'Panel ' + IntToStr(p);
        Height := 0;
        for i:=0 to 2 do
        begin
          with Items.Add do
          begin
            Caption := 'item ' + IntToStr(i);
          end;
        end;
      end;
    end;
  end;

  {$IFDEF TMSIW7}
  SupportsPartial := true;
  {$ENDIF}

end;

destructor TTIWSideNavBar.Destroy;
begin
  FPanels.Free;
  FButton.Free;
  FItem.Free;
  FClientEvents.Free;
  FDivider.Free;
  FBackgroundImage.Free;
  inherited;
//  MessageBox(0, 'sidenavbar destroy', 'snb destroy', 0);  
end;

{$IFDEF TMSIW6}
procedure TTIWSideNavBar.Invalidate;
begin
  inherited;
end;
{$ENDIF}

procedure TTIWSideNavBar.DrawGradient(Canvas: TCanvas; FromColor, ToColor: TIWColor; Steps: Integer; r:TRect; Direction: Boolean);
var
  diffr,startr,endr: Integer;
  diffg,startg,endg: Integer;
  diffb,startb,endb: Integer;
  iend: Integer;
  rstepr,rstepg,rstepb,rstepw: Real;
  i,stepw: Word;

begin
  if Steps = 0 then
    Steps := 1;

  FromColor := ColorToRGB(FromColor);
  ToColor := ColorToRGB(ToColor);

  startr := (FromColor and $0000FF);
  startg := (FromColor and $00FF00) shr 8;
  startb := (FromColor and $FF0000) shr 16;
  endr := (ToColor and $0000FF);
  endg := (ToColor and $00FF00) shr 8;
  endb := (ToColor and $FF0000) shr 16;

  diffr := endr - startr;
  diffg := endg - startg;
  diffb := endb - startb;

  rstepr := diffr / steps;
  rstepg := diffg / steps;
  rstepb := diffb / steps;

  if Direction then
    rstepw := (R.Right - R.Left) / Steps
  else
    rstepw := (R.Bottom - R.Top) / Steps;

  with Canvas do
  begin
    for i := 0 to Steps - 1 do
    begin
      endr := startr + Round(rstepr*i);
      endg := startg + Round(rstepg*i);
      endb := startb + Round(rstepb*i);
      stepw := Round(i*rstepw);
      Pen.Color := endr + (endg shl 8) + (endb shl 16);
      Brush.Color := Pen.Color;
      if Direction then
      begin
        iend := R.Left + stepw + Trunc(rstepw) + 1;
        if iend > R.Right then
          iend := R.Right;
        Rectangle(R.Left + stepw,R.Top,iend,R.Bottom)
      end
      else
      begin
        iend := R.Top + stepw + Trunc(rstepw)+1;
        if iend > r.Bottom then
          iend := r.Bottom;
        Rectangle(R.Left, R.Top+stepw,R.Right,iend);
      end;
    end;
  end;
end;


{$IFDEF TMSIW6}
procedure TTIWSideNavBar.IWPaint;
{$ELSE}
procedure TTIWSideNavBar.Paint;
{$ENDIF}
var
  offsy, p: integer;
  
  function DrawPanel(y: Integer; i: integer): integer;
  var
    th, j: integer;
    r: TRect;
  begin
    th := Canvas.TextHeight('gh') + 4;
    if Panels[i].Height > 0 then
      Result := Panels[i].Height
    else
      Result := Panels[i].Items.Count * th;

    Result := Result + th;

    r := ClientRect;
    InflateRect(r,-MarginHorizontal, -MarginVertical);
    r.Top := y;
    r.Bottom := y + th;
    DrawGradient(Canvas,Button.BackColor, Button.BackColorTo, 64, R, Button.GradientDirection <> gdVertical);

    r.Top := y + th;
    r.Bottom := y + Result;

    DrawGradient(Canvas,Panels[i].BackColor, Panels[i].BackColorTo, 64, R, Button.GradientDirection <> gdVertical);

    Canvas.Brush.Style := bsClear;
    Canvas.TextOut(r.Left + 4, y, Panels[i].Caption);

    for j := 1 to Panels[i].Items.Count do
      Canvas.TextOut(r.Left + 4, y + th * j, Panels[i].Items[j - 1].Caption);
  end;

begin
  DrawGradient(Canvas, BackColor, BackColorTo, 64, ClientRect, BackColorGradientDirection <> gdVertical);

  offsy := MarginVertical;
  for p := 1 to Panels.Count do
  begin
    offsy := offsy + DrawPanel(offsy, p - 1);
    offsy := offsy + MarginVertical;
  end;
end;

procedure TTIWSideNavBar.Notification(AComponent: TComponent; Operation: TOperation);
var
  i: integer;
begin
  if (csDestroying in ComponentState) then
    Exit;
    
  if (Operation = opRemove) then
  begin
    for i := 1 to Panels.Count do
    begin
      if Panels[i - 1].Control = AComponent then
        Panels[i - 1].Control := nil;
    end;

    if AComponent = FImages then
      FImages := nil;
  end;
end;

{$IFDEF TMSIW6}
function TTIWSideNavBar.ImageHTML(const ASrc,BSrc,IMap: string; AContext: TIWBaseComponentContext): string;
{$ELSE}
function TTIWSideNavBar.ImageHTML(const ASrc,BSrc,IMap: string): string;
{$ENDIF}
begin
end;

{$IFDEF TMSIW6}
function TTIWSideNavBar.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
{$ELSE}
function TTIWSideNavBar.RenderHTML: TIWHTMLTag;
{$ENDIF}
var
  htmlres, s, shadowdiv, GradDir, PSVal, PPVal, PanelImage, ListImage, img, pBC, isAP: string;
  itemIm, RenderImgTag, isExp, isDiv,  setNode, nodeClosed, initcontrols: string;
  i,j,p,k,n,h,w,bw,HeightTable,pos,nextLevel: integer;
  setpos, found: boolean;
  op: TSideNavBarPanel;
  isPartial, found0: boolean;
  ajaxcall, submitclick: string;
begin

  {$IFDEF TMSIW6}
  with AContext.PageContext as TIWPageContext40 do
    isPartial := WebApplication.IsPartialUpdate;
  {$ELSE}

  {$ENDIF}

  {$IFDEF TMSIW7}
  if not isPartial then
    TIWComponent40Context(AContext).AddScriptFile('/js/TMSIWSIDENAVBAR.js');
  {$ELSE}
  isPartial := false;  
  {$ENDIF}  

  h := Height + 1;
  //w := Width;
  HeightTable := h - (Panels.Count * 30);

  setpos := true;
  found0 := false;
  for i := 1 to Panels.Count do
  begin
    if not (Panels[i - 1].FPosition = 0) then
      setpos := false
    else
    begin
      if found0 then
        Panels[i - 1].FPosition := i - 1
      else
        found0 := true;
    end;
  end;

  p := 0;
  if (setpos) then
  begin
    for i := 1 to Panels.Count do
    begin
      Panels[i - 1].FPosition := p;
      p := p + 1;
    end
  end;

  //javascript object
  htmlres := htmlres + #13'<script>'#13;
  htmlres := htmlres
  + 'function '+HTMLName+'Obj(){'#13
  + 'this.ActivePanel = '+IntToStr(ActivePanel)+';'#13
  + 'this.AllowMove = '+IIF(AllowMove,'true','false')+';'#13
  + 'this.ActiveItem = '+IntToStr(SelectedItem)+';'#13
  + 'this.ActiveFontColor = "'+HTMLColor(Button.Font.Color)+'";'#13
  + 'this.BorderColor = "'+ColorToRGBString(BorderColor)+'";'#13
  + 'this.BorderSize = '+IntToStr(BorderWidth)+';'#13
  + 'this.ButtonCollapsedImage = "'+ Button.CollapsedImage.ImageRef(Self, Images)+'";'#13
  + 'this.ButtonExpandedImage = "'+ Button.ExpandedImage.ImageRef(Self, Images)+'";'#13
  + 'this.ButtonHeight = '+IntToStr(Button.Height)+';'#13
  + 'this.ColorSel = "'+ColorToRGBString(Item.SelectForeColor)+'";'#13
  + 'this.ColorOver = "'+ColorToRGBString(Item.HoverForeColor)+'";'#13
  + 'this.itemSpacing = '+IntToStr(Item.Spacing)+';'#13
  + 'this.limWidth = 1;'#13
  + 'this.limbrWidth = 1;'#13
  + 'this.PanelCount = '+IntToStr(Panels.Count)+';'#13
  + 'this.SplitterHeight = '+IntToStr(MarginVertical)+';'#13
  + 'this.SplitterWidth = '+IntToStr(MarginHorizontal)+';'#13
  + 'this.Height = '+IntToStr(Height)+';'#13
  + 'this.Width = '+IntToStr(Width)+';'#13
  + 'this.UniqueID = "'+HTMLName+'";'#13
  + 'this.toWrite = "";'#13
  + ' this.Generator = "DELPHI";'#13
  + ' this.HeightContent = ' + IntToStr(HeightTable)+';'#13
  + ' this.ItemCollapsedImage = "'+ Item.CollapsedImage.ImageRef(Self, Images)+'";'#13
  + ' this.ItemExpandedImage = "'+ Item.ExpandedImage.ImageRef(Self, Images)+'";'#13
  + ' this.LabelCSSStyle = "";'#13
  + ' this.ItemPicHeight = '+ IntToStr(Item.ImageSize.Height) +';'#13
  + ' this.ItemPicWidth = '+ IntToStr(Item.ImageSize.Width) +';'#13
  + ' this.ItemPicMarginLeft = '+IntToStr(Item.ImageMargin.Left)+';'#13
  + ' this.ItemPicMarginRight = '+IntToStr(Item.ImageMargin.Right)+';'#13
  + ' this.ItemPicMarginTop = '+IntToStr(Item.ImageMargin.Top)+';'#13
  + ' this.ItemPicMarginBottom = '+IntToStr(Item.ImageMargin.Bottom)+';'#13
  + ' this.itemScrollSpeed = 4;'#13
  + ' this.mx = 0;'#13
  + ' this.my = 0;'#13
  + ' this.toty = 0;'#13
  + ' this.tabs = new Array();'#13
  + ' this.containers = new Array();'#13
  + ' this.position = new Array();'#13
  + ' this.tabscount = 0;'#13
  + ' this.isInScroll = 0;'#13
  + ' this.xPosition = 0;'#13
  + ' this.yPosition = 0;'#13
  + ' this.theBiggest = 0;'#13                             
  + ' this.functions = new Array();'#13
  + ' this.visibleHeight = 0;'#13
  + ' this.listHeight = 0;'#13
  + ' this.MenuCont = "";'#13
  + ' this.Left = 0;'#13
  + ' this.Top = 0;'#13
  + ' this.AbsLeft = 0;'#13
  + ' this.AbsTop = 0;'#13
  + ' this.client_order = "";'#13
  + ' this.hctrl = new Array();'#13
  + ' this.PanelHeight = "0";'#13
//  + ' this.singlepanelopen = '+IIF(SinglePanelOpen,'true','false')+';'#13

  //clientevents
  + HTMLName+'Obj.prototype.ItemClick = function(obj,pnlIndex,itmIndex) {'+ClientEvents.ItemClick.GetText+'}'#13
  + HTMLName+'Obj.prototype.NodeOpen = function (obj,pnlIndex,itmIndex) {'+ClientEvents.ItemCollapse.GetText+'}'#13
  + HTMLName+'Obj.prototype.NodeClose = function(obj,pnlIndex,itmIndex) {'+ClientEvents.ItemExpand.GetText+'}'#13
  + HTMLName+'Obj.prototype.PanelChange = function(obj,pnlFrom,pnlTo) {'+ClientEvents.PanelChange.GetText+'}'#13
  + HTMLName+'Obj.prototype.PanelMoved = function(obj,pnlIndex,posFrom,posTo) {'+ClientEvents.PanelMove.GetText+'}'#13

  + HTMLName+'Obj.prototype.InitControls = function() {'#13
  + HTMLName+'InitControls();'#13
  + ' }'#13

  + HTMLName+'Obj.prototype.PanelOpen = function(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex) {'#13
  + HTMLName+'PanelOpen(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex);'#13
  + ' }'#13

  + HTMLName+'Obj.prototype.PanelUpdate = function(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex,ctrlVisibility) {'#13
  + HTMLName+'PanelUpdate(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex,ctrlVisibility);'#13
  + ' }'#13

  + HTMLName+'Obj.prototype.ControlOpen = function(obj,pnlIndex) {'#13
  + '  switch(pnlIndex) {'#13;

  s := '';                                                               

  for i:=1 to Panels.Count do
  begin
    if Assigned(Panels[i - 1].Control) then
    begin
      s := s
      + '  case ' + IntToStr(Panels[i - 1].FPosition) + ' :'#13
      + '    sidenavbar_UnHide("' + Panels[i - 1].Control.HTMLName + '");'#13
      + '    break;'#13
    end
  end;

  s := s
  + '  default:'#13
  + '    break;'#13
  + '  }'#13
  + ' }'#13

  + HTMLName+'Obj.prototype.ControlClose = function(obj,pnlIndex) {'#13
  + '  switch(pnlIndex) {'#13;

  for i:=1 to Panels.Count do
  begin
    if Assigned(Panels[i - 1].Control) then
    begin
      s := s
      + '  case ' + IntToStr(Panels[i - 1].FPosition) + ' :'#13
      + '    sidenavbar_Hide("' + Panels[i - 1].Control.HTMLName + '",' + Panels[i - 1].FControl.HTMLName + 'IWCL);'#13
      + '    break;'#13
    end
  end;

  s := s
  + '  default:'#13                             
  + '    break;'#13
  + '  }'#13
  + ' }'#13

  + HTMLName+'Obj.prototype.PanelClose = function(obj,pnlIndex) {'#13
  + '  switch(pnlIndex) {'#13;

  for i:=1 to Panels.Count do
  begin
    if Assigned(Panels[i - 1].Control) then
    begin                                        
      s := s
      + '  case ' + IntToStr(Panels[i - 1].FPosition) + ' :'#13
      + '    sidenavbar_Hide("' + Panels[i - 1].Control.HTMLName + '",' + Panels[i - 1].FControl.HTMLName + 'IWCL);'#13
      + '    break;'#13
    end
  end;                                         

  s := s                                 
  + '  default:'#13
  + '    break;'#13
  + '  }'#13                                                  

  + ClientEvents.PanelClose.GetText + ' }'#13
  + '';

  if (Align = alRight) then
    s := s + 'this.Align = "right";'#13
  else if (Align = alLeft) then
    s := s + 'this.Align = "left";'#13
  else
    s := s + ' this.Align = "none";'#13;

  if (Button.TextAlign = taRightJustify) then
    s := s + 'this.CaptionAlign = "right";'#13
  else if (Button.TextAlign = taCenter) then
    s := s + 'this.CaptionAlign = "center";'#13
  else
    s := s + 'this.CaptionAlign = "left";'#13;

  if (Item.Align = taRightJustify) then
    s := s + 'this.ItemAlign = "right";'#13
  else if (Item.Align = taCenter) then
    s := s + 'this.ItemAlign = "center";'#13
  else
    s := s + 'this.ItemAlign = "left";'#13;


  //BackColor
  if (BackColor = clNone) then
    s := s + ' this.BackgroundColor = "' + ColorToRGBString(clWhite) + '";'#13
  else
    s := s + ' this.BackgroundColor = "' + ColorToRGBString(BackColor) + '";'#13;

  if (BackColor = clNone) then
    s := s + ' this.PanelColor = "background:' + ColorToRGBString(BackColor) + '";'#13
  else
  begin
    GradDir := '0';
    if (BackColorGradientDirection = gdHorizontal) then
      GradDir := '1';

    s := s + ' this.PanelColor = "background:'+ColorToRGBString(BackColor)+';filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(BackColor) + ',EndColorStr=' + ColorToRGBString(BackColorTo) + ')";'#13;
  end;

  if not (Item.SelectBackColor = clNone) then
    s := s + ' this.BackColorSel = "' + ColorToRGBString(Item.SelectBackColor) + '";'#13
  else
    s := s + ' this.BackColorSel = "";'#13;

  if not (Item.HoverBackColor = clNone) then
    s := s + ' this.BackColorOver = "' + ColorToRGBString(Item.HoverBackColor) + '";'#13
  else
    s := s + ' this.BackColorOver = "";'#13;

  if not (BackgroundImage.FileName = EmptyStr) then
    s := s + ' this.BackgroundImage = ";background-Image:url('+StringReplace(BackgroundImage.FileName,'\','/',[rfReplaceAll])+')";'#13
  else
    s := s + ' this.BackgroundImage = "";'#13;

  //Divider Color
  if (Divider.BackColorTo = clNone) and (Divider.BackColor <> clNone) then
  begin
      s := s + ' this.DividerColor = "background:'+ ColorToRGBString(Divider.BackColor) + ';';

      if (Divider.ForeColor <> clNone) then
        s := s + 'color:' + ColorToRGBString(Divider.ForeColor) + ';';

      s:= s + '";'#13
  end
  else if (Divider.BackColor <> clNone) then
  begin
    GradDir := '0';
    if (Divider.GradientDirection = gdHorizontal) then
      GradDir := '1';

    s := s + ' this.DividerColor = "background:'+ ColorToRGBString(Divider.BackColor)
    + ';filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr='
    + ColorToRGBString(Divider.BackColor) + ',EndColorStr=' + ColorToRGBString(Divider.BackColorTo) + ');';

    if (Divider.ForeColor <> clNone) then
      s := s + 'color:' + ColorToRGBString(Divider.ForeColor) + ';';

    s:= s + '";'#13
  end;

  //PanelButtonColors
  if (Button.BackColorTo = clNone) then
  begin
    s := s
      + ' this.ButtonColor = "background:'+ ColorToRGBString(Button.BackColor) + '";'#13;
    s := s
      + ' this.ButtonColor2 = "' + ColorToRGBString(Button.BackColor) + '";'#13;
    s := s
      + ' this.ButtonColorTo = "";'#13;
  end
  else
  begin
    GradDir := '0';
    if (Button.GradientDirection = gdHorizontal) then
      GradDir := '1';

    s := s
      + ' this.ButtonColor = "background:'+ ColorToRGBString(Button.BackColor) + ';filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.BackColor) + ',EndColorStr=' + ColorToRGBString(Button.BackColorTo) + ')";'#13;
    s := s
      + ' this.ButtonColor2 = "' + ColorToRGBString(Button.BackColor) + '";'#13;
    s := s
      + ' this.ButtonColorTo = "filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.BackColor) + ',EndColorStr=' + ColorToRGBString(Button.BackColorTo) + ')";'#13;
  end;

  if (Button.HoverColorTo = clNone) then
  begin
    s := s
      + ' this.ButtonHoverColor = "' + ColorToRGBString(Button.HoverColor) + '";'#13;
    s := s
      + ' this.ButtonHoverColorTo = "";'#13;
  end
  else
  begin
    GradDir := '0';
    if (Button.GradientDirection = gdHorizontal) then
      GradDir := '1';

    s := s
      + ' this.ButtonHoverColor = "' + ColorToRGBString(Button.HoverColor) + '";'#13;
    s := s
      + ' this.ButtonHoverColorTo = "progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.HoverColor) + ',EndColorStr=' + ColorToRGBString(Button.HoverColorTo) + ')";'#13;
  end;


  if (Button.HoverForeColor = clNone) then
    s := s + ' this.ButtonHoverForeColor = "";'#13
  else
    s := s
      + ' this.ButtonHoverForeColor = "' + ColorToRGBString(Button.HoverForeColor) + '";'#13;

  if (Button.ActiveColorTo = clNone) then
  begin
    s := s
      + ' this.ButtonActiveColor = "background:'+ ColorToRGBString(Button.ActiveColor) + '";'#13;
    s := s
      + ' this.ButtonActiveColor2 = "' + ColorToRGBString(Button.ActiveColor) + '";'#13;
    s := s
      + ' this.ButtonActiveColorTo = "";'#13;
  end
  else
  begin
    GradDir := '0';
    if (Button.GradientDirection = gdHorizontal) then
      GradDir := '1';

    s := s
      + ' this.ButtonActiveColor = "background:'+ ColorToRGBString(Button.ActiveColor) + ';filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.ActiveColor) + ',EndColorStr=' + ColorToRGBString(Button.ActiveColorTo) + ')";'#13;
    s := s
      + ' this.ButtonActiveColor2 = "' + ColorToRGBString(Button.ActiveColor) + '";'#13;
    s := s
      + ' this.ButtonActiveColorTo = "filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.ActiveColor) + ',EndColorStr=' + ColorToRGBString(Button.ActiveColorTo) + ')";'#13;
  end;

  if (Button.ActiveHoverColorTo = clNone) then
  begin
    s := s
      + ' this.ButtonActiveHoverColor = "background:'+ ColorToRGBString(Button.ActiveHoverColor) + '";'#13;
    s := s
      + ' this.ButtonActiveHoverColor2 = "' + ColorToRGBString(Button.ActiveHoverColor) + '";'#13;
    s := s
      + ' this.ButtonActiveHoverColorTo = "";'#13;
  end
  else
  begin
    GradDir := '0';                                          
    if (Button.GradientDirection = gdHorizontal) then
      GradDir := '1';
                                                           
    s := s
      + ' this.ButtonActiveHoverColor = "background:'+ ColorToRGBString(Button.ActiveHoverColor) + ';filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.ActiveHoverColor) + ',EndColorStr=' + ColorToRGBString(Button.ActiveHoverColorTo) + ')";'#13;
    s := s
      + ' this.ButtonActiveHoverColor2 = "' + ColorToRGBString(Button.ActiveHoverColor) + '";'#13;
    s := s
      + ' this.ButtonActiveHoverColorTo = "filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Button.ActiveHoverColor) + ',EndColorStr=' + ColorToRGBString(Button.ActiveHoverColorTo) + ')";'#13;
  end;                                       
                                                                
  //PanelButtonFontFamily

  if not (Button.Font.FontName = EmptyStr) then
    s := s  + ' this.ButtonFontFamily = "' + Button.Font.FontName + '";'#13
  else
    s := s  + ' this.ButtonFontFamily = "'+Font.FontName+'";'#13;

  if not (Button.Font.Size = 0) then
    s := s  + ' this.ButtonFontSize = "' + IntToStr(Button.Font.Size) + '";'#13
  else
    s := s  + ' this.ButtonFontSize = 12;'#13;

  s := s  + ' this.ButtonFontColor = "' + ColorToRGBString(Button.ForeColor)+ '";'#13;
  s := s  + ' this.ActiveFontColor = "' + ColorToRGBString(Button.ActiveForeColor)+ '";'#13;
  s := s  + ' this.ButtonCSSStyle= "";'#13
    + ' this.tabScrollSpeed = 4;'#13;

   s := s  + ' this.LabelFontFamily = "'+Font.FontName+'";'#13;

  if not (Font.Size = 0) then
    s := s  + ' this.LabelFontSize = ' + IntToStr(Font.Size) + ';'#13
  else
    s := s  + ' this.LabelFontSize = 12;'#13;

  s := s  + ' this.LabelFontColor = "' + ColorToRGBString(ForeColor)+ '";'#13;

  if (fsBold in Button.Font.Style) then
    s := s  + ' this.ButtonFontBold = true;'#13
  else
    s := s  + ' this.ButtonFontBold = false;'#13;

  if (fsItalic in Button.Font.Style) then
    s := s  + ' this.ButtonFontItalic = true;'#13
  else
    s := s  + ' this.ButtonFontItalic = false;'#13;

  if (fsUnderline in Button.Font.Style) then
    s := s  + ' this.ButtonFontUnderline = true;'#13
  else
    s := s  + ' this.ButtonFontUnderline = false;'#13;

  if (fsBold in Font.Style) then
    s := s  + ' this.LabelFontBold = true;'#13
  else
    s := s  + ' this.LabelFontBold = false;'#13;

  if (fsItalic in Font.Style) then
    s := s  + ' this.LabelFontItalic = true;'#13
  else
    s := s  + ' this.LabelFontItalic = false;'#13;

  if (fsUnderline in Font.Style) then
    s := s  + ' this.LabelFontUnderline = true;'#13
  else
    s := s  + ' this.LabelFontUnderline = false;'#13;

  htmlres := htmlres + s;
  s := '';

  htmlres := htmlres
  + '}'#13

  
  + HTMLName + 'Obj = new '+HTMLName+'Obj();'#13
  + 'document.SideNavBarObj = '+HTMLName+'Obj;'#13
  + 'document.sidenavbarObj = '+HTMLName+'Obj;'#13;

  htmlres := htmlres + '</script>'#13;

  if isPartial then
    htmlres := '';

  PSval := EmptyStr;
  PPval := EmptyStr;

  for i := 1 to Panels.Count do
  begin
{*
    isexp := 'true';
    if not (Panels[i - 1].IsExpanded) then
      isexp := 'false';

    if (SinglePanelOpen) then
    begin
      isexp := 'false';
      if (isAP = 'true') then
        isexp := 'true';
    end;

    if (isexp = 'true') then
    *}
    if (Panels[i - 1].IsExpanded) then
      PSVal := PSVal + '1;'
    else
      PSVal := PSVal + '0;';
  end;

  htmlres := htmlres + '<input type="hidden" value="' + PSVal + '" name="' + HTMLName + 'PS" id="' + HTMLName + 'PS">'#13;

//p := 0;
  for p := 1 to Panels.Count do
  begin

    k := 0;

    for i := 1 to Panels.count do
    begin
      if (Panels[i - 1].FPosition = p - 1) then
        PPVal := PPVal + IntToStr(k) + ';';

      k := k + 1;
    end
  end;

  htmlres := htmlres + '<input type="hidden" value="' + PPVal + '" name="' + HTMLName + 'PP" id="' + HTMLName + 'PP">'#13;

  for k := 1 to Panels.Count do
  begin
    htmlres := htmlres + '<input type="hidden" value="" name="' + HTMLName + 'HT_' + IntToStr(k - 1) + '" id="' + HTMLName + 'HT_' + IntToStr(k - 1) + '">'#13;
  end;

  htmlres := htmlres + '<input type="hidden" value="' + IntToStr(ActivePanel) + '" name="' + HTMLName + 'AP" id="' + HTMLName + 'AP">'#13;
  htmlres := htmlres + '<input type="hidden" value="' + IntToStr(SelectedItem) + '" name="' + HTMLName + 'SI" id="' + HTMLName + 'SI">'#13;

  //javascript rendering

  if not IsPartial then
  begin
    htmlres := htmlres + '<script>'#13;
    htmlres := htmlres + 'sidenavbar_start('+HTMLName+'Obj);'#13;

    //build panels
    for p := 1 to Panels.Count do
    begin
      k := 0;
  //        j := 0;
  //        i := 0;
      op := Panels[0];

      for i := 1 to Panels.Count do
      begin
        if (Panels[i - 1].FPosition = p - 1) then
          op := Panels[k];
        k := k + 1;
      end;

      j := op.Index;

      isAP := 'false';
      if (j = ActivePanel) then
        isAP := 'true';

    if (Assigned (OnPanelChange)) then
      submitclick := 'return SubmitClick('#39 + HTMLName + #39','#39'PANELCHANGE#' + IntToStr(j)+ '#0'#39',false);'#13
    else
      submitclick := '';

    {$IFDEF TMSIW9}
    if Assigned(FOnAsyncPanelChange) then
    begin
      ajaxcall := 'processAjaxEvent(''onPanelChange'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoAsyncPanelChange' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

        Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncPanelChange', DoAsyncPanelChange);

        submitclick := '';
    end;
    {$ENDIF}

      htmlres := htmlres + 'function activepanel_' + HTMLName + '_' + IntToStr(j) + '(){'#13
        + 'p = '+ IntToStr(j) +';'#13
        + 'i = 0;'#13
        +  Panels[j].Script
        + ajaxcall
        + submitclick
        + '}'#13;

      PanelImage := EmptyStr;
      ListImage := EmptyStr;

      img := '';

      img := Panels[j].Glyph.ImageRef(Self, Images);

      if not (img = '') then
      begin
        PanelImage := '<img ondragstart='''+HTMLName+'_cancelEvent()'' border=''0'' style=''position:absolute;top:-8;z-index:25;left:2;'' src='''+img+''' valign=''middle''>&nbsp;';
        ListImage := '<img border=''0'' title='''+ StringReplace(Panels[j].Caption,'"','&quot;',[rfReplaceAll])+''' width=16 height=16 src='''+img+''' valign=''middle''>';
      end
      else
      begin
        PanelImage := '';
        ListImage := '';
      end;

      pBC := EmptyStr;
      if not (Panels[j].BackColor = clNone) then
        pBC := ColorToRGBString(Panels[j].BackColor);

    GradDir := '0';
    if (Panels[j].BackColorGradientDirection = gdHorizontal) then
      GradDir := '1';
       pBC := ' progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Panels[j].BackColor) + ',EndColorStr=' + ColorToRGBString(Panels[j].BackColorTo) + ');background:'+ColorToRGBString(Panels[j].BackColor)+';';

    if (Panels[j].BackColorTo = clNone) then
      pBC := ' progid:DXImageTransform.Microsoft.Gradient(GradientType=' + GradDir + ',StartColorStr=' + ColorToRGBString(Panels[j].BackColor) + ',EndColorStr=' + ColorToRGBString(Panels[j].BackColor) + ');background:'+ColorToRGBString(Panels[j].BackColor)+';';

      isexp := 'true';
      if not (Panels[j].IsExpanded) then
        isexp := 'false';

        {*
      if (SinglePanelOpen) then
      begin
        isexp := 'false';
        if (isAP = 'true') then
          isexp := 'true';
      end;
         *}
      htmlres := htmlres
        + 'sidenavbar_tabstart('+HTMLName+'Obj,"'+IntToStr(j)+'","' + isAP + '", "' + StringReplace(Panels[j].BackgroundImage.FileName,'\','/',[rfReplaceAll]) + '", "'+isExp+'", "' + ColorToRGBString(Panels[j].BorderColor) + '", "' + IntToStr(Panels[j].Height) + '", "' + pBC + '", "' + PanelImage + '","' + ListImage + '","' + StringReplace(Panels[j].Caption,'"','&quot;',[rfReplaceAll]) + '","JSCRIPT:activepanel_' + HTMLName + '_' + IntToStr(j) + '()");'#13;

      pos := Panels[j].FPosition;

      if not (Panels[j].IsExpanded) then
        initcontrols := initcontrols + '  obj.PanelClose('+HTMLName+'Obj,'+ IntToStr(pos) +');'#13
      else
        initcontrols := initcontrols + '  sidenavbar_PanelPositionChange('+HTMLName+'Obj,'+ IntToStr(pos) +','+isexp+');'#13;

      //build items
      for i := 1 to Panels[j].Items.Count do
      begin

        if not (Panels[j].Items[i - 1].Caption = '') then
        begin

         if Assigned(OnItemClick) then
            submitclick := 'return SubmitClick('#39 + HTMLName + #39','#39'ITEMCLICK#' + IntToStr(j)+ '#' + IntToStr(i - 1) + #39',false);'#13
          else
            submitclick := '';

          {$IFDEF TMSIW9}
          if Assigned(OnAsyncItemClick) then
          begin
            ajaxcall := 'processAjaxEvent(''onItemClick'', '
              + HTMLControlImplementation.IWCLName
              + ',''' + HTMLName + '.' + 'DoAsyncItemClick' + ''','
              + 'true' + ', null, '
              + 'true' + ');';

              Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoAsyncItemClick', DoAsyncItemClick);

              submitclick := '';
          end;
          {$ENDIF}

          htmlres := htmlres + 'function itemclick_' + HTMLName + '_' + IntToStr(j) + '_' + IntToStr(i) + '(){'#13
            + 'p = ' + IntToStr(j) +';'#13
            + 'i = ' + IntToStr(i) +';'#13
            + Panels[j].Items[i - 1].Script
            + ajaxcall
            + submitclick
            + '}'#13;
        end;

          itemIm := Panels[j].Items[i - 1].Glyph.ImageRef(Self, Images);
          RenderImgTag := '';

          if (Length(itemIm) > 1) then
          begin
            RenderImgTag := '1';
            itemIm := itemIm;
          end
          else
          begin
            itemIm := ' ';
            RenderImgTag := '0';
          end;

          isDiv := 'false';
          if (Panels[j].Items[i - 1].IsDivider) then
            isDiv := 'true';

          setnode := 'false';
          nodeclosed := 'true';
  //            nextlevel := 0;

          if (i-1 < Panels[j].Items.Count - 1) then
          begin
  //              nextlevel := Panels[j].Items[i].Level;

            if (Panels[j].Items[i].Level > Panels[j].Items[i - 1].Level) then
            begin
              setnode := 'True';
              if (Panels[j].Items[i].IsExpanded) then
                nodeclosed := 'false';
            end
          end;

          if (Panels[j].Items[i - 1].Level = 0) then
            s := s + 'document.getElementById("' + HTMLName + 'HT_'+ IntToStr(j)+ '").value += "1,";'#13
          else
          begin
            if not (Panels[j].Items[i - 1].IsExpanded) then
              s := s + 'document.getElementById("' + HTMLName + 'HT_'+ IntToStr(j)+ '").value += "0,";'#13
            else
              s := s + 'document.getElementById("' + HTMLName + 'HT_'+ IntToStr(j)+ '").value += "1,";'#13;
          end;

         s := s + 'sidenavbar_tabadditem('+HTMLName+'Obj,"' + RenderImgTag + '","' + StringReplace(Panels[j].Items[i - 1].Caption,'"','&quot;',[rfReplaceAll]) + '","' + Panels[j].Items[i - 1].Link + '","' + Panels[j].Items[i - 1].Target + '","' + IntToStr(Panels[j].Items[i - 1].Level) + '","' + isDiv + '","'+ nodeclosed + '","' + setnode + '","'+ IntToStr(j) + '","' + IntToStr(i-1) + '","' + IntToStr(Panels[j].Items.Count) + '","' + itemIm + '","' + Panels[j].Items[i - 1].Hint + '","JScript:itemclick_';
         s := s + HTMLName + '_' + IntToStr(j) + '_' + IntToStr(i) + '()","' + IntToStr(Panels[j].Height) + '");'#13;

          htmlres := htmlres + s;
          s := '';

      end;

      htmlres := htmlres + 'sidenavbar_tabend('+HTMLName+'Obj);'#13;

    end;

    //InitControls
    s := s + 'function ' + HTMLName + 'InitControls() {'#13;
    s := s + initcontrols + #13;
    s := s + '}'#13;

    //PanelOpen
    s := s + 'function ' + HTMLName + 'PanelOpen(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex) {'#13;

    found := false;

    for i:=1 to Panels.Count do
    begin
      if Assigned(Panels[i - 1].Control) then
      begin
        found := true;
        break;
      end;
    end;

    if (found) then
    begin
      s := s + '  switch(pnlIndex) {'#13;

      for i:=1 to Panels.Count do
      begin
        if Assigned(Panels[i - 1].Control) then
        begin
          s := s  + '  case ' + inttostr(Panels[i - 1].FPosition) + ' :'#13;
          s := s  + '    sidenavbar_Show("' + Panels[i - 1].FControl.HTMLName + '",true,pnlTop,pnlLeft,pnlHeight,pnlWidth,' + Panels[i - 1].FControl.HTMLName + 'IWCL);'#13;
          s := s  + '    break;'#13;
        end
      end;

      s := s
        + 'default:'#13
        + '   break;'#13
        + ' }'#13;
    end;

    s := s  + '  switch(pnlIndex) {'#13;
    n := 0;
    for i:=1 to Panels.Count do
    begin
      s := s  + '  case ' + inttostr(Panels[i - 1].FPosition) + ' :'#13;
      s := s  + '    pnlIndex = '+ inttostr(n) +';'#13;
      s := s  + '    break;'#13;
      n := n + 1;
    end;
    s := s  + '}'#13;

    s := s + ClientEvents.PanelOpen.GetText + ''#13;
    s := s  + '}'#13#13;

    //PanelUpdate
    s := s  + 'function '+HTMLName+'PanelUpdate(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex,ctrlVisibility) {'#13;

    found := false;

    for i:=1 to Panels.Count do
    begin
    if Assigned(Panels[i - 1].Control) then
    begin
      found := true;
      break;
    end;
    end;

    if (found) then
    begin
      s := s  + '  switch(pnlIndex) {'#13;

      for i:=1 to Panels.Count do
      begin
        if Assigned(Panels[i - 1].Control) then
        begin
          s := s  + '  case ' + inttostr(Panels[i - 1].FPosition) + ' :'#13;
          s := s  + '    sidenavbar_Show("' + Panels[i - 1].FControl.HTMLName + '",false,pnlTop,pnlLeft,pnlHeight,pnlWidth,' + Panels[i - 1].FControl.HTMLName + 'IWCL);'#13;
          s := s  + '    break;'#13;
        end
      end;

      s := s
        + 'default:'#13
        + '   break;'#13
        + ' }'#13;
    end;

    s := s  + '  switch(pnlIndex) {'#13;
    n := 0;
    for i:=1 to Panels.Count do
    begin
      s := s  + '  case ' + inttostr(Panels[i - 1].FPosition) + ' :'#13;
      s := s  + '    pnlIndex = '+ inttostr(n) +';'#13;
      s := s  + '    break;'#13;
      n := n + 1;
    end;
    s := s  + '}'#13;

    s := s + ClientEvents.PanelUpdate.Text + ''#13;
    s := s  + '}'#13#13;

    htmlres := htmlres + s;
    s := '';

    htmlres := htmlres + '</script>'#13;
  end;


  Result := TIWHTMLTag.CreateTag('DIV');
  Result.Contents.AddText(htmlres);


  shadowdiv := '<div id="' + HTMLName + '_shadow" style="filter:alpha(opacity=55);-moz-opacity:0.5;z-index:1500;visibility:hidden;display:none;position:absolute;width:"></div>';
  Result.Contents.AddText(shadowdiv);

  s := EmptyStr;
  s := s + 'sidenavbar_init('+HTMLName+'Obj);'#13;
  s := s + HTMLName + 'InitControls();'#13;

    {$IFDEF TMSIW6}
     with AContext.PageContext as TIWPageContext40 do
     begin
       if WebApplication.IsPartialUpdate then
       begin
         //TIWComponent40Context(AContext).AddToUpdateInitProc(s + EOL)
       end
       else
       begin
         TIWComponent40Context(AContext).AddToInitProc(s + EOL);
       end;
     end;
    {$ELSE}
    TIWAppForm(Form).AddToInitProc(s + EOL);
    {$ENDIF}

  with Result.Contents.AddTag('INPUT') do
  begin
    AddStringParam('TYPE', 'hidden');
    AddStringParam('NAME', HTMLName);
    AddStringParam('ID', HTMLName + '_INPUT');
  end;

end;

procedure TTIWSideNavBar.SetActivePanel(const Value: integer);
begin
  if (csLoading in ComponentState) then
    FActivePanel := Value
  else
  begin
    if (Value < Panels.Count) and (Value >= 0) then
      FActivePanel := Value
  end;
end;

procedure TTIWSideNavBar.SetSelectedItem(const Value: integer);
begin
  if (csLoading in ComponentState) then
    FSelectedItem := Value
  else
  begin
    if (Value < Panels[ActivePanel].Items.Count) and (Value >= -1) then
      FSelectedItem := Value
  end;
end;

procedure TTIWSideNavBar.Submit(const AValue: string);
var
  si, sp, sval: string;
  itemindex, panelindex, err: Integer;
begin
  inherited;
  // postback command
  // -> server control events

  if Pos('ITEMCLICK', AValue) > 0 then
  begin
    si := '-1';
    sp := '-1';
    sval := AValue;

    system.Delete(sval, 1, 10);
    if pos('#', sval) > 0 then
    begin
      sp := copy(sval, 1, pos('#',sval));
      si := copy(sval, pos('#',sval) + 1, length(sval));
    end;
    val(si,itemindex, err);
    val(sp,panelindex, err);

    if Assigned(FOnItemClick) then
      FOnItemClick(Self,panelindex,itemindex);
    Exit;
  end;

  if Pos('PANELCHANGE', AValue) > 0 then
  begin
    //si := '-1';
    sp := '-1';
    sval := AValue;

    system.Delete(sval, 1, 12);
    if pos('#', sval) > 0 then
    begin
      sp := copy(sval, 1, pos('#',sval));
      //si := copy(sval, pos('#',sval) + 1, length(sval));
    end;
    //val(si,itemindex, err);
    val(sp,panelindex, err);

    if Assigned(FOnPanelChange) then
      FOnPanelChange(Self,FPrevPanelClicked,panelIndex);
  end;
end;

procedure TTIWSideNavBar.SetValue(const AValue: string);
var
vp,vi,vt,i,j: integer;
VarVal,su,si,st: string;
pcheck: boolean;
begin

   //  inherited;
  // hidden input value
  // -> property updating

    VarVal := aValue;

    //retrieve panel position
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);

      for i:=1 to Panels.Count do
      begin
        vi := pos(';', su);
        if vi > 0 then
        begin
          si := copy(su, 1, vi - 1);
          Delete(su, 1, vi);

          Panels[StrToInt(si)].FPosition := i - 1;
        end;
      end;

    end;

    //retrieve panel state
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);

//      OutputDebugString(pchar('panel state: ' + su));

      for i:=1 to Panels.Count do
      begin
        vi := pos(';', su);
        if vi > 0 then
        begin
          si := copy(su, 1, vi - 1);
          Delete(su, 1, vi);

          FPrevPanelClicked := FPanelClicked;
          pcheck := Panels[i - 1].IsExpanded;

          if (StrToInt(si) = 1) then
            Panels[i - 1].IsExpanded := true
          else
            Panels[i - 1].IsExpanded := false;

          if not pcheck = Panels[i - 1].IsExpanded then
            FPanelClicked := i - 1;

          //  OutputDebugString(pchar('PanelClicked: ' + IntToStr(FPanelClicked)
           //   + ' - PrevPanelClicked: ' + IntToStr(FPrevPanelClicked) ));

        end;
      end;

    end;

    //retrieve selected item
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);

      SelectedItem := StrToInt(su);

    end;

    //retrieve active panel
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);

      ActivePanel := StrToInt(su);
      
    end;

    //retrieve treeview state
    vp := pos('|', VarVal);
    if vp > 0 then
    begin
      su := copy(VarVal, 1, vp - 1);
      Delete(VarVal, 1, vp);

     for i:=1 to Panels.Count do
      begin
        vi := pos('#', su);
        if vi > 0 then
        begin                                            
          si := copy(su, 1, vi - 1);
          Delete(su, 1, vi);

          for j:=1 to Panels[i - 1].Items.Count do
          begin
            vt := pos(',', si);
            if vt > 0 then
            begin
              st := copy(si, 1, vt - 1);
              Delete(si, 1, vt);

              if (Length(st) > 0) then
              begin
                if (StrToInt(st) = 1) then
                  Panels[i - 1].Items[j - 1].IsExpanded := true
                else
                  Panels[i - 1].Items[j - 1].IsExpanded := false;
              end;
            end;
          end;
        end;
      end;
    end;
    
end;


{ TSideNavBarButton }

constructor TSideNavBarButton.Create;
begin
  inherited;
     FActiveColor := $C7581E;
     FActiveColorTo := $C7581E;
     FActiveForeColor := $FFFFFF;
     FActiveHoverColor := $C7581E;
     FActiveHoverColorTo := $C7581E;
     FBackColor := $FFFFFF;
     FBackColorTo := $F7DFD6;
     FCollapsedImage := TTIWPicture.Create;
     FExpandedImage := TTIWPicture.Create;
     FFont := TIWFont.Create;
     FForeColor := $C7581E;
     FGradientDirection := gdHorizontal;
     FHeight := 30;
     FHoverColor := clNone;
     FHoverColorTo := clNone;
     FHoverForeColor := $FF8E42;
     FTextAlign := taLeftJustify;
end;

destructor TSideNavBarButton.Destroy;
begin
  inherited;
  FCollapsedImage.Free;
  FExpandedImage.Free;
  FFont.Free;
end;

procedure TSideNavBarButton.SetFont(const Value: TIWfont);
begin
  FFont.Assign(Value);
end;

{ TSideNavBarClientEvents }

constructor TSideNavBarClientEvents.Create;
begin
  inherited;
  FItemClick := TStringList.Create;
  FItemCollapse := TStringList.Create;
  FItemExpand := TStringList.Create;
  FPanelChange := TStringList.Create;
  FPanelClose := TStringList.Create;
  FPanelMove := TStringList.Create;
  FPanelOpen := TStringList.Create;
  FPanelUpdate := TStringList.Create;
end;

destructor TSideNavBarClientEvents.Destroy;
begin
  FItemClick.Free;
  FItemCollapse.Free;
  FItemExpand.Free;
  FPanelChange.Free;
  FPanelClose.Free;
  FPanelMove.Free;
  FPanelOpen.Free;
  FPanelUpdate.Free;
end;

function TSideNavBarClientEvents.GetJSFunction(PropName: string): string;
begin
  if (PropName = 'ItemClick') then
    Result := 'ItemClick(obj,pnlIndex,itmIndex) // obj = SideNavBar object, pnlIndex = Panel index, itmIndex = Item Index';

  if (PropName = 'ItemCollapse') then
    Result := 'ItemCollapse(obj,pnlIndex,itmIndex) // obj = SideNavBar object, pnlIndex = Panel index, itmIndex = Item Index';

  if (PropName = 'ItemExpand') then
    Result := 'ItemExpand(obj,pnlIndex,itmIndex) // obj = SideNavBar object, pnlIndex = Panel index, itmIndex = Item Index';

  if (PropName = 'PanelChange') then
    Result := 'PanelChange(obj,pnlFrom,pnlTo) // obj = SideNavBar object, pnlFrom = Position from, pnlTo = Position To';

  if (PropName = 'PanelClose') then
    Result := 'PanelClose(obj,pnlIndex) // obj = SideNavBar object, pnlIndex = Panel index';

  if (PropName = 'PanelOpen') then
    Result := 'PanelOpen(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex) // obj = SideNavBar object';

  if (PropName = 'PanelUpdate') then
    Result := 'PanelUpdate(obj,pnlIndex,pnlTop,pnlLeft,pnlWidth,pnlHeight,srvrIndex,ctrlVisibility) // obj = SideNavBar object';
end;
                        
procedure TSideNavBarClientEvents.SetItemClick(const Value: TStringList);
begin
  FItemClick.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetItemCollapse(
  const Value: TStringList);
begin
  FItemCollapse.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetItemExpand(const Value: TStringList);
begin
  FItemExpand.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetPanelChange(const Value: TStringList);
begin
  FPanelChange.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetPanelClose(const Value: TStringList);
begin
  FPanelClose.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetPanelMove(const Value: TStringList);
begin
  FPanelMove.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetPanelOpen(const Value: TStringList);
begin
  FPanelOpen.Assign(Value);
end;

procedure TSideNavBarClientEvents.SetPanelUpdate(const Value: TStringList);
begin
  FPanelUpdate.Assign(Value);
end;

{ TSideNavBarDivider }

constructor TSideNavBarDivider.Create;
begin
  inherited;
     FBackColor := clWebWHITESMOKE;
     FBackColorTo := clSilver;
     FForeColor := $00C7581E;
     FGradientDirection := gdVertical;
end;

{ TSideNavBarItems }

function TSideNavBarItems.Add: TSideNavBarItem;
begin
  Result := TSideNavBarItem(inherited Add);
end;

constructor TSideNavBarItems.Create(AOwner: TSideNavBarPanel);
begin
  inherited Create(TSideNavBarItem);
  FOwner := AOwner;
end;

function TSideNavBarItems.GetItems(Index: Integer): TSideNavBarItem;
begin
  Result := TSideNavBarItem(inherited Items[Index]);
end;

function TSideNavBarItems.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

function TSideNavBarItems.Insert(Index: Integer): TSideNavBarItem;
begin
  Result := TSideNavBarItem(inherited Insert(Index));
end;

procedure TSideNavBarItems.SetItems(Index: Integer;
  const Value: TSideNavBarItem);
begin
  inherited Items[Index] := Value;
end;

procedure TSideNavBarItems.Update(Item: TCollectionItem);
begin
  inherited;
  TSideNavBarPanels(FOwner.Collection).FOwner.Invalidate;
end;

{ TSideNavBarItemDisplay }

constructor TSideNavBarItemDisplay.Create;
begin
  inherited Create;
  FAlign := taLeftJustify;
  FCollapsedImage := TTIWPicture.Create;
  FExpandedImage := TTIWPicture.Create;
  FHoverBackColor := clNone;
  FHoverForeColor := $FF8E42;
  FImageMargin := TSideNavBarItemImageMargin.Create;
  FImageSize := TSideNavBarItemImageSize.Create;
  FSelectBackColor := clNone;
  FSelectForeColor := $FF8E42;
  FSpacing := 0;
end;

destructor TSideNavBarItemDisplay.Destroy;
begin
  FImageMargin.Free;
  FImageSize.Free;
  FCollapsedImage.Free;
  FExpandedImage.Free;
  inherited;
end;

{ TTIWPicture }

procedure TTIWPicture.Assign(Source: TPersistent);
begin
  if (Source is TTIWPicture) then
  begin
    FFileName := (Source as TTIWPicture).FileName;
    FImageIndex := (Source as TTIWPicture).ImageIndex;
  end;
end;

constructor TTIWPicture.Create;
begin
  inherited Create;
  FFileName := '';
  FImageIndex := -1;
end;

function TTIWPicture.ImageRef(Control: TIWControl; Images: TIWImageList): string;
begin
  Result := '';

  if FileName <> '' then
    Result :=  StringReplace(FileName,'\','/',[rfReplaceAll])
  else
    if Assigned(Images) and (ImageIndex >= 0) then
    {$IFDEF TMSIW7}
      Result := GServerController.CacheURL + Images.ExtractImageToCache(ImageIndex);
    {$ELSE}
      Result := GetCacheDir(Control) + Images.ExtractImageToCache(ImageIndex);
    {$ENDIF}
end;

{ TSideNavBarItemImageMargin }

constructor TSideNavBarItemImageMargin.Create;
begin
  inherited Create;
  FBottom := 2;
  FLeft := 2;
  FRight := 2;
  FTop := 2;
end;

{ TSideNavBarItemImageSize }

constructor TSideNavBarItemImageSize.Create;
begin
  inherited Create;
  FHeight := 16;
  FWidth := 16;
end;

{ TSideNavBarItem }

procedure TSideNavBarItem.Assign(Source: TPersistent);
begin
  if (Source is TSideNavBarItem) then
  begin
    FCaption := (Source as TSideNavBarItem).Caption;
    FGlyph.Assign((Source as TSideNavBarItem).Glyph);
    FHint := (Source as TSideNavBarItem).Hint;
    FIsDivider := (Source as TSideNavBarItem).IsDivider;
    FIsExpanded := (Source as TSideNavBarItem).IsExpanded;
    FLevel := (Source as TSideNavBarItem).Level;
    FName := (Source as TSideNavBarItem).Name;
    FLink := (Source as TSideNavBarItem).Link;
    FScript := (Source as TSideNavBarItem).Script;
    FTag := (Source as TSideNavBarItem).Tag;
    FTarget := (Source as TSideNavBarItem).Target;
  end;
end;

constructor TSideNavBarItem.Create(Collection: TCollection);
begin
  inherited;
  FGlyph := TTIWPicture.Create;

  FCaption := 'Item ' + IntToStr(Collection.Count - 1) ;
  FHint := EmptyStr;
  FIsDivider := false;
  FIsExpanded := true;
  FLevel := 0;
  FName := EmptyStr;
  FLink := EmptyStr;
  FScript := EmptyStr;
  FTag := 0;
  FTarget := EmptyStr;

  if Collection is TSideNavBarItems then
  begin
    FOwner := Collection as TSideNavBarItems;
  end;
end;

destructor TSideNavBarItem.Destroy;
begin
  FGlyph.Free;
  inherited;
end;

function TSideNavBarItem.GetDisplayName: string;
begin
  if Caption <> '' then
    Result := Caption
  else
    Result := 'Item '+ IntToStr(Index);
end;


function TSideNavBarItem.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

end.
