fmain.pas

来自「FlexGraphics是一套创建矢量图形的VCL组件」· PAS 代码 · 共 931 行 · 第 1/2 页

PAS
931
字号

procedure TfmMain.SortLamps;
var Sorted: boolean;
    i: integer;
    Lamp: pointer;
begin
 // Bubble sorting
 repeat
  Sorted := true;
  for i:=1 to FLamps.Count-1 do
   if TFlexControl(FLamps[i]).Tag < TFlexControl(FLamps[i-1]).Tag then begin
    Lamp := FLamps[i];
    FLamps[i] := FLamps[i-1];
    FLamps[i-1] := Lamp;
    Sorted := false;
   end;
 until Sorted;
end;

procedure TfmMain.PaintActive(AsActive: boolean);
var Style: TColorStyles;
    i, ZoneId, Index: integer;
begin
 if not Assigned(FLastActive) then begin
  FLastActiveStyle := csNone;
  exit;
 end;
 Index := FLastActive.UserData.IndexOfName('ZoneID');
 if Index >= 0 then begin
  Style := csZone;
  if Options.ShowZoneCaptions = zsSelected then begin
   // Show or hide associated ZoneNames
   ZoneId := StrToIntDef(FLastActive.UserData.ValuesByIndex[Index], 0);
   for i:=0 to FZoneNames.Count-1 do
    if TFlexControl(FZoneNames[i]).Tag = ZoneId then
     TFlexControl(FZoneNames[i]).Visible := AsActive;
  end;
 end else
 if FLastActive = FCopyright then
  Style := csCopyright
 else
 if FLastActive.ParentScheme.Name = 'MainPlan'
  then Style := csBuildings
  else Style := csButtons;
 PaintControl(AsActive, FLastActive, Style);
 FLastActiveStyle := Style;
end;

procedure TfmMain.PaintSchemeBtn(AsActive: boolean);
begin
 PaintControl(AsActive, FSchemeBtn, csSchemeBtn);
end;

function TfmMain.GetSchemeBtn(PTabIndex: PInteger = Nil): TFlexControl;
const
  Names: array[0..9, 0..1] of string = (
    ( 'MainPlan', '' ),
    ( 'AdmGrandFloor', 'BtnGrand' ),
    ( 'AdmFloor1', 'BtnFloor1' ),
    ( 'AdmFloor2', 'BtnFloor2' ),
    ( 'ControlPost', '' ),
    ( 'ProdGrandFloor', 'BtnGrand' ),
    ( 'ProdFloor1', 'BtnFloor1' ),
    ( 'ProdFloor2', 'BtnFloor2' ),
    ( 'TechGrandFloor', 'BtnGrand' ),
    ( 'TechFloor1', 'BtnFloor1' )
  );
var
  i: integer;
  Scheme: TFlexCustomScheme;
begin
 if Assigned(PTabIndex) then PTabIndex^ := -1;
 Result := Nil;
 Scheme := fpMain.ActiveScheme;
 if not Assigned(Scheme) then exit;
 for i:=0 to High(Names) do
  if CompareText(Names[i,0], Scheme.Name) = 0 then begin
   if Assigned(PTabIndex) then
    case i of
     0    : PTabIndex^ := 0;
     1..3 : PTabIndex^ := 2;
     4    : PTabIndex^ := 1;
     5..7 : PTabIndex^ := 3;
     8, 9 : PTabIndex^ := 4;
    end;
   if Names[i, 1] <> '' then Result := Scheme.FindByName(Names[i, 1]);
   break;
  end;
end;

procedure TfmMain.fpMainNotify(Sender: TObject; Control: TFlexControl;
  Notify: TFlexNotify);
var BtnControl: TFlexControl;
    TabIdx: integer;
    Id, Index: integer;
    Card: TFlexCard;
begin
 if csDestroying in ComponentState then exit;
 case Notify of
  fnRect:
    if (fpMain.ToolMode = ftmMoving) and
       (Control.UserData.Values['Type'] = 'Card') then begin
     Card := FindFlexCard(Nil, Control);
     if Assigned(Card) then Card.SavePosition;
    end;
  fnLoaded:
    begin
     // Checking Lamp
     if Control.Name = 'Lamp' then begin
      FLamps.Add(Control);
     end else
     // Checking copyright string
     if Control.Name = 'Copyright' then
      FCopyright := TFlexText(Control)
     else
     // Checking ZoneNames layer
     if (Control is TFlexLayer) and (Control.Name = 'ZoneNames') then
      FZoneNamesLayer := TFlexLayer(Control)
     else
     // Checking door control
     if Control is TFlexDoor then begin
      FDoors.Add(Control);
      TFlexDoor(Control).DoorState := dsClosed;
     end else
     // Checking ZoneName controls
     if Control.Name = 'ZoneName' then begin
      FZoneNames.Add(Control);
      Control.Visible := False;
      TFlexText(Control).WordWrap := true;
      Id := StrToIntDef(Control.UserData.Values['ZoneID'], 0);
      Control.Tag := Id;
      Index := dmMain.FindZone(Id);
      if Index >= 0 then
       TFlexText(Control).TextProp.Text := PZone(dmMain.Zones[Index]).Name;
     end else
     // Checking zone controls
     if (Control.UserData.IndexOfName('ZoneID') >= 0) and
        (Control.UserData.IndexOfName('Level') >= 0) then begin
      FZones.Add(Control);
      Id := StrToIntDef(Control.UserData.Values['ZoneID'], 0);
      Index := dmMain.FindZone(Id);
      if Index >= 0 then
       Control.Hint := PZone(dmMain.Zones[Index]).Name;
     end;
    end;
  fnSchemes:
    begin
     if Assigned(FSelected) then
      if fpMain.ActiveScheme <> FSelected.ParentScheme
       then tmSelected.Enabled := false
       else tmSelected.Enabled := true;
     PaintActive(False);
     FLastActive := Nil;
     // Scheme button checking
     BtnControl := GetSchemeBtn(@TabIdx);
     if BtnControl <> FSchemeBtn then begin
      PaintSchemeBtn(False);
      FSchemeBtn := BtnControl;
      PaintSchemeBtn(True);
     end;
     tbMain.TabIndex := TabIdx;
     HideAllPersonCards;
    end;
  fnScale:
    begin
     sbtZoomIn.Enabled := fpMain.Scale < 400;
     sbtZoomOut.Enabled := fpMain.Scale > 50;
    end;
 end;

end;

procedure TfmMain.fpMainMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var Id, Index: integer;
    s: string;

 function IsActive(Control: TFlexControl): boolean;
 begin
  Result := Assigned(Control);
  if not Result then exit;
  Result :=  Assigned(Control.Reference) or
             (Control.UserData.IndexOfName('ZoneID') >= 0) or
             (Control = FCopyright);
 end;

begin
 if not Assigned(fpMain.ActiveScheme) then exit;
 // Checking last active control (button or building on main scheme)
 if fpMain.MouseControl <> FLastActive then begin
  PaintActive(False);
  if IsActive(fpMain.MouseControl) then begin
   FLastActive := fpMain.MouseControl;
   PaintActive(True);
  end else
   FLastActive := Nil;
 end;
 // Update status bar
 s := '';
 if Assigned(FLastActive) then
  case FLastActiveStyle of
   csBuildings:
     begin
      if CompareText(FLastActive.Name, 'Administrate') = 0 then
       s := 'Go to Administrative building plans'
      else
      if CompareText(FLastActive.Name, 'Production') = 0 then
       s := 'Go to Production building plans'
      else
      if CompareText(FLastActive.Name, 'Tech center') = 0 then
       s := 'Go to Technical center plans'
      else
      if CompareText(FLastActive.Name, 'Control Post') = 0 then
       s := 'Go to Control post plan';
      if s <> '' then
       FLastActive.Hint := s;
     end;
   csZone:
     begin
      Id := StrToIntDef(FLastActive.UserData.Values['ZoneID'], 0);
      Index := dmMain.FindZone(id);
      if Index >= 0 then with PZone(dmMain.Zones[Index])^ do
       s := Format('Zone %d: %s', [Id, Name])
      else
       s := 'Unknown zone';
     end;
  end;
 sbMain.SimpleText := s;
end;

procedure TfmMain.fpMainMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 if Sender = fpMain then begin
  fpMain.SetFocus;
  if not fpMain.Focused then Windows.SetFocus(fpMain.Handle);
 end;
 if fpMain.ToolMode <> ftmSelect then exit;
 if (Button = mbLeft) and Assigned(fpMain.MouseSubControl) then begin
  if (FZones.IndexOf(fpMain.MouseSubControl) >= 0) or
     (FDoors.IndexOf(fpMain.MouseSubControl) >= 0) then
   Selected := fpMain.MouseSubControl
  else
  if fpMain.MouseSubControl = FCopyright then begin
   PaintActive(False);
   FLastActive := Nil;
   sbtAbout.Click
  end else
  if fpMain.MouseControl.UserData.Values['Type'] = 'Card' then begin
   fpMain.UnselectAll;
   fpMain.Select(fpMain.MouseControl);
   fpMain.ToolMode := ftmMoving;
  end else
  if not Assigned(fpMain.MouseControl.Reference) then
   Selected := Nil;
 end else
  Selected := Nil;
end;

procedure TfmMain.sbtExitClick(Sender: TObject);
begin
 Close;
end;

procedure TfmMain.sbtControlClick(Sender: TObject);
begin
 ShowLists;
end;

procedure TfmMain.fpMainExit(Sender: TObject);
begin
 PaintActive(False);
 FLastActive := Nil;
end;

procedure TfmMain.sbtOptionsClick(Sender: TObject);
begin
 if EditOptions then begin
  SetOptions;
  SaveOptions;
 end;
end;

procedure TfmMain.sbtZoomClick(Sender: TObject);
begin
 if Sender = sbtZoomIn then
  fpMain.Zoom(fpMain.Scale * 2, Nil)
 else
 if Sender = sbtZoomOut then
  fpMain.Zoom(fpMain.Scale div 2, Nil)
end;

procedure TfmMain.sbtAboutClick(Sender: TObject);
begin
 ShowAbout;
end;

procedure TfmMain.EventsChange(Sender: TObject);
begin
 if Assigned(fmControl) then fmControl.RefreshEvents;
end;

procedure TfmMain.SetDoorTimeOut(Door: TFlexDoor; PassId: integer);
var i: integer;
    TimeOut: PDoorTimeOut;
begin
 // Find door in persent timeouts
 TimeOut := Nil;
 for i:=0 to FDoorsTimeOuts.Count-1 do
  if PDoorTimeOut(FDoorsTimeOuts[i]).Door = Door then begin
   TimeOut := PDoorTimeOut(FDoorsTimeOuts[i]);
   break;
  end;
 if not Assigned(TimeOut) then begin
  // Create new timeout
  New(TimeOut);
  FillChar(TimeOut^, SizeOf(TimeOut^), 0);
  TimeOut.Door := Door;
  FDoorsTimeOuts.Add(TimeOut);
 end;
 TimeOut.PassId := PassId;
 TimeOut.TimeToClose := Now + SecToDT(3);
end;

function TfmMain.DoPass(PassId, PersonId: integer; DoOpen: boolean): boolean;
var Door: TFlexControl;
    Info: string;
    Index: integer;
    IsBlocked: boolean;
    NewDoorState: TDoorState;
    NewDoorEvent: TDoorEvent;
    NewAccessDir: TDoorAccessDirection;
