Skip to content
Merged
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: 3 additions & 0 deletions editor/src/messages/frontend/frontend_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ pub enum FrontendMessage {
SendShortcutAltClick {
shortcut: Option<ActionShortcut>,
},
SendShortcutShiftClick {
shortcut: Option<ActionShortcut>,
},

// Trigger prefix: cause a frontend specific API to do something
TriggerAboutGraphiteLocalizedCommitDate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
..Default::default()
},
},
description: Cow::Borrowed("Merges new content as an entry into the graphic table that represents a layer compositing stack."),
description: Cow::Borrowed("Merges the provided content as a new element in the graphic table that represents a layer compositing stack."),
properties: None,
},
DocumentNodeDefinition {
Expand Down
3 changes: 3 additions & 0 deletions editor/src/messages/portfolio/portfolio_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
responses.add(FrontendMessage::SendShortcutAltClick {
shortcut: action_shortcut_manual!(Key::Alt, Key::MouseLeft),
});
responses.add(FrontendMessage::SendShortcutShiftClick {
shortcut: action_shortcut_manual!(Key::Shift, Key::MouseLeft),
});

// Before loading any documents, initially prepare the welcome screen buttons layout
responses.add(PortfolioMessage::RequestWelcomeScreenButtonsLayout);
Expand Down
1 change: 1 addition & 0 deletions editor/src/messages/tool/common_functionality/pivot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ pub struct PivotGizmoState {

impl PivotGizmoState {
pub fn is_pivot_type(&self) -> bool {
// A disabled pivot is considered a pivot-type gizmo that is always centered
self.gizmo_type == PivotGizmoType::Pivot || self.disabled
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// State provider systems
let dialog = createDialogState(editor);
setContext("dialog", dialog);
let tooltip = createTooltipState();
let tooltip = createTooltipState(editor);
setContext("tooltip", tooltip);
let document = createDocumentState(editor);
setContext("document", document);
Expand Down
36 changes: 20 additions & 16 deletions frontend/src/components/floating-menus/ColorPicker.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts">
import { onDestroy, createEventDispatcher } from "svelte";
import { getContext, onDestroy, createEventDispatcher } from "svelte";

import type { HSV, RGB, FillChoice } from "@graphite/messages";
import type { MenuDirection } from "@graphite/messages";
import type { HSV, RGB, FillChoice, MenuDirection } from "@graphite/messages";
import { Color, contrastingOutlineFactor, Gradient } from "@graphite/messages";
import type { TooltipState } from "@graphite/state-providers/tooltip";
import { clamp } from "@graphite/utility-functions/math";

import FloatingMenu from "@graphite/components/layout/FloatingMenu.svelte";
Expand Down Expand Up @@ -40,6 +40,7 @@
];

const dispatch = createEventDispatcher<{ colorOrGradient: FillChoice; startHistoryTransaction: undefined }>();
const tooltip = getContext<TooltipState>("tooltip");

export let colorOrGradient: FillChoice;
export let allowNone = false;
Expand Down Expand Up @@ -424,12 +425,16 @@
"--opaque-color-contrasting": (newColor.opaque() || new Color(0, 0, 0, 1)).contrastingColor(),
}}
>
{@const hueDescription = "The shade along the spectrum of the rainbow."}
{@const saturationDescription = "The vividness from grayscale to full color."}
{@const valueDescription = "The brightness from black to full color."}
<LayoutCol class="pickers-and-gradient">
<LayoutRow class="pickers">
<LayoutCol
class="saturation-value-picker"
data-tooltip-label="Saturation and Value"
data-tooltip-description={disabled ? "Disabled (read-only)." : ""}
data-tooltip-description={`To move only along the saturation (X) or value (Y) axis, perform the shortcut shown.${disabled ? "\n\nDisabled (read-only)." : ""}`}
data-tooltip-shortcut={$tooltip.shiftClickShortcut?.shortcut ? JSON.stringify($tooltip.shiftClickShortcut.shortcut) : undefined}
on:pointerdown={onPointerDown}
data-saturation-value-picker
>
Expand All @@ -449,7 +454,7 @@
<LayoutCol
class="hue-picker"
data-tooltip-label="Hue"
data-tooltip-description={`The shade along the spectrum of the rainbow.${disabled ? "\n\nDisabled (read-only)." : ""}`}
data-tooltip-description={`${hueDescription}${disabled ? "\n\nDisabled (read-only)." : ""}`}
on:pointerdown={onPointerDown}
data-hue-picker
>
Expand Down Expand Up @@ -522,10 +527,8 @@
</LayoutRow>
<!-- <DropdownInput entries={[[{ label: "sRGB" }]]} selectedIndex={0} disabled={true} tooltipDescription="Color model, color space, and HDR (coming soon)." /> -->
<LayoutRow>
<TextLabel
tooltipLabel="Hex Color Code"
tooltipDescription="Color code in hexadecimal format. 6 digits if opaque, 8 with alpha.\nAccepts input of CSS color values including named colors.">Hex</TextLabel
>
{@const hexDescription = "Color code in hexadecimal format. 6 digits if opaque, 8 with alpha. Accepts input of CSS color values including named colors."}
<TextLabel tooltipLabel="Hex Color Code" tooltipDescription={hexDescription}>Hex</TextLabel>
<Separator type="Related" />
<LayoutRow>
<TextInput
Expand All @@ -537,7 +540,7 @@
}}
centered={true}
tooltipLabel="Hex Color Code"
tooltipDescription="Color code in hexadecimal format. 6 digits if opaque, 8 with alpha.\nAccepts input of CSS color values including named colors."
tooltipDescription={hexDescription}
bind:this={hexCodeInputWidget}
/>
</LayoutRow>
Expand Down Expand Up @@ -601,16 +604,17 @@
v: "Value Component",
}[channel]}
tooltipDescription={{
h: "The shade along the spectrum of the rainbow.",
s: "The vividness from grayscale to full color.",
v: "The brightness from black to full color.",
h: hueDescription,
s: saturationDescription,
v: valueDescription,
}[channel]}
/>
{/each}
</LayoutRow>
</LayoutRow>
<LayoutRow>
<TextLabel tooltipLabel="Alpha" tooltipDescription="The level of translucency, from transparent (0%) to opaque (100%).">Alpha</TextLabel>
{@const alphaDescription = "The level of translucency, from transparent (0%) to opaque (100%)."}
<TextLabel tooltipLabel="Alpha" tooltipDescription={alphaDescription}>Alpha</TextLabel>
<Separator type="Related" />
<NumberInput
value={!isNone ? alpha * 100 : undefined}
Expand All @@ -630,7 +634,7 @@
mode="Range"
displayDecimalPlaces={1}
tooltipLabel="Alpha"
tooltipDescription="The level of translucency, from transparent (0%) to opaque (100%)."
tooltipDescription={alphaDescription}
/>
</LayoutRow>
<LayoutRow class="leftover-space" />
Expand Down Expand Up @@ -670,7 +674,7 @@
data-pure-tile={name.toLowerCase()}
style:--pure-color={color}
style:--pure-color-gray={gray}
data-tooltip-label="Set to Red"
data-tooltip-label={`Set to ${name}`}
data-tooltip-description={disabled ? "Disabled (read-only)." : ""}
/>
{/each}
Expand Down
28 changes: 24 additions & 4 deletions frontend/src/components/floating-menus/Tooltip.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

let self: FloatingMenu | undefined;

$: label = filterTodo($tooltip.element?.getAttribute("data-tooltip-label")?.trim());
$: description = filterTodo($tooltip.element?.getAttribute("data-tooltip-description")?.trim());
$: label = parseMarkdown(filterTodo($tooltip.element?.getAttribute("data-tooltip-label")?.trim()));
$: description = parseMarkdown(filterTodo($tooltip.element?.getAttribute("data-tooltip-description")?.trim()));
$: shortcutJSON = $tooltip.element?.getAttribute("data-tooltip-shortcut")?.trim();
$: shortcut = ((shortcutJSON) => {
if (!shortcutJSON) return undefined;
Expand All @@ -32,6 +32,26 @@
if (text?.trim().toUpperCase() === "TODO" && !editor.handle.inDevelopmentMode()) return "";
return text;
}

function parseMarkdown(markdown: string | undefined): string | undefined {
if (!markdown) return undefined;

return (
markdown
// .split("\n")
// .map((line) => line.trim())
// .join("\n")
// .split("\n\n")
// .map((paragraph) => paragraph.replaceAll("\n", " "))
// .join("\n\n")
// Bold
.replace(/\*\*((?:(?!\*\*).)+)\*\*/g, "<strong>$1</strong>")
// Italic
.replace(/\*([^*]+)\*/g, "<em>$1</em>")
// Backticks
.replace(/`([^`]+)`/g, "<code>$1</code>")
);
}
</script>

{#if label || description}
Expand All @@ -40,15 +60,15 @@
{#if label || shortcut}
<LayoutRow class="tooltip-header">
{#if label}
<TextLabel class="tooltip-label">{label}</TextLabel>
<TextLabel class="tooltip-label">{@html label}</TextLabel>
{/if}
{#if shortcut}
<ShortcutLabel shortcut={{ shortcut }} />
{/if}
</LayoutRow>
{/if}
{#if description}
<TextLabel class="tooltip-description">{description}</TextLabel>
<TextLabel class="tooltip-description">{@html description}</TextLabel>
{/if}
</FloatingMenu>
</div>
Expand Down
18 changes: 7 additions & 11 deletions frontend/src/components/panels/Layers.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
UpdateLayersPanelControlBarLeftLayout,
UpdateLayersPanelControlBarRightLayout,
UpdateLayersPanelBottomBarLayout,
SendShortcutAltClick,
} from "@graphite/messages";
import type { ActionShortcut, DataBuffer, LayerPanelEntry, Layout } from "@graphite/messages";
import type { DataBuffer, LayerPanelEntry, Layout } from "@graphite/messages";
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import type { TooltipState } from "@graphite/state-providers/tooltip";
import { operatingSystem } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization";

Expand Down Expand Up @@ -49,6 +49,7 @@

const editor = getContext<Editor>("editor");
const nodeGraph = getContext<NodeGraphState>("nodeGraph");
const tooltip = getContext<TooltipState>("tooltip");

let list: LayoutCol | undefined;

Expand All @@ -73,13 +74,7 @@
let layersPanelControlBarRightLayout: Layout = [];
let layersPanelBottomBarLayout: Layout = [];

let altClickShortcut: ActionShortcut | undefined;

onMount(() => {
editor.subscriptions.subscribeJsMessage(SendShortcutAltClick, async (data) => {
altClickShortcut = data.shortcut;
});

editor.subscriptions.subscribeJsMessage(UpdateLayersPanelControlBarLeftLayout, (updateLayersPanelControlBarLeftLayout) => {
patchLayout(layersPanelControlBarLeftLayout, updateLayersPanelControlBarLeftLayout);
layersPanelControlBarLeftLayout = layersPanelControlBarLeftLayout;
Expand Down Expand Up @@ -628,7 +623,7 @@
? "Hide the layers nested within. (To affect all open descendants, perform the shortcut shown.)"
: "Show the layers nested within. (To affect all closed descendants, perform the shortcut shown.)") +
(listing.entry.ancestorOfSelected && !listing.entry.expanded ? "\n\nA selected layer is currently contained within.\n" : "")}
data-tooltip-shortcut={altClickShortcut?.shortcut ? JSON.stringify(altClickShortcut.shortcut) : undefined}
data-tooltip-shortcut={$tooltip.altClickShortcut?.shortcut ? JSON.stringify($tooltip.altClickShortcut.shortcut) : undefined}
on:click={(e) => handleExpandArrowClickWithModifiers(e, listing.entry.id)}
tabindex="0"
></button>
Expand All @@ -639,8 +634,9 @@
<IconLabel
icon="Clipped"
class="clipped-arrow"
tooltipDescription="Clipping mask is active. To release it, perform the shortcut on the layer border."
tooltipShortcut={altClickShortcut}
tooltipLabel="Layer Clipped"
tooltipDescription="Clipping mask is active. To release it, target the bottom border of the layer and perform the shortcut shown."
tooltipShortcut={$tooltip.altClickShortcut}
/>
{/if}
<div class="thumbnail">
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/views/Graph.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@
style:--data-color-dim={`var(--color-data-${(node.primaryOutput?.dataType || "General").toLowerCase()}-dim)`}
style:--layer-area-width={layerAreaWidth}
style:--node-chain-area-left-extension={layerChainWidth !== 0 ? layerChainWidth + 0.5 : 0}
data-tooltip-label={node.displayName === node.reference ? node.displayName : `${node.displayName} (${node.reference})`}
data-tooltip-label={node.displayName === node.reference || !node.reference ? node.displayName : `${node.displayName} (${node.reference})`}
data-tooltip-description={`
${(description || "").trim()}${editor.handle.inDevelopmentMode() ? `\n\nID: ${node.id}. Position: (${node.position.x}, ${node.position.y}).` : ""}
`.trim()}
Expand Down Expand Up @@ -651,7 +651,7 @@
style:--clip-path-id={`url(#${clipPathId})`}
style:--data-color={`var(--color-data-${(node.primaryOutput?.dataType || "General").toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${(node.primaryOutput?.dataType || "General").toLowerCase()}-dim)`}
data-tooltip-label={node.displayName === node.reference ? node.displayName : `${node.displayName} (${node.reference})`}
data-tooltip-label={node.displayName === node.reference || !node.reference ? node.displayName : `${node.displayName} (${node.reference})`}
data-tooltip-description={`
${(description || "").trim()}${editor.handle.inDevelopmentMode() ? `\n\nID: ${node.id}. Position: (${node.position.x}, ${node.position.y}).` : ""}
`.trim()}
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/components/widgets/labels/TextLabel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
font-style: italic;
}

&.monospace {
&.monospace,
code {
font-family: "Source Code Pro", monospace;
font-size: 12px;
}
Expand All @@ -94,5 +95,10 @@
a {
color: inherit;
}

code {
background: var(--color-3-darkgray);
padding: 0 2px;
}
}
</style>
19 changes: 5 additions & 14 deletions frontend/src/components/window/title-bar/WindowButtonsWeb.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
<script lang="ts">
import { getContext, onMount } from "svelte";
import { getContext } from "svelte";

import type { Editor } from "@graphite/editor";
import type { ActionShortcut } from "@graphite/messages";
import { SendShortcutF11 } from "@graphite/messages";
import type { FullscreenState } from "@graphite/state-providers/fullscreen";

import type { TooltipState } from "@graphite/state-providers/tooltip";

import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";

const fullscreen = getContext<FullscreenState>("fullscreen");
const editor = getContext<Editor>("editor");

let f11Shortcut: ActionShortcut | undefined = undefined;

onMount(() => {
editor.subscriptions.subscribeJsMessage(SendShortcutF11, async (data) => {
f11Shortcut = data.shortcut;
});
});
const tooltip = getContext<TooltipState>("tooltip");

async function handleClick() {
if ($fullscreen.windowFullscreen) fullscreen.exitFullscreen();
Expand All @@ -31,7 +22,7 @@
on:click={handleClick}
tooltipLabel={$fullscreen.windowFullscreen ? "Exit Fullscreen" : "Enter Fullscreen"}
tooltipDescription={$fullscreen.keyboardLockApiSupported ? "While fullscreen, keyboard shortcuts normally reserved by the browser become available." : ""}
tooltipShortcut={f11Shortcut}
tooltipShortcut={$tooltip.f11Shortcut}
>
<IconLabel icon={$fullscreen.windowFullscreen ? "FullscreenExit" : "FullscreenEnter"} />
</LayoutRow>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/io-managers/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,11 +481,11 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
The browser's clipboard permission has been denied.

Open the browser's website settings (usually accessible
just left of the URL) to allow this permission.
just left of the URL bar) to allow this permission.
`;
const nothing = stripIndents`
No valid clipboard data was found. You may have better
luck pasting with the standard keyboard shortcut instead.
success pasting with the standard keyboard shortcut instead.
`;

const matchMessage = {
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ export class SendShortcutAltClick extends JsMessage {
readonly shortcut!: ActionShortcut | undefined;
}

export class SendShortcutShiftClick extends JsMessage {
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
readonly shortcut!: ActionShortcut | undefined;
}

export class UpdateNodeThumbnail extends JsMessage {
readonly id!: bigint;

Expand Down Expand Up @@ -1696,6 +1701,7 @@ export const messageMakers: Record<string, MessageMaker> = {
SendUIMetadata,
SendShortcutF11,
SendShortcutAltClick,
SendShortcutShiftClick,
TriggerAboutGraphiteLocalizedCommitDate,
TriggerDisplayThirdPartyLicensesDialog,
TriggerExportImage,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/state-providers/app-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function createAppWindowState(editor: Editor) {
maximized: false,
fullscreen: false,
viewportHolePunch: false,
uiScale: 1.0,
uiScale: 1,
});

// Set up message subscriptions on creation
Expand Down
Loading