unit Favourites;
{
  Обработчики команд Flash, связанных с управлением закладками.
  Все обработчики подчиняются общему поведению, определенному
  классом TFlashHandler. См. модуль FlashHandling.
}

interface

Uses
  Windows,Forms,SysUtils,Graphics,Classes,FlshMXCt,Defaults,Logic,FlashHandling;

Type
  TSaveURLHandler=Class(TFlashHandler)
  {Обработчик команды сохранения ссылок}
  {В настоящее время не используется}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TSaveURLHandler}

  TSavePageHandler=Class(TFlashHandler)
  {Обработчик команды сохранения страницы целиком}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TSavePageHandler}

  TNewDirHandler=Class(TFlashHandler)
  {Обработчик команды создания поддиректории в структуре закладок}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TNewDirHandler}

  TTransferHandler=Class(TFlashHandler)
  {Обработчик команды выдачи списка закладок текущей директории}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TTransferHandler}

  TChangeSelHandler=Class(TFlashHandler)
  {Обработчик команды выбора (подсветки) закладки}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TChangeSelHandler}

  TExecHandler=Class(TFlashHandler)
  {Обработчик команды перехода по закладке или перехода в поддиректорию}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TExecHandler}

  TGoHandler=Class(TFlashHandler)
  {Обработчик команд движения по директориям}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TGoHandler}

  TDelHandler=Class(TFlashHandler)
  {Обработчик команды удаления закладки или директории}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TDelHandler}

  TCloseWindowHandler=Class(TFlashHandler)
  {Обработчик команды закрытия окна для удаления изображения скриншота}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TCloseWindowHandler}

  TScreenshotHandler=Class(TFlashHandler)
  {Обработчик команды установки области вывода скриншота}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TScreenshotHandler}

  TIconLoader=Class(TThread)
  {Фоновый загрузчик изображений иконок и скриншотов}
  Protected
    Procedure Execute;Override;
  Public
    Constructor Create;
  End;{TIconLoader}

  TReadyHandler=Class(TFlashHandler)
  {Обработчик команды начала работы}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TReadyHandler}

  TScrollHandler=Class(TFlashHandler)
  {Обработчик команды начала работы}
  Protected
    Procedure Process(Args:TStringList);Override;
    Function ReadCommand:String;Override;
  End;{TScrollHandler}

implementation

Uses
  Controls,FlashWindows,Utils;

