afilter.pas

来自「delphi编程控件」· PAS 代码 · 共 921 行 · 第 1/2 页

PAS
921
字号
unit afilter;
(*
 COPYRIGHT (c) RSD software 1997 - 98
 All Rights Reserved.
*)

interface

{$I aclver.inc}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DB, DBTables;

type
  TMacros = class;

  TMacroOption = (moSQL, moFilter);
  TMacroOptions  = set of TMacroOption;
  TMacrosFreeze = (mfAlways, mfDesigning, mfNever);

  TMacro = class(TObject)
  private
    FMacroList : TMacros;
    FName : String;
    FText: String;
  public
    MacroOptions : TMacroOptions;
    property Name: string read FName write FName;
    property Text : String read FText write FText;

    constructor Create(AMacroList: TMacros);
    destructor Destroy; override;

    procedure Assign(Macro: TMacro);
  end;

  TMacros = class(TPersistent)
  private
    FItems: TList;
    function GetMacro(Index: Word): TMacro;
    function GetMacroText(const MacroName: string): String;
    procedure SetMacroText(const MacroName: string; const Text: String);

    procedure ReadBinaryData(Stream: TStream);
    procedure WriteBinaryData(Stream: TStream);
  protected
    procedure AssignTo(Dest: TPersistent); override;
    procedure DefineProperties(Filer: TFiler); override;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure AssignValues(Value: TMacros);
    procedure AddMacro(Value: TMacro);
    procedure RemoveMacro(Value: TMacro);
    function CreateMacro(const MacroName: string): TMacro;
    function Count: Integer;
    procedure Clear;
    function MacroByName(const Value: string): TMacro;
    property Items[Index: Word]: TMacro read GetMacro; default;
    property MacroText[const MacroName: string]: String read GetMacroText write SetMacroText;
  end;

  TAutoFilter = class;
  TFilterLink = class;

  EFilterLinkInvalidParam = class(Exception);

  TAutoComponentsRegister = class
  private
    List : TList;
    ComponentList : TList;
    FilterLinkList : TList;

    function GetAutoFilter(Index : Integer) : TAutoFilter;
    function GetFilterLink(Index : Integer) : TFilterLink;
    function GetComponent(Index : Integer) : TComponent;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Add(AutoFilter : TAutoFilter);
    procedure AddFilterLink(FilterLink : TFilterLink);
    procedure Remove(AutoFilter : TAutoFilter);
    procedure RemoveFilterLink(FilterLink : TFilterLink);
    procedure GetAutoFilters(FList : TList; Component : TComponent);
    function Count : Integer;
    function ComponentCount : Integer;
    function FilterLinkCount : Integer;
    function ComponentIndexOf(Component : TComponent) : Integer;
    property Items[Index: Integer]: TAutoFilter read GetAutoFilter;  default;
    property FilterLinkItems[Index: Integer]: TFilterLink read GetFilterLink;
    property ComponentItems[Index: Integer]: TComponent read GetComponent;
  end;

  TAutoFilter = class(TPersistent)
  private
    FFilterLink : TList;
    FValue : String;
    FTextBefore : String;
    FTextAfter : String;
    FAssignEmpty : Boolean;

    function GetText : String;
    procedure SetTextBefore(Value : String);
    procedure SetTextAfter(Value : String);
    procedure SetValue(Value : String);
    procedure RefreshDataSets;
  public
    Owner : TComponent;
    OnBeforeChange: TNotifyEvent;
    OnAfterChange: TNotifyEvent;
    Name : String; 

    constructor Create(AOwner : TComponent);
    destructor Destroy; override;
    procedure Assign(Source : TPersistent); override;

    property Value : String read FValue write SetValue;
    property Text : String read GetText;
  published
    property AssignEmpty : Boolean read FAssignEmpty write FAssignEmpty;
    property TextBefore : String read FTextBefore write SetTextBefore;
    property TextAfter : String read FTextAfter write SetTextAfter;
  end;

  TFilterLink = class(TComponent)
  private
    FAutoRefresh : Boolean;
    FComponent : TComponent;
    FDataSet : TDataSet;
    FFilterName : String;
    FLoadFilterName : String;
    FMacro : String;
    FParam : String;
    List : TList;

    procedure SetDataSet(Value : TDataSet);
    procedure SetFilter(Value : TComponent);
    procedure SetFilterName(Value : String);
    procedure SetMacro(Value : String);
    procedure SetParam(Value : String);
  public
    AutoFilter : TAutoFilter;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Loaded; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;

    function GetFilterComponent : TComponent;
    procedure RefreshDataSet;
  published
    property AutoRefresh : Boolean read FAutoRefresh write FAutoRefresh;  
    property DataSet : TDataSet read FDataSet write SetDataSet;
    property Filter : TComponent read FComponent write SetFilter;
    property FilterName : String read FFilterName write SetFilterName;
    property Macro : String read FMacro write SetMacro;
    property Param : String read FParam write SetParam;
  end;

Var
  AutoComponentsRegister : TAutoComponentsRegister;

function GetMacroText(DataSet : TDataSet; const MacroName : String) : String;  
procedure CreateMacros(List: TMacros; const Value: PChar; MacroOptions : TMacroOptions);

implementation

uses TypInfo, aclconst;

function GetMacroText(DataSet : TDataSet; const MacroName : String) : String;
Var
  i : Integer;
begin
  Result := '';
  if(AutoComponentsRegister = Nil) then exit;
  for i := 0 to AutoComponentsRegister.FilterLinkCount - 1 do
    if(AutoComponentsRegister.FilterLinkItems[i].DataSet = DataSet)
    And (CompareText(AutoComponentsRegister.FilterLinkItems[i].Macro, MacroName) = 0) then begin
      if(AutoComponentsRegister.FilterLinkItems[i].AutoFilter <> Nil) then
        Result := AutoComponentsRegister.FilterLinkItems[i].AutoFilter.Text;
      break;
    end;
end;

procedure CreateMacros(List: TMacros; const Value: PChar;MacroOptions : TMacroOptions);
var
  CurPos, StartPos: PChar;
  CurChar: Char;
  Literal: Boolean;
  EmbeddedLiteral: Boolean;
  Name: string;

  function NameDelimiter: Boolean;
  begin
    Result := CurChar in [' ', ',', ';', ')', #13, #10];
  end;

  function IsLiteral: Boolean;
  begin
    Result := CurChar in ['''', '"'];
  end;

  function StripLiterals(Buffer: PChar): string;
  var
    Len: Word;
    TempBuf: PChar;

    procedure StripChar(Value: Char);
    begin
      if TempBuf^ = Value then
        StrMove(TempBuf, TempBuf + 1, Len - 1);
      if TempBuf[StrLen(TempBuf) - 1] = Value then
        TempBuf[StrLen(TempBuf) - 1] := #0;
    end;

  begin
    Len := StrLen(Buffer) + 1;
    TempBuf := AllocMem(Len);
    Result := '';
    try
      StrCopy(TempBuf, Buffer);
      StripChar('''');
      StripChar('"');
      Result := StrPas(TempBuf);
    finally
      FreeMem(TempBuf, Len);
    end;
  end;

Var
 Macro : TMacro;
begin
  CurPos := Value;
  Literal := False;
  EmbeddedLiteral := False;
  repeat
    CurChar := CurPos^;
    if (CurChar = acMacrosChar) and not Literal and ((CurPos + 1)^ <> acMacrosChar) then
    begin
      StartPos := CurPos;
      while (CurChar <> #0) and (Literal or not NameDelimiter) do
      begin
        Inc(CurPos);
        CurChar := CurPos^;
        if IsLiteral then
        begin
          Literal := Literal xor True;
          if CurPos = StartPos + 1 then EmbeddedLiteral := True;
        end;
      end;
      CurPos^ := #0;
      if EmbeddedLiteral then
      begin
        Name := StripLiterals(StartPos + 1);
        EmbeddedLiteral := False;
      end
      else Name := StrPas(StartPos + 1);
      Macro := List.CreateMacro(Name );
      Macro.MacroOptions := Macro.MacroOptions + MacroOptions;
      CurPos^ := CurChar;
      StartPos^ := '?';
      Inc(StartPos);
      StrMove(StartPos, CurPos, StrLen(CurPos) + 1);
      CurPos := StartPos;
    end
    else if (CurChar = acMacrosChar) and not Literal and ((CurPos + 1)^ = acMacrosChar) then
      StrMove(CurPos, CurPos + 1, StrLen(CurPos) + 1)
    else if IsLiteral then Literal := Literal xor True;
    Inc(CurPos);
  until CurChar = #0;
end;

{ TMacros }
constructor TMacros.Create;
begin
  FItems := TList.Create;
end;

destructor TMacros.Destroy;
begin
  Clear;
  FItems.Free;
  inherited Destroy;
end;

procedure TMacros.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineBinaryProperty('Data', ReadBinaryData, WriteBinaryData, Count > 0);
end;

procedure TMacros.ReadBinaryData(Stream: TStream);
var
  I : Integer;
  NumItems, Temp : SmallInt;
  TempStr: string;
begin
  Clear;
  with Stream do
  begin
    ReadBuffer(NumItems, SizeOf(NumItems));
    for I := 0 to NumItems - 1 do
      with TMacro.Create(Self) do
      begin
        Temp := 0;
        ReadBuffer(Temp, 1);
        SetLength(TempStr, Temp);
        ReadBuffer(PChar(TempStr)^, Temp);
        Name := TempStr;
        Temp := 0;
        ReadBuffer(Temp, 1);
        SetLength(TempStr, Temp);
        ReadBuffer(PChar(TempStr)^, Temp);
        Text := TempStr;
        ReadBuffer(MacroOptions, Sizeof(MacroOptions));
      end;
  end;
end;

procedure TMacros.WriteBinaryData(Stream: TStream);
var
  I: Integer;
  Temp: SmallInt;
begin
  with Stream do
  begin
    Temp := Count;
    WriteBuffer(Temp, SizeOf(Temp));
    for I := 0 to Count - 1 do
      with Items[I] do
      begin
        Temp := Length(FName);
        WriteBuffer(Temp, 1);
        WriteBuffer(PChar(FName)^, Length(FName));
        Temp := Length(FText);
        WriteBuffer(Temp, 1);
        WriteBuffer(PChar(FText)^, Length(FText));
        WriteBuffer(MacroOptions, Sizeof(MacroOptions));
      end;
  end;
end;


procedure TMacros.Assign(Source: TPersistent);
var
  I: Integer;
begin
  if Source is TMacros then
  begin
    Clear;
    for I := 0 to TMacros(Source).Count - 1 do
      with TMacro.Create(Self) do
        Assign(TMacros(Source)[I]);
  end
  else inherited Assign(Source);
end;

procedure TMacros.AssignTo(Dest: TPersistent);
begin
  if Dest is TMacros then TMacros(Dest).Assign(Self)
  else inherited AssignTo(Dest);
end;

procedure TMacros.AssignValues(Value: TMacros);
var
  I, J: Integer;
begin
    for I := 0 to Count - 1 do
      for J := 0 to Value.Count - 1 do
        if Items[I].Name = Value[J].Name then
        begin
          Items[I].Text := Value[J].Text;
          Items[I].MacroOptions := Value[J].MacroOptions;
          Break;
        end;
end;


procedure TMacros.AddMacro(Value: TMacro);
begin
  FItems.Add(Value);
  Value.FMacroList := Self;
end;

procedure TMacros.RemoveMacro(Value: TMacro);
begin
  FItems.Remove(Value);
  Value.FMacroList := nil;
end;

function TMacros.CreateMacro(const MacroName: string): TMacro;
Var
  i : Integer;
begin
  for I := 0 to FItems.Count - 1 do
    if AnsiCompareText(TMacro(FItems[i]).Name, MacroName) = 0 then begin
      Result := FItems[i];
      Exit;
    end;
  Result := TMacro.Create(Self);
  Result.Name := MacroName;
end;

function TMacros.Count: Integer;
begin
  Result := FItems.Count;
end;

procedure TMacros.Clear;
begin
  while FItems.Count > 0 do TMacro(FItems.Last).Free;
end;

function TMacros.GetMacro(Index: Word): TMacro;
begin
  Result := MacroByName(TMacro(FItems[Index]).Name);
end;

function TMacros.MacroByName(const Value: string): TMacro;
var
  I: Integer;
begin
  for I := 0 to FItems.Count - 1 do
  begin
    Result := FItems[I];
    if AnsiCompareText(Result.Name, Value) = 0 then Exit;
  end;
  Result := Nil;
end;

function TMacros.GetMacroText(const MacroName: string): String;
begin
  Result := MacroByName(MacroName).text;
end;

procedure TMacros.SetMacroText(const MacroName: string;  const text: String);
begin
  MacroByName(MacroName).Text := Text;
end;


{ TMacros }

constructor TMacro.Create(AMacroList: TMacros);
begin
  if AMacroList <> nil then AMacroList.AddMacro(Self);
  MacroOptions := [];
end;

destructor TMacro.Destroy;
begin
   if FMacroList <> nil then FMacroList.RemoveMacro(Self);
end;

procedure TMacro.Assign(Macro: TMacro);
begin
  if Macro <> nil then begin
    Text := Macro.Text;

⌨️ 快捷键说明

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