Skip to content

Scale to percentage #377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Side menu for stitch, layers, and scale menus
- Scale menu for changing the pattern scale
- Scale menu for changing the pattern scale (modified to use percentage instead of decimal)
- "Open With Pattern Projector" for PDF files on desktop, when installed with Chrome/Edge
- Show a pop up when there's an error
- Change page range in stitch menu with +/- (use + to throw beginning pages at the end e.g. for instruction pages)
- Option to arrange stitched pages by column order
- Support for SVG (with layer visibility toggling), PNG, and JPEG
- Modified open pdf message slightly to add styling

### Changed

Expand Down
10 changes: 7 additions & 3 deletions app/[locale]/calibrate/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import { Button } from "@/_components/buttons/button";
import { erosionFilter } from "@/_lib/erode";
import SvgViewer from "@/_components/svg-viewer";
import { toggleFullScreen } from "@/_lib/full-screen";
import ModifiersBanner from "@/_components/modifiers-banner";

const defaultStitchSettings = {
lineCount: 1,
Expand Down Expand Up @@ -296,7 +297,7 @@ export default function Page() {
setMeasuring(false);
setPageCount(0);
setLayers({});
dispatchPatternScaleAction({ type: "set", scale: "1.00" });
dispatchPatternScaleAction({ type: "set", scale: "1.000" });
const lineThicknessString = localStorage.getItem(
`lineThickness:${files[0].name}`,
);
Expand Down Expand Up @@ -698,15 +699,16 @@ export default function Page() {
zoomedOut={zoomedOut}
magnifying={magnifying}
restoreTransforms={restoreTransforms}
patternScale={String(patternScaleFactor)}
// patternScale={String(patternScaleFactor)}
/>
</MeasureCanvas>

<menu
className={`absolute w-screen ${visible(!menusHidden)} ${menuStates.nav ? "top-0" : "-top-16"} pointer-events-none`}
className={`absolute w-screen ${menuStates.nav ? "top-0" : "-top-16"} pointer-events-none`}
>
<menu className="pointer-events-auto">
<Header
hidden={menusHidden}
isCalibrating={isCalibrating}
setIsCalibrating={setIsCalibrating}
widthInput={widthInput}
Expand Down Expand Up @@ -779,10 +781,12 @@ export default function Page() {
/>
)}
<MailModal open={mailOpen} setOpen={setMailOpen} />
<ModifiersBanner patternScale={patternScaleFactor} />
</menu>

{!isCalibrating && file !== null && (
<SideMenu
hidden={menusHidden}
menuStates={menuStates}
setMenuStates={setMenuStates}
pageCount={pageCount}
Expand Down
39 changes: 39 additions & 0 deletions app/[locale]/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,45 @@
.scrollbar::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}

/**
* Buttons ========================
*/

/* Button base classes */
.btn-outline {
@apply flex gap-2 dark:bg-black bg-white items-center border-2 border-solid focus:outline-none font-medium rounded-lg text-sm px-5 py-2.5 text-center;
}

.btn {
@apply flex gap-2 items-center text-white font-medium rounded-lg text-sm px-5 py-2.5;
}

/* Primary color button */
.btn-primary-static-outline {
@apply btn-outline text-purple-700 border-purple-700 dark:border-purple-500 dark:text-purple-500;
}

.btn-primary-static {
@apply btn bg-purple-700 dark:bg-purple-600;
}

.btn-primary-outline {
@apply btn-primary-static-outline hover:bg-purple-800 focus:ring-purple-300 dark:hover:bg-purple-500 dark:focus:ring-purple-800;
}

.btn-primary {
@apply btn-primary-static hover:bg-purple-800 focus:ring-purple-300 dark:hover:bg-purple-700 dark:focus:ring-purple-800;
}

/* Secondary color button */
.btn-secondary-outline-static {
@apply text-blue-700 border-blue-700 dark:border-blue-500 dark:text-blue-500;
}

.btn-secondary-static {
@apply bg-blue-700 dark:bg-blue-600;
}
}

/* Do not display PDF Links https://github.com/Pattern-Projector/pattern-projector/issues/260 */
Expand Down
1 change: 0 additions & 1 deletion app/_components/canvases/calibration-canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export default function CalibrationCanvas({
false,
null,
null,
null,
);
draw(cs);
}
Expand Down
4 changes: 0 additions & 4 deletions app/_components/canvases/overlay-canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export default function OverlayCanvas({
zoomedOut,
magnifying,
restoreTransforms,
patternScale,
}: {
className: string | undefined;
points: Point[];
Expand All @@ -34,7 +33,6 @@ export default function OverlayCanvas({
zoomedOut: boolean;
magnifying: boolean;
restoreTransforms: RestoreTransforms | null;
patternScale: string;
}) {
const flipped = isFlipped(useTransformContext());
const canvasRef = useRef<HTMLCanvasElement | null>(null);
Expand Down Expand Up @@ -74,7 +72,6 @@ export default function OverlayCanvas({
magnifying,
restoreTransforms,
t,
patternScale,
);
drawOverlays(cs);
}
Expand All @@ -91,7 +88,6 @@ export default function OverlayCanvas({
magnifying,
restoreTransforms,
t,
patternScale,
]);
return (
<canvas
Expand Down
4 changes: 3 additions & 1 deletion app/_components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import { acceptedMimeTypes } from "@/_lib/is-valid-file";
import { toggleFullScreen } from "@/_lib/full-screen";

export default function Header({
hidden,
isCalibrating,
setIsCalibrating,
widthInput,
Expand Down Expand Up @@ -109,6 +110,7 @@ export default function Header({
invalidCalibration,
file,
}: {
hidden: boolean;
isCalibrating: boolean;
setIsCalibrating: Dispatch<SetStateAction<boolean>>;
widthInput: string;
Expand Down Expand Up @@ -370,7 +372,7 @@ export default function Header({
</ModalActions>
</Modal>
<header
className={`relative z-10 bg-opacity-60 dark:bg-opacity-50 bg-white dark:bg-black left-0 w-full border-b dark:border-gray-700 transition-all duration-500 h-16 flex items-center ${menuStates.nav ? "translate-y-0" : "-translate-y-16"}`}
className={`relative ${visible(!hidden)} z-10 bg-opacity-60 dark:bg-opacity-50 bg-white dark:bg-black left-0 w-full border-b dark:border-gray-700 transition-all duration-500 h-16 flex items-center ${menuStates.nav ? "translate-y-0" : "-translate-y-16"}`}
>
<nav
className="mx-auto flex max-w-7xl items-center justify-between p-2 lg:px-8 w-full"
Expand Down
19 changes: 15 additions & 4 deletions app/_components/menus/scale-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import StepperInput from "@/_components/stepper-input";
import { Dispatch } from "react";
import removeNonDigits from "@/_lib/remove-non-digits";
import { Dispatch, useMemo } from "react";
import { useTranslations } from "next-intl";
import { PatternScaleAction } from "@/_reducers/patternScaleReducer";
import { sideMenuStyles } from "../theme/styles";
import removeNonDigits, {
decimalToString,
roundTo,
} from "@/_lib/remove-non-digits";

export default function ScaleMenu({
patternScale,
Expand All @@ -14,6 +17,14 @@ export default function ScaleMenu({
}) {
const t = useTranslations("ScaleMenu");

const scaleValue: string = useMemo(() => {
const number = +patternScale;
if (Number.isNaN(number)) {
return "1";
}
return patternScale;
}, [patternScale]);

return (
<menu className={`${sideMenuStyles}`}>
<StepperInput
Expand All @@ -25,11 +36,11 @@ export default function ScaleMenu({
})
}
label={t("scale")}
value={patternScale}
value={scaleValue}
onStep={(delta) =>
dispatchPatternScaleAction({ type: "delta", delta: delta })
}
step={0.1}
step={0.05}
></StepperInput>
</menu>
);
Expand Down
5 changes: 4 additions & 1 deletion app/_components/menus/side-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import { StitchSettings } from "@/_lib/interfaces/stitch-settings";
import { LayerAction } from "@/_reducers/layersReducer";
import { PatternScaleAction } from "@/_reducers/patternScaleReducer";
import TuneIcon from "@/_icons/tune-icon";
import { visible } from "@/_components/theme/css-functions";

export default function SideMenu({
hidden,
menuStates,
setMenuStates,
pageCount,
Expand All @@ -31,6 +33,7 @@ export default function SideMenu({
patternScale,
dispatchPatternScaleAction,
}: {
hidden: boolean;
menuStates: MenuStates;
setMenuStates: Dispatch<SetStateAction<MenuStates>>;
pageCount: number;
Expand All @@ -51,7 +54,7 @@ export default function SideMenu({
pageCount === 0 || file?.name.toLocaleUpperCase().endsWith(".SVG");

return (
<menu className="pointer-events-auto flex w-fit">
<menu className={`pointer-events-auto flex w-fit ${visible(!hidden)}`}>
{/* reverse so the tooltips show on top */}
<menu className="w-16 flex flex-col-reverse justify-end gap-2 p-2 bg-opacity-60 dark:bg-opacity-50 bg-white dark:bg-black left-0 border-b border-r dark:border-gray-700 transition-all duration-500">
<Tooltip description={menuStates.scale ? sc("hide") : sc("show")}>
Expand Down
35 changes: 35 additions & 0 deletions app/_components/modifiers-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useMemo } from "react";
import { visible } from "@/_components/theme/css-functions";
import { decimalToString } from "@/_lib/remove-non-digits";
import { useTranslations } from "next-intl";

export default function ModifiersBanner({
patternScale,
}: {
patternScale?: number;
}) {
const t = useTranslations("OverlayCanvas");
const hidden = useMemo(() => {
if (!patternScale || patternScale === 1) {
return true;
}
return false;
}, [patternScale]);

const text = useMemo(() => {
if (patternScale && patternScale !== 1) {
return t.rich("scaled", {
scale: () => decimalToString(patternScale, 2),
scaleP: () => decimalToString(patternScale * 100, 1),
});
}
}, [patternScale]);

return (
<div
className={`${visible(!hidden)} h-6 bg-amber-700 w-full text-center font-bold opacity-80`}
>
{text}
</div>
);
}
21 changes: 19 additions & 2 deletions app/_components/pdf-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import { getLayersFromPdf, Layers } from "@/_lib/layers";
import { LoadStatusEnum } from "@/_lib/load-status-enum";
import { Point } from "@/_lib/point";
import { useTranslations } from "next-intl";
import { MenuStates, getDefaultMenuStates } from "@/_lib/menu-states";
import { getDefaultMenuStates, MenuStates } from "@/_lib/menu-states";
import PdfIcon from "@/_icons/pdf-icon";

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
"pdfjs-dist/build/pdf.worker.min.js",
Expand Down Expand Up @@ -75,6 +76,7 @@ export default function PdfViewer({
);
const transformer = useTransformerContext();
const t = useTranslations("PdfViewer");
const h = useTranslations("Header");

function onDocumentLoadSuccess(docProxy: PDFDocumentProxy) {
const numPages = docProxy.numPages;
Expand Down Expand Up @@ -170,7 +172,22 @@ export default function PdfViewer({
<Document
file={file}
onLoadSuccess={onDocumentLoadSuccess}
noData={<p className="text-9xl">{t("noData")}</p>}
noData={
<div className="text-9xl text-center w-full border-gray-400 leading-[1.3] px-6 py-3">
<span>{t("noDataFirst")}</span>
<div className="flex w-full align-middle justify-center">
<div className="flex items-center gap-2 scale-[4] m-16">
<label
className={`flex gap-2 items-center btn-primary-static-outline !py-1.5 !px-3`}
>
<PdfIcon ariaLabel={h("openPDF")} fill="currentColor" />
<span className="hidden md:flex">{h("openPDF")}</span>
</label>
</div>
</div>
<span>{t("noDataLast")}</span>
</div>
}
error={<p className="text-9xl">{t("error")}</p>}
onLoadError={() => setFileLoadStatus(LoadStatusEnum.FAILED)}
>
Expand Down
4 changes: 2 additions & 2 deletions app/_components/theme/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export function getColorClasses(
}
case ButtonColor.PURPLE: {
return style === ButtonStyle.OUTLINE
? "text-purple-700 border-purple-700 hover:bg-purple-800 focus:ring-purple-300 dark:border-purple-500 dark:text-purple-500 dark:hover:bg-purple-500 dark:focus:ring-purple-800"
: "bg-purple-700 hover:bg-purple-800 focus:ring-purple-300 dark:bg-purple-600 dark:hover:bg-purple-700 dark:focus:ring-purple-800";
? "btn-primary-outline"
: "btn-primary";
}
}
}
6 changes: 6 additions & 0 deletions app/_components/theme/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ export function getButtonStyleClasses(style: ButtonStyle) {
: `flex gap-2 items-center text-white focus:ring-4 font-medium rounded-lg text-sm px-5 py-2.5 focus:outline-none`;
}

export function getStaticButtonStyleClasses(style: ButtonStyle) {
return style === ButtonStyle.OUTLINE
? `flex gap-2 dark:bg-black bg-white items-center border border-2 border-solid focus:outline-none font-medium rounded-lg text-sm px-5 py-2.5 text-center`
: `flex gap-2 items-center text-white font-medium rounded-lg text-sm px-5 py-2.5`;
}

export const sideMenuStyles = `flex flex-col gap-2 p-2 w-64 items-start bg-white dark:bg-black border-b border-r border-gray-200 dark:border-gray-700`;
28 changes: 10 additions & 18 deletions app/_lib/drawing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export class CanvasState {
public magnifying: boolean,
public restoreTransforms: RestoreTransforms | null,
public t: any,
public patternScale: string | null,
) {
this.isConcave = checkIsConcave(this.points);
}
Expand Down Expand Up @@ -113,15 +112,8 @@ export function drawPolygon(
}

export function drawOverlays(cs: CanvasState) {
const {
ctx,
displaySettings,
zoomedOut,
t,
magnifying,
restoreTransforms,
patternScale,
} = cs;
const { ctx, displaySettings, zoomedOut, t, magnifying, restoreTransforms } =
cs;
const { grid, border, paper, flipLines, flippedPattern, disabled } =
displaySettings.overlay;
const { theme } = displaySettings;
Expand Down Expand Up @@ -153,14 +145,14 @@ export function drawOverlays(cs: CanvasState) {
if (flippedPattern && cs.isFlipped) {
drawFlippedPattern(cs);
}
if (patternScale && Number(patternScale) !== 1) {
drawMessage(
cs,
t.rich("scaled", {
scale: () => String(Number(patternScale).toFixed(2)),
}),
);
}
// if (patternScale && Number(patternScale) !== 1) {
// drawMessage(
// cs,
// t.rich("scaled", {
// scale: () => String(Number(patternScale).toFixed(2)),
// }),
// );
// }
}
}

Expand Down
Loading