feat: F4.8c the documentation mode's image export, as Java's
ExportRun measures Java's print panel (GUIContainer.prepareExportPanel) and image on four projects and an empty one: 10 to spare around, a light grey footer 20 below the lowest element, 20 below it, a transparent background, the documentation painted as in the design. The sidebar gains Java's "Exportieren": the surface painted with Canvas 2D (an SVG with a foreignObject taints the canvas in WebKit) and saved under the project's name; Java's message when saving fails. Not adopted: Java's empty image of an empty project (its footer overflows). The editor takes a projectName; the capture export shares the download helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
// and „Gliederungsfläche“ with Java's icons. An item is dragged onto the
|
||||
// surface, where it lands with its middle under the pointer, as Java's does;
|
||||
// tapped, it lands in the middle of the view (Java's tap makes nothing).
|
||||
// „Exportieren“ saves the surface as an image (F4.8c); if that fails, Java's
|
||||
// „Fehler beim Speichern aufgetreten!“ shows below it.
|
||||
|
||||
import { useRef, useState, type CSSProperties } from 'react';
|
||||
import type { DocumentationItemKind } from '@mdg-filius/core';
|
||||
@@ -9,10 +11,13 @@ import { DRAG_THRESHOLD } from '../canvas/Canvas.js';
|
||||
import { useTranslate } from '../i18n/i18n.js';
|
||||
import addRectangle from '../assets/documentation/add_small.png';
|
||||
import addText from '../assets/documentation/add_text_small.png';
|
||||
import exportIcon from '../assets/documentation/download_small.png';
|
||||
|
||||
export interface DocumentationSidebarProps {
|
||||
/** An item dropped at a point of the screen, or tapped (no point). */
|
||||
readonly onItem: (kind: DocumentationItemKind, at: { readonly clientX: number; readonly clientY: number } | null) => void;
|
||||
/** „Exportieren“: the surface saved as an image; rejected, it failed. */
|
||||
readonly onExport: () => Promise<void>;
|
||||
}
|
||||
|
||||
const ITEMS: readonly { readonly kind: DocumentationItemKind; readonly icon: string; readonly label: string }[] = [
|
||||
@@ -39,12 +44,25 @@ const item: CSSProperties = {
|
||||
touchAction: 'none',
|
||||
};
|
||||
|
||||
export function DocumentationSidebar({ onItem }: DocumentationSidebarProps) {
|
||||
export function DocumentationSidebar({ onItem, onExport }: DocumentationSidebarProps) {
|
||||
const t = useTranslate();
|
||||
const [ghost, setGhost] = useState<{ kind: DocumentationItemKind; x: number; y: number } | null>(null);
|
||||
const press = useRef<{ kind: DocumentationItemKind; x: number; y: number; dragging: boolean } | null>(null);
|
||||
/** The click the browser sends after a drag ends on the button: not a tap. */
|
||||
const afterDrag = useRef(false);
|
||||
const [exporting, setExporting] = useState(false);
|
||||
const [failed, setFailed] = useState(false);
|
||||
const exportImage = () => {
|
||||
setExporting(true);
|
||||
setFailed(false);
|
||||
onExport().then(
|
||||
() => setExporting(false),
|
||||
() => {
|
||||
setExporting(false);
|
||||
setFailed(true);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const onPointerDown = (kind: DocumentationItemKind) => (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
press.current = { kind, x: event.clientX, y: event.clientY, dragging: false };
|
||||
@@ -106,6 +124,15 @@ export function DocumentationSidebar({ onItem }: DocumentationSidebarProps) {
|
||||
{t(each.label)}
|
||||
</button>
|
||||
))}
|
||||
<button type="button" style={{ ...item, cursor: exporting ? 'progress' : 'pointer' }} title={t('docu.exportHint')} disabled={exporting} onClick={exportImage}>
|
||||
<img src={exportIcon} alt="" width={40} height={40} draggable={false} />
|
||||
{t('docu.export')}
|
||||
</button>
|
||||
{failed ? (
|
||||
<p role="alert" style={{ margin: 0, fontSize: 12, color: 'var(--danger)' }}>
|
||||
{t('docu.saveFailed')}
|
||||
</p>
|
||||
) : null}
|
||||
{ghost === null ? null : (
|
||||
// The item's own size, its middle under the pointer, as Java drags it.
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user