ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/ibcontrols/IBDynamicGrid.pas
Revision: 407
Committed: Tue Dec 6 23:18:32 2022 UTC (23 months, 1 week ago) by tony
Content type: text/x-pascal
File size: 40805 byte(s)
Log Message:
Fixes to ensure compilation with Laz 2.3.0

File Contents

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

Properties

Name Value
svn:eol-style native