feat: F4.8b the documentation mode in the editor
Java's third mode button, the sidebar's text and structure field (dropped with its middle under the pointer), items over the network that are moved, resized by Java's rule, typed into on their Y.Text, coloured and set in size and style from Java's menu, deleted; Java's paint per mode, measured in F4.8a. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// How the editor paints a documentation item, against the pixels Java's
|
||||
// JDocuElement paints (packages/doc/test/documentation.java.json, DocuRun):
|
||||
// a rectangle in the documentation mode and in the others, its border, the
|
||||
// text's border; the focused text's frame; where an edge is taken hold of.
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { edgesAt, fontFamily, holdFrame, rectangleBorder, rectangleFill, TEXT_BORDER, FOCUS_BORDER, FOCUS_BAND, textColor } from '../src/canvas/documentationPaint.js';
|
||||
|
||||
type Rgba = [number, number, number, number];
|
||||
const java = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../doc/test/documentation.java.json'), 'utf8')) as {
|
||||
readonly painted: Record<string, Record<string, Rgba>>;
|
||||
readonly dropped: { readonly text: { readonly bounds: number[] }; readonly textUnfocused: { readonly bounds: number[] } };
|
||||
};
|
||||
const pink = { red: 1, green: 201 / 255, blue: 201 / 255, alpha: 1 };
|
||||
const css = ([red, green, blue, alpha]: Rgba) => (alpha === 255 ? `rgb(${red}, ${green}, ${blue})` : `rgba(${red}, ${green}, ${blue}, ${alpha / 255})`);
|
||||
|
||||
describe("Java's paint of the documentation", () => {
|
||||
it('fills a rectangle at an opacity of 200 in the documentation mode, else opaque and lighter; its border four fifths of its colour', () => {
|
||||
const { rectangleEnabled, rectangleDisabled, rectangleFocused, textEnabled, textDisabled } = java.painted;
|
||||
expect(rectangleFill(pink, true)).toBe(css(rectangleEnabled!['50,25']!));
|
||||
expect(rectangleFill(pink, false)).toBe(css(rectangleDisabled!['50,25']!));
|
||||
expect(rectangleBorder(pink)).toBe(css(rectangleEnabled!['1,25']!));
|
||||
expect(rectangleBorder(pink)).toBe(css(rectangleDisabled!['1,25']!));
|
||||
// The focus: Java's blue border and translucent band (its alpha 77 of 255 is 0.3).
|
||||
expect(FOCUS_BORDER).toBe(css(rectangleFocused!['1,25']!));
|
||||
const [red, green, blue, alpha] = rectangleFocused!['3,25']!;
|
||||
expect(FOCUS_BAND).toBe(`rgba(${red}, ${green}, ${blue}, ${Math.round((alpha / 255) * 10) / 10})`);
|
||||
// A text's border only in the documentation mode.
|
||||
expect(TEXT_BORDER).toBe(css(textEnabled!['0,25']!));
|
||||
expect(textDisabled!['0,25']![3]).toBe(0);
|
||||
// Java's integer arithmetic: 255 + (c − 255) · 8 / 10 cut towards zero, c · 4 / 5 cut.
|
||||
expect(rectangleFill({ red: 0, green: 1, blue: 7 / 255, alpha: 1 }, false)).toBe('rgb(51, 255, 57)');
|
||||
expect(rectangleBorder({ red: 0, green: 1, blue: 7 / 255, alpha: 1 })).toBe('rgb(0, 204, 5)');
|
||||
// Where rounding would differ: (3 − 255) · 8 / 10 = −201.6 is −201 in Java; 3 · 4 / 5 = 2.4 is 2, 254 · 4 / 5 = 203.2 is 203.
|
||||
expect(rectangleFill({ red: 3 / 255, green: 254 / 255, blue: 1, alpha: 1 }, false)).toBe('rgb(54, 255, 255)');
|
||||
expect(rectangleBorder({ red: 3 / 255, green: 254 / 255, blue: 4 / 255, alpha: 1 })).toBe('rgb(2, 203, 3)');
|
||||
expect(textColor({ red: 0, green: 0, blue: 1, alpha: 0.5 })).toBe('rgba(0, 0, 255, 0.5)');
|
||||
});
|
||||
|
||||
it("grows a focused text's frame as Java does, and finds the edges a drag takes", () => {
|
||||
const [x, y, width, height] = java.dropped.textUnfocused.bounds as [number, number, number, number];
|
||||
const [fx, fy, fw, fh] = java.dropped.text.bounds as [number, number, number, number];
|
||||
expect(holdFrame({ kind: 'text', x, y, width, height }, true)).toEqual({ x: fx, y: fy, width: fw, height: fh });
|
||||
expect(holdFrame({ kind: 'text', x, y, width, height }, false)).toEqual({ kind: 'text', x, y, width, height });
|
||||
expect(holdFrame({ kind: 'rectangle', x, y, width, height }, true)).toEqual({ kind: 'rectangle', x, y, width, height });
|
||||
const frame = { x: 0, y: 0, width: 100, height: 50 };
|
||||
expect(edgesAt(frame, { x: 50, y: 25 }, 7)).toEqual({ left: false, right: false, top: false, bottom: false });
|
||||
expect(edgesAt(frame, { x: 7, y: 25 }, 7)).toEqual({ left: true, right: false, top: false, bottom: false });
|
||||
expect(edgesAt(frame, { x: 93, y: 49 }, 7)).toEqual({ left: false, right: true, top: false, bottom: true });
|
||||
expect(edgesAt(frame, { x: 92, y: 8 }, 7)).toEqual({ left: false, right: false, top: false, bottom: false });
|
||||
expect(edgesAt(frame, { x: 3, y: 3 }, 7)).toEqual({ left: true, right: false, top: true, bottom: false });
|
||||
// Narrower than two bands: both edges, of which the drag takes the left (resizedFrame).
|
||||
expect(edgesAt({ x: 0, y: 0, width: 10, height: 10 }, { x: 5, y: 5 }, 7)).toEqual({ left: true, right: true, top: true, bottom: true });
|
||||
});
|
||||
|
||||
it("writes Java's logical fonts as the browser's", () => {
|
||||
expect(['Dialog', 'SansSerif', 'Serif', 'Monospaced', 'DialogInput', 'Comic "Neue"'].map(fontFamily)).toEqual([
|
||||
'sans-serif',
|
||||
'sans-serif',
|
||||
'serif',
|
||||
'monospace',
|
||||
'monospace',
|
||||
'"Comic Neue", sans-serif',
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -244,6 +244,18 @@ const FROM_JAVA: Readonly<Record<string, string>> = {
|
||||
'installation.apply': 'installationsdialog_msg2',
|
||||
'mode.currentSpeed': 'guimainmemu_msg15',
|
||||
'menu.showDesktop': 'guievents_msg3',
|
||||
'mode.documentation': 'guimainmemu_msg14',
|
||||
'docu.text': 'docusidebar_msg1',
|
||||
'docu.rectangle': 'docusidebar_msg3',
|
||||
'docu.fontSize': 'guievents_msg15',
|
||||
'docu.sizeNormal': 'guievents_msg16',
|
||||
'docu.sizeLarge': 'guievents_msg17',
|
||||
'docu.sizeVeryLarge': 'guievents_msg18',
|
||||
'docu.fontStyle': 'guievents_msg14',
|
||||
'docu.stylePlain': 'guievents_msg19',
|
||||
'docu.styleItalic': 'guievents_msg20',
|
||||
'docu.styleBold': 'guievents_msg21',
|
||||
'docu.color': 'guievents_msg13',
|
||||
'capture.title': 'lauscherdialog_msg1',
|
||||
'capture.number': 'rp_lauscher_msg1',
|
||||
'capture.time': 'rp_lauscher_msg2',
|
||||
|
||||
Reference in New Issue
Block a user