ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/ibcontrols/IBDynamicGrid.pas
Revision: 80
Committed: Mon Jan 1 11:31:07 2018 UTC (6 years, 11 months ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/ibcontrols/IBDynamicGrid.pas
File size: 40493 byte(s)
Log Message:
Fixes merged into public release

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 keys 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 keys in a Custom Grid}
575
576 if (AControl <> nil) and (AControl is TEBEdit) and (AControl.Owner is TDateEdit) then
577 begin
578 if (Key in [VK_LEFT,VK_RIGHT]) then Exit; {Ignore navigation keys}
579 if TDateEdit(AControl.Owner).DroppedDown and
580 (Key in [VK_RETURN,VK_UP,VK_DOWN,VK_ESCAPE]) then Exit; {Ignore TCalender navigation keys in a Data edit}
581 end;
582
583 if assigned(FOnKeyDownHander) then
584 OnKeyDownHander(Sender,Key,Shift,Done);
585 if Done then Exit;
586
587 {Allow Scrolling}
588 if Key in [VK_UP,VK_DOWN] then
589 KeyDown(Key,Shift)
590 else
591 {Cancel Editor}
592 if Key = VK_ESCAPE then
593 begin
594 if DataLink.DataSet.State in [dsInsert,dsEdit] then
595 DataLink.DataSet.Cancel;
596 KeyDown(Key,Shift);
597 end
598 {save}
599 else
600 if Key = VK_F2 then
601 HideEditorPanel;
602 end
603 end;
604
605 procedure TDBDynamicGrid.PerformEditorHide(Data: PtrInt);
606 var ExpandedRow: integer;
607 begin
608 if AppDestroying in Application.Flags then Exit;
609 ExpandedRow := integer(Data);
610 if (ExpandedRow >= 0) and (ExpandedRow < RowCount) then
611 RowHeights[ExpandedRow] := DefaultRowHeight;
612 if CanFocus then SetFocus;
613 DoOnResize;
614 ResetSizes;
615 DoOnChangeBounds;
616 if assigned(FOnEditorPanelHide) then
617 OnEditorPanelHide(self);
618 end;
619
620 procedure TDBDynamicGrid.SetEditorPanel(AValue: TWinControl);
621 begin
622 if FEditorPanel = AValue then Exit;
623 if FEditorPanel <> nil then
624 RemoveFreeNotification(FEditorPanel);
625 FEditorPanel := AValue;
626 if FEditorPanel <> nil then
627 FreeNotification(FEditorPanel);
628 end;
629
630 procedure TDBDynamicGrid.ChangeBounds(ALeft, ATop, AWidth, AHeight: integer;
631 KeepBase: boolean);
632 begin
633 if assigned(FEditorPanel) and FEditorPanel.Visible then
634 Application.QueueAsyncCall(@DoShowEditorPanel,0); {Restore afterwards if necessary}
635 inherited ChangeBounds(ALeft, ATop, AWidth, AHeight, KeepBase);
636 end;
637
638 procedure TDBDynamicGrid.DoEnter;
639 begin
640 inherited DoEnter;
641 FWeHaveFocus := true;
642 end;
643
644 procedure TDBDynamicGrid.DoExit;
645 begin
646 FWeHaveFocus := false;
647 inherited DoExit;
648 end;
649
650 procedure TDBDynamicGrid.Loaded;
651 begin
652 inherited Loaded;
653 if assigned(FEditorPanel) and not (csDesigning in ComponentState)then
654 FEditorPanel.Visible := false;
655 if Visible then
656 DoGridResize
657 end;
658
659 procedure TDBDynamicGrid.DoOnResize;
660 begin
661 inherited DoOnResize;
662 DoGridResize
663 end;
664
665 function TDBDynamicGrid.CreateColumns: TGridColumns;
666 begin
667 result := TDBGridColumns.Create(Self, TDBDynamicGridColumn);
668 end;
669
670 procedure TDBDynamicGrid.HeaderSized(IsColumn: Boolean; Index: Integer);
671 begin
672 inherited HeaderSized(IsColumn, Index);
673 PositionTotals
674 end;
675
676 procedure TDBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
677 Y: Integer);
678 var Coord: TGridCoord;
679 begin
680 FMouseDown := true;
681 try
682 inherited MouseDown(Button, Shift, X, Y);
683 finally
684 FMouseDown := false;
685 end;
686
687 Coord := MouseCoord(X,Y);
688 if (Coord.X = 0) and (Coord.Y > 0) then
689 IndicatorClicked(Button,Shift);
690 end;
691
692 procedure TDBDynamicGrid.Notification(AComponent: TComponent;
693 Operation: TOperation);
694 var i: integer;
695 begin
696 inherited Notification(AComponent, Operation);
697 if (Operation = opRemove) and not (csDestroying in ComponentState) then
698 begin
699 if AComponent = FEditorPanel then
700 FEditorPanel := nil
701 else
702 if AComponent is TControl then
703 begin
704 for i := 0 to Columns.Count - 1 do
705 if TDBDynamicGridColumn(Columns[I]).ColumnTotalsControl = AComponent then
706 TDBDynamicGridColumn(Columns[I]).ColumnTotalsControl := nil;
707 end;
708 end
709 end;
710
711 procedure TDBDynamicGrid.TopLeftChanged;
712 begin
713 inherited TopLeftChanged;
714 UpdateEditorPanelBounds;
715 end;
716
717 procedure TDBDynamicGrid.UpdateActive;
718 begin
719 inherited UpdateActive;
720
721 if not (csLoading in ComponentState) and assigned(DataLink)
722 and assigned(DataLink.DataSet) and DataLink.DataSet.Active then
723 DoGridResize;
724
725 if not (csLoading in ComponentState) and assigned(DataLink) and
726 assigned(FEditorPanel) and not FEditorPanel.Visible and
727 assigned(DataLink.DataSet) and (DataLink.DataSet.State = dsInsert) then
728 Application.QueueAsyncCall(@DoShowEditorPanel,0);
729 end;
730
731 procedure TDBDynamicGrid.UpdateEditorPanelBounds;
732 var R: TRect;
733 Dummy: integer;
734 begin
735 if assigned(FEditorPanel) and FEditorPanel.Visible and
736 (FExpandedRow >= 0) and (FExpandedRow < RowCount) then
737 begin
738 // Upper and Lower bounds for this row
739 ColRowToOffSet(False, True, FExpandedRow, R.Top, R.Bottom);
740 //Left Bound for visible Columns
741 ColRowToOffSet(True,True,1,R.Left,Dummy);
742 //Right Bound for visible columns
743 ColRowToOffSet(True,True,ColCount - 1,Dummy,R.Right);
744 if ExpandEditorPanelBelowRow then
745 R.Top := R.Top + DefaultRowHeight;
746 FEditorPanel.BoundsRect := R;
747 end;
748 end;
749
750 procedure TDBDynamicGrid.UpdateShowing;
751 begin
752 inherited UpdateShowing;
753 DoGridResize
754 end;
755
756 procedure TDBDynamicGrid.HideEditorPanel;
757 begin
758 if Editor = FEditorPanel then
759 EditorMode := false;
760 end;
761
762 procedure TDBDynamicGrid.ShowEditorPanel;
763 var aEditor: TWinControl;
764 begin
765 if (csDesigning in ComponentState) or
766 (DataSource = nil) or (DataSource.DataSet = nil)
767 or ((DataSource.DataSet.RecordCount = 0) and (DataSource.DataSet.State <> dsInsert)) then
768 Exit;
769 aEditor := FEditorPanel;
770 if assigned(FOnSelectPanelEditor) then
771 OnSelectPanelEditor(self,aEditor);
772 if FEditorPanel <> aEditor then
773 SetEditorPanel(aEditor);
774 Editor := aEditor;
775 EditorMode := true;
776 end;
777
778 constructor TDBDynamicGrid.Create(TheComponent: TComponent);
779 begin
780 inherited Create(TheComponent);
781 ScrollBars := ssAutoVertical;
782 if not (csDesigning in ComponentState) then
783 Application.AddOnKeyDownBeforeHandler(@KeyDownHandler,false);
784 end;
785
786 destructor TDBDynamicGrid.Destroy;
787 begin
788 if not (csDesigning in ComponentState) then
789 Application.RemoveOnKeyDownBeforeHandler(@KeyDownHandler);
790 inherited Destroy;
791 end;
792
793 procedure TDBDynamicGrid.ResizeColumns;
794 begin
795 DoGridResize;
796 end;
797
798 { TDBDynamicGridColumn }
799
800 procedure TDBDynamicGridColumn.SetWidth(AValue: integer);
801 begin
802 if Width = AValue then Exit;
803 inherited Width := AValue;
804 if not TDBDynamicGrid(Grid).FResizing then
805 FDesignWidth := Width
806 end;
807
808 function TDBDynamicGridColumn.GetWidth: integer;
809 begin
810 Result := inherited Width
811 end;
812
813 type
814 THackedGrid = class(TIBDynamicGrid)
815 public
816 property FixedCols;
817 end;
818
819 { TDBLookupCellEditor }
820
821 function TDBLookupCellEditor.EditingKeyField: boolean;
822 begin
823 with TIBDynamicGridColumn(TDBGrid(FGrid).Columns[FCol - THackedGrid(FGrid).FixedCols]) do
824 Result := CompareText(FieldName, DBLookupProperties.DataFieldName) = 0;
825 end;
826
827 procedure TDBLookupCellEditor.WndProc(var TheMessage: TLMessage);
828 begin
829 if TheMessage.msg=LM_KILLFOCUS then begin
830 if HWND(TheMessage.WParam) = HWND(Handle) then begin
831 // lost the focus but it returns to ourselves
832 // eat the message.
833 TheMessage.Result := 0;
834 exit;
835 end;
836 end;
837 inherited WndProc(TheMessage);
838 end;
839
840 procedure TDBLookupCellEditor.CloseUp;
841 begin
842 UpdateData(nil); {Force Record Update}
843 if FGrid<>nil then
844 Begin
845 if EditingKeyField then
846 begin
847 if not VarIsNull(KeyValue) then
848 (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, KeyValue)
849 end
850 else
851 (FGrid as TIBDynamicGrid).EditorTextChanged(FCol, FRow, Trim(Text));
852 (FGrid as TIBDynamicGrid).UpdateData;
853 end;
854 inherited CloseUp;
855 end;
856
857 procedure TDBLookupCellEditor.KeyDown(var Key: Word; Shift: TShiftState);
858 begin
859 if (Key = VK_TAB) and assigned(FGrid) then
860 TIBDynamicGrid(FGrid).KeyDown(Key,Shift)
861 else
862 inherited KeyDown(Key, Shift);
863 end;
864
865 procedure TDBLookupCellEditor.Loaded;
866 begin
867 inherited Loaded;
868 Text := '';
869 end;
870
871 procedure TDBLookupCellEditor.msg_GetValue(var Msg: TGridMessage);
872 begin
873 CheckAndInsert;
874 Msg.Col := FCol;
875 Msg.Row := FRow;
876 if EditingKeyField then
877 begin
878 if not VarIsNull(KeyValue) then
879 Msg.Value:= KeyValue
880 else
881 Msg.Value:= ''
882 end
883 else
884 Msg.Value:= Trim(Text);
885 end;
886
887 procedure TDBLookupCellEditor.msg_SetGrid(var Msg: TGridMessage);
888 begin
889 FGrid:=Msg.Grid;
890 Msg.Options:=EO_AUTOSIZE or EO_SELECTALL or EO_HOOKKEYPRESS or EO_HOOKKEYUP;
891 end;
892
893 procedure TDBLookupCellEditor.msg_SetValue(var Msg: TGridMessage);
894 begin
895 FGrid := Msg.Grid;
896 FCol := Msg.Col;
897 FRow := Msg.Row;
898 FEditText := Msg.Value;
899 TIBDynamicGrid(FGrid).SetupEditor(self,FCol);
900 end;
901
902 procedure TDBLookupCellEditor.msg_SetPos(var Msg: TGridMessage);
903 begin
904 FCol := Msg.Col;
905 FRow := Msg.Row;
906 end;
907
908 procedure TDBLookupCellEditor.msg_GetGrid(var Msg: TGridMessage);
909 begin
910 Msg.Grid := FGrid;
911 Msg.Options:= EO_IMPLEMENTED;
912 end;
913
914 procedure TDBLookupCellEditor.EditingDone;
915 begin
916 inherited EditingDone;
917 if FGrid<>nil then
918 FGrid.EditingDone;
919 end;
920
921 { TIBDynamicGridColumn }
922
923 procedure TIBDynamicGridColumn.DoSetupEditor(Data: PtrInt);
924 var Editor: TDBlookupCellEditor;
925 begin
926 if AppDestroying in Application.Flags then Exit;
927
928 Editor := TDBlookupCellEditor(Data);
929 Editor.DataSource := nil;
930 Editor.ListSource := nil; {Allows change without causing an error}
931 Editor.KeyValue := NULL;
932
933 with DBLookupProperties do
934 begin
935 {Setup Properties}
936 Editor.AutoInsert := AutoInsert;
937 Editor.AutoComplete := AutoComplete;
938 Editor.AutoCompleteText := AutoCompleteText;
939 Editor.KeyPressInterval := KeyPressInterval;
940 Editor.Style := Style;
941 Editor.ItemHeight := ItemHeight;
942 Editor.ItemWidth := ItemWidth;
943 Editor.RelationName := RelationName;
944 Editor.OnAutoInsert := OnAutoInsert;
945 Editor.OnCanAutoInsert := OnCanAutoInsert;
946 Editor.OnDrawItem := OnDrawItem;
947 Editor.OnCloseUp := OnCloseUp;
948
949 {Setup Data Links}
950 if KeyField <> '' then
951 Editor.KeyField := KeyField
952 else
953 Editor.KeyField := ListField;
954 Editor.ListField := ListField;
955 Editor.DataField := DataFieldName;
956 end;
957 Application.QueueAsyncCall(@DoSetDataSources,PtrInt(Editor));
958 end;
959
960 procedure TIBDynamicGridColumn.DoSetDataSources(Data: PtrInt);
961 var Editor: TDBlookupCellEditor;
962 begin
963 if AppDestroying in Application.Flags then Exit;
964
965 Editor := TDBlookupCellEditor(Data);
966 with DBLookupProperties do
967 begin
968 Editor.ListSource := ListSource;
969 if DataFieldName <> '' then
970 Editor.DataSource := TDBGrid(Grid).DataSource;
971 end;
972 if Editor.EditingKeyField then
973 begin
974 if not Field.IsNull then
975 Editor.KeyValue := Editor.FEditText
976 end
977 else
978 Editor.Text := Editor.FEditText;
979 Editor.SelStart := Length(Editor.Text);
980 end;
981
982 procedure TIBDynamicGridColumn.SetInitialSortColumn(AValue: boolean);
983 begin
984 if FInitialSortColumn = AValue then Exit;
985 FInitialSortColumn := AValue;
986 (Grid as TIBDynamicGrid).UpdateSortColumn(self)
987 end;
988
989 procedure TIBDynamicGridColumn.SetupEditor(Editor: TDBlookupCellEditor);
990 begin
991 Application.QueueAsyncCall(@DoSetupEditor,PtrInt(Editor));
992 end;
993
994 constructor TIBDynamicGridColumn.Create(ACollection: TCollection);
995 begin
996 inherited Create(ACollection);
997 FDBLookupProperties := TDBLookupProperties.Create(self);
998 end;
999
1000 destructor TIBDynamicGridColumn.Destroy;
1001 begin
1002 if assigned(FDBLookupProperties) then FDBLookupProperties.Free;
1003 Application.RemoveAsyncCalls(self);
1004 inherited Destroy;
1005 end;
1006
1007
1008 { TIBDynamicGrid }
1009
1010 procedure TIBDynamicGrid.ColumnHeaderClick(Index: integer);
1011 begin
1012 FColHeaderClick := true;
1013 try
1014 if Index = FLastColIndex then
1015 FDescending := not FDescending;
1016
1017 if assigned(FOnColumnHeaderClick) then
1018 OnColumnHeaderClick(self,Index);
1019
1020 FLastColIndex := Index;
1021 FFieldPosition := 0;
1022 if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active
1023 and (DataSource.DataSet is TIBParserDataSet) then
1024 begin
1025 if FLastColIndex < Columns.Count then
1026 {try and cache field position while dataset still open}
1027 FFieldPosition := TIBParserDataSet(DataSource.DataSet).Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1028 DataSource.DataSet.Active := false;
1029 Application.QueueAsyncCall(@DoReopen,0)
1030 end;
1031 finally
1032 FColHeaderClick := false
1033 end;
1034 end;
1035
1036 function TIBDynamicGrid.GetDataSource: TDataSource;
1037 begin
1038 if assigned(DataLink) then
1039 Result := inherited DataSource
1040 else
1041 Result := nil;
1042 end;
1043
1044 function TIBDynamicGrid.GetEditorBorderStyle: TBorderStyle;
1045 begin
1046 if Editor = FDBLookupCellEditor then
1047 Result := FDBLookupCellEditor.BorderStyle
1048 else
1049 Result := inherited EditorBorderStyle
1050 end;
1051
1052 procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
1053 begin
1054 inherited DataSource := AValue;
1055 IBControlLinkChanged;
1056 end;
1057
1058 procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
1059 begin
1060 inherited EditorBorderStyle := AValue;
1061 if FDBLookupCellEditor.BorderStyle <> AValue then
1062 begin
1063 FDBLookupCellEditor.BorderStyle := AValue;
1064 if (Editor = FDBLookupCellEditor) and EditorMode then
1065 EditorWidthChanged(Col,FDBLookupCellEditor.Width);
1066 end;
1067 end;
1068
1069 procedure TIBDynamicGrid.ProcessColumns;
1070 var i: integer;
1071 begin
1072 for i := 0 to Columns.Count - 1 do
1073 begin
1074 if TIBDynamicGridColumn(columns[i]).InitialSortColumn then
1075 begin
1076 FFieldPosition := 0;
1077 FLastColIndex := i
1078 end
1079 end
1080 end;
1081
1082 procedure TIBDynamicGrid.SetIndexFieldNames(AValue: string);
1083 var idx: integer;
1084 begin
1085 if FIndexFieldNames = AValue then Exit;
1086 FIndexFieldNames := AValue;
1087 idx := 1;
1088 FIndexFieldsList.Clear;
1089 while idx <= Length(AValue) do
1090 FIndexFieldsList.Add(ExtractFieldName(AValue,idx));
1091 end;
1092
1093 procedure TIBDynamicGrid.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
1094 var OrderBy: string;
1095 begin
1096 if assigned(DataSource) and assigned(DataSource.DataSet)
1097 and (DataSource.DataSet is TIBCustomDataSet) then
1098 begin
1099 if (FFieldPosition = 0) and (FLastColIndex >= 0) and (FLastColIndex < Columns.Count) then
1100 {Not cached - let's hope we can find it before the dataset is opened.
1101 Won't work if dynamic columns}
1102 FFieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1103 if FFieldPosition > 0 then
1104 begin
1105 if Descending then
1106 Parser.OrderByClause := IntToStr(FFieldPosition) + ' desc'
1107 else
1108 Parser.OrderByClause := IntToStr(FFieldPosition) + ' asc';
1109 end;
1110
1111 if assigned(FOnUpdateSortOrder) then
1112 begin
1113 OrderBy := Parser.OrderByClause;
1114 OnUpdateSortOrder(self,FLastColIndex,OrderBy);
1115 Parser.OrderByClause := OrderBy
1116 end
1117 end;
1118 end;
1119
1120 procedure TIBDynamicGrid.UpdateSortColumn(Sender: TObject);
1121 var i: integer;
1122 begin
1123 if Sender is TIBDynamicGridColumn then
1124 begin
1125 for i := 0 to Columns.Count -1 do
1126 if TObject(Columns[i]) <> Sender then
1127 TIBDynamicGridColumn(Columns[i]).InitialSortColumn := false
1128 end
1129
1130 end;
1131
1132 procedure TIBDynamicGrid.RestorePosition;
1133 begin
1134 if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1135 begin
1136 if assigned(FOnRestorePosition) then
1137 OnRestorePosition(self,@FBookmark);
1138 if (Length(FBookmark) > 0) and
1139 DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1140
1141 if FDefaultPositionAtEnd then
1142 DataSource.DataSet.Last
1143 end;
1144 end;
1145
1146 procedure TIBDynamicGrid.SavePosition;
1147 var i: integer;
1148 F: TField;
1149 begin
1150 if FIndexFieldsList = nil then Exit;
1151
1152 SetLength(FBookmark,FIndexFieldsList.Count);
1153 for i := 0 to FIndexFieldsList.Count - 1 do
1154 begin
1155 F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
1156 if assigned(F) then
1157 FBookmark[i] := F.AsVariant;
1158 end;
1159 end;
1160
1161 procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1162 begin
1163 DataSource.DataSet.Active := true;
1164 end;
1165
1166 procedure TIBDynamicGrid.IBControlLinkChanged;
1167 begin
1168 if (DataSource <> nil) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataSet) then
1169 FIBControlLink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
1170 else
1171 FIBControlLink.IBDataSet := nil;
1172 end;
1173
1174 procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1175 );
1176 var C: TIBDynamicGridColumn;
1177 begin
1178 C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1179 if (c <> nil) then
1180 C.SetupEditor(aEditor);
1181 end;
1182
1183 procedure TIBDynamicGrid.DoEditorHide;
1184 var i: integer;
1185 begin
1186 inherited DoEditorHide;
1187 if assigned(EditorPanel) then
1188 for i := 0 to EditorPanel.ControlCount -1 do
1189 if EditorPanel.Controls[i] is TIBLookupComboEditBox then
1190 EditorPanel.Controls[i].Perform(CM_VISIBLECHANGED, WParam(ord(false)), 0);
1191 end;
1192
1193 procedure TIBDynamicGrid.Loaded;
1194 begin
1195 inherited Loaded;
1196 IBControlLinkChanged;
1197 ProcessColumns;
1198 end;
1199
1200 function TIBDynamicGrid.CreateColumns: TGridColumns;
1201 begin
1202 result := TDBGridColumns.Create(Self, TIBDynamicGridColumn);
1203 end;
1204
1205 procedure TIBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
1206 Y: Integer);
1207 var Coord: TGridCoord;
1208 obe: boolean;
1209 function PtInRect(const Rect : TRect;const p : TPoint) : Boolean;
1210
1211 begin
1212 PtInRect:=(p.y>=Rect.Top) and
1213 (p.y<Rect.Bottom) and
1214 (p.x>=Rect.Left) and
1215 (p.x<Rect.Right);
1216 end;
1217 begin
1218 if (Editor is TDBLookupCellEditor) and Editor.Visible
1219 and not PtInRect(Editor.BoundsRect,Point(X,Y)) then
1220 Editor.Perform(CM_EXIT,0,0); {Do insert new value if necessary}
1221 inherited MouseDown(Button, Shift, X, Y);
1222 obe := AllowOutboundEvents;
1223 AllowOutboundEvents := false;
1224 try
1225 Coord := MouseCoord(X,Y);
1226 if AllowColumnSort and (Coord.X <> -1) and (FixedRows > 0) and
1227 (Coord.Y = 0) and (MouseCoord(X+5,Y).X = Coord.X) {not on boundary}
1228 and (MouseCoord(X-5,Y).X = Coord.X) then
1229 ColumnHeaderClick(Coord.X-1);
1230 finally
1231 AllowOutboundEvents := obe
1232 end;
1233 end;
1234
1235 procedure TIBDynamicGrid.MoveSelection;
1236 begin
1237 inherited MoveSelection;
1238 SavePosition;
1239 end;
1240
1241 procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1242 begin
1243 IBControlLinkChanged;
1244 inherited LinkActive(Value);
1245 if (FActive <> Value) and Value then
1246 RestorePosition;
1247 FActive := Value
1248 end;
1249
1250 procedure TIBDynamicGrid.Notification(AComponent: TComponent;
1251 Operation: TOperation);
1252 var i: integer;
1253 begin
1254 inherited Notification(AComponent, Operation);
1255 if (Operation = opRemove) then
1256 begin
1257 if (FIBControlLink <> nil) and (AComponent = DataSource) then
1258 FIBControlLink.IBDataSet := nil
1259 else
1260 if AComponent is TDataSource then
1261 begin
1262 for i := 0 to Columns.Count - 1 do
1263 if TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource = AComponent then
1264 TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource := nil;
1265 end
1266 end
1267 end;
1268
1269 procedure TIBDynamicGrid.UpdateActive;
1270 begin
1271 inherited UpdateActive;
1272 if assigned(DataLink) and assigned(DataLink.DataSet) and
1273 DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1274 SavePosition;
1275 end;
1276
1277 constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1278 begin
1279 inherited Create(TheComponent);
1280 FAllowColumnSort := true;
1281 FIBControlLink := TIBGridControlLink.Create(self);
1282 FIndexFieldsList := TStringList.Create;
1283 FIndexFieldsList.Delimiter := ';';
1284 FIndexFieldsList.StrictDelimiter := true;
1285 FDBLookupCellEditor := TDBLookupCellEditor.Create(nil);
1286 FDBLookupCellEditor.Name := 'DBLookupCellEditor';
1287 FDBLookupCellEditor.Visible := False;
1288 FDBLookupCellEditor.AutoSize := false;
1289 end;
1290
1291 destructor TIBDynamicGrid.Destroy;
1292 begin
1293 if assigned(FIBControlLink) then FIBControlLink.Free;
1294 if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1295 if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
1296 Application.RemoveAsyncCalls(self);
1297 inherited Destroy;
1298 end;
1299
1300 function TIBDynamicGrid.EditorByStyle(Style: TColumnButtonStyle): TWinControl;
1301 var C: TIBDynamicGridColumn;
1302 bs: TColumnButtonStyle;
1303 begin
1304 C := ColumnFromGridColumn(Col) as TIBDynamicGridColumn;
1305 if C <> nil then
1306 begin
1307 bs := C.ButtonStyle;
1308 if (bs in [cbsAuto,cbsPickList]) and assigned(C.DBLookupProperties.ListSource) then
1309 begin
1310 Result := FDBLookupCellEditor;
1311 Exit;
1312 end;
1313 end;
1314 Result := inherited EditorByStyle(Style);
1315 end;
1316
1317 end.