anchor.diff:      FDBGrid : TDBGrid;
       FSortManager : ISortableDatasetManager;
       FGridIcons: TmGridIconsDataModule;
  +    FHeaderPopupMenu : TPopupMenu;
  +    FCurrentGridCol : longint;
  +    FGridPopupMenu : TPopupMenu;
  +    // original events
  +    FOriginalOnTitleClick : TDBGridClickEvent;
  +    FOriginalOnMouseDown : TMouseEvent;
       procedure OnTitleClick (Column: TColumn);
  +    procedure OnMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  +    procedure BuildHeaderPopupMenu;
     public
  -    constructor Create;
  +    constructor Create(aGrid : TDBGrid);
       destructor Destroy; override;
       function EditSettings : boolean;
       procedure LoadSettings (aStream : TStream);
       procedure SaveSettings (aStream : TStream);
       procedure EnableSort (aSortManager : ISortableDatasetManager);
  -
  -    property Grid : TDBGrid read FDBGrid write FDBGrid;
  +    procedure EnableHeaderPopupMenu (aGridPopupMenu : TPopupMenu);
  +
  +    property Grid : TDBGrid read FDBGrid;
     end;
   
   implementation
  
positive.code:   begin
      FGridIcons:= TmGridIconsDataModule.Create(FDBGrid);
      FDBGrid.TitleImageList := FGridIcons.GridImageList;
      FDBGrid.OnTitleClick:= Self.OnTitleClick;
      FSortManager:= aSortManager;
    end;
  end;
  
  end.
  
negative.code:   tmpSortConditions : TSortByConditions;
    i, idx : integer;
  begin
    try
      tmpSortType := stAscending;
  
      // remove every arrow from column captions
      for i := 0 to FDBGrid.Columns.Count - 1 do
        FDBGrid.Columns[i].Title.ImageIndex := -1;
  
      // analize current filter
      if (FSortManager.GetSorted) and (FSortManager.GetSortByConditions.Count > 0) and (FSortManager.GetSortByConditions.Items[0].FieldName = Column.FieldName) then
      begin
        if FSortManager.GetSortByConditions.Items[0].SortType = stAscending then
          tmpSortType:= stDescending
        else
        begin
          FSortManager.ClearSort;
          exit;
        end
      end;
  
      // set new sort condition
      FSortManager.GetSortByConditions.Clear;
      with FSortManager.GetSortByConditions.Add do
      begin
        FieldName:= Column.FieldName;
        SortType:= tmpSortType;
      end;
  
      // do sort
      if FSortManager.Sort then
      begin
        if tmpSortType = stAscending then
          idx := 0
        else
          idx := 1;
        FDBGrid.Columns[Column.Index].Title.ImageIndex := idx;
      end;
    finally
      if Assigned(FOriginalOnTitleClick) then
        FOriginalOnTitleClick(Column);
    end;
  end;
  
  procedure TmDBGridHelper.OnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  var
    tmpCol, tmpRow : longint;
  begin
    // https://www.codeproject.com/Articles/199506/Improving-Delphi-TDBGrid
    if Button = mbRight then
    begin
      if Y < FDBGrid.DefaultRowHeight then
      begin
         FDBGrid.PopupMenu := FHeaderPopupMenu;
         FDBGrid.MouseToCell(X, Y, tmpCol, tmpRow);
         FCurrentGridCol := tmpCol;
      end
      else
         FDBGrid.PopupMenu := FGridPopupMenu;
    end;
  
    if Assigned(FOriginalOnMouseDown) then
      FOriginalOnMouseDown(Sender, Button, Shift, X, Y);
  end;
  
  procedure TmDBGridHelper.BuildHeaderPopupMenu;
  var
    tmpMenuItem : TMenuItem;
  begin
    if not Assigned(FHeaderPopupMenu) then
    begin
      FHeaderPopupMenu:= TPopupMenu.Create(FDBGrid);
      tmpMenuItem := TMenuItem.Create(FHeaderPopupMenu);
      tmpMenuItem.Caption:= 'Filter values..';
      FHeaderPopupMenu.Items.Add(tmpMenuItem);
      tmpMenuItem := TMenuItem.Create(FHeaderPopupMenu);
      tmpMenuItem.Caption:= 'Add summary..';
      FHeaderPopupMenu.Items.Add(tmpMenuItem);
    end;
  end;
  
  constructor TmDBGridHelper.Create(aGrid : TDBGrid);
  begin
    FSettings := TmGridColumnsSettings.Create;
    FSortManager := nil;
    FDBGrid := aGrid;
  end;
  
  destructor TmDBGridHelper.Destroy;
  