ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 45
Committed: Tue Dec 6 10:33:46 2016 UTC (7 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 40319 byte(s)
Log Message:
Committing updates for Release R2-0-0

File Contents

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