unit siuBuscaObjetosBasicaPortal;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls,
  StdCtrls, DB, jvtypes, ituMain, utuMessage,
  XMLIntf, acuContainers,
  msxmldom, ExtCtrls,
  XMLDoc, CommCtrl, acuMenuManager, ActnList, ActnMenus, ActnMan,  CategoryButtons, ButtonGroup,
  Buttons, siuBuscaObjetos, ituUIController;

type

  TsiBuscaObjetosBasicaPortal = class(TsiBuscaObjetos)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    FPanelWarning: TPanel;
    FColumnsHint: TStringList;
    FUseCaseActions: acObjectList; //TMenuActionUseCase list, atribuido externamente;
    fMaxLinhas : Integer;
    fInterfaceController: itMain;
    fEntityCode: string;
    FActionID: string;
    FNomeBuscador: string;
    function GetNivel: integer;
    procedure SetUseCaseActions(const Value: acObjectList);
    procedure SetNomeBuscador(const Value: string);
    procedure ShowPanelWarning;
    procedure FrameResize(Sender: TObject);
  protected

    FMenuBuscador: TButtonGroup;
    procedure ClearListViewObj;
    procedure ClearViewPanel;
    procedure BuscaObjetos; virtual;
    procedure ResizeColumns; virtual;
    procedure PreencherMensagemBuscaObjetos(piMessage: mxMessage); virtual;
    procedure ChecarResultado(Dataset: TDataset);
    property InterfaceFromForm: itMain read fInterfaceController;
    function GetParamsDetailsRequest(piSuccessCallBackProcedure: itCallBackProcedure; piFailureCallBackProcedure: itCallBackProcedure = nil): acRequest;
    procedure setListViewObj(const Value: TListView); override;
    procedure MontaMenuBuscador;
  public
    { Public declarations }
    constructor Create(aowner:TComponent); overload; override;
    constructor Create(aowner:TComponent; piInterfaceController: itMain; piEntityCode: string); reintroduce; overload; override;
    destructor Destroy; override;

    procedure BuscaObjetosInicializacaoInterface; override;
    //Comportamento do ListView FListViewObj
    function GetItemAtX(piListView: TListView; var Col: integer): TListItem;
    procedure ListViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure ListViewMouseClick(Sender: TObject);
    procedure ListViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure ListViewGetSubItemImage(Sender: TObject; Item: TListItem; SubItem: Integer; var ImageIndex: Integer);
    procedure ListViewCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure ForceShowHint;
    //////////////////////////////////////

    procedure SortMethod(Sender: TObject; Column: Integer; var AMethod: TJvSortMethod); virtual;
    procedure GetInitInterface(piMessage: mxMessage); virtual;
    procedure Inicializar(piXML: string); overload; virtual;
    procedure Inicializar(piField: utField); overload; virtual;
    procedure SetParamsDetails(piField: utField); virtual;
    procedure Inicializa; virtual;

    property UseCaseActions: acObjectList read FUseCaseActions write SetUseCaseActions;

    property ViewPanel: TListView read FListViewObj;
    property MaxLinhas: Integer read fMaxLinhas write fMaxLinhas;
    property EntityCode: string read fEntityCode;
    property Nivel: integer read GetNivel;
    property ActionID: string read FActionID write FActionID;
    property NomeBuscador: string read FNomeBuscador write SetNomeBuscador;
    procedure PreencherGrid(piXML:string); overload; virtual;
    procedure PreencherGrid(piField:utField); overload; virtual;
    procedure SetLabelsInGrid(piNode: IXMLNode); overload; virtual;
    procedure SetLabelsInGrid(piField: utField); overload; virtual;
    function Version: integer; override;
    function NewRequest(piID: cardinal): mxRequestMessage;
  end;

implementation

{$R *.dfm}

uses acuObject;

procedure TsiBuscaObjetosBasicaPortal.ClearListViewObj;
var i: integer;
begin
  FListViewObj.Items.BeginUpdate;
  try
    if self.Version = 1 then
    begin
        for i := 0 to pred(FListViewObj.Items.Count) do
        begin
          TObject(FListViewObj.Items[i].Data).Free;
        end;
    end;
    FListViewObj.Items.Clear;
  finally
    FListViewObj.Items.EndUpdate;
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.ClearViewPanel;
begin

end;

procedure TsiBuscaObjetosBasicaPortal.Button1Click(Sender: TObject);
begin
  if self.Version = 1 then ClearListViewObj;
  self.BuscaObjetos;
end;

procedure TsiBuscaObjetosBasicaPortal.ChecarResultado(Dataset: TDataset);
begin
  if Dataset.RecordCount >= Maxlinhas then
     MessageDlg('Atenção: A consulta retorna mais de 100 registros.'
     + #13 +'Apenas os 100 primeiros registros serão exibidos,'
     + #13 + 'para obter resultados mais específicos mude os filtros da busca.'
     ,mtWarning, [mbOK], 0);
end;

constructor TsiBuscaObjetosBasicaPortal.Create(aowner: TComponent);
begin
  inherited;
  FColumnsHint := TStringList.Create;
  FUseCaseActions := nil;
  FListViewObj := TListView.Create(self);
  fListViewObj.ShowHint := true;
  fListViewObj.ViewStyle := vsReport;
//  FListViewObj.Align := alclient;
  fListViewObj.RowSelect := true;
  fListViewObj.ReadOnly := true;
  FListViewObj.OnCustomDrawSubItem := ListViewCustomDrawSubItem;
  FListViewObj.OnClick             := ListViewMouseClick;
  FListViewObj.OnMouseMove         := ListViewMouseMove;
  FListViewObj.OnGetSubItemImage   := ListViewGetSubItemImage;
  FListViewObj.OnCustomDrawItem    := ListViewCustomDrawItem;
  FListViewObj.HotTrack            := True;

  FListViewObj.DoubleBuffered := true;

  FMenuBuscador := TButtonGroup.Create(self);
  FMenuBuscador.ButtonOptions := [gboFullSize, gboShowCaptions];
  FMenuBuscador.BorderStyle := bsNone;
  FMenuBuscador.Align := alRight;
  FMenuBuscador.Width := 100;
  FMenuBuscador.Parent := self;

  FPanelWarning := TPanel.Create(self);
  FPanelWarning.Parent := FListViewObj;
  FPanelWarning.BorderStyle := bsNone;
  FPanelWarning.BevelOuter := bvNone;
  FPanelWarning.BevelInner := bvNone;
  FPanelWarning.Width := 300;
  FPanelWarning.height := 50;
  FPanelWarning.Color := $00996633;
  FPanelWarning.Font.Color := clwhite;
  FPanelWarning.Font.Size := 10;
  FPanelWarning.Caption := 'Nenhum registro encontrado';
  FPanelWarning.Hide;

  Self.OnResize :=  FrameResize;
end;

constructor TsiBuscaObjetosBasicaPortal.Create(aowner: TComponent; piInterfaceController: itMain; piEntityCode: string);
begin
  inherited;
  fMaxlinhas := 100;
  self.fInterfaceController := piInterfaceController;
  self.fEntityCode := piEntityCode;
  FListViewObj.SmallImages := fInterfaceController.IconList;
  FMenuBuscador.Images := fInterfaceController.IconList;
end;

destructor TsiBuscaObjetosBasicaPortal.Destroy;
begin
  FColumnsHint.Free;
  inherited;
end;

procedure TsiBuscaObjetosBasicaPortal.ForceShowHint;
begin
  Application.ActivateHint(mouse.cursorpos);
end;

procedure TsiBuscaObjetosBasicaPortal.FrameResize(Sender: TObject);
begin
  if (FPanelWarning.Visible) and (assigned(FPanelWarning.Parent)) then
  begin
    FPanelWarning.Left := (FListViewObj.Width div 2) - (FPanelWarning.Width div 2);
    FPanelWarning.Top := (FListViewObj.height div 2) - (FPanelWarning.height div 2);
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.SortMethod(Sender: TObject; Column: Integer; var AMethod: TJvSortMethod);
begin
  AMethod := smAutomatic;
end;

procedure TsiBuscaObjetosBasicaPortal.BuscaObjetosInicializacaoInterface;
var
  lMessage: mxRequestMessage;
begin
  lMessage := self.NewRequest(UM_GET_PARAMS_INICIALIZATION);
  lMessage.Fields.AddField('ENTITY').AsString := self.EntityCode;
  lMessage.Fields.AddField('ACTIONID').AsString := self.ActionID;
  self.GetInitInterface(lMessage);
  Self.InterfaceFromForm.PostMessage(lMessage);
end;

function TsiBuscaObjetosBasicaPortal.GetParamsDetailsRequest(piSuccessCallBackProcedure: itCallBackProcedure; piFailureCallBackProcedure: itCallBackProcedure = nil): acRequest;
begin
  Result := Self.InterfaceFromForm.NewRequest(UM_GET_PARAMS_DETAILS, piSuccessCallBackProcedure, piFailureCallBackProcedure);
  Result.Message.Fields.AddField('ENTITY').AsString := self.EntityCode;
  Result.Message.Fields.AddField('ACTIONID').AsString := self.ActionID;
end;

procedure TsiBuscaObjetosBasicaPortal.BuscaObjetos;
begin
  ClearListViewObj;
end;

procedure TsiBuscaObjetosBasicaPortal.Inicializar(piField: utField);
begin

end;

procedure TsiBuscaObjetosBasicaPortal.ListViewMouseClick(Sender: TObject);
var lCol: integer;
    lListItem: TListItem;
    lListView: TListView;
    lMenuAction: TMenuActionUseCase;
begin
  //Obtem qual item e qual coluna o usuário está clicnado
  lListView := sender as TListView;
  lListItem := GetItemAtX(lListView, lCol);
  if assigned(lListItem) then
    if lListView.Columns[lCol].Tag <> 0 then
    begin
      //Obtem os dados do caso de uso que será executado, previamente guardado na propriedade tag da coluna
      lMenuAction := TMenuActionUseCase(Pointer(lListView.Columns[lCol].Tag));
      //o Data do listitem possio o IDO do objeto
      lMenuAction.ExecuteObject(integer(lListItem.Data));
    end;
end;

procedure TsiBuscaObjetosBasicaPortal.ListViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var lCol: integer;
    lListItem: TListItem;
    lListView: TListView;
begin
  Application.HintPause := 100;
  lListView := Sender as TListView;
  lListView.Hint := '';
  lListItem := GetItemAtX(sender as TListView, lCol);
  if assigned(lListItem) then
  begin
    if lListView.Columns[lCol].Tag <> 0 then
    begin
      lListView.Hint := FColumnsHint[lCol];
      lListView.Cursor := crHandPoint;
      ForceShowHint;
    end
    else
    begin
      lListView.Cursor := crDefault;
    end;
  end
  else
  begin
    lListView.Cursor := crDefault;
   
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.MontaMenuBuscador;
var  lAction: TAction;
     lEnumUseCaseAction: acEnumerator;
     lButton: TGrpButtonItem;
begin
   if assigned(FUseCaseActions) then
    begin
      lEnumUseCaseAction := FUseCaseActions.GetEnumerator;;
      try
        while not lEnumUseCaseAction.EOL do
        begin
          case TMenuActionUseCase(lEnumUseCaseAction.current).ViewUseCaseType of
            mavMenu:
            begin
              lAction := TAction.Create(nil);
              lAction.Caption := TMenuActionUseCase(lEnumUseCaseAction.current).Name;
              lButton := TGrpButtonItem.Create(FMenuBuscador.Items);
              lButton.Action := lAction;
              lButton.ImageIndex := TMenuActionUseCase(lEnumUseCaseAction.current).IconCode;

//              lMenuItem := FMenuBuscador.AddMenuItem(nil, lAction);
              lAction.OnExecute := TMenuActionUseCase(lEnumUseCaseAction.current).ExecuteWithNullObject;
            end;
          end;
          lEnumUseCaseAction.MoveNext;
        end;
      finally
        lEnumUseCaseAction.Free;
      end;
    end;
end;

procedure TsiBuscaObjetosBasicaPortal.ListViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem;
  SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean);
var  lListView: TListView;
begin
  lListView := Sender as TListView;
//  lListView.Height := ((Item.DisplayRect(drBounds).Bottom - Item.DisplayRect(drBounds).Top) * lListView.Items.Count) + 40;  
  if lListView.Columns.Count > 1 then
    if lListView.Columns[SubItem].Tag <> 0 then
    begin
      lListView.Canvas.Font.Color := clBlue;
      lListView.Canvas.Font.Style := [fsUnderline];
    end;
end;

procedure TsiBuscaObjetosBasicaPortal.ListViewGetSubItemImage(Sender: TObject; Item: TListItem; SubItem: Integer;
  var ImageIndex: Integer);
  var lListView: TListView;
      lMenuAction: TMenuActionUseCase;
begin
  lListView := Sender as TListView;
  if lListView.Columns[SubItem + 1].Tag <> 0 then
  begin
    lMenuAction := TMenuActionUseCase(pointer(lListView.Columns[SubItem + 1].Tag));
    ImageIndex := lMenuAction.IconCode;
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.ListViewCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  inherited;
  if Odd(Item.Index) then
    begin
//      sender.Canvas.Font.Color  := clBlack;
      sender.Canvas.Brush.Color := $00F0F0F0;
    end
    else
    begin
//      sender.Canvas.Font.Color  := clBlack;
      sender.Canvas.Brush.Color := clWhite;
    end;
end;

procedure TsiBuscaObjetosBasicaPortal.Inicializar(piXML: string);
begin

end;

procedure TsiBuscaObjetosBasicaPortal.PreencherGrid(piField: utField);
var
  ListItem: TListItem;
  lEnum: acEnumerator;
  lField: utField;
  lAttributeEnum: acEnumerator;
  lEnumUseCaseAction: acEnumerator;
  lMenuAction: TMenuActionUseCase;
  lObjectsField: utField;
  lObjectsFound, lObjectsReturned: Integer;
begin
  ClearListViewObj;
  try
    if piField.HasField('Objects') then
    begin
      lObjectsField := piField.FieldByName('Objects');
      if lObjectsField.HasAttribute('Found') and lObjectsField.HasAttribute('Returned') then
      begin
        lObjectsFound := lObjectsField.AttributeByName('Found').AsInteger;
        lObjectsReturned := lObjectsField.AttributeByName('Returned').AsInteger;
        if lObjectsReturned < lObjectsFound then
        begin
          Application.MessageBox(PCHAR(Format('%d itens foram encontrados, entretanto apenas os %d primeiros serão mostrados. Seja mais específico na busca.',[lObjectsFound, lObjectsReturned])), 'Atenção', MB_ICONEXCLAMATION);
        end;
      end;

      FPanelWarning.Hide;
      self.ListViewObj.Items.BeginUpdate;
      try
        lEnum := lObjectsField.GetFieldsEnumerator;
        try
          if not lEnum.EOL then
          begin
            while not lEnum.EOL do
            begin
              if self.ListViewObj.Columns.Count = 0 then self.SetLabelsInGrid(piField);
              lField := utField(lEnum.Current);
              ListItem := self.ListViewObj.Items.Add;
              ListItem.ImageIndex := -1;
              lAttributeEnum := lField.GetAttibutesEnumerator;
              try
                if not lAttributeEnum.EOL then
                begin
                  if utAttribute(lAttributeEnum.Current).Name <> 'OID' then Raise Exception.Create('IDO do objeto não encontrado.');
                  ListItem.Data := pointer(strtoint(utAttribute(lAttributeEnum.Current).AsString));
                  lAttributeEnum.MoveNext;
                end;
                if not lAttributeEnum.EOL then
                begin
                  ListItem.Caption := utAttribute(lAttributeEnum.Current).AsString;
                  lAttributeEnum.MoveNext;
                end;
                while not lAttributeEnum.EOL do
                begin
                  ListItem.SubItems.Add(utAttribute(lAttributeEnum.Current).AsString);
                  lAttributeEnum.MoveNext;
                end;
              finally
                lAttributeEnum.Free;
              end;

              if assigned(FUseCaseActions) then
              begin
                //Colunas utilizadas para disparar caso de uso
                lEnumUseCaseAction := FUseCaseActions.GetEnumerator;
                try
                  while not lEnumUseCaseAction.EOL do
                  begin
                    lMenuAction := TMenuActionUseCase(lEnumUseCaseAction.current);
                    if lMenuAction.ViewUseCaseType = mavList then
                      //ListItem.SubItems.Add(lMenuAction.Name);
                      ListItem.SubItems.Add('');
                    lEnumUseCaseAction.MoveNext;
                  end;
                finally
                  lEnumUseCaseAction.Free;
                end;
              end;
              lEnum.MoveNext;
            end;
          end
          else
            ShowPanelWarning;
        finally
          lEnum.Free;
        end;
      finally
        self.ListViewObj.Items.EndUpdate;
      end;
    end;
  finally
    self.ResizeColumns;
    Screen.Cursor := crDefault;
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.PreencherGrid(piXML: string);
var
  lXMLDocumento: TXMLDocument;
  lIXMLDocumento: IXMLDocument;
  lUserNode: IXMLNode;
  li, lj: integer;
  ListItem: TListItem;
begin
  ClearListViewObj;
  lXMLDocumento := TXMLDocument.Create(nil);
  lXMLDocumento.DOMVendor := MSXML_DOM;
  lIXMLDocumento := lXMLDocumento;
  lIXMLDocumento.LoadFromXML(piXML);
  lIXMLDocumento.Active := True;
  try
    if not lIXMLDocumento.IsEmptyDoc then
    begin
      if lIXMLDocumento.DocumentElement.HasChildNodes then
      begin
        if self.ListViewObj.Columns.Count = 0 then
        begin
          if lIXMLDocumento.DocumentElement.ChildNodes.Count > 0 then
          begin
            self.SetLabelsInGrid(lIXMLDocumento.DocumentElement);
          end;
        end;
        self.ListViewObj.Items.BeginUpdate;
        try
          for li := 0  to lIXMLDocumento.DocumentElement.ChildNodes.Count - 1 do
          begin
            if lIXMLDocumento.DocumentElement.ChildNodes[li].NodeName <> 'Labels' then
            begin
              lUserNode := lIXMLDocumento.DocumentElement.ChildNodes[li];
              ListItem := self.ListViewObj.Items.Add as TListItem;
              if self.ListViewObj.Columns.Count >= 2 then
              begin
                ListItem.Caption := lUserNode.AttributeNodes[1].Text;
                for lj := 2 to  pred(lUserNode.AttributeNodes.Count) do
                begin
                  ListItem.SubItems.Add(lUserNode.AttributeNodes[lj].Text);
                end;
              end;
              if not lUserNode.HasAttribute('OID') then Raise Exception.Create('IDO do objeto não encontrado.');
              ListItem.Data := pointer(strtoint(lUserNode.Attributes['OID']));
            end;
          end;
        finally
          self.ListViewObj.Items.EndUpdate;
        end;
      end;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.SetLabelsInGrid(piField: utField);
var lEnum: acEnumerator;
    lAttributeEnum, lEnumUseCaseAction: acEnumerator;
    lListColumn: TListColumn;
begin
  LockWindowUpdate(self.ListViewObj.handle);
  self.ListViewObj.Items.BeginUpdate;
  try
    self.ListViewObj.Columns.Clear;
    begin
      if piField.HasField('Objects') then
      begin
        lEnum := piField.FieldByName('Objects').GetFieldsEnumerator;
        try
          if not lEnum.EOL then
          begin
            lAttributeEnum := utField(lEnum.Current).GetAttibutesEnumerator;
            try
              if not lAttributeEnum.EOL then lAttributeEnum.MoveNext; // Ignora attributo OID que e sempre o primeiro
              while not lAttributeEnum.EOL do
              begin
                lListColumn := Self.ListViewObj.Columns.Add;
                lListColumn.Caption := utField(lAttributeEnum.Current).Name;
                lListColumn.ImageIndex := -1;
                FColumnsHint.Add('');
                lAttributeEnum.MoveNext;
              end;
            finally
              lAttributeEnum.Free;
            end;
          end;
        finally
          lEnum.Free
        end;
      end;

      if assigned(FUseCaseActions) then
      begin
        lEnumUseCaseAction := FUseCaseActions.GetEnumerator;;
        try
          while not lEnumUseCaseAction.EOL do
          begin
            case TMenuActionUseCase(lEnumUseCaseAction.current).ViewUseCaseType of
              mavList:
              begin
                lListColumn := Self.ListViewObj.Columns.Add;
//                lListColumn.Caption := TMenuActionUseCase(lEnumUseCaseAction.current).Name;
                FColumnsHint.Add(TMenuActionUseCase(lEnumUseCaseAction.current).Hint);
                //Utiliza a tag da coluna como ponteiro, guardando qual o caso de uso que será executado
                //ao clicar em um item desta coluna
                lListColumn.Tag := integer(TMenuActionUseCase(lEnumUseCaseAction.current));
                lListColumn.ImageIndex := -1;
              end;
            end;
            lEnumUseCaseAction.MoveNext;
          end;
          Self.ListViewObj.Columns.Add;
        finally
          lEnumUseCaseAction.Free;
        end;
      end;
    end;
  finally
    self.ListViewObj.Items.EndUpdate;
    LockWindowUpdate(0);
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.setListViewObj(const Value: TListView);
begin
  Self.OnResize := nil;
  FPanelWarning.Parent := nil;
  if assigned(FListViewObj) then FListViewObj.free;

  FListViewObj := Value;
  FPanelWarning.DoubleBuffered := true;
  FPanelWarning.Parent := FListViewObj;
  Self.OnResize :=  FrameResize;
end;

procedure TsiBuscaObjetosBasicaPortal.SetNomeBuscador(const Value: string);
begin
  FNomeBuscador := Value;
end;

procedure TsiBuscaObjetosBasicaPortal.SetParamsDetails(piField: utField);
begin

end;

procedure TsiBuscaObjetosBasicaPortal.SetUseCaseActions(const Value: acObjectList);
begin
  FUseCaseActions := Value;
  MontaMenuBuscador;
end;

procedure TsiBuscaObjetosBasicaPortal.ShowPanelWarning;
begin
  FPanelWarning.Left := (FListViewObj.Width div 2) - (FPanelWarning.Width div 2);
  FPanelWarning.Top := (FListViewObj.height div 2) - (FPanelWarning.height div 2);
  FPanelWarning.Show;
end;

procedure TsiBuscaObjetosBasicaPortal.SetLabelsInGrid(piNode: IXMLNode);
var
  lLabels: IXMLNode;
  li: integer;
begin
  self.ListViewObj.Columns.Clear;
  if assigned(piNode.ChildNodes.FindNode('Labels')) then
  begin
    lLabels := piNode.ChildNodes.Nodes['Labels'];
    for li := 0 to Pred(lLabels.ChildNodes.Count) do
    begin
      Self.ListViewObj.Columns.Add.Caption := lLabels.ChildNodes.Nodes[li].NodeName;
    end;
  end
  else
  begin
    lLabels := piNode.ChildNodes[0];
    for li := 1 to Pred(lLabels.AttributeNodes.Count) do
    begin
      Self.ListViewObj.Columns.Add.Caption := lLabels.AttributeNodes[li].NodeName;
    end;
  end;
  Self.ResizeColumns;
end;

procedure TsiBuscaObjetosBasicaPortal.GetInitInterface(piMessage: mxMessage);
begin

end;

function TsiBuscaObjetosBasicaPortal.GetItemAtX(piListView: TListView; var Col: integer): TListItem;
var
  pt: TPoint;
  hittestinfo: TLVHitTestInfo;
begin
  Col := -1;
  result := nil;
  pt := piListView.ScreenToClient( mouse.cursorpos );
  FillChar( hittestinfo, sizeof( hittestinfo ), 0 );
  hittestinfo.pt := pt;
  If -1 <> piListView.perform( LVM_SUBITEMHITTEST, 0, lparam(@hittestinfo)) Then
  begin
    col := hittestinfo.iSubItem;
    result := piListView.items[hittestinfo.iItem];
  end;

  if not assigned(result) then
  begin
    result := piListView.GetItemAt( pt.x, pt.y );
    If assigned(result)  then Col := 0;
  end;end;

procedure TsiBuscaObjetosBasicaPortal.PreencherMensagemBuscaObjetos(piMessage: mxMessage);
begin
  if not piMessage.Fields.HasField('ENTITY') then
    piMessage.Fields.AddField('ENTITY').AsString := self.EntityCode;
  piMessage.Fields.AddField('ACTIONID').AsString := self.ActionID;
end;

procedure TsiBuscaObjetosBasicaPortal.ResizeColumns;
var li: integer;
begin
  if self.ListViewObj.Columns.Count > 0 then
  begin
    Self.ListViewObj.Items.BeginUpdate;
    try
      for li := pred(self.ListViewObj.Columns.Count) downto 0 do
      begin
        Self.ListViewObj.Columns.Items[li].Width := -2;
      end;
    finally
      self.ListViewObj.Columns[0].Width := self.ListViewObj.Columns[0].Width + 20;
      Self.ListViewObj.Items.EndUpdate;
    end;
  end;
end;

procedure TsiBuscaObjetosBasicaPortal.Inicializa;
begin
end;

function TsiBuscaObjetosBasicaPortal.Version: integer;
begin
  Result := 4;
end;

function TsiBuscaObjetosBasicaPortal.GetNivel: integer;
begin
  result := fInterfaceController.Level;
end;

function TsiBuscaObjetosBasicaPortal.NewRequest(piID: cardinal): mxRequestMessage;
begin
  result := mxRequestMessage.Create(piID, Self.InterfaceFromForm.UseCaseAddress, Self.InterfaceFromForm.Address);
end;

end.
