ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 41
Committed: Sat Jul 16 12:25:48 2016 UTC (7 years, 8 months ago) by tony
Content type: text/x-pascal
File size: 40078 byte(s)
Log Message:
Committing updates for Release R1-4-2

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