⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ulogobserver.pas

📁 FMA is a free1 powerful phone editing tool allowing users to easily manage all of the personal data
💻 PAS
字号:
unit uLogObserver;

{
*******************************************************************************
* Descriptions: Log Observer Component
* $Source: /cvsroot/fma/fma/uLogObserver.pas,v $
* $Locker:  $
*
* Todo:
*
* Change Log:
* $Log: uLogObserver.pas,v $
*
}

interface

uses
  Classes, Messages, uLogger;

type
  TLogBasicObserver = class(TComponent, ILogObserver)
  private
    FHandle: THandle;
    FLog: ILog;
    FMessageID: Cardinal;
    FOnLogChanged: TNotifyEvent;
    FSynchronized: Boolean;
    procedure ClearMessageQueue;
    procedure WndMethod(var Message: TMessage);
    procedure EnableSynchronization;
    procedure DisableSynchronization;
    procedure SetSynchronized(const Value: Boolean);
  protected
    procedure LogChanged;

    procedure DoLogChanged; virtual;
    procedure SetLog(const Value: ILog); virtual;
    procedure SetLogInternal(const Value: ILog);

    procedure Reset; virtual;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Log: ILog read FLog write SetLog;

    property Synchronized: Boolean read FSynchronized write SetSynchronized default True;
    property OnLogChanged: TNotifyEvent read FOnLogChanged write FOnLogChanged;
  end;

  TLogItemAddedEvent = procedure(Sender: TObject; const LogItem: ILogItem) of object;

  TLogObserver = class(TLogBasicObserver)
  private
    FLogEnumeration: ILogEnumeration;
    FOnLogItemAdded: TLogItemAddedEvent;
    FOnLogCleared: TNotifyEvent;
    FLastLogItem: ILogItem;
    FOnLogChanging: TNotifyEvent;
    procedure SetLogEnumeration(const Value: ILogEnumeration);
  protected
    procedure SetLog(const Value: ILog); override;

    procedure DoLogChanging; virtual;
    procedure DoLogChanged; override;
    procedure DoLogCleared; virtual;
    procedure DoLogItemAdded(const LogItem: ILogItem); virtual;

    procedure Reset; override;
  published
    property LogEnumeration: ILogEnumeration read FLogEnumeration write SetLogEnumeration;

    property OnLogChanging: TNotifyEvent read FOnLogChanging write FOnLogChanging;
    property OnLogCleared: TNotifyEvent read FOnLogCleared write FOnLogCleared;
    property OnLogItemAdded: TLogItemAddedEvent read FOnLogItemAdded write FOnLogItemAdded;
  end;

implementation

uses
  Windows;

{ TLogBasicObserver }

procedure TLogBasicObserver.ClearMessageQueue;
var Msg: TMsg;
begin
  while PeekMessage(Msg, FHandle, FMessageID, FMessageID, PM_REMOVE) do ;
end;

constructor TLogBasicObserver.Create(AOwner: TComponent);
begin
  inherited;

  EnableSynchronization;
end;

destructor TLogBasicObserver.Destroy;
begin
  Log := nil;

  if FSynchronized then
    DisableSynchronization;

  inherited;
end;

procedure TLogBasicObserver.DisableSynchronization;
begin
  if FSynchronized then begin
    FSynchronized := False;

    if FHandle <> 0 then begin
      Classes.DeallocateHWnd(FHandle);
      FHandle := 0;
    end;

    FMessageID := 0;
  end;
end;

procedure TLogBasicObserver.DoLogChanged;
begin
  if Assigned(FOnLogChanged) then
    FOnLogChanged(Self);
end;

procedure TLogBasicObserver.EnableSynchronization;
begin
  if not FSynchronized then begin
    FSynchronized := True;

    if not (csDesigning in ComponentState) then begin
      FHandle := Classes.AllocateHWnd(WndMethod);
      FMessageID := RegisterWindowMessage(PChar(String(ClassName)));
    end;
  end;
end;

procedure TLogBasicObserver.LogChanged;
begin
  if FSynchronized then
    PostMessage(FHandle, FMessageID, 0, 0)
  else
    DoLogChanged;
end;

procedure TLogBasicObserver.Reset;
begin
end;

procedure TLogBasicObserver.SetLog(const Value: ILog);
begin
  SetLogInternal(Value);
end;

procedure TLogBasicObserver.SetLogInternal(const Value: ILog);
begin
  if FLog <> Value then begin
    if Assigned(FLog) then FLog.UnregisterObserver(Self);

    FLog := Value;

    if Assigned(FLog) then FLog.RegisterObserver(Self);

    if not (csDestroying in ComponentState) then begin
      Reset;

      LogChanged;
    end;
  end;
end;

procedure TLogBasicObserver.SetSynchronized(const Value: Boolean);
begin
  if Value <> FSynchronized then begin
    if Value then
      EnableSynchronization
    else
      DisableSynchronization;
  end;
end;

procedure TLogBasicObserver.WndMethod(var Message: TMessage);
begin
  if Message.Msg = FMessageID then begin
    ClearMessageQueue;

    DoLogChanged;
  end;
end;

procedure TLogObserver.DoLogChanged;
var
  LogItem: ILogItem;
  ItemAdded: Boolean;
begin
  ItemAdded := False;
  try
    if Assigned(FLogEnumeration) then begin
      if Assigned(FLastLogItem) then begin
        if not FLogEnumeration.Contains(FLastLogItem) then begin // It must have been Cleared
          ItemAdded := True;
          DoLogChanging;
          Reset;
          DoLogCleared;
          LogItem := FLogEnumeration.First;
        end
        else
          LogItem := FLogEnumeration.Next(FLastLogItem);
      end
      else
        LogItem := FLogEnumeration.First;

      while Assigned(LogItem) do begin
        if FLogEnumeration.Contains(LogItem) then begin
          if not ItemAdded then begin
            ItemAdded := True;
            DoLogChanging;
          end;
          DoLogItemAdded(LogItem);
        end;

        FLastLogItem := LogItem;
        LogItem := FLogEnumeration.Next(LogItem);
      end;
    end;
  finally
    if ItemAdded then
      inherited DoLogChanged;
  end;
end;

procedure TLogObserver.DoLogChanging;
begin
  if Assigned(FOnLogChanging) then
    FOnLogChanging(Self);
end;

procedure TLogObserver.DoLogCleared;
begin
  if Assigned(FOnLogCleared) then
    FOnLogCleared(Self);
end;

procedure TLogObserver.DoLogItemAdded(const LogItem: ILogItem);
begin
  if Assigned(FOnLogItemAdded) then
    FOnLogItemAdded(Self, LogItem);
end;

procedure TLogObserver.Reset;
begin
  inherited;

  FLastLogItem := nil;
end;

procedure TLogObserver.SetLog(const Value: ILog);
begin
  if Assigned(Value) then
    FLogEnumeration := Value.GetEnumeration
  else
    FLogEnumeration := nil;

  inherited;
end;

procedure TLogObserver.SetLogEnumeration(const Value: ILogEnumeration);
begin
  FLogEnumeration := Value;

  if Assigned(FLogEnumeration) then
    SetLogInternal(FLogEnumeration.Log)
  else
    SetLogInternal(nil);

  if not (csDestroying in ComponentState) then begin
    Reset;

    LogChanged;
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -