ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 217
Committed: Fri Mar 16 10:27:26 2018 UTC (6 years ago) by tony
Content type: text/x-pascal
File size: 40435 byte(s)
Log Message:
Fixes Merged

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