ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 408
Committed: Tue Dec 13 22:37:43 2022 UTC (23 months ago) by tony
Content type: text/x-pascal
File size: 40795 byte(s)
Log Message:
Fix stray override in ibdynamicgrid

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

Properties

Name Value
svn:eol-style native