📄 fcdbtreeview.pas
字号:
tempDS, curDS: TDataSource;
index, tempIndex: integer;
token: string;
OldLinks: TList;
{ Retrieve TDataSource with the name of the datasource }
Function DataSourceFromToken(DataSourceName: string): TDataSource;
var Component: TComponent;
token1, token2: string;
begin
result:= nil;
if (pos('.', DataSourceName)<=0) and
(pos('->', DataSourceName)<=0) then
begin
Component:= GetParentForm(self).FindComponent(DataSourceName);
end
else begin
token1:= fcGetToken(DataSourceName, '.', 0);
token2:= fcGetToken(DataSourceName, '.', 1);
Component:= FindGlobalComponent(token1);
if Component<>nil then
Component:= Component.FindComponent(token2);
if Component=nil then { 7/25/99 - Builder notation }
begin
token1:= fcGetToken(DataSourceName, '->', 0);
token2:= fcGetToken(DataSourceName, '->', 1);
Component:= FindGlobalComponent(token1);
if Component<>nil then
Component:= Component.FindComponent(token2);
end
end;
if Component is TDataSource then
result:= TDataSource(Component);
end;
Function GetDataLink(curDS: TDataSource): TfcTreeDataLink;
var i: integer;
begin
for i:= 0 to OldLinks.count-1 do begin
if TfcTreeDataLink(OldLinks[i]).DataSource = curDS then
begin
result:= OldLinks[i];
OldLinks.Delete(i); { Remove from list so that its not destroyed later }
exit;
end
end;
result:= TfcTreeDataLink.Create(Self);
end;
begin
if csDestroying in ComponentState then exit;
OldLinks:= TList.Create;
try
for i:= 0 to FDataLinks.count-1 do begin
if (FDataLinks[i]<>FFirstDataLink) and
(FDataLinks[i]<>FLastDataLink) then
OldLinks.Add(FDataLinks[i]);
end;
if ((LastDS=nil) or (LastDS.DataSet=nil)) and (DataSources='') then
begin
{ Clearing datasource }
if FDataLinks.Count>0 then invalidate;
FDataLinks.Clear;
exit;
end;
FDataLinks.Clear;
if FFirstDataLink.DataSet<>nil then
begin
FDataLinks.Add(FFirstDataLink);
if FFirstDataLink.Active then // 2/23/01 - Make sure active so that recordcount gets set
FFirstDataLink.BufferCount := CacheSize;
index:= 1;
end
else index:= 0;
if FFirstDataLink.Dataset<>FLastDataLink.DataSet then
begin
FDataLinks.Add(FLastDataLink);
if FFirstDataLink.Active then // Make sure active so that recordcount gets set
FLastDataLink.BufferCount := CacheSize;
end;
if (DataSources='') then begin
{ 3/2/99 - Special case of only one level so don't add any more datalinks}
if FFirstDataLink.Dataset=FLastDataLink.DataSet then exit;
try
curDS:= LastDS;
repeat
tempDS:= fcGetControlMasterSource(curDS.dataset);
if tempDS=nil then
tempDS:= fcGetControlDataSource(curDS.dataset);
curDS:= tempDS;
if (curDS<>FirstDS) and (curDS<>nil) then
begin
FDataLink:= GetDataLink(curDS);
FDataLink.BufferCount := CacheSize;
FDataLink.DataSource := curDS;
FDataLinks.Insert(index, FDataLink);
end
until (curDS=FirstDS) or (curDS=nil);
finally
end
end
else begin
HaveBadLink:= False;
tempIndex:= 0;
repeat
token:= fcGetToken(DataSources, ';', tempIndex);
curDS:= DataSourceFromToken(token);
if (curDS=nil) and
((pos('.', token)>0) or (pos('->', token)>0)) then { 7/25/99 - Suppport Builder notation }
HaveBadLink:= True;
if (curDS<>nil) and (curDS<>FirstDS) and (curDS<>LastDS) then
begin
FDataLink:= TfcTreeDataLink.Create(Self);
FDataLink.BufferCount := CacheSize;
FDataLink.DataSource := curDS;
FDataLinks.Insert(index, FDataLink);
inc(index);
end;
inc(tempIndex);
until token = '';
end;
finally
for i:= 0 to OldLinks.Count-1 do TfcTreeDataLink(OldLinks[i]).Free;
OldLinks.Free;
end
end;
procedure TfcDBCustomTreeView.SetDataSource(Value: TDataSource);
begin
FreeLastActiveBookmark; // Free LastActiveBookmark when datasource changes
FFirstDataLink.Datasource:= Value;
RefreshDataLinks(Value, FLastDataLink.DataSource);
{ Initialize other data links }
if (Value<>nil) and (Value.DataSet<>nil) then
LinkActive(Value.DataSet, Value.Dataset.Active);
end;
procedure TfcDBCustomTreeView.SetDataSources(Value: String);
begin
if Value<>FDataSourcesMiddle then
begin
FreeLastActiveBookmark; // Free LastActiveBookmark when datasource changes
FDataSourcesMiddle:= Value;
RefreshDataLinks(FFirstDataLink.DataSource, FLastDataLink.DataSource);
if not HaveValidDataLinks then invalidate;
end
end;
procedure TfcDBCustomTreeView.SetLastDataSource(Value: TDataSource);
begin
FreeLastActiveBookmark; // Free LastActiveBookmark when datasource changes
FLastDataLink.Datasource:= Value;
RefreshDataLinks(FFirstDataLink.DataSource, Value);
{ Initialize other data links }
if (Value<>nil) and (Value.DataSet<>nil) then
LinkActive(Value.DataSet, Value.Dataset.Active);
end;
procedure TfcDBCustomTreeView.LinkActive(DataSet: TDataSet; Value: Boolean);
begin
SaveIfFirstRecordBookmark(DataSet);
if (FDataLinks.count>0) and (Dataset = TfcTreeDataLink(FDataLinks[0]).DataSet) then begin
FreeRootBookmark;
IsRootDataSetMoved;
end;
LayoutChanged;
UpdateScrollBar;
end;
{ Return true if master node has changed }
{ This code is not implemented yet }
Function TfcDBCustomTreeView.InMasterChanging(DataSet: TDataSet): boolean;
begin
if DataSet = DatasourceFirst.dataset then result:= False
else result:= True;
end;
Function TfcDBCustomTreeView.IsRootDataSetMoved: boolean;
var TempRootDataSetBookmark: TBookmark;
res: CmpBkmkRslt;
RootDataSet: TDataSet;
begin
result:= False;
if FDataLinks.count<=0 then exit;
RootDataSet:= TfcTreeDataLink(FDataLinks[0]).DataSet;
if (RootDataSet=nil) then exit;
if RootDataSet.state <> dsBrowse then exit;
TempRootDataSetBookmark:= RootDataSet.GetBookmark;
if TempRootDataSetBookmark=nil then exit;
if RootDataSetBookmark=nil then begin
RootDataSetBookmark:= TempRootDataSetBookmark;
exit;
end;
res:= RootDataSet.CompareBookmarks(RootDataSetBookmark, TempRootDataSetBookmark);
if (res=CMPKeyEql) or (res=CMPEql) then begin
RootDataSet.FreeBookmark(TempRootDataSetBookmark);
exit;
end;
result:= True;
FreeRootBookmark;
RootDataSetBookmark:= TempRootDataSetBookmark;
end;
procedure TfcDBCustomTreeView.DataChanged(DataSet: TDataSet);
var ChildDataLink: TfcTreeDataLink;
begin
if FDataLinks.Count=0 then exit;
if Dataset = TfcTreeDataLink(FDataLinks[0]).DataSet then begin
SaveIfFirstRecordBookmark(DataSet);
if IsRootDataSetMoved then
ActiveDataSet:= DataSet;
UpdateScrollBar;
end
else if FScrollWithinLevel then UpdateScrollBar;
if dataset.state = dsBrowse then
begin
ChildDataLink:= GetChildDataLink(Dataset);
if ChildDataLink<>nil then ResetStartOffsets(ChildDataLink.DataSet);
end;
// ResetStartOffsets(DataSet); { 12/23/98 }
CheckMaxWidthGrow:= True;
invalidateClient;
end;
Function TfcDBCustomTreeView.GetDataLinkIndex(Dataset: TDataset): integer;
var i:integer;
begin
result:= -1;
if DataSet =nil then exit;
for i:= 0 to FDataLinks.count-1 do begin
if TfcTreeDataLink(FDataLinks[i]).dataset = DataSet then
begin
result:= i;
break;
end
end;
end;
Function TfcDBCustomTreeView.GetDataLink(Dataset: TDataset): TfcTreeDataLink;
var i:integer;
begin
result:= nil;
if DataSet =nil then exit;
for i:= 0 to FDataLinks.count-1 do begin
if TfcTreeDataLink(FDataLinks[i]).dataset = DataSet then
result:= TfcTreeDataLink(FDataLinks[i]);
end;
end;
Function TfcDBCustomTreeView.GetParentDataLink(Dataset: TDataset): TfcTreeDataLink;
var i:integer;
begin
result:= nil;
for i:= 0 to FDataLinks.count-1 do begin
if TfcTreeDataLink(FDataLinks[i]).dataset = DataSet then
begin
if i>0 then
result:= TfcTreeDataLink(FDataLinks[i-1]);
break;
end
end;
end;
Function TfcDBCustomTreeView.GetChildDataLink(Dataset: TDataset): TfcTreeDataLink;
var i:integer;
begin
result:= nil;
for i:= 0 to FDataLinks.count-1 do begin
if TfcTreeDataLink(FDataLinks[i]).dataset = DataSet then
begin
if (i+1)<=FDataLinks.count-1 then
result:= TfcTreeDataLink(FDataLinks[i+1]);
break;
end
end;
end;
procedure TfcDBCustomTreeView.Scroll(DataSet: TDataSet; Distance: Integer);
var DataLink: TfcTreeDataLink;
begin
if not HandleAllocated then Exit;
if FDataLinks.Count>0 then begin
if Dataset = TfcTreeDataLink(FDataLinks[0]).DataSet then begin
IsRootDataSetMoved;
UpdateScrollBar;
end
else if FScrollWithinLevel then UpdateScrollBar;
end;
if IsChildDataSetOfActive(DataSet) then
begin
if (dtvoAutoExpandOnDSScroll in Options) then
LastVisibleDataSet:= dataset;
end
else LastVisibleDataSet:= dataset;
if ActiveDataSet<>DataSet then
begin
if (dtvoAutoExpandOnDSScroll in Options) then
ActiveDataSet:= DataSet;
DataLink:= GetChildDataLink(ActiveDataSet);
if DataLink<>nil then begin
ResetStartOffsets(DataLink.DataSet);
end;
end
else begin
DataLink:= GetChildDataLink(ActiveDataSet);
if DataLink<>nil then ResetStartOffsets(DataLink.DataSet);
end;
SaveIfFirstRecordBookmark(DataSet);
CheckMaxWidthGrow:= True;
InvalidateClient;
end;
Procedure TfcDBCustomTreeView.SaveIfFirstRecordBookmark(DataSet: TDataSet);
begin
if DataSet=nil then exit;
if FDataLinks.Count>0 then
begin
if Dataset <> TfcTreeDataLink(FDataLinks[0]).DataSet then exit;
if (DataSet.state = dsBrowse) and (DataSet.Bof) and (TfcTreeDataLink(FDataLinks[0]).DataSet = DataSet) then
begin
FreeFirstBookmark;
FirstBookmark:= dataset.GetBookmark;
end
end;
if DataSet.state in [dsEdit, dsInsert] then FreeFirstBookmark;
end;
Procedure TfcDBCustomTreeView.FreeFirstBookmark;
begin
{$ifdef fcdelphi4up}
if FirstBookmark<>Nil then FreeMem(FirstBookmark);
FirstBookmark:= nil;
{$else}
if FirstBookmark<>Nil then StrDispose(FirstBookmark);
FirstBookmark:= nil;
{$endif}
end;
Procedure TfcDBCustomTreeView.FreeLastActiveBookmark;
begin
{$ifdef fcdelphi4up}
if LastActiveBookmark<>Nil then FreeMem(LastActiveBookmark);
LastActiveBookmark:= nil;
{$else}
if LastActiveBookmark<>Nil then StrDispose(LastActiveBookmark);
LastActiveBookmark:= nil;
{$endif}
end;
procedure TfcDBCustomTreeView.DoCalcNodeAttributes(Node: TfcDBTreeNode);
begin
if Assigned(FOnCalcNodeAttributes) then
FOnCalcNodeAttributes(Self, Node);
end;
procedure TfcDBCustomTreeView.DoCalcSectionAttributes(Node: TfcDBTreeNode;
Section: TfcTreeHeaderSection; var DisplayText: string);
begin
if Assigned(FOnCalcSectionAttributes) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -