📄 teedbtre.pas
字号:
{**********************************************}
{ TDBTree Database Tree Component }
{ Copyright (c) 1998-2002 by David Berneda }
{**********************************************}
{$I TeeDefs.inc}
unit TeeDBTre;
{ Linking a Tree component to a Database Table or Query
(or any other DataSet), is easy just by setting some
properties.
Use the "Database Wizard Dialog" to connect DBTree components to
Tables or Queries.
For more advanced layouts, use the Layout collection property.
It's also easy to do it by code. Follow the instructions below.
Related Property:
=================
MultiLineText : Boolean ( default True )
When True, Tree nodes are filled with several lines of text.
When False, text is joined into a single line.
Situations:
===========
Situation 1:
============
We have a table or query which includes a "Code and Parent"
fields:
Code Parent Text
------ ------ ------------
1 0 Continents
2 1 America
3 1 Africa
4 1 Australia
5 2 USA
6 5 California
7 4 Sydney
.. ... ...
We want to create a tree like this:
Continents -> America -> USA -> California
-> Africa
-> Australia -> Sydney
We need to set the following properties:
With DBTree1 do
begin
DataSet := Table1 ;
CodeField := 'Code' ;
ParentField := 'Parent' ;
TextFields := 'Text';
Refresh;
end;
If we need several fields for "text", we can use this syntax:
DBTree1.TextFields := 'Text;OtherText;OtherField';
Situation 2:
============
We have a Table or Query or any other DataSet but it does not
include a "Parent" or "Code" field.
We have this data:
Country City
---------- ---------------
AUSTRALIA Sydney
USA New York
UK London
AUSTRALIA Camberra
UK Manchester
UK Liverpool
USA Michigan
USA Chicago
And the tree we need is:
AUSTRALIA -> Sydney
-> Camberra
UK -> Liverpool
-> London
-> Manchester
USA -> Chicago
-> Michigan
-> New York
The code we need is:
With DBTree1 do
begin
DataSet := Table1 ;
CodeField := '';
ParentField := 'Country' ;
TextFields := 'City' ;
Refresh;
end;
Additionally you can expand the first root node:
DBTree1.Roots[0].Expanded:=True;
Situation 3:
============
We have a master-detail relation between to tables or queries
(or any other types of datasets):
Master dataset:
Person Department
------- --------------
John Accounting
Chris Management
Anne Sales
Peter Accounting
James Sales
Linda Sales
Detail dataset:
Person Month Salary
------- ------ ----------
John April $1000
John May $1100
John June $800
John July $1200
...
Chris March $900
Chris April $700
Chris May $500
...
Anne...
We want the following tree:
Department -> Accounting -> John -> April $1000
-> May $1100
-> June $800
-> July $1200
-> Peter
-> Management -> Chris -> March $900
-> April $700
-> May $500
-> Sales -> Anne
-> James
-> Linda
The code to use is:
With DBTree1 do
begin
DataSet := Table1 ; ( the master table )
CodeField := '';
ParentField := 'Department' ;
TextFields := 'Person' ;
Detail := Table2 ; ( the detail table )
DetailFields:= 'Month;Salary' ;
Refresh;
end;
More Advanced Situations:
=========================
When having more than one master-detail relationship (more than 2 datasets)
or for special db-trees, add more DBLayout items, either at design-time
or runtime.
}
interface
uses
{$IFNDEF LINUX}
Windows, Messages,
{$ENDIF}
SysUtils, Classes,
{$IFDEF CLX}
QGraphics, QControls, QForms, QDialogs, QExtCtrls,
{$ELSE}
Graphics, Controls, Forms, Dialogs, ExtCtrls,
{$ENDIF}
{$IFDEF CLR}
Contnrs, Variants,
{$ENDIF}
TeeProcs, TeeTree, DB;
Const MaxFields = 20;
type
EDBTreeException=class(Exception);
TCustomDBTree=class;
TMaxDBTreeFields=Array[0..MaxFields-1] of TField;
TDBTreeFields=Packed Record
Count : Integer;
Field : TMaxDBTreeFields;
end;
TDBLayoutDisplay=(ldSingle,ldMultiLine,ldGrid);
TDBLayout=class(TCollectionItem)
private
FCodeField : String; // used only in situation "1" ( Parent->Code )
FDataSet : TDataSet; // the dataset
FDisplayMode : TDBLayoutDisplay; // the display mode (single line, multi, grid)
FHeaderFormat : TTreeNodeShape; // optional header text and format
FParentField : String; // List of field names to do group by
FFormat : TTreeNodeShape; // optional shape determining the node format
FFields : String; // List of field names to display
private
ICodeField : TField;
IDetails : {$IFDEF CLR}TObjectList{$ELSE}TList{$ENDIF};
IFields : TDBTreeFields;
IParents : TDBTreeFields;
Function AddNode(AParent:TTreeNodeShape):TTreeNodeShape;
Procedure AddNodeText(ANode:TTreeNodeShape; Var AFields:TDBTreeFields);
Function AddText(AChild:TTreeNodeShape):TTreeNodeShape;
Procedure RunNextLayouts(ADetailRoot:TTreeNodeShape);
procedure SetDataSet(const Value: TDataSet);
procedure SetFields(const Value: String);
procedure SetCodeField(const Value: String);
procedure SetParentField(const Value: String);
procedure SetFormat(const Value: TTreeNodeShape);
function GetFormat: TTreeNodeShape;
function GetHeaderFormat: TTreeNodeShape;
procedure SetHeaderFormat(const Value: TTreeNodeShape);
procedure ReadFormat(Reader: TStream);
procedure WriteFormat(Writer: TStream);
procedure ReadHeaderFormat(Reader: TStream);
procedure WriteHeaderFormat(Writer: TStream);
protected
procedure DefineProperties(Filer:TFiler); override;
Procedure FinishAddingText(ANode:TTreeNodeShape); virtual;
procedure Prepare; virtual;
Procedure Run(ARoot:TTreeNodeShape); virtual;
public
Destructor Destroy; override;
Procedure Assign(Source:TPersistent); override;
Function Tree:TCustomDBTree;
published
property DataSet:TDataSet read FDataSet write SetDataSet;
property DisplayMode:TDBLayoutDisplay read FDisplayMode
write FDisplayMode default ldSingle;
property HeaderFormat:TTreeNodeShape read GetHeaderFormat write SetHeaderFormat
stored False;
property Fields:String read FFields write SetFields;
property CodeField:String read FCodeField write SetCodeField;
property ParentField:String read FParentField write SetParentField;
property Format:TTreeNodeShape read GetFormat write SetFormat
stored False;
end;
TDBTreeLayout=class(TOwnedCollection)
private
Function Get(Index:Integer):TDBLayout;
Procedure Put(Index:Integer; Const Value:TDBLayout);
public
Function Add:TDBLayout;
property Node[Index:Integer]:TDBLayout read Get write Put; default;
end;
TCustomDBTree = class(TCustomTree)
private
{ Private declarations }
FLayout: TDBTreeLayout;
Procedure CreateDetail;
Procedure CreateParentLayout;
procedure SetDataSet(const Value: TDataSet);
procedure SetDetail(const Value: TDataSet);
procedure CheckDataSet(var ADataSet: TDataSet; const Value: TDataSet);
procedure SetLayout(const Value: TDBTreeLayout);
function GetDataSet: TDataSet;
function GetMultiLineText: Boolean;
procedure SetMultiLineText(const Value: Boolean);
function GetTextFields: String;
procedure SetTextFields(const Value: String);
function GetCodeField: String;
function GetDetail: TDataSet;
function GetDetailFields: String;
function GetParentField: String;
procedure SetCodeField(const Value: String);
procedure SetDetailFields(const Value: String);
procedure SetParentField(const Value: String);
function IsLayoutStored: Boolean;
protected
IPreviewRecords : Integer;
{ Protected declarations }
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
{ Public declarations }
Constructor Create(AOwner:TComponent); override;
Destructor Destroy; override;
Function FindNodeCode(ACode:Integer):TTreeNodeShape;
Procedure Refresh;
property Layout:TDBTreeLayout read FLayout write SetLayout
stored IsLayoutStored;
// compatibility with version 1.
// The new Layout[] property now replaces all these:
property CodeField:String read GetCodeField write SetCodeField;
property DataSet:TDataSet read GetDataSet write SetDataSet;
property Detail:TDataSet read GetDetail write SetDetail;
property DetailFields:String read GetDetailFields write SetDetailFields;
property MultiLineText:Boolean read GetMultiLineText write SetMultiLineText
default False;
property ParentField:String read GetParentField write SetParentField;
property TextFields:String read GetTextFields write SetTextFields;
end;
TDBTree=class(TCustomDBTree)
{$IFNDEF CLX}
{$IFDEF D4}
public
property DockManager;
{$ENDIF}
{$ENDIF}
published
{ TCustomDBTree }
property CodeField;
property DataSet;
property Detail;
property DetailFields;
property MultiLineText;
property ParentField;
property TextFields;
{ TCustomTree properties }
property AllowDelete;
property AllowPanning;
property BackImage;
property BackImageMode;
property BufferedDisplay;
property CrossBox;
property Designing;
property DragAndDrop;
property Gradient;
property Grid;
property HorzScrollBar;
property HotTrack;
property Images;
property Layout;
property Monochrome;
property Page;
property PrintProportional;
property ReadOnly;
property ScrollMouseButton;
property Selected;
property SingleSelection;
property ShowHintShapes;
property ShowRootCross;
property SnapToGrid;
property TextEditor;
property VertScrollBar;
property View3DOptions;
property WheelNavigation;
property Zoom;
{ TCustomTree events }
property OnAddingConnection;
property OnAfterDraw;
property OnBeforeDraw;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -