{******************************************************************************}
{          原始文件名:CnClasses.pas                                           }
{            单元作者:周劲羽(与月共舞)                                      }
{                      [email protected]; http://yygw.126.com                       }
{            下载地址:http://cnpack.yeah.net                                  }
{            电子邮件:[email protected]                                          }
{                备注:该单元定义了开发包用到的公共基础类                      }
{            最后更新:2002.04.08 V1.0                                         }
{                                                                              }
{******************************************************************************}

unit CnClasses;
interface

{$I CnPack.inc}

uses
  Windows, SysUtils, Classes;

type

//----------------------------------------------------------------------------//
// 带更新通知的持久性类                                                       //
//----------------------------------------------------------------------------//

{ TCnPersistent }

  TCnPersistent = class(TPersistent)
  {* 带更新通知的持久性类}
  private
    FUpdateCount: Integer;
    FOnChanging: TNotifyEvent;
    FOnChange: TNotifyEvent;
    FOwner: TPersistent;
  protected
    function GetOwner: TPersistent; override;
    function IsUpdating: Boolean;
    {* 当前更新计数是否大于0(正在更新),只读属性}
    procedure OnChildChanging(Sender: TObject); virtual;
    {* 子属性开始更新事件处理过程,可做为参数传递给TCnPersistent.Create过程
     |<BR> 默认为产生OnChanging事件,可重载}
    procedure OnChildChange(Sender: TObject); virtual;
    {* 子属性已变更事件处理过程,可做为参数传递给TCnPersistent.Create过程
     |<BR> 默认为产生OnChange事件,可重载}
    procedure Changing; virtual;
    {* 对象内容开始更新,如果更新计数为0,产生OnChanging事件,可重载}
    procedure Changed; virtual;
    {* 对象内容已变更,如果更新计数为0,产生OnChange事件,可重载}
    property Owner: TPersistent read FOwner write FOwner;
  public
    constructor Create; overload; virtual;
    {* 构造器,用于产生一个该类的实例,可重载}
    constructor Create(ChangeProc: TNotifyEvent); overload;
    {* 构造器,参数用于给OnChange事件指定一个初始值}
    constructor Create(ChangingProc, ChangeProc: TNotifyEvent); overload;
    {* 构造器,参数用于给OnChanging和OnChange事件指定一个初始值}
    procedure BeginUpdate; virtual;
    {* 开始更新,如果当前更新计数为0,自动调用Changing方法,可重载
     |<BR> 在对成批属性进行修改时请调用该方法,注意必须与EndUpdate成对使用}
    procedure EndUpdate; virtual;
    {* 结束更新,如果当前更新计数为0,自动调用Change方法,可重载
     |<BR> 在对成批属性修改后请调用该方法,注意必须与BeginUpdate成对使用}
  published
    property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
    {* 对象开始更新事件}
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    {* 对象属性已变更事件}
  end;

//----------------------------------------------------------------------------//
// 线程安全的更新通知持久性类                                                 //
//----------------------------------------------------------------------------//

{ TCnThreadPersistent }

  TCnThreadPersistent = class(TCnPersistent)
  {* 线程安全的更新通知持久性类}
  private
    FLock: TRTLCriticalSection;
    FLockCount: Integer;
  protected
    property LockCount: Integer read FLockCount;
    {* 当前Lock计数,只读属性}
  public
    constructor Create; override;
    {* 构造器,用于产生一个该类的实例}
    destructor Destroy; override;
    procedure Lock;
    {* 进入临界区,为保证多线程同步而加锁,必须与Unlock成对使用}
    function TryLock: Boolean;
    {* 如果当前Lock计数为零,则加锁返回真,否则返回假
     |<BR> 如果返回真,必须在操作完成后调用UnLock释放锁}
    procedure Unlock;
    {* 退出临界区,释放同步锁,必须与Lock成对使用}
  end;

//----------------------------------------------------------------------------//
// 带Enabled的更新通知持久性类                                                //
//----------------------------------------------------------------------------//

{ TCnEnabledPersistent }

  TCnEnabledPersistent = class(TCnPersistent)
  {* 带Enabled的更新通知持久性类}
  private
    FEnabled: Boolean;
  protected
    procedure SetEnabled(const Value: Boolean); virtual;
    procedure Changed; override;
  public
    constructor Create; override;
    {* 构造器,用于产生一个该类的实例}
    procedure Assign(Source: TPersistent); override;
  published
    property Enabled: Boolean read FEnabled write SetEnabled default False;
    {* Enabled属性,如果为假,对Changed方法的调用将不产生OnChanging事件}
  end;

//----------------------------------------------------------------------------//
// 不可视组件基础类                                                           //
//----------------------------------------------------------------------------//

{ TCnComponent }

  TCnCopyRight = type string;

  TCnComponent = class(TComponent)
  {* CnPack不可视组件基类}
  private
    FAbout: TCnCopyRight;
  protected
    function GetAuthor: string; virtual;
    {* 取组件作者函数,返回组件作者信息,可重载}
    function GetComment: string; virtual;
    {* 取组件注释函数,返回组件注释,可重载}
  public
    constructor Create(AOwner: TComponent); override;
  published
    property About: TCnCopyRight read FAbout;
    {* 组件版本属性,仅在设计期使用}
  end;

implementation

uses
  CnConsts;

var
  CounterLock: TRTLCriticalSection;

//----------------------------------------------------------------------------//
// 带更新通知的持久性类                                                       //
//----------------------------------------------------------------------------//

{ TCnPersistent }

// 初始化(供重载)

constructor TCnPersistent.Create;
begin
  inherited;
  FUpdateCount := 0;
end;

// 初始化,参数为更新通知事件

constructor TCnPersistent.Create(ChangeProc: TNotifyEvent);
begin
  Create;
  FOnChange := ChangeProc;
end;

// 初始化,参数为更新通知事件

constructor TCnPersistent.Create(ChangingProc, ChangeProc: TNotifyEvent);
begin
  Create;
  FOnChanging := ChangingProc;
  FOnChange := ChangeProc;
end;

// 开始更新

procedure TCnPersistent.BeginUpdate;
begin
  if not IsUpdating then Changing; // 开始更新
  Inc(FUpdateCount);
end;

// 正在变更

procedure TCnPersistent.Changing;
begin
  if not IsUpdating and Assigned(FOnChanging) then FOnChanging(Self);
end;

// 变更结束

procedure TCnPersistent.Changed;
begin
  if not IsUpdating and Assigned(FOnChange) then FOnChange(Self);
end;

// 结束更新

procedure TCnPersistent.EndUpdate;
begin // Assert不需要本地化
  Assert(FUpdateCount > 0, 'Unpaired TCnPersistent.EndUpdate');
  Dec(FUpdateCount);
  if not IsUpdating then Changed;
end;

// 取所有者

function TCnPersistent.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

// 子单位变更

procedure TCnPersistent.OnChildChanging(Sender: TObject);
begin
  if not IsUpdating and Assigned(FOnChanging) then FOnChanging(Sender);
end;

// 子单位已变更

procedure TCnPersistent.OnChildChange(Sender: TObject);
begin
  if not IsUpdating and Assigned(FOnChange) then FOnChange(Sender);
end;

// 正在更新

function TCnPersistent.IsUpdating: Boolean;
begin
  Result := FUpdateCount > 0;
end;

//----------------------------------------------------------------------------//
// 线程安全的更新通知持久性类                                                 //
//----------------------------------------------------------------------------//

{ TCnThreadPersistent }

// 初始化

constructor TCnThreadPersistent.Create;
begin
  inherited;
  InitializeCriticalSection(FLock); // 初始化临界区
end;

// 释放

destructor TCnThreadPersistent.Destroy;
begin
  DeleteCriticalSection(FLock);
  inherited;
end;

// 尝试进入临界区(如果已加锁返回 False)

function TCnThreadPersistent.TryLock: Boolean;
begin
  EnterCriticalSection(CounterLock);
  try
    Result := FLockCount = 0;
    if Result then Lock;
  finally
    LeaveCriticalSection(CounterLock);
  end;
end;

// 加锁

procedure TCnThreadPersistent.Lock;
begin
  EnterCriticalSection(CounterLock);
  Inc(FLockCount);
  LeaveCriticalSection(CounterLock);
  EnterCriticalSection(FLock);
end;

// 释放锁

procedure TCnThreadPersistent.Unlock;
begin
  LeaveCriticalSection(FLock);
  EnterCriticalSection(CounterLock);
  Dec(FLockCount);
  LeaveCriticalSection(CounterLock);
end;

//----------------------------------------------------------------------------//
// 带Enabled的更新通知持久性类                                                //
//----------------------------------------------------------------------------//

{ TCnEnabledPersistent }

//赋值

procedure TCnEnabledPersistent.Assign(Source: TPersistent);
begin
  if Source is TCnEnabledPersistent then
    FEnabled := TCnEnabledPersistent(Source).FEnabled
  else
    inherited Assign(Source);
end;

//更新通知

procedure TCnEnabledPersistent.Changed;
begin
  if FEnabled then //如果能用则通知
    inherited Changed;
end;

//创建

constructor TCnEnabledPersistent.Create;
begin
  inherited Create;
  FEnabled := False;
end;

//设置参数

procedure TCnEnabledPersistent.SetEnabled(const Value: Boolean);
begin
  if FEnabled <> Value then
  begin
    FEnabled := True; // 允许通知
    Changed;
    FEnabled := Value;
  end;
end;

//----------------------------------------------------------------------------//
// 不可视组件基础类                                                           //
//----------------------------------------------------------------------------//

{ TCnComponent }

// 初始化

constructor TCnComponent.Create(AOwner: TComponent);
begin
  inherited;
  FAbout := SCnPackAbout;
end;

// 返回组件作者

function TCnComponent.GetAuthor: string;
begin
  Result := SCnPackGroup;
end;

// 返回组件注释

function TCnComponent.GetComment: string;
begin
  Result := SCnPackUrl;
end;

initialization
  InitializeCriticalSection(CounterLock);

finalization
  DeleteCriticalSection(CounterLock);

end.