Var
  FavList:TFavList; {Текущая иерархия закладок. Интерфейс определен в модуле Logic.}
  CurrentSShot:TPaintItem; {Текущий объект отображения скриншота}
  IconList:TList; {Список отображаемых в данный момент иконок - TPaintItem'ов}
  ScreenshotRect:TRect; {Прямоугольник области вывода скриншота}
  ScrollTop:Integer; {Текущее смещение скорллированного списка закладок}

Procedure ClearIcons;
Begin
  {Удаление изображений иконок с поверхности Flash и из памяти}
  FlashPainter.Deactivate;
  With IconList Do
    While Count>0 Do
    Begin
      FlashPainter.Delete(Last);
      TPaintItem(Last).Free;
      Delete(Count-1);
    End;{While}
  FlashPainter.Activate;
End;{ClearIcons}

Procedure UpdateIcons;
Var
  i:Integer;
Begin
  {Назначение реальных изображений для иконок в зависимости от ScrollTop}
  i:=0;
  While (i+ScrollTop<FavList.Count) And (i<IconList.Count) Do
  Begin
    If FavList.Item(i+ScrollTop)<>Nil Then
      TPaintItem(IconList[i]).Bitmap:=FavList.Item(i+ScrollTop).Icon;
    Inc(i);
  End;{While}
End;{UpdateIcons}

{ TSaveURLHandler }

procedure TSaveURLHandler.Process(Args: TStringList);
begin
  {Создается новая закладка, сохраняется на диск, добавляется в текущий
   список закладок}
  FavList.Add(CurrentTab).Save;
end;

function TSaveURLHandler.ReadCommand: String;
begin
  Result:='SaveURL';
end;

{ TSavePageHandler }

procedure TSavePageHandler.Process(Args: TStringList);
begin
  {Создается новая закладка, сохраняется текущая страница. Закладка
  сохраняется на диск и добавляется в текущий список}
  FFlash.Refresh;
  With FavList.Add(CurrentTab) Do
    Try
      LocalPath:=CurrentTab.Save;
      Save;
    Except
      FavList.DeleteItem(FavList.Count-1);
      CurrentTab.DeleteSaved;
      Raise;
    End;{Try}
end;

function TSavePageHandler.ReadCommand: String;
begin
  Result:='SavePage';
end;

{ TNewDirHandler }

procedure TNewDirHandler.Process(Args: TStringList);
begin
  {В текущем списке закладок создается и устанаваливается текущей
  новая директория. Название берется из Flash-переменной. Затем Flash
  уведомляется о смене директории.}
  FavList.AddDir(FFlash.GetVariable('SaveDir1'));
  FFlash.TCallLabel('Procs','ChDir');
  FFlash.SetVariable('Bookmarks:FullPath',FavList.FullName);
end;

function TNewDirHandler.ReadCommand: String;
begin
  Result:='NewDir';
end;

{ TTransferHandler }

procedure TTransferHandler.Process(Args: TStringList);
Var
  i:Integer;
  X,Y:Integer;
begin
  {Проивзодим какие-либо действия, только если во Flash открыто окно Bookmark}
  With FFlash Do
    If GetVariable('Win')='Bookmarks' Then
    Begin
      {Обновляем текущий путь внутри закладок во Flash}
      SetVariable('Bookmarks:FullPath',FavList.FullName);
      {Начинаем обновление списка}
      SetVariable('Bookmarks/List:Length',IntToStr(FavList.Count));
      ClearIcons; {Очистка списков отображений иконок}
      {Устанавливаем новые TPaintItem в места отображения иконок}
      For i:=0 To StrToInt(GetVariable('Bookmarks/List:NumberOfLines'))-1 Do
      Begin
        X:=StrToInt(GetVariable('Bookmarks/List/IconLineX:'+IntToStr(i)))*Screen.Width Div FlashWidth;
        Y:=StrToInt(GetVariable('Bookmarks/List/IconLineY:'+IntToStr(i)))*Screen.Height Div FlashHeight;
        IconList.Add(TPaintItem.Create(X,Y));
        FlashPainter.Add(IconList.Last);
      End;
      ScrollTop:=0;
      {Переписываем в Flash-массив названия директорий и закладок по текущему пути}
      For i:=0 To FavList.Count-1 Do
      Begin
        SetVariable('Bookmarks/List/prog:'+IntToStr(i),FavList.Title(i));
        {Устанавливаем флаг в зависимости от необходимости показывать иконку
        и наличия самой иконки}
        If FavList.Item(i)=Nil Then
          SetVariable('Bookmarks/List/flag:'+IntToStr(i),'0')
        Else
          With FavList.Item(i) Do
          Begin
            If Icon=Nil Then
              Try
                RetrieveIcon;
              Except
              End;{Try}
            If (Icon=Nil) Or Icon.Empty Then
              SetVariable('Bookmarks/List/flag:'+IntToStr(i),'1')
            Else
              SetVariable('Bookmarks/List/flag:'+IntToStr(i),'-1');
          End;{With}
      End;{For}
      UpdateIcons;
      {Заканчиваем обновление списка}
      TCallLabel('Bookmarks/List','Reset');
      {RedrawWindow(CurrentTab.BrowserHandle,Nil,0,RDW_INVALIDATE Or RDW_UPDATENOW);}
      {Обновляем состояние кнопок}
      SetVariable('buttonWin','Bookmarks');
      SetVariable('buttonName','Back');
      SetVariable('buttonStatus',BooleanToStr(FavList.CanGoBack));
      TCallLabel('Procs','buttonActive');
      SetVariable('buttonName','Forward');
      SetVariable('buttonStatus',BooleanToStr(FavList.CanGoForward));
      TCallLabel('Procs','buttonActive');
      SetVariable('buttonName','Home');
      SetVariable('buttonStatus',BooleanToStr(FavList.CanGoHome));
      TCallLabel('Procs','buttonActive');
    End;{If}
end;

function TTransferHandler.ReadCommand: String;
begin
  Result:='Transfer';
end;

{ TChangeSelHandler }

procedure TChangeSelHandler.Process(Args: TStringList);
Var
  i:Integer;
begin
  i:=StrToInt(Args[0]);
  {Удалить предыдущий скриншот (если есть)}
  CurrentSShot.Bitmap:=Nil;
  {Заполняем переменные и инициализируем картинку скриншота}
  If FavList.Item(i)<>Nil Then
    {Если выбранный элемент - закладка:}
    With FavList.Item(i) Do
    Begin
      {Обновляем во Flash адрес и время создания}
      FFlash.SetVariable('URL',URL);
      FFlash.SetVariable('CreateTime',FormatDateTime('d.mm.yy h:nn',Created));
     {Выбрать новый элемент отрисовки с переданной картинкой}
      With ScreenshotRect Do
      Begin
        If Screenshot=Nil Then
          RetrieveScreenshot;
        If Screenshot<>Nil Then
        Begin
          Screenshot.Stretch(Right-Left,Bottom-Top);
          CurrentSShot.Bitmap:=Screenshot.Bitmap;
        End;{If}
      End;{With}
      {Добавить его в перерисовщик}
      FlashPainter.Add(CurrentSShot);
    End{With}
  Else
  Begin
    {Если выбранный элемент - директория:}
    {Обновляем во Flash адрес и отправляем в качестве скриншота пустоту}
    FFlash.SetVariable('URL','Папка');
    FFlash.SetVariable('CreateTime','');
  End;{If}
end;

function TChangeSelHandler.ReadCommand: String;
begin
  Result:='ChangeSel';
end;

{ TExecHandler }

procedure TExecHandler.Process(Args: TStringList);
Var
  Favourite:IFavourite;
begin
  {Получаем текущий элемент списка закладок}
  Favourite:=FavList.Item(StrToInt(Args[0]));
  If Favourite<>Nil Then
    {Если текущий эдемент - закладка,
    отдать ее текущему окну браузера для перехода}
    CurrentTab.NavigateFav(Favourite)
  Else
  Begin
    {Если текущий элемент - директория,
    сделать ее текущей и уведомить об этом Flash}
    FavList.Move(StrToInt(Args[0]));
    FFlash.TCallLabel('Procs','ChDir');
    FFlash.SetVariable('Bookmarks:FullPath',FavList.FullName);
  End;{If}
end;

function TExecHandler.ReadCommand: String;
begin
  Result:='Exec';
end;

{ TGoHandler }

procedure TGoHandler.Process(Args: TStringList);
begin
  {Проивзодим какие-либо действия, только если во Flash открыто окно Bookmark}
  If FFlash.GetVariable('Win')='Bookmarks' Then
  Begin
    {В зависимости от параметра команды переходим в списке закладок по истории переходов}
    If Args[0]='Begin' Then
      FavList.Move(-3);
    If Args[0]='Back' Then
      FavList.Move(-1);
    If Args[0]='Forward' Then
      FavList.Move(-2);
    With FFlash Do
    Begin
      {Уведомляем Flash о смене директории}
      TCallLabel('Procs','ChDir');
      SetVariable('Bookmarks:FullPath',FavList.FullName);
    End;{With}
  End;{If}
end;

function TGoHandler.ReadCommand: String;
begin
  Result:='Go';
end;

{ TDelHandler }

procedure TDelHandler.Process(Args: TStringList);
Var
  i:Integer;
begin
  {Проивзодим какие-либо действия, только если во Flash открыто окно Bookmark}
  If FFlash.GetVariable('Win')='Bookmarks' Then
  Begin
    i:=StrToInt(Args[0]);
    {Стираем изображение скриншота}
    Try
      FlashPainter.Delete(CurrentSShot);
    Except
    End;{Try}
    {Убираем иконку удаляемой закладки из прорисовки}
    TPaintItem(IconList[i-ScrollTop]).Bitmap:=Nil;
    {Удаляем закладку}
    FavList.DeleteItem(i);
    {Обновляем список прорисовки по новому списку закладок}
    UpdateIcons;
  End;{If}
end;

function TDelHandler.ReadCommand: String;
begin
  Result:='DelLine';
end;

{ TCloseWindowHandler }

procedure TCloseWindowHandler.Process(Args: TStringList);
begin
  If Args[0]='5' Then
  {Если закрываемое окно - скриншот, удалить картинку из перерисовщика и
  уничтожить}
  Begin
    ClearIcons;
    Try
      CurrentSShot.Bitmap:=Nil;
      FlashPainter.Delete(CurrentSShot);
    Except
    End;{Try}
  End;{If}
end;

function TCloseWindowHandler.ReadCommand: String;
begin
  Result:='CloseWindow';
end;

{ TScreenshotHandler }

procedure TScreenshotHandler.Process(Args: TStringList);
begin
  {Установка размеров прямоугльника для отображения скриншота
  с пересчетом координат в реальные для текущего разрешения экрана}
  ScreenshotRect:=Bounds(StrToInt(Args[0])*Screen.Width Div FlashWidth,
                         StrToInt(Args[1])*Screen.Height Div FlashHeight,
                         StrToInt(Args[2])*Screen.Width Div FlashWidth Div 2,
                         StrToInt(Args[3])*Screen.Height Div FlashHeight Div 2);
  CurrentSShot.X:=ScreenshotRect.Left;
  CurrentSShot.Y:=ScreenshotRect.Top;
end;

function TScreenshotHandler.ReadCommand: String;
begin
  Result:='Screenshot';
end;


{ TReadyHandler }

procedure TReadyHandler.Process(Args: TStringList);
begin
  TIconLoader.Create;
end;

function TReadyHandler.ReadCommand: String;
begin
  Result:='Ready';
end;

{ TIconLoader }

constructor TIconLoader.Create;
begin
  Inherited Create(True);
  FreeOnTerminate:=True;
  Priority:=tpIdle;
  Resume;
end;

procedure TIconLoader.Execute;
begin
  FavList.PreloadIcons;
  FavList.PreloadScreenshots;
end;

{ TScrollHandler }

procedure TScrollHandler.Process(Args: TStringList);
begin
  {Назначается новое смещение списка}
  ScrollTop:=StrToInt(Args[0]);
  {Перемещаются иконки}
  UpdateIcons;
end;

function TScrollHandler.ReadCommand: String;
begin
  Result:='Scroll';
end;

Initialization
  FavList:=TFavList.Create(FavDir);
  ScreenshotRect:=Rect(0,0,0,0);
  CurrentSShot:=TPaintItem.Create(0,0);
  IconList:=TList.Create;
  ScrollTop:=0;
  {$IFDEF Debug}
  Log('Favourites Initialized');
  {$ENDIF}

Finalization
  FavList.Free;
  CurrentSShot.Free;
  {$IFDEF Debug}
  Log('Favourites Freed');
  {$ENDIF}

end.