ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
(Generate patch)

Comparing ibx/trunk/ibcontrols/IBDynamicGrid.pas (file contents):
Revision 21 by tony, Thu Feb 26 10:33:34 2015 UTC vs.
Revision 37 by tony, Mon Feb 15 14:44:25 2016 UTC

# Line 15 | Line 15
15   *
16   *  The Initial Developer of the Original Code is Tony Whyman.
17   *
18 < *  The Original Code is (C) 2011 Tony Whyman, MWA Software
18 > *  The Original Code is (C) 2015 Tony Whyman, MWA Software
19   *  (http://www.mwasoftware.co.uk).
20   *
21   *  All Rights Reserved.
# Line 23 | Line 23
23   *  Contributor(s): ______________________________________.
24   *
25   *)
26 +
27   unit IBDynamicGrid;
28  
29   {$mode objfpc}{$H+}
# Line 31 | Line 32 | interface
32  
33   uses
34    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DBGrids, DB,
35 <  IBSqlParser, Grids, IBLookupComboEditBox, LMessages, StdCtrls, ExtCtrls;
35 >  IBSQLParser, Grids, IBLookupComboEditBox, LMessages, StdCtrls, ExtCtrls,
36 >  IBCustomDataSet;
37  
38   type
39    {
# Line 55 | Line 57 | type
57    TOnUpdateSortOrder = procedure (Sender: TObject; ColIndex: integer; var OrderBy: string) of Object;
58    TKeyDownHandler = procedure (Sender: TObject; var Key: Word;  Shift: TShiftState; var Done: boolean) of object;
59  
58  { TDynamicGridDataLink }
59
60  TDynamicGridDataLink = class(TDataLink)
61  private
62    FOwner: TIBDynamicGrid;
63  protected
64    procedure DataEvent(Event: TDataEvent; Info: Ptrint); override;
65    procedure DataSetScrolled(Distance: Integer); override;
66  public
67    constructor Create(AOwner: TIBDynamicGrid);
68  end;
69
60    { TDBDynamicGridColumn }
61  
62    TDBDynamicGridColumn = class(TColumn)
# Line 102 | Line 92 | type
92      FListSource: TDataSource;
93      FOnAutoInsert: TAutoInsert;
94      FOnCanAutoInsert: TCanAutoInsert;
95 +    FOnCloseUp: TNotifyEvent;
96      FOnDrawItem: TDrawItemEvent;
97      FOwner: TIBDynamicGridColumn;
98      FRelationName: string;
# Line 128 | Line 119 | type
119      property Style: TComboBoxStyle read FStyle write FStyle default csDropDown;
120      property OnAutoInsert: TAutoInsert read FOnAutoInsert write FOnAutoInsert;
121      property OnCanAutoInsert: TCanAutoInsert read FOnCanAutoInsert write FOnCanAutoInsert;
122 +    property OnCloseUp: TNotifyEvent read FOnCloseUp write FOnCloseUp;
123      property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
124   end;
125  
# Line 162 | Line 154 | end;
154      procedure WndProc(var TheMessage : TLMessage); override;
155      procedure CloseUp; override;
156      procedure KeyDown(var Key : Word; Shift : TShiftState); override;
157 +    procedure Loaded; override;
158      procedure msg_GetValue(var Msg: TGridMessage); message GM_GETVALUE;
159      procedure msg_SetGrid(var Msg: TGridMessage); message GM_SETGRID;
160      procedure msg_SetValue(var Msg: TGridMessage); message GM_SETVALUE;
# Line 187 | Line 180 | end;
180      FWeHaveFocus: boolean;
181      FHidingEditorPanel: boolean;
182      FAllowHide: boolean;
183 +    FMouseDown: boolean;
184 +    function ActiveControl: TControl;
185      procedure DoShowEditorPanel(Data: PtrInt);
186      procedure PositionTotals;
187      procedure KeyDownHandler(Sender: TObject; var Key: Word; Shift: TShiftState);
188 +    procedure PerformEditorHide(Data: PtrInt);
189      procedure SetEditorPanel(AValue: TWinControl);
190    protected
191      procedure ChangeBounds(ALeft, ATop, AWidth, AHeight: integer; KeepBase: boolean); override;
# Line 219 | Line 215 | end;
215      constructor Create(TheComponent: TComponent); override;
216      destructor Destroy ;override;
217      procedure ResizeColumns;
218 +    property VisibleRowCount;
219    published
220      property EditorPanel: TWinControl read FEditorPanel write SetEditorPanel;
221      property ExpandEditorPanelBelowRow: boolean read FExpandEditorPanelBelowRow write FExpandEditorPanelBelowRow;
# Line 228 | Line 225 | end;
225      property OnKeyDownHander: TKeyDownHandler read FOnKeyDownHander write FOnKeyDownHander;
226   end;
227  
228 +  {TIBGridControlLink}
229 +
230 +  TIBGridControlLink = class(TIBControlLink)
231 +  private
232 +    FOwner: TIBDynamicGrid;
233 +  protected
234 +    procedure UpdateSQL(Sender: TObject); override;
235 +  public
236 +    constructor Create(AOwner: TIBDynamicGrid);
237 +  end;
238 +
239 +  TLocationArray = array of variant;
240 +  PLocationArray = ^TLocationArray;
241 +  TOnRestorePosition = procedure(Sender: TObject; Location: PLocationArray) of object;
242 +
243    { TIBDynamicGrid }
244  
245    TIBDynamicGrid = class(TDBDynamicGrid)
246    private
247      { Private declarations }
248      FAllowColumnSort: boolean;
249 <    FDataLink: TDynamicGridDataLink;
249 >    FIBControlLink: TIBGridControlLink;
250      FOnColumnHeaderClick: TOnColumnHeaderClick;
251 +    FOnRestorePosition: TOnRestorePosition;
252      FOnUpdateSortOrder: TOnUpdateSortOrder;
253      FDefaultPositionAtEnd: boolean;
254      FDescending: boolean;
# Line 243 | Line 256 | end;
256      FLastColIndex: integer;
257      FIndexFieldNames: string;
258      FIndexFieldsList: TStringList;
259 <    FBookmark: array of variant;
259 >    FBookmark: TLocationArray;
260      FDBLookupCellEditor: TDBLookupCellEditor;
261      FActive: boolean;
262 +    FFieldPosition: integer;
263      procedure ColumnHeaderClick(Index: integer);
264      function GetDataSource: TDataSource;
265      function GetEditorBorderStyle: TBorderStyle;
266 +    procedure IBControlLinkChanged;
267      procedure SetDataSource(AValue: TDataSource);
268      procedure SetEditorBorderStyle(AValue: TBorderStyle);
269      procedure ProcessColumns;
270      procedure SetIndexFieldNames(AValue: string);
271      procedure UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
272      procedure UpdateSortColumn(Sender: TObject);
273 <    procedure DataSetScrolled(Sender: TObject);
274 <    procedure RestorePosition(Data: PtrInt);
273 >    procedure RestorePosition;
274 >    procedure SavePosition;
275      procedure DoReOpen(Data: PtrInt);
276      procedure SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer);
277    protected
# Line 266 | Line 281 | end;
281      function  CreateColumns: TGridColumns; override;
282      procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
283      procedure LinkActive(Value: Boolean); override;
284 +    procedure MoveSelection; override;
285      procedure Notification(AComponent: TComponent; Operation: TOperation); override;
286      procedure UpdateActive; override;
287    public
# Line 283 | Line 299 | end;
299      property DefaultPositionAtEnd: boolean read  FDefaultPositionAtEnd write FDefaultPositionAtEnd;
300      property IndexFieldNames: string read FIndexFieldNames write SetIndexFieldNames;
301      property OnColumnHeaderClick: TOnColumnHeaderClick read FOnColumnHeaderClick write FOnColumnHeaderClick;
302 +    property OnRestorePosition: TOnRestorePosition read FOnRestorePosition write FOnRestorePosition;
303      property OnUpdateSortOrder: TOnUpdateSortOrder read FOnUpdateSortOrder write FOnUpdateSortOrder;
304   end;
305  
306   implementation
307  
308 < uses Math, IBQuery, IBCustomDataSet, LCLType;
308 > uses Math, IBQuery, LCLType;
309 >
310 > { TIBGridControlLink }
311 >
312 > constructor TIBGridControlLink.Create(AOwner: TIBDynamicGrid);
313 > begin
314 >  inherited Create;
315 >  FOwner := AOwner;
316 > end;
317 >
318 > procedure TIBGridControlLink.UpdateSQL(Sender: TObject);
319 > begin
320 >  FOwner.UpdateSQL(self,TIBParserDataSet(Sender).Parser)
321 > end;
322  
323   { TDBLookupProperties }
324  
# Line 335 | Line 365 | begin
365    FResizing := true;
366    try
367      ColSum := 0;
338    for I := 0 to  ColCount - 1 do
339       ColSum := ColSum + ColWidths[I];
368  
369 <    if Colsum <> ClientWidth then
369 >    if (ColCount = 1) and TDBDynamicGridColumn(Columns[0]).AutoSizeColumn then
370 >      Columns[0].Width := ClientWidth
371 >    else
372      begin
373 <      ResizeColCount := 0;
374 <      for I := 0 to Columns.Count -1 do
375 <        if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn then
376 <        begin
377 <          Inc(ResizeColCount);
378 <          Colsum := Colsum + TDBDynamicGridColumn(Columns[I]).DesignWidth - Columns[I].Width;
379 <          Columns[I].Width := TDBDynamicGridColumn(Columns[I]).DesignWidth;
380 <        end;
381 <
382 <        if (Colsum < ClientWidth) and (ResizeColCount > 0) then
383 <        begin
384 <          adjustment := (ClientWidth - ColSum) div ResizeColCount;
385 <          n := (ClientWidth - ColSum) mod ResizeColCount;
386 <
387 <          for I := 0 to Columns.Count -1 do
388 <            if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn then
389 <            begin
390 <              if I = 0 then
391 <                Columns[I].Width := Columns[I].Width + adjustment + n
392 <              else
393 <                Columns[I].Width := Columns[I].Width + adjustment;
394 <            end;
395 <        end;
373 >      for I := 0 to  ColCount - 1 do
374 >         ColSum := ColSum + ColWidths[I];
375 >
376 >      if Colsum <> ClientWidth then
377 >      begin
378 >        ResizeColCount := 0;
379 >        for I := 0 to Columns.Count -1 do
380 >          if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn then
381 >          begin
382 >            Inc(ResizeColCount);
383 >            Colsum := Colsum + TDBDynamicGridColumn(Columns[I]).DesignWidth - Columns[I].Width;
384 >            Columns[I].Width := TDBDynamicGridColumn(Columns[I]).DesignWidth;
385 >          end;
386 >
387 >          if (Colsum < ClientWidth) and (ResizeColCount > 0) then
388 >          begin
389 >            adjustment := (ClientWidth - ColSum) div ResizeColCount;
390 >            n := (ClientWidth - ColSum) mod ResizeColCount;
391 >
392 >            for I := 0 to Columns.Count -1 do
393 >              if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn then
394 >              begin
395 >                if I = 0 then
396 >                  Columns[I].Width := Columns[I].Width + adjustment + n
397 >                else
398 >                  Columns[I].Width := Columns[I].Width + adjustment;
399 >              end;
400 >          end;
401 >      end;
402      end;
403      PositionTotals;
404      UpdateEditorPanelBounds;
# Line 374 | Line 410 | end;
410   procedure TDBDynamicGrid.DoEditorHide;
411   begin
412    inherited DoEditorHide;
413 <  if (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
414 <    RowHeights[FExpandedRow] := DefaultRowHeight;
415 <  FExpandedRow := -1;
416 <  if CanFocus then SetFocus;
417 <  if assigned(FOnEditorPanelHide) then
418 <     OnEditorPanelHide(self);
419 <  DoOnResize;
413 >  if Editor = FEditorPanel then
414 >  begin
415 >    if FMouseDown then
416 >      Application.QueueAsyncCall(@PerformEditorHide,FExpandedRow)
417 >    else
418 >      PerformEditorHide(FExpandedRow);
419 >    FExpandedRow := -1;
420 >  end;
421   end;
422  
423   procedure TDBDynamicGrid.DoEditorShow;
424   begin
425 +  if assigned(DataSource) and assigned(DataSource.DataSet) and
426 +             DataSource.DataSet.Active then
427 +  begin
428 +    if (DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert) then
429 +      DataSource.DataSet.Append
430 +  end;
431    if Editor = FEditorPanel then
432    begin
433      if ExpandEditorPanelBelowRow then
# Line 397 | Line 440 | begin
440      FEditorPanel.PerformTab(true);  {Select First Control}
441      if assigned(FOnEditorPanelShow) then
442         OnEditorPanelShow(self);
443 +    if assigned(Editor) and Editor.Visible then
444 +      Editor.SetFocus;
445    end
446    else
447      inherited DoEditorShow;
# Line 461 | Line 506 | begin
506      inherited KeyDown(Key, Shift);
507   end;
508  
509 + function TDBDynamicGrid.ActiveControl: TControl;
510 + var AParent: TWinControl;
511 + begin
512 +  Result := nil;
513 +  AParent := Parent;
514 +  while (AParent <> nil) and  not (AParent is TCustomForm) do
515 +    AParent := AParent.Parent;
516 +  if (AParent <> nil) and (AParent is TCustomForm)then
517 +      Result := TCustomForm(AParent).ActiveControl;
518 + end;
519 +
520   procedure TDBDynamicGrid.DoShowEditorPanel(Data: PtrInt);
521   begin
522    if AppDestroying in Application.Flags then Exit;
# Line 492 | Line 548 | end;
548   procedure TDBDynamicGrid.KeyDownHandler(Sender: TObject; var Key: Word;
549    Shift: TShiftState);
550   var Done: boolean;
551 +    AControl: TControl;
552   begin
553    if Visible and assigned(FEditorPanel) and FEditorPanel.Visible and FWeHaveFocus then
554    begin
555      Done := false;
556 +    AControl := ActiveControl;
557 +    if (AControl <> nil) and (AControl is TCustomComboBox)
558 +                         and ((Key in [VK_UP,VK_DOWN]) or
559 +                         (TCustomComboBox(AControl).DroppedDown and (Key = VK_RETURN)) or
560 +                         ((TCustomComboBox(AControl).Text <> '') and (Key =  VK_ESCAPE))) then
561 +      Exit; {ignore these keys if we are in a  combobox}
562 +
563 +    if (AControl <> nil) and (AControl is TCustomMemo)
564 +                         and (Key in [VK_RETURN,VK_UP,VK_DOWN]) then Exit; {Ignore Return in a CustomMemo}
565 +
566 +    if (AControl <> nil) and (AControl is TCustomGrid)
567 +                         and (Key in [VK_RETURN,VK_UP,VK_DOWN,VK_TAB]) then Exit; {Ignore Return in a CustomMemo}
568 +
569      if assigned(FOnKeyDownHander) then
570        OnKeyDownHander(Sender,Key,Shift,Done);
571      if Done then Exit;
# Line 518 | Line 588 | begin
588    end
589   end;
590  
591 + procedure TDBDynamicGrid.PerformEditorHide(Data: PtrInt);
592 + var ExpandedRow: integer;
593 + begin
594 +  if AppDestroying in Application.Flags then Exit;
595 +  ExpandedRow := integer(Data);
596 +  if (ExpandedRow >= 0) and (ExpandedRow < RowCount) then
597 +    RowHeights[ExpandedRow] := DefaultRowHeight;
598 +  if CanFocus then SetFocus;
599 +  DoOnResize;
600 +  ResetSizes;
601 +  DoOnChangeBounds;
602 +  if assigned(FOnEditorPanelHide) then
603 +     OnEditorPanelHide(self);
604 + end;
605 +
606   procedure TDBDynamicGrid.SetEditorPanel(AValue: TWinControl);
607   begin
608    if FEditorPanel = AValue then Exit;
# Line 552 | Line 637 | begin
637    inherited Loaded;
638    if assigned(FEditorPanel) and not (csDesigning in ComponentState)then
639      FEditorPanel.Visible := false;
640 <  DoGridResize
640 >  if Visible then
641 >    DoGridResize
642   end;
643  
644   procedure TDBDynamicGrid.DoOnResize;
# Line 576 | Line 662 | procedure TDBDynamicGrid.MouseDown(Butto
662    Y: Integer);
663   var Coord: TGridCoord;
664   begin
665 <  inherited MouseDown(Button, Shift, X, Y);
665 >  FMouseDown := true;
666 >  try
667 >    inherited MouseDown(Button, Shift, X, Y);
668 >  finally
669 >    FMouseDown := false;
670 >  end;
671  
672    Coord := MouseCoord(X,Y);
673    if (Coord.X = 0) and (Coord.Y > 0) then
# Line 602 | Line 693 | begin
693    inherited UpdateActive;
694  
695    if not (csLoading in ComponentState) and assigned(DataLink) and
696 +     assigned(FEditorPanel) and not FEditorPanel.Visible and
697       assigned(DataLink.DataSet) and (DataLink.DataSet.State = dsInsert) then
698       Application.QueueAsyncCall(@DoShowEditorPanel,0);
699   end;
# Line 634 | Line 726 | end;
726   procedure TDBDynamicGrid.HideEditorPanel;
727   begin
728    if Editor = FEditorPanel then
729 <    EditorMode := false;
729 >      EditorMode := false;
730   end;
731  
732   procedure TDBDynamicGrid.ShowEditorPanel;
733   begin
734 <  if csDesigning in ComponentState then Exit;
734 >  if (csDesigning in ComponentState) or
735 >   (DataSource = nil) or (DataSource.DataSet = nil)
736 >     or ((DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert)) then
737 >     Exit;
738    Editor := FEditorPanel;
739    EditorMode := true;
740   end;
# Line 698 | Line 793 | procedure TDBLookupCellEditor.CloseUp;
793   begin
794    UpdateData(nil); {Force Record Update}
795    if FGrid<>nil then
796 <    (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Text);
796 >  Begin
797 >    (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Trim(Text));
798 >    (FGrid as TIBDynamicGrid).UpdateData;
799 >  end;
800    inherited CloseUp;
801   end;
802  
# Line 710 | Line 808 | begin
808      inherited KeyDown(Key, Shift);
809   end;
810  
811 + procedure TDBLookupCellEditor.Loaded;
812 + begin
813 +  inherited Loaded;
814 +  Text := '';
815 + end;
816 +
817   procedure TDBLookupCellEditor.msg_GetValue(var Msg: TGridMessage);
818   begin
819    CheckAndInsert;
# Line 730 | Line 834 | begin
834    FCol := Msg.Col;
835    FRow := Msg.Row;
836    FEditText := Msg.Value;
733  SelStart := Length(Text);
837    TIBDynamicGrid(FGrid).SetupEditor(self,FCol);
838   end;
839  
# Line 779 | Line 882 | begin
882      Editor.OnAutoInsert := OnAutoInsert;
883      Editor.OnCanAutoInsert := OnCanAutoInsert;
884      Editor.OnDrawItem := OnDrawItem;
885 +    Editor.OnCloseUp := OnCloseUp;
886  
887      {Setup Data Links}
888      if KeyField <> '' then
# Line 804 | Line 908 | begin
908          Editor.DataSource := TDBGrid(Grid).DataSource;
909    end;
910    Editor.Text := Editor.FEditText;
911 +  Editor.SelStart := Length(Editor.Text);
912   end;
913  
914   procedure TIBDynamicGridColumn.SetInitialSortColumn(AValue: boolean);
# Line 830 | Line 935 | begin
935    inherited Destroy;
936   end;
937  
833 { TDynamicGridDataLink }
834
835 procedure TDynamicGridDataLink.DataEvent(Event: TDataEvent; Info: Ptrint);
836 begin
837  if (Event = deCheckBrowseMode) and (Info = 1) and not DataSet.Active then
838  begin
839    if (DataSet is TIBDataSet) then
840      FOwner.UpdateSQL(self,TIBDataSet(DataSet).Parser)
841    else
842    if (DataSet is TIBQuery) then
843      FOwner.UpdateSQL(self,TIBQuery(DataSet).Parser)
844  end
845  else
846  inherited DataEvent(Event, Info);
847 end;
848
849 procedure TDynamicGridDataLink.DataSetScrolled(Distance: Integer);
850 begin
851  inherited DataSetScrolled(Distance);
852  FOwner.DataSetScrolled(self)
853 end;
854
855 constructor TDynamicGridDataLink.Create(AOwner: TIBDynamicGrid);
856 begin
857  inherited Create;
858  FOwner := AOwner
859 end;
860
938  
939   { TIBDynamicGrid }
940  
# Line 872 | Line 949 | begin
949        OnColumnHeaderClick(self,Index);
950  
951      FLastColIndex := Index;
952 <    if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
952 >    FFieldPosition := 0;
953 >    if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active
954 >       and (DataSource.DataSet is TIBParserDataSet) then
955      begin
956 +      if FLastColIndex < Columns.Count then
957 +      {try and cache field position while dataset still open}
958 +        FFieldPosition := TIBParserDataSet(DataSource.DataSet).Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
959        DataSource.DataSet.Active := false;
960        Application.QueueAsyncCall(@DoReopen,0)
961      end;
# Line 901 | Line 983 | end;
983   procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
984   begin
985    inherited DataSource := AValue;
986 <  FDataLink.DataSource := AValue;
986 >  IBControlLinkChanged;
987   end;
988  
989   procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
# Line 921 | Line 1003 | begin
1003    for i := 0 to Columns.Count - 1 do
1004    begin
1005      if TIBDynamicGridColumn(columns[i]).InitialSortColumn then
1006 +    begin
1007 +      FFieldPosition := 0;
1008        FLastColIndex := i
1009 +    end
1010    end
1011   end;
1012  
# Line 938 | Line 1023 | end;
1023  
1024   procedure TIBDynamicGrid.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
1025   var OrderBy: string;
941    FieldPosition: integer;
1026   begin
1027 <    if (Sender = TObject(FDataLink)) and assigned(DataSource) and assigned(DataSource.DataSet)
1027 >    if assigned(DataSource) and assigned(DataSource.DataSet)
1028        and (DataSource.DataSet is TIBCustomDataSet) then
1029      begin
1030 <      FieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1031 <      if FieldPosition = 0 then Exit;
1032 <
1033 <      if Descending then
1034 <        Parser.OrderByClause := IntToStr(FieldPosition) + ' desc'
1035 <      else
1036 <        Parser.OrderByClause := IntToStr(FieldPosition) + ' asc';
1030 >      if (FFieldPosition = 0) and (FLastColIndex >= 0) and (FLastColIndex < Columns.Count) then
1031 >        {Not cached - let's hope we can find it before the dataset is opened.
1032 >         Won't work if dynamic columns}
1033 >        FFieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1034 >      if FFieldPosition > 0 then
1035 >      begin
1036 >        if Descending then
1037 >          Parser.OrderByClause := IntToStr(FFieldPosition) + ' desc'
1038 >        else
1039 >          Parser.OrderByClause := IntToStr(FFieldPosition) + ' asc';
1040 >      end;
1041  
1042        if assigned(FOnUpdateSortOrder) then
1043        begin
# Line 972 | Line 1060 | begin
1060  
1061   end;
1062  
1063 < procedure TIBDynamicGrid.DataSetScrolled(Sender: TObject);
976 < var i: integer;
977 <    F: TField;
1063 > procedure TIBDynamicGrid.RestorePosition;
1064   begin
979    SetLength(FBookmark,FIndexFieldsList.Count);
980    for i := 0 to FIndexFieldsList.Count - 1 do
981    begin
982      F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
983      if assigned(F) then
984         FBookmark[i] := F.AsVariant;
985    end;
986 end;
987
988 procedure TIBDynamicGrid.RestorePosition(Data: PtrInt);
989 begin
990  if AppDestroying in Application.Flags then Exit;
991
1065    if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1066    begin
1067 +    if assigned(FOnRestorePosition) then
1068 +      OnRestorePosition(self,@FBookmark);
1069      if (Length(FBookmark) > 0) and
1070        DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1071  
# Line 999 | Line 1074 | begin
1074    end;
1075   end;
1076  
1077 + procedure TIBDynamicGrid.SavePosition;
1078 + var i: integer;
1079 +    F: TField;
1080 + begin
1081 +  if FIndexFieldsList = nil then Exit;
1082 +
1083 +  SetLength(FBookmark,FIndexFieldsList.Count);
1084 +  for i := 0 to FIndexFieldsList.Count - 1 do
1085 +  begin
1086 +    F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
1087 +    if assigned(F) then
1088 +       FBookmark[i] := F.AsVariant;
1089 +  end;
1090 + end;
1091 +
1092   procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1093   begin
1094    DataSource.DataSet.Active := true;
1095   end;
1096  
1097 + procedure TIBDynamicGrid.IBControlLinkChanged;
1098 + begin
1099 +  if (DataSource <> nil) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataSet) then
1100 +    FIBControlLink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
1101 +  else
1102 +    FIBControlLink.IBDataSet := nil;
1103 + end;
1104 +
1105   procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1106    );
1107   var C: TIBDynamicGridColumn;
1108   begin
1109    C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1110 <  C.SetupEditor(aEditor);
1110 >  if (c <> nil) then
1111 >    C.SetupEditor(aEditor);
1112   end;
1113  
1114   procedure TIBDynamicGrid.DoEditorHide;
# Line 1025 | Line 1124 | end;
1124   procedure TIBDynamicGrid.Loaded;
1125   begin
1126    inherited Loaded;
1127 +  IBControlLinkChanged;
1128    ProcessColumns;
1129   end;
1130  
# Line 1054 | Line 1154 | begin
1154    AllowOutboundEvents := false;
1155    try
1156      Coord := MouseCoord(X,Y);
1157 <  if AllowColumnSort and  (Coord.X <> -1) and
1157 >  if AllowColumnSort and  (Coord.X <> -1) and (FixedRows > 0) and
1158     (Coord.Y = 0) and (MouseCoord(X+5,Y).X = Coord.X) {not on boundary}
1159                     and (MouseCoord(X-5,Y).X = Coord.X) then
1160      ColumnHeaderClick(Coord.X-1);
# Line 1063 | Line 1163 | begin
1163    end;
1164   end;
1165  
1166 + procedure TIBDynamicGrid.MoveSelection;
1167 + begin
1168 +  inherited MoveSelection;
1169 +  SavePosition;
1170 + end;
1171 +
1172   procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1173   begin
1174 +  IBControlLinkChanged;
1175    inherited LinkActive(Value);
1176    if (FActive <> Value) and Value then
1177 <    Application.QueueAsyncCall(@RestorePosition,0);
1177 >    RestorePosition;
1178    FActive := Value
1179   end;
1180  
# Line 1076 | Line 1183 | procedure TIBDynamicGrid.Notification(AC
1183   begin
1184    inherited Notification(AComponent, Operation);
1185    if (Operation = opRemove) and
1186 <     (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
1186 >     (FIBControlLink <> nil) and (AComponent = DataSource) then FIBControlLink.IBDataSet := nil;
1187   end;
1188  
1189   procedure TIBDynamicGrid.UpdateActive;
1190   begin
1191    inherited UpdateActive;
1192 <  if assigned(FDataLink) and assigned(FDataLink.DataSet) and
1193 <     FDataLink.DataSet.Active and (FDataLink.DataSet.State = dsInsert) then
1194 <    DataSetScrolled(nil);
1192 >  if assigned(DataLink) and assigned(DataLink.DataSet) and
1193 >     DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1194 >   SavePosition;
1195   end;
1196  
1197   constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1198   begin
1199    inherited Create(TheComponent);
1200    FAllowColumnSort := true;
1201 <  FDataLink := TDynamicGridDataLink.Create(self);
1201 >  FIBControlLink := TIBGridControlLink.Create(self);
1202    FIndexFieldsList := TStringList.Create;
1203    FIndexFieldsList.Delimiter := ';';
1204    FIndexFieldsList.StrictDelimiter := true;
# Line 1103 | Line 1210 | end;
1210  
1211   destructor TIBDynamicGrid.Destroy;
1212   begin
1213 <  if assigned(FDataLink) then FDataLink.Free;
1213 >  if assigned(FIBControlLink) then FIBControlLink.Free;
1214    if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1215    if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
1216    inherited Destroy;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines