The ZoomIn & ZoomOut do not work as described in the remarks and IMHO do not work in an intuitive manner. I would expect zooming in (or out) on a point to keep the same point under the cursor after the zoom but this is not the case, the zoom generally jumps back to the top left corner of the diagram.
I have a fix for this that I hope can be incorporated into the core atDiagram.pas:
procedure TatDiagram.ZoomIn(ARect: TSquare);
var
hc, wc: number;
r1, r2: double;
Clicked: boolean;
c: integer;
RelPosn, ClickDot : TDot;
begin
Clicked := AroundPoint(ARect.TopLeft, ARect.BottomRight, 10);
wc := ClientWidth - FLeftRuler.VisibleSize;
hc := ClientHeight - FTopRuler.VisibleSize;
ClickDot.X := (ARect.Right + ARect.Left) / 2;
ClickDot.Y := (ARect.Bottom + ARect.Top) / 2;
ClickDot := ClientToCanvas(ClickDot);
RelPosn.X := (ClickDot.x + HorzScrollBar.Position) / HorzScrollBar.range;
RelPosn.Y := (ClickDot.y + VertScrollBar.Position) / VertScrollBar.range;
if Clicked then
begin
c := 0;
while (c < MaxZoomRatios - 1) and (FZoomRatio >= ZoomRatios[c]) do
inc(c);
FZoomRatio := ZoomRatios[c];
end
else
begin
r1 := wc / (ARect.Right - ARect.left);
r2 := hc / (ARect.Bottom - ARect.top);
if r1 < r2 then
FZoomRatio := r1
else
FZoomRatio := r2;
end;
if FZoomRatio < 0.01 then
FZoomRatio := 0.01;
if FZoomRatio > 10 then
FZoomRatio := 10;
FTopRuler.Zoom := Trunc(ZoomRatio * 100);
FLeftRuler.Zoom := FTopRuler.Zoom;
CalcPanelSize;
HorzScrollBar.Position := round((HorzScrollBar.Range * RelPosn.X) - ClickDot.x);
VertScrollBar.Position := round((VertScrollBar.Range * RelPosn.Y) - ClickDot.y);
UpdateScrollBars;
end;
procedure TatDiagram.ZoomOut(ARect: TSquare);
var
hc, wc: number;
r1, r2: double;
Clicked: boolean;
c: integer;
RelPosn, ClickDot : TDot;
begin
Clicked := AroundPoint(ARect.TopLeft, ARect.BottomRight, 10);
wc := ClientWidth - FLeftRuler.VisibleSize;
hc := ClientHeight - FTopRuler.VisibleSize;
ClickDot.X := (ARect.Right + ARect.Left) / 2;
ClickDot.Y := (ARect.Bottom + ARect.Top) / 2;
ClickDot := ClientToCanvas(ClickDot);
RelPosn.X := (ClickDot.x + HorzScrollBar.Position) / HorzScrollBar.range;
RelPosn.Y := (ClickDot.y + VertScrollBar.Position) / VertScrollBar.range;
if Clicked then
begin
c := MaxZoomRatios - 1;
while (c > 0) and (FZoomRatio <= ZoomRatios[c]) do
dec(c);
FZoomRatio := ZoomRatios[c];
end
else
begin
r1 := (ARect.Right - ARect.left) * FZoomratio / ClientWidth;
r2 := (ARect.Bottom - ARect.top) * FZoomRatio / ClientHeight;
if r1 < r2 then
r1 := r2;
FZoomratio := r1;
end;
if FZoomRatio < 0.01 then
FZoomRatio := 0.01;
if FZoomRatio > 10 then
FZoomRatio := 10;
FTopRuler.Zoom := Trunc(ZoomRatio * 100);
FLeftRuler.Zoom := FTopRuler.Zoom;
CalcPanelSize;
HorzScrollBar.Position := round((HorzScrollBar.Range * RelPosn.X) - ClickDot.x);
VertScrollBar.Position := round((VertScrollBar.Range * RelPosn.Y) - ClickDot.y);
UpdateScrollBars;
end;
I am sure there are lots of improvements that could be made, but the basic concept works correctly. Clicking on a point zooms in on that point, selecting an area zooms on the center of that area.