ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 37
Committed: Mon Feb 15 14:44:25 2016 UTC (8 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 37811 byte(s)
Log Message:
Committing updates for Release R1-4-0

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     protected
154     procedure WndProc(var TheMessage : TLMessage); override;
155     procedure CloseUp; override;
156     procedure KeyDown(var Key : Word; Shift : TShiftState); override;
157 tony 27 procedure Loaded; override;
158 tony 21 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;
161     procedure msg_SetPos(var Msg: TGridMessage); message GM_SETPOS;
162     procedure msg_GetGrid(var Msg: TGridMessage); message GM_GETGRID;
163     public
164     procedure EditingDone; override;
165     property BorderStyle;
166     property OnEditingDone;
167     end;
168    
169     TDBDynamicGrid = class(TDBGrid)
170     private
171     { Private declarations }
172     FExpandEditorPanelBelowRow: boolean;
173     FEditorPanel: TWinControl;
174     FExpandedRow: integer;
175     FOnBeforeEditorHide: TNotifyEvent;
176     FOnEditorPanelHide: TNotifyEvent;
177     FOnEditorPanelShow: TNotifyEvent;
178     FOnKeyDownHander: TKeyDownHandler;
179     FResizing: boolean;
180     FWeHaveFocus: boolean;
181     FHidingEditorPanel: boolean;
182     FAllowHide: boolean;
183 tony 35 FMouseDown: boolean;
184 tony 31 function ActiveControl: TControl;
185 tony 21 procedure DoShowEditorPanel(Data: PtrInt);
186     procedure PositionTotals;
187     procedure KeyDownHandler(Sender: TObject; var Key: Word; Shift: TShiftState);
188 tony 35 procedure PerformEditorHide(Data: PtrInt);
189 tony 21 procedure SetEditorPanel(AValue: TWinControl);
190     protected
191     procedure ChangeBounds(ALeft, ATop, AWidth, AHeight: integer; KeepBase: boolean); override;
192     procedure DoEnter; override;
193     procedure DoExit; override;
194     procedure DoGridResize;
195     procedure DoEditorHide; override;
196     procedure DoEditorShow; override;
197     procedure DrawCellText(aCol,aRow: Integer; aRect: TRect; aState: TGridDrawState; aText: String); override;
198     Function EditingAllowed(ACol : Integer = -1) : Boolean; override;
199     procedure EditorHide; override;
200     procedure IndicatorClicked(Button: TMouseButton; Shift:TShiftState); virtual;
201     procedure KeyDown(var Key : Word; Shift : TShiftState); override;
202     procedure Loaded; override;
203     procedure DoOnResize; override;
204     function CreateColumns: TGridColumns; override;
205     procedure HeaderSized(IsColumn: Boolean; Index: Integer); override;
206     procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
207     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
208     procedure TopLeftChanged; override;
209     procedure UpdateActive; override;
210     procedure UpdateEditorPanelBounds;
211     procedure UpdateShowing; override;
212     public
213     procedure HideEditorPanel;
214     procedure ShowEditorPanel;
215     constructor Create(TheComponent: TComponent); override;
216     destructor Destroy ;override;
217     procedure ResizeColumns;
218 tony 27 property VisibleRowCount;
219 tony 21 published
220     property EditorPanel: TWinControl read FEditorPanel write SetEditorPanel;
221     property ExpandEditorPanelBelowRow: boolean read FExpandEditorPanelBelowRow write FExpandEditorPanelBelowRow;
222     property OnBeforeEditorHide: TNotifyEvent read FOnBeforeEditorHide write FOnBeforeEditorHide;
223     property OnEditorPanelShow: TNotifyEvent read FOnEditorPanelShow write FOnEditorPanelShow;
224     property OnEditorPanelHide: TNotifyEvent read FOnEditorPanelHide write FOnEditorPanelHide;
225     property OnKeyDownHander: TKeyDownHandler read FOnKeyDownHander write FOnKeyDownHander;
226     end;
227    
228 tony 27 {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 tony 21 { TIBDynamicGrid }
244    
245     TIBDynamicGrid = class(TDBDynamicGrid)
246     private
247     { Private declarations }
248     FAllowColumnSort: boolean;
249 tony 27 FIBControlLink: TIBGridControlLink;
250 tony 21 FOnColumnHeaderClick: TOnColumnHeaderClick;
251 tony 27 FOnRestorePosition: TOnRestorePosition;
252 tony 21 FOnUpdateSortOrder: TOnUpdateSortOrder;
253     FDefaultPositionAtEnd: boolean;
254     FDescending: boolean;
255     FColHeaderClick: boolean;
256     FLastColIndex: integer;
257     FIndexFieldNames: string;
258     FIndexFieldsList: TStringList;
259 tony 27 FBookmark: TLocationArray;
260 tony 21 FDBLookupCellEditor: TDBLookupCellEditor;
261     FActive: boolean;
262 tony 37 FFieldPosition: integer;
263 tony 21 procedure ColumnHeaderClick(Index: integer);
264     function GetDataSource: TDataSource;
265     function GetEditorBorderStyle: TBorderStyle;
266 tony 27 procedure IBControlLinkChanged;
267 tony 21 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 tony 27 procedure RestorePosition;
274     procedure SavePosition;
275 tony 21 procedure DoReOpen(Data: PtrInt);
276     procedure SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer);
277     protected
278     { Protected declarations }
279     procedure DoEditorHide; override;
280     procedure Loaded; override;
281     function CreateColumns: TGridColumns; override;
282     procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
283     procedure LinkActive(Value: Boolean); override;
284 tony 27 procedure MoveSelection; override;
285 tony 21 procedure Notification(AComponent: TComponent; Operation: TOperation); override;
286     procedure UpdateActive; override;
287     public
288     { Public declarations }
289     constructor Create(TheComponent: TComponent); override;
290     destructor Destroy; override;
291     function EditorByStyle(Style: TColumnButtonStyle): TWinControl; override;
292     property LastSortColumn: integer read FLastColIndex;
293     published
294     { Published declarations }
295     property AllowColumnSort: boolean read FAllowColumnSort write FAllowColumnSort default true;
296     property DataSource: TDataSource read GetDataSource write SetDataSource;
297     property Descending: boolean read FDescending write FDescending;
298     property EditorBorderStyle: TBorderStyle read GetEditorBorderStyle write SetEditorBorderStyle;
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 tony 27 property OnRestorePosition: TOnRestorePosition read FOnRestorePosition write FOnRestorePosition;
303 tony 21 property OnUpdateSortOrder: TOnUpdateSortOrder read FOnUpdateSortOrder write FOnUpdateSortOrder;
304     end;
305    
306     implementation
307    
308 tony 27 uses Math, IBQuery, LCLType;
309 tony 21
310 tony 27 { 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 tony 21 { TDBLookupProperties }
324    
325     function TDBLookupProperties.GetAutoCompleteText: TComboBoxAutoCompleteText;
326     begin
327     Result := FAutoCompleteText;
328     if AutoComplete then
329     Result := Result + [cbactEnabled]
330     end;
331    
332     procedure TDBLookupProperties.SetAutoCompleteText(
333     AValue: TComboBoxAutoCompleteText);
334     begin
335     if AValue <> AutoCompleteText then
336     begin
337     FAutoComplete := cbactEnabled in AValue;
338     FAutoCompleteText := AValue - [cbactEnabled]
339     end;
340     end;
341    
342     constructor TDBLookupProperties.Create(aOwner: TIBDynamicGridColumn);
343     begin
344     inherited Create;
345     FOwner := aOwner;
346     FAutoInsert := true;
347     FAutoComplete := true;
348     FAutoCompleteText := DefaultComboBoxAutoCompleteText;
349     FKeyPressInterval := 500;
350     FListSource := nil;
351     FStyle := csDropDown;
352     end;
353    
354     { TDBDynamicGrid }
355    
356     procedure TDBDynamicGrid.DoGridResize;
357     var ColSum: integer;
358     ResizeColCount: integer;
359     I: integer;
360     adjustment: integer;
361     n: integer;
362     begin
363     if (csDesigning in ComponentState) or (Columns.Count = 0) then Exit;
364    
365     FResizing := true;
366     try
367     ColSum := 0;
368    
369 tony 35 if (ColCount = 1) and TDBDynamicGridColumn(Columns[0]).AutoSizeColumn then
370     Columns[0].Width := ClientWidth
371     else
372 tony 21 begin
373 tony 35 for I := 0 to ColCount - 1 do
374     ColSum := ColSum + ColWidths[I];
375 tony 21
376 tony 35 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 tony 21
387 tony 35 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 tony 21 end;
403     PositionTotals;
404     UpdateEditorPanelBounds;
405     finally
406     FResizing := false
407     end;
408     end;
409    
410     procedure TDBDynamicGrid.DoEditorHide;
411     begin
412     inherited DoEditorHide;
413 tony 27 if Editor = FEditorPanel then
414     begin
415 tony 35 if FMouseDown then
416     Application.QueueAsyncCall(@PerformEditorHide,FExpandedRow)
417     else
418     PerformEditorHide(FExpandedRow);
419 tony 27 FExpandedRow := -1;
420     end;
421 tony 21 end;
422    
423     procedure TDBDynamicGrid.DoEditorShow;
424     begin
425 tony 35 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 tony 21 if Editor = FEditorPanel then
432     begin
433     if ExpandEditorPanelBelowRow then
434     RowHeights[Row] := FEditorPanel.Height + DefaultRowHeight
435     else
436     RowHeights[Row] := FEditorPanel.Height;
437     FExpandedRow := Row;
438     inherited DoEditorShow;
439     UpdateEditorPanelBounds; {Position Editor Panel over expanded Row}
440     FEditorPanel.PerformTab(true); {Select First Control}
441     if assigned(FOnEditorPanelShow) then
442     OnEditorPanelShow(self);
443 tony 35 if assigned(Editor) and Editor.Visible then
444     Editor.SetFocus;
445 tony 21 end
446     else
447     inherited DoEditorShow;
448     end;
449    
450     procedure TDBDynamicGrid.DrawCellText(aCol, aRow: Integer; aRect: TRect;
451     aState: TGridDrawState; aText: String);
452     var Style: TTextStyle;
453     OldStyle: TTextStyle;
454     begin
455     if ExpandEditorPanelBelowRow and assigned(FEditorPanel) and FEditorPanel.Visible and (aRow = FExpandedRow) then
456     begin
457     {Draw the text at the top of the cell}
458     Style := Canvas.TextStyle;
459     OldStyle := Style;
460     try
461     Style.Layout := tlTop;
462     Canvas.TextStyle := Style;
463     inherited DrawCellText(aCol, aRow, aRect, aState, aText);
464     finally
465     Canvas.TextStyle := OldStyle;
466     end;
467    
468     end
469     else
470     inherited DrawCellText(aCol, aRow, aRect, aState, aText);
471     end;
472    
473     function TDBDynamicGrid.EditingAllowed(ACol: Integer): Boolean;
474     begin
475     Result := ((FEditorPanel <> nil) and (FEditorPanel = Editor))
476     or inherited EditingAllowed(ACol);
477     end;
478    
479     procedure TDBDynamicGrid.EditorHide;
480     begin
481     if assigned(FOnBeforeEditorHide) then
482     OnBeforeEditorHide(self);
483     inherited EditorHide;
484     end;
485    
486     procedure TDBDynamicGrid.IndicatorClicked(Button: TMouseButton;
487     Shift: TShiftState);
488     begin
489     if assigned(FEditorPanel) then
490     begin
491     if FEditorPanel.Visible then
492     HideEditorPanel
493     else
494     ShowEditorPanel;
495     end;
496     end;
497    
498     procedure TDBDynamicGrid.KeyDown(var Key: Word; Shift: TShiftState);
499     begin
500     if (Key = VK_F2) and (Shift = []) and assigned(FEditorPanel) then
501     begin
502     if not FEditorPanel.Visible then
503     ShowEditorPanel
504     end
505     else
506     inherited KeyDown(Key, Shift);
507     end;
508    
509 tony 31 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 tony 21 procedure TDBDynamicGrid.DoShowEditorPanel(Data: PtrInt);
521     begin
522     if AppDestroying in Application.Flags then Exit;
523     ShowEditorPanel;
524     end;
525    
526     procedure TDBDynamicGrid.PositionTotals;
527     var I: integer;
528     acol: TDBDynamicGridColumn;
529     LPos: integer;
530     begin
531     LPos := Left;
532     for I := 0 to FirstGridColumn - 1 do
533     LPos := LPos + ColWidths[I];
534    
535     for I := 0 to Columns.Count - 1 do
536     begin
537     acol := TDBDynamicGridColumn(Columns[I]);
538     if assigned(acol.FColumnTotalsControl) then
539     begin
540     acol.FColumnTotalsControl.AutoSize := false;
541     acol.FColumnTotalsControl.Left := LPos;
542     acol.FColumnTotalsControl.Width := acol.Width
543     end;
544     LPos := LPos + acol.Width;
545     end;
546     end;
547    
548     procedure TDBDynamicGrid.KeyDownHandler(Sender: TObject; var Key: Word;
549     Shift: TShiftState);
550     var Done: boolean;
551 tony 31 AControl: TControl;
552 tony 21 begin
553     if Visible and assigned(FEditorPanel) and FEditorPanel.Visible and FWeHaveFocus then
554     begin
555     Done := false;
556 tony 31 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 tony 35 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 tony 21 if assigned(FOnKeyDownHander) then
570     OnKeyDownHander(Sender,Key,Shift,Done);
571     if Done then Exit;
572    
573     {Allow Scrolling}
574     if Key in [VK_UP,VK_DOWN] then
575     KeyDown(Key,Shift)
576     else
577     {Cancel Editor}
578     if Key = VK_ESCAPE then
579     begin
580     if DataLink.DataSet.State in [dsInsert,dsEdit] then
581     DataLink.DataSet.Cancel;
582     KeyDown(Key,Shift);
583     end
584     {save}
585     else
586     if Key = VK_F2 then
587     HideEditorPanel;
588     end
589     end;
590    
591 tony 35 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 tony 21 procedure TDBDynamicGrid.SetEditorPanel(AValue: TWinControl);
607     begin
608     if FEditorPanel = AValue then Exit;
609     if FEditorPanel <> nil then
610     RemoveFreeNotification(FEditorPanel);
611     FEditorPanel := AValue;
612     FreeNotification(FEditorPanel);
613     end;
614    
615     procedure TDBDynamicGrid.ChangeBounds(ALeft, ATop, AWidth, AHeight: integer;
616     KeepBase: boolean);
617     begin
618     if assigned(FEditorPanel) and FEditorPanel.Visible then
619     Application.QueueAsyncCall(@DoShowEditorPanel,0); {Restore afterwards if necessary}
620     inherited ChangeBounds(ALeft, ATop, AWidth, AHeight, KeepBase);
621     end;
622    
623     procedure TDBDynamicGrid.DoEnter;
624     begin
625     inherited DoEnter;
626     FWeHaveFocus := true;
627     end;
628    
629     procedure TDBDynamicGrid.DoExit;
630     begin
631     FWeHaveFocus := false;
632     inherited DoExit;
633     end;
634    
635     procedure TDBDynamicGrid.Loaded;
636     begin
637     inherited Loaded;
638     if assigned(FEditorPanel) and not (csDesigning in ComponentState)then
639     FEditorPanel.Visible := false;
640 tony 35 if Visible then
641     DoGridResize
642 tony 21 end;
643    
644     procedure TDBDynamicGrid.DoOnResize;
645     begin
646     inherited DoOnResize;
647     DoGridResize
648     end;
649    
650     function TDBDynamicGrid.CreateColumns: TGridColumns;
651     begin
652     result := TDBGridColumns.Create(Self, TDBDynamicGridColumn);
653     end;
654    
655     procedure TDBDynamicGrid.HeaderSized(IsColumn: Boolean; Index: Integer);
656     begin
657     inherited HeaderSized(IsColumn, Index);
658     PositionTotals
659     end;
660    
661     procedure TDBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
662     Y: Integer);
663     var Coord: TGridCoord;
664     begin
665 tony 35 FMouseDown := true;
666     try
667     inherited MouseDown(Button, Shift, X, Y);
668     finally
669     FMouseDown := false;
670     end;
671 tony 21
672     Coord := MouseCoord(X,Y);
673     if (Coord.X = 0) and (Coord.Y > 0) then
674     IndicatorClicked(Button,Shift);
675     end;
676    
677     procedure TDBDynamicGrid.Notification(AComponent: TComponent;
678     Operation: TOperation);
679     begin
680     inherited Notification(AComponent, Operation);
681     if (Operation = opRemove) and
682     (AComponent = FEditorPanel) then FEditorPanel := nil;
683     end;
684    
685     procedure TDBDynamicGrid.TopLeftChanged;
686     begin
687     inherited TopLeftChanged;
688     UpdateEditorPanelBounds;
689     end;
690    
691     procedure TDBDynamicGrid.UpdateActive;
692     begin
693     inherited UpdateActive;
694    
695     if not (csLoading in ComponentState) and assigned(DataLink) and
696 tony 35 assigned(FEditorPanel) and not FEditorPanel.Visible and
697 tony 21 assigned(DataLink.DataSet) and (DataLink.DataSet.State = dsInsert) then
698     Application.QueueAsyncCall(@DoShowEditorPanel,0);
699     end;
700    
701     procedure TDBDynamicGrid.UpdateEditorPanelBounds;
702     var R: TRect;
703     Dummy: integer;
704     begin
705     if assigned(FEditorPanel) and FEditorPanel.Visible and
706     (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
707     begin
708     // Upper and Lower bounds for this row
709     ColRowToOffSet(False, True, FExpandedRow, R.Top, R.Bottom);
710     //Left Bound for visible Columns
711     ColRowToOffSet(True,True,1,R.Left,Dummy);
712     //Right Bound for visible columns
713     ColRowToOffSet(True,True,ColCount - 1,Dummy,R.Right);
714     if ExpandEditorPanelBelowRow then
715     R.Top := R.Top + DefaultRowHeight;
716     FEditorPanel.BoundsRect := R;
717     end;
718     end;
719    
720     procedure TDBDynamicGrid.UpdateShowing;
721     begin
722     inherited UpdateShowing;
723     DoGridResize
724     end;
725    
726     procedure TDBDynamicGrid.HideEditorPanel;
727     begin
728     if Editor = FEditorPanel then
729 tony 35 EditorMode := false;
730 tony 21 end;
731    
732     procedure TDBDynamicGrid.ShowEditorPanel;
733     begin
734 tony 27 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 tony 21 Editor := FEditorPanel;
739     EditorMode := true;
740     end;
741    
742     constructor TDBDynamicGrid.Create(TheComponent: TComponent);
743     begin
744     inherited Create(TheComponent);
745     ScrollBars := ssAutoVertical;
746     if not (csDesigning in ComponentState) then
747     Application.AddOnKeyDownBeforeHandler(@KeyDownHandler,false);
748     end;
749    
750     destructor TDBDynamicGrid.Destroy;
751     begin
752     if not (csDesigning in ComponentState) then
753     Application.RemoveOnKeyDownBeforeHandler(@KeyDownHandler);
754     inherited Destroy;
755     end;
756    
757     procedure TDBDynamicGrid.ResizeColumns;
758     begin
759     DoGridResize;
760     end;
761    
762     { TDBDynamicGridColumn }
763    
764     procedure TDBDynamicGridColumn.SetWidth(AValue: integer);
765     begin
766     if Width = AValue then Exit;
767     inherited Width := AValue;
768     if not TDBDynamicGrid(Grid).FResizing then
769     FDesignWidth := Width
770     end;
771    
772     function TDBDynamicGridColumn.GetWidth: integer;
773     begin
774     Result := inherited Width
775     end;
776    
777     { TDBLookupCellEditor }
778    
779     procedure TDBLookupCellEditor.WndProc(var TheMessage: TLMessage);
780     begin
781     if TheMessage.msg=LM_KILLFOCUS then begin
782     if HWND(TheMessage.WParam) = HWND(Handle) then begin
783     // lost the focus but it returns to ourselves
784     // eat the message.
785     TheMessage.Result := 0;
786     exit;
787     end;
788     end;
789     inherited WndProc(TheMessage);
790     end;
791    
792     procedure TDBLookupCellEditor.CloseUp;
793     begin
794     UpdateData(nil); {Force Record Update}
795     if FGrid<>nil then
796 tony 27 Begin
797     (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Trim(Text));
798     (FGrid as TIBDynamicGrid).UpdateData;
799     end;
800 tony 21 inherited CloseUp;
801     end;
802    
803     procedure TDBLookupCellEditor.KeyDown(var Key: Word; Shift: TShiftState);
804     begin
805     if (Key = VK_TAB) and assigned(FGrid) then
806     TIBDynamicGrid(FGrid).KeyDown(Key,Shift)
807     else
808     inherited KeyDown(Key, Shift);
809     end;
810    
811 tony 27 procedure TDBLookupCellEditor.Loaded;
812     begin
813     inherited Loaded;
814     Text := '';
815     end;
816    
817 tony 21 procedure TDBLookupCellEditor.msg_GetValue(var Msg: TGridMessage);
818     begin
819     CheckAndInsert;
820     Msg.Col := FCol;
821     Msg.Row := FRow;
822     Msg.Value:= Trim(Text);
823     end;
824    
825     procedure TDBLookupCellEditor.msg_SetGrid(var Msg: TGridMessage);
826     begin
827     FGrid:=Msg.Grid;
828     Msg.Options:=EO_AUTOSIZE or EO_SELECTALL or EO_HOOKKEYPRESS or EO_HOOKKEYUP;
829     end;
830    
831     procedure TDBLookupCellEditor.msg_SetValue(var Msg: TGridMessage);
832     begin
833     FGrid := Msg.Grid;
834     FCol := Msg.Col;
835     FRow := Msg.Row;
836     FEditText := Msg.Value;
837     TIBDynamicGrid(FGrid).SetupEditor(self,FCol);
838     end;
839    
840     procedure TDBLookupCellEditor.msg_SetPos(var Msg: TGridMessage);
841     begin
842     FCol := Msg.Col;
843     FRow := Msg.Row;
844     end;
845    
846     procedure TDBLookupCellEditor.msg_GetGrid(var Msg: TGridMessage);
847     begin
848     Msg.Grid := FGrid;
849     Msg.Options:= EO_IMPLEMENTED;
850     end;
851    
852     procedure TDBLookupCellEditor.EditingDone;
853     begin
854     inherited EditingDone;
855     if FGrid<>nil then
856     FGrid.EditingDone;
857     end;
858    
859     { TIBDynamicGridColumn }
860    
861     procedure TIBDynamicGridColumn.DoSetupEditor(Data: PtrInt);
862     var Editor: TDBlookupCellEditor;
863     begin
864     if AppDestroying in Application.Flags then Exit;
865    
866     Editor := TDBlookupCellEditor(Data);
867     Editor.DataSource := nil;
868     Editor.ListSource := nil; {Allows change without causing an error}
869     Editor.KeyValue := NULL;
870    
871     with DBLookupProperties do
872     begin
873     {Setup Properties}
874     Editor.AutoInsert := AutoInsert;
875     Editor.AutoComplete := AutoComplete;
876     Editor.AutoCompleteText := AutoCompleteText;
877     Editor.KeyPressInterval := KeyPressInterval;
878     Editor.Style := Style;
879     Editor.ItemHeight := ItemHeight;
880     Editor.ItemWidth := ItemWidth;
881     Editor.RelationName := RelationName;
882     Editor.OnAutoInsert := OnAutoInsert;
883     Editor.OnCanAutoInsert := OnCanAutoInsert;
884     Editor.OnDrawItem := OnDrawItem;
885 tony 31 Editor.OnCloseUp := OnCloseUp;
886 tony 21
887     {Setup Data Links}
888     if KeyField <> '' then
889     Editor.KeyField := KeyField
890     else
891     Editor.KeyField := ListField;
892     Editor.ListField := ListField;
893     Editor.DataField := DataFieldName;
894     end;
895     Application.QueueAsyncCall(@DoSetDataSources,PtrInt(Editor));
896     end;
897    
898     procedure TIBDynamicGridColumn.DoSetDataSources(Data: PtrInt);
899     var Editor: TDBlookupCellEditor;
900     begin
901     if AppDestroying in Application.Flags then Exit;
902    
903     Editor := TDBlookupCellEditor(Data);
904     with DBLookupProperties do
905     begin
906     Editor.ListSource := ListSource;
907     if DataFieldName <> '' then
908     Editor.DataSource := TDBGrid(Grid).DataSource;
909     end;
910     Editor.Text := Editor.FEditText;
911 tony 31 Editor.SelStart := Length(Editor.Text);
912 tony 21 end;
913    
914     procedure TIBDynamicGridColumn.SetInitialSortColumn(AValue: boolean);
915     begin
916     if FInitialSortColumn = AValue then Exit;
917     FInitialSortColumn := AValue;
918     (Grid as TIBDynamicGrid).UpdateSortColumn(self)
919     end;
920    
921     procedure TIBDynamicGridColumn.SetupEditor(Editor: TDBlookupCellEditor);
922     begin
923     Application.QueueAsyncCall(@DoSetupEditor,PtrInt(Editor));
924     end;
925    
926     constructor TIBDynamicGridColumn.Create(ACollection: TCollection);
927     begin
928     inherited Create(ACollection);
929     FDBLookupProperties := TDBLookupProperties.Create(self);
930     end;
931    
932     destructor TIBDynamicGridColumn.Destroy;
933     begin
934     if assigned(FDBLookupProperties) then FDBLookupProperties.Free;
935     inherited Destroy;
936     end;
937    
938    
939     { TIBDynamicGrid }
940    
941     procedure TIBDynamicGrid.ColumnHeaderClick(Index: integer);
942     begin
943     FColHeaderClick := true;
944     try
945     if Index = FLastColIndex then
946     FDescending := not FDescending;
947    
948     if assigned(FOnColumnHeaderClick) then
949     OnColumnHeaderClick(self,Index);
950    
951     FLastColIndex := Index;
952 tony 37 FFieldPosition := 0;
953     if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active
954     and (DataSource.DataSet is TIBParserDataSet) then
955 tony 21 begin
956 tony 37 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 tony 21 DataSource.DataSet.Active := false;
960     Application.QueueAsyncCall(@DoReopen,0)
961     end;
962     finally
963     FColHeaderClick := false
964     end;
965     end;
966    
967     function TIBDynamicGrid.GetDataSource: TDataSource;
968     begin
969     if assigned(DataLink) then
970     Result := inherited DataSource
971     else
972     Result := nil;
973     end;
974    
975     function TIBDynamicGrid.GetEditorBorderStyle: TBorderStyle;
976     begin
977     if Editor = FDBLookupCellEditor then
978     Result := FDBLookupCellEditor.BorderStyle
979     else
980     Result := inherited EditorBorderStyle
981     end;
982    
983     procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
984     begin
985     inherited DataSource := AValue;
986 tony 27 IBControlLinkChanged;
987 tony 21 end;
988    
989     procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
990     begin
991     inherited EditorBorderStyle := AValue;
992     if FDBLookupCellEditor.BorderStyle <> AValue then
993     begin
994     FDBLookupCellEditor.BorderStyle := AValue;
995     if (Editor = FDBLookupCellEditor) and EditorMode then
996     EditorWidthChanged(Col,FDBLookupCellEditor.Width);
997     end;
998     end;
999    
1000     procedure TIBDynamicGrid.ProcessColumns;
1001     var i: integer;
1002     begin
1003     for i := 0 to Columns.Count - 1 do
1004     begin
1005     if TIBDynamicGridColumn(columns[i]).InitialSortColumn then
1006 tony 37 begin
1007     FFieldPosition := 0;
1008 tony 21 FLastColIndex := i
1009 tony 37 end
1010 tony 21 end
1011     end;
1012    
1013     procedure TIBDynamicGrid.SetIndexFieldNames(AValue: string);
1014     var idx: integer;
1015     begin
1016     if FIndexFieldNames = AValue then Exit;
1017     FIndexFieldNames := AValue;
1018     idx := 1;
1019     FIndexFieldsList.Clear;
1020     while idx <= Length(AValue) do
1021     FIndexFieldsList.Add(ExtractFieldName(AValue,idx));
1022     end;
1023    
1024     procedure TIBDynamicGrid.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
1025     var OrderBy: string;
1026     begin
1027 tony 27 if assigned(DataSource) and assigned(DataSource.DataSet)
1028 tony 21 and (DataSource.DataSet is TIBCustomDataSet) then
1029     begin
1030 tony 37 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 tony 35 begin
1036     if Descending then
1037 tony 37 Parser.OrderByClause := IntToStr(FFieldPosition) + ' desc'
1038 tony 35 else
1039 tony 37 Parser.OrderByClause := IntToStr(FFieldPosition) + ' asc';
1040 tony 35 end;
1041 tony 21
1042     if assigned(FOnUpdateSortOrder) then
1043     begin
1044     OrderBy := Parser.OrderByClause;
1045     OnUpdateSortOrder(self,FLastColIndex,OrderBy);
1046     Parser.OrderByClause := OrderBy
1047     end
1048     end;
1049     end;
1050    
1051     procedure TIBDynamicGrid.UpdateSortColumn(Sender: TObject);
1052     var i: integer;
1053     begin
1054     if Sender is TIBDynamicGridColumn then
1055     begin
1056     for i := 0 to Columns.Count -1 do
1057     if TObject(Columns[i]) <> Sender then
1058     TIBDynamicGridColumn(Columns[i]).InitialSortColumn := false
1059     end
1060    
1061     end;
1062    
1063 tony 27 procedure TIBDynamicGrid.RestorePosition;
1064 tony 21 begin
1065     if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1066     begin
1067 tony 27 if assigned(FOnRestorePosition) then
1068     OnRestorePosition(self,@FBookmark);
1069 tony 21 if (Length(FBookmark) > 0) and
1070     DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1071    
1072     if FDefaultPositionAtEnd then
1073     DataSource.DataSet.Last
1074     end;
1075     end;
1076    
1077 tony 27 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 tony 21 procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1093     begin
1094     DataSource.DataSet.Active := true;
1095     end;
1096    
1097 tony 27 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 tony 21 procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1106     );
1107     var C: TIBDynamicGridColumn;
1108     begin
1109     C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1110 tony 27 if (c <> nil) then
1111     C.SetupEditor(aEditor);
1112 tony 21 end;
1113    
1114     procedure TIBDynamicGrid.DoEditorHide;
1115     var i: integer;
1116     begin
1117     inherited DoEditorHide;
1118     if assigned(EditorPanel) then
1119     for i := 0 to EditorPanel.ControlCount -1 do
1120     if EditorPanel.Controls[i] is TIBLookupComboEditBox then
1121     EditorPanel.Controls[i].Perform(CM_VISIBLECHANGED, WParam(ord(false)), 0);
1122     end;
1123    
1124     procedure TIBDynamicGrid.Loaded;
1125     begin
1126     inherited Loaded;
1127 tony 29 IBControlLinkChanged;
1128 tony 21 ProcessColumns;
1129     end;
1130    
1131     function TIBDynamicGrid.CreateColumns: TGridColumns;
1132     begin
1133     result := TDBGridColumns.Create(Self, TIBDynamicGridColumn);
1134     end;
1135    
1136     procedure TIBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
1137     Y: Integer);
1138     var Coord: TGridCoord;
1139     obe: boolean;
1140     function PtInRect(const Rect : TRect;const p : TPoint) : Boolean;
1141    
1142     begin
1143     PtInRect:=(p.y>=Rect.Top) and
1144     (p.y<Rect.Bottom) and
1145     (p.x>=Rect.Left) and
1146     (p.x<Rect.Right);
1147     end;
1148     begin
1149     if (Editor is TDBLookupCellEditor) and Editor.Visible
1150     and not PtInRect(Editor.BoundsRect,Point(X,Y)) then
1151     Editor.Perform(CM_EXIT,0,0); {Do insert new value if necessary}
1152     inherited MouseDown(Button, Shift, X, Y);
1153     obe := AllowOutboundEvents;
1154     AllowOutboundEvents := false;
1155     try
1156     Coord := MouseCoord(X,Y);
1157 tony 27 if AllowColumnSort and (Coord.X <> -1) and (FixedRows > 0) and
1158 tony 21 (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);
1161     finally
1162     AllowOutboundEvents := obe
1163     end;
1164     end;
1165    
1166 tony 27 procedure TIBDynamicGrid.MoveSelection;
1167     begin
1168     inherited MoveSelection;
1169     SavePosition;
1170     end;
1171    
1172 tony 21 procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1173     begin
1174 tony 27 IBControlLinkChanged;
1175 tony 21 inherited LinkActive(Value);
1176     if (FActive <> Value) and Value then
1177 tony 27 RestorePosition;
1178 tony 21 FActive := Value
1179     end;
1180    
1181     procedure TIBDynamicGrid.Notification(AComponent: TComponent;
1182     Operation: TOperation);
1183     begin
1184     inherited Notification(AComponent, Operation);
1185     if (Operation = opRemove) and
1186 tony 27 (FIBControlLink <> nil) and (AComponent = DataSource) then FIBControlLink.IBDataSet := nil;
1187 tony 21 end;
1188    
1189     procedure TIBDynamicGrid.UpdateActive;
1190     begin
1191     inherited UpdateActive;
1192 tony 27 if assigned(DataLink) and assigned(DataLink.DataSet) and
1193     DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1194     SavePosition;
1195 tony 21 end;
1196    
1197     constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1198     begin
1199     inherited Create(TheComponent);
1200     FAllowColumnSort := true;
1201 tony 27 FIBControlLink := TIBGridControlLink.Create(self);
1202 tony 21 FIndexFieldsList := TStringList.Create;
1203     FIndexFieldsList.Delimiter := ';';
1204     FIndexFieldsList.StrictDelimiter := true;
1205     FDBLookupCellEditor := TDBLookupCellEditor.Create(nil);
1206     FDBLookupCellEditor.Name := 'DBLookupCellEditor';
1207     FDBLookupCellEditor.Visible := False;
1208     FDBLookupCellEditor.AutoSize := false;
1209     end;
1210    
1211     destructor TIBDynamicGrid.Destroy;
1212     begin
1213 tony 27 if assigned(FIBControlLink) then FIBControlLink.Free;
1214 tony 21 if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1215     if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
1216     inherited Destroy;
1217     end;
1218    
1219     function TIBDynamicGrid.EditorByStyle(Style: TColumnButtonStyle): TWinControl;
1220     var C: TIBDynamicGridColumn;
1221     bs: TColumnButtonStyle;
1222     begin
1223     C := ColumnFromGridColumn(Col) as TIBDynamicGridColumn;
1224     if C <> nil then
1225     begin
1226     bs := C.ButtonStyle;
1227     if (bs in [cbsAuto,cbsPickList]) and assigned(C.DBLookupProperties.ListSource) then
1228     begin
1229     Result := FDBLookupCellEditor;
1230     Exit;
1231     end;
1232     end;
1233     Result := inherited EditorByStyle(Style);
1234     end;
1235    
1236     end.