9e147c6335
* Add text tool to IO * Remove unnecessary parentheses * Fix text objects always grouped * Remove log * Fix text objects hidden on back side * Implement text scaling * Add inverse text outline * Warn about IO notes with only text objects This will result in a different error message than the case where no objects are added at all though, and the user can bypass the warning. Maybe this is better to avoid discarding the user's work if they have spent some time adding text. * Add isValidType * Use matches! * Lock aspect ratio of text objects * Reword misleading comment The confusion probably comes from the Fabric docs, which apparently need updating: http://fabricjs.com/docs/fabric.Canvas.html#uniformScaling * Do not count text objects when calculating current index * Make text objects respond to size changes * Fix uniform scaling not working when editing * Use Arial font * Escape colons and unify parsing * Handle scale factor when restricting shape to view * Use 'cloned' * Add text background * Tweak drawShape's params
342 lines
9.4 KiB
Svelte
342 lines
9.4 KiB
Svelte
<!--
|
|
Copyright: Ankitects Pty Ltd and contributors
|
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
-->
|
|
<script>
|
|
import * as tr from "@tslib/ftl";
|
|
import DropdownItem from "components/DropdownItem.svelte";
|
|
import IconButton from "components/IconButton.svelte";
|
|
import Popover from "components/Popover.svelte";
|
|
import WithFloating from "components/WithFloating.svelte";
|
|
|
|
import { mdiEye, mdiFormatAlignCenter, mdiSquare, mdiViewDashboard } from "./icons";
|
|
import { hideAllGuessOne } from "./store";
|
|
import { drawEllipse, drawPolygon, drawRectangle, drawText } from "./tools/index";
|
|
import { makeMaskTransparent } from "./tools/lib";
|
|
import { enableSelectable, stopDraw } from "./tools/lib";
|
|
import {
|
|
alignTools,
|
|
deleteDuplicateTools,
|
|
groupUngroupTools,
|
|
zoomTools,
|
|
} from "./tools/more-tools";
|
|
import { tools } from "./tools/tool-buttons";
|
|
import { undoRedoTools, undoStack } from "./tools/tool-undo-redo";
|
|
|
|
export let canvas;
|
|
export let instance;
|
|
export let iconSize;
|
|
export let activeTool = "cursor";
|
|
let showAlignTools = false;
|
|
let leftPos = 82;
|
|
let maksOpacity = false;
|
|
let showFloating = false;
|
|
|
|
document.addEventListener("click", (event) => {
|
|
const upperCanvas = document.querySelector(".upper-canvas");
|
|
if (event.target == upperCanvas) {
|
|
showAlignTools = false;
|
|
}
|
|
});
|
|
|
|
// handle tool changes after initialization
|
|
$: if (instance && canvas) {
|
|
disableFunctions();
|
|
enableSelectable(canvas, true);
|
|
|
|
switch (activeTool) {
|
|
case "magnify":
|
|
enableSelectable(canvas, false);
|
|
instance.resume();
|
|
break;
|
|
case "draw-rectangle":
|
|
drawRectangle(canvas);
|
|
break;
|
|
case "draw-ellipse":
|
|
drawEllipse(canvas);
|
|
break;
|
|
case "draw-polygon":
|
|
drawPolygon(canvas, instance);
|
|
break;
|
|
case "draw-text":
|
|
drawText(canvas);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
const disableFunctions = () => {
|
|
instance.pause();
|
|
stopDraw(canvas);
|
|
canvas.selectionColor = "rgba(100, 100, 255, 0.3)";
|
|
};
|
|
|
|
const setOcclusionFieldForDesktop = () => {
|
|
const clist = document.body.classList;
|
|
if (
|
|
clist.contains("isLin") ||
|
|
clist.contains("isMac") ||
|
|
clist.contains("isWin")
|
|
) {
|
|
globalThis.setOcclusionFieldInner();
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<div class="tool-bar-container">
|
|
{#each tools as tool}
|
|
<IconButton
|
|
class="tool-icon-button {activeTool == tool.id ? 'active-tool' : ''}"
|
|
{iconSize}
|
|
active={activeTool === tool.id}
|
|
on:click={() => {
|
|
activeTool = tool.id;
|
|
}}
|
|
>
|
|
{@html tool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
</div>
|
|
|
|
<div class="top-tool-bar-container">
|
|
<div class="undo-redo-button" on:click={() => (showFloating = !showFloating)}>
|
|
<WithFloating
|
|
show={showFloating}
|
|
closeOnInsideClick
|
|
inline
|
|
style="line-height: unset !important"
|
|
on:close={() => (showFloating = false)}
|
|
>
|
|
<IconButton
|
|
class="top-tool-icon-button right-border-radius dropdown-tool-mode"
|
|
slot="reference"
|
|
{iconSize}
|
|
>
|
|
{#if $hideAllGuessOne}
|
|
{@html mdiViewDashboard}
|
|
{:else}
|
|
{@html mdiSquare}
|
|
{/if}
|
|
</IconButton>
|
|
|
|
<Popover slot="floating" --popover-padding-inline="0">
|
|
<DropdownItem
|
|
on:click={() => {
|
|
$hideAllGuessOne = true;
|
|
setOcclusionFieldForDesktop();
|
|
}}
|
|
>
|
|
<span>{tr.notetypesHideAllGuessOne()}</span>
|
|
</DropdownItem>
|
|
<DropdownItem
|
|
on:click={() => {
|
|
$hideAllGuessOne = false;
|
|
setOcclusionFieldForDesktop();
|
|
}}
|
|
>
|
|
<span>{tr.notetypesHideOneGuessOne()}</span>
|
|
</DropdownItem>
|
|
</Popover>
|
|
</WithFloating>
|
|
</div>
|
|
|
|
<!-- undo & redo tools -->
|
|
<div class="undo-redo-button">
|
|
{#each undoRedoTools as tool}
|
|
<IconButton
|
|
class="top-tool-icon-button {tool.name === 'undo'
|
|
? 'left-border-radius'
|
|
: 'right-border-radius'}"
|
|
{iconSize}
|
|
on:click={tool.action}
|
|
disabled={tool.name === "undo"
|
|
? !$undoStack.undoable
|
|
: !$undoStack.redoable}
|
|
>
|
|
{@html tool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
</div>
|
|
|
|
<!-- zoom tools -->
|
|
<div class="tool-button-container">
|
|
{#each zoomTools as tool}
|
|
<IconButton
|
|
class="top-tool-icon-button {tool.name === 'zoomOut'
|
|
? 'left-border-radius'
|
|
: ''} {tool.name === 'zoomReset' ? 'right-border-radius' : ''}"
|
|
{iconSize}
|
|
on:click={() => {
|
|
tool.action(instance);
|
|
}}
|
|
>
|
|
{@html tool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
</div>
|
|
|
|
<div class="tool-button-container">
|
|
<!-- opacity tools -->
|
|
<IconButton
|
|
class="top-tool-icon-button left-border-radius"
|
|
{iconSize}
|
|
on:click={() => {
|
|
maksOpacity = !maksOpacity;
|
|
makeMaskTransparent(canvas, maksOpacity);
|
|
}}
|
|
>
|
|
{@html mdiEye}
|
|
</IconButton>
|
|
|
|
<!-- cursor tools -->
|
|
{#each deleteDuplicateTools as tool}
|
|
<IconButton
|
|
class="top-tool-icon-button {tool.name === 'duplicate'
|
|
? 'right-border-radius'
|
|
: ''}"
|
|
{iconSize}
|
|
on:click={() => {
|
|
tool.action(canvas);
|
|
}}
|
|
>
|
|
{@html tool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
</div>
|
|
|
|
<div class="tool-button-container">
|
|
<!-- group & ungroup tools -->
|
|
{#each groupUngroupTools as tool}
|
|
<IconButton
|
|
class="top-tool-icon-button {tool.name === 'group'
|
|
? 'left-border-radius'
|
|
: ''}"
|
|
{iconSize}
|
|
on:click={() => {
|
|
tool.action(canvas);
|
|
}}
|
|
>
|
|
{@html tool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
|
|
<IconButton
|
|
class="top-tool-icon-button dropdown-tool right-border-radius"
|
|
{iconSize}
|
|
on:click={(e) => {
|
|
showAlignTools = !showAlignTools;
|
|
leftPos = e.pageX - 100;
|
|
}}
|
|
>
|
|
{@html mdiFormatAlignCenter}
|
|
</IconButton>
|
|
</div>
|
|
</div>
|
|
|
|
<div class:show={showAlignTools} class="dropdown-content" style="left:{leftPos}px;">
|
|
{#each alignTools as alignTool}
|
|
<IconButton
|
|
class="top-tool-icon-button"
|
|
{iconSize}
|
|
on:click={() => {
|
|
alignTool.action(canvas);
|
|
}}
|
|
>
|
|
{@html alignTool.icon}
|
|
</IconButton>
|
|
{/each}
|
|
</div>
|
|
|
|
<style>
|
|
.top-tool-bar-container {
|
|
display: flex;
|
|
overflow-y: scroll;
|
|
z-index: 99;
|
|
margin-left: 106px;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.undo-redo-button {
|
|
margin-right: 2px;
|
|
display: flex;
|
|
}
|
|
|
|
.tool-button-container {
|
|
margin-left: 2px;
|
|
margin-right: 2px;
|
|
display: flex;
|
|
}
|
|
|
|
:global(.left-border-radius) {
|
|
border-radius: 5px 0 0 5px !important;
|
|
}
|
|
|
|
:global(.right-border-radius) {
|
|
border-radius: 0 5px 5px 0 !important;
|
|
}
|
|
|
|
:global(.top-tool-icon-button) {
|
|
border: unset;
|
|
display: inline;
|
|
width: 32px;
|
|
height: 32px;
|
|
margin: unset;
|
|
padding: 6px !important;
|
|
font-size: 16px !important;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
z-index: 100;
|
|
top: 40px;
|
|
margin-top: 1px;
|
|
}
|
|
|
|
.show {
|
|
display: block;
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 0.1em !important;
|
|
height: 0.1em !important;
|
|
}
|
|
|
|
.tool-bar-container {
|
|
position: fixed;
|
|
top: 42px;
|
|
left: 2px;
|
|
height: 100%;
|
|
border-right: 1px solid var(--border);
|
|
overflow-y: auto;
|
|
width: 32px;
|
|
z-index: 99;
|
|
background: var(--canvas-elevated);
|
|
padding-bottom: 100px;
|
|
}
|
|
|
|
:global(.tool-icon-button) {
|
|
border: unset;
|
|
display: block;
|
|
width: 32px;
|
|
height: 32px;
|
|
margin: unset;
|
|
padding: 6px !important;
|
|
}
|
|
|
|
:global(.active-tool) {
|
|
color: white !important;
|
|
background: var(--button-primary-bg) !important;
|
|
}
|
|
|
|
:global(.icon-border-radius) {
|
|
border-radius: 5px !important;
|
|
}
|
|
|
|
:global(.dropdown-tool-mode) {
|
|
height: 38px !important;
|
|
display: inline;
|
|
}
|
|
</style>
|