mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 10:58:04 +08:00
Add embedable images (#564)
* Add embedable bitmaps * Initial work on blob urls * Finish implementing data url * Fix some bugs * Rename bitmap to image * Fix loading image on document load * Add transform properties for image * Remove some logging * Add image dimensions * Implement system copy and paste * Fix pasting images * Fix test * Address code review Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
parent
0ee492a857
commit
51c31f042b
@@ -75,9 +75,23 @@
|
||||
<CanvasRuler :origin="rulerOrigin.y" :majorMarkSpacing="rulerSpacing" :numberInterval="rulerInterval" :direction="'Vertical'" ref="rulerVertical" />
|
||||
</LayoutCol>
|
||||
<LayoutCol class="canvas-area">
|
||||
<div class="canvas" data-canvas ref="canvas" :style="{ cursor: canvasCursor }" @pointerdown="(e: PointerEvent) => canvasPointerDown(e)">
|
||||
<div
|
||||
class="canvas"
|
||||
data-canvas
|
||||
ref="canvas"
|
||||
:style="{ cursor: canvasCursor }"
|
||||
@pointerdown="(e: PointerEvent) => canvasPointerDown(e)"
|
||||
@dragover="(e) => e.preventDefault()"
|
||||
@drop="(e) => pasteFile(e)"
|
||||
>
|
||||
<svg class="artboards" v-html="artboardSvg" :style="{ width: canvasSvgWidth, height: canvasSvgHeight }"></svg>
|
||||
<svg class="artwork" v-html="artworkSvg" :style="{ width: canvasSvgWidth, height: canvasSvgHeight }"></svg>
|
||||
<svg
|
||||
class="artwork"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
v-html="artworkSvg"
|
||||
:style="{ width: canvasSvgWidth, height: canvasSvgHeight }"
|
||||
></svg>
|
||||
<svg class="overlays" v-html="overlaysSvg" :style="{ width: canvasSvgWidth, height: canvasSvgHeight }"></svg>
|
||||
</div>
|
||||
</LayoutCol>
|
||||
@@ -267,7 +281,9 @@ import {
|
||||
UpdateToolOptionsLayout,
|
||||
defaultWidgetLayout,
|
||||
UpdateDocumentBarLayout,
|
||||
UpdateImageData,
|
||||
TriggerTextCommit,
|
||||
TriggerTextCopy,
|
||||
TriggerViewportResize,
|
||||
DisplayRemoveEditableTextbox,
|
||||
DisplayEditableTextbox,
|
||||
@@ -312,6 +328,22 @@ export default defineComponent({
|
||||
if (rulerHorizontal) rulerHorizontal.handleResize();
|
||||
if (rulerVertical) rulerVertical.handleResize();
|
||||
},
|
||||
pasteFile(e: DragEvent) {
|
||||
const { dataTransfer } = e;
|
||||
if (!dataTransfer) return;
|
||||
e.preventDefault();
|
||||
|
||||
Array.from(dataTransfer.items).forEach((item) => {
|
||||
const file = item.getAsFile();
|
||||
if (file && file.type.startsWith("image")) {
|
||||
file.arrayBuffer().then((buffer): void => {
|
||||
const u8Array = new Uint8Array(buffer);
|
||||
|
||||
this.editor.instance.paste_image(file.type, u8Array, e.clientX, e.clientY);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
translateCanvasX(newValue: number) {
|
||||
const delta = newValue - this.scrollbarPos.x;
|
||||
this.scrollbarPos.x = newValue;
|
||||
@@ -421,6 +453,15 @@ export default defineComponent({
|
||||
this.editor.dispatcher.subscribeJsMessage(TriggerTextCommit, () => {
|
||||
if (this.textInput) this.editor.instance.on_change_text(textInputCleanup(this.textInput.innerText));
|
||||
});
|
||||
this.editor.dispatcher.subscribeJsMessage(TriggerTextCopy, async (triggerTextCopy) => {
|
||||
// Clipboard API supported?
|
||||
if (!navigator.clipboard) return;
|
||||
|
||||
// copy text to clipboard
|
||||
if (navigator.clipboard.writeText) {
|
||||
await navigator.clipboard.writeText(triggerTextCopy.copy_text);
|
||||
}
|
||||
});
|
||||
|
||||
this.editor.dispatcher.subscribeJsMessage(DisplayEditableTextbox, (displayEditableTextbox) => {
|
||||
this.textInput = document.createElement("DIV") as HTMLDivElement;
|
||||
@@ -457,6 +498,19 @@ export default defineComponent({
|
||||
});
|
||||
this.editor.dispatcher.subscribeJsMessage(TriggerViewportResize, this.viewportResize);
|
||||
|
||||
this.editor.dispatcher.subscribeJsMessage(UpdateImageData, (updateImageData) => {
|
||||
updateImageData.image_data.forEach((element) => {
|
||||
// Using updateImageData.image_data.buffer returns undefined for some reason?
|
||||
const blob = new Blob([new Uint8Array(element.image_data.values()).buffer], { type: element.mime });
|
||||
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
createImageBitmap(blob).then((image) => {
|
||||
this.editor.instance.set_image_blob_url(element.path, url, image.width, image.height);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// TODO(mfish33): Replace with initialization system Issue:#524
|
||||
// Get initial Document Bar
|
||||
this.editor.instance.init_document_bar();
|
||||
|
||||
@@ -75,8 +75,8 @@
|
||||
>
|
||||
<LayoutRow class="layer-type-icon">
|
||||
<IconLabel v-if="listing.entry.layer_type === 'Folder'" :icon="'NodeFolder'" title="Folder" />
|
||||
<IconLabel v-else-if="listing.entry.layer_type === 'Image'" :icon="'NodeImage'" title="Path" />
|
||||
<IconLabel v-else-if="listing.entry.layer_type === 'Shape'" :icon="'NodeShape'" title="Path" />
|
||||
<IconLabel v-else-if="listing.entry.layer_type === 'Image'" :icon="'NodeImage'" title="Image" />
|
||||
<IconLabel v-else-if="listing.entry.layer_type === 'Shape'" :icon="'NodeShape'" title="Shape" />
|
||||
<IconLabel v-else-if="listing.entry.layer_type === 'Text'" :icon="'NodeText'" title="Path" />
|
||||
</LayoutRow>
|
||||
<LayoutRow class="layer-name" @dblclick="() => onEditLayerName(listing)">
|
||||
|
||||
@@ -119,7 +119,8 @@ function makeMenuEntries(editor: EditorState): MenuListEntries {
|
||||
[
|
||||
{ label: "Cut", shortcut: ["KeyControl", "KeyX"], action: async (): Promise<void> => editor.instance.cut() },
|
||||
{ label: "Copy", icon: "Copy", shortcut: ["KeyControl", "KeyC"], action: async (): Promise<void> => editor.instance.copy() },
|
||||
{ label: "Paste", icon: "Paste", shortcut: ["KeyControl", "KeyV"], action: async (): Promise<void> => editor.instance.paste() },
|
||||
// TODO: Fix this
|
||||
// { label: "Paste", icon: "Paste", shortcut: ["KeyControl", "KeyV"], action: async (): Promise<void> => editor.instance.paste() },
|
||||
],
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user