unit UnitFrmSysTrayMenu;
{
    Purpose:
        This unit is responsible for the system tray icon and it's
        popup menu.
}
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ExtCtrls, ShellAPI, StdCtrls, ImgList, 
  Vcl.PlatformDefaultStyleActnCtrls, Vcl.ActnPopup, UnitFrmTooltipNew;


const MY_WM_TRAYICON = WM_USER + 1; // used to receive tray icon messsages


type
  TfrmSysTrayMenu = class(TForm)
    Label1: TLabel;
    ToggleTimer: TTimer;
    ImageList1: TImageList;
    timDisabled: TTimer;
    PopupActionBar1: TPopupActionBar;
    ilPopupIcons: TImageList;
    test1: TMenuItem;
    test21: TMenuItem;
    timCloseTooltip: TTimer;
    timShowTooltip: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure timDisabledTimer(Sender: TObject);
    procedure timCloseTooltipTimer(Sender: TObject);
    procedure timShowTooltipTimer(Sender: TObject);
    procedure FormHide(Sender: TObject);
  private
    { Private declarations }

    TrayIcon: TNotifyIconData;          {tray icon info}
    iconPic : TIcon;
    DisableIconChanges : boolean;
    PopupShowing : boolean;
    WM_TASKBAR_CREATE : Cardinal;
    ForceIconRestore : boolean;
    JustSwitched : boolean;
    targetEXE : string;
    CurrentIconIndex : integer;
    DisalbedEXEs,
    NoRightClickEXEs,
    ExplorerCompatEXEs,
    ProgramMacroEXEs : TSTringList;

    //tooltip : TTooltipWindow;
    TooltipNew : TFrmTooltipNew;
    notooltip : boolean;

    disabled : boolean;

    lastmouseX, lastMouseY : integer;
    ignoreForeground : boolean;
    function GetIconTooltipText : string;


    procedure SetIconByIndex(index : longint);
    procedure CreateTrayIcon;
    procedure TooltipClickEvent(sender : TObject);
    procedure UpdateTrayIcon;
    procedure ShowTooltip;
    procedure CloseTooltip;
  public
    TrayPopup : TPopupMenu;

    procedure AboutClickEvent(sender : TObject);
    procedure ExitMenuItemClickEvent(Sender: TObject);
    procedure EditHistoryMenuItemClickEvent(sender : TObject);
     procedure EditClipboardMenuItemClickEvent(sender : TObject);

    procedure ConfigureMenuItemClickEvent(Sender : TObject);
    procedure RefreshMenuItemClickEvent(Sender : TObject);
    procedure FlushPopupClipsClick(Sender : TObject);
    procedure FlushTextNonTextClickEvent(Sender : TObject);
    procedure FlushEverything(Sender : TObject);
    procedure FlushClipboard(Sender: TObject);
    procedure FlushRemovedClips(Sender: TObject);
    procedure ClipboardBarShow(Sender : TObject);
    procedure ClipboardBarHide(Sender : Tobject);


    procedure DisabledEXEClickEvent(Sender : TObject);
        procedure NoRightClickEvent(Sender : TObject);
      procedure RemovedItemsMenuItemClickEvent(sender : Tobject);

    procedure PermanentClipsMenuItemClickEvent(sender : TOBject);
    //procedure MethodMenuItemClickEvent(Sender : TObject);
    procedure SwitchPermFolder(sender : TObject);
    function IsDisabledEXE(exename : string) : boolean;
    function IsNoRightClickEXE(exename : string) : boolean;
    function IsExplorerCompatEXE(exename : string) : boolean;
    function GetProgramMacro(exename : string) : string;

    procedure GetEXEDisabledList(var sl : TStringList);
    procedure GetEXENoRightClickList(var sl : TStringList);
    procedure GetEXEExplorerCompatList(var sl : TStringList);
    procedure GetEXEProgramMacro(var sl : TStringList);

    procedure ToggletDisabledEXE(exename : string);
    procedure ToggleNoRightClickEXE(exename : string);
    procedure ToggleExplorerCompatEXE(exename : string);
    procedure SetProgramMacro(exename : string; macro : string);


        procedure WMTrayIcon(var Msg: TMessage); message MY_WM_TRAYICON;
        procedure WndProc(var Msg: TMessage); override; // trap new icon message

        procedure SetIconNormal;
        procedure SetIconIgnore;
        procedure SetIconTriggered;
        procedure ForceIconUpdate;
        procedure SetDisableIconChanges(value : boolean);
        function GetJustSwitched : boolean;


        procedure ShowPopup(inmenu : TMenuItem = nil);

        procedure AfterLoadReport;
  end;

var
  frmSysTrayMenu: TfrmSysTrayMenu;


implementation

uses  UnitFrmConfig, UnitFrmClipboardManager, clipbrd,
  UnitFrmMainPopup,UnitPopupGenerate, UnitClipQueue, UnitFrmAbout, {UnitFrmRemoved,}
  UnitKeyboardQuery, UnitFrmPermanentNew, UnitMisc, UnitOtherQueue,
  UnitPaste, UnitMenuItemTagdata, UnitFrmEditItem , UnitFrmDummyClipboardBar, ActnMenus
  , UnitFrmEditTextExternal, UnitFrmEditHistory, Math, UnitFrmDebug, UnitFocusManager;
{$R *.dfm}

CONST INDEX_IGNORE = 0;
        INDEX_NORMAL = 2;
        INDEX_TRIGGERED = 1;


{////////////////////}
{//Public Interface//}
{////////////////////}

procedure TfrmSysTrayMenu.ToggleNoRightClickEXE(exename: string);
begin
    self.targetEXE := exename;
    self.NoRightClickEvent(self);
end;
procedure TfrmSysTrayMenu.ToggletDisabledEXE(exename: string);
begin
    self.targetEXE := exename;
    self.DisabledEXEClickEvent(self);
end;
procedure TfrmSysTrayMenu.ToggleExplorerCompatEXE(exename : string);
var
    s : string;
begin
    exename := lowercase(exename);
    s := self.ExplorerCompatEXEs.values[exename];
    if (s = '') or (s = '0') then begin
        self.ExplorerCompatEXEs.values[exename] := '1';
    end else begin
        self.ExplorerCompatEXEs.values[exename] := '0';
    end;
end;
procedure TfrmSysTrayMenu.SetProgramMacro(exename : string; macro : string);
begin
    self.ProgramMacroEXEs.Values[lowercase(exename)] := macro;
end;
procedure TfrmSysTrayMenu.GetEXEDisabledList(var sl: TStringList);
begin
    sl.AddStrings(DisalbedEXEs);
end;
procedure TfrmSysTrayMenu.GetEXENoRightClickList(var sl: TStringList);
begin
    sl.AddStrings(NoRightClickEXEs);
end;
procedure TfrmSysTrayMenu.GetEXEExplorerCompatList(var sl : TStringList);
begin
    sl.AddStrings(ExplorerCompatEXEs);
end;
procedure TfrmSysTrayMenu.GetEXEProgramMacro(var sl : TStringList);
begin
    sl.AddStrings(ProgramMacroEXEs);
end;
function TfrmSysTrayMenu.IsDisabledEXE(exename: string): boolean;
begin
    result := self.DisalbedEXEs.Values[exename] <> '';
end;
function TfrmSysTrayMenu.IsNoRightClickEXE(exename: string): boolean;
begin
    result := self.NoRightClickEXEs.Values[exename] <> '';
end;
function TfrmSysTrayMenu.IsExplorerCompatEXE(exename : string) : boolean;
var s : string;
begin
    exename := lowercase(exename);
    s := self.ExplorerCompatEXEs.Values[exename];
    result := (s = '1') or ((s = '') and (lowercase(exename)='explorer.exe') );
end;
function TfrmSysTrayMenu.GetProgramMacro(exename : string) : string;
begin
    exename := lowercase(exename);
    result := self.ProgramMacroEXEs.Values[exename];
end;
procedure TfrmSysTrayMenu.DisabledEXEClickEvent(Sender: TObject);
var s : string;
begin
    s := self.DisalbedEXEs.values[targetEXE];
    if s = '' then begin
        self.DisalbedEXEs.values[targetEXE] := '1';
    end else begin
        self.DisalbedEXEs.values[targetEXE] := '';
    end;

    targetEXE := '';
end;
procedure TfrmSysTrayMenu.NoRightClickEvent(Sender: TObject);
var s : string;
begin
    s := self.NoRightClickEXEs.values[targetEXE];
    if s = '' then begin
        self.NoRightClickEXEs.values[targetEXE] := '1';
    end else begin
        self.NoRightClickEXEs.values[targetEXE] := '';
    end;

    targetEXE := '';
end;



procedure TFrmSysTrayMenu.SetDisableIconChanges(value: boolean);
begin
   self.DisableIconChanges := value;
end;
procedure TFrmSysTrayMenu.SetIconNormal;
var s : string;
begin
    ToggleTimer.Enabled := false;

    {Do I really need disable updates if the icon is normal?}
    //if (not self.DisableIconChanges) or (self.ForceIconRestore) then begin
        self.CurrentIconIndex := INDEX_NORMAL;
        self.ForceIconRestore := false;
        TrayIcon.cbSize := SizeOf(TrayIcon);
        TrayIcon.Wnd := Self.Handle;
        TrayIcon.uID := 0;
        TrayIcon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE;
        TrayIcon.uCallbackMessage := MY_WM_TRAYICON;
        TrayIcon.hIcon := Application.Icon.Handle;

        s := GetIconTooltipText;
        move(s[1], TrayIcon.szTip, strsize(s));


        ShellAPI.Shell_notifyIcon(NIM_MODIFY, @TrayIcon);
    //end;
end;
procedure TFrmSysTrayMenu.SetIconIgnore;
begin
    self.SetIconByIndex(INDEX_IGNORE);
end;
procedure TFrmSysTrayMenu.SetIconTriggered;
begin
    if ToggleTimer.Enabled = False then
        self.SetIconByIndex(INDEX_TRIGGERED);
end;
procedure TFrmSysTrayMenu.SetIconByIndex(index : longint);
var s : string;
begin
    ToggleTimer.Enabled := true;

    if (not frmconfig.cbDisableSystemTrayIconNotification.Checked) then begin
        self.CurrentIconIndex := index;
        ImageList1.GetIcon(index, IconPic);
        TrayIcon.cbSize := SizeOf(TrayIcon);
        TrayIcon.Wnd := Self.Handle;
        TrayIcon.uID := 0;
        TrayIcon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE;
        TrayIcon.uCallbackMessage := MY_WM_TRAYICON;

        TrayIcon.hIcon :=  IconPic.Handle;

        s := GetIconTooltipText;
        move(s[1], TrayIcon.szTip, strsize(s));

        ShellAPI.Shell_notifyIcon(NIM_MODIFY, @TrayIcon);
    end;
end;


procedure TFrmSysTrayMenu.AfterLoadReport;
begin
    self.disabled := false;
end;

{
--========================
-- // Create/Destroy   //
--========================
}
const DISABLED_FILE = 'disabled.ini';
const NORIGHTCLICK_FILE = 'noright.ini';
const EXPLORERCOMPAT_FILE = 'explorer.ini';
const PROGRAMMACRO_FILe = 'programmacro.ini';

procedure TfrmSysTrayMenu.ForceIconUpdate;
begin
    self.UpdateTrayIcon;
end;
procedure TfrmSysTrayMenu.CreateTrayIcon;
var s : string;
begin
    //
    // create the initial icon
    // NIM_MODIFY will be performed for updates
    //
    TrayIcon.cbSize := SizeOf(TrayIcon);
    TrayIcon.Wnd := Self.Handle;
    TrayIcon.uID := 0;
    TrayIcon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE;
    TrayIcon.uCallbackMessage := MY_WM_TRAYICON;
    TrayIcon.hIcon := Application.Icon.Handle;

    s := GetIconTooltipText;
    move(s[1], TrayIcon.szTip, strsize(s));

    ShellAPI.Shell_notifyIcon(NIM_ADD, @TrayIcon);

end;

procedure TfrmSysTrayMenu.FormCreate(Sender: TObject);
    procedure LoadSettings(nameonly : string; sl : TStringList);
    var s : string;
    begin
        s := UnitMisc.GetAppPath;
        s := s + nameonly;
        if FileExists(s) then begin
            sl.LoadFromFile(s);
        end;
    end;
begin
    FrmDebug.AppendLog('SystemTrayIcon - creating');

    disabled := true;

    if assigned(FrmConfig)  and FrmConfig.GetOldTrayPopup then begin
        TrayPopup := TPopupMenu.Create(self);
    end else begin
        TrayPopup := TPopupActionBar.Create(self);
    end;
    iconpic := TIcon.Create;


    self.CreateTrayIcon;
    WM_TASKBAR_CREATE := RegisterWindowMessage('TaskbarCreated');

    self.DisalbedEXEs := TStringList.Create;
    self.NoRightClickEXEs := TStringList.Create;
    self.ExplorerCompatEXEs := TStringList.Create;
    ProgramMacroEXEs := TStringList.Create;

    LoadSettings(DISABLED_FILE, self.DisalbedEXEs);
    LoadSettings(NORIGHTCLICK_FILE, self.NoRightClickEXEs);
    LoadSettings(EXPLORERCOMPAT_FILE, self.ExplorerCompatEXEs);
    LoadSettings(PROGRAMMACRO_FILe, self.ProgramMacroEXEs);

    //tooltip := TTooltipWindow.Create;
    TooltipNew := TFrmTooltipNew.Create(application);


    lastmousex := 0;
    lastmousey := 0;
end;
procedure TfrmSysTrayMenu.FormDestroy(Sender: TObject);
    procedure SaveSettings(nameonly : string; sl : TStringList);
    var s : string;
    begin
        s := UnitMisc.GetAppPath;
        s := s + nameonly;
        sl.SaveToFile(s);
    end;
begin
    //
    // Remove tray icon
    //
    ShellAPI.Shell_notifyIcon(NIM_DELETE, @TrayIcon);

    TrayPopup.Items.Clear;
    MyFree(TrayPopup);
    MyFree(iconPic);

    SaveSettings(NORIGHTCLICK_FILE, self.NoRightClickEXEs);
    SaveSettings(DISABLED_FILE, self.DisalbedEXEs);
    SaveSettings(EXPLORERCOMPAT_FILE, self.ExplorerCompatEXEs);
    SaveSettings(PROGRAMMACRO_FILe, self.ProgramMacroEXEs);

    MyFree(DisalbedEXEs);
    MyFree(NoRightClickEXEs);
    MyFree(self.ExplorerCompatEXEs);
    MyFree(self.ProgramMacroEXEs);
end;
procedure TfrmSysTrayMenu.FormHide(Sender: TObject);
begin

end;

{
--========================
-- // Trayicon messages //
--========================
                                          r
Description: On a right click on the tray icon,
    present a popup menu that allows the user to

close the program
run configuration
run permanent items
switch permanent items
flush the clipboard history

}


procedure TfrmSysTrayMenu.WndProc(var Msg: TMessage);
begin
    // force a restore if explorer crashes
    if msg.Msg = self.WM_TASKBAR_CREATE  then begin
        self.ForceIconRestore := true;
        self.CreateTrayIcon;
        EXIT;
    end else begin
        inherited;
    end;
end;

var UpdatedOnce : boolean;
procedure TFrmSysTrayMenu.ShowTooltip;
begin
	if (assigned(tooltipnew)) and (not TooltipNew.myshowing) then begin
        if not UpdatedOnce then begin
            UpdatedOnce := true;
            self.ForceIconUpdate;
        end;


        TooltipNew.OnClick := self.TooltipClickEvent;
        TooltipNew.SmallFontOnce := true;
        TooltipNew.MaxWidth := frmConfig.UDToolWidth.Position;
        TooltipNew.MaxHeight := frmConfig.UDToolHeight.Position;
        TooltipNew.CloseOnLostFocus := true;

        UnitClipQueue.CurrentClipboard.GetClipboardItem(0);
        if FrmConfig.cbSystemTrayTooltip.Checked then begin
            TooltipNew.ShowTooltip(UnitClipQueue.CurrentClipboard,point(mouse.CursorPos.X+19,mouse.cursorpos.Y),
                'ArsClip v' + FrmAbout.lblversion.caption + '  ['+ pchar(frmconfig.GetHumanReadableHotkey)+']',
                'Click to Edit'
            );

        end else begin
            TooltipNew.ShowTooltip(UnitClipQueue.CurrentClipboard,point(mouse.CursorPos.X+19,mouse.cursorpos.Y),
                '  '+ pchar(frmconfig.GetHumanReadableHotkey) + '    ---    Click to Edit  '
            );
        end;

        TooltipNew.DodgePoint(mouse.CursorPos);
    end;
end;
procedure TFrmSysTrayMenu.CloseTooltip;
begin
	tooltipNew.Hide;

    timCloseTooltip.Enabled := false;
    timShowTooltip.Enabled  := false;

    lastmouseX := 0;
    lastmouseY := 0;
end;

procedure TFrmSysTrayMenu.WMTrayIcon(var Msg: TMessage);
    procedure ClickEvent(sender : Tobject);
    begin
        ShowMessage('hello!');
    end;
begin
    if disabled then EXIT;
    //
    // show Popup menu on a right click
    // show configuration form on a left double click
    // show/hide debug window on right double click
    //

    case msg.LParam of
    WM_LBUTTONDOWN : begin
        ignoreForeground := true;
    	self.notooltip := true;
        self.CloseTooltip;
        if (FrmConfig.cbPopupSingleclick.checked) then begin
            FrmMainPopup.ShowOnNextWindow;
        end else if (FrmConfig.cbPopupSingleclickTray.checked) then begin
            FrmMainPopup.ShowOnSystemTray;
        end else begin
        	//self.timCloseTooltip.Interval := 2000;
        	ShowTooltip;
        end;
        self.notooltip := false;
    end;

    WM_MOUSEMOVE: begin
    	if frmconfig.cbSystemTrayTooltip.Checked then begin
            lastmouseX := mouse.CursorPos.X;
            lastMouseY := mouse.CursorPos.y;

            if (not self.notooltip) and not FrmMainPopup.PopupIsShowing   then begin

                timShowTooltip.Enabled := true;
            end;
        end;
    end;
    WM_Rbuttondown : begin
        self.notooltip := true;
        self.CloseTooltip;
        self.ShowPopup;
        self.notooltip := false;
    end;
    WM_LBUTTONDBLCLK : begin
        self.notooltip := true;
        self.CloseTooltip;

        if (FrmConfig.cbPopupDoubleclick.checked) then begin
            FrmMainPopup.ShowOnNextWindow;
        end else if (FrmConfig.cbPopupDoubleclickTray.checked) then begin
            FrmMainPopup.ShowOnSystemTray;
        end else begin
            frmconfig.show();
            TFocusManager.ForceForeground(frmconfig.Handle);
        end;
        self.notooltip := false;

    end;
    WM_RBUTTONDBLCLK : begin
        FrmDebug.Show;
    end;
    end;
end;
procedure TfrmSysTrayMenu.timShowTooltipTimer(Sender: TObject);
const MOUSE_DIST = 16;

begin
	//timShowTooltip.Enabled := false;
    self.timCloseTooltip.Enabled := false;
    self.timCloseTooltip.Enabled := true;

    if (abs(mouse.CursorPos.x - lastmouseX) < MOUSE_DIST) and
		(abs(mouse.CursorPos.y - lastmouseY) < MOUSE_DIST) then begin

        //self.timCloseTooltip.interval := 1500;

        self.ShowTooltip;
    end else begin
        self.timCloseTooltip.Enabled := true;
        timShowTooltip.Enabled := false;

        ignoreForeground := False;
    end;



    //lastmousex := 0;
    //lastmousey := 0;
   
end;
procedure TfrmSysTrayMenu.timCloseTooltipTimer(Sender: TObject);
begin
    lastmousex := 0;
    lastmousey := 0;
    //tooltip.CloseTooltip;
   	self.CloseTooltip;

    timCloseTooltip.Enabled := false;
end;



procedure TfrmSysTrayMenu.TooltipClickEvent(sender: TObject);

begin
    self.CloseTooltip;
    {
    self.EditClipboardMenuItemClickEvent(sender);
    }
    Tooltipnew.Close;
    Application.ProcessMessages;

    frmEditTextExternal.EditClipboard;
end;




procedure TfrmSysTrayMenu.UpdateTrayIcon;
begin
    if not frmClipboardManager.GetMonitoring  then begin
        self.SetIconIgnore;
        EXIT;
    end;
    if assigned(frmconfig) then
        If (FrmConfig.cbDisableWhenScrollLock.checked) then begin
            if (KeyboardQuery.LockOn(VK_SCROLL)) then begin
                self.SetIconIgnore;
                EXIT;
            end;
        end;
    if self.CurrentIconIndex <> INDEX_NORMAL then begin
        self.SetIconNormal;
    end;

end;

procedure TFrmSysTrayMenu.ShowPopup(inmenu : TMenuItem);
var CursorPos : TPoint;
    menu: TMenuItem;
    submenu : TMenuItem;
    i : integer;
    s : string;
    procedure AddToPopup(item : TMenuItem);
    begin
        if (inmenu = nil) then begin
            TrayPopup.Items.Add(item);
        end else begin
            inmenu.Add(item);
        end;
    end;
begin
    if (self.PopupShowing) then EXIT;
    self.PopupShowing := true;
    {
    |=================|
    | Configure       |
    |-----------------|
    | Permenant Clips |
    | Switch to... |> |
    |-----------------|
    | Flush History   |
    | Edit History    |
    | Edit Clipboard..|
    |-----------------|
    | About           |
    | Exit            |
    |=================|
    }
    FrmDebug.AppendLog('WMTrayIcon right button ');

    if (inmenu = nil) then begin
        Windows.GetCursorPos(CursorPos);

        TrayPopup.Items.Clear;
        TrayPopup.AutoHotkeys := maAutomatic;
    end;

    MyFree(TrayPopup);
    if FrmConfig.GetOldTrayPopup then begin
        TrayPopup := TPopupMenu.Create(self);
    end else begin
        TrayPopup := TPopupActionBar.Create(self);
    end;

    traypopup.Images := ilPopupIcons;
    // for dynamically created popup, the image list isn't set yet
    // and must be forced

    menu := TMenuItem.Create(TrayPopup);
    menu.caption := '&Configure ...';
    menu.OnClick := self.ConfigureMenuItemClickEvent;
    menu.Bitmap := FrmMainPopup.imgA.Picture.Bitmap;
    //menu.Bitmap := nil;
    menu.ImageIndex := 0;

    //menu.hint := IntToStr(Integer(@FrmMainPopup.imgA));
    AddToPopup(menu);

    if not frmClipboardManager.IsNewClipboardAPI then begin
        menu := TMenuItem.Create(TrayPopup);
        menu.caption := '&Refresh Clipboard Monitoring';
        menu.OnClick := self.RefreshMenuItemClickEvent;
        menu.ImageIndex := -1;
        //menu.Bitmap := FrmMainPopup.imgA.Picture.Bitmap;
        AddToPopup(menu);
    end;


    menu := TMenuItem.Create(TrayPopup);
    menu.Caption := 'Edit Clips/Macros ...';
    menu.Bitmap := FrmMainPopup.imgEdit.Picture.Bitmap;
    menu.OnClick := self.EditHistoryMenuItemClickEvent;
    menu.ImageIndex := 3;

    AddToPopup(menu);
    AddToPopup(NewLine());

    menu := TMenuItem.Create(TrayPopup);
    menu.Caption := 'Clipboard Bar';
    menu.OnClick := nil;
    menu.Bitmap := FrmMainPopup.imgPaste.Picture.Bitmap;
    menu.ImageIndex := -1;
    submenu := TMenuItem.Create(TrayPopup);
    submenu.Caption := 'Bar Shown';
    if assigned(frmClipboardBar) then begin
        submenu.Checked := frmClipboardBar.IsVisible;
    end else begin
        submenu.checked := false;
    end;
    submenu.OnClick := self.ClipboardBarShow;
    menu.Add(submenu);
    submenu := TMenuItem.Create(TrayPopup);
    submenu.Caption := 'Bar Hidden';
    if assigned(frmClipboardBar) then begin
        submenu.Checked := not frmClipboardBar.IsVisible;
    end else begin
        submenu.checked := true;
    end;
    submenu.OnClick := self.ClipboardBarHide;
    menu.Add(submenu);
    AddToPopup(menu);






{
    if (inmenu = nil) then begin
        // switch to sub menu (checkmark current item)
        menu := TMenuItem.Create(TrayPopup);
        menu.Caption := 'Switch to Group     ';
        s := frmPermanent.GetPermanentPath;
        for i := 0 to frmPermanent.PermFoldersGetCount - 1 do begin
            if FrmPermanent.PermFolderIsSystem(i) then CONTINUE;

            submenu := TMenuItem.Create(menu);
            submenu.hint := frmPermanent.PermFoldersGetItem(i);
            submenu.caption := submenu.hint;
            if (submenu.Hint = s) then begin
                submenu.Checked := true;
            end;
            submenu.OnClick := self.SwitchPermFolder;
            //menu.Insert(i, submenu)
            menu.Add(submenu);
        end;
        AddToPopup(menu);
    end;

    AddToPopup(NewLine());
}


    menu := TMenuItem.Create(TrayPopup);
    menu.Caption := 'Edit Clipboard ...';
    menu.Bitmap := FrmMainPopup.imgPaste.Picture.Bitmap;
    menu.OnClick := self.EditClipboardMenuItemClickEvent;
    menu.ImageIndex := 4;

    AddToPopup(menu);

    submenu := TMenuItem.Create(TrayPopup);
    submenu.Caption := 'Flush';
    submenu.OnClick := nil;
    submenu.Bitmap := FrmMainPopup.imgFlush.Picture.Bitmap;
    submenu.ImageIndex := 2;
        menu := TMenuItem.Create(TrayPopup);
        menu.Caption := 'Flush Clipboard';
        menu.Bitmap := FrmMainPopup.imgFlush.Picture.Bitmap;
        menu.ImageIndex := 2;
        menu.OnClick := Self.FlushClipboard;
        submenu.Add(menu);
        submenu.Add(NewLine());
        menu := TMenuItem.Create(TrayPopup);
        menu.Caption := 'Flush Popup Clips';
        menu.Bitmap := FrmMainPopup.imgFlush.Picture.Bitmap;
        menu.OnClick := self.FlushPopupClipsClick;
        submenu.Add(menu);
        menu := TMenuItem.Create(TrayPopup);
        menu.Caption := 'Flush Removed Clips';
        menu.Bitmap := FrmMainPopup.imgFlush.Picture.Bitmap;
        menu.OnClick := self.FlushRemovedClips;
        submenu.Add(menu);
        submenu.Add(NewLine());
        menu := TMenuItem.Create(TrayPopup);
        menu.Caption := 'Flush All Clip History';
        menu.Bitmap := FrmMainPopup.imgFlush.Picture.Bitmap;
        menu.OnClick := self.FlushEverything;
        menu.ImageIndex := 2;
        submenu.Add(menu);
    AddToPopup(submenu);

    AddToPopup(NewLine());

    menu := TMenuItem.Create(TrayPopup);
    menu.caption := 'About';
    menu.OnClick := self.AboutClickEvent;
    AddToPopup(menu);

    menu := TMenuItem.Create(TrayPopup);
    menu.caption := 'Exit ArsClip';
    menu.OnClick := self.ExitMenuItemClickEvent;
    AddToPopup(menu);

    if (inmenu = nil) then begin
        FrmDebug.AppendLog('>>tray popup');
        Windows.SetForegroundWindow(FrmMainPopup.Handle);
        try
            TrayPopup.Popup(CursorPos.x+2, CursorPos.y-4);
        except
            // automagically catch and show the old popup on a crash
            if not FrmConfig.GetOldTrayPopup then begin
                FrmConfig.ForceOldTrayPopup;
                self.ShowPopup(inmenu);
            end;
        end;
        Windows.PostMessage(frmMainPopup.Handle, WM_NULL, 0, 0);
        FrmDebug.AppendLog('>>tray popup done');
    end;

    self.PopupShowing := false;
end;


{
  // menu item clicks
}


procedure TFrmSysTrayMenu.FlushPopupClipsClick(Sender : TObject);
begin
    ClipQueue.ClearQueue;
end;

procedure TFrmSysTrayMenu.RefreshMenuItemClickEvent(Sender : TObject);
begin
    frmClipboardManager.RefreshClipboardMonitor;
end;
procedure TFrmSysTrayMenu.ExitMenuItemClickEvent(Sender: TObject);
begin
    // End the program nicely
    frmMainPopup.Close;
end;

procedure TfrmSysTrayMenu.ClipboardBarHide(Sender: Tobject);
begin
    if assigned(frmClipboardBar) then begin
        frmClipboardBar.SetVisible(false);
    end;
end;
procedure TfrmSysTrayMenu.ClipboardBarShow(Sender: TObject);
begin
    if assigned(frmClipboardBar) then begin
        frmconfig.LoadClipboardBarState;
        frmClipboardBar.SetVisible(true);
    end;
end;

procedure TFrmSysTrayMenu.ConfigureMenuItemClickEvent(Sender : TObject);
begin
    Windows.SetForegroundWindow(frmConfig.Handle);
    frmConfig.Show;
end;
procedure TFrmSysTrayMenu.SwitchPermFolder(sender : TObject);
begin
    with sender as TMenuItem do begin
        frmPermanent.SetPermanentPath( hint );
    end;

    FrmMainPopup.ShowOnNextWindow(false);
    FrmPermanent.AssignPIG(frmmainpopup.GetTargetEXE);

    self.JustSwitched := true;
end;

procedure TfrmSysTrayMenu.timDisabledTimer(Sender: TObject);
begin
    self.ForceIconUpdate;
end;



procedure TfrmSysTrayMenu.EditClipboardMenuItemClickEvent(sender: TObject);
var

    current : string;
begin
    current := clipbrd.Clipboard.AsText;
    FrmEditTextExternal.EditClip(current);
end;

procedure TFrmSysTrayMenu.PermanentClipsMenuItemClickEvent(sender : TOBject);
begin
    frmEditHistory.ShowPermanent;
    TFocusManager.ForceForeground(frmEditHistory.Handle);
end;

procedure TFrmSysTrayMenu.EditHistoryMenuItemClickEvent(sender : TObject);
begin
    frmEditHistory.ShowPopup;
    TFocusManager.ForceForeground(frmEditHistory.Handle);
end;
procedure TFrmSysTrayMenu.RemovedItemsMenuItemClickEvent(sender : Tobject);
begin
    frmEditHistory.ShowRemoved;
    TFocusManager.ForceForeground(frmEditHistory.Handle);
end;

procedure TFrmSysTrayMenu.AboutClickEvent(sender : TObject);
begin
    //Windows.SetForegroundWindow(frmAbout.Handle);
    frmAbout.show;
    TFocusManager.ForceForeground(frmabout.Handle )
end;





function TfrmSysTrayMenu.GetIconTooltipText: string;
begin

    result := 'ArsClip v' + FrmAbout.lblversion.caption + #0;

    if assigned(FrmConfig) then begin
        if frmconfig.cbSystemTrayTooltip.Checked then begin
            result := #0;
        end;
    end;
end;
function TfrmSysTrayMenu.GetJustSwitched: boolean;
begin
    result := self.JustSwitched;
    self.JustSwitched := false;
end;

procedure TfrmSysTrayMenu.FlushTextNonTextClickEvent(Sender: TObject);
begin
	ClipQueue.ClearQueue;
end;
procedure TfrmSysTrayMenu.FlushClipboard(Sender: TObject);
begin
    frmClipboardManager.ClearClipboard;
end;
procedure TfrmSysTrayMenu.FlushEverything(Sender: TObject);
begin
    self.FlushTextNonTextClickEvent(self);
    ClickedClipQueue.ClearQueue;
    self.FlushClipboard(self);
    frmClipboardManager.ClearClipboard;
    FrmMainPopup.ClearCurrentLast;

    RemovedQueue.ClearQueue;
    //TempClipQueue.ClearQueue;
end;
procedure TfrmSysTrayMenu.FlushRemovedClips(Sender: TObject);
begin
    RemovedQueue.ClearQueue;
    //TempClipQueue.ClearQueue;
end;

end.
