{*******************************************************************} { } { Developer Express Visual Component Library } { Express data-aware OrgChart } { } { Copyright (c) 1998-2009 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSORGCHART AND ALL ACCOMPANYING } { VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE end USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {*******************************************************************} unit dxdborgc; {$I cxVer.inc} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, dxorgchr {$IFDEF DELPHI6}, Variants{$ENDIF}; type TdxDbOrgChart = class; TdxOcNewKeyEvent = procedure(Sender:TObject; MaxValue:Variant; var KeyValue:Variant) of object; TdxOcDataLink = class(TDataLink) private FTree: TdxDbOrgChart; FFiltered: Boolean; FFilter: String; protected procedure ActiveChanged; override; procedure DataSetChanged; override; procedure DataSetScrolled(Distance: Integer); override; procedure RecordChanged(Field: TField); override; end; TdxDbOcNode = class(TdxOcNode) private FKey: Variant; FParentKey: Variant; FOrder: Variant; FRecNum: Integer; FRefreshed: Boolean; protected procedure SetText(const Value: String); override; procedure ReadData(Stream: TStream); override; public function DbOwner: TdxDbOrgChart; property Key: Variant read FKey; property ParentKey: Variant read FParentKey; end; TdxDbOrgChart = class(TdxCustomOrgChart) private FLink: TdxOcDataLink; FKeyFieldName: String; FParentFieldName: String; FTextFieldName: String; FOrderFieldName: String; FWidthFieldName: String; FHeightFieldName: String; FColorFieldName: String; FShapeFieldName: String; FChAlignFieldName: String; FImIndexFieldName: String; FImAlignFieldName: String; FKeyField: TField; FParentField: TField; FTextField: TField; FOrderField: TField; FWidthField: TField; FHeightField: TField; FColorField: TField; FShapeField: TField; FChAlignField: TField; FImIndexField: TField; FImAlignField: TField; FKeyList: TList; FMaxKey: Variant; FCurRec: Integer; FRecCount: Integer; FOnNewKey: TdxOcNewKeyEvent; FOnLoadNode: TdxOcEvent; FEnableDB: Boolean; FKeyOrder: Boolean; procedure AssignFields; procedure RefreshItems; procedure RefreshRecord; procedure RefreshParents; procedure BeginRefresh; procedure EndRefresh; function FindNearest(AKey: Variant; var AIndex: Integer): Boolean; function GetNodeByKey(AKey: Variant): TdxDbOcNode; procedure AddToKeyList(ANode: TdxDbOcNode); procedure DelFromKeyList(ANode: TdxDbOcNode); function FindIndex(AKey: Variant; AParent: TdxDbOcNode): Integer; function LocateToNode(ANode: TdxDbOcNode): Boolean; procedure SetParentNode(ANode: TdxDbOcNode); procedure CheckKeys(ANode: TdxDbOcNode); procedure CheckRec(ANode: TdxDbOcNode); function NewKey: Variant; function CreateDBNode(AKey: Variant; AParent: TdxDbOcNode): TdxDbOcNode; procedure MoveDBNode(ANode,AParent: TdxDbOcNode); function GetDataSource: TDataSource; function GetDataSet: TDataSet; procedure ActiveChanged; procedure DataChanged; procedure Scroll(Dist: Integer); procedure RecordChanged(Field: TField); procedure SetBookmark(ABookmark: Integer); procedure SetDataSource(Value: TDataSource); procedure SetKeyFieldName(const Value: String); procedure SetParentFieldName(const Value: String); procedure SetTextFieldName(const Value: String); procedure SetOrderFieldName(const Value: String); procedure SetWidthFieldName(const Value: String); procedure SetHeightFieldName(const Value: String); procedure SetColorFieldName(const Value: String); procedure SetShapeFieldName(const Value: String); procedure SetChAlignFieldName(const Value: String); procedure SetImIndexFieldName(const Value: String); procedure SetImAlignFieldName(const Value: String); protected function CreateNode: TdxOcNode; override; function CreateEditor: TdxOcInplaceEdit; override; function InternalAdd(AParent: TdxOcNode; Data: TdxOcNodeData; Idx:Integer): TdxOcNode; override; procedure InternalMoveTo(AParent, ANode: TdxOcNode; Idx: Integer); override; procedure NodeChanged(ANode: TdxOcNode); override; procedure DoChange(Node: TdxOcNode); override; procedure DoChanging(Node: TdxOcNode; var Allow: Boolean); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Delete(ANode: TdxOcNode); override; procedure ShowEditor; override; function Active: Boolean; property DataSet: TDataSet read GetDataSet; property KeyField: TField read FKeyField; property ParentField: TField read FParentField; property TextField: TField read FTextField; property OrderField: TField read FOrderField; property WidthField: TField read FWidthField; property HeightField: TField read FHeightField; property ColorField: TField read FColorField; property ShapeField: TField read FShapeField; property ChAlignField: TField read FChAlignField; property ImageField: TField read FImIndexField; property ImAlignField: TField read FImAlignField; property WidthFieldName: String read FWidthFieldName write SetWidthFieldName; property HeightFieldName: String read FHeightFieldName write SetHeightFieldName; property ColorFieldName: String read FColorFieldName write SetColorFieldName; property ShapeFieldName: String read FShapeFieldName write SetShapeFieldName; property ChAlignFieldName: String read FChAlignFieldName write SetChAlignFieldName; property ImAlignFieldName: String read FImAlignFieldName write SetImAlignFieldName; published property DataSource: TDataSource read GetDataSource write SetDataSource; property KeyFieldName: String read FKeyFieldName write SetKeyFieldName; property ParentFieldName: String read FParentFieldName write SetParentFieldName; property TextFieldName: String read FTextFieldName write SetTextFieldName; property OrderFieldName: String read FOrderFieldName write SetOrderFieldName; property ImageFieldName: String read FImIndexFieldName write SetImIndexFieldName; property KeyOrder: Boolean read FKeyOrder write FKeyOrder default False; property OnNewKey: TdxOcNewKeyEvent read FOnNewKey write FOnNewKey; property OnLoadNode: TdxOcEvent read FOnLoadNode write FOnLoadNode; property LineColor; property LineWidth; property SelectedNodeColor; property SelectedNodeTextColor; property DefaultNodeWidth; property DefaultNodeHeight; property IndentX; property IndentY; property Options; property EditMode; property Images; property DefaultImageAlign; property BorderStyle; property Rotated; property Zoom; property OnCreateNode; property OnChange; property OnChanging; property OnCollapsed; property OnCollapsing; property OnDeletion; property OnExpanded; property OnExpansion; property OnEditing; property OnEdited; property OnSetFont; property OnDrawNode; property OnGetText; property OnSetText; property Align; property Ctl3D; property Color; property Enabled; property Font; property ParentColor default False; property ParentCtl3D; property TabStop default True; property Visible; property OnClick; property OnDblClick; property OnEnter; property OnExit; property OnDragDrop; property OnDragOver; property OnStartDrag; property OnEndDrag; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnKeyDown; property OnKeyPress; property OnKeyUp; property PopupMenu; property ParentFont; property ParentShowHint; property ShowHint; end; implementation {$IFDEF DELPHI6} function VarCompare(const V1, V2: Variant): Integer; begin try if V1 = V2 then Result := 0 else if VarIsNull(V1) then Result := -1 else if VarIsNull(V2) then Result := 1 else if V1 < V2 then Result := -1 else Result := 1; except on EVariantError do Result := -1; end end; {$ENDIF} function VarEQ(const V1,V2: Variant): Boolean; begin try Result := V1 = V2; except Result := False; end; end; function VarGT(const V1,V2: Variant): Boolean; begin try {$IFDEF DELPHI6} Result := VarCompare(V1, V2) > 0; {$ELSE} Result := V1 > V2; {$ENDIF} except Result := False; end; end; function VarGE(const V1,V2: Variant): Boolean; begin try {$IFDEF DELPHI6} Result := VarCompare(V1, V2) >= 0; {$ELSE} Result := V1 >= V2; {$ENDIF} except Result := False; end; end; function IsIntegerField(AField: TField): Boolean; begin if AField=nil then Result := False else Result := AField.DataType in [ftInteger,ftSmallint,ftWord,ftAutoInc]; end; { TdxOcDataLink } procedure TdxOcDataLink.ActiveChanged; begin FTree.ActiveChanged; end; procedure TdxOcDataLink.DataSetChanged; begin if (FFiltered<>DataSet.Filtered) or (FFilter<>DataSet.Filter) then FTree.ActiveChanged else FTree.DataChanged; end; procedure TdxOcDataLink.DataSetScrolled(Distance: Integer); begin FTree.Scroll(Distance); end; procedure TdxOcDataLink.RecordChanged(Field: TField); begin FTree.RecordChanged(Field); end; { TdxDbOcNode } function TdxDbOcNode.DbOwner: TdxDbOrgChart; begin Result := TdxDbOrgChart(Owner); end; procedure TdxDbOcNode.SetText(const Value: String); var TheText: String; begin TheText := Value; if (DbOwner.TextField<>nil) and (Length(TheText) > DbOwner.TextField.Size) then SetLength (TheText, DbOwner.TextField.Size); inherited SetText(TheText); end; procedure TdxDbOcNode.ReadData(Stream: TStream); begin DbOwner.FEnableDB := False; inherited ReadData(Stream); DbOwner.FEnableDB := True; DbOwner.NodeChanged(Self); end; { TdxDbOrgChart } constructor TdxDbOrgChart.Create(AOwner: TComponent); begin inherited Create(AOwner); FLink := TdxOcDataLink.Create; FLink.FTree := Self; FKeyList := TList.Create; FMaxKey := null; FEnableDB := True; end; destructor TdxDbOrgChart.Destroy; begin FEnableDB := False; FLink.Free; FKeyList.Free; FKeyList := nil; inherited Destroy; end; function TdxDbOrgChart.Active: Boolean; begin Result := FLink.Active and (KeyField<>nil) and (ParentField<>nil); end; function TdxDbOrgChart.GetDataSet: TDataSet; begin Result := FLink.DataSet; end; function TdxDbOrgChart.GetDataSource: TDataSource; begin Result := FLink.DataSource; end; procedure TdxDbOrgChart.SetBookmark(ABookmark: Integer); begin if ABookmark<>FCurRec then FCurRec := FCurRec + DataSet.MoveBy(ABookmark-FCurRec); end; procedure TdxDbOrgChart.ShowEditor; begin if Active and DataSet.CanModify then inherited ShowEditor; end; procedure TdxDbOrgChart.AssignFields; procedure AssignField(var Field: TField; const FName: String); begin if FName <> '' then Field := DataSet.FindField(FName); end; procedure ChkInt(var Field: TField); begin if not IsIntegerField(Field) then Field := nil; end; begin if FLink.Active then begin AssignField(FKeyField,FKeyFieldName); AssignField(FParentField,FParentFieldName); AssignField(FTextField,FTextFieldName); AssignField(FOrderField,FOrderFieldName); AssignField(FWidthField,FWidthFieldName); AssignField(FHeightField,FHeightFieldName); AssignField(FColorField,FColorFieldName); AssignField(FShapeField,FShapeFieldName); AssignField(FChAlignField,FChAlignFieldName); AssignField(FImIndexField,FImIndexFieldName); AssignField(FImAlignField,FImAlignFieldName); if (FOrderField <> nil) and (FOrderField.DataType <> ftFloat) then ChkInt(FOrderField); ChkInt(FWidthField); ChkInt(FHeightField); ChkInt(FColorField); ChkInt(FShapeField); ChkInt(FChAlignField); ChkInt(FImIndexField); ChkInt(FImAlignField); end; end; procedure TdxDbOrgChart.RefreshItems; var Bm: Integer; CurKey: Variant; begin if not Active then Exit; BeginRefresh; FEnableDB := False; DataSet.DisableControls; CurKey := KeyField.Value; FRecCount := -1; FCurRec := 0; FMaxKey := null; Bm := -DataSet.MoveBy(-99999999); while not DataSet.EOF do begin Inc(FRecCount); FCurRec := FRecCount; RefreshRecord; DataSet.Next; end; RefreshParents; EndRefresh; SetBookmark(Bm); DataSet.EnableControls; FEnableDB := True; if csDesigning in ComponentState then FullExpand; end; procedure TdxDbOrgChart.BeginRefresh; var I: Integer; begin for I := 0 to FKeyList.Count-1 do TdxDbOcNode(FKeyList[I]).FRefreshed := False; end; procedure TdxDbOrgChart.EndRefresh; var I: Integer; begin I := 0; while I < FKeyList.Count do begin if TdxDbOcNode(FKeyList[I]).FRefreshed then Inc(I) else begin Delete(TdxDbOcNode(FKeyList[I])); I := 0; end; end; end; procedure TdxDbOrgChart.RefreshRecord; function GetIntField(Field: TField; Default: Integer): Integer; begin if Field.IsNull then Result := Default else Result := Field.AsInteger; end; var Node,Par: TdxDbOcNode; ParKey: Variant; begin if KeyField.IsNull then Exit; if VarIsNull(FMaxKey) or VarGT(KeyField.Value,FMaxKey) then FMaxKey := KeyField.Value; ParKey := ParentField.Value; if VarEQ(ParKey,KeyField.Value) then ParKey := null; Node := GetNodeByKey(KeyField.Value); Par := GetNodeByKey(ParKey); if Node=nil then Node := CreateDBNode(KeyField.Value,Par); if Node=nil then Exit; if VarIsNull(Node.ParentKey) then Node.FParentKey := ParKey; if Node.Parent<>Par then MoveDBNode(Node,Par); with Node do begin if TextField<>nil then Text := TextField.AsString; if WidthField<>nil then Width := GetIntField(WidthField,0); if HeightField<>nil then Height := GetIntField(HeightField,0); if ColorField<>nil then Color := GetIntField(ColorField,clNone); if ShapeField<>nil then Shape := TdxOcShape(GetIntField(ShapeField,Ord(shRectangle))); if ChAlignField<>nil then ChildAlign := TdxOcNodeAlign(GetIntField(ChAlignField,Ord(caCenter))); if ImAlignField<>nil then ImageAlign := TdxOcImageAlign(GetIntField(ImAlignField,Ord(iaNone))); if ImageField<>nil then ImageIndex := GetIntField(ImageField,-1); if Assigned(OnLoadNode) then OnLoadNode(Self,Node); FRecNum := FCurRec; FRefreshed := True; end; end; procedure TdxDbOrgChart.RefreshParents; var Node,Par: TdxDbOcNode; I: Integer; begin for I := 0 to FKeyList.Count-1 do begin Node := TdxDbOcNode(FKeyList[I]); if Node.FRefreshed and (Node.Parent = nil) then begin Par := GetNodeByKey(Node.ParentKey); if (Par=nil) and not VarIsNull(Node.ParentKey) then begin if not Node.IsParentRoot then Node.FRefreshed := False end else MoveDBNode(Node, Par); end; end; end; function TdxDbOrgChart.FindNearest(AKey: Variant; var AIndex: Integer): Boolean; var CKey: Variant; Min,Max: Integer; begin Result := False; Min := 0; Max := FKeyList.Count; while true do begin AIndex := (Min + Max) shr 1; if Min=Max then Exit; CKey := TdxDbOcNode(FKeyList[AIndex]).Key; if VarEQ(AKey,CKey) then begin Result := True; Exit; end; if VarGT(AKey,CKey) then Min := AIndex+1 else Max := AIndex; end; end; function TdxDbOrgChart.GetNodeByKey(AKey: Variant): TdxDbOcNode; var I: Integer; begin if FindNearest(AKey,I) then Result := TdxDbOcNode(FKeyList[I]) else Result := nil; end; function TdxDbOrgChart.FindIndex(AKey: Variant; AParent: TdxDbOcNode): Integer; var Node: TdxDbOcNode; begin // if AParent=nil then Result := RootNode.Count else Result := AParent.Count; // if not KeyOrder and (OrderField=nil) then Exit; Result := 0; if AParent=nil then Node := TdxDbOcNode(GetFirstNode) else Node := TdxDbOcNode(AParent.GetFirstChild); while Node<>nil do begin if not VarGT(AKey,Node.FOrder) then Exit; Inc(Result); Node := TdxDbOcNode(Node.GetNextSibling); end; end; function TdxDbOrgChart.CreateDBNode(AKey: Variant; AParent: TdxDbOcNode): TdxDbOcNode; var Order: Variant; begin if OrderField=nil then Order := AKey else Order := OrderField.Value; if VarIsNull(Order) then Order := 0; Result := TdxDbOcNode(InternalAdd(AParent,nil,FindIndex(Order,AParent))); if Result<>nil then begin Result.FKey := AKey; Result.FRecNum := FCurRec; Result.FOrder := Order; if AParent<>nil then Result.FParentKey := AParent.Key; AddToKeyList(Result); end; end; procedure TdxDbOrgChart.MoveDBNode(ANode,AParent: TdxDbOcNode); begin if (AParent=ANode) or (AParent<>nil) and AParent.HasAsParent(ANode) then Exit; InternalMoveTo(AParent,ANode,FindIndex(ANode.FOrder,AParent)); end; procedure TdxDbOrgChart.AddToKeyList(ANode: TdxDbOcNode); var I: Integer; begin FindNearest(ANode.Key,I); FKeyList.Insert(I,ANode); end; procedure TdxDbOrgChart.DelFromKeyList(ANode: TdxDbOcNode); var I: Integer; begin if FindNearest(ANode.Key,I) then FKeyList.Delete(I); end; procedure TdxDbOrgChart.SetParentNode(ANode: TdxDbOcNode); begin if VarIsNull(ANode.ParentKey) and ParentField.Required then ParentField.Value := ANode.Key else ParentField.Value := ANode.ParentKey; end; function TdxDbOrgChart.InternalAdd(AParent:TdxOcNode; Data: TdxOcNodeData; Idx:Integer): TdxOcNode; var Node: TdxDbOcNode; Bm: Integer; begin Result := nil; if not Active or FEnableDB and not DataSet.CanModify then Exit; Result := inherited InternalAdd(AParent, Data, Idx); if FEnableDB and (Result<>nil) then begin Bm := FCurRec; FEnableDB := False; Node := TdxDbOcNode(Result); {$IFDEF DELPHI3}if not (KeyField is TAutoIncField) then Node.FKey := NewKey;{$ENDIF} if AParent<>nil then Node.FParentKey := TdxDbOcNode(AParent).Key; if Node.Index=0 then Node.FOrder := 0 else Node.FOrder := TdxDbOcNode(Node.GetPrevSibling).FOrder+1; try DataSet.Append; Inc(FRecCount); FCurRec := FRecCount; Node.FRecNum := FCurRec; {$IFDEF DELPHI3}if not (KeyField is TAutoIncField) then KeyField.Value := Node.Key;{$ENDIF} SetParentNode(Node); if OrderField<>nil then OrderField.Value := Node.FOrder; DataSet.Post; {$IFDEF DELPHI3}if KeyField is TAutoIncField then Node.FKey := KeyField.Value;{$ENDIF} if OrderField=nil then Node.FOrder := Node.FKey; CheckRec(Node); AddToKeyList(Node); CheckKeys(Node); finally SetBookmark(Bm); FEnableDB := True; end; end; end; procedure TdxDbOrgChart.InternalMoveTo(AParent,ANode: TdxOcNode; Idx: Integer); var Node: TdxDbOcNode; Bm: Integer; begin if FEnableDB and not DataSet.CanModify then Exit; inherited InternalMoveTo(AParent,ANode,Idx); Node := TdxDbOcNode(ANode); if Node.Parent=nil then Node.FParentKey := null else Node.FParentKey := TdxDbOcNode(Node.Parent).Key; if FEnableDB then begin Bm := FCurRec; FEnableDB := False; try if LocateToNode(Node) then begin DataSet.Edit; SetParentNode(Node); DataSet.Post; CheckRec(Node); end; if Node.Index=0 then CheckKeys(Node) else CheckKeys(TdxDbOcNode(Node.GetPrevSibling)); finally SetBookmark(Bm); FEnableDB := True; end; end; end; function TdxDbOrgChart.LocateToNode(ANode: TdxDbOcNode): Boolean; begin SetBookmark(ANode.FRecNum); Result := (FCurRec=ANode.FRecNum) and VarEQ(ANode.Key,KeyField.Value); if not Result then Result := DataSet.Locate(KeyFieldName, ANode.Key, []); end; procedure TdxDbOrgChart.CheckKeys(ANode: TdxDbOcNode); var Node: TdxDbOcNode; I: Integer; Loc: Boolean; begin if not KeyOrder and (OrderField=nil) then Exit; Node := TdxDbOcNode(ANode.GetNextSibling); if Node=nil then Exit; if VarGE(ANode.FOrder,Node.FOrder) then begin Loc := LocateToNode(Node); if OrderField<>nil then Node.FOrder := ANode.Forder+1 else begin Node.FKey := NewKey; Node.FOrder := Node.Key; end; if Loc then begin DataSet.Edit; if OrderField=nil then KeyField.Value := Node.Key else OrderField.Value := Node.FOrder; DataSet.Post; CheckRec(Node); end; if OrderField=nil then begin FKeyList.Remove(Node); FKeyList.Insert(FKeyList.Count,Node); for I := 0 to Node.Count-1 do begin TdxDbOcNode(Node[I]).FParentKey := Node.Key; if LocateToNode(TdxDbOcNode(Node[I])) then begin DataSet.Edit; ParentField.Value := Node.Key; DataSet.Post; CheckRec(Node); end; end; end; end; CheckKeys(Node); end; procedure TdxDbOrgChart.CheckRec(ANode: TdxDbOcNode); var Node: TdxDbOcNode; I,OldNum,NewNum: Integer; begin OldNum := ANode.FRecNum; NewNum := DataSet.RecNo-1; FCurRec := NewNum; if NewNum < 0 then begin NewNum := -DataSet.MoveBy(-99999999); FCurRec := 0; end; if OldNum=NewNum then Exit; for I := 0 to FKeyList.Count-1 do begin Node := TdxDbOcNode(FKeyList[I]); if Node.FRecNum > OldNum then Dec(Node.FRecNum); if Node.FRecNum >= NewNum then Inc(Node.FRecNum); end; ANode.FRecNum := NewNum; end; function TdxDbOrgChart.NewKey: Variant; begin Result := null; if Assigned(OnNewKey) then begin OnNewKey(Self,FMaxKey,Result); if not VarGT(Result,FMaxKey) then Result := null; end; if VarIsNull(Result) and IsIntegerField(KeyField) then if VarIsNull(FMaxKey) then Result := 0 else Result := FMaxKey+1; if not VarIsNull(Result) then FMaxKey := Result else raise EVariantError.Create('Cannot create new key.'); end; procedure TdxDbOrgChart.Delete(ANode: TdxOcNode); var Node: TdxDbOcNode; Bm: Integer; begin if ANode=nil then Exit; if FEnableDB and Active then begin if not DataSet.CanModify then Exit; FEnableDB := False; Bm := FCurRec; try if LocateToNode(TdxDbOcNode(ANode)) then begin DataSet.Delete; Dec(FRecCount); if FCurRec > FRecCount then FCurRec := FRecCount; if Bm > FCurRec then Dec(Bm); Node := TdxDbOcNode(GetFirstNode); while Node<>nil do begin if Node.FRecNum > FCurRec then Dec(Node.FRecNum); if (Node=ANode.Parent) and Node.Deleting then Node := TdxDbOcNode(ANode); Node := TdxDbOcNode(Node.GetNext); end; end; finally SetBookmark(Bm); FEnableDB := True; end; end; if FKeyList<>nil then DelFromKeyList(TdxDbOcNode(ANode)); inherited Delete(ANode); end; procedure TdxDbOrgChart.Scroll(Dist: Integer); var Sel: TdxDbOcNode; begin if FEnableDB and (KeyField<>nil) then begin FEnableDB := False; FCurRec := FCurRec + Dist; Sel := GetNodeByKey(KeyField.Value); if (Sel <> nil) and not VarEQ(KeyField.Value, Sel.Key) then Sel := nil; Selected := Sel; if Sel <> nil then Sel.MakeVisible; FEnableDB := True; end; end; procedure TdxDbOrgChart.RecordChanged(Field: TField); begin if FEnableDB and (Selected<>nil) and (Field<>nil) and (DataSet.State=dsEdit) then begin FEnableDB := False; if Field = TextField then Selected.Text := TextField.AsString; if Field = ImageField then Selected.ImageIndex := ImageField.AsInteger; FEnableDB := True; end; end; procedure TdxDbOrgChart.NodeChanged(ANode: TdxOcNode); var Bm: Integer; Info: TdxOcNodeInfo; begin if FEnableDB and DataSet.CanModify then begin FEnableDB := False; Bm := FCurRec; try if LocateToNode(TdxDbOcNode(ANode)) then begin ANode.GetNodeInfo(Info); DataSet.Edit; if TextField<>nil then TextField.AsString := ANode.Text; if WidthField<>nil then WidthField.AsInteger := Info.Width; if HeightField<>nil then HeightField.AsInteger := Info.Height; if ColorField<>nil then ColorField.AsInteger := Info.Color; if ShapeField<>nil then ShapeField.AsInteger := Ord(Info.Shape); if ChAlignField<>nil then ChAlignField.AsInteger := Ord(Info.Align); if ImAlignField<>nil then ImAlignField.AsInteger := Ord(Info.IAlign); if ImageField<>nil then ImageField.AsInteger := Info.Index; DataSet.Post; CheckRec(TdxDbOcNode(ANode)); end; finally SetBookmark(Bm); FEnableDB := True; end; end; end; procedure TdxDbOrgChart.ActiveChanged; begin FKeyField := nil; FParentField := nil; FTextField := nil; FWidthField := nil; FHeightField := nil; FColorField := nil; FShapeField := nil; FChAlignField := nil; FImIndexField := nil; FImAlignField := nil; FEnableDB := False; Clear; FEnableDB := True; if DataSet<>nil then begin FLink.FFiltered := DataSet.Filtered; FLink.FFilter := DataSet.Filter; end; AssignFields; if Active then DataChanged; end; procedure TdxDbOrgChart.DataChanged; begin if not FEnableDB or (DataSet.State in [dsEdit,dsInsert]) then Exit; RefreshItems; Scroll(0); end; procedure TdxDbOrgChart.DoChange(Node: TdxOcNode); begin if FEnableDB and (Node<>nil) then begin FEnableDB := False; try LocateToNode(TdxDbOcNode(Node)); except end; FEnableDB := True; end; inherited DoChange(Node); end; procedure TdxDbOrgChart.DoChanging(Node: TdxOcNode; var Allow: Boolean); var Bm: Integer; begin inherited DoChanging(Node,Allow); if Allow and FEnableDB and (Node<>nil) then begin Bm := FCurRec; FEnableDB := False; try Allow := LocateToNode(TdxDbOcNode(Node)); except Allow := False; end; if not Allow then SetBookmark(Bm); FEnableDB := True; end; end; procedure TdxDbOrgChart.SetDataSource(Value: TDataSource); begin FLink.DataSource := Value; end; procedure TdxDbOrgChart.SetKeyFieldName(const Value: String); begin if FKeyFieldName <> Value then begin FKeyFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetParentFieldName(const Value: String); begin if FParentFieldName <> Value then begin FParentFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetTextFieldName(const Value: String); begin if FTextFieldName <> Value then begin FTextFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetOrderFieldName(const Value: String); begin if FOrderFieldName <> Value then begin FOrderFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetWidthFieldName(const Value: String); begin if FWidthFieldName <> Value then begin FWidthFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetHeightFieldName(const Value: String); begin if FHeightFieldName <> Value then begin FHeightFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetColorFieldName(const Value: String); begin if FColorFieldName <> Value then begin FColorFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetShapeFieldName(const Value: String); begin if FShapeFieldName <> Value then begin FShapeFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetChAlignFieldName(const Value: String); begin if FChAlignFieldName <> Value then begin FChAlignFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetImIndexFieldName(const Value: String); begin if FImIndexFieldName <> Value then begin FImIndexFieldName := Value; ActiveChanged; end; end; procedure TdxDbOrgChart.SetImAlignFieldName(const Value: String); begin if FImAlignFieldName <> Value then begin FImAlignFieldName := Value; ActiveChanged; end; end; function TdxDbOrgChart.CreateNode: TdxOcNode; begin Result := TdxDbOcNode.Create(Self); with TdxDbOcNode(Result) do begin FKey := null; FParentKey := null; end; end; function TdxDbOrgChart.CreateEditor: TdxOcInplaceEdit; begin Result := inherited CreateEditor; if TextField<>nil then Result.MaxLength := TextField.Size; end; end.