ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 49
Committed: Thu Feb 2 16:20:12 2017 UTC (7 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 40417 byte(s)
Log Message:
Committing updates for Trunk

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 inherited Destroy;
1004 end;
1005
1006
1007 { TIBDynamicGrid }
1008
1009 procedure TIBDynamicGrid.ColumnHeaderClick(Index: integer);
1010 begin
1011 FColHeaderClick := true;
1012 try
1013 if Index = FLastColIndex then
1014 FDescending := not FDescending;
1015
1016 if assigned(FOnColumnHeaderClick) then
1017 OnColumnHeaderClick(self,Index);
1018
1019 FLastColIndex := Index;
1020 FFieldPosition := 0;
1021 if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active
1022 and (DataSource.DataSet is TIBParserDataSet) then
1023 begin
1024 if FLastColIndex < Columns.Count then
1025 {try and cache field position while dataset still open}
1026 FFieldPosition := TIBParserDataSet(DataSource.DataSet).Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1027 DataSource.DataSet.Active := false;
1028 Application.QueueAsyncCall(@DoReopen,0)
1029 end;
1030 finally
1031 FColHeaderClick := false
1032 end;
1033 end;
1034
1035 function TIBDynamicGrid.GetDataSource: TDataSource;
1036 begin
1037 if assigned(DataLink) then
1038 Result := inherited DataSource
1039 else
1040 Result := nil;
1041 end;
1042
1043 function TIBDynamicGrid.GetEditorBorderStyle: TBorderStyle;
1044 begin
1045 if Editor = FDBLookupCellEditor then
1046 Result := FDBLookupCellEditor.BorderStyle
1047 else
1048 Result := inherited EditorBorderStyle
1049 end;
1050
1051 procedure TIBDynamicGrid.SetDataSource(AValue: TDataSource);
1052 begin
1053 inherited DataSource := AValue;
1054 IBControlLinkChanged;
1055 end;
1056
1057 procedure TIBDynamicGrid.SetEditorBorderStyle(AValue: TBorderStyle);
1058 begin
1059 inherited EditorBorderStyle := AValue;
1060 if FDBLookupCellEditor.BorderStyle <> AValue then
1061 begin
1062 FDBLookupCellEditor.BorderStyle := AValue;
1063 if (Editor = FDBLookupCellEditor) and EditorMode then
1064 EditorWidthChanged(Col,FDBLookupCellEditor.Width);
1065 end;
1066 end;
1067
1068 procedure TIBDynamicGrid.ProcessColumns;
1069 var i: integer;
1070 begin
1071 for i := 0 to Columns.Count - 1 do
1072 begin
1073 if TIBDynamicGridColumn(columns[i]).InitialSortColumn then
1074 begin
1075 FFieldPosition := 0;
1076 FLastColIndex := i
1077 end
1078 end
1079 end;
1080
1081 procedure TIBDynamicGrid.SetIndexFieldNames(AValue: string);
1082 var idx: integer;
1083 begin
1084 if FIndexFieldNames = AValue then Exit;
1085 FIndexFieldNames := AValue;
1086 idx := 1;
1087 FIndexFieldsList.Clear;
1088 while idx <= Length(AValue) do
1089 FIndexFieldsList.Add(ExtractFieldName(AValue,idx));
1090 end;
1091
1092 procedure TIBDynamicGrid.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
1093 var OrderBy: string;
1094 begin
1095 if assigned(DataSource) and assigned(DataSource.DataSet)
1096 and (DataSource.DataSet is TIBCustomDataSet) then
1097 begin
1098 if (FFieldPosition = 0) and (FLastColIndex >= 0) and (FLastColIndex < Columns.Count) then
1099 {Not cached - let's hope we can find it before the dataset is opened.
1100 Won't work if dynamic columns}
1101 FFieldPosition := Parser.GetFieldPosition(Columns[FLastColIndex].FieldName);
1102 if FFieldPosition > 0 then
1103 begin
1104 if Descending then
1105 Parser.OrderByClause := IntToStr(FFieldPosition) + ' desc'
1106 else
1107 Parser.OrderByClause := IntToStr(FFieldPosition) + ' asc';
1108 end;
1109
1110 if assigned(FOnUpdateSortOrder) then
1111 begin
1112 OrderBy := Parser.OrderByClause;
1113 OnUpdateSortOrder(self,FLastColIndex,OrderBy);
1114 Parser.OrderByClause := OrderBy
1115 end
1116 end;
1117 end;
1118
1119 procedure TIBDynamicGrid.UpdateSortColumn(Sender: TObject);
1120 var i: integer;
1121 begin
1122 if Sender is TIBDynamicGridColumn then
1123 begin
1124 for i := 0 to Columns.Count -1 do
1125 if TObject(Columns[i]) <> Sender then
1126 TIBDynamicGridColumn(Columns[i]).InitialSortColumn := false
1127 end
1128
1129 end;
1130
1131 procedure TIBDynamicGrid.RestorePosition;
1132 begin
1133 if assigned(DataSource) and assigned(DataSource.DataSet) and DataSource.DataSet.Active then
1134 begin
1135 if assigned(FOnRestorePosition) then
1136 OnRestorePosition(self,@FBookmark);
1137 if (Length(FBookmark) > 0) and
1138 DataSource.DataSet.Locate(FIndexFieldNames,FBookmark,[]) then Exit;
1139
1140 if FDefaultPositionAtEnd then
1141 DataSource.DataSet.Last
1142 end;
1143 end;
1144
1145 procedure TIBDynamicGrid.SavePosition;
1146 var i: integer;
1147 F: TField;
1148 begin
1149 if FIndexFieldsList = nil then Exit;
1150
1151 SetLength(FBookmark,FIndexFieldsList.Count);
1152 for i := 0 to FIndexFieldsList.Count - 1 do
1153 begin
1154 F := DataSource.DataSet.FindField(FIndexFieldsList[i]);
1155 if assigned(F) then
1156 FBookmark[i] := F.AsVariant;
1157 end;
1158 end;
1159
1160 procedure TIBDynamicGrid.DoReOpen(Data: PtrInt);
1161 begin
1162 DataSource.DataSet.Active := true;
1163 end;
1164
1165 procedure TIBDynamicGrid.IBControlLinkChanged;
1166 begin
1167 if (DataSource <> nil) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataSet) then
1168 FIBControlLink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
1169 else
1170 FIBControlLink.IBDataSet := nil;
1171 end;
1172
1173 procedure TIBDynamicGrid.SetupEditor(aEditor: TDBLookupCellEditor; aCol: integer
1174 );
1175 var C: TIBDynamicGridColumn;
1176 begin
1177 C := ColumnFromGridColumn(aCol) as TIBDynamicGridColumn;
1178 if (c <> nil) then
1179 C.SetupEditor(aEditor);
1180 end;
1181
1182 procedure TIBDynamicGrid.DoEditorHide;
1183 var i: integer;
1184 begin
1185 inherited DoEditorHide;
1186 if assigned(EditorPanel) then
1187 for i := 0 to EditorPanel.ControlCount -1 do
1188 if EditorPanel.Controls[i] is TIBLookupComboEditBox then
1189 EditorPanel.Controls[i].Perform(CM_VISIBLECHANGED, WParam(ord(false)), 0);
1190 end;
1191
1192 procedure TIBDynamicGrid.Loaded;
1193 begin
1194 inherited Loaded;
1195 IBControlLinkChanged;
1196 ProcessColumns;
1197 end;
1198
1199 function TIBDynamicGrid.CreateColumns: TGridColumns;
1200 begin
1201 result := TDBGridColumns.Create(Self, TIBDynamicGridColumn);
1202 end;
1203
1204 procedure TIBDynamicGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
1205 Y: Integer);
1206 var Coord: TGridCoord;
1207 obe: boolean;
1208 function PtInRect(const Rect : TRect;const p : TPoint) : Boolean;
1209
1210 begin
1211 PtInRect:=(p.y>=Rect.Top) and
1212 (p.y<Rect.Bottom) and
1213 (p.x>=Rect.Left) and
1214 (p.x<Rect.Right);
1215 end;
1216 begin
1217 if (Editor is TDBLookupCellEditor) and Editor.Visible
1218 and not PtInRect(Editor.BoundsRect,Point(X,Y)) then
1219 Editor.Perform(CM_EXIT,0,0); {Do insert new value if necessary}
1220 inherited MouseDown(Button, Shift, X, Y);
1221 obe := AllowOutboundEvents;
1222 AllowOutboundEvents := false;
1223 try
1224 Coord := MouseCoord(X,Y);
1225 if AllowColumnSort and (Coord.X <> -1) and (FixedRows > 0) and
1226 (Coord.Y = 0) and (MouseCoord(X+5,Y).X = Coord.X) {not on boundary}
1227 and (MouseCoord(X-5,Y).X = Coord.X) then
1228 ColumnHeaderClick(Coord.X-1);
1229 finally
1230 AllowOutboundEvents := obe
1231 end;
1232 end;
1233
1234 procedure TIBDynamicGrid.MoveSelection;
1235 begin
1236 inherited MoveSelection;
1237 SavePosition;
1238 end;
1239
1240 procedure TIBDynamicGrid.LinkActive(Value: Boolean);
1241 begin
1242 IBControlLinkChanged;
1243 inherited LinkActive(Value);
1244 if (FActive <> Value) and Value then
1245 RestorePosition;
1246 FActive := Value
1247 end;
1248
1249 procedure TIBDynamicGrid.Notification(AComponent: TComponent;
1250 Operation: TOperation);
1251 var i: integer;
1252 begin
1253 inherited Notification(AComponent, Operation);
1254 if (Operation = opRemove) then
1255 begin
1256 if (FIBControlLink <> nil) and (AComponent = DataSource) then
1257 FIBControlLink.IBDataSet := nil
1258 else
1259 if AComponent is TDataSource then
1260 begin
1261 for i := 0 to Columns.Count - 1 do
1262 if TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource = AComponent then
1263 TIBDynamicGridColumn(Columns[I]).DBLookupProperties.ListSource := nil;
1264 end
1265 end
1266 end;
1267
1268 procedure TIBDynamicGrid.UpdateActive;
1269 begin
1270 inherited UpdateActive;
1271 if assigned(DataLink) and assigned(DataLink.DataSet) and
1272 DataLink.DataSet.Active and (DataLink.DataSet.State = dsInsert) then
1273 SavePosition;
1274 end;
1275
1276 constructor TIBDynamicGrid.Create(TheComponent: TComponent);
1277 begin
1278 inherited Create(TheComponent);
1279 FAllowColumnSort := true;
1280 FIBControlLink := TIBGridControlLink.Create(self);
1281 FIndexFieldsList := TStringList.Create;
1282 FIndexFieldsList.Delimiter := ';';
1283 FIndexFieldsList.StrictDelimiter := true;
1284 FDBLookupCellEditor := TDBLookupCellEditor.Create(nil);
1285 FDBLookupCellEditor.Name := 'DBLookupCellEditor';
1286 FDBLookupCellEditor.Visible := False;
1287 FDBLookupCellEditor.AutoSize := false;
1288 end;
1289
1290 destructor TIBDynamicGrid.Destroy;
1291 begin
1292 if assigned(FIBControlLink) then FIBControlLink.Free;
1293 if assigned(FIndexFieldsList) then FIndexFieldsList.Free;
1294 if assigned(FDBLookupCellEditor) then FDBLookupCellEditor.Free;
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.