unit PluginTabControl;

interface

uses
  Tabs, Classes, SysUtils, uICaption, uPluginObject;

type
  TPluginTabControl = class(TTabSet)
  private
    function checkGetPluginObject(pvIndex:Integer): TPluginObject;
  protected
    procedure OnTabChange(Sender: TObject; NewTab: Integer; var AllowChange:
        Boolean);
    procedure OnTabClose(Sender: TObject; var ACanClose: Boolean);

    procedure setCaptionMananger(const pvPlugin: IInterface; pvCaptionMananger:
        ICaptionManager);

    procedure onPluginSetCaption(Sender: TObject; pvCaption:String);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    function BindPlugin(const pvPlugin: IInterface; pvInstanceID: string): TPluginObject;

    function unBindPlugin(pvIndex: Integer; const pvPluginObject: TPluginObject):
        Boolean;

    function remove(pvInstanceID:string): Boolean;

    procedure showCurrentPlugin();

    function ShowTabPlugin(pvIndex: Integer): IInterface;
    
    function FindPlugin(const pvInstanceID: string): Integer;

    function CheckFind(const pvInstanceID: string; pvRaiseIfFalse: Boolean = true):
        Integer;

    function GetActivePlugin: IInterface;

    procedure closeAll;

    procedure freeAll;

    procedure RefreshCaption(const pvPlugin: IInterface);
  end;



implementation

uses
  Forms, uMainFormTools;

constructor TPluginTabControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
//  self.ShowCloseButton := true;
//  self.ShowCloseButtonOnActiveTab := true;
  self.OnChange := OnTabChange;
  //self.OnClose := OnTabClose;
end;

destructor TPluginTabControl.Destroy;
begin
  inherited Destroy;
end;

procedure TPluginTabControl.OnTabClose(Sender: TObject; var ACanClose: Boolean);
var
  lvPluginObject: TPluginObject;
begin
  //在Plugin释放的时候移除
  ACanClose := false;
  lvPluginObject := TPluginObject(Self.Tabs.Objects[self.TabIndex]);
  if not lvPluginObject.canClose then
  begin //不允许手工关闭, 主页
    {nop}
  end else
  begin
    TMainFormTools.closePlugin(lvPluginObject.Plugin);
  end;
end;

procedure TPluginTabControl.OnTabChange(Sender: TObject; NewTab: Integer; var
    AllowChange: Boolean);
var
  lvPluginObject: TPluginObject;
begin
  if self.TabIndex = -1 then exit;
  
  lvPluginObject := TPluginObject(Self.Tabs.Objects[self.TabIndex]);
  if lvPluginObject<> nil then
  begin
    TMainFormTools.showAsNormal(lvPluginObject.Plugin);
  end;
end;

function TPluginTabControl.BindPlugin(const pvPlugin: IInterface; pvInstanceID:
    string): TPluginObject;
var
  lvObj: TPluginObject;
  lvStr:String;
begin
  lvObj := TPluginObject.Create();
  lvObj.OnSetCaption := self.onPluginSetCaption;
  lvObj.InstanceID := pvInstanceID;
  lvObj.Plugin := pvPlugin;
  
  lvStr := TMainFormTools.getPluginCaption(lvObj.Plugin);
  self.setCaptionMananger(pvPlugin, lvObj);

  Self.OnChange := nil;
  try
    self.TabIndex := self.Tabs.AddObject(lvStr, lvObj);
  finally
    self.OnChange := OnTabChange;
  end;

//  with self.Tabs.Add do
//  begin
//    self.TabIndex := Index;
//    Data := lvObj;
//    ImageIndex := 0;
//    Caption := lvStr;
//  end;
  Result := lvObj;
end;

function TPluginTabControl.CheckFind(const pvInstanceID: string;
    pvRaiseIfFalse: Boolean = true): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Self.Tabs.Count - 1 do
  begin
    if checkGetPluginObject(i).InstanceID = pvInstanceID then
    begin
      Result := i;
      Break;
    end;
  end;

  if (Result = -1) and pvRaiseIfFalse then
    raise Exception.CreateFmt('未找到(%)插件对应的页面', [pvInstanceID]);
end;

procedure TPluginTabControl.closeAll;
var
  i: Integer;
  lvPluginObject: TPluginObject;
begin
  for i := Self.Tabs.Count - 1 downto 0 do
  begin
    lvPluginObject := checkGetPluginObject(i);
    if not lvPluginObject.canClose then
    begin //不允许手工关闭, 主页
      {nop}
    end else
    begin
      TMainFormTools.closePlugin(lvPluginObject.Plugin);
    end;
  end;

end;

function TPluginTabControl.FindPlugin(const pvInstanceID: string): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Self.Tabs.Count - 1 do
  begin
    if checkGetPluginObject(i).InstanceID = pvInstanceID then
    begin
      Result := i;
      Break;
    end;
  end;
end;

procedure TPluginTabControl.freeAll;
var
  i: Integer;
  lvPluginObject: TPluginObject;
begin
  for i := Self.Tabs.Count - 1 downto 0 do
  begin
    lvPluginObject := checkGetPluginObject(i);
    try
      unBindPlugin(i, lvPluginObject);
      TMainFormTools.freePlugin(lvPluginObject.Plugin);
    finally
      lvPluginObject.Free;
    end;
  end;
end;

function TPluginTabControl.GetActivePlugin: IInterface;
begin
  Result := nil;
  if Self.TabIndex = -1 then exit;
  Result := checkGetPluginObject(self.TabIndex).Plugin;
end;

function TPluginTabControl.checkGetPluginObject(pvIndex:Integer): TPluginObject;
begin
  Result := TPluginObject(Self.Tabs.Objects[pvIndex]);
  if Result = nil then
  begin
    raise Exception.Create('获取不到页面插件对象');
  end;
end;

procedure TPluginTabControl.onPluginSetCaption(Sender: TObject;
  pvCaption: String);
begin

end;

procedure TPluginTabControl.RefreshCaption(const pvPlugin: IInterface);
var
  lvIndex: Integer;
  lvInstanceID:String;
begin
  lvInstanceID := TMainFormTools.getInstanceID(pvPlugin);
  lvIndex := CheckFind(lvInstanceID, False);
  if lvIndex <> -1 then
  begin
    self.Tabs[lvIndex] := TMainFormTools.getPluginCaption(pvPlugin);
  end;
end;

function TPluginTabControl.remove(pvInstanceID:string): Boolean;
var
  lvIndex: Integer;
  lvObj: TPluginObject;
begin
  Result := false;
  lvIndex := CheckFind(pvInstanceID, False);
  if lvIndex <> -1 then
  begin
    lvObj := checkGetPluginObject(lvIndex);
    try
      unBindPlugin(lvIndex, lvObj);
      Result := true;

    finally
      lvObj.Free;
    end;

  end;

end;

procedure TPluginTabControl.setCaptionMananger(const pvPlugin: IInterface;
    pvCaptionMananger: ICaptionManager);
var
  lvSetter:ICaptionManagerSetter;
begin
  if pvPlugin = nil then Exit;  
  try
    if pvPlugin.QueryInterface(ICaptionManagerSetter, lvSetter) = S_OK then
    begin
      lvSetter.setCaptionManager(pvCaptionMananger);
    end;
  except
  end;
end;

procedure TPluginTabControl.showCurrentPlugin;
begin
  ShowTabPlugin(self.TabIndex);
end;

function TPluginTabControl.ShowTabPlugin(pvIndex: Integer): IInterface;
var
  lvPluginObject: TPluginObject;
begin
  Self.TabIndex := pvIndex;
  if pvIndex = -1 then exit;
  
  lvPluginObject := checkGetPluginObject(pvIndex);
  TMainFormTools.showAsNormal(lvPluginObject.Plugin);
  Result := lvPluginObject.Plugin;
end;

function TPluginTabControl.unBindPlugin(pvIndex: Integer; const pvPluginObject:
    TPluginObject): Boolean;
begin
  self.OnChange := nil;
  try
    Result := false;
    setCaptionMananger(pvPluginObject.Plugin, nil);
    //先删除
    //Self.Tabs[lvIndex] := nil;
    self.Tabs.Objects[pvIndex] := nil;

    Self.Tabs.Delete(pvIndex);
  finally
    self.OnChange := OnTabChange;
  end;

end;


end.

