ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 39
Committed: Tue May 17 08:14:52 2016 UTC (8 years, 5 months ago) by tony
Content type: text/x-pascal
File size: 39412 byte(s)
Log Message:
Committing updates for Release R1-4-1

File Contents

# User Rev Content
1 tony 21 (*
2     * IBX For Lazarus (Firebird Express)
3     *
4     * The contents of this file are subject to the Initial Developer's
5     * Public License Version 1.0 (the "License"); you may not use this
6     * file except in compliance with the License. You may obtain a copy
7     * of the License here:
8     *
9     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10     *
11     * Software distributed under the License is distributed on an "AS
12     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13     * implied. See the License for the specific language governing rights
14     * and limitations under the License.
15     *
16     * The Initial Developer of the Original Code is Tony Whyman.
17     *
18 tony 23 * The Original Code is (C) 2015 Tony Whyman, MWA Software
19 tony 21 * (http://www.mwasoftware.co.uk).
20     *
21     * All Rights Reserved.
22     *
23     * Contributor(s): ______________________________________.
24     *
25     *)
26 tony 35
27 tony 21 unit IBDynamicGrid;
28    
29     {$mode objfpc}{$H+}
30    
31     interface
32    
33     uses
34     Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DBGrids, DB,
35 tony 27 IBSQLParser, Grids, IBLookupComboEditBox, LMessages, StdCtrls, ExtCtrls,
36     IBCustomDataSet;
37 tony 21
38     type
39     {
40     TIBDynamicGrid is a TDBGrid descendent that provides for:
41     - automatic resizing of selected columns to fill the available row length
42     - automatic positioning and sizing of a "totals" control, typically at the
43     column footer, on a per column basis.
44     - DataSet resorting on header row click, sorting the dataset by the selected column.
45     A second click on the same header cell reversed the sort order.
46     - Reselection of the same row following resorting.
47     - A new cell editor that provides the same functionality as TIBLookupComboEditBox.
48     Its properties are specified on a per column basis and allows for one or more
49     columns to have their values selected from a list provided by a dataset.
50     Autocomplete and autoinsert are also available. The existing picklist editor
51     is unaffected by the extension.
52     }
53    
54     TIBDynamicGrid = class;
55    
56     TOnColumnHeaderClick = procedure(Sender: TObject; var ColIndex: integer) of object;
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    
60     { TDBDynamicGridColumn }
61    
62     TDBDynamicGridColumn = class(TColumn)
63     private
64     FAutoSizeColumn: boolean;
65     FColumnTotalsControl: TControl;
66     FDesignWidth: integer;
67     function GetWidth: integer;
68     procedure SetWidth(AValue: integer);
69     public
70     property DesignWidth: integer read FDesignWidth;
71     published
72     property ColumnTotalsControl: TControl read FColumnTotalsControl write FColumnTotalsControl;
73     property AutoSizeColumn: boolean read FAutoSizeColumn write FAutoSizeColumn;
74     property Width: integer read GetWidth write SetWidth;
75     end;
76    
77     TIBDynamicGridColumn = class;
78    
79     { TDBLookupProperties }
80    
81     TDBLookupProperties = class(TPersistent)
82     private
83     FAutoComplete: boolean;
84     FAutoCompleteText: TComboBoxAutoCompleteText;
85     FAutoInsert: boolean;
86     FDataFieldName: string;
87     FItemHeight: integer;
88     FItemWidth: integer;
89     FKeyField: string;
90     FKeyPressInterval: integer;
91     FListField: string;
92     FListSource: TDataSource;
93     FOnAutoInsert: TAutoInsert;
94     FOnCanAutoInsert: TCanAutoInsert;
95 tony 31 FOnCloseUp: TNotifyEvent;
96 tony 21 FOnDrawItem: TDrawItemEvent;
97     FOwner: TIBDynamicGridColumn;
98     FRelationName: string;
99     FStyle: TComboBoxStyle;
100     function GetAutoCompleteText: TComboBoxAutoCompleteText;
101     procedure SetAutoCompleteText(AValue: TComboBoxAutoCompleteText);
102     public
103     constructor Create(aOwner: TIBDynamicGridColumn);
104     property Owner: TIBDynamicGridColumn read FOwner;
105     published
106     property DataFieldName: string read FDataFieldName write FDataFieldName;
107     property KeyField: string read FKeyField write FKeyField;
108     property ItemHeight: integer read FItemHeight write FItemHeight;
109     property ItemWidth: integer read FItemWidth write FItemWidth;
110     property ListSource: TDataSource read FListSource write FListSource;
111     property ListField: string read FListField write FListField;
112     property AutoInsert: boolean read FAutoInsert write FAutoInsert default true;
113     property AutoComplete: boolean read FAutoComplete write FAutoComplete default true;
114     property AutoCompleteText: TComboBoxAutoCompleteText
115     read GetAutoCompleteText write SetAutoCompleteText
116     default DefaultComboBoxAutoCompleteText;
117     property KeyPressInterval: integer read FKeyPressInterval write FKeyPressInterval default 500;
118     property RelationName: string read FRelationName write FRelationName;
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 tony 31 property OnCloseUp: TNotifyEvent read FOnCloseUp write FOnCloseUp;
123 tony 21 property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
124     end;
125    
126     TDBLookupCellEditor = class;
127    
128     { TIBDynamicGridColumn }
129    
130     TIBDynamicGridColumn = class(TDBDynamicGridColumn)
131     private
132     FDBLookupProperties: TDBLookupProperties;
133     FInitialSortColumn: boolean;
134     procedure DoSetupEditor(Data: PtrInt);
135     procedure DoSetDataSources(Data: PtrInt);
136     procedure SetInitialSortColumn(AValue: boolean);
137     public
138     procedure SetupEditor(Editor: TDBlookupCellEditor);
139     constructor Create(ACollection: TCollection); override;
140     destructor Destroy; override;
141     published
142     property InitialSortColumn: boolean read FInitialSortColumn write SetInitialSortColumn;
143     property DBLookupProperties: TDBLookupProperties read FDBLookupProperties write FDBLookupProperties;
144     end;
145    
146     { TDBLookupCellEditor }
147    
148     TDBLookupCellEditor = class(TIBLookupComboEditBox)
149     private
150     FGrid: TCustomGrid;
151     FCol,FRow: Integer;
152     FEditText: string;
153 tony 39 function EditingKeyField: boolean;
154 tony 21 protected
155     procedure WndProc(var TheMessage : TLMessage); override;
156     procedure CloseUp; override;
157     procedure KeyDown(var Key : Word; Shift : TShiftState); override;
158 tony 27 procedure Loaded; override;
159 tony 21 procedure msg_GetValue(var Msg: TGridMessage); message GM_GETVALUE;
160     procedure msg_SetGrid(var Msg: TGridMessage); message GM_SETGRID;
161     procedure msg_SetValue(var Msg: TGridMessage); message GM_SETVALUE;
162     procedure msg_SetPos(var Msg: TGridMessage); message GM_SETPOS;
163     procedure msg_GetGrid(var Msg: TGridMessage); message GM_GETGRID;
164     public
165     procedure EditingDone; override;
166     property BorderStyle;
167     property OnEditingDone;
168     end;
169    
170     TDBDynamicGrid = class(TDBGrid)
171     private
172     { Private declarations }
173     FExpandEditorPanelBelowRow: boolean;
174     FEditorPanel: TWinControl;
175     FExpandedRow: integer;
176     FOnBeforeEditorHide: TNotifyEvent;
177     FOnEditorPanelHide: TNotifyEvent;
178     FOnEditorPanelShow: TNotifyEvent;
179     FOnKeyDownHander: TKeyDownHandler;
180     FResizing: boolean;
181     FWeHaveFocus: boolean;
182     FHidingEditorPanel: boolean;
183     FAllowHide: boolean;
184 tony 35 FMouseDown: boolean;
185 tony 31 function ActiveControl: TControl;
186 tony 21 procedure DoShowEditorPanel(Data: PtrInt);
187     procedure PositionTotals;
188     procedure KeyDownHandler(Sender: TObject; var Key: Word; Shift: TShiftState);
189 tony 35 procedure PerformEditorHide(Data: PtrInt);
190 tony 21 procedure SetEditorPanel(AValue: TWinControl);
191     protected
192     procedure ChangeBounds(ALeft, ATop, AWidth, AHeight: integer; KeepBase: boolean); override;
193     procedure DoEnter; override;
194     procedure DoExit; override;
195     procedure DoGridResize;
196     procedure DoEditorHide; override;
197     procedure DoEditorShow; override;
198     procedure DrawCellText(aCol,aRow: Integer; aRect: TRect; aState: TGridDrawState; aText: String); override;
199     Function EditingAllowed(ACol : Integer = -1) : Boolean; override;
200     procedure EditorHide; override;
201     procedure IndicatorClicked(Button: TMouseButton; Shift:TShiftState); virtual;
202     procedure KeyDown(var Key : Word; Shift : TShiftState); override;
203     procedure Loaded; override;
204     procedure DoOnResize; override;
205     function CreateColumns: TGridColumns; override;
206     procedure HeaderSized(IsColumn: Boolean; Index: Integer); override;
207     procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
208     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
209     procedure TopLeftChanged; override;
210     procedure UpdateActive; override;
211     procedure UpdateEditorPanelBounds;
212     procedure UpdateShowing; override;
213     public
214     procedure HideEditorPanel;
215     procedure ShowEditorPanel;
216     constructor Create(TheComponent: TComponent); override;
217     destructor Destroy ;override;
218     procedure ResizeColumns;
219 tony 27 property VisibleRowCount;
220 tony 21 published
221     property EditorPanel: TWinControl read FEditorPanel write SetEditorPanel;
222     property ExpandEditorPanelBelowRow: boolean read FExpandEditorPanelBelowRow write FExpandEditorPanelBelowRow;
223     property OnBeforeEditorHide: TNotifyEvent read FOnBeforeEditorHide write FOnBeforeEditorHide;
224     property OnEditorPanelShow: TNotifyEvent read FOnEditorPanelShow write FOnEditorPanelShow;
225     property OnEditorPanelHide: TNotifyEvent read FOnEditorPanelHide write FOnEditorPanelHide;
226     property OnKeyDownHander: TKeyDownHandler read FOnKeyDownHander write FOnKeyDownHander;
227     end;
228    
229 tony 27 {TIBGridControlLink}
230    
231     TIBGridControlLink = class(TIBControlLink)
232     private
233     FOwner: TIBDynamicGrid;
234     protected
235     procedure UpdateSQL(Sender: TObject); override;
236     public
237     constructor Create(AOwner: TIBDynamicGrid);
238     end;
239    
240     TLocationArray = array of variant;
241     PLocationArray = ^TLocationArray;
242     TOnRestorePosition = procedure(Sender: TObject; Location: PLocationArray) of object;
243    
244 tony 21 { TIBDynamicGrid }
245    
246     TIBDynamicGrid = class(TDBDynamicGrid)
247     private
248     { Private declarations }
249     FAllowColumnSort: boolean;
250 tony 27 FIBControlLink: TIBGridControlLink;
251 tony 21 FOnColumnHeaderClick: TOnColumnHeaderClick;
252 tony 27 FOnRestorePosition: TOnRestorePosition;
253 tony 21 FOnUpdateSortOrder: TOnUpdateSortOrder;
254     FDefaultPositionAtEnd: boolean;
255     FDescending: boolean;
256     FColHeaderClick: boolean;
257     FLastColIndex: integer;
258     FIndexFieldNames: string;
259     FIndexFieldsList: TStringList;
260 tony 27 FBookmark: TLocationArray;
261 tony 21 FDBLookupCellEditor: TDBLookupCellEditor;
262     FActive: boolean;
263 tony 37 FFieldPosition: integer;
264 tony 21 procedure ColumnHeaderClick(Index: integer);
265     function GetDataSource: TDataSource;
266     function GetEditorBorderStyle: TBorderStyle;
267 tony 27 procedure IBControlLinkChanged;
268 tony 21 procedure SetDataSource(AValue: TDataSource);
269     procedure SetEditorBorderStyle(AValue: TBorderStyle);
270     procedure ProcessColumns;
271     procedure SetIndexFieldNames(AValue: string);
272     procedure UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
273     procedure UpdateSortColumn(Sender: TObject);
274 tony 27 procedure RestorePosition;
275     procedure SavePosition;
276 tony 21 procedure DoReOpen(Data: PtrInt);
277     procedure SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer);
278     protected
279     { Protected declarations }
280     procedure DoEditorHide; override;
281     procedure Loaded; override;
282     function CreateColumns: TGridColumns; override;
283     procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
284     procedure LinkActive(Value: Boolean); override;
285 tony 27 procedure MoveSelection; override;
286 tony 21 procedure Notification(AComponent: TComponent; Operation: TOperation); override;
287     procedure UpdateActive; override;
288     public
289     { Public declarations }
290     constructor Create(TheComponent: TComponent); override;
291     destructor Destroy; override;
292     function EditorByStyle(Style: TColumnButtonStyle): TWinControl; override;
293     property LastSortColumn: integer read FLastColIndex;
294     published
295     { Published declarations }
296     property AllowColumnSort: boolean read FAllowColumnSort write FAllowColumnSort default true;
297     property DataSource: TDataSource read GetDataSource write SetDataSource;
298     property Descending: boolean read FDescending write FDescending;
299     property EditorBorderStyle: TBorderStyle read GetEditorBorderStyle write SetEditorBorderStyle;
300     property DefaultPositionAtEnd: boolean read FDefaultPositionAtEnd write FDefaultPositionAtEnd;
301     property IndexFieldNames: string read FIndexFieldNames write SetIndexFieldNames;
302     property OnColumnHeaderClick: TOnColumnHeaderClick read FOnColumnHeaderClick write FOnColumnHeaderClick;
303 tony 27 property OnRestorePosition: TOnRestorePosition read FOnRestorePosition write FOnRestorePosition;
304 tony 21 property OnUpdateSortOrder: TOnUpdateSortOrder read FOnUpdateSortOrder write FOnUpdateSortOrder;
305     end;
306    
307     implementation
308    
309 tony 39 uses Math, IBQuery, LCLType, Variants;
310 tony 21
311 tony 27 { TIBGridControlLink }
312    
313     constructor TIBGridControlLink.Create(AOwner: TIBDynamicGrid);
314     begin
315     inherited Create;
316     FOwner := AOwner;
317     end;
318    
319     procedure TIBGridControlLink.UpdateSQL(Sender: TObject);
320     begin
321     FOwner.UpdateSQL(self,TIBParserDataSet(Sender).Parser)
322     end;
323    
324 tony 21 { TDBLookupProperties }
325    
326     function TDBLookupProperties.GetAutoCompleteText: TComboBoxAutoCompleteText;
327     begin
328     Result := FAutoCompleteText;
329     if AutoComplete then
330     Result := Result + [cbactEnabled]
331     end;
332    
333     procedure TDBLookupProperties.SetAutoCompleteText(
334     AValue: TComboBoxAutoCompleteText);
335     begin
336     if AValue <> AutoCompleteText then
337     begin
338     FAutoComplete := cbactEnabled in AValue;
339     FAutoCompleteText := AValue - [cbactEnabled]
340     end;
341     end;
342    
343     constructor TDBLookupProperties.Create(aOwner: TIBDynamicGridColumn);
344     begin
345     inherited Create;
346     FOwner := aOwner;
347     FAutoInsert := true;
348     FAutoComplete := true;
349     FAutoCompleteText := DefaultComboBoxAutoCompleteText;
350     FKeyPressInterval := 500;
351     FListSource := nil;
352     FStyle := csDropDown;
353     end;
354    
355     { TDBDynamicGrid }
356    
357     procedure TDBDynamicGrid.DoGridResize;
358     var ColSum: integer;
359     ResizeColCount: integer;
360     I: integer;
361     adjustment: integer;
362     n: integer;
363     begin
364     if (csDesigning in ComponentState) or (Columns.Count = 0) then Exit;
365    
366     FResizing := true;
367     try
368     ColSum := 0;
369    
370 tony 35 if (ColCount = 1) and TDBDynamicGridColumn(Columns[0]).AutoSizeColumn then
371     Columns[0].Width := ClientWidth
372     else
373 tony 21 begin
374 tony 35 for I := 0 to ColCount - 1 do
375 tony 39 if (I < FixedCols) or Columns[I - FixedCols].Visible then
376 tony 35 ColSum := ColSum + ColWidths[I];
377 tony 21
378 tony 35 if Colsum <> ClientWidth then
379     begin
380     ResizeColCount := 0;
381     for I := 0 to Columns.Count -1 do
382 tony 39 if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn and Columns[I].Visible then
383 tony 35 begin
384     Inc(ResizeColCount);
385     Colsum := Colsum + TDBDynamicGridColumn(Columns[I]).DesignWidth - Columns[I].Width;
386     Columns[I].Width := TDBDynamicGridColumn(Columns[I]).DesignWidth;
387     end;
388 tony 21
389 tony 35 if (Colsum < ClientWidth) and (ResizeColCount > 0) then
390     begin
391     adjustment := (ClientWidth - ColSum) div ResizeColCount;
392     n := (ClientWidth - ColSum) mod ResizeColCount;
393    
394     for I := 0 to Columns.Count -1 do
395 tony 39 if TDBDynamicGridColumn(Columns[I]).AutoSizeColumn and Columns[I].Visible then
396 tony 35 begin
397     if I = 0 then
398     Columns[I].Width := Columns[I].Width + adjustment + n
399     else
400     Columns[I].Width := Columns[I].Width + adjustment;
401     end;
402     end;
403     end;
404 tony 21 end;
405     PositionTotals;
406     UpdateEditorPanelBounds;
407     finally
408     FResizing := false
409     end;
410     end;
411    
412     procedure TDBDynamicGrid.DoEditorHide;
413     begin
414     inherited DoEditorHide;
415 tony 27 if Editor = FEditorPanel then
416     begin
417 tony 35 if FMouseDown then
418     Application.QueueAsyncCall(@PerformEditorHide,FExpandedRow)
419     else
420     PerformEditorHide(FExpandedRow);
421 tony 27 FExpandedRow := -1;
422     end;
423 tony 21 end;
424    
425     procedure TDBDynamicGrid.DoEditorShow;
426     begin
427 tony 35 if assigned(DataSource) and assigned(DataSource.DataSet) and
428     DataSource.DataSet.Active then
429     begin
430     if (DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert) then
431     DataSource.DataSet.Append
432     end;
433 tony 21 if Editor = FEditorPanel then
434     begin
435     if ExpandEditorPanelBelowRow then
436     RowHeights[Row] := FEditorPanel.Height + DefaultRowHeight
437     else
438     RowHeights[Row] := FEditorPanel.Height;
439     FExpandedRow := Row;
440     inherited DoEditorShow;
441     UpdateEditorPanelBounds; {Position Editor Panel over expanded Row}
442     FEditorPanel.PerformTab(true); {Select First Control}
443     if assigned(FOnEditorPanelShow) then
444     OnEditorPanelShow(self);
445 tony 35 if assigned(Editor) and Editor.Visible then
446     Editor.SetFocus;
447 tony 21 end
448     else
449     inherited DoEditorShow;
450     end;
451    
452     procedure TDBDynamicGrid.DrawCellText(aCol, aRow: Integer; aRect: TRect;
453     aState: TGridDrawState; aText: String);
454     var Style: TTextStyle;
455     OldStyle: TTextStyle;
456     begin
457     if ExpandEditorPanelBelowRow and assigned(FEditorPanel) and FEditorPanel.Visible and (aRow = FExpandedRow) then
458     begin
459     {Draw the text at the top of the cell}
460     Style := Canvas.TextStyle;
461     OldStyle := Style;
462     try
463     Style.Layout := tlTop;
464     Canvas.TextStyle := Style;
465     inherited DrawCellText(aCol, aRow, aRect, aState, aText);
466     finally
467     Canvas.TextStyle := OldStyle;
468     end;
469    
470     end
471     else
472     inherited DrawCellText(aCol, aRow, aRect, aState, aText);
473     end;
474    
475     function TDBDynamicGrid.EditingAllowed(ACol: Integer): Boolean;
476     begin
477     Result := ((FEditorPanel <> nil) and (FEditorPanel = Editor))
478     or inherited EditingAllowed(ACol);
479     end;
480    
481     procedure TDBDynamicGrid.EditorHide;
482     begin
483     if assigned(FOnBeforeEditorHide) then
484     OnBeforeEditorHide(self);
485     inherited EditorHide;
486     end;
487    
488     procedure TDBDynamicGrid.IndicatorClicked(Button: TMouseButton;
489     Shift: TShiftState);
490     begin
491     if assigned(FEditorPanel) then
492     begin
493     if FEditorPanel.Visible then
494     HideEditorPanel
495     else
496     ShowEditorPanel;
497     end;
498     end;
499    
500     procedure TDBDynamicGrid.KeyDown(var Key: Word; Shift: TShiftState);
501     begin
502     if (Key = VK_F2) and (Shift = []) and assigned(FEditorPanel) then
503     begin
504     if not FEditorPanel.Visible then
505     ShowEditorPanel
506     end
507     else
508     inherited KeyDown(Key, Shift);
509     end;
510    
511 tony 31 function TDBDynamicGrid.ActiveControl: TControl;
512     var AParent: TWinControl;
513     begin
514     Result := nil;
515     AParent := Parent;
516     while (AParent <> nil) and not (AParent is TCustomForm) do
517     AParent := AParent.Parent;
518     if (AParent <> nil) and (AParent is TCustomForm)then
519     Result := TCustomForm(AParent).ActiveControl;
520     end;
521    
522 tony 21 procedure TDBDynamicGrid.DoShowEditorPanel(Data: PtrInt);
523     begin
524     if AppDestroying in Application.Flags then Exit;
525     ShowEditorPanel;
526     end;
527    
528     procedure TDBDynamicGrid.PositionTotals;
529     var I: integer;
530     acol: TDBDynamicGridColumn;
531     LPos: integer;
532     begin
533     LPos := Left;
534     for I := 0 to FirstGridColumn - 1 do
535     LPos := LPos + ColWidths[I];
536    
537     for I := 0 to Columns.Count - 1 do
538     begin
539     acol := TDBDynamicGridColumn(Columns[I]);
540     if assigned(acol.FColumnTotalsControl) then
541     begin
542     acol.FColumnTotalsControl.AutoSize := false;
543     acol.FColumnTotalsControl.Left := LPos;
544     acol.FColumnTotalsControl.Width := acol.Width
545     end;
546     LPos := LPos + acol.Width;
547     end;
548     end;
549    
550     procedure TDBDynamicGrid.KeyDownHandler(Sender: TObject; var Key: Word;
551     Shift: TShiftState);
552     var Done: boolean;
553 tony 31 AControl: TControl;
554 tony 21 begin
555     if Visible and assigned(FEditorPanel) and FEditorPanel.Visible and FWeHaveFocus then
556     begin
557     Done := false;
558 tony 31 AControl := ActiveControl;
559     if (AControl <> nil) and (AControl is TCustomComboBox)
560     and ((Key in [VK_UP,VK_DOWN]) or
561     (TCustomComboBox(AControl).DroppedDown and (Key = VK_RETURN)) or
562     ((TCustomComboBox(AControl).Text <> '') and (Key = VK_ESCAPE))) then
563     Exit; {ignore these keys if we are in a combobox}
564    
565     if (AControl <> nil) and (AControl is TCustomMemo)
566 tony 35 and (Key in [VK_RETURN,VK_UP,VK_DOWN]) then Exit; {Ignore Return in a CustomMemo}
567    
568     if (AControl <> nil) and (AControl is TCustomGrid)
569     and (Key in [VK_RETURN,VK_UP,VK_DOWN,VK_TAB]) then Exit; {Ignore Return in a CustomMemo}
570    
571 tony 21 if assigned(FOnKeyDownHander) then
572     OnKeyDownHander(Sender,Key,Shift,Done);
573     if Done then Exit;
574    
575     {Allow Scrolling}
576     if Key in [VK_UP,VK_DOWN] then
577     KeyDown(Key,Shift)
578     else
579     {Cancel Editor}
580     if Key = VK_ESCAPE then
581     begin
582     if DataLink.DataSet.State in [dsInsert,dsEdit] then
583     DataLink.DataSet.Cancel;
584     KeyDown(Key,Shift);
585     end
586     {save}
587     else
588     if Key = VK_F2 then
589     HideEditorPanel;
590     end
591     end;
592    
593 tony 35 procedure TDBDynamicGrid.PerformEditorHide(Data: PtrInt);
594     var ExpandedRow: integer;
595     begin
596     if AppDestroying in Application.Flags then Exit;
597     ExpandedRow := integer(Data);
598     if (ExpandedRow >= 0) and (ExpandedRow < RowCount) then
599     RowHeights[ExpandedRow] := DefaultRowHeight;
600     if CanFocus then SetFocus;
601     DoOnResize;
602     ResetSizes;
603     DoOnChangeBounds;
604     if assigned(FOnEditorPanelHide) then
605     OnEditorPanelHide(self);
606     end;
607    
608 tony 21 procedure TDBDynamicGrid.SetEditorPanel(AValue: TWinControl);
609     begin
610     if FEditorPanel = AValue then Exit;
611     if FEditorPanel <> nil then
612     RemoveFreeNotification(FEditorPanel);
613     FEditorPanel := AValue;
614 tony 39 if FEditorPanel <> nil then
615     FreeNotification(FEditorPanel);
616 tony 21 end;
617    
618     procedure TDBDynamicGrid.ChangeBounds(ALeft, ATop, AWidth, AHeight: integer;
619     KeepBase: boolean);
620     begin
621     if assigned(FEditorPanel) and FEditorPanel.Visible then
622     Application.QueueAsyncCall(@DoShowEditorPanel,0); {Restore afterwards if necessary}
623     inherited ChangeBounds(ALeft, ATop, AWidth, AHeight, KeepBase);
624     end;
625    
626     procedure TDBDynamicGrid.DoEnter;
627     begin
628     inherited DoEnter;
629     FWeHaveFocus := true;
630     end;
631    
632     procedure TDBDynamicGrid.DoExit;
633     begin
634     FWeHaveFocus := false;
635     inherited DoExit;
636     end;
637    
638     procedure TDBDynamicGrid.Loaded;
639     begin
640     inherited Loaded;
641     if assigned(FEditorPanel) and not (csDesigning in ComponentState)then
642     FEditorPanel.Visible := false;
643 tony 35 if Visible then
644     DoGridResize
645 tony 21 end;
646    
647     procedure TDBDynamicGrid.DoOnResize;
648     begin
649     inherited DoOnResize;
650     DoGridResize
651     end;
652    
653     function TDBDynamicGrid.CreateColumns: TGridColumns;
654     begin
655     result := TDBGridColumns.Create(Self, TDBDynamicGridColumn);
656     end;
657    
658     procedure TDBDynamicGrid.HeaderSized(IsColumn: Boolean; Index: Integer);
659     begin
660     inherited HeaderSized(IsColumn, Index);
661     PositionTotals
662     end;
663    
664     procedure TDBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
665     Y: Integer);
666     var Coord: TGridCoord;
667     begin
668 tony 35 FMouseDown := true;
669     try
670     inherited MouseDown(Button, Shift, X, Y);
671     finally
672     FMouseDown := false;
673     end;
674 tony 21
675     Coord := MouseCoord(X,Y);
676     if (Coord.X = 0) and (Coord.Y > 0) then
677     IndicatorClicked(Button,Shift);
678     end;
679    
680     procedure TDBDynamicGrid.Notification(AComponent: TComponent;
681     Operation: TOperation);
682 tony 39 var i: integer;
683 tony 21 begin
684     inherited Notification(AComponent, Operation);
685 tony 39 if (Operation = opRemove) and not (csDestroying in ComponentState) then
686     begin
687     if AComponent = FEditorPanel then
688     FEditorPanel := nil
689     else
690     if AComponent is TControl then
691     begin
692     for i := 0 to Columns.Count - 1 do
693     if TDBDynamicGridColumn(Columns[I]).ColumnTotalsControl = AComponent then
694     TDBDynamicGridColumn(Columns[I]).ColumnTotalsControl := nil;
695     end;
696     end
697 tony 21 end;
698    
699     procedure TDBDynamicGrid.TopLeftChanged;
700     begin
701     inherited TopLeftChanged;
702     UpdateEditorPanelBounds;
703     end;
704    
705     procedure TDBDynamicGrid.UpdateActive;
706     begin
707     inherited UpdateActive;
708    
709     if not (csLoading in ComponentState) and assigned(DataLink) and
710 tony 35 assigned(FEditorPanel) and not FEditorPanel.Visible and
711 tony 21 assigned(DataLink.DataSet) and (DataLink.DataSet.State = dsInsert) then
712     Application.QueueAsyncCall(@DoShowEditorPanel,0);
713     end;
714    
715     procedure TDBDynamicGrid.UpdateEditorPanelBounds;
716     var R: TRect;
717     Dummy: integer;
718     begin
719     if assigned(FEditorPanel) and FEditorPanel.Visible and
720     (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
721     begin
722     // Upper and Lower bounds for this row
723     ColRowToOffSet(False, True, FExpandedRow, R.Top, R.Bottom);
724     //Left Bound for visible Columns
725     ColRowToOffSet(True,True,1,R.Left,Dummy);
726     //Right Bound for visible columns
727     ColRowToOffSet(True,True,ColCount - 1,Dummy,R.Right);
728     if ExpandEditorPanelBelowRow then
729     R.Top := R.Top + DefaultRowHeight;
730     FEditorPanel.BoundsRect := R;
731     end;
732     end;
733    
734     procedure TDBDynamicGrid.UpdateShowing;
735     begin
736     inherited UpdateShowing;
737     DoGridResize
738     end;
739    
740     procedure TDBDynamicGrid.HideEditorPanel;
741     begin
742     if Editor = FEditorPanel then
743 tony 35 EditorMode := false;
744 tony 21 end;
745    
746     procedure TDBDynamicGrid.ShowEditorPanel;
747     begin
748 tony 27 if (csDesigning in ComponentState) or
749     (DataSource = nil) or (DataSource.DataSet = nil)
750     or ((DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert)) then
751     Exit;
752 tony 21 Editor := FEditorPanel;
753     EditorMode := true;
754     end;
755    
756     constructor TDBDynamicGrid.Create(TheComponent: TComponent);
757     begin
758     inherited Create(TheComponent);
759     ScrollBars := ssAutoVertical;
760     if not (csDesigning in ComponentState) then
761     Application.AddOnKeyDownBeforeHandler(@KeyDownHandler,false);
762     end;
763    
764     destructor TDBDynamicGrid.Destroy;
765     begin
766     if not (csDesigning in ComponentState) then
767     Application.RemoveOnKeyDownBeforeHandler(@KeyDownHandler);
768     inherited Destroy;
769     end;
770    
771     procedure TDBDynamicGrid.ResizeColumns;
772     begin
773     DoGridResize;
774     end;
775    
776     { TDBDynamicGridColumn }
777    
778     procedure TDBDynamicGridColumn.SetWidth(AValue: integer);
779     begin
780     if Width = AValue then Exit;
781     inherited Width := AValue;
782     if not TDBDynamicGrid(Grid).FResizing then
783     FDesignWidth := Width
784     end;
785    
786     function TDBDynamicGridColumn.GetWidth: integer;
787     begin
788     Result := inherited Width
789     end;
790    
791 tony 39 type
792     THackedGrid = class(TIBDynamicGrid)
793     public
794     property FixedCols;
795     end;
796    
797 tony 21 { TDBLookupCellEditor }
798    
799 tony 39 function TDBLookupCellEditor.EditingKeyField: boolean;
800     begin
801     with TIBDynamicGridColumn(TDBGrid(FGrid).Columns[FCol - THackedGrid(FGrid).FixedCols]) do
802     Result := CompareText(FieldName, DBLookupProperties.DataFieldName) = 0;
803     end;
804    
805 tony 21 procedure TDBLookupCellEditor.WndProc(var TheMessage: TLMessage);
806     begin
807     if TheMessage.msg=LM_KILLFOCUS then begin
808     if HWND(TheMessage.WParam) = HWND(Handle) then begin
809     // lost the focus but it returns to ourselves
810     // eat the message.
811     TheMessage.Result := 0;
812     exit;
813     end;
814     end;
815     inherited WndProc(TheMessage);
816     end;
817    
818     procedure TDBLookupCellEditor.CloseUp;
819     begin
820     UpdateData(nil); {Force Record Update}
821     if FGrid<>nil then
822 tony 27 Begin
823 tony 39 if EditingKeyField then
824     begin
825     if not VarIsNull(KeyValue) then
826     (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, KeyValue)
827     end
828     else
829     (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Trim(Text));
830 tony 27 (FGrid as TIBDynamicGrid).UpdateData;
831     end;
832 tony 21 inherited CloseUp;
833     end;
834    
835     procedure TDBLookupCellEditor.KeyDown(var Key: Word; Shift: TShiftState);
836     begin
837     if (Key = VK_TAB) and assigned(FGrid) then
838     TIBDynamicGrid(FGrid).KeyDown(Key,Shift)
839     else
840     inherited KeyDown(Key, Shift);
841     end;
842    
843 tony 27 procedure TDBLookupCellEditor.Loaded;
844     begin
845     inherited Loaded;
846     Text := '';
847     end;
848    
849 tony 21 procedure TDBLookupCellEditor.msg_GetValue(var Msg: TGridMessage);
850     begin
851     CheckAndInsert;
852     Msg.Col := FCol;
853     Msg.Row := FRow;
854 tony 39 if EditingKeyField then
855     begin
856     if not VarIsNull(KeyValue) then
857     Msg.Value:= KeyValue
858     else
859     Msg.Value:= ''
860     end
861     else
862     Msg.Value:= Trim(Text);
863 tony 21 end;
864    
865     procedure TDBLookupCellEditor.msg_SetGrid(var Msg: TGridMessage);
866     begin
867     FGrid:=Msg.Grid;
868     Msg.Options:=EO_AUTOSIZE or EO_SELECTALL or EO_HOOKKEYPRESS or EO_HOOKKEYUP;
869     end;
870    
871     procedure TDBLookupCellEditor.msg_SetValue(var Msg: TGridMessage);
872     begin
873     FGrid := Msg.Grid;
874     FCol := Msg.Col;
875     FRow := Msg.Row;
876     FEditText := Msg.Value;
877     TIBDynamicGrid(FGrid).SetupEditor(self,FCol);
878     end;
879    
880     procedure TDBLookupCellEditor.msg_SetPos(var Msg: TGridMessage);
881     begin
882     FCol := Msg.Col;
883     FRow := Msg.Row;
884     end;
885    
886     procedure TDBLookupCellEditor.msg_GetGrid(var Msg: TGridMessage);
887     begin
888     Msg.Grid := FGrid;
889     Msg.Options:= EO_IMPLEMENTED;
890     end;
891    
892     procedure TDBLookupCellEditor.EditingDone;
893     begin
894     inherited EditingDone;
895     if FGrid<>nil then
896     FGrid.EditingDone;
897     end;
898    
899     { TIBDynamicGridColumn }
900    
901     procedure TIBDynamicGridColumn.DoSetupEditor(Data: PtrInt);
902     var Editor: TDBlookupCellEditor;
903     begin
904     if AppDestroying in Application.Flags then Exit;
905    
906     Editor := TDBlookupCellEditor(Data);
907     Editor.DataSource := nil;
908     Editor.ListSource := nil; {Allows change without causing an error}
909     Editor.KeyValue := NULL;
910    
911     with DBLookupProperties do
912     begin
913     {Setup Properties}
914     Editor.AutoInsert := AutoInsert;
915     Editor.AutoComplete := AutoComplete;
916     Editor.AutoCompleteText := AutoCompleteText;
917     Editor.KeyPressInterval := KeyPressInterval;
918     Editor.Style := Style;
919     Editor.ItemHeight := ItemHeight;
920     Editor.ItemWidth := ItemWidth;
921     Editor.RelationName := RelationName;
922     Editor.OnAutoInsert := OnAutoInsert;
923     Editor.OnCanAutoInsert := OnCanAutoInsert;
924     Editor.OnDrawItem := OnDrawItem;
925 tony 31 Editor.OnCloseUp := OnCloseUp;
926 tony 21
927     {Setup Data Links}
928     if KeyField <> '' then
929     Editor.KeyField := KeyField
930     else
931     Editor.KeyField := ListField;
932     Editor.ListField := ListField;
933     Editor.DataField := DataFieldName;
934     end;
935     Application.QueueAsyncCall(@DoSetDataSources,PtrInt(Editor));
936     end;
937    
938     procedure TIBDynamicGridColumn.DoSetDataSources(Data: PtrInt);
939     var Editor: TDBlookupCellEditor;
940     begin
941     if AppDestroying in Application.Flags then Exit;
942    
943     Editor := TDBlookupCellEditor(Data);
944     with DBLookupProperties do
945     begin
946     Editor.ListSource := ListSource;
947     if DataFieldName <> '' then
948     Editor.DataSource := TDBGrid(Grid).DataSource;
949     end;
950 tony 39 if Editor.EditingKeyField then
951     begin
952     if not Field.IsNull then
953     Editor.KeyValue := Editor.FEditText
954     end
955     else
956     Editor.Text := Editor.FEditText;
957 tony 31 Editor.SelStart := Length(Editor.Text);
958 tony 21 end;
959    
960     procedure TIBDynamicGridColumn.SetInitialSortColumn(AValue: boolean);
961     begin
962     if FInitialSortColumn = AValue then Exit;
963     FInitialSortColumn := AValue;
964     (Grid as TIBDynamicGrid).UpdateSortColumn(self)
965     end;
966    
967     procedure TIBDynamicGridColumn.SetupEditor(Editor: TDBlookupCellEditor);
968     begin
969     Application.QueueAsyncCall(@DoSetupEditor,PtrInt(Editor));
970     end;
971    
972     constructor TIBDynamicGridColumn.Create(ACollection: TCollection);
973     begin
974     inherited Create(ACollection);
975     FDBLookupProperties := TDBLookupProperties.Create(self);
976     end;
977    
978     destructor TIBDynamicGridColumn.Destroy;
979     begin
980     if assigned(FDBLookupProperties) then FDBLookupProperties.Free;
981     inherited Destroy;
982     end;
983    
984    
985     { TIBDynamicGrid }
986    
987     procedure TIBDynamicGrid.ColumnHeaderClick(Index: integer);
988     begin
989     FColHeaderClick := true;
990     try
991     if Index = FLastColIndex then
992     FDescending := not FDescending;
993    
994     if assigned(FOnColumnHeaderClick) then
995     OnColumnHeaderClick(self,Index);
996    
997     FLastColIndex := Index;
998 tony 37 FFieldPosition := 0;
999     if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active
1000     and (DataSource.DataSet is TIBParserDataSet) then
1001 tony 21 begin
1002 tony 37 if FLastColIndex < Columns.Count then
1003     {try and cache field position while dataset still open}
1004     FFieldPosition := TIBParserDataSet(DataSource.DataSet).Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1005 tony 21 DataSource.DataSet.Active := false;
1006     Application.QueueAsyncCall(@DoReopen,0)
1007     end;
1008     finally
1009     FColHeaderClick := false
1010     end;
1011     end;
1012    
1013     function TIBDynamicGrid.GetDataSource: TDataSource;
1014     begin
1015     if assigned(DataLink) then
1016     Result := inherited DataSource
1017     else
1018     Result := nil;
1019     end;
1020    
1021     function TIBDynamicGrid.GetEditorBorderStyle: TBorderStyle;
1022     begin
1023     if Editor = FDBLookupCellEditor then
1024     Result := FDBLookupCellEditor.BorderStyle
1025     else
1026     Result := inherited EditorBorderStyle
1027     end;
1028    
1029     procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
1030     begin
1031     inherited DataSource := AValue;
1032 tony 27 IBControlLinkChanged;
1033 tony 21 end;
1034    
1035     procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
1036     begin
1037     inherited EditorBorderStyle := AValue;
1038     if FDBLookupCellEditor.BorderStyle <> AValue then
1039     begin
1040     FDBLookupCellEditor.BorderStyle := AValue;
1041     if (Editor = FDBLookupCellEditor) and EditorMode then
1042     EditorWidthChanged(Col,FDBLookupCellEditor.Width);
1043     end;
1044     end;
1045    
1046     procedure TIBDynamicGrid.ProcessColumns;
1047     var i: integer;
1048     begin
1049     for i := 0 to Columns.Count - 1 do
1050     begin
1051     if TIBDynamicGridColumn(columns[i]).InitialSortColumn then
1052 tony 37 begin
1053     FFieldPosition := 0;
1054 tony 21 FLastColIndex := i
1055 tony 37 end
1056 tony 21 end
1057     end;
1058    
1059     procedure TIBDynamicGrid.SetIndexFieldNames(AValue: string);
1060     var idx: integer;
1061     begin
1062     if FIndexFieldNames = AValue then Exit;
1063     FIndexFieldNames := AValue;
1064     idx := 1;
1065     FIndexFieldsList.Clear;
1066     while idx <= Length(AValue) do
1067     FIndexFieldsList.Add(ExtractFieldName(AValue,idx));
1068     end;
1069    
1070     procedure TIBDynamicGrid.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
1071     var OrderBy: string;
1072     begin
1073 tony 27 if assigned(DataSource) and assigned(DataSource.DataSet)
1074 tony 21 and (DataSource.DataSet is TIBCustomDataSet) then
1075     begin
1076 tony 37 if (FFieldPosition = 0) and (FLastColIndex >= 0) and (FLastColIndex < Columns.Count) then
1077     {Not cached - let's hope we can find it before the dataset is opened.
1078     Won't work if dynamic columns}
1079     FFieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1080     if FFieldPosition > 0 then
1081 tony 35 begin
1082     if Descending then
1083 tony 37 Parser.OrderByClause := IntToStr(FFieldPosition) + ' desc'
1084 tony 35 else
1085 tony 37 Parser.OrderByClause := IntToStr(FFieldPosition) + ' asc';
1086 tony 35 end;
1087 tony 21
1088     if assigned(FOnUpdateSortOrder) then
1089     begin
1090     OrderBy := Parser.OrderByClause;
1091     OnUpdateSortOrder(self,FLastColIndex,OrderBy);
1092     Parser.OrderByClause := OrderBy
1093     end
1094     end;
1095     end;
1096    
1097     procedure TIBDynamicGrid.UpdateSortColumn(Sender: TObject);
1098     var i: integer;
1099     begin
1100     if Sender is TIBDynamicGridColumn then
1101     begin
1102     for i := 0 to Columns.Count -1 do
1103     if TObject(Columns[i]) <> Sender then
1104     TIBDynamicGridColumn(Columns[i]).InitialSortColumn := false
1105     end
1106    
1107     end;
1108    
1109 tony 27 procedure TIBDynamicGrid.RestorePosition;
1110 tony 21 begin
1111     if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1112     begin
1113 tony 27 if assigned(FOnRestorePosition) then
1114     OnRestorePosition(self,@FBookmark);
1115 tony 21 if (Length(FBookmark) > 0) and
1116     DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1117    
1118     if FDefaultPositionAtEnd then
1119     DataSource.DataSet.Last
1120     end;
1121     end;
1122    
1123 tony 27 procedure TIBDynamicGrid.SavePosition;
1124     var i: integer;
1125     F: TField;
1126     begin
1127     if FIndexFieldsList = nil then Exit;
1128    
1129     SetLength(FBookmark,FIndexFieldsList.Count);
1130     for i := 0 to FIndexFieldsList.Count - 1 do
1131     begin
1132     F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
1133     if assigned(F) then
1134     FBookmark[i] := F.AsVariant;
1135     end;
1136     end;
1137    
1138 tony 21 procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1139     begin
1140     DataSource.DataSet.Active := true;
1141     end;
1142    
1143 tony 27 procedure TIBDynamicGrid.IBControlLinkChanged;
1144     begin
1145     if (DataSource <> nil) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataSet) then
1146     FIBControlLink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
1147     else
1148     FIBControlLink.IBDataSet := nil;
1149     end;
1150    
1151 tony 21 procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1152     );
1153     var C: TIBDynamicGridColumn;
1154     begin
1155     C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1156 tony 27 if (c <> nil) then
1157     C.SetupEditor(aEditor);
1158 tony 21 end;
1159    
1160     procedure TIBDynamicGrid.DoEditorHide;
1161     var i: integer;
1162     begin
1163     inherited DoEditorHide;
1164     if assigned(EditorPanel) then
1165     for i := 0 to EditorPanel.ControlCount -1 do
1166     if EditorPanel.Controls[i] is TIBLookupComboEditBox then
1167     EditorPanel.Controls[i].Perform(CM_VISIBLECHANGED, WParam(ord(false)), 0);
1168     end;
1169    
1170     procedure TIBDynamicGrid.Loaded;
1171     begin
1172     inherited Loaded;
1173 tony 29 IBControlLinkChanged;
1174 tony 21 ProcessColumns;
1175     end;
1176    
1177     function TIBDynamicGrid.CreateColumns: TGridColumns;
1178     begin
1179     result := TDBGridColumns.Create(Self, TIBDynamicGridColumn);
1180     end;
1181    
1182     procedure TIBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
1183     Y: Integer);
1184     var Coord: TGridCoord;
1185     obe: boolean;
1186     function PtInRect(const Rect : TRect;const p : TPoint) : Boolean;
1187    
1188     begin
1189     PtInRect:=(p.y>=Rect.Top) and
1190     (p.y<Rect.Bottom) and
1191     (p.x>=Rect.Left) and
1192     (p.x<Rect.Right);
1193     end;
1194     begin
1195     if (Editor is TDBLookupCellEditor) and Editor.Visible
1196     and not PtInRect(Editor.BoundsRect,Point(X,Y)) then
1197     Editor.Perform(CM_EXIT,0,0); {Do insert new value if necessary}
1198     inherited MouseDown(Button, Shift, X, Y);
1199     obe := AllowOutboundEvents;
1200     AllowOutboundEvents := false;
1201     try
1202     Coord := MouseCoord(X,Y);
1203 tony 27 if AllowColumnSort and (Coord.X <> -1) and (FixedRows > 0) and
1204 tony 21 (Coord.Y = 0) and (MouseCoord(X+5,Y).X = Coord.X) {not on boundary}
1205     and (MouseCoord(X-5,Y).X = Coord.X) then
1206     ColumnHeaderClick(Coord.X-1);
1207     finally
1208     AllowOutboundEvents := obe
1209     end;
1210     end;
1211    
1212 tony 27 procedure TIBDynamicGrid.MoveSelection;
1213     begin
1214     inherited MoveSelection;
1215     SavePosition;
1216     end;
1217    
1218 tony 21 procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1219     begin
1220 tony 27 IBControlLinkChanged;
1221 tony 21 inherited LinkActive(Value);
1222     if (FActive <> Value) and Value then
1223 tony 27 RestorePosition;
1224 tony 21 FActive := Value
1225     end;
1226    
1227     procedure TIBDynamicGrid.Notification(AComponent: TComponent;
1228     Operation: TOperation);
1229 tony 39 var i: integer;
1230 tony 21 begin
1231     inherited Notification(AComponent, Operation);
1232 tony 39 if (Operation = opRemove) then
1233     begin
1234     if (FIBControlLink <> nil) and (AComponent = DataSource) then
1235     FIBControlLink.IBDataSet := nil
1236     else
1237     if AComponent is TDataSource then
1238     begin
1239     for i := 0 to Columns.Count - 1 do
1240     if TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource = AComponent then
1241     TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource := nil;
1242     end
1243     end
1244 tony 21 end;
1245    
1246     procedure TIBDynamicGrid.UpdateActive;
1247     begin
1248     inherited UpdateActive;
1249 tony 27 if assigned(DataLink) and assigned(DataLink.DataSet) and
1250     DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1251     SavePosition;
1252 tony 21 end;
1253    
1254     constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1255     begin
1256     inherited Create(TheComponent);
1257     FAllowColumnSort := true;
1258 tony 27 FIBControlLink := TIBGridControlLink.Create(self);
1259 tony 21 FIndexFieldsList := TStringList.Create;
1260     FIndexFieldsList.Delimiter := ';';
1261     FIndexFieldsList.StrictDelimiter := true;
1262     FDBLookupCellEditor := TDBLookupCellEditor.Create(nil);
1263     FDBLookupCellEditor.Name := 'DBLookupCellEditor';
1264     FDBLookupCellEditor.Visible := False;
1265     FDBLookupCellEditor.AutoSize := false;
1266     end;
1267    
1268     destructor TIBDynamicGrid.Destroy;
1269     begin
1270 tony 27 if assigned(FIBControlLink) then FIBControlLink.Free;
1271 tony 21 if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1272     if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
1273     inherited Destroy;
1274     end;
1275    
1276     function TIBDynamicGrid.EditorByStyle(Style: TColumnButtonStyle): TWinControl;
1277     var C: TIBDynamicGridColumn;
1278     bs: TColumnButtonStyle;
1279     begin
1280     C := ColumnFromGridColumn(Col) as TIBDynamicGridColumn;
1281     if C <> nil then
1282     begin
1283     bs := C.ButtonStyle;
1284     if (bs in [cbsAuto,cbsPickList]) and assigned(C.DBLookupProperties.ListSource) then
1285     begin
1286     Result := FDBLookupCellEditor;
1287     Exit;
1288     end;
1289     end;
1290     Result := inherited EditorByStyle(Style);
1291     end;
1292    
1293     end.