📄 jvqsimlogic.pas
字号:
begin
Left := nc.X - D;
Width := -nw + D + D;
end
else
Width := nw;
nh := nc.Y - FConAnchor.Y;
// adjust BR new hot position
if (nw < D) and (not (nh < D)) then
begin
case FConHot of
jcpBR:
FConPos := jcpBL;
jcpTL:
FConPos := jcpTR;
end;
FShape := jcsTRBL;
end
else
if (nw < D) and (nh < D) then
begin
case FConHot of
jcpBR:
FConPos := jcpTL;
jcpTL:
FConPos := jcpBR;
end;
FShape := jcsTLBR;
end
else
if (not nw < D) and (nh < D) then
begin
case FConHot of
jcpBR:
FConPos := jcpTR;
jcpTL:
FConPos := jcpBL;
end;
FShape := jcsTRBL;
end
else
begin
case FConHot of
jcpBR:
FConPos := jcpBR;
jcpTL:
FConPos := jcpTL;
end;
FShape := jcsTLBR;
end;
// end of adjust BR new hot
if nh < D then
begin
Top := FConAnchor.Y + nh - D;
Height := -nh + D + D;
end
else
Height := nh;
end;
jcmBL:
begin
nw := FConAnchor.X - nc.X;
if nw < D then
begin
Left := FConAnchor.X - D;
Width := -nw + D + D;
end
else
begin
Left := FConAnchor.X - nw;
Width := nw;
end;
nh := nc.Y - FConAnchor.Y;
// adjust BL new hot position
if (nw < D) and (not (nh < D)) then
begin
case FConHot of
jcpBL:
FConPos := jcpBR;
jcpTR:
FConPos := jcpTL;
end;
FShape := jcsTLBR;
end
else
if (nw < D) and (nh < D) then
begin
case FConHot of
jcpBL:
FConPos := jcpTR;
jcpTR:
FConPos := jcpBL;
end;
FShape := jcsTRBL;
end
else
if (not nw < D) and (nh < D) then
begin
case FConHot of
jcpBL:
FConPos := jcpTL;
jcpTR:
FConPos := jcpBR;
end;
FShape := jcsTLBR;
end
else
begin
case FConHot of
jcpBL:
FConPos := jcpBL;
jcpTR:
FConPos := jcpTR;
end;
FShape := jcsTRBL;
end;
// end of adjust BL new hot
if nh < D then
begin
Top := FConAnchor.Y + nh - D;
Height := -nh + D + D;
end
else
Height := nh;
end;
end;
end;
procedure TJvSIMConnector.Connect;
var
Pi, Po: TPoint;
R: TRect;
D, d2, xw, yh: Integer;
Wc: TWinControl;
Vi: Boolean;
sBut: TJvSimButton;
sLog: TJvLogic;
sLight: TJvSimLight;
sRev: TJvSimReverse;
pl: TPoint;
// convert a corner point to a Parent point
function ParentPoint(X, Y: Integer): TPoint;
var
P: TPoint;
begin
P := Point(X, Y);
P := ClientToScreen(P);
Result := Wc.ScreenToClient(P);
end;
function GetVi: Boolean;
var
J: Integer;
begin
Result := True;
for J := 0 to Wc.ControlCount - 1 do
begin
if Wc.Controls[J] is TJvSimButton then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Pi) then
begin
sBut := TJvSimButton(Wc.Controls[J]);
Vi := sBut.Down;
Exit;
end;
end
else
if Wc.Controls[J] is TJvSimReverse then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, D);
if PtInRect(R, Pi) then
begin
sRev := TJvSimReverse(Wc.Controls[J]);
// now check if P is the output area
pl := sRev.Gates[1].Pos;
R := Rect(sRev.Left + pl.X, sRev.Top - D, sRev.Left + pl.X + 12, sRev.Top + pl.Y + 12);
if PtInRect(R, Pi) and sRev.Gates[1].Active then
begin // output
Vi := sRev.Output1;
Exit;
end;
pl := sRev.Gates[2].Pos;
R := Rect(sRev.Left - D, sRev.Top + pl.Y, sRev.Left + pl.X + 12, sRev.Top + pl.Y + 12);
if PtInRect(R, Pi) and sRev.Gates[2].Active then
begin // output
Vi := sRev.Output2;
Exit;
end;
pl := sRev.Gates[3].Pos;
R := Rect(sRev.Left + pl.X, sRev.Top + pl.Y, sRev.Left + pl.X + 12, sRev.Top + sRev.Height + D);
if PtInRect(R, Pi) and sRev.Gates[3].Active then
begin // output
Vi := sRev.Output3;
Exit;
end;
end;
end
else
if Wc.Controls[J] is TJvLogic then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Pi) then
begin
sLog := TJvLogic(Wc.Controls[J]);
// now check if P is in one of the 3 output area's
R := Rect(sLog.Left + 33, sLog.Top, sLog.Left + sLog.Width + FConSize, sLog.Top + 22);
if PtInRect(R, Pi) and sLog.Gates[3].Active then
begin // output is gate 3
Vi := sLog.Output1;
Exit;
end;
R := Rect(sLog.Left + 33, sLog.Top + 23, sLog.Left + sLog.Width + FConSize, sLog.Top + 44);
if PtInRect(R, Pi) and sLog.Gates[4].Active then
begin // output is gate 4
Vi := sLog.Output2;
Exit;
end;
R := Rect(sLog.Left + 33, sLog.Top + 45, sLog.Left + sLog.Width + FConSize, sLog.Top + 64);
if PtInRect(R, Pi) and sLog.Gates[5].Active then
begin // output is gate 5
Vi := sLog.Output3;
Exit;
end;
end;
end;
end;
Result := False;
end;
procedure SetVo;
var
J: Integer;
begin
for J := 0 to Wc.ControlCount - 1 do
begin
if (Wc.Controls[J] is TJvSimLight) then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Po) then
begin
sLight := TJvSimLight(Wc.Controls[J]);
sLight.Lit := Vi;
Exit;
end;
end
else
if Wc.Controls[J] is TJvSimReverse then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Po) then
begin
sRev := TJvSimReverse(Wc.Controls[J]);
// now check if P is in the input area
pl := sRev.Gates[0].Pos;
R := Rect(sRev.Left + pl.X, sRev.Top + pl.Y, sRev.Left + sRev.Width + D, sRev.Top + pl.Y + 12);
if PtInRect(R, Po) and sRev.Gates[0].Active then
begin // input
sRev.Input1 := Vi;
Exit;
end;
end;
end
else
if Wc.Controls[J] is TJvLogic then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Po) then
begin
sLog := TJvLogic(Wc.Controls[J]);
// now check if P is in one of the 3 input area's
R := Rect(sLog.Left - D, sLog.Top, sLog.Left + 32, sLog.Top + 22);
if PtInRect(R, Po) and sLog.Gates[0].Active then
begin // input is gate 0
sLog.Input1 := Vi;
Exit;
end;
R := Rect(sLog.Left - D, sLog.Top + 23, sLog.Left + 32, sLog.Top + 44);
if PtInRect(R, Po) and sLog.Gates[1].Active then
begin // input is gate 1
sLog.Input2 := Vi;
Exit;
end;
R := Rect(sLog.Left - D, sLog.Top + 45, sLog.Left + 32, sLog.Top + 64);
if PtInRect(R, Po) and sLog.Gates[2].Active then
begin // input is gate 2
sLog.Input3 := Vi;
Exit;
end;
end;
end;
end;
end;
begin
// connect input and output using the FConPos
d2 := FConSize div 2;
D := FConSize;
xw := Width - 1;
yh := Height - 1;
Wc := Parent;
case FConPos of
jcpTL:
begin
Pi := ParentPoint(d2, d2);
Po := ParentPoint(xw - d2, yh - d2);
end;
jcpTR:
begin
Pi := ParentPoint(xw - d2, d2);
Po := ParentPoint(d2, yh - d2);
end;
jcpBR:
begin
Pi := ParentPoint(xw - d2, yh - d2);
Po := ParentPoint(d2, d2);
end;
jcpBL:
begin
Pi := ParentPoint(d2, yh - d2);
Po := ParentPoint(xw - d2, d2);
end;
end;
// get input Vi
if GetVi then
SetVo;
end;
procedure TJvSIMConnector.Disconnect;
var
Pi, Po: TPoint;
R: TRect;
D, d2, xw, yh: Integer;
Wc: TWinControl;
sLog: TJvLogic;
sLight: TJvSimLight;
// convert a corner point to a Parent point
function ParentPoint(X, Y: Integer): TPoint;
var
P: TPoint;
begin
P := Point(X, Y);
P := ClientToScreen(P);
Result := Wc.ScreenToClient(P);
end;
procedure SetVo;
var
J: Integer;
begin
for J := 0 to Wc.ControlCount - 1 do
begin
if Wc.Controls[J] is TJvSimLight then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Po) then
begin
sLight := TJvSimLight(Wc.Controls[J]);
FDisCon := sLight;
//sLight.Lit:=False;
Exit;
end;
end
else
if Wc.Controls[J] is TJvLogic then
begin
R := Wc.Controls[J].BoundsRect;
InflateRect(R, D, 0);
if PtInRect(R, Po) then
begin
sLog := TJvLogic(Wc.Controls[J]);
// now check if P is in one of the 3 input area's
R := Rect(sLog.Left - D, sLog.Top, sLog.Left + 32, sLog.Top + 22);
if PtInRect(R, Po) and sLog.Gates[0].Active then
begin // input is gate 0
FDisCon := sLog;
FDisConI := 1;
// sLog.Input1:=False;
Exit;
end;
R := Rect(sLog.Left - D, sLog.Top + 23, sLog.Left + 32, sLog.Top + 44);
if PtInRect(R, Po) and sLog.Gates[1].Active then
begin // input is gate 1
FDisCon := sLog;
FDisConI := 2;
// sLog.Input2:=False;
Exit;
end;
R := Rect(sLog.Left - D, sLog.Top + 45, sLog.Left + 32, sLog.Top + 64);
if PtInRect(R, Po) and sLog.Gates[2].Active then
begin // input is gate 2
FDisCon := sLog;
FDisConI := 3;
// sLog.Input3:=False;
Exit;
end;
end;
end;
end;
end;
begin
// connect input and output using the FConPos
FDisCon := nil;
FDisConI := 0;
d2 := FConSize div 2;
D := FConSize;
xw := Width - 1;
yh := Height - 1;
Wc := Parent;
case FConPos of
jcpTL:
begin
Pi := ParentPoint(d2, d2);
Po := ParentPoint(xw - d2, yh - d2);
end;
jcpTR:
begin
Pi := ParentPoint(xw - d2, d2);
Po := ParentPoint(d2, yh - d2);
end;
jcpBR:
begin
Pi := ParentPoint(xw - d2, yh - d2);
Po := ParentPoint(d2, d2);
end;
jcpBL:
begin
Pi := ParentPoint(d2, yh - d2);
Po := ParentPoint(xw - d2, d2);
end;
end;
// clear logic inputs and lights
SetVo;
end;
//=== { TJvLogic } ===========================================================
constructor TJvLogic.Create(AOwner: TComponent);
var
I: Integer;
begin
inherited Create(AOwner);
Width := 65;
Height := 65;
// initialize Gates
FGates[0].Pos := Point(1, 10);
FGates[1].Pos := Point(1, 28);
FGates[2].Pos := Point(1, 46);
FGates[3].Pos := Point(52, 10);
FGates[4].Pos := Point(52, 28);
FGates[5].Pos := Point(52, 46);
for I := 0 to 5 do
FGates[I].State := False;
for I := 0 to 2 do
begin
FGates[I].Style := jgsDI;
FGates[I + 3].Style := jgsDO;
end;
FLogicFunc := jlfAND;
FGates[0].Active := True;
FGates[1].Active := False;
FGates[2].Active := True;
FGates[3].Active := False;
FGates[4].Active := True;
FGates[5].Active := False;
FConnectors := TList.Create;
end;
destructor TJvLogic.Destroy;
begin
FConnectors.Free;
inherited Destroy;
end;
function TJvLogic.GetGate(Index: Integer): TJvGate;
begin
Result := FGates[Index];
end;
procedure TJvLogic.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
R: TRect;
begin
FDoMove := False;
FDoStyle := False;
FStyleDown := False;
FMdp := Point(X, Y);
R := ClientRect;
InflateRect(R, -15, -15);
FDoStyle := PtInRect(R, FMdp);
FDoMove := not FDoStyle;
FOldp := Point(X, Y);
if FDoMove then
AnchorConnectors;
if FDoStyle then
begin
FStyleDown := True;
Invalidate;
end;
end;
procedure TJvLogic.MouseMove(Shift: TShiftState; X, Y: Integer);
var
P: TPoint;
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -