📄 teetools.pas
字号:
var t : Integer;
begin
inherited;
if (AEvent=cteAfterDraw) and (Lines.Count>0) then
begin
with ParentChart do
begin
Canvas.BackMode:=cbmTransparent;
ClipDrawingRegion;
end;
for t:=0 to Lines.Count-1 do
With Lines[t] do
begin
ParentChart.Canvas.AssignVisiblePen(Pen);
DrawLine(AxisPoint(StartPos),AxisPoint(EndPos),Style);
end;
if Assigned(ISelected) then ISelected.DrawHandles;
ParentChart.Canvas.UnClipRectangle;
end;
end;
Procedure TDrawLineTool.ClipDrawingRegion;
var R : TRect;
begin
if Assigned(Series) then
With Series do
R:=TeeRect(GetHorizAxis.IStartPos,GetVertAxis.IStartPos,
GetHorizAxis.IEndPos,GetVertAxis.IEndPos)
else
R:=ParentChart.ChartRect;
With ParentChart do
if CanClip then Canvas.ClipCube(R,0,Width3D);
end;
Function TDrawLineTool.InternalClicked(X,Y:Integer; AHandle:TDrawLineHandle):TDrawLine;
var P : TPoint;
Function ClickedLine(ALine:TDrawLine):Boolean;
var tmpStart : TPoint;
tmpEnd : TPoint;
begin
With ALine do
begin
tmpStart:=AxisPoint(StartPos);
tmpEnd:=AxisPoint(EndPos);
Case AHandle of
chStart: result:=PointInRect(StartHandle,P.X,P.Y);
chEnd : result:=PointInRect(EndHandle,P.X,P.Y);
else
Case Style of
dlLine : result:=PointInLine(P,tmpStart,tmpEnd,4);
dlHorizParallel : begin
result:=PointInLine(P,tmpStart.X,tmpStart.Y,
tmpEnd.X,tmpStart.Y,4);
if not result then
result:=PointInLine( P,tmpStart.X,tmpEnd.Y,
tmpEnd.X,tmpEnd.Y,4);
end;
else
begin
result:=PointInLine( P,tmpStart.X,tmpStart.Y,
tmpStart.X,tmpEnd.Y,4);
if not result then
result:=PointInLine( P,tmpEnd.X,tmpStart.Y,
tmpEnd.X,tmpEnd.Y,4);
end
end;
end;
end;
end;
var t : Integer;
begin
result:=nil;
// convert from 3D to 2D...
ParentChart.Canvas.Calculate2DPosition(X,Y,0);
// first, find if clicked the selected line...
P:=TeePoint(X,Y);
if Assigned(ISelected) and ClickedLine(ISelected) then
begin
result:=ISelected;
exit;
end;
// find which clicked line...
for t:=0 to Lines.Count-1 do
if ClickedLine(Lines[t]) then
begin
result:=Lines[t];
break;
end;
end;
Function TDrawLineTool.Clicked(X,Y:Integer):TDrawLine;
begin
// try first with whole line...
result:=InternalClicked(X,Y,chNone);
// try then at start and end line points...
if not Assigned(result) then result:=InternalClicked(X,Y,chStart);
if not Assigned(result) then result:=InternalClicked(X,Y,chEnd);
end;
Procedure TDrawLineTool.ChartMouseEvent( AEvent: TChartMouseEvent;
AButton:TMouseButton;
AShift: TShiftState; X, Y: Integer);
{ returns True if the mouse is over selected line ending points or over
any non-selected line.
If True, the Chart cursor is changed.
}
Function CheckCursor:Boolean;
begin
if Assigned(ISelected) and
((InternalClicked(X,Y,chStart)=ISelected) or
(InternalClicked(X,Y,chEnd)=ISelected)) then { ending points }
begin
ParentChart.Cursor:=crCross;
result:=True;
end
else
if Assigned(Clicked(X,Y)) then { over a line }
begin
ParentChart.Cursor:=crHandPoint; // set cursor
result:=True;
end
else result:=False;
end;
var tmpLine : TDrawLine;
tmpAllow : Boolean;
begin
Case AEvent of
cmeDown: if AButton=FButton then
begin
if FEnableSelect then tmpLine:=Clicked(X,Y)
else tmpLine:=nil;
if Assigned(tmpLine) then { clicked line, do select }
begin
FromPoint:=AxisPoint(tmpLine.StartPos);
ToPoint:=AxisPoint(tmpLine.EndPos);
IHandle:=chSeries;
IPoint:=TeePoint(X,Y);
if tmpLine<>ISelected then
begin
tmpAllow:=True;
if Assigned(FOnSelecting) then
FOnSelecting(Self,tmpLine,tmpAllow); { 5.03 }
if tmpAllow then
begin
{ change selected line }
if Assigned(ISelected) then
begin
ISelected:=tmpLine;
Repaint;
end
else
begin
ISelected:=tmpLine;
ISelected.DrawHandles;
end;
{ call event }
if Assigned(FOnSelect) then FOnSelect(Self);
end;
end
else
begin
{ check if clicked on ending points }
if Assigned(InternalClicked(X,Y,chStart)) then
IHandle:=chStart
else
if Assigned(InternalClicked(X,Y,chEnd)) then
IHandle:=chEnd;
end;
ParentChart.CancelMouse:=True;
end
else
begin
{ un-select }
ISelected:=nil;
if EnableDraw then
begin
IDrawing:=True;
FromPoint:=TeePoint(X,Y);
ToPoint:=FromPoint;
RedrawLine(ISelected);
ParentChart.CancelMouse:=True;
end;
end;
end;
cmeMove: if IDrawing or (IHandle<>chNone) then // drawing or dragging
begin
RedrawLine(ISelected); // hide previous line
if IDrawing then ToPoint:=TeePoint(X,Y)
else
begin
if IHandle=chStart then FromPoint:=TeePoint(X,Y)
else
if IHandle=chEnd then ToPoint:=TeePoint(X,Y)
else
if IHandle=chSeries then
begin
Inc(FromPoint.X,X-IPoint.X);
Inc(FromPoint.Y,Y-IPoint.Y);
Inc(ToPoint.X,X-IPoint.X);
Inc(ToPoint.Y,Y-IPoint.Y);
IPoint:=TeePoint(X,Y);
end;
end;
RedrawLine(ISelected); // show line at new position
ParentChart.CancelMouse:=True;
// call event
if Assigned(FOnDragLine) then FOnDragLine(Self);
end
else
if FEnableSelect then { change the cursor if mouse is over lines }
ParentChart.CancelMouse:=CheckCursor;
cmeUp: if AButton=FButton then
begin
if IHandle<>chNone then // if dragging...
begin
if (IHandle=chStart) or (IHandle=chSeries) then
ISelected.StartPos:=ScreenPoint(FromPoint);
if (IHandle=chEnd) or (IHandle=chSeries) then
ISelected.EndPos:=ScreenPoint(ToPoint);
IHandle:=chNone;
// stop dragging, repaint
Repaint;
// call event
if Assigned(FOnDraggedLine) then FOnDraggedLine(Self); { 5.01 }
end
else
if IDrawing then // drawing a new line...
begin
if (FromPoint.X<>ToPoint.X) or (FromPoint.Y<>ToPoint.Y) then
begin
// create the new drawn line...
with TeeDrawLineClass.Create(Lines) do // 5.02
begin
StartPos:=ScreenPoint(FromPoint);
EndPos :=ScreenPoint(ToPoint);
end;
// repaint chart
Repaint;
// call event
if Assigned(FOnNewLine) then FOnNewLine(Self);
end;
IDrawing:=False;
end;
end;
end;
end;
class function TDrawLineTool.Description: String;
begin
result:=TeeMsg_DrawLineTool
end;
type TCustomTeePanelAccess=class(TCustomTeePanel);
procedure TDrawLineTool.RedrawLine(ALine:TDrawLine);
var tmp : TColor;
begin
// draw current selected or dragged line with "not xor" pen mode
With ParentChart.Canvas do
begin
tmp:=ColorToRGB(TCustomTeePanelAccess(ParentChart).GetBackColor);
AssignVisiblePenColor(Self.Pen,(clWhite-tmp) xor Self.Pen.Color);
Pen.Mode:=pmNotXor;
if Assigned(ALine) then
DrawLine(FromPoint,ToPoint,ALine.Style)
else
DrawLine(FromPoint,ToPoint,dlLine);
Pen.Mode:=pmCopy;
end;
end;
class function TDrawLineTool.GetEditorClass: String;
begin
result:='TDrawLineEdit';
end;
function TDrawLineTool.AxisPoint(const P: TFloatPoint): TPoint;
begin
// convert from axis double XY to screen pixels XY
result.X:=GetHorizAxis.CalcPosValue(P.X);
result.Y:=GetVertAxis.CalcPosValue(P.Y);
end;
function TDrawLineTool.ScreenPoint(P: TPoint): TFloatPoint;
begin
// convert from screen pixels XY position to axis double XY
result.X:=GetHorizAxis.CalcPosPoint(P.X);
result.Y:=GetVertAxis.CalcPosPoint(P.Y);
end;
procedure TDrawLineTool.SetEnableSelect(Value: Boolean);
begin
if FEnableSelect<>Value then
begin
FEnableSelect:=Value;
if not FEnableSelect then
begin
if Assigned(ISelected) then
begin
ISelected:=nil;
Repaint;
end;
end;
end;
end;
procedure TDrawLineTool.DeleteSelected;
begin
if Assigned(ISelected) then
begin
IDrawing:=False; // 5.02
IHandle:=chNone; // 5.02
FreeAndNil(ISelected);
Repaint;
end;
end;
procedure TDrawLineTool.SetSelected(Value: TDrawLine);
begin
ISelected:=Value;
Repaint;
end;
procedure TDrawLineTool.SetLines(const Value: TDrawLines);
begin
FLines.Assign(Value);
end;
{ TNearestTool }
Constructor TNearestTool.Create(AOwner: TComponent);
begin
inherited;
FLinePen:=CreateChartPen;
Point:=-1;
FullRepaint:=True;
Brush.Style:=bsClear;
Pen.Style:=psDot;
Pen.Color:=clWhite;
FSize:=20;
FStyle:=hsCircle;
end;
Destructor TNearestTool.Destroy;
begin
FLinePen.Free;
inherited;
end;
function TNearestTool.ZAxisCalc(const Value:Double):Integer;
begin
result:=Series.ParentChart.Axes.Depth.CalcPosValue(Value);
end;
Function TNearestTool.GetDrawLine:Boolean;
begin
result:=LinePen.Visible;
end;
procedure TNearestTool.SetDrawLine(const Value: Boolean);
begin
LinePen.Visible:=Value;
end;
procedure TNearestTool.SetLinePen(const Value: TChartPen);
begin
FLinePen.Assign(Value);
end;
procedure TNearestTool.PaintHint;
var x : Integer;
y : Integer;
R : TRect;
P : TFourPoints;
tmpZ : Integer;
begin
if Assigned(Series) and (Point<>-1) and (Series.Count>Point) then // 6.01
With ParentChart.Canvas do
begin
AssignVisiblePen(Self.Pen);
if not FullRepaint then Pen.Mode:=pmNotXor;
x:=Series.CalcXPos(Point);
y:=Series.CalcYPos(Point);
if Series.HasZValues then // 7.0
tmpZ:=ZAxisCalc(Series.GetYValueList('Z').Value[Point])
else
tmpZ:=Series.StartZ;
if Self.Style<>hsNone then
begin
AssignBrush(Self.Brush,clBlack);
Case Self.Style of
hsCircle: if ParentChart.View3D then
EllipseWithZ(x-FSize,y-FSize,x+FSize,y+FSize,tmpZ)
else
Ellipse(x-FSize,y-FSize,x+FSize,y+FSize);
hsRectangle: begin
R:=TeeRect(x-FSize,y-FSize,x+FSize,y+FSize);
if ParentChart.View3D then RectangleWithZ(R,tmpZ)
else Rectangle(R);
end;
hsDiamond: begin
P[0]:=T
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -