ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/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 31 by tony, Tue Jul 14 15:31:25 2015 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 31 | Line 31 | interface
31  
32   uses
33    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DBGrids, DB,
34 <  IBSqlParser, Grids, IBLookupComboEditBox, LMessages, StdCtrls, ExtCtrls;
34 >  IBSQLParser, Grids, IBLookupComboEditBox, LMessages, StdCtrls, ExtCtrls,
35 >  IBCustomDataSet;
36  
37   type
38    {
# Line 55 | Line 56 | type
56    TOnUpdateSortOrder = procedure (Sender: TObject; ColIndex: integer; var OrderBy: string) of Object;
57    TKeyDownHandler = procedure (Sender: TObject; var Key: Word;  Shift: TShiftState; var Done: boolean) of object;
58  
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
59    { TDBDynamicGridColumn }
60  
61    TDBDynamicGridColumn = class(TColumn)
# Line 102 | Line 91 | type
91      FListSource: TDataSource;
92      FOnAutoInsert: TAutoInsert;
93      FOnCanAutoInsert: TCanAutoInsert;
94 +    FOnCloseUp: TNotifyEvent;
95      FOnDrawItem: TDrawItemEvent;
96      FOwner: TIBDynamicGridColumn;
97      FRelationName: string;
# Line 128 | Line 118 | type
118      property Style: TComboBoxStyle read FStyle write FStyle default csDropDown;
119      property OnAutoInsert: TAutoInsert read FOnAutoInsert write FOnAutoInsert;
120      property OnCanAutoInsert: TCanAutoInsert read FOnCanAutoInsert write FOnCanAutoInsert;
121 +    property OnCloseUp: TNotifyEvent read FOnCloseUp write FOnCloseUp;
122      property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
123   end;
124  
# Line 162 | Line 153 | end;
153      procedure WndProc(var TheMessage : TLMessage); override;
154      procedure CloseUp; override;
155      procedure KeyDown(var Key : Word; Shift : TShiftState); override;
156 +    procedure Loaded; override;
157      procedure msg_GetValue(var Msg: TGridMessage); message GM_GETVALUE;
158      procedure msg_SetGrid(var Msg: TGridMessage); message GM_SETGRID;
159      procedure msg_SetValue(var Msg: TGridMessage); message GM_SETVALUE;
# Line 187 | Line 179 | end;
179      FWeHaveFocus: boolean;
180      FHidingEditorPanel: boolean;
181      FAllowHide: boolean;
182 +    function ActiveControl: TControl;
183      procedure DoShowEditorPanel(Data: PtrInt);
184      procedure PositionTotals;
185      procedure KeyDownHandler(Sender: TObject; var Key: Word; Shift: TShiftState);
# Line 219 | Line 212 | end;
212      constructor Create(TheComponent: TComponent); override;
213      destructor Destroy ;override;
214      procedure ResizeColumns;
215 +    property VisibleRowCount;
216    published
217      property EditorPanel: TWinControl read FEditorPanel write SetEditorPanel;
218      property ExpandEditorPanelBelowRow: boolean read FExpandEditorPanelBelowRow write FExpandEditorPanelBelowRow;
# Line 228 | Line 222 | end;
222      property OnKeyDownHander: TKeyDownHandler read FOnKeyDownHander write FOnKeyDownHander;
223   end;
224  
225 +  {TIBGridControlLink}
226 +
227 +  TIBGridControlLink = class(TIBControlLink)
228 +  private
229 +    FOwner: TIBDynamicGrid;
230 +  protected
231 +    procedure UpdateSQL(Sender: TObject); override;
232 +  public
233 +    constructor Create(AOwner: TIBDynamicGrid);
234 +  end;
235 +
236 +  TLocationArray = array of variant;
237 +  PLocationArray = ^TLocationArray;
238 +  TOnRestorePosition = procedure(Sender: TObject; Location: PLocationArray) of object;
239 +
240    { TIBDynamicGrid }
241  
242    TIBDynamicGrid = class(TDBDynamicGrid)
243    private
244      { Private declarations }
245      FAllowColumnSort: boolean;
246 <    FDataLink: TDynamicGridDataLink;
246 >    FIBControlLink: TIBGridControlLink;
247      FOnColumnHeaderClick: TOnColumnHeaderClick;
248 +    FOnRestorePosition: TOnRestorePosition;
249      FOnUpdateSortOrder: TOnUpdateSortOrder;
250      FDefaultPositionAtEnd: boolean;
251      FDescending: boolean;
# Line 243 | Line 253 | end;
253      FLastColIndex: integer;
254      FIndexFieldNames: string;
255      FIndexFieldsList: TStringList;
256 <    FBookmark: array of variant;
256 >    FBookmark: TLocationArray;
257      FDBLookupCellEditor: TDBLookupCellEditor;
258      FActive: boolean;
259      procedure ColumnHeaderClick(Index: integer);
260      function GetDataSource: TDataSource;
261      function GetEditorBorderStyle: TBorderStyle;
262 +    procedure IBControlLinkChanged;
263      procedure SetDataSource(AValue: TDataSource);
264      procedure SetEditorBorderStyle(AValue: TBorderStyle);
265      procedure ProcessColumns;
266      procedure SetIndexFieldNames(AValue: string);
267      procedure UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
268      procedure UpdateSortColumn(Sender: TObject);
269 <    procedure DataSetScrolled(Sender: TObject);
270 <    procedure RestorePosition(Data: PtrInt);
269 >    procedure RestorePosition;
270 >    procedure SavePosition;
271      procedure DoReOpen(Data: PtrInt);
272      procedure SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer);
273    protected
# Line 266 | Line 277 | end;
277      function  CreateColumns: TGridColumns; override;
278      procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
279      procedure LinkActive(Value: Boolean); override;
280 +    procedure MoveSelection; override;
281      procedure Notification(AComponent: TComponent; Operation: TOperation); override;
282      procedure UpdateActive; override;
283    public
# Line 283 | Line 295 | end;
295      property DefaultPositionAtEnd: boolean read  FDefaultPositionAtEnd write FDefaultPositionAtEnd;
296      property IndexFieldNames: string read FIndexFieldNames write SetIndexFieldNames;
297      property OnColumnHeaderClick: TOnColumnHeaderClick read FOnColumnHeaderClick write FOnColumnHeaderClick;
298 +    property OnRestorePosition: TOnRestorePosition read FOnRestorePosition write FOnRestorePosition;
299      property OnUpdateSortOrder: TOnUpdateSortOrder read FOnUpdateSortOrder write FOnUpdateSortOrder;
300   end;
301  
302   implementation
303  
304 < uses Math, IBQuery, IBCustomDataSet, LCLType;
304 > uses Math, IBQuery, LCLType;
305 >
306 > { TIBGridControlLink }
307 >
308 > constructor TIBGridControlLink.Create(AOwner: TIBDynamicGrid);
309 > begin
310 >  inherited Create;
311 >  FOwner := AOwner;
312 > end;
313 >
314 > procedure TIBGridControlLink.UpdateSQL(Sender: TObject);
315 > begin
316 >  FOwner.UpdateSQL(self,TIBParserDataSet(Sender).Parser)
317 > end;
318  
319   { TDBLookupProperties }
320  
# Line 374 | Line 400 | end;
400   procedure TDBDynamicGrid.DoEditorHide;
401   begin
402    inherited DoEditorHide;
403 <  if (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
404 <    RowHeights[FExpandedRow] := DefaultRowHeight;
405 <  FExpandedRow := -1;
406 <  if CanFocus then SetFocus;
407 <  if assigned(FOnEditorPanelHide) then
408 <     OnEditorPanelHide(self);
409 <  DoOnResize;
403 >  if Editor = FEditorPanel then
404 >  begin
405 >    if (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
406 >      RowHeights[FExpandedRow] := DefaultRowHeight;
407 >    FExpandedRow := -1;
408 >    if CanFocus then SetFocus;
409 >    DoOnResize;
410 >    ResetSizes;
411 >    DoOnChangeBounds;
412 >    if assigned(FOnEditorPanelHide) then
413 >       OnEditorPanelHide(self);
414 >  end;
415   end;
416  
417   procedure TDBDynamicGrid.DoEditorShow;
# Line 461 | Line 492 | begin
492      inherited KeyDown(Key, Shift);
493   end;
494  
495 + function TDBDynamicGrid.ActiveControl: TControl;
496 + var AParent: TWinControl;
497 + begin
498 +  Result := nil;
499 +  AParent := Parent;
500 +  while (AParent <> nil) and  not (AParent is TCustomForm) do
501 +    AParent := AParent.Parent;
502 +  if (AParent <> nil) and (AParent is TCustomForm)then
503 +      Result := TCustomForm(AParent).ActiveControl;
504 + end;
505 +
506   procedure TDBDynamicGrid.DoShowEditorPanel(Data: PtrInt);
507   begin
508    if AppDestroying in Application.Flags then Exit;
# Line 492 | Line 534 | end;
534   procedure TDBDynamicGrid.KeyDownHandler(Sender: TObject; var Key: Word;
535    Shift: TShiftState);
536   var Done: boolean;
537 +    AControl: TControl;
538   begin
539    if Visible and assigned(FEditorPanel) and FEditorPanel.Visible and FWeHaveFocus then
540    begin
541      Done := false;
542 +    AControl := ActiveControl;
543 +    if (AControl <> nil) and (AControl is TCustomComboBox)
544 +                         and ((Key in [VK_UP,VK_DOWN]) or
545 +                         (TCustomComboBox(AControl).DroppedDown and (Key = VK_RETURN)) or
546 +                         ((TCustomComboBox(AControl).Text <> '') and (Key =  VK_ESCAPE))) then
547 +      Exit; {ignore these keys if we are in a  combobox}
548 +
549 +    if (AControl <> nil) and (AControl is TCustomMemo)
550 +                         and (Key = VK_RETURN) then Exit; {Ignore Return in a CustomMemo}
551      if assigned(FOnKeyDownHander) then
552        OnKeyDownHander(Sender,Key,Shift,Done);
553      if Done then Exit;
# Line 639 | Line 691 | end;
691  
692   procedure TDBDynamicGrid.ShowEditorPanel;
693   begin
694 <  if csDesigning in ComponentState then Exit;
694 >  if (csDesigning in ComponentState) or
695 >   (DataSource = nil) or (DataSource.DataSet = nil)
696 >     or ((DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert)) then
697 >     Exit;
698    Editor := FEditorPanel;
699    EditorMode := true;
700   end;
# Line 698 | Line 753 | procedure TDBLookupCellEditor.CloseUp;
753   begin
754    UpdateData(nil); {Force Record Update}
755    if FGrid<>nil then
756 <    (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Text);
756 >  Begin
757 >    (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Trim(Text));
758 >    (FGrid as TIBDynamicGrid).UpdateData;
759 >  end;
760    inherited CloseUp;
761   end;
762  
# Line 710 | Line 768 | begin
768      inherited KeyDown(Key, Shift);
769   end;
770  
771 + procedure TDBLookupCellEditor.Loaded;
772 + begin
773 +  inherited Loaded;
774 +  Text := '';
775 + end;
776 +
777   procedure TDBLookupCellEditor.msg_GetValue(var Msg: TGridMessage);
778   begin
779    CheckAndInsert;
# Line 730 | Line 794 | begin
794    FCol := Msg.Col;
795    FRow := Msg.Row;
796    FEditText := Msg.Value;
733  SelStart := Length(Text);
797    TIBDynamicGrid(FGrid).SetupEditor(self,FCol);
798   end;
799  
# Line 779 | Line 842 | begin
842      Editor.OnAutoInsert := OnAutoInsert;
843      Editor.OnCanAutoInsert := OnCanAutoInsert;
844      Editor.OnDrawItem := OnDrawItem;
845 +    Editor.OnCloseUp := OnCloseUp;
846  
847      {Setup Data Links}
848      if KeyField <> '' then
# Line 804 | Line 868 | begin
868          Editor.DataSource := TDBGrid(Grid).DataSource;
869    end;
870    Editor.Text := Editor.FEditText;
871 +  Editor.SelStart := Length(Editor.Text);
872   end;
873  
874   procedure TIBDynamicGridColumn.SetInitialSortColumn(AValue: boolean);
# Line 830 | Line 895 | begin
895    inherited Destroy;
896   end;
897  
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
898  
899   { TIBDynamicGrid }
900  
# Line 901 | Line 938 | end;
938   procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
939   begin
940    inherited DataSource := AValue;
941 <  FDataLink.DataSource := AValue;
941 >  IBControlLinkChanged;
942   end;
943  
944   procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
# Line 940 | Line 977 | procedure TIBDynamicGrid.UpdateSQL(Sende
977   var OrderBy: string;
978      FieldPosition: integer;
979   begin
980 <    if (Sender = TObject(FDataLink)) and assigned(DataSource) and assigned(DataSource.DataSet)
980 >    if assigned(DataSource) and assigned(DataSource.DataSet)
981        and (DataSource.DataSet is TIBCustomDataSet) then
982      begin
983 +      if (FLastColIndex < 0) or (FLastColIndex >= Columns.Count) then Exit;
984        FieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
985        if FieldPosition = 0 then Exit;
986  
# Line 972 | Line 1010 | begin
1010  
1011   end;
1012  
1013 < procedure TIBDynamicGrid.DataSetScrolled(Sender: TObject);
976 < var i: integer;
977 <    F: TField;
978 < 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);
1013 > procedure TIBDynamicGrid.RestorePosition;
1014   begin
990  if AppDestroying in Application.Flags then Exit;
991
1015    if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1016    begin
1017 +    if assigned(FOnRestorePosition) then
1018 +      OnRestorePosition(self,@FBookmark);
1019      if (Length(FBookmark) > 0) and
1020        DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1021  
# Line 999 | Line 1024 | begin
1024    end;
1025   end;
1026  
1027 + procedure TIBDynamicGrid.SavePosition;
1028 + var i: integer;
1029 +    F: TField;
1030 + begin
1031 +  if FIndexFieldsList = nil then Exit;
1032 +
1033 +  SetLength(FBookmark,FIndexFieldsList.Count);
1034 +  for i := 0 to FIndexFieldsList.Count - 1 do
1035 +  begin
1036 +    F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
1037 +    if assigned(F) then
1038 +       FBookmark[i] := F.AsVariant;
1039 +  end;
1040 + end;
1041 +
1042   procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1043   begin
1044    DataSource.DataSet.Active := true;
1045   end;
1046  
1047 + procedure TIBDynamicGrid.IBControlLinkChanged;
1048 + begin
1049 +  if (DataSource <> nil) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataSet) then
1050 +    FIBControlLink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
1051 +  else
1052 +    FIBControlLink.IBDataSet := nil;
1053 + end;
1054 +
1055   procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1056    );
1057   var C: TIBDynamicGridColumn;
1058   begin
1059    C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1060 <  C.SetupEditor(aEditor);
1060 >  if (c <> nil) then
1061 >    C.SetupEditor(aEditor);
1062   end;
1063  
1064   procedure TIBDynamicGrid.DoEditorHide;
# Line 1025 | Line 1074 | end;
1074   procedure TIBDynamicGrid.Loaded;
1075   begin
1076    inherited Loaded;
1077 +  IBControlLinkChanged;
1078    ProcessColumns;
1079   end;
1080  
# Line 1054 | Line 1104 | begin
1104    AllowOutboundEvents := false;
1105    try
1106      Coord := MouseCoord(X,Y);
1107 <  if AllowColumnSort and  (Coord.X <> -1) and
1107 >  if AllowColumnSort and  (Coord.X <> -1) and (FixedRows > 0) and
1108     (Coord.Y = 0) and (MouseCoord(X+5,Y).X = Coord.X) {not on boundary}
1109                     and (MouseCoord(X-5,Y).X = Coord.X) then
1110      ColumnHeaderClick(Coord.X-1);
# Line 1063 | Line 1113 | begin
1113    end;
1114   end;
1115  
1116 + procedure TIBDynamicGrid.MoveSelection;
1117 + begin
1118 +  inherited MoveSelection;
1119 +  SavePosition;
1120 + end;
1121 +
1122   procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1123   begin
1124 +  IBControlLinkChanged;
1125    inherited LinkActive(Value);
1126    if (FActive <> Value) and Value then
1127 <    Application.QueueAsyncCall(@RestorePosition,0);
1127 >    RestorePosition;
1128    FActive := Value
1129   end;
1130  
# Line 1076 | Line 1133 | procedure TIBDynamicGrid.Notification(AC
1133   begin
1134    inherited Notification(AComponent, Operation);
1135    if (Operation = opRemove) and
1136 <     (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
1136 >     (FIBControlLink <> nil) and (AComponent = DataSource) then FIBControlLink.IBDataSet := nil;
1137   end;
1138  
1139   procedure TIBDynamicGrid.UpdateActive;
1140   begin
1141    inherited UpdateActive;
1142 <  if assigned(FDataLink) and assigned(FDataLink.DataSet) and
1143 <     FDataLink.DataSet.Active and (FDataLink.DataSet.State = dsInsert) then
1144 <    DataSetScrolled(nil);
1142 >  if assigned(DataLink) and assigned(DataLink.DataSet) and
1143 >     DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1144 >   SavePosition;
1145   end;
1146  
1147   constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1148   begin
1149    inherited Create(TheComponent);
1150    FAllowColumnSort := true;
1151 <  FDataLink := TDynamicGridDataLink.Create(self);
1151 >  FIBControlLink := TIBGridControlLink.Create(self);
1152    FIndexFieldsList := TStringList.Create;
1153    FIndexFieldsList.Delimiter := ';';
1154    FIndexFieldsList.StrictDelimiter := true;
# Line 1103 | Line 1160 | end;
1160  
1161   destructor TIBDynamicGrid.Destroy;
1162   begin
1163 <  if assigned(FDataLink) then FDataLink.Free;
1163 >  if assigned(FIBControlLink) then FIBControlLink.Free;
1164    if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1165    if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
1166    inherited Destroy;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines