mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-22 19:46:39 +00:00
Positioning and logic fixes
This commit is contained in:
parent
5a24e00497
commit
03eda04aec
@ -43,7 +43,7 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
|
|||||||
// Convert PDF crop area to DOM coordinates for display
|
// Convert PDF crop area to DOM coordinates for display
|
||||||
const domRect = pdfToDOMCoordinates(cropArea, pdfBounds);
|
const domRect = pdfToDOMCoordinates(cropArea, pdfBounds);
|
||||||
|
|
||||||
// Handle mouse down on overlay (start dragging)
|
// Handle mouse down on overlay (start dragging or resizing)
|
||||||
const handleOverlayMouseDown = useCallback((e: React.MouseEvent) => {
|
const handleOverlayMouseDown = useCallback((e: React.MouseEvent) => {
|
||||||
if (disabled || !containerRef.current) return;
|
if (disabled || !containerRef.current) return;
|
||||||
|
|
||||||
@ -54,18 +54,18 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
|
|||||||
const x = e.clientX - rect.left;
|
const x = e.clientX - rect.left;
|
||||||
const y = e.clientY - rect.top;
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
// Check if we're clicking on a resize handle
|
// Check if we're clicking on a resize handle first (higher priority)
|
||||||
const handle = getResizeHandle(x, y, domRect);
|
const handle = getResizeHandle(x, y, domRect);
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
setIsResizing(handle);
|
setIsResizing(handle);
|
||||||
setInitialCropArea(cropArea);
|
setInitialCropArea(cropArea);
|
||||||
} else {
|
setIsDragging(false); // Ensure we're not dragging when resizing
|
||||||
// Check if we're clicking within the crop area for dragging
|
} else if (isPointInCropArea(x, y, domRect)) {
|
||||||
if (isPointInCropArea(x, y, domRect)) {
|
// Only allow dragging if we're not on a resize handle
|
||||||
setIsDragging(true);
|
setIsDragging(true);
|
||||||
setDragStart({ x: x - domRect.x, y: y - domRect.y });
|
setIsResizing(null); // Ensure we're not resizing when dragging
|
||||||
}
|
setDragStart({ x: x - domRect.x, y: y - domRect.y });
|
||||||
}
|
}
|
||||||
}, [disabled, cropArea, domRect]);
|
}, [disabled, cropArea, domRect]);
|
||||||
|
|
||||||
@ -211,15 +211,15 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
|
|||||||
|
|
||||||
function getResizeHandle(x: number, y: number, domRect: DOMRect): ResizeHandle {
|
function getResizeHandle(x: number, y: number, domRect: DOMRect): ResizeHandle {
|
||||||
const handleSize = 8;
|
const handleSize = 8;
|
||||||
const tolerance = 4;
|
const tolerance = handleSize;
|
||||||
|
|
||||||
// Corner handles
|
// Corner handles (check these first, they have priority)
|
||||||
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y, tolerance)) return 'nw';
|
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y, tolerance)) return 'nw';
|
||||||
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y, tolerance)) return 'ne';
|
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y, tolerance)) return 'ne';
|
||||||
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'sw';
|
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'sw';
|
||||||
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'se';
|
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'se';
|
||||||
|
|
||||||
// Edge handles
|
// Edge handles (only if not in corner area)
|
||||||
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y, tolerance)) return 'n';
|
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y, tolerance)) return 'n';
|
||||||
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height / 2, tolerance)) return 'e';
|
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height / 2, tolerance)) return 'e';
|
||||||
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 's';
|
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 's';
|
||||||
|
@ -1,28 +1,24 @@
|
|||||||
import React, { useMemo, useState, useEffect } from "react";
|
import { useMemo, useState, useEffect } from "react";
|
||||||
import { Stack, Text, Box, Group, NumberInput, ActionIcon, Center, Alert } from "@mantine/core";
|
import { Stack, Text, Box, Group, NumberInput, ActionIcon, Center, Alert } from "@mantine/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import RestartAltIcon from "@mui/icons-material/RestartAlt";
|
import RestartAltIcon from "@mui/icons-material/RestartAlt";
|
||||||
import InfoIcon from "@mui/icons-material/Info";
|
|
||||||
import { CropParametersHook } from "../../../hooks/tools/crop/useCropParameters";
|
import { CropParametersHook } from "../../../hooks/tools/crop/useCropParameters";
|
||||||
import { useSelectedFiles } from "../../../contexts/file/fileHooks";
|
import { useSelectedFiles } from "../../../contexts/file/fileHooks";
|
||||||
import { useFileContext } from "../../../contexts/FileContext";
|
|
||||||
import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail";
|
|
||||||
import CropAreaSelector from "./CropAreaSelector";
|
import CropAreaSelector from "./CropAreaSelector";
|
||||||
import {
|
import {
|
||||||
calculatePDFBounds,
|
calculatePDFBounds,
|
||||||
PDFBounds,
|
PDFBounds,
|
||||||
CropArea,
|
CropArea
|
||||||
getPDFAspectRatio,
|
|
||||||
createFullPDFCropArea
|
|
||||||
} from "../../../utils/cropCoordinates";
|
} from "../../../utils/cropCoordinates";
|
||||||
import { pdfWorkerManager } from "../../../services/pdfWorkerManager";
|
import { pdfWorkerManager } from "../../../services/pdfWorkerManager";
|
||||||
|
import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail";
|
||||||
|
|
||||||
interface CropSettingsProps {
|
interface CropSettingsProps {
|
||||||
parameters: CropParametersHook;
|
parameters: CropParametersHook;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONTAINER_SIZE = 400; // Larger container for better crop precision
|
const CONTAINER_SIZE = 250; // Fit within actual pane width
|
||||||
|
|
||||||
const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -41,7 +37,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
// Get thumbnail for the selected file
|
// Get thumbnail for the selected file
|
||||||
const [thumbnail, setThumbnail] = useState<string | null>(null);
|
const [thumbnail, setThumbnail] = useState<string | null>(null);
|
||||||
const [pdfBounds, setPdfBounds] = useState<PDFBounds | null>(null);
|
const [pdfBounds, setPdfBounds] = useState<PDFBounds | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadPDFDimensions = async () => {
|
const loadPDFDimensions = async () => {
|
||||||
@ -52,7 +47,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setThumbnail(selectedStub.thumbnailUrl || null);
|
setThumbnail(selectedStub.thumbnailUrl || null);
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get PDF dimensions from the actual file
|
// Get PDF dimensions from the actual file
|
||||||
@ -95,8 +89,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
if (parameters.parameters.width === 595 && parameters.parameters.height === 842) {
|
if (parameters.parameters.width === 595 && parameters.parameters.height === 842) {
|
||||||
parameters.resetToFullPDF(bounds);
|
parameters.resetToFullPDF(bounds);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +98,7 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
// Current crop area
|
// Current crop area
|
||||||
const cropArea = parameters.getCropArea();
|
const cropArea = parameters.getCropArea();
|
||||||
|
|
||||||
|
|
||||||
// Handle crop area changes from the selector
|
// Handle crop area changes from the selector
|
||||||
const handleCropAreaChange = (newCropArea: CropArea) => {
|
const handleCropAreaChange = (newCropArea: CropArea) => {
|
||||||
if (pdfBounds) {
|
if (pdfBounds) {
|
||||||
@ -139,19 +132,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
return Math.round((cropAreaSize / totalArea) * 100);
|
return Math.round((cropAreaSize / totalArea) * 100);
|
||||||
}, [cropArea, pdfBounds]);
|
}, [cropArea, pdfBounds]);
|
||||||
|
|
||||||
// Get aspect ratio information
|
|
||||||
const aspectRatioInfo = useMemo(() => {
|
|
||||||
if (!pdfBounds) return null;
|
|
||||||
const pdfRatio = getPDFAspectRatio(pdfBounds);
|
|
||||||
const cropRatio = cropArea.width / cropArea.height;
|
|
||||||
|
|
||||||
return {
|
|
||||||
pdf: pdfRatio.toFixed(2),
|
|
||||||
crop: cropRatio.toFixed(2),
|
|
||||||
orientation: pdfRatio > 1 ? 'Landscape' : 'Portrait'
|
|
||||||
};
|
|
||||||
}, [pdfBounds, cropArea]);
|
|
||||||
|
|
||||||
if (!selectedStub || !pdfBounds) {
|
if (!selectedStub || !pdfBounds) {
|
||||||
return (
|
return (
|
||||||
<Center style={{ height: '200px' }}>
|
<Center style={{ height: '200px' }}>
|
||||||
@ -222,14 +202,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
<Text size="xs" color="dimmed">
|
<Text size="xs" color="dimmed">
|
||||||
{t("crop.info.percentage", "Area: {{percentage}}%", { percentage: cropPercentage })}
|
{t("crop.info.percentage", "Area: {{percentage}}%", { percentage: cropPercentage })}
|
||||||
</Text>
|
</Text>
|
||||||
{aspectRatioInfo && (
|
|
||||||
<Text size="xs" color="dimmed">
|
|
||||||
{t("crop.info.ratio", "Ratio: {{ratio}} ({{orientation}})", {
|
|
||||||
ratio: aspectRatioInfo.crop,
|
|
||||||
orientation: parseFloat(aspectRatioInfo.crop) > 1 ? 'Landscape' : 'Portrait'
|
|
||||||
})}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
@ -289,28 +261,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
|
|||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
{/* PDF Dimensions Info */}
|
|
||||||
<Alert
|
|
||||||
icon={<InfoIcon />}
|
|
||||||
color="blue"
|
|
||||||
variant="light"
|
|
||||||
style={{ fontSize: '0.75rem' }}
|
|
||||||
>
|
|
||||||
<Text size="xs">
|
|
||||||
{t("crop.info.pdfDimensions", "PDF Size: {{width}} × {{height}} points", {
|
|
||||||
width: Math.round(pdfBounds.actualWidth),
|
|
||||||
height: Math.round(pdfBounds.actualHeight)
|
|
||||||
})}
|
|
||||||
</Text>
|
|
||||||
{aspectRatioInfo && (
|
|
||||||
<Text size="xs">
|
|
||||||
{t("crop.info.aspectRatio", "Aspect Ratio: {{ratio}} ({{orientation}})", {
|
|
||||||
ratio: aspectRatioInfo.pdf,
|
|
||||||
orientation: aspectRatioInfo.orientation
|
|
||||||
})}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Alert>
|
|
||||||
|
|
||||||
{/* Validation Alert */}
|
{/* Validation Alert */}
|
||||||
{!isCropValid && (
|
{!isCropValid && (
|
||||||
|
@ -59,7 +59,7 @@ export const calculatePDFBounds = (
|
|||||||
const thumbnailWidth = actualPDFWidth * scale;
|
const thumbnailWidth = actualPDFWidth * scale;
|
||||||
const thumbnailHeight = actualPDFHeight * scale;
|
const thumbnailHeight = actualPDFHeight * scale;
|
||||||
|
|
||||||
// Calculate centering offsets
|
// Calculate centering offsets - these represent where the thumbnail is positioned within the container
|
||||||
const offsetX = (containerWidth - thumbnailWidth) / 2;
|
const offsetX = (containerWidth - thumbnailWidth) / 2;
|
||||||
const offsetY = (containerHeight - thumbnailHeight) / 2;
|
const offsetY = (containerHeight - thumbnailHeight) / 2;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user