unit ULBrowu;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, Grids,
  PropUtl, UlanGlob, UlanType, MyType,
  ULRecTyp, ULRecUtl, ULObju, ULObjDes, ExtCtrls, Menus
  {v0.13},TVType, ShowMsg{/v0.13}
  {$IFDEF DEBUG} ,DebugFrm{$ENDIF}
  {v0.18},Clipbrd, strgrdex{/v0.18};

type
  TBrowseForm = class(TForm)
    Grid: TStringGridEx;
    Panel: TPanel;
    NewRecBtn: TBitBtn;
    EditRecBtn: TBitBtn;
    DelRecBtn: TBitBtn;
    PgDnBtn: TBitBtn;
    DownBtn: TBitBtn;
    UpBtn: TBitBtn;
    PgUpBtn: TBitBtn;
    FirstRecBtn: TBitBtn;
    PopupMenu: TPopupMenu;
    a1: TMenuItem;
    AllDetailsCheckBox: TCheckBox;
    InternalValuesCheckBox: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure GridEnter(Sender: TObject);
    procedure GridClick(Sender: TObject);
    procedure EditRecBtnClick(Sender: TObject);
    procedure NewRecBtnClick(Sender: TObject);
    procedure a1Click(Sender: TObject);
    procedure DelRecBtnClick(Sender: TObject);
    procedure GridKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure GridGetEditText(Sender: TObject; ACol, ARow: Integer;
      var Value: String);
    procedure GridSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure GridSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure GridExit(Sender: TObject);
    procedure AllDetailsCheckBoxClick(Sender: TObject);
    procedure InternalValuesCheckBoxClick(Sender: TObject);
    procedure GridMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
    FObj: TULObj;
    FCurChild: TULObj;
      { Currently selected child (row) }
    FModified: boolean;
    LCol, LRow:integer;
    LRecID: TULRecID;
      { what was the last active record's id (for redrawing captions) }
    IsInHandleCommand:boolean;

    FLastEditCol, FLastEditRow: integer;
    FLastEditChild: TULObj;
    FLastEditValue: string;

    FSavingText: boolean;
    FAddingChild: boolean;
{    FDeletingChild: boolean;}
    FEditEnabled: boolean;
    FMaxColWidths: TULBrowseColWidths;
    FMaxColCaptionWidths: TULBrowseColWidths;
    FFixedRows: integer;
    FFixedCols: integer;
    FInternalValues: boolean;
    procedure WMCommand(var Msg:TWMCommand);message WM_COMMAND;
  protected
    procedure MenuItemClick(Sender: TObject);
    procedure WMAppMessage(var Msg: TMessage); message WM_APPMESSAGE;
    procedure SaveText(AChild: TULObj; ACol,ARow:integer; const Value:string);
    procedure CheckSaveText(ACol, ARow:integer; const Value: string);
    procedure SetBrowseMode(bm:TULBrowseMode);
    {v0.18}
    procedure GridSelToObj{UpdateSelection};{called (e.g. before copy to clipboard) to
      reflect grid's selected region to FObj.Childs }
    {/v0.18}
  public
    { Public declarations }
    procedure UpdateGrid;
    function HandleCommand(cm: integer):boolean;
    procedure AddNewRec(i:integer);
      { Create new child record of RecID that has index
        in allowed child RecIDs array = i }
    procedure NewRec;
    function EditRec: integer;
    procedure DelRec;
  end;

var
  BrowseForm: TBrowseForm;

const
  ULBrowDebLog: boolean = true;
implementation

{$R *.DFM}

procedure TBrowseForm.FormCreate(Sender: TObject);
var
  s: string;
  i: integer;
  {v0.13}
  o: TULObj;
  {/v0.13}
begin
  FObj := {ulobju.}CurULObj;
  if FObj = nil then
    raise EEmptyCurULObj.Create('TBrowseForm.FormCreate');
  FObj.UserRegister(Self);
  {v0.13}
  s := FObj.ObjDesc.Caption;
  o := TULObj(FObj.Owner);
  while (o <> nil) and (o is TULObj) do begin
    if o.RecID = ULFID then
      s := o.RelFileName + ':' + s
    else
      s := o.ObjDesc.Caption + '\' + s;
    o := TULObj(o.Owner);
  end;
  {/v0.13
  s := FObj.ObjDesc.Caption;
  if FObj.RecID = ULFID then
    s := s + ' ' + FObj.FileName;}
  FFixedRows := Grid.FixedRows;
  FFixedCols := Grid.FixedCols;
  Caption := s;
  CurULObj := nil;
  FModified := true;
  LRow := -1;
  LCol := -1;
  FLastEditCol:= -1;
  FLastEditRow:= -1;
  LRecID := 0;
  for i := low(FMaxColCaptionWidths) to high(FMaxColCaptionWidths) do
    FMaxColCaptionWidths[i] :=  Canvas.TextWidth('MMMM');
  if UserMode = umSysOp then begin
    FEditEnabled := true;
    InternalValuesCheckBox.Visible := true;
    Grid.Options := Grid.Options + [goEditing];
  end else begin
    FEditEnabled := false;
    InternalValuesCheckBox.Visible := false;
  end;
  FInternalValues := InternalValuesCheckBox.Checked;
  FModified := true;
  UpdateGrid;
end;

procedure TBrowseForm.SetBrowseMode(bm:TULBrowseMode);
begin
  if FObj.ChildWithFlagFirst(rfVisible) then
  repeat
    FObj.ActiveChild.ObjDesc.BrowseMode := bm;
  until not FObj.ChildWithFlagNext(rfVisible);
  FModified := true;
  LRecID := 0;
  UpdateGrid;
end;

procedure TBrowseForm.UpdateGrid;
var
  childCnt, rowCnt: integer;
  o: TULObj;
  oi: TULObjDesc;
  curind, i, j, ind: integer;
{  n: shortstring;
  v: AnsiString;}
  curChildSet:boolean;
  maxfldcnt:integer;

  curcol, currow, w: integer;
  widthChanged:boolean;
begin
  if FObj = nil then
    exit;
  maxfldcnt := 0;
  widthChanged := false;

  childCnt := FObj.ChildWithFlagCount(rfVisible);
  rowCnt := Grid.RowCount - FFixedRows;

  curind := Grid.Row - FFixedRows;
  curChildSet := false;

  if (rowCnt <> childCnt) or FModified then begin

    if AutoSizeBrowseCols then
      FMaxColWidths := FMaxColCaptionWidths;
    LCol := -1;
      { .. force updating of header }
    if rowCnt <> childCnt then begin
      if childCnt = 0 then begin
        Grid.RowCount := 0;
      end else begin
        Grid.RowCount := childCnt + FFixedRows;
        Grid.FixedRows := FFixedRows;
      end;
    end;

    i := 0;

    if FObj.ChildWithFlagFirst(rfVisible) then
    begin
      { scan all child records: }
      repeat
        o := FObj.ActiveChild;
        oi := o.ObjDesc;
        if oi.BrowseFieldCount + FFixedCols > Grid.ColCount then begin
          { make sure that there is enough of columns for all childs: }
          Grid.ColCount := oi.BrowseFieldCount + FFixedCols;
          Grid.FixedCols := FFixedCols;
        end else begin
          { find out what is the maximal number of childs' fields }
          if oi.BrowseFieldCount > maxfldcnt then
            maxfldcnt := oi.BrowseFieldCount;
        end;
        currow := i + FFixedRows;
        {v0.20}
        Grid.SetSelectRow(currow, o.IsFlagSet(rfSelected));
        {/v0.20}

        for j := 0 to oi.BrowseFieldCount - 1 do begin
          { scan all fields of current row child: }
          ind := oi.BrowseFields[j].ULIndex;
          curcol := j + FFixedCols;

          if (curcol <> FLastEditCol) or (currow <> FLastEditRow) or
             (FLastEditChild <> o)
          then begin
            {.. do not disturb eventually changing call value }
            if FInternalValues then begin
              Grid.Cells[curcol, currow] := trim(o.Fields[ind].Value);
            end else begin
              Grid.Cells[curcol, currow] := trim(o.Fields[ind].UsrValue);
            end;
          end;

          if AutoSizeBrowseCols then begin
            if curcol < MaxULBrowseCols then begin
              w := Canvas.TextWidth(Grid.Cells[curcol, currow]+'  ');
              if w > FMaxColWidths[curcol] then begin
                FMaxColWidths[curcol] := w;
                widthChanged := true;
              end;
            end;
          end;

        end;

        if FFixedCols > 0 then begin
          {v0.09}
          if FInternalValues then begin
            Grid.Cells[0, currow] := trim(o.RecIDStr);
          end else
          {/v0.09}
          begin
            Grid.Cells[0, currow] := trim(oi.Caption);
          end;

          if AutoSizeBrowseCols then begin
            w := Canvas.TextWidth(Grid.Cells[0, currow]+'  ');
            if w > FMaxColWidths[0{curcol}] then begin
              FMaxColWidths[0{curcol}] := w;
              FMaxColCaptionWidths[0] := w;
              widthChanged := true;
            end;
          end;

        end;

        if i = curind then begin
          curChildSet := true;
          FCurChild := o;
        end;
        inc(i);
      until not FObj.ChildWithFlagNext(rfVisible);
    end else begin
      { no childs: }
      FCurChild := nil;
      LRecID := 0;
      Grid.RowCount := 0;
      {if Grid.RowCount > 0 then begin
        for j := 0 to Grid.ColCount - 1 do
          Grid.Cells[j, 0] := '';
      end;}
    end;

    if AutoSizeBrowseCols then begin
      if (maxfldcnt + FFixedCols) < Grid.ColCount then begin
        if maxfldcnt = 0 then begin
          Grid.ColCount := 0;
        end else begin
          Grid.ColCount := maxfldcnt + FFixedCols;
          Grid.FixedCols := FFixedCols;
        end;
      end;
    end;

    {if i <> Grid.RowCount then
      raise EULBrowse.Create('ULBrowse row/child count mismatch ' +
        IntToStr(i) + ' x ' + IntToStr(Grid.RowCount));}

    {
    while i < rowCnt do begin
      for j := Grid.FixedCols to Grid.ColCount - 1 do begin
        Grid.Cells[j, i + Grid.FixedRows] := '';
      end;
      if Grid.FixedCols > 0 then
        Grid.Cells[0, i + Grid.FixedRows] := '';
      inc(i);
    end;
    }
  end;

  if (LCol <> Grid.Col) or (LRow <> Grid.Row) {v0.10} or FModified{/v0.10} then
  begin
    if (childCnt > 0) and (curind < childCnt) then begin

      if not curChildSet then begin
        i := 0;
        if FObj.ChildWithFlagFirst(rfVisible) then
        repeat
          if i = curind then
            break;
          inc(i);
        until not FObj.ChildWithFlagNext(rfVisible);
        FCurChild := FObj.ActiveChild;
      end;

      if (LRecID <> FCurChild.RecID) {v0.10}or FModified{/v0.10} then begin
        oi := FCurChild.ObjDesc;
        if oi.BrowseFieldCount + FFixedCols > Grid.ColCount then begin
          Grid.ColCount := oi.BrowseFieldCount + FFixedCols;
          Grid.FixedCols := FFixedCols;
        end;
        j := 0;
        while j < oi.BrowseFieldCount do begin
          curcol := j + FFixedCols;
          if FInternalValues then begin
            Grid.Cells[curcol, 0] := trim(oi.BrowseFields[j].Name);
          end else begin
            Grid.Cells[curcol, 0] := trim(oi.BrowseFields[j].Caption);
          end;

          if AutoSizeBrowseCols then begin
            w := Canvas.TextWidth(Grid.Cells[curcol, 0]+'  ');
            if w > FMaxColWidths[curcol] then begin
              FMaxColWidths[curcol] := w;
              FMaxColCaptionWidths[curcol] := w;
              widthChanged := true;
            end;
          end;

          inc(j);
        end;

        j := oi.BrowseFieldCount + FFixedCols;
        while j < Grid.ColCount do begin
          Grid.Cells[j, 0] := '';
          inc(j);
        end;
        LRecID := FCurChild.RecID;
      end;

    end else begin
      FCurChild := nil;
      LRecID := 0;
    end;
    LCol := Grid.Col;
    LRow := Grid.Row;
    {Invalidate;}
  end;

  if AutoSizeBrowseCols and widthChanged then begin
    for j := 0 to Grid.ColCount - 1 do begin
      w := FMaxColWidths[j];
      if w <> 0 then
        Grid.ColWidths[j] := w;
    end;
  end;
end;

{v0.18}
procedure TBrowseForm.GridSelToObj;{UpdateSelection;}
var
  o: TULObj;
  i: integer;
  currow: integer;
begin
  if FObj = nil then
    exit;
  if FObj.ChildWithFlagFirst(rfVisible) then
  begin
    { scan all child records: }
    i := 0;
    FObj.DoChangeLock;
    repeat
      o := FObj.ActiveChild;
      currow := i + FFixedRows;
      {v0.20}
      o.SetFlag(rfSelected, Grid.GetSelectRow(currow));
      {/v0.20
      o.SetFlag(rfSelected, (currow >= Grid.Selection.Top) and (currow <= Grid.Selection.Bottom));}
      inc(i);
    until not FObj.ChildWithFlagNext(rfVisible);
    FObj.DoChangeUnlock;
  end;
end;
{/v0.18}

procedure TBrowseForm.GridEnter(Sender: TObject);
begin
  UpdateGrid;
end;

procedure TBrowseForm.GridClick(Sender: TObject);
begin
  UpdateGrid;
end;

procedure TBrowseForm.EditRecBtnClick(Sender: TObject);
begin
  EditRec;
end;

procedure TBrowseForm.NewRecBtnClick(Sender: TObject);
begin
  NewRec;
end;

procedure TBrowseForm.NewRec;
var
 i: integer;
 r: TULRecID;
 rd: PULRecDesc;
 mi: TMenuItem;
begin
  if FObj = nil then
    exit;
  if FObj.ObjDesc.ChildRecIDCount = 0 then
    exit;
  if FObj.ObjDesc.ChildRecIDCount = 1 then begin
    r := FObj.ObjDesc.ChildRecIDs[0];
    rd := FObj.GetULRecDescOf(r);
    if (rd = nil) or ((rd^.Flags and rfVisible) <> 0) then
      AddNewRec(0);
  end else begin
    while PopupMenu.Items.Count > 0 do begin
      PopupMenu.Items[PopupMenu.Items.Count - 1].Free;
    end;
    for i := 0 to FObj.ObjDesc.ChildRecIDCount - 1 do begin
      r := FObj.ObjDesc.ChildRecIDs[i];
      rd := FObj.GetULRecDescOf(r);
      if (rd = nil) or ((rd^.Flags and rfVisible) <> 0) then begin
        mi := TMenuItem.Create(Self);
        if rd = nil then
          mi.Caption := ULRecIDToStr(r)
        else
          mi.Caption := rd^.Caption;
        mi.OnClick := MenuItemClick;
        PopupMenu.Items.Add(mi);
      end;
    end;
    PopupMenu.Popup(Left + NewRecBtn.Left, Top + NewRecBtn.Top + NewRecBtn.Height);
  end;
end;

function TBrowseForm.HandleCommand(cm: integer):boolean;
var i:integer;
begin
  Result := false;
  if IsInHandleCommand then
    exit;
  try
    IsInHandleCommand := true;
    for i := 0 to PopupMenu.Items.Count - 1 do begin
      if cm = PopupMenu.Items[i].Command then begin
        AddNewRec(i);
        Result := true;
        break;
      end;
    end;
  finally
    IsInHandleCommand := false;
  end;
end;

procedure TBrowseForm.WMCommand(var Msg:TWMCommand);
begin
 if not HandleCommand(Msg.ItemID) then
   inherited;
end;

procedure TBrowseForm.WMAppMessage(var Msg: TMessage);
begin
  case Msg.wParam of

    cmULObjCanDestroy: begin
      if TULObj(Msg.lParam) = FObj then
        Msg.Result := 1;
    end;

    cmULObjUpdated: begin
      if (TULObj(Msg.lParam) = FObj) then
      begin
        if (not FSavingText) and (not FAddingChild){ and (not FDeletingChild)} then begin
          UpdateGrid;
        end;
      end;
    end;

    cmULObjBrowseFormBringToFront: begin
      if (TULObj(Msg.lParam) = FObj) then
      begin
        Msg.Result := 1;
        BringToFront;
      end;
    end;

    cmULObjAfterEdit: begin

    end;

    cmULObjDestroyed: begin
      if TULObj(Msg.lParam) = FObj then begin
        FObj := nil;
        FCurChild := nil;
        Release;
      end;
    end;
    {v0.18}
    cmClipCopy: begin
      if FObj <> nil then begin
        GridSelToObj;{UpdateSelection;}
        Clipboard.Assign(FObj);{.CopyToClipboard;}
      end;
    end;
    cmClipPaste: begin
      if FObj <> nil then begin
        FObj.Assign(Clipboard);{CopyFromClipboard;}
        UpdateGrid;
      end;
    end;
    cmClipCut: begin
      if FObj <> nil then begin
        GridSelToObj;{UpdateSelection;}
        Clipboard.Assign(FObj);{.CopyToClipboard;}
        FObj.ChildsDelete(0, rfSelected);
        UpdateGrid;
      end;
    end;
    {v0.18}
  end;
end;

procedure TBrowseForm.a1Click(Sender: TObject);
begin
  HandleCommand(TMenuItem(Sender).Command);
end;

procedure TBrowseForm.MenuItemClick(Sender: TObject);
begin
  HandleCommand(TMenuItem(Sender).Command);
end;

procedure TBrowseForm.AddNewRec(i: integer);
var
  cnt, j: integer;
  r: TULRecID;
  rd: PULRecDesc;
begin
  if FObj = nil then
    exit;
  cnt := 0;
  for j := 0 to FObj.ObjDesc.ChildRecIDCount - 1 do begin
    r := FObj.ObjDesc.ChildRecIDs[j];
    rd := FObj.GetULRecDescOf(r);
    if (rd = nil) or ((rd^.Flags and rfVisible) <> 0) then begin
      if cnt = i then begin
        FAddingChild:= true;
        try
          FCurChild := FObj.Add(r);
          FCurChild.SetFlag(rfJustCreated, true);
        finally
          FAddingChild := false;
        end;
        if EditRec <> mrOK then
          DelRec;
        break;
      end;
      inc(cnt);
    end;
  end;
end;

function TBrowseForm.EditRec: integer;
begin
  Result := mrCancel;
  if FCurChild <> nil then begin
    if FCurChild.IsFlagSet(rfVisible) and FCurChild.IsFlagSet(rfEnabled) then
    begin
      if FCurChild.IsFlagSet(rfBrowseOnEdit) then begin
        FCurChild.Browse;
        UpdateGrid;
        Result := mrOK;
      end else begin
        if FCurChild.Edit = mrOK then begin
          FModified := true;
          UpdateGrid;
          Result := mrOK;
        end;
      end;
    end;
  end;
end;

procedure TBrowseForm.DelRecBtnClick(Sender: TObject);
begin
  DelRec;
end;

procedure TBrowseForm.DelRec;
begin
  if FCurChild <> nil then begin
    {v0.13}
    if FCurChild.IsFlagSet(rfCantDelete) or (not FCurChild.CanDestroy) then begin
      if UserMode = umSysOp then begin
        if ShowMessage('Really destroy object used by other objects (GPF will follow)?', smYesNo, 0) <> cmYes then
          exit;
      end else begin
        exit;
      end;
    end;
    FCurChild.Free;
    SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterBrowseEdit,
      longint(FObj));
    {/v0.13
    if not FCurChild.IsFlagSet(rfCantDelete) or (UserMode = umSysOp) then begin
      if (not FCurChild.CanDestroy) and (UserMode <> umSysOp) then
        exit;
      FCurChild.Free;
      SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterBrowseEdit,
        longint(FObj));
    end;}
  end;
end;

procedure TBrowseForm.GridKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    vk_Insert: NewRec;
    vk_Delete: DelRec;
    vk_Return: EditRec;
  else
    exit;
  end;
  Key := 0;
end;

procedure TBrowseForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TBrowseForm.FormDestroy(Sender: TObject);
begin
  if FObj <> nil then
    FObj.UserUnregister(Self);
end;

procedure TBrowseForm.GridGetEditText(Sender: TObject; ACol, ARow: Integer;
  var Value: String);
{var
  j: integer;
  n: shortstring;
  v: AnsiString;
  oi: TULObjDesc;}
begin
  {$IFDEF DEBUG}
  if ULBrowDebLog then begin
    DebLog('OnGetText ' + IntToStr(ACol) + ',' + IntToStr(ARow) + ' :' + Value + ':');
  end;
  {$ENDIF}
  CheckSaveText(ACol, ARow, Value);

  FLastEditCol := ACol;
  FLastEditRow := ARow;
  FLastEditChild := FCurChild;
  FLastEditValue := Value;
end;

procedure TBrowseForm.GridSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: String);
begin
  {$IFDEF DEBUG}
  if ULBrowDebLog then
    DebLog('OnSetText ' + IntToStr(ACol) + ',' + IntToStr(ARow) + ' :' + Value + ':');
  {$ENDIF}
{  FLastEditValue := Value;
  FLastEditCol := ACol;
  FLastEditRow := ARow;}
{
  if FCurChild <> nil then begin
    if (FLastEditRow = ARow) and (FLastEditCol = ACol) then begin
    end;
  end;
  }
  CheckSaveText(ACol, ARow, Value);
end;

procedure TBrowseForm.CheckSaveText(ACol, ARow:integer; const Value: string);
begin
  if (ACol <> FLastEditCol) or (ARow <> FLastEditRow) then begin
    if FLastEditRow >= 0 then
      SaveText(FLastEditChild, FLastEditCol, FLastEditRow, FLastEditValue);
  end else begin
    FLastEditValue := Value;
  end;
end;

procedure TBrowseForm.SaveText(AChild: TULObj; ACol,ARow:integer; const Value:string);
var
  j: integer;
{  n: shortstring;
  v: AnsiString;}
{  oi: TULObjDesc;}
begin
  if (AChild = nil) then
    exit;
{  oi := AChild.ObjDesc;}
  j := ACol - FFixedCols;
  {if ClassGetPropStr(AChild, j + oi.FirstPropIndex, n, v) then}
  begin
    FSavingText := true;
    try
      if j < AChild.ObjDesc.BrowseFieldCount then begin
        if FInternalValues then begin
          AChild.Fields[AChild.ObjDesc.BrowseFields[j].ULIndex].Value := Value;
        end else begin
          AChild.Fields[AChild.ObjDesc.BrowseFields[j].ULIndex].UsrValue := Value;
        end;
        SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterBrowseEdit,
          longint(AChild));
        SendMessage(Application.MainForm.Handle, WM_APPMESSAGE, cmULObjAfterBrowseEdit,
          longint(FObj));
      end;
      {ClassSetPropStr(AChild, n, Value);}
    finally
      FSavingText := false;
    end;
  end;

  FLastEditRow := -1;
  FLastEditCol := -1;
  FLastEditValue := '';
  FLastEditChild := nil;
end;

procedure TBrowseForm.GridSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
  CheckSaveText(ACol, ARow, '');
end;

procedure TBrowseForm.GridExit(Sender: TObject);
begin
  CheckSaveText(-1, -1, '');
end;

procedure TBrowseForm.AllDetailsCheckBoxClick(Sender: TObject);
begin
  FModified := true;
  if AllDetailsCheckBox.Checked then
    SetBrowseMode(bmFull)
  else
    SetBrowseMode(bmShort)
end;

procedure TBrowseForm.InternalValuesCheckBoxClick(Sender: TObject);
begin
  FInternalValues := InternalValuesCheckBox.Checked;
  FModified := true;
  UpdateGrid;
end;

procedure TBrowseForm.GridMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  {v0.18}
  GridSelToObj;{UpdateSelection;}
  {/v0.18}
end;

end.