begin
 Result := false;
 Door := fmMain.FindPass(PassId);
 if Assigned(Door) then with TFlexDoor(Door) do begin
  IsBlocked := DoorEvent = deBroken;
  // Define direction
  if PassAProp.Value = PassId
   then NewAccessDir := ddForward
   else NewAccessDir := ddBackward;
  // Define state
  if DoOpen then begin
   NewDoorState := dsOpened;
   if IsBlocked
    then Info := 'Attempt to open blocked door %d by '
    else Info := 'Door %d opened by ';
  end else begin
   NewDoorState := dsClosed;
   if IsBlocked
    then Info := 'Attempt to close blocked door %d by '
    else Info := 'Door %d closed by ';
  end;
  // Define person
  if PersonId = -1 then begin
   // is time out
   NewDoorEvent := DoorEvent; //deInactive;
   Info := Info + 'timeout';
  end else
  if PersonId = 0 then begin
   // is operator
   NewDoorEvent := deInactive;
   Info := Info + 'operator';
  end else begin
   // is person
   Index := dmMain.FindPerson(PersonId);
   if Index >= 0 then with PPerson(dmMain.Personnel[Index])^ do begin
    Info := Info + FirstName + ' ' + LastName;
    NewDoorEvent := deValid;
   end else begin
    // Alert. Unknown person
    Info := Info + '<unknown>';
    NewDoorEvent := deError;
   end;
  end;
  if not IsBlocked then begin
   // Set new state
   AccessDir := NewAccessDir;
   DoorEvent := NewDoorEvent;
   DoorState := NewDoorState;
   if DoorState = dsOpened then SetDoorTimeOut(TFlexDoor(Door), PassId);
   if not FMinimized {(WindowState <> wsMinimized)} and
      Options.ShowPersonsCards then
    if Options.ShowCardsInFlex then begin
     // Flex card
     if DoorState = dsOpened
      then ShowFlexCard(PassId, PersonId, Door)
      else DestroyFlexCard(Door);
    end else
    // Card as form
    if Door.ParentScheme = fpMain.ActiveScheme then
     if DoorState = dsOpened
      then ShowPersonCard(PassId, PersonId, Door)
      else HidePersonCard(Door);
   Result := true;
  end else begin
   // Alarm state
   Result := DoorState = dsOpened;
   if not Result then
    if Options.ShowCardsInFlex then
     // Flex card
     ShowFlexCard(PassId, PersonId, Door, True)
    else
    // Card as form
    if Door.ParentScheme = fpMain.ActiveScheme then
     ShowPersonCard(PassId, PersonId, Door, True);
  end;
  // Add event
  dmMain.AddEvent(Format(Info, [PassId]), PassId, 0, PersonId);
 end;
end;

procedure TfmMain.DoBlock(PassId: integer; IsBlock: boolean);
var Door: TFlexDoor;
    Info: string;
    IsBlocked: boolean;
begin
 Door := TFlexDoor(fmMain.FindPass(PassId));
 if not Assigned(Door) then exit;
 IsBlocked := Door.DoorEvent = deBroken;
 if IsBlocked = IsBlock then exit;
 if IsBlock then begin
  Info := 'Door %d blocked by operator';
  Door.DoorEvent := deBroken;
 end else begin
  Info := 'Door %d unblocked by operator';
  Door.DoorEvent := deInactive;
 end;
 // Add event
 dmMain.AddEvent(Format(Info, [PassId]), PassId, 0, 0);
end;

procedure TfmMain.tmTimeOutsTimer(Sender: TObject);
var i: integer;
begin
 for i:=FDoorsTimeOuts.Count-1 downto 0 do
  with PDoorTimeOut(FDoorsTimeOuts[i])^ do
   if Now - TimeToClose >= 0 then begin
    DoPass(PassId, -1, False);
    Dispose(PDoorTimeOut(FDoorsTimeOuts[i]));
    FDoorsTimeOuts.Delete(i);
   end;
end;

procedure TfmMain.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if (Key = VK_MENU) and (fpMain.ToolMode = ftmSelect) and
    not Assigned(fpMain.CreatingControlClass) then
  fpMain.ToolMode := ftmPan
 else
 if Key = vk_F1 then sbtAbout.Click;
end;

procedure TfmMain.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if (Key = VK_MENU) and
   ((fpMain.ToolMode = ftmPan) or (fpMain.ToolMode = ftmPanning)) then
  fpMain.ToolMode := ftmSelect;
end;

end.

⌨️ 快捷键说明

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