Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link appearance's fill + border + stroke with UI interaction #630

Merged
merged 7 commits into from
Dec 17, 2024
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 .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 11 additions & 3 deletions monosketch-svelte/src/lib/mono/action-manager/one-time-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ export const OneTimeAction = {
newBorderStyleId,
}),

ChangeShapeBorderDashPatternExtra: (dash?: number, gap?: number, offset?: number): OneTimeActionType => ({
ChangeShapeBorderDashPatternExtra: ({ dash, gap, offset }: {
dash?: number,
gap?: number,
offset?: number
}): OneTimeActionType => ({
type: 'ChangeShapeBorderDashPatternExtra',
dash,
gap,
Expand All @@ -160,13 +164,17 @@ export const OneTimeAction = {
isEnabled,
newStrokeStyleId,
}),
ChangeLineStrokeDashPatternExtra: (dash?: number, gap?: number, offset?: number): OneTimeActionType => ({
ChangeLineStrokeDashPatternExtra: ({ dash, gap, offset }: {
dash?: number,
gap?: number,
offset?: number
}): OneTimeActionType => ({
type: 'ChangeLineStrokeDashPatternExtra',
dash,
gap,
offset,
}),
ChangeLineStrokeCornerExtra: (isRoundedCorner: boolean) => ({
ChangeLineStrokeCornerExtra: (isRoundedCorner: boolean): OneTimeActionType => ({
type: 'ChangeLineStrokeCornerExtra',
isRoundedCorner,
}),
Expand Down
50 changes: 4 additions & 46 deletions monosketch-svelte/src/lib/mono/shape/extra/extra-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,49 +37,7 @@ export interface IRectangleExtra {
corner: RectangleBorderCornerPattern;
}

interface IShapeExtraManager {
defaultRectangleExtra: IRectangleExtra;
defaultLineExtra: ILineExtra;
defaultTextAlign: TextAlign;
defaultExtraStateUpdateFlow: Flow<void>;

setDefaultValues(params: {
isFillEnabled?: boolean;
fillStyleId?: string;
isBorderEnabled?: boolean;
borderStyleId?: string;
isBorderRoundedCorner?: boolean;
borderDashPattern?: StraightStrokeDashPattern;
isLineStrokeEnabled?: boolean;
lineStrokeStyleId?: string;
isLineStrokeRoundedCorner?: boolean;
lineDashPattern?: StraightStrokeDashPattern;
isStartHeadAnchorCharEnabled?: boolean;
startHeadAnchorCharId?: string;
isEndHeadAnchorCharEnabled?: boolean;
endHeadAnchorCharId?: string;
textHorizontalAlign?: TextHorizontalAlign;
textVerticalAlign?: TextVerticalAlign;
}): void;

getRectangleFillStyle(id?: string, defaultStyle?: RectangleFillStyle): RectangleFillStyle;

getAllPredefinedRectangleFillStyles(): RectangleFillStyle[];

getRectangleBorderStyle(id?: string, defaultStyle?: StraightStrokeStyle): StraightStrokeStyle;

getLineStrokeStyle(id?: string, defaultStyle?: StraightStrokeStyle): StraightStrokeStyle;

getAllPredefinedStrokeStyles(): StraightStrokeStyle[];

getStartHeadAnchorChar(id?: string, defaultChar?: AnchorChar): AnchorChar;

getEndHeadAnchorChar(id?: string, defaultChar?: AnchorChar): AnchorChar;

getAllPredefinedAnchorChars(): AnchorChar[];
}

class ShapeExtraManagerImpl implements IShapeExtraManager {
class ShapeExtraManagerImpl {
defaultRectangleExtra: IRectangleExtra = {
isFillEnabled: false,
userSelectedFillStyle: PredefinedRectangleFillStyle.PREDEFINED_STYLES[0],
Expand All @@ -105,8 +63,8 @@ class ShapeExtraManagerImpl implements IShapeExtraManager {
TextVerticalAlign.MIDDLE,
);

private defaultExtraStateUpdateMutableFlow = new Flow<void>();
defaultExtraStateUpdateFlow: Flow<void> = this.defaultExtraStateUpdateMutableFlow.immutable();
private readonly defaultExtraStateUpdateMutableFlow = new Flow(0);
readonly defaultExtraStateUpdateFlow: Flow<number> = this.defaultExtraStateUpdateMutableFlow.immutable();

setDefaultValues({
isFillEnabled,
Expand Down Expand Up @@ -172,7 +130,7 @@ class ShapeExtraManagerImpl implements IShapeExtraManager {
textVerticalAlign ?? this.defaultTextAlign.verticalAlign,
);

this.defaultExtraStateUpdateMutableFlow.value = undefined;
this.defaultExtraStateUpdateMutableFlow.value = this.defaultExtraStateUpdateFlow.value! + 1;
}

getRectangleFillStyle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ export class PredefinedStraightStrokeStyle {
return PredefinedStraightStrokeStyle.ID_TO_STYLE_MAP[adjustedId];
}

static isCornerRoundable(id: string): boolean {
static isCornerRoundable(id: string | null | undefined): boolean {
if (id === null || id === undefined) {
return false;
}
return id in PredefinedStraightStrokeStyle.STYLE_TO_ROUNDED_CORNER_STYLE_MAP;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export let value: number;
export let minValue: number | null = null;
export let isEnabled: boolean = true;
export let boundIncludesLabel = false;

export let onChange: () => void;
</script>

<div class:child-bounds="{!boundIncludesLabel}">
Expand All @@ -12,6 +14,7 @@ export let boundIncludesLabel = false;
type="number"
bind:value
disabled="{!isEnabled}"
on:change={onChange}
min="{minValue !== null ? minValue : ''}"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
<script lang="ts">
import CommonBorderTool from './common/CommonBorderTool.svelte';
import CommonBorderTool from './common/CommonBorderTool.svelte';
import { getContext, onDestroy, onMount } from "svelte";
import { ShapeToolViewModel } from "$ui/pannel/shapetool/viewmodel/shape-tool-viewmodel";
import { SHAPE_TOOL_VIEWMODEL } from "$ui/pannel/shapetool/constants";
import { LifecycleOwner } from "$libs/flow";
import type { StrokeDashPattern } from "$ui/pannel/shapetool/viewmodel/models";
import { OneTimeAction } from "$mono/action-manager/one-time-actions";

let selectedId = 'B1';
let cornerRounded = false;
let viewModel = getContext<ShapeToolViewModel>(SHAPE_TOOL_VIEWMODEL);
let lifecycleOwner = new LifecycleOwner();

let dashDash = 1;
let dashGap = 0;
let dashShift = 0;
let selectedStrokeItem = viewModel.shapeBorderTypeFlow.value;
let cornerRounded = viewModel.shapeBorderRoundedCornerFlow.value;

function onItemSelect(id: string) {
selectedId = id;
}
let dashPattern: StrokeDashPattern | null | undefined = viewModel.shapeBorderDashTypeFlow.value;

function onCornerRoundedChange(value: boolean) {
cornerRounded = value;
}
function onItemSelect(id: string | null) {
viewModel.update(OneTimeAction.ChangeShapeBorderExtra({ newBorderStyleId: id, isEnabled: id !== null }));
}

function onCornerRoundedChange(value: boolean) {
viewModel.update(OneTimeAction.ChangeShapeBorderCornerExtra(value));
}

function onDashPatternChange(dashPattern: StrokeDashPattern) {
viewModel.update(OneTimeAction.ChangeShapeBorderDashPatternExtra(dashPattern));
}

onMount(() => {
lifecycleOwner.onStart();

viewModel.shapeBorderTypeFlow.observe(lifecycleOwner, (value) => {
selectedStrokeItem = value;
});

viewModel.shapeBorderRoundedCornerFlow.observe(lifecycleOwner, (value) => {
cornerRounded = value;
});

viewModel.shapeBorderDashTypeFlow.observe(lifecycleOwner, (value) => {
dashPattern = value;
});
});

onDestroy(() => {
lifecycleOwner.onStop();
});
</script>

<CommonBorderTool
title="Border"
{onItemSelect}
{selectedId}
{cornerRounded}
onCornerRounded="{onCornerRoundedChange}"
bind:dashDash
bind:dashGap
bind:dashShift
/>
{#if selectedStrokeItem && cornerRounded !== undefined && dashPattern !== undefined}
<CommonBorderTool
title="Border"
{onItemSelect}
selectedId="{selectedStrokeItem.selectedId}"
{cornerRounded}
onCornerRounded="{onCornerRoundedChange}"
{dashPattern}
{onDashPatternChange}
/>
{/if}
Original file line number Diff line number Diff line change
@@ -1,36 +1,60 @@
<script lang="ts">
import Tool from './common/Tool.svelte';
import CloudItem from './common/CloudItem.svelte';
import type { ShapeToolViewModel } from "$ui/pannel/shapetool/viewmodel/shape-tool-viewmodel";
import { getContext } from "svelte";
import { SHAPE_TOOL_VIEWMODEL } from "$ui/pannel/shapetool/constants";
import Tool from './common/Tool.svelte';
import CloudItem from './common/CloudItem.svelte';
import type { ShapeToolViewModel } from "$ui/pannel/shapetool/viewmodel/shape-tool-viewmodel";
import { getContext, onDestroy, onMount } from "svelte";
import { SHAPE_TOOL_VIEWMODEL } from "$ui/pannel/shapetool/constants";
import { LifecycleOwner } from "$libs/flow";
import { OneTimeAction } from "$mono/action-manager/one-time-actions";
import type { CloudItemSelectionState } from "$ui/pannel/shapetool/viewmodel/models";

let viewModel = getContext<ShapeToolViewModel>(SHAPE_TOOL_VIEWMODEL);
let viewModel = getContext<ShapeToolViewModel>(SHAPE_TOOL_VIEWMODEL);
let lifecycleOwner = new LifecycleOwner();

let selectedId = 'F0';
let shapeFillToolSelectionState: CloudItemSelectionState | null | undefined = viewModel.shapeFillTypeFlow.value;

function onItemSelect(id: string) {
selectedId = id;
}
</script>
onMount(() => {
lifecycleOwner.onStart();

viewModel.shapeFillTypeFlow.observe(lifecycleOwner, (value) => {
shapeFillToolSelectionState = value;
});
});

onDestroy(() => {
lifecycleOwner.onStop();
});

<Tool title="Fill" available="{true}">
<div>
{#each viewModel.fillOptions as option}
function onItemSelect(id: string | null) {
viewModel.update(OneTimeAction.ChangeShapeFillExtra({ isEnabled: id !== null, newFillStyleId: id }));
}
</script>
{#if shapeFillToolSelectionState}
<Tool title="Fill" available="{true}">
<div>
<!-- Disable-item -->
<CloudItem
id="{option.id}"
selected="{option.id === selectedId}"
useDashBorder="{option.useDashBorder}"
onSelect="{onItemSelect}">{option.name}</CloudItem
>
{/each}
</div>
</Tool>
id="{null}"
selected="{shapeFillToolSelectionState.selectedId === null}"
useDashBorder="{true}"
onSelect="{onItemSelect}">×
</CloudItem>

{#each viewModel.fillOptions as option}
<CloudItem
id="{option.id}"
selected="{option.id === shapeFillToolSelectionState.selectedId}"
onSelect="{onItemSelect}">{option.name}</CloudItem
>
{/each}
</div>
</Tool>
{/if}

<style lang="scss">
div {
display: flex;
flex-wrap: wrap;
gap: 7px;
}
div {
display: flex;
flex-wrap: wrap;
gap: 7px;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
<script lang="ts">
import CommonBorderTool from './common/CommonBorderTool.svelte';
import CommonBorderTool from './common/CommonBorderTool.svelte';
import { SHAPE_TOOL_VIEWMODEL } from "$ui/pannel/shapetool/constants";
import { getContext, onDestroy, onMount } from "svelte";
import { ShapeToolViewModel } from "$ui/pannel/shapetool/viewmodel/shape-tool-viewmodel";
import { LifecycleOwner } from "$libs/flow";
import { OneTimeAction } from "$mono/action-manager/one-time-actions";
import type { StrokeDashPattern } from "$ui/pannel/shapetool/viewmodel/models";

let selectedId = 'B1';
let cornerRounded = false;
let viewModel = getContext<ShapeToolViewModel>(SHAPE_TOOL_VIEWMODEL);
let lifecycleOwner = new LifecycleOwner();

let dashDash = 1;
let dashGap = 0;
let dashShift = 0;
let selectedStrokeItem = viewModel.lineStrokeTypeFlow.value;
let cornerRounded = viewModel.lineStrokeRoundedCornerFlow.value;

function onItemSelect(id: string) {
selectedId = id;
}
let dashPattern: StrokeDashPattern | null | undefined = viewModel.lineStrokeDashTypeFlow.value;

function onCornerRoundedChange(value: boolean) {
cornerRounded = value;
}
</script>
function onItemSelect(id: string | null) {
viewModel.update(OneTimeAction.ChangeLineStrokeExtra({ newStrokeStyleId: id, isEnabled: id !== null }));
}

function onCornerRoundedChange(value: boolean) {
viewModel.update(OneTimeAction.ChangeLineStrokeCornerExtra(value));
}

function onDashPatternChange(dashPattern: StrokeDashPattern) {
viewModel.update(OneTimeAction.ChangeLineStrokeDashPatternExtra(dashPattern));
}

onMount(() => {
lifecycleOwner.onStart();

<CommonBorderTool
title="Stroke"
{onItemSelect}
{selectedId}
{cornerRounded}
onCornerRounded="{onCornerRoundedChange}"
bind:dashDash
bind:dashGap
bind:dashShift
/>
viewModel.lineStrokeTypeFlow.observe(lifecycleOwner, (value) => {
selectedStrokeItem = value;
});

viewModel.lineStrokeRoundedCornerFlow.observe(lifecycleOwner, (value) => {
cornerRounded = value;
});

viewModel.lineStrokeDashTypeFlow.observe(lifecycleOwner, (value) => {
dashPattern = value;
});
});

onDestroy(() => {
lifecycleOwner.onStop();
});
</script>
{#if selectedStrokeItem && cornerRounded !== undefined && dashPattern !== undefined}
<CommonBorderTool
title="Stroke"
{onItemSelect}
selectedId="{selectedStrokeItem.selectedId}"
{cornerRounded}
onCornerRounded="{onCornerRoundedChange}"
{dashPattern}
{onDashPatternChange}
/>
{/if}
Loading
Loading